mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d: Introduce struct vkd3d_null_event.
This effectively moves "null_event_cond" from struct d3d12_fence and "latch" from struct vkd3d_waiting_event together into a separate structure, as well as storing the signalling function in struct vkd3d_waiting_event instead of getting it from struct d3d12_device. I think that largely makes sense on its own, but storing the signalling function in struct vkd3d_waiting_event also allows us to more easily implement d3d12_device_SetEventOnMultipleFenceCompletion() in a subsequent commit.
This commit is contained in:
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
@@ -31,6 +31,50 @@ 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)
|
||||||
|
{
|
||||||
|
vkd3d_mutex_lock(&e->mutex);
|
||||||
|
e->signalled = true;
|
||||||
|
vkd3d_cond_signal(&e->cond);
|
||||||
|
vkd3d_mutex_unlock(&e->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static void vkd3d_null_event_wait(struct vkd3d_null_event *e)
|
||||||
|
{
|
||||||
|
vkd3d_mutex_lock(&e->mutex);
|
||||||
|
while (!e->signalled)
|
||||||
|
vkd3d_cond_wait(&e->cond, &e->mutex);
|
||||||
|
e->signalled = false;
|
||||||
|
vkd3d_mutex_unlock(&e->mutex);
|
||||||
|
}
|
||||||
|
|
||||||
|
static 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)
|
||||||
|
{
|
||||||
|
vkd3d_mutex_init(&e->mutex);
|
||||||
|
vkd3d_cond_init(&e->cond);
|
||||||
|
e->signalled = false;
|
||||||
|
}
|
||||||
|
|
||||||
|
static HRESULT vkd3d_signal_null_event(HANDLE h)
|
||||||
|
{
|
||||||
|
vkd3d_null_event_signal(h);
|
||||||
|
|
||||||
|
return S_OK;
|
||||||
|
}
|
||||||
|
|
||||||
HRESULT vkd3d_queue_create(struct d3d12_device *device,
|
HRESULT vkd3d_queue_create(struct d3d12_device *device,
|
||||||
uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
|
uint32_t family_index, const VkQueueFamilyProperties *properties, struct vkd3d_queue **queue)
|
||||||
{
|
{
|
||||||
@@ -753,8 +797,6 @@ static HRESULT d3d12_fence_add_vk_semaphore(struct d3d12_fence *fence, VkSemapho
|
|||||||
|
|
||||||
static void d3d12_fence_signal_external_events_locked(struct d3d12_fence *fence)
|
static void d3d12_fence_signal_external_events_locked(struct d3d12_fence *fence)
|
||||||
{
|
{
|
||||||
struct d3d12_device *device = fence->device;
|
|
||||||
bool signal_null_event_cond = false;
|
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
|
|
||||||
for (i = 0, j = 0; i < fence->event_count; ++i)
|
for (i = 0, j = 0; i < fence->event_count; ++i)
|
||||||
@@ -763,28 +805,16 @@ static void d3d12_fence_signal_external_events_locked(struct d3d12_fence *fence)
|
|||||||
|
|
||||||
if (current->value <= fence->value)
|
if (current->value <= fence->value)
|
||||||
{
|
{
|
||||||
if (current->event)
|
current->signal(current->event);
|
||||||
{
|
continue;
|
||||||
device->signal_event(current->event);
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
*current->latch = true;
|
|
||||||
signal_null_event_cond = true;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
if (i != j)
|
|
||||||
fence->events[j] = *current;
|
|
||||||
++j;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (i != j)
|
||||||
|
fence->events[j] = *current;
|
||||||
|
++j;
|
||||||
}
|
}
|
||||||
|
|
||||||
fence->event_count = j;
|
fence->event_count = j;
|
||||||
|
|
||||||
if (signal_null_event_cond)
|
|
||||||
vkd3d_cond_broadcast(&fence->null_event_cond);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence, bool on_cpu)
|
static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkFence vk_fence, bool on_cpu)
|
||||||
@@ -978,7 +1008,6 @@ static void d3d12_fence_decref(struct d3d12_fence *fence)
|
|||||||
vkd3d_free(fence->events);
|
vkd3d_free(fence->events);
|
||||||
vkd3d_free(fence->semaphores);
|
vkd3d_free(fence->semaphores);
|
||||||
vkd3d_mutex_destroy(&fence->mutex);
|
vkd3d_mutex_destroy(&fence->mutex);
|
||||||
vkd3d_cond_destroy(&fence->null_event_cond);
|
|
||||||
vkd3d_free(fence);
|
vkd3d_free(fence);
|
||||||
|
|
||||||
d3d12_device_release(device);
|
d3d12_device_release(device);
|
||||||
@@ -1051,8 +1080,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence1 *
|
|||||||
UINT64 value, HANDLE event)
|
UINT64 value, HANDLE event)
|
||||||
{
|
{
|
||||||
struct d3d12_fence *fence = impl_from_ID3D12Fence1(iface);
|
struct d3d12_fence *fence = impl_from_ID3D12Fence1(iface);
|
||||||
|
struct vkd3d_null_event null_event;
|
||||||
|
PFN_vkd3d_signal_event signal;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
bool latch = false;
|
|
||||||
|
|
||||||
TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
|
TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
|
||||||
|
|
||||||
@@ -1078,6 +1108,14 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence1 *
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
signal = fence->device->signal_event;
|
||||||
|
if (!event)
|
||||||
|
{
|
||||||
|
vkd3d_null_event_init(&null_event);
|
||||||
|
event = &null_event;
|
||||||
|
signal = vkd3d_signal_null_event;
|
||||||
|
}
|
||||||
|
|
||||||
if (!vkd3d_array_reserve((void **)&fence->events, &fence->events_size,
|
if (!vkd3d_array_reserve((void **)&fence->events, &fence->events_size,
|
||||||
fence->event_count + 1, sizeof(*fence->events)))
|
fence->event_count + 1, sizeof(*fence->events)))
|
||||||
{
|
{
|
||||||
@@ -1086,22 +1124,19 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence1 *
|
|||||||
return E_OUTOFMEMORY;
|
return E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
fence->events[fence->event_count].value = value;
|
|
||||||
fence->events[fence->event_count].event = event;
|
fence->events[fence->event_count].event = event;
|
||||||
fence->events[fence->event_count].latch = &latch;
|
fence->events[fence->event_count].signal = signal;
|
||||||
|
fence->events[fence->event_count].value = value;
|
||||||
++fence->event_count;
|
++fence->event_count;
|
||||||
|
|
||||||
/* If event is NULL, we need to block until the fence value completes.
|
vkd3d_mutex_unlock(&fence->mutex);
|
||||||
* 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
|
if (event == &null_event)
|
||||||
* and signal a condition variable instead of calling external signal_event callback. */
|
|
||||||
if (!event)
|
|
||||||
{
|
{
|
||||||
while (!latch)
|
vkd3d_null_event_wait(&null_event);
|
||||||
vkd3d_cond_wait(&fence->null_event_cond, &fence->mutex);
|
vkd3d_null_event_cleanup(&null_event);
|
||||||
}
|
}
|
||||||
|
|
||||||
vkd3d_mutex_unlock(&fence->mutex);
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -1185,8 +1220,6 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
|
|||||||
|
|
||||||
vkd3d_mutex_init(&fence->mutex);
|
vkd3d_mutex_init(&fence->mutex);
|
||||||
|
|
||||||
vkd3d_cond_init(&fence->null_event_cond);
|
|
||||||
|
|
||||||
if ((fence->flags = flags))
|
if ((fence->flags = flags))
|
||||||
FIXME("Ignoring flags %#x.\n", flags);
|
FIXME("Ignoring flags %#x.\n", flags);
|
||||||
|
|
||||||
@@ -1201,8 +1234,8 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
|
|||||||
&fence->timeline_semaphore)) < 0)
|
&fence->timeline_semaphore)) < 0)
|
||||||
{
|
{
|
||||||
WARN("Failed to create timeline semaphore, vr %d.\n", vr);
|
WARN("Failed to create timeline semaphore, vr %d.\n", vr);
|
||||||
hr = hresult_from_vk_result(vr);
|
vkd3d_mutex_destroy(&fence->mutex);
|
||||||
goto fail_destroy_null_cond;
|
return hresult_from_vk_result(vr);
|
||||||
}
|
}
|
||||||
|
|
||||||
fence->semaphores = NULL;
|
fence->semaphores = NULL;
|
||||||
@@ -1213,20 +1246,14 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
|
|||||||
|
|
||||||
if (FAILED(hr = vkd3d_private_store_init(&fence->private_store)))
|
if (FAILED(hr = vkd3d_private_store_init(&fence->private_store)))
|
||||||
{
|
{
|
||||||
goto fail_destroy_timeline_semaphore;
|
VK_CALL(vkDestroySemaphore(device->vk_device, fence->timeline_semaphore, NULL));
|
||||||
|
vkd3d_mutex_destroy(&fence->mutex);
|
||||||
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
d3d12_device_add_ref(fence->device = device);
|
d3d12_device_add_ref(fence->device = device);
|
||||||
|
|
||||||
return S_OK;
|
return S_OK;
|
||||||
|
|
||||||
fail_destroy_timeline_semaphore:
|
|
||||||
VK_CALL(vkDestroySemaphore(device->vk_device, fence->timeline_semaphore, NULL));
|
|
||||||
fail_destroy_null_cond:
|
|
||||||
vkd3d_cond_destroy(&fence->null_event_cond);
|
|
||||||
vkd3d_mutex_destroy(&fence->mutex);
|
|
||||||
|
|
||||||
return hr;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
HRESULT d3d12_fence_create(struct d3d12_device *device,
|
HRESULT d3d12_fence_create(struct d3d12_device *device,
|
||||||
|
@@ -385,13 +385,12 @@ struct d3d12_fence
|
|||||||
uint64_t value;
|
uint64_t value;
|
||||||
uint64_t max_pending_value;
|
uint64_t max_pending_value;
|
||||||
struct vkd3d_mutex mutex;
|
struct vkd3d_mutex mutex;
|
||||||
struct vkd3d_cond null_event_cond;
|
|
||||||
|
|
||||||
struct vkd3d_waiting_event
|
struct vkd3d_waiting_event
|
||||||
{
|
{
|
||||||
uint64_t value;
|
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
bool *latch;
|
PFN_vkd3d_signal_event signal;
|
||||||
|
uint64_t value;
|
||||||
} *events;
|
} *events;
|
||||||
size_t events_size;
|
size_t events_size;
|
||||||
size_t event_count;
|
size_t event_count;
|
||||||
|
Reference in New Issue
Block a user