From 654efa44e3b895549c06b9842a2384d9e7bf43e6 Mon Sep 17 00:00:00 2001 From: Pierre-Eric Pelloux-Prayer Date: Tue, 29 Jul 2025 10:12:41 +0200 Subject: [PATCH] mesa/st: always use base_serialized_nir for draw MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit f2f640f35 introduces base variants, so we get 2 NIR shaders: glsl-to-nir -> base_serialized_nir -> serialized_nir Then, depending on who is using the shader the right one would be picked: * draw uses base_serialized_nir * hw driver uses serialized_nir ef0c9231a75 made sure that base wasn't used when the shader is loaded from the cache because it's missing, so in this case, glsl-to-nir does: glsl-to-nir -> from-cache -> serialized_nir The problem is that if draw tries to use this shader it may fail, for the same reason as the referenced commits were introduced: draw may not be compatible with some NIR passes used by the driver. To fix this we need to serialize both NIR shaders, and pick the right one depending on the user. Fixes: ef0c9231a75 ("mesa/st: don't use serialized_nir for cached shaders") Reviewed-by: Marek Olšák Part-of: (cherry picked from commit 0e3ec9e82ca27844dac7b1ce4aff7a65332181f2) --- .pick_status.json | 2 +- src/mesa/state_tracker/st_program.c | 6 ++++-- src/mesa/state_tracker/st_shader_cache.c | 8 ++++++++ 3 files changed, 13 insertions(+), 3 deletions(-) diff --git a/.pick_status.json b/.pick_status.json index dfaa84543bb..3d8ed168bbf 100644 --- a/.pick_status.json +++ b/.pick_status.json @@ -5364,7 +5364,7 @@ "description": "mesa/st: always use base_serialized_nir for draw", "nominated": true, "nomination_type": 2, - "resolution": 0, + "resolution": 1, "main_sha": null, "because_sha": "ef0c9231a75e78fcf49436d2cfa20dbfb9968e85", "notes": null diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c index 03b9c55d67f..519069e131e 100644 --- a/src/mesa/state_tracker/st_program.c +++ b/src/mesa/state_tracker/st_program.c @@ -636,6 +636,9 @@ get_nir_shader(struct st_context *st, struct gl_program *prog, bool is_draw) if ((!is_draw || !st->ctx->Const.PackedDriverUniformStorage) && prog->nir) { nir_shader *nir = prog->nir; + if (nir->info.stage == MESA_SHADER_VERTEX) + assert(prog->base_serialized_nir && prog->base_serialized_nir_size); + /* The first shader variant takes ownership of NIR, so that there is * no cloning. Additional shader variants are always generated from * serialized NIR to save memory. @@ -649,8 +652,7 @@ get_nir_shader(struct st_context *st, struct gl_program *prog, bool is_draw) const struct nir_shader_compiler_options *options = is_draw ? &draw_nir_options : st_get_nir_compiler_options(st, prog->info.stage); - if (is_draw && st->ctx->Const.PackedDriverUniformStorage && - (!prog->shader_program || prog->shader_program->data->LinkStatus != LINKING_SKIPPED)) { + if (is_draw && st->ctx->Const.PackedDriverUniformStorage) { assert(prog->base_serialized_nir); blob_reader_init(&blob_reader, prog->base_serialized_nir, prog->base_serialized_nir_size); } else { diff --git a/src/mesa/state_tracker/st_shader_cache.c b/src/mesa/state_tracker/st_shader_cache.c index 139e53b923d..4b53972fd7a 100644 --- a/src/mesa/state_tracker/st_shader_cache.c +++ b/src/mesa/state_tracker/st_shader_cache.c @@ -63,10 +63,15 @@ static void write_nir_to_cache(struct blob *blob, struct gl_program *prog) { st_serialize_nir(prog); + if (prog->info.stage == MESA_SHADER_VERTEX) + st_serialize_base_nir(prog, prog->nir); blob_write_intptr(blob, prog->serialized_nir_size); blob_write_bytes(blob, prog->serialized_nir, prog->serialized_nir_size); + blob_write_intptr(blob, prog->base_serialized_nir_size); + blob_write_bytes(blob, prog->base_serialized_nir, prog->base_serialized_nir_size); + copy_blob_to_driver_cache_blob(blob, prog); } @@ -182,6 +187,9 @@ st_deserialise_nir_program(struct gl_context *ctx, prog->serialized_nir_size = blob_read_intptr(&blob_reader); prog->serialized_nir = malloc(prog->serialized_nir_size); blob_copy_bytes(&blob_reader, prog->serialized_nir, prog->serialized_nir_size); + prog->base_serialized_nir_size = blob_read_intptr(&blob_reader); + prog->base_serialized_nir = malloc(prog->base_serialized_nir_size); + blob_copy_bytes(&blob_reader, prog->base_serialized_nir, prog->base_serialized_nir_size); prog->shader_program = shProg; /* Make sure we don't try to read more data than we wrote. This should