libobs-d3d11: Use waitable object to avoid stalls

Skip Present if the waitable object says the swap chain isn't ready.
master
jpark37 2021-09-14 21:59:54 -07:00 committed by Jim
parent fbe3e7e14b
commit 608cd3867e
2 changed files with 37 additions and 8 deletions

View File

@ -203,6 +203,7 @@ gs_swap_chain::gs_swap_chain(gs_device *device, const gs_init_data *data)
initData.num_backbuffers = max(data->num_backbuffers, 2);
effect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
flags |= DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
ComPtr<IDXGIFactory5> factory5;
factory5 = ComQIPtr<IDXGIFactory5>(device->factory);
@ -221,17 +222,34 @@ gs_swap_chain::gs_swap_chain(gs_device *device, const gs_init_data *data)
}
make_swap_desc(swapDesc, &initData, effect, flags);
const HRESULT hr = device->factory->CreateSwapChain(
device->device, &swapDesc, swap.Assign());
HRESULT hr = device->factory->CreateSwapChain(device->device, &swapDesc,
swap.Assign());
if (FAILED(hr))
throw HRError("Failed to create swap chain", hr);
/* Ignore Alt+Enter */
device->factory->MakeWindowAssociation(hwnd, DXGI_MWA_NO_ALT_ENTER);
if (flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) {
ComPtr<IDXGISwapChain2> swap2 = ComQIPtr<IDXGISwapChain2>(swap);
hWaitable = swap2->GetFrameLatencyWaitableObject();
if (hWaitable) {
hr = swap2->SetMaximumFrameLatency(40);
if (FAILED(hr))
throw HRError("Could not relax frame latency",
hr);
}
}
Init();
}
gs_swap_chain::~gs_swap_chain()
{
if (hWaitable)
CloseHandle(hWaitable);
}
void gs_device::InitCompiler()
{
char d3dcompiler[40] = {};
@ -2019,11 +2037,16 @@ void device_present(gs_device_t *device)
{
gs_swap_chain *const curSwapChain = device->curSwapChain;
if (curSwapChain) {
const HRESULT hr = curSwapChain->swap->Present(
0, curSwapChain->presentFlags);
if (hr == DXGI_ERROR_DEVICE_REMOVED ||
hr == DXGI_ERROR_DEVICE_RESET) {
device->RebuildDevice();
/* Skip Present because full queue may cause a stall */
const HANDLE hWaitiable = curSwapChain->hWaitable;
if ((hWaitiable == NULL) ||
WaitForSingleObject(hWaitiable, 0) == WAIT_OBJECT_0) {
const HRESULT hr = curSwapChain->swap->Present(
0, curSwapChain->presentFlags);
if (hr == DXGI_ERROR_DEVICE_REMOVED ||
hr == DXGI_ERROR_DEVICE_RESET) {
device->RebuildDevice();
}
}
} else {
blog(LOG_WARNING, "device_present (D3D11): No active swap");

View File

@ -801,6 +801,7 @@ struct gs_swap_chain : gs_obj {
gs_texture_2d target;
gs_zstencil_buffer zs;
ComPtr<IDXGISwapChain> swap;
HANDLE hWaitable = NULL;
void InitTarget(uint32_t cx, uint32_t cy);
void InitZStencilBuffer(uint32_t cx, uint32_t cy);
@ -813,10 +814,15 @@ struct gs_swap_chain : gs_obj {
{
target.Release();
zs.Release();
swap.Release();
if (hWaitable) {
CloseHandle(hWaitable);
hWaitable = NULL;
}
swap.Clear();
}
gs_swap_chain(gs_device *device, const gs_init_data *data);
virtual ~gs_swap_chain();
};
struct BlendState {