mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-20 07:20:10 +01:00
vulkan/wsi: Add mechanism to wait for WSI semaphore unsignal.
When vkWaitForPresentKHR succeeds, we are guaranteed that any dependent semaphores have been unsignalled. In an explicit sync world, we are guaranteed this automatically by having a present complete, since that event must follow a semaphore wait completion. However, if the swapchain image is implicitly synchronized, the semaphore might technically not have been unsignaled before the present complete event triggers. Present IDs must be signalled in monotonic order, same as timeline semaphores. Signed-off-by: Hans-Kristian Arntzen <post@arntzen-software.no> Reviewed-by: Joshua Ashton <joshua@froggi.es> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19279>
This commit is contained in:
parent
339c0f6a7e
commit
c888da3d48
3 changed files with 85 additions and 0 deletions
|
|
@ -129,6 +129,12 @@ wsi_device_init(struct wsi_device *wsi,
|
|||
&vk_physical_device_from_handle(pdevice)->supported_extensions;
|
||||
wsi->has_import_memory_host =
|
||||
supported_extensions->EXT_external_memory_host;
|
||||
wsi->khr_present_wait =
|
||||
supported_extensions->KHR_present_id &&
|
||||
supported_extensions->KHR_present_wait;
|
||||
|
||||
/* We cannot expose KHR_present_wait without timeline semaphores. */
|
||||
assert(!wsi->khr_present_wait || supported_extensions->KHR_timeline_semaphore);
|
||||
|
||||
list_inithead(&wsi->hotplug_fences);
|
||||
|
||||
|
|
@ -169,6 +175,8 @@ wsi_device_init(struct wsi_device *wsi,
|
|||
WSI_GET_CB(WaitForFences);
|
||||
WSI_GET_CB(MapMemory);
|
||||
WSI_GET_CB(UnmapMemory);
|
||||
if (wsi->khr_present_wait)
|
||||
WSI_GET_CB(WaitSemaphoresKHR);
|
||||
#undef WSI_GET_CB
|
||||
|
||||
#ifdef VK_USE_PLATFORM_XCB_KHR
|
||||
|
|
@ -487,6 +495,8 @@ wsi_swapchain_finish(struct wsi_swapchain *chain)
|
|||
}
|
||||
chain->wsi->DestroySemaphore(chain->device, chain->dma_buf_semaphore,
|
||||
&chain->alloc);
|
||||
chain->wsi->DestroySemaphore(chain->device, chain->present_id_timeline,
|
||||
&chain->alloc);
|
||||
|
||||
int cmd_pools_count = chain->buffer_blit_queue != VK_NULL_HANDLE ?
|
||||
1 : chain->wsi->queue_family_count;
|
||||
|
|
@ -879,12 +889,33 @@ wsi_CreateSwapchainKHR(VkDevice _device,
|
|||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
||||
if (wsi_device->khr_present_wait) {
|
||||
const VkSemaphoreTypeCreateInfo type_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_TYPE_CREATE_INFO,
|
||||
.semaphoreType = VK_SEMAPHORE_TYPE_TIMELINE,
|
||||
};
|
||||
|
||||
const VkSemaphoreCreateInfo sem_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
|
||||
.pNext = &type_info,
|
||||
.flags = 0,
|
||||
};
|
||||
|
||||
/* We assume here that a driver exposing present_wait also exposes VK_KHR_timeline_semaphore. */
|
||||
result = wsi_device->CreateSemaphore(_device, &sem_info, alloc, &swapchain->present_id_timeline);
|
||||
if (result != VK_SUCCESS) {
|
||||
swapchain->destroy(swapchain, alloc);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
}
|
||||
|
||||
if (swapchain->buffer_blit_queue != VK_NULL_HANDLE) {
|
||||
swapchain->buffer_blit_semaphores = vk_zalloc(alloc,
|
||||
sizeof (*swapchain->buffer_blit_semaphores) * swapchain->image_count,
|
||||
sizeof (*swapchain->buffer_blit_semaphores),
|
||||
VK_SYSTEM_ALLOCATION_SCOPE_OBJECT);
|
||||
if (!swapchain->buffer_blit_semaphores) {
|
||||
wsi_device->DestroySemaphore(_device, swapchain->present_id_timeline, alloc);
|
||||
swapchain->destroy(swapchain, alloc);
|
||||
return VK_ERROR_OUT_OF_HOST_MEMORY;
|
||||
}
|
||||
|
|
@ -1091,6 +1122,27 @@ wsi_AcquireNextImage2KHR(VkDevice _device,
|
|||
_device, pAcquireInfo, pImageIndex);
|
||||
}
|
||||
|
||||
static VkResult wsi_signal_present_id_timeline(struct wsi_swapchain *swapchain,
|
||||
VkQueue queue, uint64_t present_id)
|
||||
{
|
||||
assert(swapchain->present_id_timeline);
|
||||
|
||||
const VkTimelineSemaphoreSubmitInfo timeline_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO,
|
||||
.pSignalSemaphoreValues = &present_id,
|
||||
.signalSemaphoreValueCount = 1,
|
||||
};
|
||||
|
||||
const VkSubmitInfo submit_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO,
|
||||
.pNext = &timeline_info,
|
||||
.signalSemaphoreCount = 1,
|
||||
.pSignalSemaphores = &swapchain->present_id_timeline,
|
||||
};
|
||||
|
||||
return swapchain->wsi->QueueSubmit(queue, 1, &submit_info, VK_NULL_HANDLE);
|
||||
}
|
||||
|
||||
VkResult
|
||||
wsi_common_queue_present(const struct wsi_device *wsi,
|
||||
VkDevice device,
|
||||
|
|
@ -1260,6 +1312,12 @@ wsi_common_queue_present(const struct wsi_device *wsi,
|
|||
if (present_ids && present_ids->pPresentIds)
|
||||
present_id = present_ids->pPresentIds[i];
|
||||
|
||||
if (present_id) {
|
||||
result = wsi_signal_present_id_timeline(swapchain, queue, present_id);
|
||||
if (result != VK_SUCCESS)
|
||||
goto fail_present;
|
||||
}
|
||||
|
||||
result = swapchain->queue_present(swapchain, image_index, present_id, region);
|
||||
if (result != VK_SUCCESS && result != VK_SUBOPTIMAL_KHR)
|
||||
goto fail_present;
|
||||
|
|
@ -1386,6 +1444,21 @@ wsi_common_bind_swapchain_image(const struct wsi_device *wsi,
|
|||
return wsi->BindImageMemory(chain->device, vk_image, image->memory, 0);
|
||||
}
|
||||
|
||||
VkResult
|
||||
wsi_swapchain_wait_for_present_semaphore(const struct wsi_swapchain *chain,
|
||||
uint64_t present_id, uint64_t timeout)
|
||||
{
|
||||
assert(chain->present_id_timeline);
|
||||
const VkSemaphoreWaitInfo wait_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_WAIT_INFO,
|
||||
.semaphoreCount = 1,
|
||||
.pSemaphores = &chain->present_id_timeline,
|
||||
.pValues = &present_id,
|
||||
};
|
||||
|
||||
return chain->wsi->WaitSemaphoresKHR(chain->device, &wait_info, timeout);
|
||||
}
|
||||
|
||||
uint32_t
|
||||
wsi_select_memory_type(const struct wsi_device *wsi,
|
||||
VkMemoryPropertyFlags req_props,
|
||||
|
|
|
|||
|
|
@ -166,6 +166,12 @@ struct wsi_device {
|
|||
*/
|
||||
bool signal_fence_with_memory;
|
||||
|
||||
/* Whether present_wait functionality is enabled on the device.
|
||||
* In this case, we have to create an extra timeline semaphore
|
||||
* to be able to synchronize with the WSI present semaphore being unsignalled.
|
||||
* This requires VK_KHR_timeline_semaphore. */
|
||||
bool khr_present_wait;
|
||||
|
||||
/*
|
||||
* This sets the ownership for a WSI memory object:
|
||||
*
|
||||
|
|
@ -229,6 +235,7 @@ struct wsi_device {
|
|||
WSI_CB(WaitForFences);
|
||||
WSI_CB(MapMemory);
|
||||
WSI_CB(UnmapMemory);
|
||||
WSI_CB(WaitSemaphoresKHR);
|
||||
#undef WSI_CB
|
||||
|
||||
struct wsi_interface * wsi[VK_ICD_WSI_PLATFORM_MAX];
|
||||
|
|
|
|||
|
|
@ -134,6 +134,7 @@ struct wsi_swapchain {
|
|||
VkFence* fences;
|
||||
VkSemaphore* buffer_blit_semaphores;
|
||||
VkPresentModeKHR present_mode;
|
||||
VkSemaphore present_id_timeline;
|
||||
|
||||
int signal_dma_buf_from_semaphore;
|
||||
VkSemaphore dma_buf_semaphore;
|
||||
|
|
@ -256,6 +257,10 @@ void
|
|||
wsi_destroy_image(const struct wsi_swapchain *chain,
|
||||
struct wsi_image *image);
|
||||
|
||||
VkResult
|
||||
wsi_swapchain_wait_for_present_semaphore(const struct wsi_swapchain *chain,
|
||||
uint64_t present_id, uint64_t timeout);
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
VkResult
|
||||
wsi_prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain,
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue