mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2024-11-21 16:46:41 -08:00
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@codeweavers.com> Signed-off-by: Henri Verbeet <hverbeet@codeweavers.com> Signed-off-by: Alexandre Julliard <julliard@winehq.org>
This commit is contained in:
parent
de87352f77
commit
c965b7b213
@ -806,6 +806,7 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
|
|||||||
{
|
{
|
||||||
struct d3d12_device *device = fence->device;
|
struct d3d12_device *device = fence->device;
|
||||||
struct vkd3d_signaled_semaphore *current;
|
struct vkd3d_signaled_semaphore *current;
|
||||||
|
bool signal_null_event_cond = false;
|
||||||
unsigned int i, j;
|
unsigned int i, j;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
@ -822,10 +823,18 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
|
|||||||
struct vkd3d_waiting_event *current = &fence->events[i];
|
struct vkd3d_waiting_event *current = &fence->events[i];
|
||||||
|
|
||||||
if (current->value <= value)
|
if (current->value <= value)
|
||||||
|
{
|
||||||
|
if (current->event)
|
||||||
{
|
{
|
||||||
fence->device->signal_event(current->event);
|
fence->device->signal_event(current->event);
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
{
|
||||||
|
current->latch = true;
|
||||||
|
signal_null_event_cond = true;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
else
|
||||||
{
|
{
|
||||||
if (i != j)
|
if (i != j)
|
||||||
fence->events[j] = *current;
|
fence->events[j] = *current;
|
||||||
@ -834,6 +843,9 @@ static HRESULT d3d12_fence_signal(struct d3d12_fence *fence, uint64_t value, VkF
|
|||||||
}
|
}
|
||||||
fence->event_count = j;
|
fence->event_count = j;
|
||||||
|
|
||||||
|
if (signal_null_event_cond)
|
||||||
|
pthread_cond_broadcast(&fence->null_event_cond);
|
||||||
|
|
||||||
if (vk_fence)
|
if (vk_fence)
|
||||||
{
|
{
|
||||||
const struct vkd3d_vk_device_procs *vk_procs = &device->vk_procs;
|
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);
|
vkd3d_free(fence->events);
|
||||||
if ((rc = pthread_mutex_destroy(&fence->mutex)))
|
if ((rc = pthread_mutex_destroy(&fence->mutex)))
|
||||||
ERR("Failed to destroy mutex, error %d.\n", rc);
|
ERR("Failed to destroy mutex, error %d.\n", rc);
|
||||||
|
pthread_cond_destroy(&fence->null_event_cond);
|
||||||
vkd3d_free(fence);
|
vkd3d_free(fence);
|
||||||
|
|
||||||
d3d12_device_release(device);
|
d3d12_device_release(device);
|
||||||
@ -997,6 +1010,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
|
|||||||
{
|
{
|
||||||
struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
|
struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
|
bool *latch;
|
||||||
int rc;
|
int rc;
|
||||||
|
|
||||||
TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
|
TRACE("iface %p, value %#"PRIx64", event %p.\n", iface, value, event);
|
||||||
@ -1009,6 +1023,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
|
|||||||
|
|
||||||
if (value <= fence->value)
|
if (value <= fence->value)
|
||||||
{
|
{
|
||||||
|
if (event)
|
||||||
fence->device->signal_event(event);
|
fence->device->signal_event(event);
|
||||||
pthread_mutex_unlock(&fence->mutex);
|
pthread_mutex_unlock(&fence->mutex);
|
||||||
return S_OK;
|
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].value = value;
|
||||||
fence->events[fence->event_count].event = event;
|
fence->events[fence->event_count].event = event;
|
||||||
|
fence->events[fence->event_count].latch = false;
|
||||||
|
latch = &fence->events[fence->event_count].latch;
|
||||||
++fence->event_count;
|
++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);
|
pthread_mutex_unlock(&fence->mutex);
|
||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
@ -1095,6 +1122,13 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
|
|||||||
return hresult_from_errno(rc);
|
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)
|
if (flags)
|
||||||
FIXME("Ignoring flags %#x.\n", 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)))
|
if (FAILED(hr = vkd3d_private_store_init(&fence->private_store)))
|
||||||
{
|
{
|
||||||
pthread_mutex_destroy(&fence->mutex);
|
pthread_mutex_destroy(&fence->mutex);
|
||||||
|
pthread_cond_destroy(&fence->null_event_cond);
|
||||||
return hr;
|
return hr;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -367,11 +367,13 @@ struct d3d12_fence
|
|||||||
|
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
pthread_mutex_t mutex;
|
pthread_mutex_t mutex;
|
||||||
|
pthread_cond_t null_event_cond;
|
||||||
|
|
||||||
struct vkd3d_waiting_event
|
struct vkd3d_waiting_event
|
||||||
{
|
{
|
||||||
uint64_t value;
|
uint64_t value;
|
||||||
HANDLE event;
|
HANDLE event;
|
||||||
|
bool latch;
|
||||||
} *events;
|
} *events;
|
||||||
size_t events_size;
|
size_t events_size;
|
||||||
size_t event_count;
|
size_t event_count;
|
||||||
|
Loading…
Reference in New Issue
Block a user