vulkan/android: improve vkQueueSignalReleaseImageANDROID

There're two issues with the current implementation:
1. Wait semaphores are implicitly required to be SYNC_FD exportable
2. As a queue command that can further record cmds against the wsi
   image, it currently doesn't account for pending cmds in the queue
   beyond the wait semaphores.

This change fixes both by doing a queue submission in the call with a
SYNC_FD external signal semaphore. However, due to Android wsi not
exposing swapchain to icd, we have to cache the signal semaphore in the
queue, otherwise would have to create/destroy in each present.

Signed-off-by: Yiwei Zhang <zzyiwei@chromium.org>
Reviewed-by: Chia-I Wu <olvaffe@gmail.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/25185>
This commit is contained in:
Yiwei Zhang
2023-09-09 17:10:44 -07:00
committed by Marge Bot
parent 6ed2515df1
commit 3c4c263dc7
3 changed files with 69 additions and 36 deletions

View File

@@ -301,6 +301,24 @@ vk_common_AcquireImageANDROID(VkDevice _device,
return result;
}
static VkResult
vk_anb_semaphore_init_once(struct vk_queue *queue, struct vk_device *device)
{
if (queue->anb_semaphore != VK_NULL_HANDLE)
return VK_SUCCESS;
const VkExportSemaphoreCreateInfo export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
const VkSemaphoreCreateInfo create_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &export_info,
};
return device->dispatch_table.CreateSemaphore(vk_device_to_handle(device),
&create_info, NULL,
&queue->anb_semaphore);
}
VKAPI_ATTR VkResult VKAPI_CALL
vk_common_QueueSignalReleaseImageANDROID(VkQueue _queue,
@@ -313,43 +331,32 @@ vk_common_QueueSignalReleaseImageANDROID(VkQueue _queue,
struct vk_device *device = queue->base.device;
VkResult result = VK_SUCCESS;
if (waitSemaphoreCount == 0) {
if (pNativeFenceFd)
*pNativeFenceFd = -1;
return VK_SUCCESS;
}
STACK_ARRAY(VkPipelineStageFlags, stage_flags, MAX2(1, waitSemaphoreCount));
for (uint32_t i = 0; i < MAX2(1, waitSemaphoreCount); i++)
stage_flags[i] = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
int fd = -1;
result = vk_anb_semaphore_init_once(queue, device);
if (result != VK_SUCCESS)
return result;
for (uint32_t i = 0; i < waitSemaphoreCount; ++i) {
const VkSemaphoreGetFdInfoKHR get_fd = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
.semaphore = pWaitSemaphores[i],
};
int tmp_fd;
result = device->dispatch_table.GetSemaphoreFdKHR(vk_device_to_handle(device),
&get_fd, &tmp_fd);
if (result != VK_SUCCESS) {
if (fd >= 0)
close(fd);
return result;
}
const VkSubmitInfo submit_info = {
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
.waitSemaphoreCount = waitSemaphoreCount,
.pWaitSemaphores = pWaitSemaphores,
.pWaitDstStageMask = stage_flags,
.signalSemaphoreCount = 1,
.pSignalSemaphores = &queue->anb_semaphore,
};
result = device->dispatch_table.QueueSubmit(_queue, 1, &submit_info,
VK_NULL_HANDLE);
if (result != VK_SUCCESS)
return result;
if (fd < 0) {
fd = tmp_fd;
} else if (tmp_fd >= 0) {
sync_accumulate("vulkan", &fd, tmp_fd);
close(tmp_fd);
}
}
if (pNativeFenceFd) {
*pNativeFenceFd = fd;
} else if (fd >= 0) {
close(fd);
/* We still need to do the exports, to reset the semaphores, but
* otherwise we don't wait on them. */
}
return VK_SUCCESS;
const VkSemaphoreGetFdInfoKHR get_fd = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
.semaphore = queue->anb_semaphore,
};
return device->dispatch_table.GetSemaphoreFdKHR(vk_device_to_handle(device),
&get_fd, pNativeFenceFd);
}