vkd3d: Handle frame latency without WAITABLE_OBJECT
Documentation says that this should always be 3 without WAITABLE_OBJECT unlike in D3D11 where it will use the DXGI device's frame latency. This stops runaway presentations in the non-blocking acquire image case with the new semaphore setup. Signed-off-by: Joshua Ashton <joshua@froggi.es>
This commit is contained in:
parent
582138b063
commit
c33cfd048b
|
@ -1757,7 +1757,6 @@ static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain,
|
|||
static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
||||
unsigned int sync_interval, unsigned int flags)
|
||||
{
|
||||
HANDLE frame_latency_event;
|
||||
VkQueue vk_queue;
|
||||
VkResult vr;
|
||||
HRESULT hr;
|
||||
|
@ -1819,24 +1818,42 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
|||
return hresult_from_vk_result(vr);
|
||||
}
|
||||
|
||||
if ((frame_latency_event = swapchain->frame_latency_event))
|
||||
++swapchain->frame_number;
|
||||
|
||||
if (FAILED(hr = ID3D12CommandQueue_Signal(d3d12_swapchain_queue_iface(swapchain),
|
||||
swapchain->frame_latency_fence, swapchain->frame_number)))
|
||||
{
|
||||
++swapchain->frame_number;
|
||||
|
||||
if (FAILED(hr = ID3D12CommandQueue_Signal(d3d12_swapchain_queue_iface(swapchain),
|
||||
swapchain->frame_latency_fence, swapchain->frame_number)))
|
||||
{
|
||||
ERR("Failed to signal frame latency fence, hr %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
ERR("Failed to signal frame latency fence, hr %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
|
||||
{
|
||||
if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence,
|
||||
swapchain->frame_number - swapchain->frame_latency, frame_latency_event)))
|
||||
swapchain->frame_number - swapchain->frame_latency, swapchain->frame_latency_event)))
|
||||
{
|
||||
ERR("Failed to enqueue frame latency event, hr %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
const uint32_t sync_latency = min(swapchain->frame_latency, swapchain->desc.BufferCount + 1);
|
||||
const uint64_t frame_target = swapchain->frame_number - sync_latency;
|
||||
|
||||
if (ID3D12Fence_GetCompletedValue(swapchain->frame_latency_fence) < frame_target)
|
||||
{
|
||||
/* Wait on the latency. */
|
||||
if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence,
|
||||
frame_target, swapchain->frame_latency_event)))
|
||||
{
|
||||
ERR("Failed to enqueue frame latency event (internal), hr %#x.\n", hr);
|
||||
return hr;
|
||||
}
|
||||
|
||||
WaitForSingleObject(swapchain->frame_latency_event, INFINITE);
|
||||
}
|
||||
}
|
||||
|
||||
swapchain->current_buffer_index = (swapchain->current_buffer_index + 1) % swapchain->desc.BufferCount;
|
||||
return hresult_from_vk_result(vr);
|
||||
|
@ -2295,6 +2312,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMaximumFrameLatency(dxgi_swa
|
|||
TRACE("iface %p, max_latency %u.\n", iface, max_latency);
|
||||
EnterCriticalSection(&swapchain->mutex);
|
||||
|
||||
/* Max frame latency without WAITABLE_OBJECT is always 3,
|
||||
* even if set on the device, according to docs. */
|
||||
if (!(swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
|
||||
{
|
||||
WARN("DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT not set for swap chain %p.\n", iface);
|
||||
|
@ -2339,6 +2358,9 @@ static HANDLE STDMETHODCALLTYPE d3d12_swapchain_GetFrameLatencyWaitableObject(dx
|
|||
|
||||
TRACE("iface %p.\n", iface);
|
||||
|
||||
if (!(swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
|
||||
return NULL;
|
||||
|
||||
return swapchain->frame_latency_event;
|
||||
}
|
||||
|
||||
|
@ -2671,26 +2693,26 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IDXGIFact
|
|||
|
||||
swapchain->current_buffer_index = 0;
|
||||
|
||||
swapchain->frame_number = DXGI_MAX_SWAP_CHAIN_BUFFERS;
|
||||
swapchain->frame_latency = 3;
|
||||
|
||||
if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
|
||||
{
|
||||
swapchain->frame_number = DXGI_MAX_SWAP_CHAIN_BUFFERS;
|
||||
swapchain->frame_latency = 1;
|
||||
|
||||
if (FAILED(hr = ID3D12Device6_CreateFence(d3d12_swapchain_device_iface(swapchain), DXGI_MAX_SWAP_CHAIN_BUFFERS,
|
||||
0, &IID_ID3D12Fence, (void **)&swapchain->frame_latency_fence)))
|
||||
{
|
||||
WARN("Failed to create frame latency fence, hr %#x.\n", hr);
|
||||
d3d12_swapchain_destroy(swapchain);
|
||||
return hr;
|
||||
}
|
||||
if (FAILED(hr = ID3D12Device6_CreateFence(d3d12_swapchain_device_iface(swapchain), DXGI_MAX_SWAP_CHAIN_BUFFERS,
|
||||
0, &IID_ID3D12Fence, (void **)&swapchain->frame_latency_fence)))
|
||||
{
|
||||
WARN("Failed to create frame latency fence, hr %#x.\n", hr);
|
||||
d3d12_swapchain_destroy(swapchain);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (!(swapchain->frame_latency_event = CreateEventW(NULL, FALSE, TRUE, NULL)))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
WARN("Failed to create frame latency event, hr %#x.\n", hr);
|
||||
d3d12_swapchain_destroy(swapchain);
|
||||
return hr;
|
||||
}
|
||||
if (!(swapchain->frame_latency_event = CreateEventW(NULL, FALSE, TRUE, NULL)))
|
||||
{
|
||||
hr = HRESULT_FROM_WIN32(GetLastError());
|
||||
WARN("Failed to create frame latency event, hr %#x.\n", hr);
|
||||
d3d12_swapchain_destroy(swapchain);
|
||||
return hr;
|
||||
}
|
||||
|
||||
if (FAILED(hr = d3d12_swapchain_set_fullscreen(swapchain, target, TRUE)))
|
||||
|
|
Loading…
Reference in New Issue