vkd3d: Handle multiple fence ALL waits in d3d12_device_SetEventOnMultipleFenceCompletion().

This commit is contained in:
Henri Verbeet
2025-04-29 21:03:25 +02:00
parent 52b947a005
commit 9222f5e5b1
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 86 additions and 10 deletions

View File

@@ -1076,7 +1076,7 @@ static UINT64 STDMETHODCALLTYPE d3d12_fence_GetCompletedValue(ID3D12Fence1 *ifac
return completed_value; return completed_value;
} }
static bool d3d12_fence_add_waiting_event(struct d3d12_fence *fence, bool d3d12_fence_add_waiting_event(struct d3d12_fence *fence,
HANDLE event, PFN_vkd3d_signal_event signal, uint64_t value) HANDLE event, PFN_vkd3d_signal_event signal, uint64_t value)
{ {
struct vkd3d_waiting_event *e; struct vkd3d_waiting_event *e;
@@ -1205,7 +1205,7 @@ static const struct ID3D12Fence1Vtbl d3d12_fence_vtbl =
d3d12_fence_GetCreationFlags, d3d12_fence_GetCreationFlags,
}; };
static struct d3d12_fence *unsafe_impl_from_ID3D12Fence(ID3D12Fence *iface) struct d3d12_fence *unsafe_impl_from_ID3D12Fence(ID3D12Fence *iface)
{ {
ID3D12Fence1 *iface1; ID3D12Fence1 *iface1;

View File

@@ -4901,11 +4901,38 @@ static HRESULT STDMETHODCALLTYPE d3d12_device_CreatePipelineLibrary(ID3D12Device
return DXGI_ERROR_UNSUPPORTED; return DXGI_ERROR_UNSUPPORTED;
} }
struct waiting_event_semaphore
{
HANDLE event;
PFN_vkd3d_signal_event signal;
uint32_t value;
};
static HRESULT waiting_event_semaphore_signal(HANDLE h)
{
struct waiting_event_semaphore *s = h;
if (vkd3d_atomic_decrement_u32(&s->value))
return S_OK;
if (s->event)
s->signal(s->event);
vkd3d_free(s);
return S_OK;
}
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)
{ {
FIXME("iface %p, fences %p, values %p, fence_count %u, flags %#x, event %p partial stub!\n", struct d3d12_device *device = impl_from_ID3D12Device9(iface);
struct waiting_event_semaphore *s;
struct d3d12_fence *fence;
HRESULT hr = S_OK;
unsigned int i;
TRACE("iface %p, fences %p, values %p, fence_count %u, flags %#x, event %p.\n",
iface, fences, values, fence_count, flags, event); iface, fences, values, fence_count, flags, event);
if (flags & ~D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY) if (flags & ~D3D12_MULTIPLE_FENCE_WAIT_FLAG_ANY)
@@ -4920,7 +4947,53 @@ 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);
return E_NOTIMPL; if (flags)
{
FIXME("Unhandled flags %#x.\n", flags);
return E_NOTIMPL;
}
if (!event)
{
FIXME("Unhandled NULL event.\n");
return E_NOTIMPL;
}
if (!(s = vkd3d_malloc(sizeof(*s))))
{
WARN("Failed to allocate semaphore memory.\n");
return E_OUTOFMEMORY;
}
s->event = event;
s->signal = device->signal_event;
s->value = fence_count;
for (i = 0; i < fence_count; ++i)
{
fence = unsafe_impl_from_ID3D12Fence(fences[i]);
vkd3d_mutex_lock(&fence->mutex);
if (values[i] <= fence->value)
{
vkd3d_mutex_unlock(&fence->mutex);
waiting_event_semaphore_signal(s);
continue;
}
if (!d3d12_fence_add_waiting_event(fence, s, waiting_event_semaphore_signal, values[i]))
{
WARN("Failed to add event.\n");
s->event = NULL;
waiting_event_semaphore_signal(s);
hr = E_OUTOFMEMORY;
}
vkd3d_mutex_unlock(&fence->mutex);
}
return hr;
} }
static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device9 *iface, static HRESULT STDMETHODCALLTYPE d3d12_device_SetResidencyPriority(ID3D12Device9 *iface,

View File

@@ -410,8 +410,11 @@ struct d3d12_fence
struct vkd3d_private_store private_store; struct vkd3d_private_store private_store;
}; };
bool d3d12_fence_add_waiting_event(struct d3d12_fence *fence,
HANDLE event, PFN_vkd3d_signal_event signal, uint64_t value);
HRESULT d3d12_fence_create(struct d3d12_device *device, uint64_t initial_value, HRESULT d3d12_fence_create(struct d3d12_device *device, uint64_t initial_value,
D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence); D3D12_FENCE_FLAGS flags, struct d3d12_fence **fence);
struct d3d12_fence *unsafe_impl_from_ID3D12Fence(ID3D12Fence *iface);
VkResult vkd3d_create_timeline_semaphore(const struct d3d12_device *device, uint64_t initial_value, VkResult vkd3d_create_timeline_semaphore(const struct d3d12_device *device, uint64_t initial_value,
VkSemaphore *timeline_semaphore); VkSemaphore *timeline_semaphore);

View File

@@ -39055,9 +39055,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_ALL, event); fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, 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);
todo ok(hr == S_OK, "Got hr %#x.\n", hr); todo ok(hr == S_OK, "Got hr %#x.\n", hr);
@@ -39075,7 +39075,7 @@ static void test_multi_fence_event(void)
fence_values[2] = 34; fence_values[2] = 34;
hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences, hr = ID3D12Device1_SetEventOnMultipleFenceCompletion(device1, fences,
fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, event); fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, 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], 34); hr = ID3D12Fence_Signal(fences[2], 34);
@@ -39089,7 +39089,7 @@ static void test_multi_fence_event(void)
hr = ID3D12Fence_Signal(fences[1], 33); hr = ID3D12Fence_Signal(fences[1], 33);
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);
fence_values[0] = 40; fence_values[0] = 40;
fence_values[1] = 41; fence_values[1] = 41;
@@ -39175,13 +39175,13 @@ 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, event); fence_values, 3, D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL, 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[1], 65); hr = ID3D12Fence_Signal(fences[1], 65);
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);
fence_values[1] = 67; fence_values[1] = 67;
thread_data.flags = D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL; thread_data.flags = D3D12_MULTIPLE_FENCE_WAIT_FLAG_ALL;