[PATCH vkd3d 3/4] vkd3d: Emit a noop wait between command queue executions to implement the D3D12 command order guarantee.

Conor McCarthy cmccarthy at codeweavers.com
Thu May 12 10:11:07 CDT 2022


D3D12 guarantees no overlap between commands sent in separate calls to
ExecuteCommandLists(). A Vulkan noop wait provides a barrier against
reordering.

Signed-off-by: Conor McCarthy <cmccarthy at codeweavers.com>
---
 libs/vkd3d/command.c       | 18 ++++++++++++++++++
 libs/vkd3d/device.c        | 13 +++++++++++++
 libs/vkd3d/vkd3d_private.h |  2 ++
 3 files changed, 33 insertions(+)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index d0782e5a..a44eb02f 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -6285,9 +6285,13 @@ static void STDMETHODCALLTYPE d3d12_command_queue_CopyTileMappings(ID3D12Command
 static void d3d12_command_queue_execute(struct d3d12_command_queue *command_queue,
         VkCommandBuffer *buffers, unsigned int count)
 {
+    static const VkPipelineStageFlagBits wait_stage_mask = VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
     const struct vkd3d_vk_device_procs *vk_procs = &command_queue->device->vk_procs;
     struct vkd3d_queue *vkd3d_queue = command_queue->vkd3d_queue;
+    VkTimelineSemaphoreSubmitInfoKHR timeline_submit_info;
+    struct d3d12_device *device = command_queue->device;
     VkSubmitInfo submit_desc;
+    uint64_t noop_value = 0;
     VkQueue vk_queue;
     VkResult vr;
 
@@ -6300,6 +6304,20 @@ static void d3d12_command_queue_execute(struct d3d12_command_queue *command_queu
     }
 
     submit_desc.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
+    if (device->vk_info.KHR_timeline_semaphore)
+    {
+        /* Insert a noop wait to provide the barrier between executions which D3D12 guarantees.
+         * The limitations of binary semaphores would make this complex to do with them. */
+        submit_desc.pNext = &timeline_submit_info;
+        submit_desc.pWaitSemaphores = &device->noop_semaphore;
+        submit_desc.waitSemaphoreCount = 1;
+        submit_desc.pWaitDstStageMask = &wait_stage_mask;
+
+        memset(&timeline_submit_info, 0, sizeof(timeline_submit_info));
+        timeline_submit_info.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR;
+        timeline_submit_info.waitSemaphoreValueCount = 1;
+        timeline_submit_info.pWaitSemaphoreValues = &noop_value;
+    }
     submit_desc.commandBufferCount = count;
     submit_desc.pCommandBuffers = buffers;
 
diff --git a/libs/vkd3d/device.c b/libs/vkd3d/device.c
index eaedc444..bdc80ba3 100644
--- a/libs/vkd3d/device.c
+++ b/libs/vkd3d/device.c
@@ -2626,6 +2626,7 @@ static ULONG STDMETHODCALLTYPE d3d12_device_Release(ID3D12Device *iface)
         vkd3d_private_store_destroy(&device->private_store);
 
         vkd3d_cleanup_format_info(device);
+        VK_CALL(vkDestroySemaphore(device->vk_device, device->noop_semaphore, NULL));
         vkd3d_vk_descriptor_heap_layouts_cleanup(device);
         vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device);
         vkd3d_destroy_null_resources(&device->null_resources, device);
@@ -4241,6 +4242,7 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
         struct vkd3d_instance *instance, const struct vkd3d_device_create_info *create_info)
 {
     const struct vkd3d_vk_device_procs *vk_procs;
+    VkResult vr;
     HRESULT hr;
     size_t i;
 
@@ -4278,6 +4280,15 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
     if (FAILED(hr = vkd3d_vk_descriptor_heap_layouts_init(device)))
         goto out_cleanup_uav_clear_state;
 
+    device->noop_semaphore = VK_NULL_HANDLE;
+    if (device->vk_info.KHR_timeline_semaphore && (vr = vkd3d_create_timeline_semaphore(device, 0,
+            &device->noop_semaphore)) < 0)
+    {
+        WARN("Failed to create timeline semaphore, vr %d.\n", vr);
+        hr = hresult_from_vk_result(vr);
+        goto out_cleanup_descriptor_heap_layouts;
+    }
+
     vkd3d_render_pass_cache_init(&device->render_pass_cache);
     vkd3d_gpu_descriptor_allocator_init(&device->gpu_descriptor_allocator);
     vkd3d_gpu_va_allocator_init(&device->gpu_va_allocator);
@@ -4295,6 +4306,8 @@ static HRESULT d3d12_device_init(struct d3d12_device *device,
 
     return S_OK;
 
+out_cleanup_descriptor_heap_layouts:
+    vkd3d_vk_descriptor_heap_layouts_cleanup(device);
 out_cleanup_uav_clear_state:
     vkd3d_uav_clear_state_cleanup(&device->uav_clear_state, device);
 out_destroy_null_resources:
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index f00181a2..37bac159 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -1493,6 +1493,8 @@ struct d3d12_device
     struct d3d12_command_queue *blocked_queues[VKD3D_MAX_DEVICE_BLOCKED_QUEUES];
     unsigned int blocked_queue_count;
 
+    VkSemaphore noop_semaphore;
+
     struct vkd3d_instance *vkd3d_instance;
 
     IUnknown *parent;
-- 
2.35.1




More information about the wine-devel mailing list