-- v2: demos: Use a fence to synchronize D3D12 and Vulkan work.
From: Giovanni Mascellani gmascellani@codeweavers.com
--- include/vkd3d.h | 35 +++++++++++++++++++++++++++++++++++ 1 file changed, 35 insertions(+)
diff --git a/include/vkd3d.h b/include/vkd3d.h index f36d9043..3adce97b 100644 --- a/include/vkd3d.h +++ b/include/vkd3d.h @@ -207,7 +207,42 @@ VKD3D_API VkPhysicalDevice vkd3d_get_vk_physical_device(ID3D12Device *device); VKD3D_API struct vkd3d_instance *vkd3d_instance_from_device(ID3D12Device *device);
VKD3D_API uint32_t vkd3d_get_vk_queue_family_index(ID3D12CommandQueue *queue); + +/** + * Acquire the Vulkan queue backing a command queue. + * + * While a queue is acquired by the client, it is locked so that + * neither the vkd3d library nor other threads can submit work to + * it. For that reason it should be released as soon as possible with + * vkd3d_release_vk_queue(). The lock is not reentrant, so the same + * queue must not be acquired more than once by the same thread. + * + * Work submitted through the Direct3D 12 API exposed by vkd3d is not + * always immediately submitted to the Vulkan queue; sometimes it is + * kept in another internal queue, which might not necessarily be + * empty at the time vkd3d_acquire_vk_queue() is called. For this + * reason, work submitted directly to the Vulkan queue might appear to + * the Vulkan driver as being submitted before other work submitted + * though the Direct3D 12 API. If this is not desired, it is + * recommended to synchronize work submission using an ID3D12Fence + * object, by submitting to the queue a signal operation after all the + * Direct3D 12 work is submitted and waiting for it before calling + * vkd3d_acquire_vk_queue(). + * + * \since 1.0 + */ VKD3D_API VkQueue vkd3d_acquire_vk_queue(ID3D12CommandQueue *queue); + +/** + * Release the Vulkan queue backing a command queue. + * + * This must be paired to an earlier corresponding + * vkd3d_acquire_vk_queue(). After this function is called, the Vulkan + * queue returned by vkd3d_acquire_vk_queue() must not be used any + * more. + * + * \since 1.0 + */ VKD3D_API void vkd3d_release_vk_queue(ID3D12CommandQueue *queue);
VKD3D_API HRESULT vkd3d_create_image_resource(ID3D12Device *device,
From: Giovanni Mascellani gmascellani@codeweavers.com
--- demos/demo_xcb.h | 21 +++++++++++++++++++++ 1 file changed, 21 insertions(+)
diff --git a/demos/demo_xcb.h b/demos/demo_xcb.h index 5ebe0ff9..f71e89f6 100644 --- a/demos/demo_xcb.h +++ b/demos/demo_xcb.h @@ -113,6 +113,9 @@ struct demo_swapchain VkDevice vk_device; ID3D12CommandQueue *command_queue;
+ ID3D12Fence *present_fence; + unsigned long long present_count; + uint32_t current_buffer; unsigned int buffer_count; ID3D12Resource *buffers[1]; @@ -529,6 +532,17 @@ static inline struct demo_swapchain *demo_swapchain_create(ID3D12CommandQueue *c } swapchain->buffer_count = image_count; free(vk_images); + + if (FAILED(ID3D12Device_CreateFence(d3d12_device, 0, 0, &IID_ID3D12Fence, (void **)&swapchain->present_fence))) + { + for (i = 0; i < image_count; ++i) + { + ID3D12Resource_Release(swapchain->buffers[i]); + } + free(swapchain); + goto fail; + } + swapchain->present_count = 0; ID3D12Device_Release(d3d12_device);
ID3D12CommandQueue_AddRef(swapchain->command_queue = command_queue); @@ -574,6 +588,12 @@ static inline void demo_swapchain_present(struct demo_swapchain *swapchain) present_desc.pImageIndices = &swapchain->current_buffer; present_desc.pResults = NULL;
+ /* Synchronize vkd3d_acquire_vk_queue() with the Direct3D 12 work + * already submitted to the command queue. */ + ++swapchain->present_count; + ID3D12CommandQueue_Signal(swapchain->command_queue, swapchain->present_fence, swapchain->present_count); + ID3D12Fence_SetEventOnCompletion(swapchain->present_fence, swapchain->present_count, NULL); + vk_queue = vkd3d_acquire_vk_queue(swapchain->command_queue); vkQueuePresentKHR(vk_queue, &present_desc); vkd3d_release_vk_queue(swapchain->command_queue); @@ -589,6 +609,7 @@ static inline void demo_swapchain_destroy(struct demo_swapchain *swapchain) unsigned int i;
ID3D12CommandQueue_Release(swapchain->command_queue); + ID3D12Fence_Release(swapchain->present_fence); for (i = 0; i < swapchain->buffer_count; ++i) { ID3D12Resource_Release(swapchain->buffers[i]);
On Thu Jul 6 10:57:23 2023 +0000, Giovanni Mascellani wrote:
changed this line in [version 2 of the diff](/wine/vkd3d/-/merge_requests/266/diffs?diff_id=55978&start_sha=ed464b53da5540f2f590f30e8aa8a240810833d4#65edd45d15be6402237adbf648766315067fa6be_536_536)
Should be fixed now, together with a bug with the swapchain creation failure path.
This merge request was approved by Henri Verbeet.