radv: Implement fences based on syncobjs.
authorBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Mon, 27 Nov 2017 22:58:35 +0000 (23:58 +0100)
committerBas Nieuwenhuizen <bas@basnieuwenhuizen.nl>
Mon, 18 Dec 2017 08:31:12 +0000 (09:31 +0100)
Reviewed-by: Dave Airlie <airlied@redhat.com>
src/amd/vulkan/radv_device.c
src/amd/vulkan/radv_private.h
src/amd/vulkan/radv_wsi.c

index 7c0971d190d2de67416b3623dfb353ad7f23cf82..fc9fb59f9916db1fb95df902022c9411ede31cdf 100644 (file)
@@ -1850,12 +1850,14 @@ fail:
 static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts,
                                      int num_sems,
                                      const VkSemaphore *sems,
+                                     VkFence _fence,
                                      bool reset_temp)
 {
        int syncobj_idx = 0, sem_idx = 0;
 
-       if (num_sems == 0)
+       if (num_sems == 0 && _fence == VK_NULL_HANDLE)
                return VK_SUCCESS;
+
        for (uint32_t i = 0; i < num_sems; i++) {
                RADV_FROM_HANDLE(radv_semaphore, sem, sems[i]);
 
@@ -1865,6 +1867,12 @@ static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts,
                        counts->sem_count++;
        }
 
+       if (_fence != VK_NULL_HANDLE) {
+               RADV_FROM_HANDLE(radv_fence, fence, _fence);
+               if (fence->temp_syncobj || fence->syncobj)
+                       counts->syncobj_count++;
+       }
+
        if (counts->syncobj_count) {
                counts->syncobj = (uint32_t *)malloc(sizeof(uint32_t) * counts->syncobj_count);
                if (!counts->syncobj)
@@ -1893,6 +1901,14 @@ static VkResult radv_alloc_sem_counts(struct radv_winsys_sem_counts *counts,
                }
        }
 
+       if (_fence != VK_NULL_HANDLE) {
+               RADV_FROM_HANDLE(radv_fence, fence, _fence);
+               if (fence->temp_syncobj)
+                       counts->syncobj[syncobj_idx++] = fence->temp_syncobj;
+               else if (fence->syncobj)
+                       counts->syncobj[syncobj_idx++] = fence->syncobj;
+       }
+
        return VK_SUCCESS;
 }
 
@@ -1923,15 +1939,16 @@ VkResult radv_alloc_sem_info(struct radv_winsys_sem_info *sem_info,
                             int num_wait_sems,
                             const VkSemaphore *wait_sems,
                             int num_signal_sems,
-                            const VkSemaphore *signal_sems)
+                            const VkSemaphore *signal_sems,
+                            VkFence fence)
 {
        VkResult ret;
        memset(sem_info, 0, sizeof(*sem_info));
 
-       ret = radv_alloc_sem_counts(&sem_info->wait, num_wait_sems, wait_sems, true);
+       ret = radv_alloc_sem_counts(&sem_info->wait, num_wait_sems, wait_sems, VK_NULL_HANDLE, true);
        if (ret)
                return ret;
-       ret = radv_alloc_sem_counts(&sem_info->signal, num_signal_sems, signal_sems, false);
+       ret = radv_alloc_sem_counts(&sem_info->signal, num_signal_sems, signal_sems, fence, false);
        if (ret)
                radv_free_sem_info(sem_info);
 
@@ -1997,7 +2014,8 @@ VkResult radv_QueueSubmit(
                                             pSubmits[i].waitSemaphoreCount,
                                             pSubmits[i].pWaitSemaphores,
                                             pSubmits[i].signalSemaphoreCount,
-                                            pSubmits[i].pSignalSemaphores);
+                                            pSubmits[i].pSignalSemaphores,
+                                            _fence);
                if (result != VK_SUCCESS)
                        return result;
 
@@ -2068,11 +2086,18 @@ VkResult radv_QueueSubmit(
 
        if (fence) {
                if (!fence_emitted) {
-                       struct radv_winsys_sem_info sem_info = {0};
+                       struct radv_winsys_sem_info sem_info;
+
+                       result = radv_alloc_sem_info(&sem_info, 0, NULL, 0, NULL,
+                                                    _fence);
+                       if (result != VK_SUCCESS)
+                               return result;
+
                        ret = queue->device->ws->cs_submit(ctx, queue->queue_idx,
                                                           &queue->device->empty_cs[queue->queue_family_index],
                                                           1, NULL, NULL, &sem_info,
                                                           false, base_fence);
+                       radv_free_sem_info(&sem_info);
                }
                fence->submitted = true;
        }
@@ -2573,7 +2598,8 @@ radv_sparse_image_opaque_bind_memory(struct radv_device *device,
                                             pBindInfo[i].waitSemaphoreCount,
                                             pBindInfo[i].pWaitSemaphores,
                                             pBindInfo[i].signalSemaphoreCount,
-                                            pBindInfo[i].pSignalSemaphores);
+                                            pBindInfo[i].pSignalSemaphores,
+                                            _fence);
                if (result != VK_SUCCESS)
                        return result;
 
@@ -2606,6 +2632,11 @@ VkResult radv_CreateFence(
        VkFence*                                    pFence)
 {
        RADV_FROM_HANDLE(radv_device, device, _device);
+       const VkExportFenceCreateInfoKHR *export =
+               vk_find_struct_const(pCreateInfo->pNext, EXPORT_FENCE_CREATE_INFO_KHR);
+       VkExternalFenceHandleTypeFlagsKHR handleTypes =
+               export ? export->handleTypes : 0;
+
        struct radv_fence *fence = vk_alloc2(&device->alloc, pAllocator,
                                               sizeof(*fence), 8,
                                               VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
@@ -2615,10 +2646,24 @@ VkResult radv_CreateFence(
 
        fence->submitted = false;
        fence->signalled = !!(pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT);
-       fence->fence = device->ws->create_fence();
-       if (!fence->fence) {
-               vk_free2(&device->alloc, pAllocator, fence);
-               return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+       fence->temp_syncobj = 0;
+       if (handleTypes) {
+               int ret = device->ws->create_syncobj(device->ws, &fence->syncobj);
+               if (ret) {
+                       vk_free2(&device->alloc, pAllocator, fence);
+                       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+               }
+               if (pCreateInfo->flags & VK_FENCE_CREATE_SIGNALED_BIT) {
+                       device->ws->signal_syncobj(device->ws, fence->syncobj);
+               }
+               fence->fence = NULL;
+       } else {
+               fence->fence = device->ws->create_fence();
+               if (!fence->fence) {
+                       vk_free2(&device->alloc, pAllocator, fence);
+                       return vk_error(VK_ERROR_OUT_OF_HOST_MEMORY);
+               }
+               fence->syncobj = 0;
        }
 
        *pFence = radv_fence_to_handle(fence);
@@ -2636,7 +2681,13 @@ void radv_DestroyFence(
 
        if (!fence)
                return;
-       device->ws->destroy_fence(fence->fence);
+
+       if (fence->temp_syncobj)
+               device->ws->destroy_syncobj(device->ws, fence->temp_syncobj);
+       if (fence->syncobj)
+               device->ws->destroy_syncobj(device->ws, fence->syncobj);
+       if (fence->fence)
+               device->ws->destroy_fence(fence->fence);
        vk_free2(&device->alloc, pAllocator, fence);
 }
 
@@ -2671,6 +2722,18 @@ VkResult radv_WaitForFences(
                RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
                bool expired = false;
 
+               if (fence->temp_syncobj) {
+                       if (!device->ws->wait_syncobj(device->ws, fence->temp_syncobj, timeout))
+                               return VK_TIMEOUT;
+                       continue;
+               }
+
+               if (fence->syncobj) {
+                       if (!device->ws->wait_syncobj(device->ws, fence->syncobj, timeout))
+                               return VK_TIMEOUT;
+                       continue;
+               }
+
                if (fence->signalled)
                        continue;
 
@@ -2687,13 +2750,26 @@ VkResult radv_WaitForFences(
        return VK_SUCCESS;
 }
 
-VkResult radv_ResetFences(VkDevice device,
+VkResult radv_ResetFences(VkDevice _device,
                          uint32_t fenceCount,
                          const VkFence *pFences)
 {
+       RADV_FROM_HANDLE(radv_device, device, _device);
+
        for (unsigned i = 0; i < fenceCount; ++i) {
                RADV_FROM_HANDLE(radv_fence, fence, pFences[i]);
                fence->submitted = fence->signalled = false;
+
+               /* Per spec, we first restore the permanent payload, and then reset, so
+                * having a temp syncobj should not skip resetting the permanent syncobj. */
+               if (fence->temp_syncobj) {
+                       device->ws->destroy_syncobj(device->ws, fence->temp_syncobj);
+                       fence->temp_syncobj = 0;
+               }
+
+               if (fence->syncobj) {
+                       device->ws->reset_syncobj(device->ws, fence->syncobj);
+               }
        }
 
        return VK_SUCCESS;
@@ -2704,11 +2780,20 @@ VkResult radv_GetFenceStatus(VkDevice _device, VkFence _fence)
        RADV_FROM_HANDLE(radv_device, device, _device);
        RADV_FROM_HANDLE(radv_fence, fence, _fence);
 
+       if (fence->temp_syncobj) {
+                       bool success = device->ws->wait_syncobj(device->ws, fence->temp_syncobj, 0);
+                       return success ? VK_SUCCESS : VK_NOT_READY;
+       }
+
+       if (fence->syncobj) {
+                       bool success = device->ws->wait_syncobj(device->ws, fence->syncobj, 0);
+                       return success ? VK_SUCCESS : VK_NOT_READY;
+       }
+
        if (fence->signalled)
                return VK_SUCCESS;
        if (!fence->submitted)
                return VK_NOT_READY;
-
        if (!device->ws->fence_wait(device->ws, fence->fence, false, 0))
                return VK_NOT_READY;
 
index 2e1362c446d3b6ab441cc360fcb5e9612d2e339e..1b231801583670c75941c29941fcc9d5ff23c9f8 100644 (file)
@@ -1558,7 +1558,8 @@ VkResult radv_alloc_sem_info(struct radv_winsys_sem_info *sem_info,
                             int num_wait_sems,
                             const VkSemaphore *wait_sems,
                             int num_signal_sems,
-                            const VkSemaphore *signal_sems);
+                            const VkSemaphore *signal_sems,
+                            VkFence fence);
 void radv_free_sem_info(struct radv_winsys_sem_info *sem_info);
 
 void radv_set_descriptor_set(struct radv_cmd_buffer *cmd_buffer,
@@ -1597,6 +1598,9 @@ struct radv_fence {
        struct radeon_winsys_fence *fence;
        bool submitted;
        bool signalled;
+
+       uint32_t syncobj;
+       uint32_t temp_syncobj;
 };
 
 struct radeon_winsys_sem;
index 51e8ec666f7ea5f4641b084fe99a425656eb0b80..e016e8371029fd4144175b9650392e20c35ddf82 100644 (file)
@@ -214,6 +214,11 @@ VkResult radv_AcquireNextImageKHR(
        if (fence && (result == VK_SUCCESS || result == VK_SUBOPTIMAL_KHR)) {
                fence->submitted = true;
                fence->signalled = true;
+               if (fence->temp_syncobj) {
+                       device->ws->signal_syncobj(device->ws, fence->temp_syncobj);
+               } else if (fence->syncobj) {
+                       device->ws->signal_syncobj(device->ws, fence->syncobj);
+               }
        }
        return result;
 }