[Mesa-dev] [PATCH 10/13] glsl: Add a lowering pass for gl_VertexID

Tapani Pälli tapani.palli at intel.com
Tue Jul 29 23:51:36 PDT 2014


On 06/21/2014 04:01 AM, Ian Romanick wrote:
> From: Ian Romanick <ian.d.romanick at intel.com>
>
> Converts gl_VertexID to (gl_VertexIDMESA + gl_BaseVertex). gl_VertexIDMESA
> is backed by SYSTEM_VALUE_VERTEX_ID_ZERO_BASE, and gl_BaseVertex is backed
> by a built-in uniform from {STATE_INTERNAL, STATE_BASE_VERTEX}.
>
> NOTE: The enum has to be declared outside the struct or C++ just cannot
> find the values.  I tried many variations of scope resolution in
> linker.cpp, but could not make it do-the-right-thing.
>
> Signed-off-by: Ian Romanick <ian.d.romanick at intel.com>
> Cc: "10.2" <mesa-stable at lists.freedesktop.org>
> ---
>  src/glsl/Makefile.sources    |   1 +
>  src/glsl/ir_optimization.h   |   2 +
>  src/glsl/linker.cpp          |   7 ++
>  src/glsl/lower_vertex_id.cpp | 152 +++++++++++++++++++++++++++++++++++++++++++
>  src/mesa/main/context.c      |   5 ++
>  src/mesa/main/mtypes.h       |  14 ++++
>  6 files changed, 181 insertions(+)
>  create mode 100644 src/glsl/lower_vertex_id.cpp
>
> diff --git a/src/glsl/Makefile.sources b/src/glsl/Makefile.sources
> index b54eae7..b884d66 100644
> --- a/src/glsl/Makefile.sources
> +++ b/src/glsl/Makefile.sources
> @@ -77,6 +77,7 @@ LIBGLSL_FILES = \
>  	$(GLSL_SRCDIR)/lower_vec_index_to_swizzle.cpp \
>  	$(GLSL_SRCDIR)/lower_vector.cpp \
>  	$(GLSL_SRCDIR)/lower_vector_insert.cpp \
> +	$(GLSL_SRCDIR)/lower_vertex_id.cpp \
>  	$(GLSL_SRCDIR)/lower_output_reads.cpp \
>  	$(GLSL_SRCDIR)/lower_ubo_reference.cpp \
>  	$(GLSL_SRCDIR)/opt_algebraic.cpp \
> diff --git a/src/glsl/ir_optimization.h b/src/glsl/ir_optimization.h
> index b83c225..2892dc2 100644
> --- a/src/glsl/ir_optimization.h
> +++ b/src/glsl/ir_optimization.h
> @@ -125,6 +125,8 @@ bool optimize_redundant_jumps(exec_list *instructions);
>  bool optimize_split_arrays(exec_list *instructions, bool linked);
>  bool lower_offset_arrays(exec_list *instructions);
>  
> +bool lower_vertex_id(gl_shader *shader);
> +
>  ir_rvalue *
>  compare_index_block(exec_list *instructions, ir_variable *index,
>  		    unsigned base, unsigned components, void *mem_ctx);
> diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
> index 813108c..2e9a0b6 100644
> --- a/src/glsl/linker.cpp
> +++ b/src/glsl/linker.cpp
> @@ -1623,6 +1623,13 @@ link_intrastage_shaders(void *mem_ctx,
>        }
>     }
>  
> +   if (ctx->Const.VertexID != gl_VertexID_native) {
> +      /* FINISHME: The other lowering method is not yet implemented.
> +       */
> +      assert(ctx->Const.VertexID == gl_VertexID_using_uniform_gl_BaseVertex);
> +      lower_vertex_id(linked);
> +   }
> +
>     /* 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.
> diff --git a/src/glsl/lower_vertex_id.cpp b/src/glsl/lower_vertex_id.cpp
> new file mode 100644
> index 0000000..c9cced1
> --- /dev/null
> +++ b/src/glsl/lower_vertex_id.cpp
> @@ -0,0 +1,152 @@
> +/*
> + * Copyright © 2014 Intel Corporation
> + *
> + * Permission is hereby granted, free of charge, to any person obtaining a
> + * copy of this software and associated documentation files (the "Software"),
> + * to deal in the Software without restriction, including without limitation
> + * the rights to use, copy, modify, merge, publish, distribute, sublicense,
> + * and/or sell copies of the Software, and to permit persons to whom the
> + * Software is furnished to do so, subject to the following conditions:
> + *
> + * The above copyright notice and this permission notice (including the next
> + * paragraph) shall be included in all copies or substantial portions of the
> + * Software.
> + *
> + * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
> + * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
> + * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
> + * THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
> + * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
> + * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER
> + * DEALINGS IN THE SOFTWARE.
> + */
> +
> +/**
> + * \file lower_vertex_id.cpp
> + *
> + * There exists hardware, such as i965, that does not implement the OpenGL
> + * semantic for gl_VertexID.  Instead, that hardware does not include the
> + * value of basevertex in the gl_VertexID value.  To implement the OpenGL
> + * semantic, we'll have to convert gl_Vertex_ID to
> + * gl_VertexIDMESA+gl_BaseVertexMESA.
> + */
> +
> +#include "glsl_symbol_table.h"
> +#include "ir_hierarchical_visitor.h"
> +#include "ir.h"
> +#include "ir_builder.h"
> +#include "linker.h"
> +#include "program/prog_statevars.h"
> +
> +namespace {
> +
> +class lower_vertex_id_visitor : public ir_hierarchical_visitor {
> +public:
> +   explicit lower_vertex_id_visitor(ir_function_signature *main_sig,
> +                                    exec_list *ir_list)
> +      : progress(false), VertexID(NULL), gl_VertexID(NULL),
> +        gl_BaseVertex(NULL), main_sig(main_sig), ir_list(ir_list)
> +   {

This loop could be optimized a bit (?) by having shader as the
constructor parameter, initializing ir_list(shader->ir) and figuring out
variable from the symbol table:

var = shader->symbols->get_variable("gl_BaseVertex");

(would also need to add this variable to the symbol table when/if adding
it to IR below)

> +      foreach_list(node, ir_list) {
> +         ir_instruction *const ir = (ir_instruction *) node;
> +         ir_variable *const var = ir->as_variable();
> +
> +         if (var != NULL && strcmp(var->name, "gl_BaseVertex") == 0) {
> +            gl_BaseVertex = var;
> +            break;
> +         }
> +      }
> +   }
> +
> +   virtual ir_visitor_status visit(ir_dereference_variable *);
> +
> +   bool progress;
> +
> +private:
> +   ir_variable *VertexID;
> +   ir_variable *gl_VertexID;
> +   ir_variable *gl_BaseVertex;
> +
> +   ir_function_signature *main_sig;
> +   exec_list *ir_list;
> +};
> +
> +} /* anonymous namespace */
> +
> +ir_visitor_status
> +lower_vertex_id_visitor::visit(ir_dereference_variable *ir)
> +{
> +   if (strcmp(ir->var->name, "gl_VertexID") != 0)
> +      return visit_continue;
> +
> +   if (VertexID == NULL) {
> +      const glsl_type *const int_t = glsl_type::int_type;
> +      void *const mem_ctx = ralloc_parent(ir);
> +
> +      VertexID = new(mem_ctx) ir_variable(int_t, "__VertexID",
> +                                          ir_var_temporary);
> +      ir_list->push_head(VertexID);
> +
> +      gl_VertexID = new(mem_ctx) ir_variable(int_t, "gl_VertexIDMESA",
> +                                             ir_var_system_value);
> +      gl_VertexID->data.how_declared = ir_var_declared_implicitly;
> +      gl_VertexID->data.read_only = true;
> +      gl_VertexID->data.location = SYSTEM_VALUE_VERTEX_ID_ZERO_BASE;
> +      gl_VertexID->data.explicit_location = true;
> +      gl_VertexID->data.explicit_index = 0;
> +      ir_list->push_head(gl_VertexID);
> +
> +      if (gl_BaseVertex == NULL) {
> +         static const int slots[STATE_LENGTH] = {
> +            STATE_INTERNAL,
> +            STATE_BASE_VERTEX,
> +            0,
> +            0,
> +            0
> +         };
> +
> +         gl_BaseVertex = new(mem_ctx) ir_variable(int_t, "gl_BaseVertex",
> +                                                  ir_var_uniform);
> +         gl_BaseVertex->num_state_slots = 1;
> +         gl_BaseVertex->state_slots =
> +            ralloc_array(gl_BaseVertex, ir_state_slot,
> +                         gl_BaseVertex->num_state_slots);
> +         memcpy(gl_BaseVertex->state_slots, slots, sizeof(slots));
> +
> +         ir_list->push_head(gl_BaseVertex);

(with my proposal wouild need to
shader->symbols_add_variable("gl_BaseVertex"); here)

> +      }
> +
> +      ir_instruction *const inst =
> +         ir_builder::assign(VertexID,
> +                            ir_builder::add(gl_VertexID, gl_BaseVertex));
> +
> +      main_sig->body.push_head(inst);
> +   }
> +
> +   ir->var = VertexID;
> +   progress = true;
> +
> +   return visit_continue;
> +}
> +
> +bool
> +lower_vertex_id(gl_shader *shader)
> +{
> +   /* gl_VertexID only exists in the vertex shader.
> +    */
> +   if (shader->Stage != MESA_SHADER_VERTEX)
> +      return false;
> +
> +   ir_function_signature *const main_sig =
> +      link_get_main_function_signature(shader);
> +   if (main_sig == NULL) {
> +      assert(main_sig != NULL);
> +      return false;
> +   }
> +
> +   lower_vertex_id_visitor v(main_sig, shader->ir);
> +
> +   v.run(shader->ir);
> +
> +   return v.progress;
> +}
> diff --git a/src/mesa/main/context.c b/src/mesa/main/context.c
> index 244e63e..40a3a2c 100644
> --- a/src/mesa/main/context.c
> +++ b/src/mesa/main/context.c
> @@ -622,6 +622,11 @@ _mesa_init_constants(struct gl_context *ctx)
>     ctx->Const.MaxProgramMatrices = MAX_PROGRAM_MATRICES;
>     ctx->Const.MaxProgramMatrixStackDepth = MAX_PROGRAM_MATRIX_STACK_DEPTH;
>  
> +   /* Assume that if GLSL 1.30+ (or GLSL ES 3.00+) is supported that
> +    * gl_VertexID is implemented using a native hardware register.
> +    */
> +   ctx->Const.VertexID = gl_VertexID_native;
> +
>     /* CheckArrayBounds is overriden by drivers/x11 for X server */
>     ctx->Const.CheckArrayBounds = GL_FALSE;
>  
> diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h
> index c66a16a..e581008 100644
> --- a/src/mesa/main/mtypes.h
> +++ b/src/mesa/main/mtypes.h
> @@ -3335,6 +3335,11 @@ struct gl_program_constants
>     GLuint MaxImageUniforms;
>  };
>  
> +enum _mesa_VertexID_mode {
> +   gl_VertexID_native,
> +   gl_VertexID_using_system_gl_BaseVertex,
> +   gl_VertexID_using_uniform_gl_BaseVertex
> +};
>  
>  /**
>   * Constants which may be overridden by device driver during context creation
> @@ -3444,6 +3449,15 @@ struct gl_constants
>     GLboolean NativeIntegers;
>  
>     /**
> +    * Method used to implement gl_VertexID
> +    *
> +    * \note
> +    * If desktop GLSL 1.30 or GLSL ES 3.00 are not supported, this field is
> +    * ignored and need not be set.
> +    */
> +   enum _mesa_VertexID_mode VertexID;
> +
> +   /**
>      * If the driver supports real 32-bit integers, what integer value should be
>      * used for boolean true in uniform uploads?  (Usually 1 or ~0.)
>      */



More information about the mesa-dev mailing list