wsi/drm: Do the dma_buf_semaphore setup at swapchain creation time.

Less work at present time, and will let us make decisions about implicit
sync up front.

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/19309>
This commit is contained in:
Emma Anholt 2025-08-05 17:50:42 -07:00 committed by Marge Bot
parent a377d32fdc
commit 8f67d59725
3 changed files with 54 additions and 73 deletions

View file

@ -500,6 +500,12 @@ wsi_swapchain_init(const struct wsi_device *wsi,
if (result != VK_SUCCESS)
goto fail;
#ifdef HAVE_LIBDRM
result = wsi_drm_init_swapchain_implicit_sync(chain);
if (result != VK_SUCCESS)
goto fail;
#endif
return VK_SUCCESS;
fail:
@ -1485,7 +1491,6 @@ wsi_common_queue_present(const struct wsi_device *wsi,
VkFence fence = swapchain->fences[image_index];
bool has_signal_dma_buf = false;
bool explicit_sync = swapchain->image_info.explicit_sync;
if (explicit_sync) {
/* We will signal this acquire value ourselves when GPU work is done. */
@ -1500,20 +1505,11 @@ wsi_common_queue_present(const struct wsi_device *wsi,
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &image->explicit_sync[WSI_ES_ACQUIRE].semaphore;
__vk_append_struct(&submit_info, &timeline_submit_info);
} else {
#ifdef HAVE_LIBDRM
result = wsi_prepare_signal_dma_buf_from_semaphore(swapchain, image);
if (result == VK_SUCCESS) {
assert(submit_info.signalSemaphoreCount == 0);
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &swapchain->dma_buf_semaphore;
has_signal_dma_buf = true;
} else if (result == VK_ERROR_FEATURE_NOT_PRESENT) {
result = VK_SUCCESS;
has_signal_dma_buf = false;
} else {
goto fail_present;
}
} else if (swapchain->dma_buf_semaphore) {
assert(submit_info.signalSemaphoreCount == 0);
submit_info.signalSemaphoreCount = 1;
submit_info.pSignalSemaphores = &swapchain->dma_buf_semaphore;
#endif
}
@ -1532,13 +1528,11 @@ wsi_common_queue_present(const struct wsi_device *wsi,
*/
if (!explicit_sync) {
#ifdef HAVE_LIBDRM
if (has_signal_dma_buf) {
if (swapchain->dma_buf_semaphore) {
result = wsi_signal_dma_buf_from_semaphore(swapchain, image);
if (result != VK_SUCCESS)
goto fail_present;
}
#else
assert(!has_signal_dma_buf);
#endif
}

View file

@ -174,62 +174,6 @@ out:
return result;
}
static VkResult
prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain,
const struct wsi_image *image)
{
VkResult result;
if (!(chain->wsi->semaphore_export_handle_types &
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT))
return VK_ERROR_FEATURE_NOT_PRESENT;
int sync_file_fd = -1;
result = wsi_dma_buf_export_sync_file(image->dma_buf_fd, &sync_file_fd);
if (result != VK_SUCCESS)
return result;
result = wsi_dma_buf_import_sync_file(image->dma_buf_fd, sync_file_fd);
close(sync_file_fd);
if (result != VK_SUCCESS)
return result;
/* If we got here, all our checks pass. Create the actual semaphore */
const VkExportSemaphoreCreateInfo export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
const VkSemaphoreCreateInfo semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &export_info,
};
result = chain->wsi->CreateSemaphore(chain->device, &semaphore_info,
&chain->alloc,
&chain->dma_buf_semaphore);
if (result != VK_SUCCESS)
return result;
return VK_SUCCESS;
}
VkResult
wsi_prepare_signal_dma_buf_from_semaphore(struct wsi_swapchain *chain,
const struct wsi_image *image)
{
VkResult result;
/* We cache result - 1 in the swapchain */
if (unlikely(chain->signal_dma_buf_from_semaphore == 0)) {
result = prepare_signal_dma_buf_from_semaphore(chain, image);
assert(result <= 0);
chain->signal_dma_buf_from_semaphore = (int)result - 1;
} else {
result = (VkResult)(chain->signal_dma_buf_from_semaphore + 1);
}
return result;
}
/**
* Imports the dma_buf_semaphore's syncobj into the dmabuf so that display
* implicit sync waits on it.
@ -401,6 +345,46 @@ wsi_destroy_image_explicit_sync_drm(const struct wsi_swapchain *chain,
}
}
/**
* Sets up the semaphore for WSI-internal implicit sync handling if the WSI
* backend is not doing explicit sync.
*/
VkResult
wsi_drm_init_swapchain_implicit_sync(struct wsi_swapchain *chain)
{
/* We don't need implicit sync if explicit sync is available through the
* window system protocol.
*/
if (chain->image_info.explicit_sync)
return VK_SUCCESS;
/* If semaphores don't support sync FD or if the kernel doesn't support
* sync file import/export, then WSI will fall back to requesting BO-based
* implicit sync from the driver.
*/
if (!(chain->wsi->semaphore_export_handle_types &
VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT))
return VK_SUCCESS;
VkResult result =
wsi_drm_check_dma_buf_sync_file_import_export(chain->wsi, chain->device);
if (result == VK_ERROR_FEATURE_NOT_PRESENT)
return VK_SUCCESS;
/* If we got here, all our checks pass. Create the actual semaphore */
const VkExportSemaphoreCreateInfo export_info = {
.sType = VK_STRUCTURE_TYPE_EXPORT_SEMAPHORE_CREATE_INFO,
.handleTypes = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
};
const VkSemaphoreCreateInfo semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
.pNext = &export_info,
};
return chain->wsi->CreateSemaphore(chain->device, &semaphore_info,
&chain->alloc,
&chain->dma_buf_semaphore);
}
static VkResult
wsi_create_sync_imm(struct vk_device *device, struct vk_sync **sync_out)
{

View file

@ -409,6 +409,9 @@ wsi_drm_wait_for_explicit_sync_release(struct wsi_swapchain *chain,
uint64_t rel_timeout_ns,
uint32_t *image_index);
VkResult
wsi_drm_init_swapchain_implicit_sync(struct wsi_swapchain *chain);
#endif
struct wsi_interface {