[host] dxgi: use DwmFlush to sync to presentation interval

This change reduces the host GPU and CPU load by a large margin
improving guest system performance along with removing latency spikes
when moving the mouse. This is default enabled but can be disabled with
the new option `dxgi:dwmFlush=no` as it limits the capture rate to the
refresh rate of the guests output which may not be desireable.
This commit is contained in:
Geoffrey McRae 2022-01-06 18:39:08 +11:00
parent 208b722348
commit 92f27cc0f0
2 changed files with 18 additions and 0 deletions

View File

@ -11,6 +11,7 @@ target_link_libraries(capture_DXGI
lg_common lg_common
d3d11 d3d11
dxgi dxgi
dwmapi
) )
target_include_directories(capture_DXGI target_include_directories(capture_DXGI

View File

@ -38,6 +38,7 @@
#include <d3d11.h> #include <d3d11.h>
#include <d3dcommon.h> #include <d3dcommon.h>
#include <versionhelpers.h> #include <versionhelpers.h>
#include <dwmapi.h>
#include "dxgi_extra.h" #include "dxgi_extra.h"
@ -85,6 +86,7 @@ struct iface
ID3D11DeviceContext * deviceContext; ID3D11DeviceContext * deviceContext;
LG_Lock deviceContextLock; LG_Lock deviceContextLock;
bool useAcquireLock; bool useAcquireLock;
bool dwmFlush;
D3D_FEATURE_LEVEL featureLevel; D3D_FEATURE_LEVEL featureLevel;
IDXGIOutputDuplication * dup; IDXGIOutputDuplication * dup;
int maxTextures; int maxTextures;
@ -161,6 +163,13 @@ static void dxgi_initOptions(void)
.type = OPTION_TYPE_BOOL, .type = OPTION_TYPE_BOOL,
.value.x_bool = true .value.x_bool = true
}, },
{
.module = "dxgi",
.name = "dwmFlush",
.description = "Use DwmFlush to sync the capture to the windows presentation inverval",
.type = OPTION_TYPE_BOOL,
.value.x_bool = true
},
{0} {0}
}; };
@ -190,6 +199,7 @@ static bool dxgi_create(CaptureGetPointerBuffer getPointerBufferFn, CapturePostP
this->maxTextures = 1; this->maxTextures = 1;
this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock"); this->useAcquireLock = option_get_bool("dxgi", "useAcquireLock");
this->dwmFlush = option_get_bool("dxgi", "dwmFlush");
this->texture = calloc(this->maxTextures, sizeof(*this->texture)); this->texture = calloc(this->maxTextures, sizeof(*this->texture));
this->getPointerBufferFn = getPointerBufferFn; this->getPointerBufferFn = getPointerBufferFn;
this->postPointerBufferFn = postPointerBufferFn; this->postPointerBufferFn = postPointerBufferFn;
@ -807,6 +817,13 @@ static CaptureResult dxgi_capture(void)
if (result != CAPTURE_RESULT_OK) if (result != CAPTURE_RESULT_OK)
return result; return result;
// this is a bit of a hack as it causes this thread to block until the next
// present, by doing this we can allow the mouse updates to accumulate instead
// of being called to process every single one. The only caveat is we are
// limited to the refresh rate of the monitor.
if (this->dwmFlush)
DwmFlush();
if (this->useAcquireLock) if (this->useAcquireLock)
{ {
LOCKED({ LOCKED({