zink: defer batch state resets more competently
previously batch states would defer resource object destruction until "later", which was somewhat unreliable in the event that the batch state wasn't checked again for a long while instead, defer all "large" batch states and then reset them in the submit thread, which should yield more consistent results, including in scenarios with multiple contexts in use Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37068>
This commit is contained in:
committed by
Marge Bot
parent
6dd081ab1b
commit
067873d4a4
@@ -56,12 +56,10 @@ reset_obj_list(struct zink_screen *screen, struct zink_batch_state *bs, struct z
|
||||
}
|
||||
|
||||
/* reset a given batch state */
|
||||
void
|
||||
zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
static void
|
||||
reset_batch_state_internal(struct zink_screen *screen, struct zink_batch_state *bs)
|
||||
{
|
||||
MESA_TRACE_FUNC();
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
|
||||
VkResult result = VKSCR(ResetCommandPool)(screen->dev, bs->cmdpool, 0);
|
||||
if (result != VK_SUCCESS)
|
||||
mesa_loge("ZINK: vkResetCommandPool failed (%s)", vk_Result_to_str(result));
|
||||
@@ -83,16 +81,6 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
reset_obj(screen, bs, obj);
|
||||
}
|
||||
|
||||
/* this is where bindless texture/buffer ids get recycled */
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
while (util_dynarray_contains(&bs->bindless_releases[i], uint32_t)) {
|
||||
uint32_t handle = util_dynarray_pop(&bs->bindless_releases[i], uint32_t);
|
||||
bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
|
||||
struct util_idalloc *ids = i ? &ctx->di.bindless[is_buffer].img_slots : &ctx->di.bindless[is_buffer].tex_slots;
|
||||
util_idalloc_free(ids, is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle);
|
||||
}
|
||||
}
|
||||
|
||||
/* queries must only be destroyed once they are inactive */
|
||||
set_foreach_remove(&bs->active_queries, entry) {
|
||||
struct zink_query *query = (void*)entry->key;
|
||||
@@ -179,6 +167,20 @@ zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
bs->has_unsync = false;
|
||||
}
|
||||
|
||||
static void
|
||||
reset_batch_state_ctx(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
{
|
||||
/* this is where bindless texture/buffer ids get recycled */
|
||||
for (unsigned i = 0; i < 2; i++) {
|
||||
while (util_dynarray_contains(&bs->bindless_releases[i], uint32_t)) {
|
||||
uint32_t handle = util_dynarray_pop(&bs->bindless_releases[i], uint32_t);
|
||||
bool is_buffer = ZINK_BINDLESS_IS_BUFFER(handle);
|
||||
struct util_idalloc *ids = i ? &ctx->di.bindless[is_buffer].img_slots : &ctx->di.bindless[is_buffer].tex_slots;
|
||||
util_idalloc_free(ids, is_buffer ? handle - ZINK_MAX_BINDLESS_HANDLES : handle);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* this is where deferred resource unrefs occur */
|
||||
static void
|
||||
unref_resources(struct zink_screen *screen, struct zink_batch_state *bs)
|
||||
@@ -190,6 +192,15 @@ unref_resources(struct zink_screen *screen, struct zink_batch_state *bs)
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
zink_reset_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
{
|
||||
struct zink_screen *screen = zink_screen(ctx->base.screen);
|
||||
reset_batch_state_ctx(ctx, bs);
|
||||
reset_batch_state_internal(screen, bs);
|
||||
unref_resources(screen, bs);
|
||||
}
|
||||
|
||||
/* utility for resetting a batch state; called on context destruction */
|
||||
void
|
||||
zink_clear_batch_state(struct zink_context *ctx, struct zink_batch_state *bs)
|
||||
@@ -437,15 +448,17 @@ find_completed_batch_state(struct zink_context *ctx)
|
||||
struct zink_batch_state *bs = NULL;
|
||||
|
||||
/* states are stored sequentially, so if the first one doesn't work, none of them will */
|
||||
for (struct zink_batch_state *i = ctx->batch_states; i; i = i->next) {
|
||||
for (struct zink_batch_state *i = ctx->batch_states, *j = i ? i->next : NULL; i; i = j, j = j ? j->next : NULL) {
|
||||
/* only a submitted state can be reused */
|
||||
if (p_atomic_read(&i->fence.submitted) &&
|
||||
/* a submitted state must have completed before it can be reused */
|
||||
(zink_screen_check_last_finished(screen, i->fence.batch_id) ||
|
||||
p_atomic_read(&i->fence.completed))) {
|
||||
pop_batch_state(ctx);
|
||||
zink_reset_batch_state(ctx, bs);
|
||||
return i;
|
||||
reset_batch_state_ctx(ctx, i);
|
||||
simple_mtx_lock(&screen->active_batch_states_lock);
|
||||
zink_batch_state_append(&screen->active_batch_states, &screen->last_active_batch_state, i);
|
||||
simple_mtx_unlock(&screen->active_batch_states_lock);
|
||||
} else {
|
||||
return bs;
|
||||
}
|
||||
@@ -811,7 +824,18 @@ end:
|
||||
cnd_broadcast(&bs->usage.flush);
|
||||
|
||||
p_atomic_set(&bs->fence.submitted, true);
|
||||
unref_resources(screen, bs);
|
||||
|
||||
simple_mtx_lock(&screen->active_batch_states_lock);
|
||||
simple_mtx_lock(&screen->free_batch_states_lock);
|
||||
for (struct zink_batch_state *i = screen->active_batch_states, *j = i ? i->next : NULL; i; i = j, j = j ? j->next : NULL) {
|
||||
reset_batch_state_internal(screen, i);
|
||||
unref_resources(screen, i);
|
||||
zink_batch_state_append(&screen->free_batch_states, &screen->last_free_batch_state, i);
|
||||
}
|
||||
screen->active_batch_states = NULL;
|
||||
screen->last_active_batch_state = NULL;
|
||||
simple_mtx_unlock(&screen->free_batch_states_lock);
|
||||
simple_mtx_unlock(&screen->active_batch_states_lock);
|
||||
}
|
||||
|
||||
/* called during flush */
|
||||
|
||||
@@ -1474,6 +1474,12 @@ zink_destroy_screen(struct pipe_screen *pscreen)
|
||||
zink_batch_state_destroy(screen, bs);
|
||||
bs = bs_next;
|
||||
}
|
||||
bs = screen->active_batch_states;
|
||||
while (bs) {
|
||||
struct zink_batch_state *bs_next = bs->next;
|
||||
zink_batch_state_destroy(screen, bs);
|
||||
bs = bs_next;
|
||||
}
|
||||
|
||||
if (VK_NULL_HANDLE != screen->debugUtilsCallbackHandle) {
|
||||
VKSCR(DestroyDebugUtilsMessengerEXT)(screen->instance, screen->debugUtilsCallbackHandle, NULL);
|
||||
@@ -3658,6 +3664,7 @@ zink_internal_create_screen(const struct pipe_screen_config *config, int64_t dev
|
||||
}
|
||||
|
||||
simple_mtx_init(&screen->free_batch_states_lock, mtx_plain);
|
||||
simple_mtx_init(&screen->active_batch_states_lock, mtx_plain);
|
||||
simple_mtx_init(&screen->dt_lock, mtx_plain);
|
||||
|
||||
util_idalloc_mt_init_tc(&screen->buffer_ids);
|
||||
|
||||
@@ -1369,6 +1369,10 @@ struct zink_screen {
|
||||
struct zink_batch_state *last_free_batch_state; //for appending
|
||||
simple_mtx_t free_batch_states_lock;
|
||||
|
||||
struct zink_batch_state *active_batch_states; //active batch states
|
||||
struct zink_batch_state *last_active_batch_state; //for appending
|
||||
simple_mtx_t active_batch_states_lock;
|
||||
|
||||
simple_mtx_t semaphores_lock;
|
||||
struct util_dynarray semaphores;
|
||||
struct util_dynarray fd_semaphores;
|
||||
|
||||
Reference in New Issue
Block a user