Merge pull request #164 from psyke83/DwmFlush
platform/windows: add DwmFlush() call to improve Windows capture
This commit is contained in:
commit
b5fd69a9ed
7 changed files with 79 additions and 17 deletions
|
|
@ -122,6 +122,7 @@ if(WIN32)
|
|||
ws2_32
|
||||
d3d11 dxgi D3DCompiler
|
||||
setupapi
|
||||
dwmapi
|
||||
)
|
||||
|
||||
set_source_files_properties(third-party/ViGEmClient/src/ViGEmClient.cpp PROPERTIES COMPILE_DEFINITIONS "UNICODE=1;ERROR_INVALID_DEVICE_OBJECT_PARAMETER=650")
|
||||
|
|
|
|||
|
|
@ -333,6 +333,26 @@ Example
|
|||
3840x1600,
|
||||
]
|
||||
|
||||
dwmflush
|
||||
^^^^^^^^
|
||||
|
||||
Description
|
||||
Invoke DwmFlush() to sync screen capture to the Windows presentation interval.
|
||||
|
||||
.. Caution:: Applies to Windows only. Alleviates visual stuttering during mouse movement.
|
||||
If enabled, this feature will automatically deactivate if the client framerate exceeds
|
||||
the host monitor's current refresh rate.
|
||||
|
||||
Default
|
||||
``enabled``
|
||||
|
||||
Examples
|
||||
|
||||
Windows
|
||||
.. code-block:: text
|
||||
|
||||
dwmflush = enabled
|
||||
|
||||
Audio
|
||||
-----
|
||||
|
||||
|
|
|
|||
|
|
@ -37,13 +37,13 @@
|
|||
class="form-select"
|
||||
v-model="config.min_log_level"
|
||||
>
|
||||
<option :value="0">Verbose</option>
|
||||
<option :value="1">Debug</option>
|
||||
<option :value="2">Info</option>
|
||||
<option :value="3">Warning</option>
|
||||
<option :value="4">Error</option>
|
||||
<option :value="5">Fatal</option>
|
||||
<option :value="6">None</option>
|
||||
<option value="0">Verbose</option>
|
||||
<option value="1">Debug</option>
|
||||
<option value="2">Info</option>
|
||||
<option value="3">Warning</option>
|
||||
<option value="4">Error</option>
|
||||
<option value="5">Fatal</option>
|
||||
<option value="6">None</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
The minimum log level printed to standard out
|
||||
|
|
@ -400,7 +400,18 @@
|
|||
You can select the video card you want to stream:<br />
|
||||
The appropriate values can be found using the following command:<br />
|
||||
tools\dxgi-info.exe<br />
|
||||
<br />
|
||||
</div>
|
||||
</div>
|
||||
<!--DwmFlush-->
|
||||
<div class="mb-3" v-if="platform === 'windows'">
|
||||
<label for="dwmflush" class="form-label">DwmFlush</label>
|
||||
<select id="dwmflush" class="form-select" v-model="config.dwmflush">
|
||||
<option value="disabled">Disabled</option>
|
||||
<option value="enabled">Enabled</option>
|
||||
</select>
|
||||
<div class="form-text">
|
||||
Improves capture latency/smoothness during mouse movement.<br />
|
||||
Disable if you encounter any VSync-related issues.
|
||||
</div>
|
||||
</div>
|
||||
<div class="mb-3" class="config-page" v-if="platform === 'linux'">
|
||||
|
|
@ -497,7 +508,7 @@
|
|||
<div class="mb-3">
|
||||
<label for="encoder" class="form-label">Force a Specific Encoder</label>
|
||||
<select id="encoder" class="form-select" v-model="config.encoder">
|
||||
<option :value="''">Autodetect</option>
|
||||
<option value>Autodetect</option>
|
||||
<option value="nvenc">nVidia NVENC</option>
|
||||
<option value="amdvce">AMD AMF/VCE</option>
|
||||
<option value="vaapi">VA-API</option>
|
||||
|
|
@ -696,7 +707,7 @@
|
|||
</select>
|
||||
</div>
|
||||
<div class="mb-3">
|
||||
<label for="amd_coder" class="form-label">AMD AMF Rate Control</label>
|
||||
<label for="amd_coder" class="form-label">AMD AMF Coder</label>
|
||||
<select id="amd_coder" class="form-select" v-model="config.amd_coder">
|
||||
<option value="auto">auto</option>
|
||||
<option value="cabac">cabac</option>
|
||||
|
|
@ -832,6 +843,7 @@
|
|||
this.config.key_rightalt_to_key_win || "disabled";
|
||||
this.config.gamepad = this.config.gamepad || "x360";
|
||||
this.config.upnp = this.config.upnp || "disabled";
|
||||
this.config.dwmflush = this.config.dwmflush || "enabled";
|
||||
this.config.min_log_level = this.config.min_log_level || 2;
|
||||
this.config.origin_pin_allowed =
|
||||
this.config.origin_pin_allowed || "pc";
|
||||
|
|
@ -842,6 +854,7 @@
|
|||
this.config.nv_preset = this.config.nv_preset || "default";
|
||||
this.config.nv_rc = this.config.nv_rc || "auto";
|
||||
this.config.nv_coder = this.config.nv_coder || "auto";
|
||||
this.config.amd_coder = this.config.amd_coder || "auto"
|
||||
this.config.amd_quality = this.config.amd_quality || "default";
|
||||
this.config.amd_rc = this.config.amd_rc || "auto";
|
||||
this.config.vt_coder = this.config.vt_coder || "auto";
|
||||
|
|
|
|||
|
|
@ -220,9 +220,16 @@ video_t video {
|
|||
std::nullopt,
|
||||
-1 }, // amd
|
||||
|
||||
{}, // encoder
|
||||
{}, // adapter_name
|
||||
{}, // output_name
|
||||
{
|
||||
0,
|
||||
0,
|
||||
1,
|
||||
-1 }, // vt
|
||||
|
||||
{}, // encoder
|
||||
{}, // adapter_name
|
||||
{}, // output_name
|
||||
true // dwmflush
|
||||
};
|
||||
|
||||
audio_t audio {};
|
||||
|
|
@ -722,16 +729,14 @@ void apply_config(std::unordered_map<std::string, std::string> &&vars) {
|
|||
}
|
||||
|
||||
int_f(vars, "vt_coder", video.vt.coder, vt::coder_from_view);
|
||||
video.vt.allow_sw = 0;
|
||||
int_f(vars, "vt_software", video.vt.allow_sw, vt::allow_software_from_view);
|
||||
video.vt.require_sw = 0;
|
||||
int_f(vars, "vt_software", video.vt.require_sw, vt::force_software_from_view);
|
||||
video.vt.realtime = 1;
|
||||
int_f(vars, "vt_realtime", video.vt.realtime, vt::rt_from_view);
|
||||
|
||||
string_f(vars, "encoder", video.encoder);
|
||||
string_f(vars, "adapter_name", video.adapter_name);
|
||||
string_f(vars, "output_name", video.output_name);
|
||||
bool_f(vars, "dwmflush", video.dwmflush);
|
||||
|
||||
path_f(vars, "pkey", nvhttp.pkey);
|
||||
path_f(vars, "cert", nvhttp.cert);
|
||||
|
|
|
|||
|
|
@ -44,6 +44,7 @@ struct video_t {
|
|||
std::string encoder;
|
||||
std::string adapter_name;
|
||||
std::string output_name;
|
||||
bool dwmflush;
|
||||
};
|
||||
|
||||
struct audio_t {
|
||||
|
|
|
|||
|
|
@ -8,6 +8,7 @@
|
|||
#include <d3d11.h>
|
||||
#include <d3d11_4.h>
|
||||
#include <d3dcommon.h>
|
||||
#include <dwmapi.h>
|
||||
#include <dxgi.h>
|
||||
#include <dxgi1_2.h>
|
||||
|
||||
|
|
@ -95,6 +96,7 @@ class duplication_t {
|
|||
public:
|
||||
dup_t dup;
|
||||
bool has_frame {};
|
||||
bool use_dwmflush {};
|
||||
|
||||
capture_e next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::chrono::milliseconds timeout, resource_t::pointer *res_p);
|
||||
capture_e reset(dup_t::pointer dup_p = dup_t::pointer());
|
||||
|
|
@ -172,4 +174,4 @@ public:
|
|||
};
|
||||
} // namespace platf::dxgi
|
||||
|
||||
#endif
|
||||
#endif
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
// Created by loki on 1/12/20.
|
||||
//
|
||||
|
||||
#include <cmath>
|
||||
#include <codecvt>
|
||||
|
||||
#include "display.h"
|
||||
|
|
@ -20,6 +21,10 @@ capture_e duplication_t::next_frame(DXGI_OUTDUPL_FRAME_INFO &frame_info, std::ch
|
|||
return capture_status;
|
||||
}
|
||||
|
||||
if(use_dwmflush) {
|
||||
DwmFlush();
|
||||
}
|
||||
|
||||
auto status = dup->AcquireNextFrame(timeout.count(), &frame_info, res_p);
|
||||
|
||||
switch(status) {
|
||||
|
|
@ -213,6 +218,21 @@ int display_base_t::init(int framerate, const std::string &display_name) {
|
|||
<< "Offset : "sv << offset_x << 'x' << offset_y << std::endl
|
||||
<< "Virtual Desktop : "sv << env_width << 'x' << env_height;
|
||||
|
||||
// Enable DwmFlush() only if the current refresh rate can match the client framerate.
|
||||
auto refresh_rate = framerate;
|
||||
DWM_TIMING_INFO timing_info;
|
||||
timing_info.cbSize = sizeof(timing_info);
|
||||
|
||||
status = DwmGetCompositionTimingInfo(NULL, &timing_info);
|
||||
if(FAILED(status)) {
|
||||
BOOST_LOG(warning) << "Failed to detect active refresh rate.";
|
||||
}
|
||||
else {
|
||||
refresh_rate = std::round((double)timing_info.rateRefresh.uiNumerator / (double)timing_info.rateRefresh.uiDenominator);
|
||||
}
|
||||
|
||||
dup.use_dwmflush = config::video.dwmflush && !(framerate > refresh_rate) ? true : false;
|
||||
|
||||
// Bump up thread priority
|
||||
{
|
||||
const DWORD flags = TOKEN_ADJUST_PRIVILEGES | TOKEN_QUERY;
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue