From cb4b5641eab7b7db2f107a62cb81afebd6e71da5 Mon Sep 17 00:00:00 2001 From: Henri Verbeet Date: Tue, 29 Apr 2025 21:03:26 +0200 Subject: [PATCH] vkd3d: Handle multiple fence NULL event waits in d3d12_device_SetEventOnMultipleFenceCompletion(). --- libs/vkd3d/command.c | 15 ++++--------- libs/vkd3d/device.c | 22 +++++++++++++------ libs/vkd3d/vkd3d_private.h | 12 +++++++++++ tests/d3d12.c | 44 ++++++++++++-------------------------- 4 files changed, 45 insertions(+), 48 deletions(-) diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c index 1399494ef..e487ed0b9 100644 --- a/libs/vkd3d/command.c +++ b/libs/vkd3d/command.c @@ -31,13 +31,6 @@ static void d3d12_command_queue_submit_locked(struct d3d12_command_queue *queue) static HRESULT d3d12_command_queue_flush_ops(struct d3d12_command_queue *queue, bool *flushed_any); static HRESULT d3d12_command_queue_flush_ops_locked(struct d3d12_command_queue *queue, bool *flushed_any); -struct vkd3d_null_event -{ - struct vkd3d_mutex mutex; - struct vkd3d_cond cond; - bool signalled; -}; - static void vkd3d_null_event_signal(struct vkd3d_null_event *e) { vkd3d_mutex_lock(&e->mutex); @@ -46,7 +39,7 @@ static void vkd3d_null_event_signal(struct vkd3d_null_event *e) vkd3d_mutex_unlock(&e->mutex); } -static void vkd3d_null_event_wait(struct vkd3d_null_event *e) +void vkd3d_null_event_wait(struct vkd3d_null_event *e) { vkd3d_mutex_lock(&e->mutex); while (!e->signalled) @@ -55,20 +48,20 @@ static void vkd3d_null_event_wait(struct vkd3d_null_event *e) vkd3d_mutex_unlock(&e->mutex); } -static void vkd3d_null_event_cleanup(struct vkd3d_null_event *e) +void vkd3d_null_event_cleanup(struct vkd3d_null_event *e) { vkd3d_cond_destroy(&e->cond); vkd3d_mutex_destroy(&e->mutex); } -static void vkd3d_null_event_init(struct vkd3d_null_event *e) +void vkd3d_null_event_init(struct vkd3d_null_event *e) { vkd3d_mutex_init(&e->mutex); vkd3d_cond_init(&e->cond); e->signalled = false; } -static HRESULT vkd3d_signal_null_event(HANDLE h) +HRESULT vkd3d_signal_null_event(HANDLE h) { vkd3d_null_event_signal(h); diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c index a928a5734..b2636fd55 100644 --- a/libs/vkd3d/device.c +++ b/libs/vkd3d/device.c @@ -4948,6 +4948,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion( D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event) { struct d3d12_device *device = impl_from_ID3D12Device9(iface); + struct vkd3d_null_event null_event; struct waiting_event_semaphore *s; PFN_vkd3d_signal_event signal; struct d3d12_fence *fence; @@ -4969,20 +4970,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion( if (fence_count == 1) return ID3D12Fence_SetEventOnCompletion(fences[0], values[0], event); - if (!event) - { - FIXME("Unhandled NULL event.\n"); - return E_NOTIMPL; - } - if (!(s = vkd3d_malloc(sizeof(*s)))) { WARN("Failed to allocate semaphore memory.\n"); return E_OUTOFMEMORY; } + signal = device->signal_event; + if (!event) + { + vkd3d_null_event_init(&null_event); + event = &null_event; + signal = vkd3d_signal_null_event; + } s->event = event; - s->signal = device->signal_event; + s->signal = signal; s->value = fence_count; if (flags & D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY) @@ -5017,6 +5019,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion( vkd3d_mutex_unlock(&fence->mutex); } + if (event == &null_event) + { + vkd3d_null_event_wait(&null_event); + vkd3d_null_event_cleanup(&null_event); + } + return hr; } diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h index ac232fb04..682adc816 100644 --- a/libs/vkd3d/vkd3d_private.h +++ b/libs/vkd3d/vkd3d_private.h @@ -357,6 +357,18 @@ HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store, const GUID *tag, unsigned int data_size, const void *data); HRESULT vkd3d_set_private_data_interface(struct vkd3d_private_store *store, const GUID *tag, const IUnknown *object); +struct vkd3d_null_event +{ + struct vkd3d_mutex mutex; + struct vkd3d_cond cond; + bool signalled; +}; + +void vkd3d_null_event_cleanup(struct vkd3d_null_event *e); +void vkd3d_null_event_init(struct vkd3d_null_event *e); +void vkd3d_null_event_wait(struct vkd3d_null_event *e); +HRESULT vkd3d_signal_null_event(HANDLE h); + struct vkd3d_signaled_semaphore { uint64_t value; diff --git a/tests/d3d12.c b/tests/d3d12.c index c045040fd..788ad66e7 100644 --- a/tests/d3d12.c +++ b/tests/d3d12.c @@ -38915,8 +38915,7 @@ static void multi_fence_event_wait_main(void *ctx) hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(data->device, data->fences, data->values, data->fence_count, data->flags, NULL); - if (vkd3d_test_platform_is_windows() || data->fence_count == 1) - ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); signal_event(data->completed); } @@ -39050,7 +39049,7 @@ static void test_multi_fence_event(void) ok(hr == S_OK, "Got hr %#x.\n", hr); hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, NULL); - todo ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ret = wait_event(event, 0); ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, @@ -39060,7 +39059,7 @@ static void test_multi_fence_event(void) ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, NULL); - todo ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); ret = wait_event(event, 0); ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, @@ -39100,25 +39099,16 @@ static void test_multi_fence_event(void) ok(thread, "Failed to create thread.\n"); ret = wait_event(thread_data.started, INFINITE); ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); - if (vkd3d_test_platform_is_windows()) - { - ret = wait_event(thread_data.completed, 0); - ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); - } + ret = wait_event(thread_data.completed, 0); + ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Fence_Signal(fences[1], 41); ok(hr == S_OK, "Got hr %#x.\n", hr); - if (vkd3d_test_platform_is_windows()) - { - ret = wait_event(thread_data.completed, 0); - ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); - } + ret = wait_event(thread_data.completed, 0); + ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Fence_Signal(fences[0], 40); ok(hr == S_OK, "Got hr %#x.\n", hr); - if (vkd3d_test_platform_is_windows()) - { - ret = wait_event(thread_data.completed, 0); - ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); - } + ret = wait_event(thread_data.completed, 0); + ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Fence_Signal(fences[2], 42); ok(hr == S_OK, "Got hr %#x.\n", hr); ret = wait_event(thread_data.completed, INFINITE); @@ -39154,11 +39144,8 @@ static void test_multi_fence_event(void) ok(thread, "Failed to create thread.\n"); ret = wait_event(thread_data.started, INFINITE); ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); - if (vkd3d_test_platform_is_windows()) - { - ret = wait_event(thread_data.completed, 0); - ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); - } + ret = wait_event(thread_data.completed, 0); + ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Fence_Signal(fences[1], 57); ok(hr == S_OK, "Got hr %#x.\n", hr); ret = wait_event(thread_data.completed, INFINITE); @@ -39189,11 +39176,8 @@ static void test_multi_fence_event(void) ok(thread, "Failed to create thread.\n"); ret = wait_event(thread_data.started, INFINITE); ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); - if (vkd3d_test_platform_is_windows()) - { - ret = wait_event(thread_data.completed, 0); - ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); - } + ret = wait_event(thread_data.completed, 0); + ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); hr = ID3D12Fence_Signal(fences[1], 67); ok(hr == S_OK, "Got hr %#x.\n", hr); ret = wait_event(thread_data.completed, INFINITE); @@ -39211,7 +39195,7 @@ static void test_multi_fence_event(void) hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, NULL); - todo ok(hr == S_OK, "Got hr %#x.\n", hr); + ok(hr == S_OK, "Got hr %#x.\n", hr); destroy_event(thread_data.completed); destroy_event(thread_data.started);