mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-24 02:20:11 +01:00
zink: handle implicit sync for dmabufs
this adds explicit queue transitions to FOREIGN at the end of the batch for all written-to dmabufs, then also adds signal/wait semaphores using the dmabuf fds Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/24962>
This commit is contained in:
parent
4932e65f1e
commit
d4f8ad27f2
5 changed files with 181 additions and 0 deletions
|
|
@ -350,6 +350,7 @@ create_batch_state(struct zink_context *ctx)
|
|||
|
||||
SET_CREATE_OR_FAIL(&bs->programs);
|
||||
SET_CREATE_OR_FAIL(&bs->active_queries);
|
||||
SET_CREATE_OR_FAIL(&bs->dmabuf_exports);
|
||||
util_dynarray_init(&bs->signal_semaphores, NULL);
|
||||
util_dynarray_init(&bs->wait_semaphores, NULL);
|
||||
util_dynarray_init(&bs->fd_wait_semaphores, NULL);
|
||||
|
|
@ -584,6 +585,15 @@ submit_queue(void *data, void *gdata, int thread_index)
|
|||
assert(util_dynarray_num_elements(&bs->acquires, VkSemaphore) <= util_dynarray_num_elements(&bs->acquire_flags, VkPipelineStageFlags));
|
||||
si[ZINK_SUBMIT_WAIT_ACQUIRE].pWaitDstStageMask = bs->acquire_flags.data;
|
||||
|
||||
si[ZINK_SUBMIT_WAIT_FD].waitSemaphoreCount = util_dynarray_num_elements(&bs->fd_wait_semaphores, VkSemaphore);
|
||||
si[ZINK_SUBMIT_WAIT_FD].pWaitSemaphores = bs->fd_wait_semaphores.data;
|
||||
while (util_dynarray_num_elements(&bs->fd_wait_semaphore_stages, VkPipelineStageFlags) < si[ZINK_SUBMIT_WAIT_FD].waitSemaphoreCount) {
|
||||
VkPipelineStageFlags mask = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
|
||||
util_dynarray_append(&bs->fd_wait_semaphore_stages, VkPipelineStageFlags, mask);
|
||||
}
|
||||
assert(util_dynarray_num_elements(&bs->fd_wait_semaphores, VkSemaphore) <= util_dynarray_num_elements(&bs->fd_wait_semaphore_stages, VkPipelineStageFlags));
|
||||
si[ZINK_SUBMIT_WAIT_FD].pWaitDstStageMask = bs->fd_wait_semaphore_stages.data;
|
||||
|
||||
if (si[ZINK_SUBMIT_WAIT_ACQUIRE].waitSemaphoreCount == 0) {
|
||||
num_si--;
|
||||
submit++;
|
||||
|
|
@ -621,6 +631,10 @@ submit_queue(void *data, void *gdata, int thread_index)
|
|||
signals[si[ZINK_SUBMIT_CMDBUF].signalSemaphoreCount++] = bs->present;
|
||||
tsi.signalSemaphoreValueCount = si[ZINK_SUBMIT_CMDBUF].signalSemaphoreCount;
|
||||
|
||||
/* then the optional signal submit */
|
||||
si[ZINK_SUBMIT_SIGNAL].signalSemaphoreCount = util_dynarray_num_elements(&bs->signal_semaphores, VkSemaphore);
|
||||
si[ZINK_SUBMIT_SIGNAL].pSignalSemaphores = bs->signal_semaphores.data;
|
||||
|
||||
VkResult result = VKSCR(EndCommandBuffer)(bs->cmdbuf);
|
||||
if (result != VK_SUCCESS) {
|
||||
mesa_loge("ZINK: vkEndCommandBuffer failed (%s)", vk_Result_to_str(result));
|
||||
|
|
@ -656,6 +670,18 @@ submit_queue(void *data, void *gdata, int thread_index)
|
|||
bs->is_device_lost = true;
|
||||
}
|
||||
simple_mtx_unlock(&screen->queue_lock);
|
||||
|
||||
unsigned i = 0;
|
||||
set_foreach_remove(&bs->dmabuf_exports, entry) {
|
||||
struct zink_resource *res = (void*)entry->key;
|
||||
VkSemaphore *sem = bs->signal_semaphores.data;
|
||||
zink_screen_import_dmabuf_semaphore(screen, res, sem[i]);
|
||||
i++;
|
||||
|
||||
struct pipe_resource *pres = &res->base.b;
|
||||
pipe_resource_reference(&pres, NULL);
|
||||
}
|
||||
|
||||
bs->usage.submit_count++;
|
||||
end:
|
||||
cnd_broadcast(&bs->usage.flush);
|
||||
|
|
@ -727,6 +753,47 @@ zink_end_batch(struct zink_context *ctx, struct zink_batch *batch)
|
|||
zink_query_sync(ctx, (void*)entry->key);
|
||||
}
|
||||
|
||||
set_foreach(&bs->dmabuf_exports, entry) {
|
||||
struct zink_resource *res = (void*)entry->key;
|
||||
if (screen->info.have_KHR_synchronization2) {
|
||||
VkImageMemoryBarrier2 imb;
|
||||
zink_resource_image_barrier2_init(&imb, res, res->layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||
imb.srcQueueFamilyIndex = screen->gfx_queue;
|
||||
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
|
||||
VkDependencyInfo dep = {
|
||||
VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
NULL,
|
||||
0,
|
||||
0,
|
||||
NULL,
|
||||
0,
|
||||
NULL,
|
||||
1,
|
||||
&imb
|
||||
};
|
||||
VKCTX(CmdPipelineBarrier2)(bs->cmdbuf, &dep);
|
||||
} else {
|
||||
VkImageMemoryBarrier imb;
|
||||
zink_resource_image_barrier_init(&imb, res, res->layout, 0, VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT);
|
||||
imb.srcQueueFamilyIndex = screen->gfx_queue;
|
||||
imb.dstQueueFamilyIndex = VK_QUEUE_FAMILY_FOREIGN_EXT;
|
||||
VKCTX(CmdPipelineBarrier)(
|
||||
bs->cmdbuf,
|
||||
res->obj->access_stage,
|
||||
VK_PIPELINE_STAGE_BOTTOM_OF_PIPE_BIT,
|
||||
0,
|
||||
0, NULL,
|
||||
0, NULL,
|
||||
1, &imb
|
||||
);
|
||||
}
|
||||
res->queue = VK_QUEUE_FAMILY_FOREIGN_EXT;
|
||||
|
||||
VkSemaphore sem = zink_create_exportable_semaphore(screen);
|
||||
if (sem)
|
||||
util_dynarray_append(&ctx->batch.state->signal_semaphores, VkSemaphore, sem);
|
||||
}
|
||||
|
||||
if (screen->threaded_submit) {
|
||||
util_queue_add_job(&screen->flush_queue, bs, &bs->flush_completed,
|
||||
submit_queue, post_submit, 0);
|
||||
|
|
|
|||
|
|
@ -80,6 +80,7 @@ bool zink_tracing = false;
|
|||
#endif
|
||||
|
||||
#ifdef HAVE_LIBDRM
|
||||
#include "drm-uapi/dma-buf.h"
|
||||
#include <xf86drm.h>
|
||||
#endif
|
||||
|
||||
|
|
@ -2199,6 +2200,99 @@ zink_create_exportable_semaphore(struct zink_screen *screen)
|
|||
return ret == VK_SUCCESS ? sem : VK_NULL_HANDLE;
|
||||
}
|
||||
|
||||
VkSemaphore
|
||||
zink_screen_export_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res)
|
||||
{
|
||||
VkSemaphore sem = VK_NULL_HANDLE;
|
||||
#if defined(HAVE_LIBDRM) && (DETECT_OS_LINUX || DETECT_OS_BSD)
|
||||
struct dma_buf_export_sync_file export = {
|
||||
.flags = DMA_BUF_SYNC_RW,
|
||||
.fd = -1,
|
||||
};
|
||||
|
||||
int fd;
|
||||
VkMemoryGetFdInfoKHR fd_info = {0};
|
||||
fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
|
||||
fd_info.memory = zink_bo_get_mem(res->obj->bo);
|
||||
fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
VKSCR(GetMemoryFdKHR)(screen->dev, &fd_info, &fd);
|
||||
|
||||
int ret = drmIoctl(fd, DMA_BUF_IOCTL_EXPORT_SYNC_FILE, &export);
|
||||
if (ret) {
|
||||
if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) {
|
||||
assert(!"how did this fail?");
|
||||
return VK_NULL_HANDLE;
|
||||
} else {
|
||||
mesa_loge("MESA: failed to import sync file '%s'", strerror(errno));
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
}
|
||||
|
||||
sem = zink_create_exportable_semaphore(screen);
|
||||
|
||||
const VkImportSemaphoreFdInfoKHR sdi = {
|
||||
.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR,
|
||||
.semaphore = sem,
|
||||
.flags = VK_SEMAPHORE_IMPORT_TEMPORARY_BIT,
|
||||
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||
.fd = export.fd,
|
||||
};
|
||||
bool success = VKSCR(ImportSemaphoreFdKHR)(screen->dev, &sdi) == VK_SUCCESS;
|
||||
close(fd);
|
||||
if (!success) {
|
||||
VKSCR(DestroySemaphore)(screen->dev, sem, NULL);
|
||||
return VK_NULL_HANDLE;
|
||||
}
|
||||
#endif
|
||||
return sem;
|
||||
}
|
||||
|
||||
bool
|
||||
zink_screen_import_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res, VkSemaphore sem)
|
||||
{
|
||||
#if defined(HAVE_LIBDRM) && (DETECT_OS_LINUX || DETECT_OS_BSD)
|
||||
const VkSemaphoreGetFdInfoKHR get_fd_info = {
|
||||
.sType = VK_STRUCTURE_TYPE_SEMAPHORE_GET_FD_INFO_KHR,
|
||||
.semaphore = sem,
|
||||
.handleType = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
|
||||
};
|
||||
int sync_file_fd = -1;
|
||||
VkResult result = VKSCR(GetSemaphoreFdKHR)(screen->dev, &get_fd_info, &sync_file_fd);
|
||||
if (result != VK_SUCCESS) {
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ret = false;
|
||||
int fd;
|
||||
VkMemoryGetFdInfoKHR fd_info = {0};
|
||||
fd_info.sType = VK_STRUCTURE_TYPE_MEMORY_GET_FD_INFO_KHR;
|
||||
fd_info.memory = zink_bo_get_mem(res->obj->bo);
|
||||
fd_info.handleType = VK_EXTERNAL_MEMORY_HANDLE_TYPE_DMA_BUF_BIT_EXT;
|
||||
if (VKSCR(GetMemoryFdKHR)(screen->dev, &fd_info, &fd) == VK_SUCCESS) {
|
||||
struct dma_buf_import_sync_file import = {
|
||||
.flags = DMA_BUF_SYNC_RW,
|
||||
.fd = sync_file_fd,
|
||||
};
|
||||
int ret = drmIoctl(fd, DMA_BUF_IOCTL_IMPORT_SYNC_FILE, &import);
|
||||
if (ret) {
|
||||
if (errno == ENOTTY || errno == EBADF || errno == ENOSYS) {
|
||||
assert(!"how did this fail?");
|
||||
} else {
|
||||
mesa_loge("MESA: failed to import sync file '%s'", strerror(errno));
|
||||
}
|
||||
} else {
|
||||
ret = true;
|
||||
}
|
||||
}
|
||||
|
||||
close(sync_file_fd);
|
||||
close(fd);
|
||||
return ret;
|
||||
#else
|
||||
return true;
|
||||
#endif
|
||||
}
|
||||
|
||||
bool
|
||||
zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout)
|
||||
{
|
||||
|
|
|
|||
|
|
@ -124,6 +124,10 @@ zink_screen_unlock_context(struct zink_screen *screen);
|
|||
|
||||
VkSemaphore
|
||||
zink_create_exportable_semaphore(struct zink_screen *screen);
|
||||
VkSemaphore
|
||||
zink_screen_export_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res);
|
||||
bool
|
||||
zink_screen_import_dmabuf_semaphore(struct zink_screen *screen, struct zink_resource *res, VkSemaphore sem);
|
||||
|
||||
VkFormat
|
||||
zink_get_format(struct zink_screen *screen, enum pipe_format format);
|
||||
|
|
|
|||
|
|
@ -364,6 +364,7 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res,
|
|||
}
|
||||
assert(new_layout);
|
||||
bool marker = zink_cmd_debug_marker_begin(ctx, cmdbuf, "image_barrier(%s->%s)", vk_ImageLayout_to_str(res->layout), vk_ImageLayout_to_str(new_layout));
|
||||
bool queue_import = false;
|
||||
if (HAS_SYNC2) {
|
||||
VkImageMemoryBarrier2 imb;
|
||||
zink_resource_image_barrier2_init(&imb, res, new_layout, flags, pipeline);
|
||||
|
|
@ -376,6 +377,7 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res,
|
|||
imb.srcQueueFamilyIndex = res->queue;
|
||||
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
||||
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
||||
queue_import = true;
|
||||
}
|
||||
VkDependencyInfo dep = {
|
||||
VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
||||
|
|
@ -401,6 +403,7 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res,
|
|||
imb.srcQueueFamilyIndex = res->queue;
|
||||
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
||||
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
||||
queue_import = true;
|
||||
}
|
||||
VKCTX(CmdPipelineBarrier)(
|
||||
cmdbuf,
|
||||
|
|
@ -427,6 +430,18 @@ zink_resource_image_barrier(struct zink_context *ctx, struct zink_resource *res,
|
|||
if (cdt->swapchain->num_acquires && res->obj->dt_idx != UINT32_MAX) {
|
||||
cdt->swapchain->images[res->obj->dt_idx].layout = res->layout;
|
||||
}
|
||||
} else if (res->obj->exportable) {
|
||||
struct pipe_resource *pres = NULL;
|
||||
bool found = false;
|
||||
_mesa_set_search_or_add(&ctx->batch.state->dmabuf_exports, res, &found);
|
||||
if (!found) {
|
||||
pipe_resource_reference(&pres, &res->base.b);
|
||||
}
|
||||
}
|
||||
if (res->obj->exportable && queue_import) {
|
||||
VkSemaphore sem = zink_screen_export_dmabuf_semaphore(zink_screen(ctx->base.screen), res);
|
||||
if (sem)
|
||||
util_dynarray_append(&ctx->batch.state->fd_wait_semaphores, VkSemaphore, sem);
|
||||
}
|
||||
if (new_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||
zink_resource_copies_reset(res);
|
||||
|
|
|
|||
|
|
@ -621,6 +621,7 @@ struct zink_batch_state {
|
|||
struct util_queue_fence flush_completed;
|
||||
|
||||
struct set programs;
|
||||
struct set dmabuf_exports;
|
||||
|
||||
#define BUFFER_HASHLIST_SIZE 32768
|
||||
/* buffer_indices_hashlist[hash(bo)] returns -1 if the bo
|
||||
|
|
|
|||
Loading…
Add table
Reference in a new issue