zink: rework sparse semaphore waits

previously this reused the swapchain acquire array to add wait
semaphores, but doing so failed to synchronize between successive
API commits

instead, track a single wait semaphore on the batch which can be
updated/reused across all sparse operations, though this has the
unfortunate side effect of synchronizing sparse binds for unrelated
resources

Closes: https://gitlab.freedesktop.org/mesa/mesa/-/issues/10137
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/29152>
This commit is contained in:
Mike Blumenkrantz 2024-05-09 11:41:34 -04:00 committed by Marge Bot
parent f339f1e7ad
commit 63e17ccc0a
5 changed files with 29 additions and 35 deletions

View file

@ -152,6 +152,7 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
bs->resource_size = 0;
bs->signal_semaphore = VK_NULL_HANDLE;
bs->sparse_semaphore = VK_NULL_HANDLE;
util_dynarray_clear(&bs->wait_semaphore_stages);
bs->present = VK_NULL_HANDLE;
@ -649,6 +650,8 @@ submit_queue(void *data, void *gdata, int thread_index)
/* first submit is just for acquire waits since they have a separate array */
for (unsigned i = 0; i < ARRAY_SIZE(si); i++)
si[i].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO;
if (bs->sparse_semaphore)
util_dynarray_append(&ctx->bs->acquires, VkSemaphore, bs->sparse_semaphore);
si[ZINK_SUBMIT_WAIT_ACQUIRE].waitSemaphoreCount = util_dynarray_num_elements(&bs->acquires, VkSemaphore);
si[ZINK_SUBMIT_WAIT_ACQUIRE].pWaitSemaphores = bs->acquires.data;
while (util_dynarray_num_elements(&bs->acquire_flags, VkPipelineStageFlags) < si[ZINK_SUBMIT_WAIT_ACQUIRE].waitSemaphoreCount) {
@ -781,6 +784,9 @@ submit_queue(void *data, void *gdata, int thread_index)
}
_mesa_set_clear(&bs->dmabuf_exports, NULL);
if (bs->sparse_semaphore)
(void)util_dynarray_pop(&ctx->bs->acquires, VkSemaphore);
bs->usage.submit_count++;
end:
cnd_broadcast(&bs->usage.flush);
@ -960,12 +966,6 @@ zink_batch_reference_resource_rw(struct zink_context *ctx, struct zink_resource
zink_batch_resource_usage_set(ctx->bs, res, write, res->obj->is_buffer);
}
void
zink_batch_add_wait_semaphore(struct zink_context *ctx, VkSemaphore sem)
{
util_dynarray_append(&ctx->bs->acquires, VkSemaphore, sem);
}
static bool
batch_ptr_add_usage(struct zink_context *ctx, struct set *s, void *ptr)
{

View file

@ -61,9 +61,6 @@ zink_start_batch(struct zink_context *ctx);
void
zink_end_batch(struct zink_context *ctx);
void
zink_batch_add_wait_semaphore(struct zink_context *ctx, VkSemaphore sem);
void
zink_batch_reference_resource_rw(struct zink_context *ctx,
struct zink_resource *res,

View file

@ -831,12 +831,12 @@ buffer_bo_commit(struct zink_context *ctx, struct zink_resource *res, uint32_t o
ok = false;
goto out;
}
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = buffer_commit_single(screen, res, backing->bo, backing_start,
(uint64_t)span_va_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
(uint64_t)backing_size * ZINK_SPARSE_BUFFER_PAGE_SIZE, true, cur_sem);
if (!cur_sem) {
if (cur_sem) {
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
} else {
ok = sparse_backing_free(screen, bo, backing, backing_start, backing_size);
assert(ok && "sufficient memory should already be allocated");
@ -868,12 +868,12 @@ buffer_bo_commit(struct zink_context *ctx, struct zink_resource *res, uint32_t o
}
if (!done) {
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = buffer_commit_single(screen, res, NULL, 0,
(uint64_t)base_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
(uint64_t)(end_va_page - base_page) * ZINK_SPARSE_BUFFER_PAGE_SIZE, false, cur_sem);
if (!cur_sem) {
if (cur_sem) {
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
} else {
ok = false;
goto out;
}
@ -972,7 +972,7 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
bool ok = true;
struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_bo *bo = res->obj->bo;
VkSemaphore cur_sem = VK_NULL_HANDLE;
VkSemaphore cur_sem = *sem;
simple_mtx_lock(&screen->queue_lock);
simple_mtx_lock(&bo->lock);
@ -1076,13 +1076,13 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
}
if (level >= res->sparse.imageMipTailFirstLod) {
uint32_t offset = res->sparse.imageMipTailOffset;
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = texture_commit_miptail(screen, res, backing[i]->bo, backing_start[i], offset, commit, cur_sem);
if (cur_sem)
if (cur_sem) {
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
res->obj->miptail_commits++;
else
} else {
ok = false;
}
goto out;
} else {
ibind[i].memory = backing[i]->bo->mem ? backing[i]->bo->mem : backing[i]->bo->u.slab.real->mem;
@ -1132,10 +1132,10 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
assert(res->obj->miptail_commits);
res->obj->miptail_commits--;
if (!res->obj->miptail_commits) {
cur_sem = texture_commit_miptail(screen, res, NULL, 0, offset, commit, cur_sem);
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = texture_commit_miptail(screen, res, NULL, 0, offset, commit, cur_sem);
if (!cur_sem)
else
ok = false;
}
goto out;
@ -1146,10 +1146,10 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
}
}
if (i == ARRAY_SIZE(ibind)) {
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = texture_commit_single(screen, res, ibind, ARRAY_SIZE(ibind), commit, cur_sem);
if (!cur_sem) {
if (cur_sem) {
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
} else {
for (unsigned s = 0; s < i; s++) {
ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
if (!ok) {
@ -1167,10 +1167,10 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
}
}
if (commits_pending) {
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = texture_commit_single(screen, res, ibind, i, commit, cur_sem);
if (!cur_sem) {
if (cur_sem) {
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
} else {
for (unsigned s = 0; s < i; s++) {
ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
if (!ok) {

View file

@ -4855,14 +4855,10 @@ zink_resource_commit(struct pipe_context *pctx, struct pipe_resource *pres, unsi
if (zink_resource_has_unflushed_usage(res))
zink_flush_queue(ctx);
VkSemaphore sem = VK_NULL_HANDLE;
bool ret = zink_bo_commit(ctx, res, level, box, commit, &sem);
bool ret = zink_bo_commit(ctx, res, level, box, commit, &ctx->bs->sparse_semaphore);
if (ret) {
if (sem) {
zink_batch_add_wait_semaphore(ctx, sem);
zink_batch_reference_resource_rw(ctx, res, true);
ctx->bs->has_work = true;
}
zink_batch_reference_resource_rw(ctx, res, true);
ctx->bs->has_work = true;
} else {
check_device_lost(ctx);
}

View file

@ -611,6 +611,7 @@ struct zink_batch_state {
struct util_dynarray fd_wait_semaphores; //dmabuf wait semaphores
struct util_dynarray fd_wait_semaphore_stages; //dmabuf wait semaphores
struct util_dynarray tracked_semaphores; //semaphores which are just tracked
VkSemaphore sparse_semaphore; //current sparse wait semaphore
struct util_dynarray fences; //zink_tc_fence refs
simple_mtx_t ref_lock;