OpenGL allows you to call ShaderSource and CompileShader on existing shaders which are already attached to programs that have been linked.
I want to be able to accurately track when programs need relinking, and unfortunately this is one of those cases. Signed-off-by: Kenneth Graunke <kenn...@whitecape.org> --- src/glsl/linker.cpp | 7 +++++++ src/mesa/main/mtypes.h | 2 ++ src/mesa/main/shaderapi.c | 28 ++++++++++++++++++++++++++++ src/mesa/main/shaderapi.h | 3 +++ 4 files changed, 40 insertions(+) I loathe this code. I'd say there has to be a better way, but I sure couldn't think of one. This is necessary to make Piglit's glsl-reload-source continue passing after my early-return-from-LinkProgram patch, later in the series. I don't know why OpenGL made this a feature. diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index a43d230..49eb2d4 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -2618,6 +2618,13 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog) /* FINISHME: Assign fragment shader output locations. */ done: + if (prog->LinkStatus) { + ralloc_free(prog->ShaderEpochs); + prog->ShaderEpochs = ralloc_array(prog, unsigned, prog->NumShaders); + for (unsigned i = 0; i < prog->NumShaders; i++) + prog->ShaderEpochs[i] = prog->Shaders[i]->CompileEpoch; + } + for (unsigned i = 0; i < MESA_SHADER_STAGES; i++) { free(shader_list[i]); if (prog->_LinkedShaders[i] == NULL) diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 741f936..df7715b 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2379,6 +2379,7 @@ struct gl_shader GLint RefCount; /**< Reference count */ GLboolean DeletePending; GLboolean CompileStatus; + unsigned CompileEpoch; /**< Incremented each time the shader is recompiled */ const GLchar *Source; /**< Source code string */ GLuint SourceChecksum; /**< for debug/logging purposes */ struct gl_program *Program; /**< Post-compile assembly code */ @@ -2615,6 +2616,7 @@ struct gl_shader_program GLuint NumShaders; /**< number of attached shaders */ struct gl_shader **Shaders; /**< List of attached the shaders */ + unsigned *ShaderEpochs; /**< List of CompileEpochs for attached shaders. */ /** * User-defined attribute bindings diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c index 59d30ff..3a4a2a9 100644 --- a/src/mesa/main/shaderapi.c +++ b/src/mesa/main/shaderapi.c @@ -827,6 +827,8 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) if (!sh) return; + ++sh->CompileEpoch; + options = &ctx->ShaderCompilerOptions[sh->Stage]; /* set default pragma state for shader */ @@ -887,6 +889,32 @@ compile_shader(struct gl_context *ctx, GLuint shaderObj) } } +/** + * Updates shProg->NeedsRelink if any of the attached shaders have been + * recompiled since the last LinkProgram call. + * + * This will break if the shaders are recompiled exactly 2^32 times between + * LinkProgram calls, but only an extremely targeted test would hit that. + */ +void +_mesa_check_for_recompiled_shaders(struct gl_shader_program *shProg) +{ + unsigned i; + + /* If the program isn't linked, we have no existing LinkedShaders to + * compare to. If it's already marked as needing a relink, there's + * no need to bother checking. + */ + if (!shProg->LinkStatus || shProg->NeedsRelink) + return; + + for (i = 0; i < shProg->NumShaders; i++) { + if (shProg->Shaders[i]->CompileEpoch != shProg->ShaderEpochs[i]) { + shProg->NeedsRelink = true; + return; + } + } +} /** * Link a program's shaders. diff --git a/src/mesa/main/shaderapi.h b/src/mesa/main/shaderapi.h index 17b05b3..4a7be5c 100644 --- a/src/mesa/main/shaderapi.h +++ b/src/mesa/main/shaderapi.h @@ -60,6 +60,9 @@ _mesa_count_active_attribs(struct gl_shader_program *shProg); extern size_t _mesa_longest_attribute_name_length(struct gl_shader_program *shProg); +extern void +_mesa_check_for_recompiled_shaders(struct gl_shader_program *shProg); + extern void GLAPIENTRY _mesa_AttachObjectARB(GLhandleARB, GLhandleARB); -- 1.9.2 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev