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
6f5f55c84a
commit
92ed98ccea
|
@ -1764,7 +1764,6 @@ static VkResult d3d12_swapchain_queue_present(struct d3d12_swapchain *swapchain,
|
||||||
static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
||||||
unsigned int sync_interval, unsigned int flags)
|
unsigned int sync_interval, unsigned int flags)
|
||||||
{
|
{
|
||||||
HANDLE frame_latency_event;
|
|
||||||
VkQueue vk_queue;
|
VkQueue vk_queue;
|
||||||
VkResult vr;
|
VkResult vr;
|
||||||
HRESULT hr;
|
HRESULT hr;
|
||||||
|
@ -1826,8 +1825,6 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
||||||
return hresult_from_vk_result(vr);
|
return hresult_from_vk_result(vr);
|
||||||
}
|
}
|
||||||
|
|
||||||
if ((frame_latency_event = swapchain->frame_latency_event))
|
|
||||||
{
|
|
||||||
++swapchain->frame_number;
|
++swapchain->frame_number;
|
||||||
|
|
||||||
if (FAILED(hr = ID3D12CommandQueue_Signal(d3d12_swapchain_queue_iface(swapchain),
|
if (FAILED(hr = ID3D12CommandQueue_Signal(d3d12_swapchain_queue_iface(swapchain),
|
||||||
|
@ -1837,13 +1834,33 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain,
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
|
||||||
|
{
|
||||||
if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence,
|
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);
|
ERR("Failed to enqueue frame latency event, hr %#x.\n", hr);
|
||||||
return 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;
|
swapchain->current_buffer_index = (swapchain->current_buffer_index + 1) % swapchain->desc.BufferCount;
|
||||||
return hresult_from_vk_result(vr);
|
return hresult_from_vk_result(vr);
|
||||||
|
@ -2302,6 +2319,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMaximumFrameLatency(dxgi_swa
|
||||||
TRACE("iface %p, max_latency %u.\n", iface, max_latency);
|
TRACE("iface %p, max_latency %u.\n", iface, max_latency);
|
||||||
EnterCriticalSection(&swapchain->mutex);
|
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))
|
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);
|
WARN("DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT not set for swap chain %p.\n", iface);
|
||||||
|
@ -2346,6 +2365,9 @@ static HANDLE STDMETHODCALLTYPE d3d12_swapchain_GetFrameLatencyWaitableObject(dx
|
||||||
|
|
||||||
TRACE("iface %p.\n", iface);
|
TRACE("iface %p.\n", iface);
|
||||||
|
|
||||||
|
if (!(swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT))
|
||||||
|
return NULL;
|
||||||
|
|
||||||
return swapchain->frame_latency_event;
|
return swapchain->frame_latency_event;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2678,9 +2700,10 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IDXGIFact
|
||||||
|
|
||||||
swapchain->current_buffer_index = 0;
|
swapchain->current_buffer_index = 0;
|
||||||
|
|
||||||
if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)
|
|
||||||
{
|
|
||||||
swapchain->frame_number = DXGI_MAX_SWAP_CHAIN_BUFFERS;
|
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_latency = 1;
|
swapchain->frame_latency = 1;
|
||||||
|
|
||||||
if (FAILED(hr = ID3D12Device6_CreateFence(d3d12_swapchain_device_iface(swapchain), DXGI_MAX_SWAP_CHAIN_BUFFERS,
|
if (FAILED(hr = ID3D12Device6_CreateFence(d3d12_swapchain_device_iface(swapchain), DXGI_MAX_SWAP_CHAIN_BUFFERS,
|
||||||
|
@ -2698,7 +2721,6 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IDXGIFact
|
||||||
d3d12_swapchain_destroy(swapchain);
|
d3d12_swapchain_destroy(swapchain);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
if (FAILED(hr = d3d12_swapchain_set_fullscreen(swapchain, target, TRUE)))
|
if (FAILED(hr = d3d12_swapchain_set_fullscreen(swapchain, target, TRUE)))
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue