[Mesa-dev] [PATCH 11/34] glsl: support compilation of geometry shaders

Kenneth Graunke kenneth at whitecape.org
Tue Jul 30 15:16:47 PDT 2013


On 07/28/2013 11:03 PM, Paul Berry wrote:
> From: Bryan Cain <bryancain3 at gmail.com>
>
> This commit adds all of the parsing and semantics for GLSL 150 style
> geometry shaders.
>
> v2 (Paul Berry <stereotype441 at gmail.com>): Adjust i965's
> brw_link_shader() to pass the new is_geometry_shader argument to
> do_set_program_inouts.  Add a few missing calls to
> get_pipeline_stage().  Fix some signed/unsigned comparison warnings.
> Fix handling of NULL consumer in assign_varying_locations().
>
> v3 (Bryan Cain <bryancain3 at gmail.com>): fix indexing order of 2D
> arrays.  Also, allow interpolation qualifiers in geometry shaders.
>
> v4 (Paul Berry <stereotype441 at gmail.com>): Eliminate
> get_pipeline_stage()--it is no longer needed thanks to 030ca23 (mesa:
> renumber shader indices according to their placement in pipeline).
> Remove 2D stuff.  Move vertices_per_prim() to ir.h, so that it will be
> accessible from outside the linker.  Remove
> inject_num_vertices_visitor.  Move use of geom_array_resize_visitor
> prior to use of array_resizing_visitor.  Rework for GLSL 1.50.  Use a
> single shader_type argument for do_set_program_inouts()
> ---
>   src/glsl/ast_to_hir.cpp                    |  31 +++++--
>   src/glsl/ir.cpp                            |  21 +++++
>   src/glsl/ir.h                              |   5 +-
>   src/glsl/ir_set_program_inouts.cpp         |  86 +++++++++++++-----
>   src/glsl/linker.cpp                        | 135 +++++++++++++++++++++++++++--
>   src/mesa/drivers/dri/i965/brw_shader.cpp   |   3 +-
>   src/mesa/main/mtypes.h                     |   4 +-
>   src/mesa/program/ir_to_mesa.cpp            |   2 +-
>   src/mesa/state_tracker/st_glsl_to_tgsi.cpp |   2 +-
>   9 files changed, 253 insertions(+), 36 deletions(-)
>
> diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp
> index 2569cde..431a13d 100644
> --- a/src/glsl/ast_to_hir.cpp
> +++ b/src/glsl/ast_to_hir.cpp
> @@ -2056,11 +2056,11 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>         var->interpolation = INTERP_QUALIFIER_NONE;
>
>      if (var->interpolation != INTERP_QUALIFIER_NONE &&
> -       !(state->target == vertex_shader && var->mode == ir_var_shader_out) &&
> -       !(state->target == fragment_shader && var->mode == ir_var_shader_in)) {
> +       ((state->target == vertex_shader && var->mode == ir_var_shader_in) ||
> +        (state->target == fragment_shader && var->mode == ir_var_shader_out))) {
>         _mesa_glsl_error(loc, state,
> -		       "interpolation qualifier `%s' can only be applied to "
> -		       "vertex shader outputs and fragment shader inputs",
> +		       "interpolation qualifier `%s' cannot be applied to "
> +		       "vertex shader inputs or fragment shader outputs",
>   		       var->interpolation_string());
>      }
>
> @@ -2662,6 +2662,27 @@ ast_declarator_list::hir(exec_list *instructions,
>
>         var = new(ctx) ir_variable(var_type, decl->identifier, ir_var_auto);
>
> +      /* The 'varying in' and 'varying out' qualifiers can only be used with
> +       * ARB_geometry_shader4 and EXT_geometry_shader4, which we don't support
> +       * yet.
> +       */
> +      if (this->type->qualifier.flags.q.varying) {
> +	 if (this->type->qualifier.flags.q.in) {
> +	    _mesa_glsl_error(& loc, state,
> +			     "`varying in' qualifier in declaration of "
> +			     "`%s' only valid for geometry shaders using "
> +			     "ARB_geometry_shader4 or EXT_geometry_shader4",
> +			     decl->identifier);
> +	 }
> +	 else if (this->type->qualifier.flags.q.out) {

Style-nit:

} else if (this->type->qualifier.flagsq.out) {

(Mesa historically has used the two-line style in your patch, but has 
largely moved away from that.  In particular, the compiler has always 
used "} else {".)

Might be nice to kill the tabs too, but not a big deal either way.

> +	    _mesa_glsl_error(& loc, state,
> +			     "`varying out' qualifier in declaration of "
> +			     "`%s' only valid for geometry shaders using "
> +			     "ARB_geometry_shader4 or EXT_geometry_shader4",
> +			     decl->identifier);
> +	 }
> +      }
> +
>         /* From page 22 (page 28 of the PDF) of the GLSL 1.10 specification;
>          *
>          *     "Global variables can only use the qualifiers const,
> @@ -2906,7 +2927,7 @@ ast_declarator_list::hir(exec_list *instructions,
>               }
>               break;
>            default:
> -            assert(0);
> +            break;
>            }
>         }
>
> diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp
> index dad58de..1a3983e 100644
> --- a/src/glsl/ir.cpp
> +++ b/src/glsl/ir.cpp
> @@ -1778,3 +1778,24 @@ ir_rvalue::as_rvalue_to_saturate()
>
>      return NULL;
>   }
> +
> +
> +unsigned
> +vertices_per_prim(GLenum prim)
> +{
> +   switch (prim) {
> +   case GL_POINTS:
> +      return 1;
> +   case GL_LINES:
> +      return 2;
> +   case GL_TRIANGLES:
> +      return 3;
> +   case GL_LINES_ADJACENCY_ARB:
> +      return 4;
> +   case GL_TRIANGLES_ADJACENCY_ARB:
> +      return 6;
> +   default:
> +      assert(!"Bad primitive");
> +      return 3;
> +   }
> +}
> diff --git a/src/glsl/ir.h b/src/glsl/ir.h
> index ae79a39..af9d77e 100644
> --- a/src/glsl/ir.h
> +++ b/src/glsl/ir.h
> @@ -2112,7 +2112,7 @@ ir_has_call(ir_instruction *ir);
>
>   extern void
>   do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
> -                      bool is_fragment_shader);
> +                      GLenum shader_type);

This patch is getting pretty huge.  It might be nice to do the 
s/is_fragment_shader/shader_type/ in a separate patch, since that's an 
obvious hunk.

>
>   extern char *
>   prototype_string(const glsl_type *return_type, const char *name,
> @@ -2128,4 +2128,7 @@ extern void _mesa_print_ir(struct exec_list *instructions,
>   } /* extern "C" */
>   #endif
>
> +unsigned
> +vertices_per_prim(GLenum prim);
> +
>   #endif /* IR_H */
> diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp
> index 91a8b45..a578e2a 100644
> --- a/src/glsl/ir_set_program_inouts.cpp
> +++ b/src/glsl/ir_set_program_inouts.cpp
> @@ -44,11 +44,10 @@
>
>   class ir_set_program_inouts_visitor : public ir_hierarchical_visitor {
>   public:
> -   ir_set_program_inouts_visitor(struct gl_program *prog,
> -                                 bool is_fragment_shader)
> +   ir_set_program_inouts_visitor(struct gl_program *prog, GLenum shader_type)
>      {
>         this->prog = prog;
> -      this->is_fragment_shader = is_fragment_shader;
> +      this->shader_type = shader_type;
>      }
>      ~ir_set_program_inouts_visitor()
>      {
> @@ -61,7 +60,7 @@ public:
>      virtual ir_visitor_status visit(ir_dereference_variable *);
>
>      struct gl_program *prog;
> -   bool is_fragment_shader;
> +   GLenum shader_type;
>   };
>
>   static inline bool
> @@ -112,14 +111,24 @@ ir_set_program_inouts_visitor::visit(ir_dereference_variable *ir)
>         return visit_continue;
>
>      if (ir->type->is_array()) {
> -      mark(this->prog, ir->var, 0,
> -	   ir->type->length * ir->type->fields.array->matrix_columns,
> -           this->is_fragment_shader);
> +      int matrix_columns = ir->type->fields.array->matrix_columns;
> +      int length = ir->type->length;

I was wondering if this was left over from the ARB_gs4 stuff. 
Apparently it's for lowered arrays of instance blocks?  Maybe a comment 
would be in order.

> +      if (this->shader_type == GL_GEOMETRY_SHADER &&
> +          ir->var->mode == ir_var_shader_in) {
> +         if (ir->type->element_type()->is_array()) {
> +            const glsl_type *inner_array_type = ir->type->fields.array;
> +            matrix_columns = inner_array_type->fields.array->matrix_columns;
> +            length = inner_array_type->length;
> +         } else {
> +            length = 1;
> +         }
> +      }
> +      mark(this->prog, ir->var, 0, length * matrix_columns,
> +           this->shader_type == GL_FRAGMENT_SHADER);
>      } else {
>         mark(this->prog, ir->var, 0, ir->type->matrix_columns,
> -           this->is_fragment_shader);
> +           this->shader_type == GL_FRAGMENT_SHADER);
>      }
> -
>      return visit_continue;
>   }
>
> @@ -129,7 +138,40 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
>      ir_dereference_variable *deref_var;
>      ir_constant *index = ir->array_index->as_constant();
>      deref_var = ir->array->as_dereference_variable();
> -   ir_variable *var = deref_var ? deref_var->var : NULL;
> +   ir_variable *var;
> +   bool is_vert_array = false, is_2D_array = false;
> +
> +   /* Check whether this dereference is of a GS input array.  These are special
> +    * because the array index refers to the index of an input vertex instead of
> +    * the attribute index.  The exceptions to this exception are 2D arrays
> +    * such as gl_TexCoordIn.  For these, there is a nested dereference_array,
> +    * where the inner index specifies the vertex and the outer index specifies
> +    * the attribute.  To complicate things further, matrix columns are also
> +    * accessed with dereference_array.  So we have to correctly handle 1D
> +    * arrays of non-matrices, 1D arrays of matrices, 2D arrays of non-matrices,
> +    * and 2D arrays of matrices.
> +    */
> +   if (this->shader_type == GL_GEOMETRY_SHADER) {
> +      if (!deref_var) {
> +         /* Either an outer (attribute) dereference of a 2D array or a column
> +          * dereference of an array of matrices. */

Style-nit: */ goes on a separate line.

> +         ir_dereference_array *inner_deref = ir->array->as_dereference_array();
> +         assert(inner_deref);
> +         deref_var = inner_deref->array->as_dereference_variable();
> +         is_2D_array = true;
> +      }
> +
> +      if (deref_var && deref_var->var->mode == ir_var_shader_in) {
> +         if (ir->type->is_array())
> +            /* Inner (vertex) dereference of a 2D array */
> +            return visit_continue;
> +         else
> +            /* Dereference of a 1D (vertex) array */
> +            is_vert_array = true;
> +      }
> +   }

I'm not terribly comfortable with this code, but I'm not sure what to 
suggest instead.  One concern I have is varying structs.

As I understand it, if a VS outputs a struct, the corresponding GS input 
would be an array of structs.  Wouldn't those be accessed via (array_ref 
(record_ref ...) ...)?

The code above seems to assume that if it's not
   (array_ref (var_ref ...))
then it *must* be
   (array_ref (array_ref ...) ...)
which seems wrong, or at least dubious.

The "this must be a matrix" stuff concerns me too.

> +
> +   var = deref_var ? deref_var->var : NULL;
>
>      /* Check that we're dereferencing a shader in or out */
>      if (!var || !is_shader_inout(var))
> @@ -137,14 +179,17 @@ ir_set_program_inouts_visitor::visit_enter(ir_dereference_array *ir)
>
>      if (index) {
>         int width = 1;
> +      const glsl_type *type = is_vert_array ?
> +                              deref_var->type->fields.array : deref_var->type;
> +      int offset = is_vert_array && !is_2D_array ? 0 : index->value.i[0];
>
> -      if (deref_var->type->is_array() &&
> -	  deref_var->type->fields.array->is_matrix()) {
> -	 width = deref_var->type->fields.array->matrix_columns;
> +      if (type->is_array() &&
> +	  type->fields.array->is_matrix()) {
> +	 width = type->fields.array->matrix_columns;
>         }
>
> -      mark(this->prog, var, index->value.i[0] * width, width,
> -           this->is_fragment_shader);
> +      mark(this->prog, var, offset * width, width,
> +           this->shader_type == GL_FRAGMENT_SHADER);
>         return visit_continue_with_parent;
>      }
>
> @@ -164,7 +209,8 @@ ir_set_program_inouts_visitor::visit_enter(ir_function_signature *ir)
>   ir_visitor_status
>   ir_set_program_inouts_visitor::visit_enter(ir_expression *ir)
>   {
> -   if (is_fragment_shader && ir->operation == ir_unop_dFdy) {
> +   if (this->shader_type == GL_FRAGMENT_SHADER &&
> +       ir->operation == ir_unop_dFdy) {
>         gl_fragment_program *fprog = (gl_fragment_program *) prog;
>         fprog->UsesDFdy = true;
>      }
> @@ -175,7 +221,7 @@ ir_visitor_status
>   ir_set_program_inouts_visitor::visit_enter(ir_discard *)
>   {
>      /* discards are only allowed in fragment shaders. */
> -   assert(is_fragment_shader);
> +   assert(this->shader_type == GL_FRAGMENT_SHADER);
>
>      gl_fragment_program *fprog = (gl_fragment_program *) prog;
>      fprog->UsesKill = true;
> @@ -185,14 +231,14 @@ ir_set_program_inouts_visitor::visit_enter(ir_discard *)
>
>   void
>   do_set_program_inouts(exec_list *instructions, struct gl_program *prog,
> -                      bool is_fragment_shader)
> +                      GLenum shader_type)
>   {
> -   ir_set_program_inouts_visitor v(prog, is_fragment_shader);
> +   ir_set_program_inouts_visitor v(prog, shader_type);
>
>      prog->InputsRead = 0;
>      prog->OutputsWritten = 0;
>      prog->SystemValuesRead = 0;
> -   if (is_fragment_shader) {
> +   if (shader_type == GL_FRAGMENT_SHADER) {
>         gl_fragment_program *fprog = (gl_fragment_program *) prog;
>         memset(fprog->InterpQualifier, 0, sizeof(fprog->InterpQualifier));
>         fprog->IsCentroid = 0;
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index 7192567..70d9cf4 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -73,11 +73,14 @@
>   #include "linker.h"
>   #include "link_varyings.h"
>   #include "ir_optimization.h"
> +#include "ir_rvalue_visitor.h"
>
>   extern "C" {
>   #include "main/shaderobj.h"
>   }
>
> +void linker_error(gl_shader_program *, const char *, ...);
> +
>   /**
>    * Visitor that determines whether or not a variable is ever written.
>    */
> @@ -174,6 +177,77 @@ private:
>   };
>
>
> +class geom_array_resize_visitor : public ir_hierarchical_visitor {

This looks like it might be the code to cross-validate

layout(triangles)
in vec4 foo[3];
in vec4 foo[2];

and such.  But only in part?  It might be nice to have that in a 
separate patch as well...it's complicated enough to not be lumped in 
with basic plumbing.

> +public:
> +   unsigned num_vertices;
> +   gl_shader_program *prog;
> +
> +   geom_array_resize_visitor(unsigned num_vertices, gl_shader_program *prog)
> +   {
> +      this->num_vertices = num_vertices;
> +      this->prog = prog;
> +   }
> +
> +   virtual ~geom_array_resize_visitor()
> +   {
> +      /* empty */
> +   }
> +
> +   virtual ir_visitor_status visit(ir_variable *var)
> +   {
> +      if (!var->type->is_array() || var->mode != ir_var_shader_in)
> +         return visit_continue;
> +
> +      unsigned size = var->type->length;
> +
> +      /* Generate a link error if the shader has declared this array with an
> +       * incorrect size.
> +       */
> +      if (size && size != this->num_vertices) {
> +         linker_error(this->prog, "size of array %s declared as %u, "
> +                      "but number of input vertices is %u\n",
> +                      var->name, size, this->num_vertices);
> +         return visit_continue;
> +      }
> +
> +      /* Generate a link error if the shader attempts to access an input
> +       * array using an index too large for its actual size assigned at link
> +       * time.
> +       */
> +      if (var->max_array_access >= this->num_vertices) {
> +         linker_error(this->prog, "geometry shader accesses element %i of "
> +                      "%s, but only %i input vertices\n",
> +                      var->max_array_access, var->name, this->num_vertices);
> +         return visit_continue;
> +      }
> +
> +      var->type = glsl_type::get_array_instance(var->type->element_type(),
> +                                                this->num_vertices);
> +      var->max_array_access = this->num_vertices - 1;
> +
> +      return visit_continue;
> +   }
> +
> +   /* Dereferences of input variables need to be updated so that their type
> +    * matches the newly assigned type of the variable they are accessing. */
> +   virtual ir_visitor_status visit(ir_dereference_variable *ir)
> +   {
> +      ir->type = ir->var->type;
> +      return visit_continue;
> +   }
> +
> +   /* Dereferences of 2D input arrays need to be updated so that their type
> +    * matches the newly assigned type of the array they are accessing. */
> +   virtual ir_visitor_status visit_leave(ir_dereference_array *ir)
> +   {
> +      const glsl_type *const vt = ir->array->type;
> +      if (vt->is_array())
> +         ir->type = vt->element_type();
> +      return visit_continue;
> +   }
> +};
> +
> +
>   void
>   linker_error(gl_shader_program *prog, const char *fmt, ...)
>   {
> @@ -437,6 +511,24 @@ validate_fragment_shader_executable(struct gl_shader_program *prog,
>      }
>   }
>
> +/**
> + * Verify that a geometry shader executable meets all semantic requirements
> + *
> + * Also sets prog->Geom.VerticesIn as a side effect.
> + *
> + * \param shader Geometry shader executable to be verified
> + */
> +void
> +validate_geometry_shader_executable(struct gl_shader_program *prog,
> +				    struct gl_shader *shader)
> +{
> +   if (shader == NULL)
> +      return;
> +
> +   unsigned num_vertices = vertices_per_prim(prog->Geom.InputType);
> +   prog->Geom.VerticesIn = num_vertices;
> +}
> +
>
>   /**
>    * Generate a string describing the mode of a variable
> @@ -1091,6 +1183,16 @@ link_intrastage_shaders(void *mem_ctx,
>      if (linked)
>         validate_ir_tree(linked->ir);
>
> +   /* Set the size of geometry shader input arrays */
> +   if (linked->Type == GL_GEOMETRY_SHADER) {
> +      unsigned num_vertices = vertices_per_prim(prog->Geom.InputType);
> +      geom_array_resize_visitor input_resize_visitor(num_vertices, prog);
> +      foreach_iter(exec_list_iterator, iter, *linked->ir) {
> +         ir_instruction *ir = (ir_instruction *)iter.get();
> +         ir->accept(&input_resize_visitor);
> +      }
> +   }
> +
>      /* Make a pass over all variable declarations to ensure that arrays with
>       * unspecified sizes have a size specified.  The size is inferred from the
>       * max_array_access field.
> @@ -1648,10 +1750,13 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>      unsigned num_vert_shaders = 0;
>      struct gl_shader **frag_shader_list;
>      unsigned num_frag_shaders = 0;
> +   struct gl_shader **geom_shader_list;
> +   unsigned num_geom_shaders = 0;
>
>      vert_shader_list = (struct gl_shader **)
> -      calloc(2 * prog->NumShaders, sizeof(struct gl_shader *));
> +      calloc(3 * prog->NumShaders, sizeof(struct gl_shader *));
>      frag_shader_list =  &vert_shader_list[prog->NumShaders];
> +   geom_shader_list =  &vert_shader_list[prog->NumShaders * 2];

This code is getting ugly.  It looks like the idea is to allocate two 
(now three) separate arrays, but somebody decided to be "clever" and 
batch them into a single calloc/free big enough to hold all of them.

I would much prefer to see:

    struct gl_shader **vert_shader_list =
       calloc(prog->NumShaders, sizeof(struct gl_shader *));
    struct gl_shader **frag_shader_list =
       calloc(prog->NumShaders, sizeof(struct gl_shader *));
    struct gl_shader **geom_shader_list =
       calloc(prog->NumShaders, sizeof(struct gl_shader *));

and then later:

    free(vert_shader_list);
    free(frag_shader_list);
    free(geom_shader_list);

Linking is complicated enough without accidental complexity.

>      unsigned min_version = UINT_MAX;
>      unsigned max_version = 0;
> @@ -1677,8 +1782,8 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>   	 num_frag_shaders++;
>   	 break;
>         case GL_GEOMETRY_SHADER:
> -	 /* FINISHME: Support geometry shaders. */
> -	 assert(prog->Shaders[i]->Type != GL_GEOMETRY_SHADER);
> +	 geom_shader_list[num_geom_shaders] = prog->Shaders[i];
> +	 num_geom_shaders++;
>   	 break;
>         }
>      }
> @@ -1740,6 +1845,22 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>   			     sh);
>      }
>
> +   if (num_geom_shaders > 0) {
> +      gl_shader *const sh =
> +	 link_intrastage_shaders(mem_ctx, ctx, prog, geom_shader_list,
> +				 num_geom_shaders);
> +
> +      if (!prog->LinkStatus)
> +	 goto done;
> +
> +      validate_geometry_shader_executable(prog, sh);
> +      if (!prog->LinkStatus)
> +	 goto done;
> +
> +      _mesa_reference_shader(ctx, &prog->_LinkedShaders[MESA_SHADER_GEOMETRY],
> +			     sh);
> +   }
> +
>      /* Here begins the inter-stage linking phase.  Some initial validation is
>       * performed, then locations are assigned for uniforms, attributes, and
>       * varyings.
> @@ -1826,7 +1947,11 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>               prog->_LinkedShaders[MESA_SHADER_VERTEX],
>               VERT_ATTRIB_GENERIC0, VARYING_SLOT_VAR0);
>      }
> -   /* FINISHME: Geometry shaders not implemented yet */
> +   if (prog->_LinkedShaders[MESA_SHADER_GEOMETRY] != NULL) {
> +      link_invalidate_variable_locations(
> +            prog->_LinkedShaders[MESA_SHADER_GEOMETRY],
> +            VARYING_SLOT_VAR0, VARYING_SLOT_VAR0);
> +   }
>      if (prog->_LinkedShaders[MESA_SHADER_FRAGMENT] != NULL) {
>         link_invalidate_variable_locations(
>               prog->_LinkedShaders[MESA_SHADER_FRAGMENT],
> @@ -1860,7 +1985,7 @@ link_shaders(struct gl_context *ctx, struct gl_shader_program *prog)
>          *     non-zero, but the program object has no vertex or geometry
>          *     shader;
>          */
> -      if (first >= MESA_SHADER_FRAGMENT) {
> +      if (first == MESA_SHADER_FRAGMENT) {

This hunk is unnecessary (but harmless).

>            linker_error(prog, "Transform feedback varyings specified, but "
>                         "no vertex or geometry shader is present.");
>            goto done;
> diff --git a/src/mesa/drivers/dri/i965/brw_shader.cpp b/src/mesa/drivers/dri/i965/brw_shader.cpp
> index 3322e80..418ea9b 100644
> --- a/src/mesa/drivers/dri/i965/brw_shader.cpp
> +++ b/src/mesa/drivers/dri/i965/brw_shader.cpp
> @@ -236,8 +236,7 @@ brw_link_shader(struct gl_context *ctx, struct gl_shader_program *shProg)
>         reparent_ir(shader->ir, shader->ir);
>         ralloc_free(mem_ctx);
>
> -      do_set_program_inouts(shader->ir, prog,
> -			    shader->base.Type == GL_FRAGMENT_SHADER);
> +      do_set_program_inouts(shader->ir, prog, shader->base.Type);
>
>         prog->SamplersUsed = shader->base.active_samplers;
>         _mesa_update_shader_textures_used(shProg, prog);
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index efa2d39..2725eef 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -1851,7 +1851,7 @@ struct gl_program
>      GLuint Id;
>      GLubyte *String;  /**< Null-terminated program text */
>      GLint RefCount;
> -   GLenum Target;    /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB */
> +   GLenum Target;    /**< GL_VERTEX/FRAGMENT_PROGRAM_ARB, GL_GEOMETRY_PROGRAM_NV */
>      GLenum Format;    /**< String encoding format */
>
>      struct prog_instruction *Instructions;
> @@ -1918,6 +1918,7 @@ struct gl_geometry_program
>   {
>      struct gl_program Base;   /**< base class */
>
> +   GLint VerticesIn;
>      GLint VerticesOut;
>      GLenum InputType;  /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
>                              GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
> @@ -2320,6 +2321,7 @@ struct gl_shader_program
>
>      /** Geometry shader state - copied into gl_geometry_program at link time */
>      struct {
> +      GLint VerticesIn;
>         GLint VerticesOut;
>         GLenum InputType;  /**< GL_POINTS, GL_LINES, GL_LINES_ADJACENCY_ARB,
>                                 GL_TRIANGLES, or GL_TRIANGLES_ADJACENCY_ARB */
> diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp
> index e526582..914aca4 100644
> --- a/src/mesa/program/ir_to_mesa.cpp
> +++ b/src/mesa/program/ir_to_mesa.cpp
> @@ -2975,7 +2975,7 @@ get_mesa_program(struct gl_context *ctx,
>       */
>      mesa_instructions = NULL;
>
> -   do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
> +   do_set_program_inouts(shader->ir, prog, shader->Type);
>
>      prog->SamplersUsed = shader->active_samplers;
>      prog->ShadowSamplers = shader->shadow_samplers;
> diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> index 77623f9..52e44ad 100644
> --- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> +++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
> @@ -5128,7 +5128,7 @@ get_mesa_program(struct gl_context *ctx,
>      prog->Instructions = NULL;
>      prog->NumInstructions = 0;
>
> -   do_set_program_inouts(shader->ir, prog, shader->Type == GL_FRAGMENT_SHADER);
> +   do_set_program_inouts(shader->ir, prog, shader->Type);
>      count_resources(v, prog);
>
>      _mesa_reference_program(ctx, &shader->Program, prog);
>



More information about the mesa-dev mailing list