Mesa (7.9): glsl: Slightly change the semantic of _LinkedShaders

Ian Romanick idr at kemper.freedesktop.org
Tue Dec 14 21:13:04 UTC 2010


Module: Mesa
Branch: 7.9
Commit: e5ad6c3366ce3dbce3209b912e21e3f0406d6a1e
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=e5ad6c3366ce3dbce3209b912e21e3f0406d6a1e

Author: Ian Romanick <ian.d.romanick at intel.com>
Date:   Thu Oct 14 13:28:42 2010 -0700

glsl: Slightly change the semantic of _LinkedShaders

Previously _LinkedShaders was a compact array of the linked shaders
for each shader stage.  Now it is arranged such that each slot,
indexed by the MESA_SHADER_* defines, refers to a specific shader
stage.  As a result, some slots will be NULL.  This makes things a
little more complex in the linker, but it simplifies things in other
places.

As a side effect _NumLinkedShaders is removed.

NOTE: This may be a candidate for the 7.9 branch.  If there are other
patches that get backported to 7.9 that use _LinkedShader, this patch
should be cherry picked also.

(cherry picked from commit 3322fbaf3b5e305ce00c1d08c26965bb98e0cef0)

---

 src/glsl/glcpp/glcpp.c                   |    8 +++
 src/glsl/linker.cpp                      |   83 +++++++++++++++++++++++-------
 src/glsl/main.cpp                        |   13 ++++-
 src/mesa/drivers/dri/i965/brw_fs.cpp     |   17 ++----
 src/mesa/drivers/dri/i965/brw_program.c  |   12 +---
 src/mesa/drivers/dri/i965/brw_wm_state.c |   13 ++---
 src/mesa/main/context.c                  |   22 ++++----
 src/mesa/main/mtypes.h                   |    9 ++--
 src/mesa/main/shaderapi.c                |    2 +-
 src/mesa/main/shaderobj.c                |    8 ++-
 src/mesa/program/ir_to_mesa.cpp          |   16 +++++-
 11 files changed, 130 insertions(+), 73 deletions(-)

diff --git a/src/glsl/glcpp/glcpp.c b/src/glsl/glcpp/glcpp.c
index 8d1ced5..017099d 100644
--- a/src/glsl/glcpp/glcpp.c
+++ b/src/glsl/glcpp/glcpp.c
@@ -29,9 +29,17 @@
 #include <errno.h>
 #include "glcpp.h"
 #include "main/mtypes.h"
+#include "main/shaderobj.h"
 
 extern int yydebug;
 
+void
+_mesa_reference_shader(GLcontext *ctx, struct gl_shader **ptr,
+                       struct gl_shader *sh)
+{
+   *ptr = sh;
+}
+
 /* Read from fd until EOF and return a string of everything read.
  */
 static char *
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 1f98750..63ec4fd 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -80,6 +80,10 @@ extern "C" {
 #include "linker.h"
 #include "ir_optimization.h"
 
+extern "C" {
+#include "main/shaderobj.h"
+}
+
 /**
  * Visitor that determines whether or not a variable is ever written.
  */
@@ -321,6 +325,9 @@ cross_validate_globals(struct gl_shader_program *prog,
     */
    glsl_symbol_table variables;
    for (unsigned i = 0; i < num_shaders; i++) {
+      if (shader_list[i] == NULL)
+	 continue;
+
       foreach_list(node, shader_list[i]->ir) {
 	 ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
@@ -407,7 +414,7 @@ bool
 cross_validate_uniforms(struct gl_shader_program *prog)
 {
    return cross_validate_globals(prog, prog->_LinkedShaders,
-				 prog->_NumLinkedShaders, true);
+				 MESA_SHADER_TYPES, true);
 }
 
 
@@ -863,7 +870,10 @@ struct uniform_node {
 static void
 update_array_sizes(struct gl_shader_program *prog)
 {
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+	 if (prog->_LinkedShaders[i] == NULL)
+	    continue;
+
       foreach_list(node, prog->_LinkedShaders[i]->ir) {
 	 ir_variable *const var = ((ir_instruction *) node)->as_variable();
 
@@ -874,7 +884,10 @@ update_array_sizes(struct gl_shader_program *prog)
 	    continue;
 
 	 unsigned int size = var->max_array_access;
-	 for (unsigned j = 0; j < prog->_NumLinkedShaders; j++) {
+	 for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) {
+	       if (prog->_LinkedShaders[j] == NULL)
+		  continue;
+
 	    foreach_list(node2, prog->_LinkedShaders[j]->ir) {
 	       ir_variable *other_var = ((ir_instruction *) node2)->as_variable();
 	       if (!other_var)
@@ -986,7 +999,10 @@ assign_uniform_locations(struct gl_shader_program *prog)
 				    hash_table_string_compare);
    void *mem_ctx = talloc_new(NULL);
 
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+	 continue;
+
       unsigned next_position = 0;
 
       foreach_list(node, prog->_LinkedShaders[i]->ir) {
@@ -1418,13 +1434,15 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
 
    prog->Version = max_version;
 
-   for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
-      ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+   for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] != NULL)
+	 ctx->Driver.DeleteShader(ctx, prog->_LinkedShaders[i]);
+
+      prog->_LinkedShaders[i] = NULL;
    }
 
    /* Link all shaders for a particular stage and validate the result.
     */
-   prog->_NumLinkedShaders = 0;
    if (num_vert_shaders > 0) {
       gl_shader *const sh =
 	 link_intrastage_shaders(ctx, prog, vert_shader_list, num_vert_shaders);
@@ -1435,8 +1453,8 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
       if (!validate_vertex_shader_executable(prog, sh))
 	  goto done;
 
-      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
-      prog->_NumLinkedShaders++;
+      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_VERTEX],
+			     sh);
    }
 
    if (num_frag_shaders > 0) {
@@ -1449,8 +1467,8 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
       if (!validate_fragment_shader_executable(prog, sh))
 	  goto done;
 
-      prog->_LinkedShaders[prog->_NumLinkedShaders] = sh;
-      prog->_NumLinkedShaders++;
+      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
+			     sh);
    }
 
    /* Here begins the inter-stage linking phase.  Some initial validation is
@@ -1458,14 +1476,26 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
     * varyings.
     */
    if (cross_validate_uniforms(prog)) {
+      unsigned prev;
+
+      for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+	 if (prog->_LinkedShaders[prev] != NULL)
+	    break;
+      }
+
       /* Validate the inputs of each stage with the output of the preceeding
        * stage.
        */
-      for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) {
+      for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+	 if (prog->_LinkedShaders[i] == NULL)
+	    continue;
+
 	 if (!cross_validate_outputs_to_inputs(prog,
-					       prog->_LinkedShaders[i - 1],
+					       prog->_LinkedShaders[prev],
 					       prog->_LinkedShaders[i]))
 	    goto done;
+
+	 prev = i;
       }
 
       prog->LinkStatus = true;
@@ -1475,7 +1505,10 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
     * uniforms, and varyings.  Later optimization could possibly make
     * some of that unused.
     */
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+	 continue;
+
       while (do_common_optimization(prog->_LinkedShaders[i]->ir, true, 32))
 	 ;
    }
@@ -1484,7 +1517,7 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
 
    assign_uniform_locations(prog);
 
-   if (prog->_NumLinkedShaders && prog->_LinkedShaders[0]->Type == GL_VERTEX_SHADER) {
+   if (prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL) {
       /* FINISHME: The value of the max_attribute_index parameter is
        * FINISHME: implementation dependent based on the value of
        * FINISHME: GL_MAX_VERTEX_ATTRIBS.  GL_MAX_VERTEX_ATTRIBS must be
@@ -1493,14 +1526,26 @@ link_shaders(GLcontext *ctx, struct gl_shader_program *prog)
       if (!assign_attribute_locations(prog, 16))
 	 goto done;
 
-      if (prog->_NumLinkedShaders == 1)
-	 demote_unread_shader_outputs(prog->_LinkedShaders[0]);
+      if ((prog->_LinkedShaders[MESA_SHADER_GEOMETRY] == NULL)
+	  && (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] == NULL))
+	 demote_unread_shader_outputs(prog->_LinkedShaders[MESA_SHADER_VERTEX]);
    }
 
-   for (unsigned i = 1; i < prog->_NumLinkedShaders; i++)
+   unsigned prev;
+   for (prev = 0; prev < MESA_SHADER_TYPES; prev++) {
+      if (prog->_LinkedShaders[prev] != NULL)
+	 break;
+   }
+
+   for (unsigned i = prev + 1; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+	 continue;
+
       assign_varying_locations(prog,
-			       prog->_LinkedShaders[i - 1],
+			       prog->_LinkedShaders[prev],
 			       prog->_LinkedShaders[i]);
+      prev = i;
+   }
 
    /* FINISHME: Assign fragment shader output locations. */
 
diff --git a/src/glsl/main.cpp b/src/glsl/main.cpp
index 94c14a5..51274f5 100644
--- a/src/glsl/main.cpp
+++ b/src/glsl/main.cpp
@@ -40,8 +40,19 @@
 extern "C" struct gl_shader *
 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type);
 
+extern "C" void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+                       struct gl_shader *sh);
+
 /* Copied from shader_api.c for the stand-alone compiler.
  */
+void
+_mesa_reference_shader(struct gl_context *ctx, struct gl_shader **ptr,
+                       struct gl_shader *sh)
+{
+   *ptr = sh;
+}
+
 struct gl_shader *
 _mesa_new_shader(GLcontext *ctx, GLuint name, GLenum type)
 {
@@ -319,7 +330,7 @@ main(int argc, char **argv)
 	 printf("Info log for linking:\n%s\n", whole_program->InfoLog);
    }
 
-   for (unsigned i = 0; i < whole_program->_NumLinkedShaders; i++)
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++)
       talloc_free(whole_program->_LinkedShaders[i]);
 
    talloc_free(whole_program);
diff --git a/src/mesa/drivers/dri/i965/brw_fs.cpp b/src/mesa/drivers/dri/i965/brw_fs.cpp
index cf5c521..a0d7a34 100644
--- a/src/mesa/drivers/dri/i965/brw_fs.cpp
+++ b/src/mesa/drivers/dri/i965/brw_fs.cpp
@@ -117,10 +117,9 @@ brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
    if (using_new_fs == -1)
       using_new_fs = getenv("INTEL_NEW_FS") != NULL;
 
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
-      struct brw_shader *shader = (struct brw_shader *)prog->_LinkedShaders[i];
-
-      if (using_new_fs && shader->base.Type == GL_FRAGMENT_SHADER) {
+   struct brw_shader *shader =
+      (struct brw_shader *)prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
+   if (shader != NULL && using_new_fs) {
 	 void *mem_ctx = talloc_new(NULL);
 	 bool progress;
 
@@ -148,7 +147,6 @@ brw_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
 
 	 reparent_ir(shader->ir, shader->ir);
 	 talloc_free(mem_ctx);
-      }
    }
 
    if (!_mesa_ir_link_shader(ctx, prog))
@@ -1835,7 +1833,6 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c)
    struct brw_compile *p = &c->func;
    struct intel_context *intel = &brw->intel;
    GLcontext *ctx = &intel->ctx;
-   struct brw_shader *shader = NULL;
    struct gl_shader_program *prog = ctx->Shader.CurrentProgram;
 
    if (!prog)
@@ -1844,12 +1841,8 @@ brw_wm_fs_emit(struct brw_context *brw, struct brw_wm_compile *c)
    if (!using_new_fs)
       return GL_FALSE;
 
-   for (unsigned int i = 0; i < prog->_NumLinkedShaders; i++) {
-      if (prog->_LinkedShaders[i]->Type == GL_FRAGMENT_SHADER) {
-	 shader = (struct brw_shader *)prog->_LinkedShaders[i];
-	 break;
-      }
-   }
+   struct brw_shader *shader =
+     (brw_shader *) prog->_LinkedShaders[MESA_SHADER_FRAGMENT];
    if (!shader)
       return GL_FALSE;
 
diff --git a/src/mesa/drivers/dri/i965/brw_program.c b/src/mesa/drivers/dri/i965/brw_program.c
index 3e52be5..9937407 100644
--- a/src/mesa/drivers/dri/i965/brw_program.c
+++ b/src/mesa/drivers/dri/i965/brw_program.c
@@ -148,15 +148,9 @@ static GLboolean brwProgramStringNotify( GLcontext *ctx,
        * using the new FS backend.
        */
       shader_program = _mesa_lookup_shader_program(ctx, prog->Id);
-      if (shader_program) {
-	 for (i = 0; i < shader_program->_NumLinkedShaders; i++) {
-	    struct brw_shader *shader;
-
-	    shader = (struct brw_shader *)shader_program->_LinkedShaders[i];
-	    if (shader->base.Type == GL_FRAGMENT_SHADER && shader->ir) {
-	       return GL_TRUE;
-	    }
-	 }
+      if (shader_program
+	  && shader_program->_LinkedShaders[MESA_SHADER_FRAGMENT]) {
+	 return GL_TRUE;
       }
    }
    else if (target == GL_VERTEX_PROGRAM_ARB) {
diff --git a/src/mesa/drivers/dri/i965/brw_wm_state.c b/src/mesa/drivers/dri/i965/brw_wm_state.c
index 6699d0a..07b17ad 100644
--- a/src/mesa/drivers/dri/i965/brw_wm_state.c
+++ b/src/mesa/drivers/dri/i965/brw_wm_state.c
@@ -108,16 +108,11 @@ wm_unit_populate_key(struct brw_context *brw, struct brw_wm_unit_key *key)
     * 8-wide.
     */
    if (ctx->Shader.CurrentProgram) {
-      int i;
+      struct brw_shader *shader = (struct brw_shader *)
+	 ctx->Shader.CurrentProgram->_LinkedShaders[MESA_SHADER_FRAGMENT];
 
-      for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
-	 struct brw_shader *shader =
-	    (struct brw_shader *)ctx->Shader.CurrentProgram->_LinkedShaders[i];;
-
-	 if (shader->base.Type == GL_FRAGMENT_SHADER &&
-	     shader->ir != NULL) {
-	    key->is_glsl = GL_TRUE;
-	 }
+      if (shader != NULL && shader->ir != NULL) {
+	 key->is_glsl = GL_TRUE;
       }
    }
 
diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
index 68f016a..4cf5e7d 100644
--- a/src/mesa/main/context.c
+++ b/src/mesa/main/context.c
@@ -1717,10 +1717,10 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
       _mesa_update_state(ctx);
 
    if (ctx->Shader.CurrentProgram) {
-      unsigned i;
+      struct gl_shader_program *const prog = ctx->Shader.CurrentProgram;
 
       /* using shaders */
-      if (!ctx->Shader.CurrentProgram->LinkStatus) {
+      if (!prog->LinkStatus) {
          _mesa_error(ctx, GL_INVALID_OPERATION,
                      "%s(shader not linked)", where);
          return GL_FALSE;
@@ -1728,10 +1728,9 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
 #if 0 /* not normally enabled */
       {
          char errMsg[100];
-         if (!_mesa_validate_shader_program(ctx, ctx->Shader.CurrentProgram,
-                                            errMsg)) {
+         if (!_mesa_validate_shader_program(ctx, prog, errMsg)) {
             _mesa_warning(ctx, "Shader program %u is invalid: %s",
-                          ctx->Shader.CurrentProgram->Name, errMsg);
+                          prog->Name, errMsg);
          }
       }
 #endif
@@ -1740,13 +1739,12 @@ _mesa_valid_to_render(GLcontext *ctx, const char *where)
        * any stages that are not provided, the corresponding assembly shader
        * target will be validated below.
        */
-      for (i = 0; i < ctx->Shader.CurrentProgram->_NumLinkedShaders; i++) {
-	 switch (ctx->Shader.CurrentProgram->_LinkedShaders[i]->Type) {
-	 case GL_VERTEX_SHADER: vert_from_glsl_shader = true; break;
-	 case GL_GEOMETRY_SHADER_ARB: geom_from_glsl_shader = true; break;
-	 case GL_FRAGMENT_SHADER: frag_from_glsl_shader = true; break;
-	 }
-      }
+      vert_from_glsl_shader =
+	 prog->_LinkedShaders[MESA_SHADER_VERTEX] != NULL;
+      geom_from_glsl_shader =
+	 prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL;
+      frag_from_glsl_shader =
+	 prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL;
    }
 
 
diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
index 5494be8..58958fd 100644
--- a/src/mesa/main/mtypes.h
+++ b/src/mesa/main/mtypes.h
@@ -2143,11 +2143,12 @@ struct gl_shader_program
 
    /**
     * Per-stage shaders resulting from the first stage of linking.
+    *
+    * Set of linked shaders for this program.  The array is accessed using the
+    * \c MESA_SHADER_* defines.  Entries for non-existent stages will be
+    * \c NULL.
     */
-   /*@{*/
-   GLuint _NumLinkedShaders;
-   struct gl_shader *_LinkedShaders[2];
-   /*@}*/
+   struct gl_shader *_LinkedShaders[MESA_SHADER_TYPES];
 };   
 
 
diff --git a/src/mesa/main/shaderapi.c b/src/mesa/main/shaderapi.c
index 90045ad..4b69544 100644
--- a/src/mesa/main/shaderapi.c
+++ b/src/mesa/main/shaderapi.c
@@ -209,7 +209,7 @@ _mesa_copy_string(GLchar *dst, GLsizei maxLength,
  *
  */
 static bool
-validate_shader_target(const struct gl_context *ctx, GLenum type)
+validate_shader_target(const GLcontext *ctx, GLenum type)
 {
    switch (type) {
 #if FEATURE_ARB_fragment_shader
diff --git a/src/mesa/main/shaderobj.c b/src/mesa/main/shaderobj.c
index 2de8f27..4d77fc8 100644
--- a/src/mesa/main/shaderobj.c
+++ b/src/mesa/main/shaderobj.c
@@ -326,10 +326,12 @@ _mesa_free_shader_program_data(GLcontext *ctx,
    shProg->TransformFeedback.NumVarying = 0;
 
 
-   for (i = 0; i < shProg->_NumLinkedShaders; i++) {
-      ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[i]);
+   for (i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (shProg->_LinkedShaders[i] != NULL) {
+	 ctx->Driver.DeleteShader(ctx, shProg->_LinkedShaders[i]);
+	 shProg->_LinkedShaders[i] = NULL;
+      }
    }
-   shProg->_NumLinkedShaders = 0;
 }
 
 
diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
index 93b6c30..aa660af 100644
--- a/src/mesa/program/ir_to_mesa.cpp
+++ b/src/mesa/program/ir_to_mesa.cpp
@@ -2552,8 +2552,12 @@ set_uniform_initializers(GLcontext *ctx,
 {
    void *mem_ctx = NULL;
 
-   for (unsigned int i = 0; i < shader_program->_NumLinkedShaders; i++) {
+   for (unsigned int i = 0; i < MESA_SHADER_TYPES; i++) {
       struct gl_shader *shader = shader_program->_LinkedShaders[i];
+
+      if (shader == NULL)
+	 continue;
+
       foreach_iter(exec_list_iterator, iter, *shader->ir) {
 	 ir_instruction *ir = (ir_instruction *)iter.get();
 	 ir_variable *var = ir->as_variable();
@@ -2761,7 +2765,10 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
 {
    assert(prog->LinkStatus);
 
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
+      if (prog->_LinkedShaders[i] == NULL)
+	 continue;
+
       bool progress;
       exec_list *ir = prog->_LinkedShaders[i]->ir;
       struct gl_shader_compiler_options *options =
@@ -2805,10 +2812,13 @@ _mesa_ir_link_shader(GLcontext *ctx, struct gl_shader_program *prog)
       validate_ir_tree(ir);
    }
 
-   for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
+   for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) {
       struct gl_program *linked_prog;
       bool ok = true;
 
+      if (prog->_LinkedShaders[i] == NULL)
+	 continue;
+
       linked_prog = get_mesa_program(ctx, prog, prog->_LinkedShaders[i]);
 
       switch (prog->_LinkedShaders[i]->Type) {




More information about the mesa-commit mailing list