[Mesa-dev] [PATCH 2/6] mesa: Track whether shaders have been recompiled since the last link.

Kenneth Graunke kenneth at whitecape.org
Wed May 14 17:28:13 PDT 2014


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 <kenneth at 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



More information about the mesa-dev mailing list