This series implements DXGI 1.3 frame latency events for D3D12 swap chains, which is used by Resident Evil 2/3, and is required for Monster Hunter World.
The implementation just signals a D3D12 fence after presenting, and uses its SetEventOnCompletion function to signal the event, which doesn't necessarily happen after the Vulkan present operation has finished on the GPU, but will always happen after the command buffer that blits the back buffer to the Vulkan swap chain image has finished execution, so it should be good enough, since the D3D12 app does not have direct access to the Vulkan swap chain.
- Philip
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/swapchain.c | 30 +++++++++++++++++++++++++++++- 1 file changed, 29 insertions(+), 1 deletion(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index f19b58da2e..54563a208b 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1094,6 +1094,9 @@ struct d3d12_swapchain IDXGIOutput *target; DXGI_SWAP_CHAIN_DESC1 desc; DXGI_SWAP_CHAIN_FULLSCREEN_DESC fullscreen_desc; + + ID3D12Fence *frame_latency_fence; + HANDLE *frame_latency_event; };
static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format) @@ -1887,6 +1890,12 @@ static void d3d12_swapchain_destroy(struct d3d12_swapchain *swapchain)
d3d12_swapchain_destroy_buffers(swapchain, TRUE);
+ if (swapchain->frame_latency_event) + CloseHandle(swapchain->frame_latency_event); + + if (swapchain->frame_latency_fence) + ID3D12Fence_Release(swapchain->frame_latency_fence); + if (swapchain->command_queue) ID3D12CommandQueue_Release(swapchain->command_queue);
@@ -2906,7 +2915,7 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI FIXME("Ignoring scaling %#x.\n", swapchain_desc->Scaling); if (swapchain_desc->AlphaMode && swapchain_desc->AlphaMode != DXGI_ALPHA_MODE_IGNORE) FIXME("Ignoring alpha mode %#x.\n", swapchain_desc->AlphaMode); - if (swapchain_desc->Flags) + if (swapchain_desc->Flags & ~(DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) FIXME("Ignoring swapchain flags %#x.\n", swapchain_desc->Flags);
if (fullscreen_desc->RefreshRate.Numerator || fullscreen_desc->RefreshRate.Denominator) @@ -2983,6 +2992,25 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI return hresult_from_vk_result(vr); }
+ if (swapchain_desc->Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + { + if (FAILED(hr = ID3D12Device_CreateFence(device, DXGI_MAX_SWAP_CHAIN_BUFFERS, + 0, &IID_ID3D12Fence, (void **)&swapchain->frame_latency_fence))) + { + WARN("Failed to create D3D12 fence, hr %d.\n", hr); + d3d12_swapchain_destroy(swapchain); + return hr; + } + + if (!(swapchain->frame_latency_event = CreateEventW(NULL, TRUE, TRUE, NULL))) + { + hr = HRESULT_FROM_WIN32(GetLastError()); + WARN("Failed to create frame latency event, hr %d.\n", hr); + d3d12_swapchain_destroy(swapchain); + return hr; + } + } + IWineDXGIFactory_AddRef(swapchain->factory = factory);
return S_OK;
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/swapchain.c | 36 ++++++++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 54563a208b..f55a94e7cd 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -1097,6 +1097,9 @@ struct d3d12_swapchain
ID3D12Fence *frame_latency_fence; HANDLE *frame_latency_event; + + uint64_t frame_number; + uint32_t frame_latency; };
static DXGI_FORMAT dxgi_format_from_vk_format(VkFormat vk_format) @@ -2125,6 +2128,17 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, if (FAILED(hr = d3d12_swapchain_set_sync_interval(swapchain, sync_interval))) return hr;
+ if (swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + { + if (WaitForSingleObject(swapchain->frame_latency_event, INFINITE)) + { + ERR("Failed to wait for frame latency event, error %u.\n", GetLastError()); + return E_FAIL; + } + + ResetEvent(swapchain->frame_latency_event); + } + if (!(vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue))) { ERR("Failed to acquire Vulkan queue.\n"); @@ -2166,6 +2180,25 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, return hresult_from_vk_result(vr); }
+ if (swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + { + ++swapchain->frame_number; + + if (FAILED(hr = ID3D12CommandQueue_Signal(swapchain->command_queue, + swapchain->frame_latency_fence, swapchain->frame_number))) + { + ERR("Failed to signal frame latency fence, hr %#x.\n", hr); + return hr; + } + + if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence, + swapchain->frame_number - swapchain->frame_latency, swapchain->frame_latency_event))) + { + FIXME("Failed to enqueue frame latency event, hr %#x.\n", hr); + return hr; + } + } + swapchain->current_buffer_index = (swapchain->current_buffer_index + 1) % swapchain->desc.BufferCount; vr = d3d12_swapchain_acquire_next_back_buffer(swapchain); if (vr == VK_ERROR_OUT_OF_DATE_KHR) @@ -2994,6 +3027,9 @@ static HRESULT d3d12_swapchain_init(struct d3d12_swapchain *swapchain, IWineDXGI
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 = ID3D12Device_CreateFence(device, DXGI_MAX_SWAP_CHAIN_BUFFERS, 0, &IID_ID3D12Fence, (void **)&swapchain->frame_latency_fence))) {
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/swapchain.c | 6 ++++-- 1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index f55a94e7cd..1c7cf5c537 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2632,9 +2632,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetMaximumFrameLatency(IDXGISwa
static HANDLE STDMETHODCALLTYPE d3d12_swapchain_GetFrameLatencyWaitableObject(IDXGISwapChain3 *iface) { - FIXME("iface %p stub!\n", iface); + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
- return NULL; + TRACE("iface %p.\n", iface); + + return swapchain->frame_latency_event; }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMatrixTransform(IDXGISwapChain3 *iface,
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/swapchain.c | 36 ++++++++++++++++++++++++++++++++++-- 1 file changed, 34 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 1c7cf5c537..1411ede376 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2618,9 +2618,41 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetSourceSize(IDXGISwapChain3 *
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMaximumFrameLatency(IDXGISwapChain3 *iface, UINT max_latency) { - FIXME("iface %p, max_latency %u stub!\n", iface, max_latency); + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface); + HRESULT hr;
- return E_NOTIMPL; + TRACE("iface %p, max_latency %u.\n", iface, max_latency); + + if (!(swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + { + FIXME("DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT not set for swap chain %p.\n", iface); + return DXGI_ERROR_INVALID_CALL; + } + + if (!max_latency || max_latency > DXGI_MAX_SWAP_CHAIN_BUFFERS) + { + FIXME("Invalid maximum frame latency %u.\n", max_latency); + return DXGI_ERROR_INVALID_CALL; + } + + if (WaitForSingleObject(swapchain->frame_latency_event, INFINITE)) + { + ERR("Failed to wait for frame latency event, error %u.\n", GetLastError()); + return E_FAIL; + } + + if (max_latency < swapchain->frame_latency) + ResetEvent(swapchain->frame_latency_event); + + if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence, + swapchain->frame_number - max_latency, swapchain->frame_latency_event))) + { + ERR("Failed to enqueue frame latency event, hr %#x.\n", hr); + return hr; + } + + swapchain->frame_latency = max_latency; + return S_OK; }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetMaximumFrameLatency(IDXGISwapChain3 *iface, UINT *max_latency)
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/swapchain.c | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 1411ede376..8239d12486 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2657,9 +2657,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMaximumFrameLatency(IDXGISwa
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetMaximumFrameLatency(IDXGISwapChain3 *iface, UINT *max_latency) { - FIXME("iface %p, max_latency %p stub!\n", iface, max_latency); + struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain3(iface);
- return E_NOTIMPL; + TRACE("iface %p, max_latency %p.\n", iface, max_latency); + + if (!(swapchain->desc.Flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + { + FIXME("DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT not set for swap chain %p.\n", iface); + return DXGI_ERROR_INVALID_CALL; + } + + *max_latency = swapchain->frame_latency; + return S_OK; }
static HANDLE STDMETHODCALLTYPE d3d12_swapchain_GetFrameLatencyWaitableObject(IDXGISwapChain3 *iface)
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de --- dlls/dxgi/tests/dxgi.c | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 3887982634..b016c35938 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6188,6 +6188,127 @@ static void test_factory_check_feature_support(void) ok(!ref_count, "Factory has %u references left.\n", ref_count); }
+static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) +{ + DXGI_SWAP_CHAIN_DESC1 swapchain_desc; + IDXGISwapChain2 *swapchain2; + IDXGISwapChain1 *swapchain1; + IDXGIFactory2 *factory2; + IDXGIFactory *factory; + UINT frame_latency; + DWORD wait_result; + ULONG ref_count; + unsigned int i; + HANDLE event; + HWND window; + HRESULT hr; + + get_factory(device, is_d3d12, &factory); + + hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory2, (void**)&factory2); + IDXGIFactory_Release(factory); + + if (FAILED(hr)) + { + win_skip("IDXGIFactory2 not available.\n"); + return; + } + + window = CreateWindowA("static", "dxgi_test", 0, 640, 480, 0, 0, 0, 0, 0, 0); + + swapchain_desc.Width = 640; + swapchain_desc.Height = 480; + swapchain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM; + swapchain_desc.Stereo = FALSE; + swapchain_desc.SampleDesc.Count = 1; + swapchain_desc.SampleDesc.Quality = 0; + swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT; + swapchain_desc.BufferCount = 2; + swapchain_desc.Scaling = DXGI_SCALING_STRETCH; + swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD; + swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED; + swapchain_desc.Flags = 0; + + hr = IDXGIFactory2_CreateSwapChainForHwnd(factory2, device, + window, &swapchain_desc, NULL, NULL, &swapchain1); + ok(hr == S_OK, "Failed to create swap chain, hr %#x.\n", hr); + + hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void**)&swapchain2); + IDXGISwapChain1_Release(swapchain1); + + if (FAILED(hr)) + { + win_skip("IDXGISwapChain2 not available.\n"); + IDXGIFactory2_Release(factory2); + return; + } + + /* test swap chain without waitable object */ + frame_latency = 0xdeadbeef; + hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + ok(frame_latency == 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency); + hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 1); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!event, "Got unexpected event %p.\n", event); + + ref_count = IDXGISwapChain2_Release(swapchain2); + ok(!ref_count, "Swap chain has %u references left.\n", ref_count); + + /* test swap chain with waitable object */ + swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT; + + hr = IDXGIFactory2_CreateSwapChainForHwnd(factory2, device, + window, &swapchain_desc, NULL, NULL, &swapchain1); + ok(hr == S_OK, "Failed to create swap chain, hr %#x.\n", hr); + hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void**)&swapchain2); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + IDXGISwapChain1_Release(swapchain1); + + event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!event, "Got unexpected event %p.\n", event); + + /* manual-reset event */ + wait_result = WaitForSingleObject(event, 0); + ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result); + wait_result = WaitForSingleObject(event, 0); + ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result); + + hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency); + + hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 0); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr); + hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency); + + hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 2); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); + ok(hr == S_OK, "Got unexpected hr %#x.\n", hr); + ok(frame_latency == 2, "Got unexpected frame latency %#x.\n", frame_latency); + + for (i = 0; i < 5; i++) + { + hr = IDXGISwapChain2_Present(swapchain2, 0, 0); + ok(hr == S_OK, "Present failed with hr %#x.\n", hr); + } + + wait_result = WaitForSingleObject(event, 1000); + ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result); + + ref_count = IDXGISwapChain2_Release(swapchain2); + ok(!ref_count, "Swap chain has %u references left.\n", ref_count); + + DestroyWindow(window); + + ref_count = IDXGIFactory2_Release(factory2); + ok(ref_count == !is_d3d12, "Factory has %u references left.\n", ref_count); +} + static void run_on_d3d10(void (*test_func)(IUnknown *device, BOOL is_d3d12)) { IDXGIDevice *device; @@ -6325,6 +6446,7 @@ START_TEST(dxgi) run_on_d3d12(test_swapchain_formats); run_on_d3d12(test_output_ownership); run_on_d3d12(test_cursor_clipping); + run_on_d3d12(test_frame_latency_event);
FreeLibrary(d3d12_module); }
Actually this started failing on Windows 10 now for some reason, I'll investigate.
Am 15.04.20 um 17:23 schrieb Philip Rebohle:
Signed-off-by: Philip Rebohle philip.rebohle@tu-dortmund.de
dlls/dxgi/tests/dxgi.c | 122 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 122 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 3887982634..b016c35938 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6188,6 +6188,127 @@ static void test_factory_check_feature_support(void) ok(!ref_count, "Factory has %u references left.\n", ref_count); }
+static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) +{
- DXGI_SWAP_CHAIN_DESC1 swapchain_desc;
- IDXGISwapChain2 *swapchain2;
- IDXGISwapChain1 *swapchain1;
- IDXGIFactory2 *factory2;
- IDXGIFactory *factory;
- UINT frame_latency;
- DWORD wait_result;
- ULONG ref_count;
- unsigned int i;
- HANDLE event;
- HWND window;
- HRESULT hr;
- get_factory(device, is_d3d12, &factory);
- hr = IDXGIFactory_QueryInterface(factory, &IID_IDXGIFactory2, (void**)&factory2);
- IDXGIFactory_Release(factory);
- if (FAILED(hr))
- {
win_skip("IDXGIFactory2 not available.\n");
return;
- }
- window = CreateWindowA("static", "dxgi_test", 0, 640, 480, 0, 0, 0, 0, 0, 0);
- swapchain_desc.Width = 640;
- swapchain_desc.Height = 480;
- swapchain_desc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
- swapchain_desc.Stereo = FALSE;
- swapchain_desc.SampleDesc.Count = 1;
- swapchain_desc.SampleDesc.Quality = 0;
- swapchain_desc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
- swapchain_desc.BufferCount = 2;
- swapchain_desc.Scaling = DXGI_SCALING_STRETCH;
- swapchain_desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD;
- swapchain_desc.AlphaMode = DXGI_ALPHA_MODE_UNSPECIFIED;
- swapchain_desc.Flags = 0;
- hr = IDXGIFactory2_CreateSwapChainForHwnd(factory2, device,
window, &swapchain_desc, NULL, NULL, &swapchain1);
- ok(hr == S_OK, "Failed to create swap chain, hr %#x.\n", hr);
- hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void**)&swapchain2);
- IDXGISwapChain1_Release(swapchain1);
- if (FAILED(hr))
- {
win_skip("IDXGISwapChain2 not available.\n");
IDXGIFactory2_Release(factory2);
return;
- }
- /* test swap chain without waitable object */
- frame_latency = 0xdeadbeef;
- hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency);
- ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
- ok(frame_latency == 0xdeadbeef, "Got unexpected frame latency %#x.\n", frame_latency);
- hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 1);
- ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
- event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2);
- ok(!event, "Got unexpected event %p.\n", event);
- ref_count = IDXGISwapChain2_Release(swapchain2);
- ok(!ref_count, "Swap chain has %u references left.\n", ref_count);
- /* test swap chain with waitable object */
- swapchain_desc.Flags = DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT;
- hr = IDXGIFactory2_CreateSwapChainForHwnd(factory2, device,
window, &swapchain_desc, NULL, NULL, &swapchain1);
- ok(hr == S_OK, "Failed to create swap chain, hr %#x.\n", hr);
- hr = IDXGISwapChain1_QueryInterface(swapchain1, &IID_IDXGISwapChain2, (void**)&swapchain2);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- IDXGISwapChain1_Release(swapchain1);
- event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2);
- ok(!!event, "Got unexpected event %p.\n", event);
- /* manual-reset event */
- wait_result = WaitForSingleObject(event, 0);
- ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result);
- wait_result = WaitForSingleObject(event, 0);
- ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result);
- hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency);
- hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 0);
- ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#x.\n", hr);
- hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency);
- hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 2);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency);
- ok(hr == S_OK, "Got unexpected hr %#x.\n", hr);
- ok(frame_latency == 2, "Got unexpected frame latency %#x.\n", frame_latency);
- for (i = 0; i < 5; i++)
- {
hr = IDXGISwapChain2_Present(swapchain2, 0, 0);
ok(hr == S_OK, "Present failed with hr %#x.\n", hr);
- }
- wait_result = WaitForSingleObject(event, 1000);
- ok(!wait_result, "Got unexpected wait result %#x.\n", wait_result);
- ref_count = IDXGISwapChain2_Release(swapchain2);
- ok(!ref_count, "Swap chain has %u references left.\n", ref_count);
- DestroyWindow(window);
- ref_count = IDXGIFactory2_Release(factory2);
- ok(ref_count == !is_d3d12, "Factory has %u references left.\n", ref_count);
+}
- static void run_on_d3d10(void (*test_func)(IUnknown *device, BOOL is_d3d12)) { IDXGIDevice *device;
@@ -6325,6 +6446,7 @@ START_TEST(dxgi) run_on_d3d12(test_swapchain_formats); run_on_d3d12(test_output_ownership); run_on_d3d12(test_cursor_clipping);
run_on_d3d12(test_frame_latency_event);
FreeLibrary(d3d12_module); }
Hi,
While running your changed tests, I think I found new failures. Being a bot and all I'm not very good at pattern recognition, so I might be wrong, but could you please double-check?
Full results can be found at: https://testbot.winehq.org/JobDetails.pl?Key=69708
Your paranoid android.
=== w1064v1809 (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809_2scr (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809_ar (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809_he (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809_ja (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809_zh_CN (32 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.
=== w1064v1809 (64 bit report) ===
dxgi: dxgi.c:6276: Test failed: Got unexpected wait result 0x102.