From 969421b7dab414313c2ec9ba6f2d193b4c117cec Mon Sep 17 00:00:00 2001 From: Bas Nieuwenhuizen Date: Mon, 27 Nov 2017 23:58:35 +0100 Subject: [PATCH] radv: Implement fences based on syncobjs. Reviewed-by: Dave Airlie --- src/amd/vulkan/radv_device.c | 113 +++++++++++++++++++++++++++++----- src/amd/vulkan/radv_private.h | 6 +- src/amd/vulkan/radv_wsi.c | 5 ++ 3 files changed, 109 insertions(+), 15 deletions(-) diff --git a/src/amd/vulkan/radv_device.c b/src/amd/vulkan/radv_device.c index 7c0971d190d..fc9fb59f991 100644 --- a/src/amd/vulkan/radv_device.c +++ b/src/amd/vulkan/radv_device.c @@ -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; diff --git a/src/amd/vulkan/radv_private.h b/src/amd/vulkan/radv_private.h index 2e1362c446d..1b231801583 100644 --- a/src/amd/vulkan/radv_private.h +++ b/src/amd/vulkan/radv_private.h @@ -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; diff --git a/src/amd/vulkan/radv_wsi.c b/src/amd/vulkan/radv_wsi.c index 51e8ec666f7..e016e837102 100644 --- a/src/amd/vulkan/radv_wsi.c +++ b/src/amd/vulkan/radv_wsi.c @@ -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; } -- 2.30.2