[PATCH vkd3d 2/2] vkd3d: Support wait-before-signal for fences using timeline semaphores.

Rémi Bernon rbernon at codeweavers.com
Thu Dec 12 13:02:44 CST 2019


This fixes some fixme messages when playing The Turing Test.

Signed-off-by: Rémi Bernon <rbernon at codeweavers.com>
---
 libs/vkd3d/command.c       | 142 ++++++++++++++++++++++++++++++++-----
 libs/vkd3d/vkd3d_private.h |   1 +
 2 files changed, 125 insertions(+), 18 deletions(-)

diff --git a/libs/vkd3d/command.c b/libs/vkd3d/command.c
index 8a7ff668..48b5d4f2 100644
--- a/libs/vkd3d/command.c
+++ b/libs/vkd3d/command.c
@@ -623,6 +623,34 @@ create_fence:
     return vr;
 }
 
+static VkResult d3d12_fence_create_vk_timeline_semaphore(struct d3d12_fence *fence, VkSemaphore *vk_semaphore,
+        uint64_t initial_value)
+{
+    struct d3d12_device *device = fence->device;
+    const struct vkd3d_vk_device_procs *vk_procs;
+    VkSemaphoreCreateInfo semaphore_info;
+    VkSemaphoreTypeCreateInfoKHR semaphore_type_info;
+    VkResult vr;
+
+    vk_procs = &device->vk_procs;
+
+    semaphore_type_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO_KHR;
+    semaphore_type_info.pNext = NULL;
+    semaphore_type_info.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE_KHR;
+    semaphore_type_info.initialValue = initial_value;
+
+    semaphore_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO;
+    semaphore_info.pNext = &semaphore_type_info;
+    semaphore_info.flags = 0;
+    if ((vr = VK_CALL(vkCreateSemaphore(device->vk_device, &semaphore_info, NULL, vk_semaphore))) < 0)
+    {
+        WARN("Failed to create Vulkan semaphore, vr %d.\n", vr);
+        *vk_semaphore = VK_NULL_HANDLE;
+    }
+
+    return vr;
+}
+
 static void d3d12_fence_garbage_collect_vk_semaphores_locked(struct d3d12_fence *fence,
         bool destroy_all)
 {
@@ -682,6 +710,9 @@ static void d3d12_fence_destroy_vk_objects(struct d3d12_fence *fence)
         fence->old_vk_fences[i] = VK_NULL_HANDLE;
     }
 
+    if (fence->vk_timeline_semaphore)
+        VK_CALL(vkDestroySemaphore(device->vk_device, fence->vk_timeline_semaphore, NULL));
+
     d3d12_fence_garbage_collect_vk_semaphores_locked(fence, true);
 
     pthread_mutex_unlock(&fence->mutex);
@@ -1044,9 +1075,26 @@ static HRESULT STDMETHODCALLTYPE d3d12_fence_SetEventOnCompletion(ID3D12Fence *i
 static HRESULT STDMETHODCALLTYPE d3d12_fence_Signal(ID3D12Fence *iface, UINT64 value)
 {
     struct d3d12_fence *fence = impl_from_ID3D12Fence(iface);
+    const struct vkd3d_vk_device_procs *vk_procs = &fence->device->vk_procs;
+    VkSemaphoreSignalInfoKHR signal_info;
+    VkResult vr;
 
     TRACE("iface %p, value %#"PRIx64".\n", iface, value);
 
+    if (fence->vk_timeline_semaphore)
+    {
+        signal_info.sType = VK_STRUCTURE_TYPE_SEMAPHORE_SIGNAL_INFO_KHR;
+        signal_info.pNext = NULL;
+        signal_info.semaphore = fence->vk_timeline_semaphore;
+        signal_info.value = value;
+
+        if ((vr = VK_CALL(vkSignalSemaphoreKHR(fence->device->vk_device, &signal_info))) < 0)
+        {
+            ERR("Failed to signal semaphore, vr %d.\n", vr);
+            return hresult_from_vk_result(vr);
+        }
+    }
+
     return d3d12_fence_signal(fence, value, VK_NULL_HANDLE);
 }
 
@@ -1081,6 +1129,7 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
         UINT64 initial_value, D3D12_FENCE_FLAGS flags)
 {
     HRESULT hr;
+    VkResult vr;
     int rc;
 
     fence->ID3D12Fence_iface.lpVtbl = &d3d12_fence_vtbl;
@@ -1116,6 +1165,16 @@ static HRESULT d3d12_fence_init(struct d3d12_fence *fence, struct d3d12_device *
 
     d3d12_device_add_ref(fence->device = device);
 
+    if (!device->vk_info.KHR_timeline_semaphore)
+    {
+        fence->vk_timeline_semaphore = VK_NULL_HANDLE;
+    }
+    else if ((vr = d3d12_fence_create_vk_timeline_semaphore(fence, &fence->vk_timeline_semaphore, initial_value)) < 0)
+    {
+        ERR("Failed to create Vulkan timeline semaphore, vr %d.\n", vr);
+        return hresult_from_vk_result(vr);
+    }
+
     return S_OK;
 }
 
@@ -5904,6 +5963,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue *
     struct d3d12_device *device;
     struct d3d12_fence *fence;
     VkSubmitInfo submit_info;
+    VkTimelineSemaphoreSubmitInfoKHR timeline_info;
     uint64_t sequence_number;
     VkQueue vk_queue;
     VkResult vr;
@@ -5930,7 +5990,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue *
         goto fail;
     }
 
-    if ((vr = vkd3d_queue_create_vk_semaphore_locked(vkd3d_queue, device, &vk_semaphore)) < 0)
+    if (fence->vk_timeline_semaphore)
+    {
+        vk_semaphore = fence->vk_timeline_semaphore;
+    }
+    else if ((vr = vkd3d_queue_create_vk_semaphore_locked(vkd3d_queue, device, &vk_semaphore)) < 0)
     {
         ERR("Failed to create Vulkan semaphore, vr %d.\n", vr);
         vk_semaphore = VK_NULL_HANDLE;
@@ -5946,6 +6010,18 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue *
     submit_info.signalSemaphoreCount = vk_semaphore ? 1 : 0;
     submit_info.pSignalSemaphores = &vk_semaphore;
 
+    if (vk_semaphore == fence->vk_timeline_semaphore)
+    {
+        timeline_info.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR;
+        timeline_info.pNext = NULL;
+        timeline_info.waitSemaphoreValueCount = 0;
+        timeline_info.pWaitSemaphoreValues = NULL;
+        timeline_info.signalSemaphoreValueCount = 1;
+        timeline_info.pSignalSemaphoreValues = &value;
+
+        submit_info.pNext = &timeline_info;
+    }
+
     if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, vk_fence))) >= 0)
     {
         sequence_number = ++vkd3d_queue->submitted_sequence_number;
@@ -5963,7 +6039,9 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Signal(ID3D12CommandQueue *
         goto fail_vkresult;
     }
 
-    if (vk_semaphore && SUCCEEDED(hr = d3d12_fence_add_vk_semaphore(fence, vk_semaphore, vk_fence, value)))
+    if (vk_semaphore == fence->vk_timeline_semaphore)
+        vk_semaphore = VK_NULL_HANDLE;
+    else if (vk_semaphore && SUCCEEDED(hr = d3d12_fence_add_vk_semaphore(fence, vk_semaphore, vk_fence, value)))
         vk_semaphore = VK_NULL_HANDLE;
 
     vr = VK_CALL(vkGetFenceStatus(device->vk_device, vk_fence));
@@ -6013,6 +6091,8 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
     struct vkd3d_queue *queue;
     struct d3d12_fence *fence;
     VkSubmitInfo submit_info;
+    VkTimelineSemaphoreSubmitInfoKHR timeline_info;
+    VkSemaphore vk_semaphore;
     VkQueue vk_queue;
     VkResult vr;
     HRESULT hr;
@@ -6024,23 +6104,30 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
 
     fence = unsafe_impl_from_ID3D12Fence(fence_iface);
 
-    semaphore = d3d12_fence_acquire_vk_semaphore(fence, value, &completed_value);
-    if (!semaphore && completed_value >= value)
+    if ((vk_semaphore = fence->vk_timeline_semaphore))
     {
-        /* We don't get a Vulkan semaphore if the fence was signaled on CPU. */
-        TRACE("Already signaled %p, value %#"PRIx64".\n", fence, completed_value);
-        return S_OK;
+        semaphore = NULL;
     }
-
-    if (!(vk_queue = vkd3d_queue_acquire(queue)))
+    else if ((semaphore = d3d12_fence_acquire_vk_semaphore(fence, value, &completed_value)))
     {
-        ERR("Failed to acquire queue %p.\n", queue);
-        hr = E_FAIL;
-        goto fail;
+        vk_semaphore = semaphore->vk_semaphore;
     }
-
-    if (!semaphore)
+    else
     {
+        if (completed_value >= value)
+        {
+            /* We don't get a Vulkan semaphore if the fence was signaled on CPU. */
+            TRACE("Already signaled %p, value %#"PRIx64".\n", fence, completed_value);
+            return S_OK;
+        }
+
+        if (!(vk_queue = vkd3d_queue_acquire(queue)))
+        {
+            ERR("Failed to acquire queue %p.\n", queue);
+            hr = E_FAIL;
+            goto fail;
+        }
+
         if (command_queue->last_waited_fence == fence && command_queue->last_waited_fence_value >= value)
         {
             WARN("Already waited on fence %p, value %#"PRIx64".\n", fence, value);
@@ -6055,16 +6142,35 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
         return S_OK;
     }
 
+    if (!(vk_queue = vkd3d_queue_acquire(queue)))
+    {
+        ERR("Failed to acquire queue %p.\n", queue);
+        hr = E_FAIL;
+        goto fail;
+    }
+
     submit_info.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
     submit_info.pNext = NULL;
     submit_info.waitSemaphoreCount = 1;
-    submit_info.pWaitSemaphores = &semaphore->vk_semaphore;
+    submit_info.pWaitSemaphores = &vk_semaphore;
     submit_info.pWaitDstStageMask = &wait_stage_mask;
     submit_info.commandBufferCount = 0;
     submit_info.pCommandBuffers = NULL;
     submit_info.signalSemaphoreCount = 0;
     submit_info.pSignalSemaphores = NULL;
 
+    if (vk_semaphore == fence->vk_timeline_semaphore)
+    {
+        timeline_info.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO_KHR;
+        timeline_info.pNext = NULL;
+        timeline_info.waitSemaphoreValueCount = 1;
+        timeline_info.pWaitSemaphoreValues = &value;
+        timeline_info.signalSemaphoreValueCount = 0;
+        timeline_info.pSignalSemaphoreValues = NULL;
+
+        submit_info.pNext = &timeline_info;
+    }
+
     if (!vkd3d_array_reserve((void **)&queue->semaphores, &queue->semaphores_size,
             queue->semaphore_count + 1, sizeof(*queue->semaphores)))
     {
@@ -6074,7 +6180,7 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
         goto fail;
     }
 
-    if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, VK_NULL_HANDLE))) >= 0)
+    if ((vr = VK_CALL(vkQueueSubmit(vk_queue, 1, &submit_info, VK_NULL_HANDLE))) >= 0 && semaphore)
     {
         queue->semaphores[queue->semaphore_count].vk_semaphore = semaphore->vk_semaphore;
         queue->semaphores[queue->semaphore_count].sequence_number = queue->submitted_sequence_number + 1;
@@ -6093,11 +6199,11 @@ static HRESULT STDMETHODCALLTYPE d3d12_command_queue_Wait(ID3D12CommandQueue *if
         goto fail;
     }
 
-    d3d12_fence_remove_vk_semaphore(fence, semaphore);
+    if (semaphore) d3d12_fence_remove_vk_semaphore(fence, semaphore);
     return S_OK;
 
 fail:
-    d3d12_fence_release_vk_semaphore(fence, semaphore);
+    if (semaphore) d3d12_fence_release_vk_semaphore(fence, semaphore);
     return hr;
 }
 
diff --git a/libs/vkd3d/vkd3d_private.h b/libs/vkd3d/vkd3d_private.h
index 84abcb8d..d9290db7 100644
--- a/libs/vkd3d/vkd3d_private.h
+++ b/libs/vkd3d/vkd3d_private.h
@@ -357,6 +357,7 @@ struct d3d12_fence
     LONG pending_worker_operation_count;
 
     VkFence old_vk_fences[VKD3D_MAX_VK_SYNC_OBJECTS];
+    VkSemaphore vk_timeline_semaphore;
 
     struct d3d12_device *device;
 
-- 
2.24.0




More information about the wine-devel mailing list