render/vulkan: add support for explicit sync

This commit is contained in:
Simon Ser 2024-08-05 20:51:15 +02:00 committed by Alexander Orzechowski
parent 9351c78d70
commit 3bbfae73ae
5 changed files with 190 additions and 71 deletions

View file

@ -13,6 +13,7 @@
#include <wlr/types/wlr_drm.h>
#include <wlr/util/box.h>
#include <wlr/util/log.h>
#include <wlr/render/drm_syncobj.h>
#include <wlr/render/vulkan.h>
#include <wlr/backend/interface.h>
#include <wlr/types/wlr_linux_dmabuf_v1.h>
@ -921,9 +922,9 @@ static struct wlr_vk_render_buffer *get_render_buffer(
return buffer;
}
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture) {
bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture,
int sync_file_fds[static WLR_DMABUF_MAX_PLANES]) {
struct wlr_vk_renderer *renderer = texture->renderer;
VkResult res;
struct wlr_dmabuf_attributes dmabuf = {0};
if (!wlr_buffer_get_dmabuf(texture->buffer, &dmabuf)) {
@ -960,52 +961,22 @@ bool vulkan_sync_foreign_texture(struct wlr_vk_texture *texture) {
return false;
}
if (texture->foreign_semaphores[i] == VK_NULL_HANDLE) {
VkSemaphoreCreateInfo semaphore_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
};
res = vkCreateSemaphore(renderer->dev->dev, &semaphore_info, NULL,
&texture->foreign_semaphores[i]);
if (res != VK_SUCCESS) {
close(sync_file_fd);
wlr_vk_error("vkCreateSemaphore", res);
return false;
}
}
VkImportSemaphoreFdInfoKHR import_info = {
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
.semaphore = texture->foreign_semaphores[i],
.fd = sync_file_fd,
};
res = renderer->dev->api.vkImportSemaphoreFdKHR(renderer->dev->dev, &import_info);
if (res != VK_SUCCESS) {
close(sync_file_fd);
wlr_vk_error("vkImportSemaphoreFdKHR", res);
return false;
}
sync_file_fds[i] = sync_file_fd;
}
return true;
}
bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb) {
struct wlr_vk_render_buffer *render_buffer, struct wlr_vk_command_buffer *cb,
struct wlr_drm_syncobj_timeline *signal_timeline, uint64_t signal_point) {
VkResult res;
if (!renderer->dev->implicit_sync_interop) {
if (!renderer->dev->implicit_sync_interop && signal_timeline == NULL) {
// We have no choice but to block here sadly
return vulkan_wait_command_buffer(cb, renderer);
}
struct wlr_dmabuf_attributes dmabuf = {0};
if (!wlr_buffer_get_dmabuf(render_buffer->wlr_buffer, &dmabuf)) {
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf failed");
return false;
}
// Note: vkGetSemaphoreFdKHR implicitly resets the semaphore
const VkSemaphoreGetFdInfoKHR get_fence_fd_info = {
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
@ -1020,17 +991,32 @@ bool vulkan_sync_render_buffer(struct wlr_vk_renderer *renderer,
return false;
}
for (int i = 0; i < dmabuf.n_planes; i++) {
if (!dmabuf_import_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_WRITE,
sync_file_fd)) {
close(sync_file_fd);
return false;
bool ok = false;
if (signal_timeline != NULL) {
if (!wlr_drm_syncobj_timeline_import_sync_file(signal_timeline,
signal_point, sync_file_fd)) {
goto out;
}
} else {
struct wlr_dmabuf_attributes dmabuf = {0};
if (!wlr_buffer_get_dmabuf(render_buffer->wlr_buffer, &dmabuf)) {
wlr_log(WLR_ERROR, "wlr_buffer_get_dmabuf failed");
goto out;
}
for (int i = 0; i < dmabuf.n_planes; i++) {
if (!dmabuf_import_sync_file(dmabuf.fd[i], DMA_BUF_SYNC_WRITE,
sync_file_fd)) {
goto out;
}
}
}
close(sync_file_fd);
ok = true;
return true;
out:
close(sync_file_fd);
return ok;
}
static const struct wlr_drm_format_set *vulkan_get_texture_formats(
@ -1073,6 +1059,11 @@ static void vulkan_destroy(struct wlr_renderer *wlr_renderer) {
if (cb->binary_semaphore != VK_NULL_HANDLE) {
vkDestroySemaphore(renderer->dev->dev, cb->binary_semaphore, NULL);
}
VkSemaphore *sem_ptr;
wl_array_for_each(sem_ptr, &cb->wait_semaphores) {
vkDestroySemaphore(renderer->dev->dev, *sem_ptr, NULL);
}
wl_array_release(&cb->wait_semaphores);
}
// stage.cb automatically freed with command pool
@ -2436,6 +2427,11 @@ struct wlr_renderer *vulkan_renderer_create_for_device(struct wlr_vk_device *dev
wl_list_init(&renderer->color_transforms);
wl_list_init(&renderer->pipeline_layouts);
uint64_t cap_syncobj_timeline;
if (dev->drm_fd >= 0 && drmGetCap(dev->drm_fd, DRM_CAP_SYNCOBJ_TIMELINE, &cap_syncobj_timeline) == 0) {
renderer->wlr_renderer.features.timeline = dev->sync_file_import_export && cap_syncobj_timeline != 0;
}
if (!init_static_render_data(renderer)) {
goto error;
}