mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2026-05-05 18:18:06 +02: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->programs);
|
||||||
SET_CREATE_OR_FAIL(&bs->active_queries);
|
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->signal_semaphores, NULL);
|
||||||
util_dynarray_init(&bs->wait_semaphores, NULL);
|
util_dynarray_init(&bs->wait_semaphores, NULL);
|
||||||
util_dynarray_init(&bs->fd_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));
|
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_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) {
|
if (si[ZINK_SUBMIT_WAIT_ACQUIRE].waitSemaphoreCount == 0) {
|
||||||
num_si--;
|
num_si--;
|
||||||
submit++;
|
submit++;
|
||||||
|
|
@ -621,6 +631,10 @@ submit_queue(void *data, void *gdata, int thread_index)
|
||||||
signals[si[ZINK_SUBMIT_CMDBUF].signalSemaphoreCount++] = bs->present;
|
signals[si[ZINK_SUBMIT_CMDBUF].signalSemaphoreCount++] = bs->present;
|
||||||
tsi.signalSemaphoreValueCount = si[ZINK_SUBMIT_CMDBUF].signalSemaphoreCount;
|
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);
|
VkResult result = VKSCR(EndCommandBuffer)(bs->cmdbuf);
|
||||||
if (result != VK_SUCCESS) {
|
if (result != VK_SUCCESS) {
|
||||||
mesa_loge("ZINK: vkEndCommandBuffer failed (%s)", vk_Result_to_str(result));
|
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;
|
bs->is_device_lost = true;
|
||||||
}
|
}
|
||||||
simple_mtx_unlock(&screen->queue_lock);
|
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++;
|
bs->usage.submit_count++;
|
||||||
end:
|
end:
|
||||||
cnd_broadcast(&bs->usage.flush);
|
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);
|
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) {
|
if (screen->threaded_submit) {
|
||||||
util_queue_add_job(&screen->flush_queue, bs, &bs->flush_completed,
|
util_queue_add_job(&screen->flush_queue, bs, &bs->flush_completed,
|
||||||
submit_queue, post_submit, 0);
|
submit_queue, post_submit, 0);
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,7 @@ bool zink_tracing = false;
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
#ifdef HAVE_LIBDRM
|
#ifdef HAVE_LIBDRM
|
||||||
|
#include "drm-uapi/dma-buf.h"
|
||||||
#include <xf86drm.h>
|
#include <xf86drm.h>
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
@ -2199,6 +2200,99 @@ zink_create_exportable_semaphore(struct zink_screen *screen)
|
||||||
return ret == VK_SUCCESS ? sem : VK_NULL_HANDLE;
|
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
|
bool
|
||||||
zink_screen_timeline_wait(struct zink_screen *screen, uint64_t batch_id, uint64_t timeout)
|
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
|
VkSemaphore
|
||||||
zink_create_exportable_semaphore(struct zink_screen *screen);
|
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
|
VkFormat
|
||||||
zink_get_format(struct zink_screen *screen, enum pipe_format format);
|
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);
|
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 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) {
|
if (HAS_SYNC2) {
|
||||||
VkImageMemoryBarrier2 imb;
|
VkImageMemoryBarrier2 imb;
|
||||||
zink_resource_image_barrier2_init(&imb, res, new_layout, flags, pipeline);
|
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.srcQueueFamilyIndex = res->queue;
|
||||||
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
||||||
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
queue_import = true;
|
||||||
}
|
}
|
||||||
VkDependencyInfo dep = {
|
VkDependencyInfo dep = {
|
||||||
VK_STRUCTURE_TYPE_DEPENDENCY_INFO,
|
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.srcQueueFamilyIndex = res->queue;
|
||||||
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
imb.dstQueueFamilyIndex = zink_screen(ctx->base.screen)->gfx_queue;
|
||||||
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
res->queue = VK_QUEUE_FAMILY_IGNORED;
|
||||||
|
queue_import = true;
|
||||||
}
|
}
|
||||||
VKCTX(CmdPipelineBarrier)(
|
VKCTX(CmdPipelineBarrier)(
|
||||||
cmdbuf,
|
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) {
|
if (cdt->swapchain->num_acquires && res->obj->dt_idx != UINT32_MAX) {
|
||||||
cdt->swapchain->images[res->obj->dt_idx].layout = res->layout;
|
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)
|
if (new_layout != VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL)
|
||||||
zink_resource_copies_reset(res);
|
zink_resource_copies_reset(res);
|
||||||
|
|
|
||||||
|
|
@ -621,6 +621,7 @@ struct zink_batch_state {
|
||||||
struct util_queue_fence flush_completed;
|
struct util_queue_fence flush_completed;
|
||||||
|
|
||||||
struct set programs;
|
struct set programs;
|
||||||
|
struct set dmabuf_exports;
|
||||||
|
|
||||||
#define BUFFER_HASHLIST_SIZE 32768
|
#define BUFFER_HASHLIST_SIZE 32768
|
||||||
/* buffer_indices_hashlist[hash(bo)] returns -1 if the bo
|
/* buffer_indices_hashlist[hash(bo)] returns -1 if the bo
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue