diff --git a/src/virtio/vulkan/vn_android.c b/src/virtio/vulkan/vn_android.c index 9895f3bc805..f1ba3ce68f1 100644 --- a/src/virtio/vulkan/vn_android.c +++ b/src/virtio/vulkan/vn_android.c @@ -796,17 +796,38 @@ vn_AcquireImageANDROID(VkDevice device, return vn_result(dev->instance, result); } +static VkResult +vn_android_sync_fence_create(struct vn_queue *queue) +{ + struct vn_device *dev = queue->device; + + const VkExportFenceCreateInfo export_info = { + .sType = VK_STRUCTURE_TYPE_EXPORT_FENCE_CREATE_INFO, + .pNext = NULL, + .handleTypes = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, + }; + const VkFenceCreateInfo create_info = { + .sType = VK_STRUCTURE_TYPE_FENCE_CREATE_INFO, + .pNext = + dev->instance->experimental.globalFencing ? &export_info : NULL, + .flags = 0, + }; + return vn_CreateFence(vn_device_to_handle(dev), &create_info, NULL, + &queue->sync_fence); +} + VkResult -vn_QueueSignalReleaseImageANDROID(VkQueue queue, +vn_QueueSignalReleaseImageANDROID(VkQueue _queue, uint32_t waitSemaphoreCount, const VkSemaphore *pWaitSemaphores, VkImage image, int *pNativeFenceFd) { VN_TRACE_FUNC(); - struct vn_queue *que = vn_queue_from_handle(queue); - struct vn_device *dev = que->device; + struct vn_queue *queue = vn_queue_from_handle(_queue); + struct vn_device *dev = queue->device; const VkAllocationCallbacks *alloc = &dev->base.base.alloc; + const bool has_global_fencing = dev->instance->experimental.globalFencing; VkDevice device = vn_device_to_handle(dev); VkPipelineStageFlags local_stage_masks[8]; VkPipelineStageFlags *stage_masks = local_stage_masks; @@ -818,6 +839,13 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue, return VK_SUCCESS; } + /* lazily create sync fence for Android wsi */ + if (queue->sync_fence == VK_NULL_HANDLE) { + result = vn_android_sync_fence_create(queue); + if (result != VK_SUCCESS) + return result; + } + if (waitSemaphoreCount > ARRAY_SIZE(local_stage_masks)) { stage_masks = vk_alloc(alloc, sizeof(*stage_masks) * waitSemaphoreCount, @@ -844,10 +872,9 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue, * reset the fence during vn_GetFenceFdKHR currently. Thus to ensure proper * host driver behavior, we pass VK_NULL_HANDLE here. */ - result = vn_QueueSubmit( - queue, 1, &submit_info, - dev->instance->experimental.globalFencing == VK_TRUE ? VK_NULL_HANDLE - : que->wait_fence); + result = + vn_QueueSubmit(_queue, 1, &submit_info, + has_global_fencing ? VK_NULL_HANDLE : queue->sync_fence); if (stage_masks != local_stage_masks) vk_free(alloc, stage_masks); @@ -855,7 +882,7 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue, if (result != VK_SUCCESS) return vn_error(dev->instance, result); - if (dev->instance->experimental.globalFencing == VK_TRUE) { + if (has_global_fencing) { /* With globalFencing, the external queue fence was not passed in the * above vn_QueueSubmit to hint it to be synchronous. So we need to wait * for the ring here before vn_GetFenceFdKHR which is pure kernel ops. @@ -867,17 +894,17 @@ vn_QueueSignalReleaseImageANDROID(VkQueue queue, const VkFenceGetFdInfoKHR fd_info = { .sType = VK_STRUCTURE_TYPE_FENCE_GET_FD_INFO_KHR, .pNext = NULL, - .fence = que->wait_fence, + .fence = queue->sync_fence, .handleType = VK_EXTERNAL_FENCE_HANDLE_TYPE_SYNC_FD_BIT, }; result = vn_GetFenceFdKHR(device, &fd_info, &fd); } else { result = - vn_WaitForFences(device, 1, &que->wait_fence, VK_TRUE, UINT64_MAX); + vn_WaitForFences(device, 1, &queue->sync_fence, VK_TRUE, UINT64_MAX); if (result != VK_SUCCESS) return vn_error(dev->instance, result); - result = vn_ResetFences(device, 1, &que->wait_fence); + result = vn_ResetFences(device, 1, &queue->sync_fence); } if (result != VK_SUCCESS) diff --git a/src/virtio/vulkan/vn_device.c b/src/virtio/vulkan/vn_device.c index e83e0f2ced7..57a72da643e 100644 --- a/src/virtio/vulkan/vn_device.c +++ b/src/virtio/vulkan/vn_device.c @@ -22,9 +22,13 @@ static void vn_queue_fini(struct vn_queue *queue) { + VkDevice dev_handle = vn_device_to_handle(queue->device); + if (queue->wait_fence != VK_NULL_HANDLE) { - vn_DestroyFence(vn_device_to_handle(queue->device), queue->wait_fence, - NULL); + vn_DestroyFence(dev_handle, queue->wait_fence, NULL); + } + if (queue->sync_fence != VK_NULL_HANDLE) { + vn_DestroyFence(dev_handle, queue->sync_fence, NULL); } vn_object_base_fini(&queue->base); } diff --git a/src/virtio/vulkan/vn_queue.h b/src/virtio/vulkan/vn_queue.h index 594ca226e53..c815b994564 100644 --- a/src/virtio/vulkan/vn_queue.h +++ b/src/virtio/vulkan/vn_queue.h @@ -23,7 +23,11 @@ struct vn_queue { uint32_t index; uint32_t flags; + /* wait fence used for vn_QueueWaitIdle */ VkFence wait_fence; + + /* sync fence used for Android wsi */ + VkFence sync_fence; }; VK_DEFINE_HANDLE_CASTS(vn_queue, base.base, VkQueue, VK_OBJECT_TYPE_QUEUE)