zink: move gfx shader init to thread

zink_shader_init is a long function, and making it async unblocks
the main app thread to improve startup/load times

this also eliminates a deserialize from separate shader compile by
linking up the lifetime of the nir_shader with the shader compilation

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28955>
This commit is contained in:
Mike Blumenkrantz
2024-04-25 07:38:15 -04:00
committed by Marge Bot
parent 450447257b
commit 921fbac6a3
2 changed files with 32 additions and 22 deletions
+1 -2
View File
@@ -4201,7 +4201,7 @@ zink_shader_compile(struct zink_screen *screen, bool can_shobj, struct zink_shad
struct zink_shader_object
zink_shader_compile_separate(struct zink_screen *screen, struct zink_shader *zs)
{
nir_shader *nir = zink_shader_deserialize(screen, zs);
nir_shader *nir = zs->nir;
/* TODO: maybe compile multiple variants for different set counts for compact mode? */
int set = zs->info.stage == MESA_SHADER_FRAGMENT;
if (screen->info.have_EXT_shader_object)
@@ -4255,7 +4255,6 @@ zink_shader_compile_separate(struct zink_screen *screen, struct zink_shader *zs)
zs->non_fs.generated_tcs->nir = NULL;
}
}
ralloc_free(nir);
spirv_shader_delete(obj.spirv);
obj.spirv = NULL;
return obj;
+31 -20
View File
@@ -1105,6 +1105,7 @@ zink_create_gfx_program(struct zink_context *ctx,
util_dynarray_init(&prog->shader_cache[i][1][1], prog);
if (stages[i]) {
prog->shaders[i] = stages[i];
util_queue_fence_wait(&stages[i]->precompile.fence);
prog->stages_present |= BITFIELD_BIT(i);
if (i != MESA_SHADER_FRAGMENT)
prog->optimal_keys &= !prog->shaders[i]->non_fs.is_generated;
@@ -2215,11 +2216,8 @@ zink_delete_shader_state(struct pipe_context *pctx, void *cso)
}
static void
precompile_separate_shader_job(void *data, void *gdata, int thread_index)
precompile_separate_shader(struct zink_shader *zs, struct zink_screen *screen)
{
struct zink_screen *screen = gdata;
struct zink_shader *zs = data;
zs->precompile.obj = zink_shader_compile_separate(screen, zs);
if (!screen->info.have_EXT_shader_object) {
struct zink_shader_object objs[ZINK_GFX_SHADER_COUNT] = {0};
@@ -2228,6 +2226,30 @@ precompile_separate_shader_job(void *data, void *gdata, int thread_index)
}
}
static void
gfx_shader_init_job(void *data, void *gdata, int thread_index)
{
struct zink_screen *screen = gdata;
struct zink_shader *zs = data;
zink_shader_init(screen, zs);
if (zink_debug & ZINK_DEBUG_NOPC) {
ralloc_free(zs->nir);
zs->nir = NULL;
return;
}
if (zs->info.separate_shader && zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB &&
(screen->info.have_EXT_shader_object ||
(screen->info.have_EXT_graphics_pipeline_library && (zs->info.stage == MESA_SHADER_FRAGMENT || zs->info.stage == MESA_SHADER_VERTEX)))) {
/* sample shading can't precompile */
if (zs->info.stage != MESA_SHADER_FRAGMENT || !zs->info.fs.uses_sample_shading)
precompile_separate_shader(zs, screen);
}
ralloc_free(zs->nir);
zs->nir = NULL;
}
void *
zink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader_state *shader)
{
@@ -2244,22 +2266,10 @@ zink_create_gfx_shader_state(struct pipe_context *pctx, const struct pipe_shader
zink_descriptors_init_bindless(zink_context(pctx));
struct zink_shader *zs = zink_shader_create(zink_screen(pctx->screen), nir);
zink_shader_init(zink_screen(pctx->screen), zs);
if (!(zink_debug & ZINK_DEBUG_NOPC)) {
if (nir->info.separate_shader && zink_descriptor_mode == ZINK_DESCRIPTOR_MODE_DB &&
(screen->info.have_EXT_shader_object ||
(screen->info.have_EXT_graphics_pipeline_library && (nir->info.stage == MESA_SHADER_FRAGMENT || nir->info.stage == MESA_SHADER_VERTEX)))) {
/* sample shading can't precompile */
if (nir->info.stage != MESA_SHADER_FRAGMENT || !nir->info.fs.uses_sample_shading) {
if (zink_debug & ZINK_DEBUG_NOBGC)
precompile_separate_shader_job(zs, screen, 0);
else
util_queue_add_job(&screen->cache_get_thread, zs, &zs->precompile.fence, precompile_separate_shader_job, NULL, 0);
}
}
}
ralloc_free(nir);
if (zink_debug & ZINK_DEBUG_NOBGC)
gfx_shader_init_job(zs, screen, 0);
else
util_queue_add_job(&screen->cache_get_thread, zs, &zs->precompile.fence, gfx_shader_init_job, NULL, 0);
return zs;
}
@@ -2513,6 +2523,7 @@ zink_set_primitive_emulation_keys(struct zink_context *ctx)
ctx->gfx_stages[MESA_SHADER_GEOMETRY]->info.gs.input_primitive != ctx->gfx_pipeline_state.gfx_prim_mode)) {
if (!ctx->gfx_stages[prev_vertex_stage]->non_fs.generated_gs[ctx->gfx_pipeline_state.gfx_prim_mode][zink_prim_type]) {
util_queue_fence_wait(&ctx->gfx_stages[prev_vertex_stage]->precompile.fence);
nir_shader *prev_stage = zink_shader_deserialize(screen, ctx->gfx_stages[prev_vertex_stage]);
nir_shader *nir;
if (lower_filled_quad) {