-- v2: dxgi/tests: Test the frame latency waitable more thoroughly.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/tests/dxgi.c | 100 ++++++++++++++++++++++++----------------- 1 file changed, 59 insertions(+), 41 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index ac302840dec..b5f1475ca78 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -908,8 +908,8 @@ static IDXGIAdapter *get_adapter_(unsigned int line, IUnknown *device, BOOL is_d return adapter; }
-#define create_swapchain(a, b, c) create_swapchain_(__LINE__, a, b, c) -static IDXGISwapChain *create_swapchain_(unsigned int line, IUnknown *device, BOOL is_d3d12, HWND window) +#define create_swapchain(a, b, c, d) create_swapchain_(__LINE__, a, b, c, d) +static IDXGISwapChain *create_swapchain_(unsigned int line, IUnknown *device, BOOL is_d3d12, HWND window, UINT flags) { DXGI_SWAP_CHAIN_DESC desc; IDXGISwapChain *swapchain; @@ -930,7 +930,7 @@ static IDXGISwapChain *create_swapchain_(unsigned int line, IUnknown *device, BO desc.OutputWindow = window; desc.Windowed = TRUE; desc.SwapEffect = is_d3d12 ? DXGI_SWAP_EFFECT_FLIP_DISCARD : DXGI_SWAP_EFFECT_DISCARD; - desc.Flags = 0; + desc.Flags = flags;
get_factory(device, is_d3d12, &factory); hr = IDXGIFactory_CreateSwapChain(factory, device, &desc, &swapchain); @@ -7564,57 +7564,75 @@ done:
static void test_swapchain_present_count(IUnknown *device, BOOL is_d3d12) { + static const UINT test_flags[] = + { + 0, + DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT, + }; + UINT present_count, expected; IDXGISwapChain *swapchain; + unsigned int i; HWND window; HRESULT hr;
window = create_window(); - swapchain = create_swapchain(device, is_d3d12, window);
- present_count = ~0u; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(!present_count, "Got unexpected present count %u.\n", present_count); + for (i = 0; i < ARRAY_SIZE(test_flags); ++i) + { + UINT flags = test_flags[i];
- hr = IDXGISwapChain_Present(swapchain, 0, 0); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - expected = present_count + 1; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + if (!is_d3d12 && (flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT)) + continue;
- hr = IDXGISwapChain_Present(swapchain, 10, 0); - ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); - expected = present_count; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + swapchain = create_swapchain(device, is_d3d12, window, flags);
- hr = IDXGISwapChain_Present(swapchain, 0, DXGI_PRESENT_TEST); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - expected = present_count; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + present_count = ~0u; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + todo_wine_if(flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) + ok(!present_count, "Got unexpected present count %u.\n", present_count);
- ShowWindow(window, SW_MINIMIZE); - hr = IDXGISwapChain_Present(swapchain, 0, 0); - ok(hr == (is_d3d12 ? S_OK : DXGI_STATUS_OCCLUDED), "Got unexpected hr %#lx.\n", hr); - expected = present_count + !!is_d3d12; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + hr = IDXGISwapChain_Present(swapchain, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + expected = present_count + 1; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected);
- ShowWindow(window, SW_NORMAL); - hr = IDXGISwapChain_Present(swapchain, 0, 0); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - expected = present_count + 1; - hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); - ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + hr = IDXGISwapChain_Present(swapchain, 10, 0); + ok(hr == DXGI_ERROR_INVALID_CALL, "Got unexpected hr %#lx.\n", hr); + expected = present_count; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + + hr = IDXGISwapChain_Present(swapchain, 0, DXGI_PRESENT_TEST); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + expected = present_count; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + + ShowWindow(window, SW_MINIMIZE); + hr = IDXGISwapChain_Present(swapchain, 0, 0); + ok(hr == (is_d3d12 ? S_OK : DXGI_STATUS_OCCLUDED), "Got unexpected hr %#lx.\n", hr); + expected = present_count + !!is_d3d12; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + + ShowWindow(window, SW_NORMAL); + hr = IDXGISwapChain_Present(swapchain, 0, 0); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + expected = present_count + 1; + hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(present_count == expected, "Got unexpected present count %u, expected %u.\n", present_count, expected); + + IDXGISwapChain_Release(swapchain); + }
- IDXGISwapChain_Release(swapchain); DestroyWindow(window); }
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 9 ++++++--- dlls/dxgi/tests/dxgi.c | 1 - 2 files changed, 6 insertions(+), 4 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 1f5eb99ab4b..554e910de11 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2039,15 +2039,19 @@ static HRESULT d3d12_swapchain_present(struct d3d12_swapchain *swapchain, ++swapchain->frame_number; if ((frame_latency_event = swapchain->frame_latency_event)) { + /* Bias the frame number to avoid underflowing in + * SetEventOnCompletion(). */ + uint64_t number = swapchain->frame_number + DXGI_MAX_SWAP_CHAIN_BUFFERS; + if (FAILED(hr = ID3D12CommandQueue_Signal(swapchain->command_queue, - swapchain->frame_latency_fence, swapchain->frame_number))) + swapchain->frame_latency_fence, number))) { ERR("Failed to signal frame latency fence, hr %#lx.\n", hr); return hr; }
if (FAILED(hr = ID3D12Fence_SetEventOnCompletion(swapchain->frame_latency_fence, - swapchain->frame_number - swapchain->frame_latency, frame_latency_event))) + number - swapchain->frame_latency, frame_latency_event))) { ERR("Failed to enqueue frame latency event, hr %#lx.\n", hr); return hr; @@ -2979,7 +2983,6 @@ 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, diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index b5f1475ca78..0661c68b109 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -7590,7 +7590,6 @@ static void test_swapchain_present_count(IUnknown *device, BOOL is_d3d12) present_count = ~0u; hr = IDXGISwapChain_GetLastPresentCount(swapchain, &present_count); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); - todo_wine_if(flags & DXGI_SWAP_CHAIN_FLAG_FRAME_LATENCY_WAITABLE_OBJECT) ok(!present_count, "Got unexpected present count %u.\n", present_count);
hr = IDXGISwapChain_Present(swapchain, 0, 0);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/swapchain.c | 16 +++++++++++++++- dlls/dxgi/tests/dxgi.c | 18 ++++++++++++++++-- 2 files changed, 31 insertions(+), 3 deletions(-)
diff --git a/dlls/dxgi/swapchain.c b/dlls/dxgi/swapchain.c index 554e910de11..910286b8c5f 100644 --- a/dlls/dxgi/swapchain.c +++ b/dlls/dxgi/swapchain.c @@ -2564,10 +2564,24 @@ static HRESULT STDMETHODCALLTYPE d3d12_swapchain_GetMaximumFrameLatency(IDXGISwa static HANDLE STDMETHODCALLTYPE d3d12_swapchain_GetFrameLatencyWaitableObject(IDXGISwapChain4 *iface) { struct d3d12_swapchain *swapchain = d3d12_swapchain_from_IDXGISwapChain4(iface); + HANDLE dup; + BOOL ret;
TRACE("iface %p.\n", iface);
- return swapchain->frame_latency_event; + if (!swapchain->frame_latency_event) + return NULL; + + ret = DuplicateHandle(GetCurrentProcess(), swapchain->frame_latency_event, GetCurrentProcess(), + &dup, 0, FALSE, DUPLICATE_SAME_ACCESS); + + if (!ret) + { + ERR("Cannot duplicate handle, last error %lu.\n", GetLastError()); + return NULL; + } + + return dup; }
static HRESULT STDMETHODCALLTYPE d3d12_swapchain_SetMatrixTransform(IDXGISwapChain4 *iface, diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 0661c68b109..4cd122995ef 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6981,13 +6981,14 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) IDXGISwapChain1 *swapchain1; IDXGIFactory2 *factory2; IDXGIFactory *factory; + HANDLE event, event2; UINT frame_latency; DWORD wait_result; ULONG ref_count; unsigned int i; - HANDLE event; HWND window; HRESULT hr; + BOOL ret;
get_factory(device, is_d3d12, &factory);
@@ -7052,7 +7053,20 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) IDXGISwapChain1_Release(swapchain1);
event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); - ok(!!event, "Got unexpected event %p.\n", event); + ok(!!event, "Got unexpected NULL event.\n"); + + /* a new duplicate handle is returned each time */ + event2 = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!event2, "Got unexpected NULL event.\n"); + ok(event != event2, "Got the same event twice %p.\n", event); + + ret = CloseHandle(event); + ok(!!ret, "Failed to close handle, last error %lu.\n", GetLastError()); + ret = CloseHandle(event2); + ok(!!ret, "Failed to close handle, last error %lu.\n", GetLastError()); + + event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!event, "Got unexpected NULL event.\n");
/* auto-reset event */ wait_result = WaitForSingleObject(event, 0);
From: Giovanni Mascellani gmascellani@codeweavers.com
From the tests it behaves more like a semaphore than like an event.
I'm not testing explicitly because I'm not sure it's relevant, but another indication is that calling ReleaseSemaphore() returns ERROR_ACCESS_DENIED, while calling SetEvent() returns ERROR_INVALID_HANDLE. --- dlls/dxgi/tests/dxgi.c | 39 +++++++++++++++++++-------------------- 1 file changed, 19 insertions(+), 20 deletions(-)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index 4cd122995ef..b8863594090 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6977,11 +6977,11 @@ static void test_factory_check_feature_support(void) static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) { DXGI_SWAP_CHAIN_DESC1 swapchain_desc; + HANDLE semaphore, semaphore2; IDXGISwapChain2 *swapchain2; IDXGISwapChain1 *swapchain1; IDXGIFactory2 *factory2; IDXGIFactory *factory; - HANDLE event, event2; UINT frame_latency; DWORD wait_result; ULONG ref_count; @@ -7036,8 +7036,8 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) 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 %#lx.\n", hr); - event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); - ok(!event, "Got unexpected event %p.\n", event); + semaphore = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!semaphore, "Got unexpected semaphore %p.\n", semaphore);
ref_count = IDXGISwapChain2_Release(swapchain2); ok(!ref_count, "Swap chain has %lu references left.\n", ref_count); @@ -7052,26 +7052,25 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); IDXGISwapChain1_Release(swapchain1);
- event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); - ok(!!event, "Got unexpected NULL event.\n"); + semaphore = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!semaphore, "Got unexpected NULL semaphore.\n");
/* a new duplicate handle is returned each time */ - event2 = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); - ok(!!event2, "Got unexpected NULL event.\n"); - ok(event != event2, "Got the same event twice %p.\n", event); + semaphore2 = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!semaphore2, "Got unexpected NULL semaphore.\n"); + ok(semaphore != semaphore2, "Got the same semaphore twice %p.\n", semaphore);
- ret = CloseHandle(event); + ret = CloseHandle(semaphore); ok(!!ret, "Failed to close handle, last error %lu.\n", GetLastError()); - ret = CloseHandle(event2); + ret = CloseHandle(semaphore2); ok(!!ret, "Failed to close handle, last error %lu.\n", GetLastError());
- event = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); - ok(!!event, "Got unexpected NULL event.\n"); + semaphore = IDXGISwapChain2_GetFrameLatencyWaitableObject(swapchain2); + ok(!!semaphore, "Got unexpected NULL semaphore.\n");
- /* auto-reset event */ - wait_result = WaitForSingleObject(event, 0); + wait_result = WaitForSingleObject(semaphore, 0); ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); - wait_result = WaitForSingleObject(event, 0); + wait_result = WaitForSingleObject(semaphore, 0); ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result);
hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); @@ -7090,11 +7089,11 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(frame_latency == 3, "Got unexpected frame latency %#x.\n", frame_latency);
- wait_result = WaitForSingleObject(event, 0); + wait_result = WaitForSingleObject(semaphore, 0); todo_wine ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); - wait_result = WaitForSingleObject(event, 0); + wait_result = WaitForSingleObject(semaphore, 0); todo_wine ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); - wait_result = WaitForSingleObject(event, 100); + wait_result = WaitForSingleObject(semaphore, 100); ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result);
for (i = 0; i < 5; i++) @@ -7102,11 +7101,11 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) hr = IDXGISwapChain2_Present(swapchain2, 0, 0); ok(hr == S_OK, "Present %u failed with hr %#lx.\n", i, hr);
- wait_result = WaitForSingleObject(event, 100); + wait_result = WaitForSingleObject(semaphore, 100); ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); }
- wait_result = WaitForSingleObject(event, 100); + wait_result = WaitForSingleObject(semaphore, 100); ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result);
ref_count = IDXGISwapChain2_Release(swapchain2);
From: Giovanni Mascellani gmascellani@codeweavers.com
--- dlls/dxgi/tests/dxgi.c | 90 ++++++++++++++++++++++++++++++++++++++++++ 1 file changed, 90 insertions(+)
diff --git a/dlls/dxgi/tests/dxgi.c b/dlls/dxgi/tests/dxgi.c index b8863594090..a80a21ae206 100644 --- a/dlls/dxgi/tests/dxgi.c +++ b/dlls/dxgi/tests/dxgi.c @@ -6980,8 +6980,11 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) HANDLE semaphore, semaphore2; IDXGISwapChain2 *swapchain2; IDXGISwapChain1 *swapchain1; + ID3D12Device *d3d12_device; + ID3D12CommandQueue *queue; IDXGIFactory2 *factory2; IDXGIFactory *factory; + ID3D12Fence *fence; UINT frame_latency; DWORD wait_result; ULONG ref_count; @@ -7083,6 +7086,8 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency);
+ /* raising the maximum frame latency releases the semaphore the + * corresponding number of times */ hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 3); ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); @@ -7096,6 +7101,17 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) wait_result = WaitForSingleObject(semaphore, 100); ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result);
+ /* lowering the maximum frame latency doesn't seem to impact the + * semaphore */ + hr = IDXGISwapChain2_SetMaximumFrameLatency(swapchain2, 1); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + hr = IDXGISwapChain2_GetMaximumFrameLatency(swapchain2, &frame_latency); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + ok(frame_latency == 1, "Got unexpected frame latency %#x.\n", frame_latency); + + wait_result = WaitForSingleObject(semaphore, 100); + ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result); + for (i = 0; i < 5; i++) { hr = IDXGISwapChain2_Present(swapchain2, 0, 0); @@ -7108,6 +7124,80 @@ static void test_frame_latency_event(IUnknown *device, BOOL is_d3d12) wait_result = WaitForSingleObject(semaphore, 100); ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result);
+ /* each frame presentation releases the semaphore */ + for (i = 0; i < 5; i++) + { + hr = IDXGISwapChain2_Present(swapchain2, 0, 0); + ok(hr == S_OK, "Present %u failed with hr %#lx.\n", i, hr); + } + + for (i = 0; i < 5; i++) + { + wait_result = WaitForSingleObject(semaphore, 100); + todo_wine_if(i != 0) + ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); + } + + wait_result = WaitForSingleObject(semaphore, 100); + ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result); + + if (is_d3d12) + { + hr = IUnknown_QueryInterface(device, &IID_ID3D12CommandQueue, (void **)&queue); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID3D12CommandQueue_GetDevice(queue, &IID_ID3D12Device, (void **)&d3d12_device); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + hr = ID3D12Device_CreateFence(d3d12_device, 0, 0, &IID_ID3D12Fence, (void **)&fence); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + /* the semaphore is released when the frame is really + * presented, not when Present() is called */ + for (i = 0; i < 3; i++) + { + hr = IDXGISwapChain2_Present(swapchain2, 0, 0); + ok(hr == S_OK, "Present %u failed with hr %#lx.\n", i, hr); + } + + hr = ID3D12CommandQueue_Wait(queue, fence, 1); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (i = 0; i < 4; i++) + { + hr = IDXGISwapChain2_Present(swapchain2, 0, 0); + ok(hr == S_OK, "Present %u failed with hr %#lx.\n", i, hr); + } + + for (i = 0; i < 3; i++) + { + wait_result = WaitForSingleObject(semaphore, 100); + todo_wine_if(i != 0) + ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); + } + + wait_result = WaitForSingleObject(semaphore, 100); + ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result); + + hr = ID3D12Fence_Signal(fence, 1); + ok(hr == S_OK, "Got unexpected hr %#lx.\n", hr); + + for (i = 0; i < 4; i++) + { + wait_result = WaitForSingleObject(semaphore, 100); + todo_wine_if(i != 0) + ok(!wait_result, "Got unexpected wait result %#lx.\n", wait_result); + } + + wait_result = WaitForSingleObject(semaphore, 100); + ok(wait_result == WAIT_TIMEOUT, "Got unexpected wait result %#lx.\n", wait_result); + + ref_count = ID3D12Fence_Release(fence); + ok(!ref_count, "Fence has %lu references left.\n", ref_count); + ID3D12Device_Release(d3d12_device); + ID3D12CommandQueue_Release(queue); + } + ref_count = IDXGISwapChain2_Release(swapchain2); ok(!ref_count, "Swap chain has %lu references left.\n", ref_count); DestroyWindow(window);
On Fri Mar 24 15:46:37 2023 +0000, Giovanni Mascellani wrote:
Basically what the comment says: that lowering the maximum frame latency (here going from 3 to 1) doesn't cause any change in the semaphore state (which had value zero just before these lines and still has value zero here). When I realized that raising the maximum frame latency causes the semaphore to be released I wondered what would happen when lowering it. For example, it could wait on it. However, it seems it doesn't (this is apparently also confirmed by vkd3d-proton's implementation).
Oh, duh, I understand what this is doing now. Chalk that up to me not properly understanding the code before reviewing.
This is randomly succeeding for me, along the lines of:
dxgi.c:7138: Test succeeded inside todo block: Got unexpected wait result 0. dxgi.c:7189: Test succeeded inside todo block: Got unexpected wait result 0. dxgi.c:7189: Test succeeded inside todo block: Got unexpected wait result 0.
Is there any way to avoid that?
On Wed Mar 29 14:05:35 2023 +0000, Zebediah Figura wrote:
This is randomly succeeding for me, along the lines of: dxgi.c:7138: Test succeeded inside todo block: Got unexpected wait result 0. dxgi.c:7189: Test succeeded inside todo block: Got unexpected wait result 0. dxgi.c:7189: Test succeeded inside todo block: Got unexpected wait result 0. Is there any way to avoid that?
Ha, that's what that `Sleep(100)` call was for! I guess that sometimes the scheduled presentation requests take a bit longer to happen, and set the event after it is waited for, seemingly making it behave like a semaphore and therefore violating the `todo_wine_if()` annotation. I'll reintroduce `Sleep(100)`, so that waiting for events starts only once all presentations have (hopefully) happened. Once `todo_wine_if()` is removed, the `Sleep(100)` can be removed to (what is the future tense of "can" in English, in the contexts where "be able to" is not a valid replacement for "can"?).