vkd3d: Handle multiple fence NULL event waits in d3d12_device_SetEventOnMultipleFenceCompletion().

This commit is contained in:
Henri Verbeet
2025-04-29 21:03:26 +02:00
parent 3fabac3f70
commit cb4b5641ea
Notes: Henri Verbeet 2025-05-06 19:05:21 +02:00
Approved-by: Henri Verbeet (@hverbeet)
Merge-Request: https://gitlab.winehq.org/wine/vkd3d/-/merge_requests/1476
4 changed files with 45 additions and 48 deletions

View File

@@ -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(struct d3d12_command_queue *queue, bool *flushed_any);
static HRESULT d3d12_command_queue_flush_ops_locked(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) static void vkd3d_null_event_signal(struct vkd3d_null_event *e)
{ {
vkd3d_mutex_lock(&e->mutex); 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); 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); vkd3d_mutex_lock(&e->mutex);
while (!e->signalled) while (!e->signalled)
@@ -55,20 +48,20 @@ static void vkd3d_null_event_wait(struct vkd3d_null_event *e)
vkd3d_mutex_unlock(&e->mutex); 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_cond_destroy(&e->cond);
vkd3d_mutex_destroy(&e->mutex); 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_mutex_init(&e->mutex);
vkd3d_cond_init(&e->cond); vkd3d_cond_init(&e->cond);
e->signalled = false; e->signalled = false;
} }
static HRESULT vkd3d_signal_null_event(HANDLE h) HRESULT vkd3d_signal_null_event(HANDLE h)
{ {
vkd3d_null_event_signal(h); vkd3d_null_event_signal(h);

View File

@@ -4948,6 +4948,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event) D3D12_MULTIPLE_FENCE_WAIT_FLAGS flags, HANDLE event)
{ {
struct d3d12_device *device = impl_from_ID3D12Device9(iface); struct d3d12_device *device = impl_from_ID3D12Device9(iface);
struct vkd3d_null_event null_event;
struct waiting_event_semaphore *s; struct waiting_event_semaphore *s;
PFN_vkd3d_signal_event signal; PFN_vkd3d_signal_event signal;
struct d3d12_fence *fence; struct d3d12_fence *fence;
@@ -4969,20 +4970,21 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
if (fence_count == 1) if (fence_count == 1)
return ID3D12Fence_SetEventOnCompletion(fences[0], values[0], event); return ID3D12Fence_SetEventOnCompletion(fences[0], values[0], event);
if (!event)
{
FIXME("Unhandled NULL event.\n");
return E_NOTIMPL;
}
if (!(s = vkd3d_malloc(sizeof(*s)))) if (!(s = vkd3d_malloc(sizeof(*s))))
{ {
WARN("Failed to allocate semaphore memory.\n"); WARN("Failed to allocate semaphore memory.\n");
return E_OUTOFMEMORY; 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->event = event;
s->signal = device->signal_event; s->signal = signal;
s->value = fence_count; s->value = fence_count;
if (flags & D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY) if (flags & D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY)
@@ -5017,6 +5019,12 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
vkd3d_mutex_unlock(&fence->mutex); vkd3d_mutex_unlock(&fence->mutex);
} }
if (event == &null_event)
{
vkd3d_null_event_wait(&null_event);
vkd3d_null_event_cleanup(&null_event);
}
return hr; return hr;
} }

View File

@@ -357,6 +357,18 @@ HRESULT vkd3d_set_private_data(struct vkd3d_private_store *store,
const GUID *tag, unsigned int data_size, const void *data); 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); 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 struct vkd3d_signaled_semaphore
{ {
uint64_t value; uint64_t value;

View File

@@ -38915,8 +38915,7 @@ static void multi_fence_event_wait_main(void *ctx)
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(data->device, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(data->device,
data->fences, data->values, data->fence_count, data->flags, NULL); 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); signal_event(data->completed);
} }
@@ -39050,7 +39049,7 @@ static void test_multi_fence_event(void)
ok(hr == S_OK, "Got hr %#x.\n", hr); ok(hr == S_OK, "Got hr %#x.\n", hr);
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, NULL); 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); ret = wait_event(event, 0);
ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret);
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, 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); ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret);
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, NULL); 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); ret = wait_event(event, 0);
ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret); ok(ret == WAIT_TIMEOUT, "Got ret %#x.\n", ret);
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
@@ -39100,25 +39099,16 @@ static void test_multi_fence_event(void)
ok(thread, "Failed to create thread.\n"); ok(thread, "Failed to create thread.\n");
ret = wait_event(thread_data.started, INFINITE); ret = wait_event(thread_data.started, INFINITE);
ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); 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); hr = ID3D12Fence_Signal(fences[1], 41);
ok(hr == S_OK, "Got hr %#x.\n", hr); 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); hr = ID3D12Fence_Signal(fences[0], 40);
ok(hr == S_OK, "Got hr %#x.\n", hr); 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); hr = ID3D12Fence_Signal(fences[2], 42);
ok(hr == S_OK, "Got hr %#x.\n", hr); ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = wait_event(thread_data.completed, INFINITE); 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"); ok(thread, "Failed to create thread.\n");
ret = wait_event(thread_data.started, INFINITE); ret = wait_event(thread_data.started, INFINITE);
ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); 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); hr = ID3D12Fence_Signal(fences[1], 57);
ok(hr == S_OK, "Got hr %#x.\n", hr); ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = wait_event(thread_data.completed, INFINITE); 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"); ok(thread, "Failed to create thread.\n");
ret = wait_event(thread_data.started, INFINITE); ret = wait_event(thread_data.started, INFINITE);
ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret); 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); hr = ID3D12Fence_Signal(fences[1], 67);
ok(hr == S_OK, "Got hr %#x.\n", hr); ok(hr == S_OK, "Got hr %#x.\n", hr);
ret = wait_event(thread_data.completed, INFINITE); ret = wait_event(thread_data.completed, INFINITE);
@@ -39211,7 +39195,7 @@ static void test_multi_fence_event(void)
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, NULL); 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.completed);
destroy_event(thread_data.started); destroy_event(thread_data.started);