zink: implement GL semaphores

this is basically just a wrapper around vulkan semaphores, so it maps
fairly well

the existing fence function was a big ??? and should never have been triggered
like it was

Reviewed-by: Dave Airlie <airlied@redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14498>
This commit is contained in:
Mike Blumenkrantz 2022-01-11 13:57:00 -05:00 committed by Marge Bot
parent 29285a0e85
commit 32597e116d
5 changed files with 84 additions and 14 deletions

View File

@ -96,6 +96,9 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
pipe_resource_reference(&bs->flush_res, NULL);
bs->resource_size = 0;
bs->signal_semaphore = VK_NULL_HANDLE;
util_dynarray_clear(&bs->wait_semaphores);
util_dynarray_clear(&bs->wait_semaphore_stages);
/* only reset submitted here so that tc fence desync can pick up the 'completed' flag
* before the state is reused
@ -222,6 +225,8 @@ create_batch_state(struct zink_context *ctx)
SET_CREATE_OR_FAIL(bs->bufferviews);
SET_CREATE_OR_FAIL(bs->programs);
SET_CREATE_OR_FAIL(bs->active_queries);
util_dynarray_init(&bs->wait_semaphores, NULL);
util_dynarray_init(&bs->wait_semaphore_stages, NULL);
util_dynarray_init(&bs->zombie_samplers, NULL);
util_dynarray_init(&bs->dead_framebuffers, NULL);
util_dynarray_init(&bs->persistent_resources, NULL);
@ -369,11 +374,9 @@ submit_queue(void *data, void *gdata, int thread_index)
uint64_t batch_id = bs->fence.batch_id;
si.sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
si.waitSemaphoreCount = 0;
si.pWaitSemaphores = NULL;
si.signalSemaphoreCount = 0;
si.pSignalSemaphores = NULL;
si.pWaitDstStageMask = NULL;
si.waitSemaphoreCount = util_dynarray_num_elements(&bs->wait_semaphores, VkSemaphore);
si.pWaitSemaphores = bs->wait_semaphores.data;
si.pWaitDstStageMask = bs->wait_semaphore_stages.data;
si.commandBufferCount = bs->has_barriers ? 2 : 1;
VkCommandBuffer cmdbufs[2] = {
bs->barrier_cmdbuf,
@ -381,14 +384,17 @@ submit_queue(void *data, void *gdata, int thread_index)
};
si.pCommandBuffers = bs->has_barriers ? cmdbufs : &cmdbufs[1];
VkSemaphore signals[2];
si.signalSemaphoreCount = !!bs->signal_semaphore;
signals[0] = bs->signal_semaphore;
si.pSignalSemaphores = signals;
VkTimelineSemaphoreSubmitInfo tsi = {0};
if (bs->have_timelines) {
tsi.sType = VK_STRUCTURE_TYPE_TIMELINE_SEMAPHORE_SUBMIT_INFO;
si.pNext = &tsi;
tsi.signalSemaphoreValueCount = 1;
tsi.pSignalSemaphoreValues = &batch_id;
si.signalSemaphoreCount = 1;
si.pSignalSemaphores = &screen->sem;
signals[si.signalSemaphoreCount++] = screen->sem;
}
struct wsi_memory_signal_submit_info mem_signal = {

View File

@ -68,6 +68,9 @@ struct zink_batch_state {
VkCommandPool cmdpool;
VkCommandBuffer cmdbuf;
VkCommandBuffer barrier_cmdbuf;
VkSemaphore signal_semaphore; //external signal semaphore
struct util_dynarray wait_semaphores; //external wait semaphores
struct util_dynarray wait_semaphore_stages; //external wait semaphores
VkQueue queue; //duplicated from batch for threading
VkSemaphore sem;

View File

@ -4115,7 +4115,9 @@ zink_context_create(struct pipe_screen *pscreen, void *priv, unsigned flags)
ctx->base.clear_render_target = zink_clear_render_target;
ctx->base.clear_depth_stencil = zink_clear_depth_stencil;
ctx->base.create_fence_fd = zink_create_fence_fd;
ctx->base.fence_server_sync = zink_fence_server_sync;
ctx->base.fence_server_signal = zink_fence_server_signal;
ctx->base.flush = zink_flush;
ctx->base.memory_barrier = zink_memory_barrier;
ctx->base.texture_barrier = zink_texture_barrier;

View File

@ -36,6 +36,7 @@ destroy_fence(struct zink_screen *screen, struct zink_tc_fence *mfence)
{
mfence->fence = NULL;
tc_unflushed_batch_token_reference(&mfence->tc_token, NULL);
VKSCR(DestroySemaphore)(screen->dev, mfence->sem, NULL);
FREE(mfence);
}
@ -196,20 +197,73 @@ fence_finish(struct pipe_screen *pscreen, struct pipe_context *pctx,
timeout_ns);
}
void
zink_fence_server_signal(struct pipe_context *pctx, struct pipe_fence_handle *pfence)
{
struct zink_context *ctx = zink_context(pctx);
struct zink_tc_fence *mfence = (struct zink_tc_fence *)pfence;
assert(!ctx->batch.state->signal_semaphore);
/* this is a deferred flush to reduce overhead */
ctx->batch.state->signal_semaphore = mfence->sem;
pctx->flush(pctx, NULL, PIPE_FLUSH_ASYNC);
}
void
zink_fence_server_sync(struct pipe_context *pctx, struct pipe_fence_handle *pfence)
{
struct zink_tc_fence *mfence = zink_tc_fence(pfence);
struct zink_context *ctx = zink_context(pctx);
struct zink_tc_fence *mfence = (struct zink_tc_fence *)pfence;
if (mfence->deferred_ctx == pctx)
if (mfence->deferred_ctx == pctx || !mfence->sem)
return;
if (mfence->deferred_ctx) {
zink_context(pctx)->batch.has_work = true;
/* this must be the current batch */
pctx->flush(pctx, NULL, 0);
mfence->deferred_ctx = pctx;
/* this will be applied on the next submit */
VkPipelineStageFlags flag = VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
util_dynarray_append(&ctx->batch.state->wait_semaphores, VkSemaphore, mfence->sem);
util_dynarray_append(&ctx->batch.state->wait_semaphore_stages, VkPipelineStageFlags, flag);
}
void
zink_create_fence_fd(struct pipe_context *pctx, struct pipe_fence_handle **pfence, int fd, enum pipe_fd_type type)
{
struct zink_screen *screen = zink_screen(pctx->screen);
VkResult ret = VK_ERROR_UNKNOWN;
VkSemaphoreCreateInfo sci = {
VK_STRUCTURE_TYPE_SEMAPHORE_CREATE_INFO,
NULL,
0
};
struct zink_tc_fence *mfence = zink_create_tc_fence();
VkExternalSemaphoreHandleTypeFlagBits flags[] = {
[PIPE_FD_TYPE_NATIVE_SYNC] = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_SYNC_FD_BIT,
[PIPE_FD_TYPE_SYNCOBJ] = VK_EXTERNAL_SEMAPHORE_HANDLE_TYPE_OPAQUE_FD_BIT,
};
VkImportSemaphoreFdInfoKHR sdi = {0};
assert(type < ARRAY_SIZE(flags));
*pfence = NULL;
if (VKSCR(CreateSemaphore)(screen->dev, &sci, NULL, &mfence->sem) != VK_SUCCESS) {
FREE(mfence);
return;
}
zink_fence_finish(zink_screen(pctx->screen), pctx, mfence, PIPE_TIMEOUT_INFINITE);
sdi.sType = VK_STRUCTURE_TYPE_IMPORT_SEMAPHORE_FD_INFO_KHR;
sdi.semaphore = mfence->sem;
sdi.handleType = flags[type];
sdi.fd = fd;
ret = VKSCR(ImportSemaphoreFdKHR)(screen->dev, &sdi);
if (!zink_screen_handle_vkresult(screen, ret))
goto fail;
*pfence = (struct pipe_fence_handle *)mfence;
return;
fail:
VKSCR(DestroySemaphore)(screen->dev, mfence->sem, NULL);
FREE(mfence);
}
void

View File

@ -46,6 +46,7 @@ struct zink_tc_fence {
struct tc_unflushed_batch_token *tc_token;
struct pipe_context *deferred_ctx;
struct zink_fence *fence;
VkSemaphore sem;
};
struct zink_fence {
@ -78,6 +79,10 @@ zink_fence_reference(struct zink_screen *screen,
struct zink_tc_fence **ptr,
struct zink_tc_fence *fence);
void
zink_create_fence_fd(struct pipe_context *pctx, struct pipe_fence_handle **pfence, int fd, enum pipe_fd_type type);
void
zink_fence_server_signal(struct pipe_context *pctx, struct pipe_fence_handle *pfence);
void
zink_fence_server_sync(struct pipe_context *pctx, struct pipe_fence_handle *pfence);