Conor McCarthy : vkd3d: Handle NULL event handles in ID3D12Fence::SetEventOnCompletion().
Alexandre Julliard
julliard at winehq.org
Wed Jan 19 15:52:11 CST 2022
Module: vkd3d
Branch: master
Commit: c965b7b213f59adf39626d984e5af1ae9ddd7148
URL: https://source.winehq.org/git/vkd3d.git/?a=commit;h=c965b7b213f59adf39626d984e5af1ae9ddd7148
Author: Conor McCarthy <cmccarthy at codeweavers.com>
Date: Tue Jan 18 15:54:11 2022 +1000
vkd3d: Handle NULL event handles in ID3D12Fence::SetEventOnCompletion().
The D3D12 documentation states: "If hEvent is a null handle, then
this API will not return until the specified fence value(s) have
been reached."
Based on a vkd3d-proton patch by Hans-Kristian Arntzen.
Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
Signed-off-by: Henri Verbeet <hverbeet at codeweavers.com>
Signed-off-by: Alexandre Julliard <julliard at winehq.org>
---
libs/vkd3d/command.c | 39 +++++++++++++++++++++++++++++++++++++--
libs/vkd3d/vkd3d_private.h | 2 ++
2 files changed, 39 insertions(+), 2 deletions(-)
diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 6689c1a..73ba226 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -806,6 +806,7 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
{
struct d3d12_device *device = fence->device;
struct vkd3d_signaled_semaphore *current;
+ bool signal_null_event_cond = false;
unsigned int i, j;
int rc;
@@ -823,7 +824,15 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
if (current->value <= value)
{
- fence->device->signal_event(current->event);
+ if (current->event)
+ {
+ fence->device->signal_event(current->event);
+ }
+ else
+ {
+ current->latch = true;
+ signal_null_event_cond = true;
+ }
}
else
{
@@ -834,6 +843,9 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
}
fence->event_count = j;
+ if (signal_null_event_cond)
+ pthread_cond_broadcast(&fence->null_event_cond);
+
if (vk_fence)
{
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
@@ -916,6 +928,7 @@ static ULONG STDMETHODCALLTYPE d3d12_fence_Release(ID3D12Fence *iface)
vkd3d_free(fence->events);
if ((rc = pthread_mutex_destroy(&fence->mutex)))
ERR("Failed to destroy mutex, error %d.\n", rc);
+ pthread_cond_destroy(&fence->null_event_cond);
vkd3d_free(fence);
d3d12_device_release(device);
@@ -997,6 +1010,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
{
struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
unsigned int i;
+ bool *latch;
int rc;
TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
@@ -1009,7 +1023,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
if (value <= fence->value)
{
- fence->device->signal_event(event);
+ if (event)
+ fence->device->signal_event(event);
pthread_mutex_unlock(&fence->mutex);
return S_OK;
}
@@ -1036,8 +1051,20 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
fence->events[fence->event_count].value = value;
fence->events[fence->event_count].event = event;
+ fence->events[fence->event_count].latch = false;
+ latch = &fence->events[fence->event_count].latch;
++fence->event_count;
+ /* If event is NULL, we need to block until the fence value completes.
+ * Implement this in a uniform way where we pretend we have a dummy event.
+ * A NULL fence->events[].event means that we should set latch to true
+ * and signal a condition variable instead of calling external signal_event callback. */
+ if (!event)
+ {
+ while (!*latch)
+ pthread_cond_wait(&fence->null_event_cond, &fence->mutex);
+ }
+
pthread_mutex_unlock(&fence->mutex);
return S_OK;
}
@@ -1095,6 +1122,13 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
return hresult_from_errno(rc);
}
+ if ((rc = pthread_cond_init(&fence->null_event_cond, NULL)))
+ {
+ ERR("Failed to initialize cond variable, error %d.\n", rc);
+ pthread_mutex_destroy(&fence->mutex);
+ return hresult_from_errno(rc);
+ }
+
if (flags)
FIXME("Ignoring flags %#x.\n", flags);
@@ -1112,6 +1146,7 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
if (FAILED(hr = vkd3d_private_store_init(&fence->private_store)))
{
pthread_mutex_destroy(&fence->mutex);
+ pthread_cond_destroy(&fence->null_event_cond);
return hr;
}
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index aa18fcb..b630b6d 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -367,11 +367,13 @@ struct d3d12_fence
uint64_t value;
pthread_mutex_t mutex;
+ pthread_cond_t null_event_cond;
struct vkd3d_waiting_event
{
uint64_t value;
HANDLE event;
+ bool latch;
} *events;
size_t events_size;
size_t event_count;
More information about the wine-cvs
mailing list