[Mesa-dev] [PATCH 4/6] radv: Implement fences based on syncobjs.

Bas Nieuwenhuizen bas at basnieuwenhuizen.nl
Sun Dec 17 00:11:53 UTC 2017


---
 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.15.1



More information about the mesa-dev mailing list