mirror of
https://gitlab.winehq.org/wine/vkd3d.git
synced 2025-09-12 18:50:22 -07:00
vkd3d: Handle multiple fence ANY waits in d3d12_device_SetEventOnMultipleFenceCompletion().
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
@@ -4922,12 +4922,34 @@ static HRESULT waiting_event_semaphore_signal(HANDLE h)
|
|||||||
return S_OK;
|
return S_OK;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
static HRESULT waiting_event_semaphore_signal_first(HANDLE h)
|
||||||
|
{
|
||||||
|
struct waiting_event_semaphore *s = h;
|
||||||
|
HANDLE event;
|
||||||
|
|
||||||
|
if ((event = vkd3d_atomic_exchange_ptr(&s->event, NULL)))
|
||||||
|
s->signal(event);
|
||||||
|
|
||||||
|
return waiting_event_semaphore_signal(h);
|
||||||
|
}
|
||||||
|
|
||||||
|
static bool waiting_event_semaphore_cancel(struct waiting_event_semaphore *s)
|
||||||
|
{
|
||||||
|
bool ret;
|
||||||
|
|
||||||
|
ret = !vkd3d_atomic_exchange_ptr(&s->event, NULL);
|
||||||
|
waiting_event_semaphore_signal(s);
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device9 *iface,
|
static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(ID3D12Device9 *iface,
|
||||||
ID3D12Fence *const *fences, const UINT64 *values, UINT fence_count,
|
ID3D12Fence *const *fences, const UINT64 *values, UINT fence_count,
|
||||||
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 waiting_event_semaphore *s;
|
struct waiting_event_semaphore *s;
|
||||||
|
PFN_vkd3d_signal_event signal;
|
||||||
struct d3d12_fence *fence;
|
struct d3d12_fence *fence;
|
||||||
HRESULT hr = S_OK;
|
HRESULT hr = S_OK;
|
||||||
unsigned int i;
|
unsigned int i;
|
||||||
@@ -4947,12 +4969,6 @@ 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 (flags)
|
|
||||||
{
|
|
||||||
FIXME("Unhandled flags %#x.\n", flags);
|
|
||||||
return E_NOTIMPL;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (!event)
|
if (!event)
|
||||||
{
|
{
|
||||||
FIXME("Unhandled NULL event.\n");
|
FIXME("Unhandled NULL event.\n");
|
||||||
@@ -4969,6 +4985,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
|
|||||||
s->signal = device->signal_event;
|
s->signal = device->signal_event;
|
||||||
s->value = fence_count;
|
s->value = fence_count;
|
||||||
|
|
||||||
|
if (flags & D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY)
|
||||||
|
signal = waiting_event_semaphore_signal_first;
|
||||||
|
else
|
||||||
|
signal = waiting_event_semaphore_signal;
|
||||||
|
|
||||||
for (i = 0; i < fence_count; ++i)
|
for (i = 0; i < fence_count; ++i)
|
||||||
{
|
{
|
||||||
fence = unsafe_impl_from_ID3D12Fence(fences[i]);
|
fence = unsafe_impl_from_ID3D12Fence(fences[i]);
|
||||||
@@ -4978,15 +4999,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_SetEventOnMultipleFenceCompletion(
|
|||||||
if (values[i] <= fence->value)
|
if (values[i] <= fence->value)
|
||||||
{
|
{
|
||||||
vkd3d_mutex_unlock(&fence->mutex);
|
vkd3d_mutex_unlock(&fence->mutex);
|
||||||
waiting_event_semaphore_signal(s);
|
signal(s);
|
||||||
continue;
|
continue;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!d3d12_fence_add_waiting_event(fence, s, waiting_event_semaphore_signal, values[i]))
|
if (!d3d12_fence_add_waiting_event(fence, s, signal, values[i]))
|
||||||
{
|
{
|
||||||
WARN("Failed to add event.\n");
|
WARN("Failed to add event.\n");
|
||||||
s->event = NULL;
|
/* If the event was already signalled, we don't need to fail here.
|
||||||
waiting_event_semaphore_signal(s);
|
* Note that cancel() will also return "true" for any subsequent
|
||||||
|
* cancel() calls; that's fine, because we already failed in that
|
||||||
|
* case. */
|
||||||
|
if (!waiting_event_semaphore_cancel(s))
|
||||||
hr = E_OUTOFMEMORY;
|
hr = E_OUTOFMEMORY;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@@ -39065,9 +39065,9 @@ static void test_multi_fence_event(void)
|
|||||||
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,
|
||||||
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
||||||
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);
|
||||||
todo ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret);
|
ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret);
|
||||||
|
|
||||||
/* No fences signalled yet. */
|
/* No fences signalled yet. */
|
||||||
fence_values[0] = 32;
|
fence_values[0] = 32;
|
||||||
@@ -39130,13 +39130,13 @@ static void test_multi_fence_event(void)
|
|||||||
fence_values[2] = 50;
|
fence_values[2] = 50;
|
||||||
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
|
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
|
||||||
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
||||||
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 = ID3D12Fence_Signal(fences[2], 50);
|
hr = ID3D12Fence_Signal(fences[2], 50);
|
||||||
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);
|
||||||
todo ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret);
|
ok(ret == WAIT_OBJECT_0, "Got ret %#x.\n", ret);
|
||||||
hr = ID3D12Fence_Signal(fences[0], 48);
|
hr = ID3D12Fence_Signal(fences[0], 48);
|
||||||
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);
|
||||||
@@ -39205,9 +39205,9 @@ static void test_multi_fence_event(void)
|
|||||||
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,
|
||||||
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY, event);
|
||||||
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);
|
||||||
todo 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);
|
||||||
|
Reference in New Issue
Block a user