A number of things can happen that change the shader source after it is compiled or linked.
For example: - Source changed after it is first compiled - Source changed after linking - Shader detached after linking In order to be able to fallback to a full rebuild on a cache miss we make a copy of the shader source it into the new FallbackShaders field when linking. --- src/compiler/glsl/linker.cpp | 27 ++++++++++++++++----------- src/compiler/glsl/shader_cache.cpp | 22 ++++++++++++++++++++++ src/mesa/drivers/dri/i965/brw_shader_cache.c | 26 ++++++++++++++++++++------ src/mesa/main/mtypes.h | 3 +++ src/mesa/main/shaderobj.c | 6 ++++++ src/mesa/program/ir_to_mesa.cpp | 16 ++++++++++++---- 6 files changed, 79 insertions(+), 21 deletions(-) diff --git a/src/compiler/glsl/linker.cpp b/src/compiler/glsl/linker.cpp index 5719c87..f782210 100644 --- a/src/compiler/glsl/linker.cpp +++ b/src/compiler/glsl/linker.cpp @@ -4500,7 +4500,9 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog, * fixed-function. This applies to the case where all stages are * missing. */ - if (prog->NumShaders == 0) { + unsigned shader_count = is_cache_fallback ? + prog->NumFallbackShaders : prog->NumShaders; + if (shader_count == 0) { if (ctx->API != API_OPENGL_COMPAT) linker_error(prog, "no shaders attached to the program\n"); return; @@ -4546,44 +4548,47 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog, struct gl_shader **shader_list[MESA_SHADER_STAGES]; unsigned num_shaders[MESA_SHADER_STAGES]; + struct gl_shader **shaders = is_cache_fallback ? + prog->FallbackShaders : prog->Shaders; + for (int i = 0; i < MESA_SHADER_STAGES; i++) { shader_list[i] = (struct gl_shader **) - calloc(prog->NumShaders, sizeof(struct gl_shader *)); + calloc(shader_count, sizeof(struct gl_shader *)); num_shaders[i] = 0; } unsigned min_version = UINT_MAX; unsigned max_version = 0; - for (unsigned i = 0; i < prog->NumShaders; i++) { - min_version = MIN2(min_version, prog->Shaders[i]->Version); - max_version = MAX2(max_version, prog->Shaders[i]->Version); + for (unsigned i = 0; i < shader_count; i++) { + min_version = MIN2(min_version, shaders[i]->Version); + max_version = MAX2(max_version, shaders[i]->Version); - if (prog->Shaders[i]->IsES != prog->Shaders[0]->IsES) { + if (shaders[i]->IsES != shaders[0]->IsES) { linker_error(prog, "all shaders must use same shading " "language version\n"); goto done; } - if (prog->Shaders[i]->info.ARB_fragment_coord_conventions_enable) { + if (shaders[i]->info.ARB_fragment_coord_conventions_enable) { prog->ARB_fragment_coord_conventions_enable = true; } - gl_shader_stage shader_type = prog->Shaders[i]->Stage; - shader_list[shader_type][num_shaders[shader_type]] = prog->Shaders[i]; + gl_shader_stage shader_type = shaders[i]->Stage; + shader_list[shader_type][num_shaders[shader_type]] = shaders[i]; num_shaders[shader_type]++; } /* In desktop GLSL, different shader versions may be linked together. In * GLSL ES, all shader versions must be the same. */ - if (prog->Shaders[0]->IsES && min_version != max_version) { + if (shaders[0]->IsES && min_version != max_version) { linker_error(prog, "all shaders must use same shading " "language version\n"); goto done; } prog->Version = max_version; - prog->IsES = prog->Shaders[0]->IsES; + prog->IsES = shaders[0]->IsES; /* Some shaders have to be linked with some other shaders present. */ diff --git a/src/compiler/glsl/shader_cache.cpp b/src/compiler/glsl/shader_cache.cpp index c661557..d27bc18 100644 --- a/src/compiler/glsl/shader_cache.cpp +++ b/src/compiler/glsl/shader_cache.cpp @@ -1168,6 +1168,28 @@ shader_cache_read_program_metadata(struct gl_context *ctx, if (!cache) return false; + /* Shaders could be recompiled using different source code after linking, + * or the shader could be detached from the program so store some + * information about the shader to be used in case of fallback. + */ + if (prog->FallbackShaders == NULL) { + prog->NumFallbackShaders = prog->NumShaders; + prog->FallbackShaders = (struct gl_shader **) + reralloc(NULL, prog->FallbackShaders, struct gl_shader *, + prog->NumShaders); + for (unsigned i = 0; i < prog->NumShaders; i++) { + prog->FallbackShaders[i] = rzalloc(prog->FallbackShaders, + struct gl_shader); + memcpy(prog->FallbackShaders[i]->sha1, prog->Shaders[i]->sha1, + sizeof(prog->Shaders[i]->sha1)); + prog->FallbackShaders[i]->Stage = prog->Shaders[i]->Stage; + prog->FallbackShaders[i]->Source = + ralloc_strdup(prog->FallbackShaders, prog->Shaders[i]->Source); + prog->FallbackShaders[i]->InfoLog = + ralloc_strdup(prog->FallbackShaders, ""); + } + } + for (unsigned i = 0; i < prog->NumShaders; i++) { if (prog->Shaders[i]->Stage == MESA_SHADER_COMPUTE) { compile_shaders(ctx, prog); diff --git a/src/mesa/drivers/dri/i965/brw_shader_cache.c b/src/mesa/drivers/dri/i965/brw_shader_cache.c index 6e3b6e9..80086a5 100644 --- a/src/mesa/drivers/dri/i965/brw_shader_cache.c +++ b/src/mesa/drivers/dri/i965/brw_shader_cache.c @@ -189,12 +189,19 @@ fallback_to_full_recompile(struct brw_context *brw, if (fp) fp->cache_fallback = true; - for (unsigned i = 0; i < shProg->NumShaders; i++) { - _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false, - false, true); + for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) { + _mesa_glsl_compile_shader(&brw->ctx, shProg->FallbackShaders[i], + false, false, true); } _mesa_glsl_link_shader(&brw->ctx, shProg, true); + /* We should never get here again so free the shaders */ + shProg->NumFallbackShaders = 0; + for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) { + ralloc_free(shProg->FallbackShaders); + shProg->FallbackShaders = NULL; + } + vp->cache_fallback = false; if (tcp) tcp->cache_fallback = true; @@ -215,12 +222,19 @@ fallback_to_full_recompile(struct brw_context *brw, fp->cache_fallback = true; - for (unsigned i = 0; i < shProg->NumShaders; i++) { - _mesa_glsl_compile_shader(&brw->ctx, shProg->Shaders[i], false, - false, true); + for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) { + _mesa_glsl_compile_shader(&brw->ctx, shProg->FallbackShaders[i], + false, false, true); } _mesa_glsl_link_shader(&brw->ctx, shProg, true); + /* We should never get here again so free the shaders */ + shProg->NumFallbackShaders = 0; + for (unsigned i = 0; i < shProg->NumFallbackShaders; i++) { + ralloc_free(shProg->FallbackShaders); + shProg->FallbackShaders = NULL; + } + fp->cache_fallback = false; } } diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index d7d5e18..f2cb020 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2699,6 +2699,9 @@ struct gl_shader_program GLuint NumShaders; /**< number of attached shaders */ struct gl_shader **Shaders; /**< List of attached the shaders */ + GLuint NumFallbackShaders; + struct gl_shader **FallbackShaders; /**< Shaders used for cache fallback */ + /** * User-defined attribute bindings * diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c index 0fcb469..f114cf5 100644 --- a/src/mesa/main/shaderobj.c +++ b/src/mesa/main/shaderobj.c @@ -377,10 +377,16 @@ _mesa_free_shader_program_data(struct gl_context *ctx, _mesa_reference_shader(ctx, &shProg->Shaders[i], NULL); } shProg->NumShaders = 0; + shProg->NumFallbackShaders = 0; free(shProg->Shaders); shProg->Shaders = NULL; + if (shProg->FallbackShaders){ + ralloc_free(shProg->FallbackShaders); + shProg->FallbackShaders = NULL; + } + /* Transform feedback varying vars */ for (i = 0; i < shProg->TransformFeedback.NumVarying; i++) { free(shProg->TransformFeedback.VaryingNames[i]); diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 4978095..dae364d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3061,9 +3061,11 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog, prog->LinkStatus = GL_TRUE; - for (i = 0; i < prog->NumShaders; i++) { - if (!prog->Shaders[i]->CompileStatus) { - linker_error(prog, "linking with uncompiled shader"); + if (!is_cache_fallback) { + for (i = 0; i < prog->NumShaders; i++) { + if (!prog->Shaders[i]->CompileStatus) { + linker_error(prog, "linking with uncompiled shader"); + } } } @@ -3097,8 +3099,14 @@ _mesa_glsl_link_shader(struct gl_context *ctx, struct gl_shader_program *prog, } #ifdef ENABLE_SHADER_CACHE - if (prog->LinkStatus) + if (prog->LinkStatus && !is_cache_fallback) { + if (prog->FallbackShaders) { + prog->NumFallbackShaders = 0; + ralloc_free(prog->FallbackShaders); + prog->FallbackShaders = NULL; + } shader_cache_write_program_metadata(ctx, prog); + } #endif } -- 2.7.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org https://lists.freedesktop.org/mailman/listinfo/mesa-dev