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->resource_size = 0;
bs->signal_semaphore = VK_NULL_HANDLE; bs->signal_semaphore = VK_NULL_HANDLE;
bs->sparse_semaphore = VK_NULL_HANDLE;
util_dynarray_clear(&bs->wait_semaphore_stages); util_dynarray_clear(&bs->wait_semaphore_stages);
bs->present = VK_NULL_HANDLE; 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 */ /* first submit is just for acquire waits since they have a separate array */
for (unsigned i = 0; i < ARRAY_SIZE(si); i++) for (unsigned i = 0; i < ARRAY_SIZE(si); i++)
si[i].sType = VK_STRUCTURE_TYPE_SUBMIT_INFO; 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].waitSemaphoreCount = util_dynarray_num_elements(&bs->acquires, VkSemaphore);
si[ZINK_SUBMIT_WAIT_ACQUIRE].pWaitSemaphores = bs->acquires.data; si[ZINK_SUBMIT_WAIT_ACQUIRE].pWaitSemaphores = bs->acquires.data;
while (util_dynarray_num_elements(&bs->acquire_flags, VkPipelineStageFlags) < si[ZINK_SUBMIT_WAIT_ACQUIRE].waitSemaphoreCount) { 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); _mesa_set_clear(&bs->dmabuf_exports, NULL);
if (bs->sparse_semaphore)
(void)util_dynarray_pop(&ctx->bs->acquires, VkSemaphore);
bs->usage.submit_count++; bs->usage.submit_count++;
end: end:
cnd_broadcast(&bs->usage.flush); 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); 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 static bool
batch_ptr_add_usage(struct zink_context *ctx, struct set *s, void *ptr) 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 void
zink_end_batch(struct zink_context *ctx); zink_end_batch(struct zink_context *ctx);
void
zink_batch_add_wait_semaphore(struct zink_context *ctx, VkSemaphore sem);
void void
zink_batch_reference_resource_rw(struct zink_context *ctx, zink_batch_reference_resource_rw(struct zink_context *ctx,
struct zink_resource *res, 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; ok = false;
goto out; 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, cur_sem = buffer_commit_single(screen, res, backing->bo, backing_start,
(uint64_t)span_va_page * ZINK_SPARSE_BUFFER_PAGE_SIZE, (uint64_t)span_va_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
(uint64_t)backing_size * ZINK_SPARSE_BUFFER_PAGE_SIZE, true, cur_sem); (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); ok = sparse_backing_free(screen, bo, backing, backing_start, backing_size);
assert(ok && "sufficient memory should already be allocated"); 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 (!done) {
if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, cur_sem);
cur_sem = buffer_commit_single(screen, res, NULL, 0, cur_sem = buffer_commit_single(screen, res, NULL, 0,
(uint64_t)base_page * ZINK_SPARSE_BUFFER_PAGE_SIZE, (uint64_t)base_page * ZINK_SPARSE_BUFFER_PAGE_SIZE,
(uint64_t)(end_va_page - base_page) * ZINK_SPARSE_BUFFER_PAGE_SIZE, false, cur_sem); (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; ok = false;
goto out; goto out;
} }
@ -972,7 +972,7 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
bool ok = true; bool ok = true;
struct zink_screen *screen = zink_screen(ctx->base.screen); struct zink_screen *screen = zink_screen(ctx->base.screen);
struct zink_bo *bo = res->obj->bo; 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(&screen->queue_lock);
simple_mtx_lock(&bo->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) { if (level >= res->sparse.imageMipTailFirstLod) {
uint32_t offset = res->sparse.imageMipTailOffset; 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); 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++; res->obj->miptail_commits++;
else } else {
ok = false; ok = false;
}
goto out; goto out;
} else { } else {
ibind[i].memory = backing[i]->bo->mem ? backing[i]->bo->mem : backing[i]->bo->u.slab.real->mem; 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); assert(res->obj->miptail_commits);
res->obj->miptail_commits--; res->obj->miptail_commits--;
if (!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) if (cur_sem)
util_dynarray_append(&ctx->bs->tracked_semaphores, VkSemaphore, 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); else
if (!cur_sem)
ok = false; ok = false;
} }
goto out; 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 (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); 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++) { for (unsigned s = 0; s < i; s++) {
ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]); ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
if (!ok) { if (!ok) {
@ -1167,10 +1167,10 @@ zink_bo_commit(struct zink_context *ctx, struct zink_resource *res, unsigned lev
} }
} }
if (commits_pending) { 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); 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++) { for (unsigned s = 0; s < i; s++) {
ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]); ok = sparse_backing_free(screen, backing[s]->bo, backing[s], backing_start[s], backing_size[s]);
if (!ok) { 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)) if (zink_resource_has_unflushed_usage(res))
zink_flush_queue(ctx); zink_flush_queue(ctx);
VkSemaphore sem = VK_NULL_HANDLE; bool ret = zink_bo_commit(ctx, res, level, box, commit, &ctx->bs->sparse_semaphore);
bool ret = zink_bo_commit(ctx, res, level, box, commit, &sem);
if (ret) { if (ret) {
if (sem) { zink_batch_reference_resource_rw(ctx, res, true);
zink_batch_add_wait_semaphore(ctx, sem); ctx->bs->has_work = true;
zink_batch_reference_resource_rw(ctx, res, true);
ctx->bs->has_work = true;
}
} else { } else {
check_device_lost(ctx); 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_semaphores; //dmabuf wait semaphores
struct util_dynarray fd_wait_semaphore_stages; //dmabuf wait semaphores struct util_dynarray fd_wait_semaphore_stages; //dmabuf wait semaphores
struct util_dynarray tracked_semaphores; //semaphores which are just tracked 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 struct util_dynarray fences; //zink_tc_fence refs
simple_mtx_t ref_lock; simple_mtx_t ref_lock;