[Mesa-dev] [PATCH] glsl_to_tgsi: indirect array information

Vadim Girlin vadimgirlin at gmail.com
Mon Jan 21 12:10:28 PST 2013


Provide the information about indirectly addressable arrays (ranges of temps) in
the shader to the drivers. TGSI representation itself isn't modified, array
information is passed as an additional data in the pipe_shader_state, so the
drivers can use it as a hint for optimization.
---

It's far from being an ideal solution, but I saw the discussions about that
problem starting from 2009 IIRC, and we still have no solution (neither good
nor bad) despite the years passed. I hope we can use this not very intrusive
approach until we get something better.

 src/gallium/auxiliary/tgsi/tgsi_ureg.c     |  2 ++
 src/gallium/include/pipe/p_state.h         | 13 +++++++
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 57 +++++++++++++++++++++++++-----
 src/mesa/state_tracker/st_program.c        |  4 +++
 src/mesa/state_tracker/st_program.h        |  1 +
 5 files changed, 69 insertions(+), 8 deletions(-)

diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
index 3c2a923..61db431 100644
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c
@@ -1658,6 +1658,8 @@ void *ureg_create_shader( struct ureg_program *ureg,
    else
       memset(&state.stream_output, 0, sizeof(state.stream_output));
 
+   memset(&state.array_info, 0, sizeof(state.array_info));
+
    if (ureg->processor == TGSI_PROCESSOR_VERTEX)
       return pipe->create_vs_state( pipe, &state );
    else
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h
index ab49cab..4490f2e 100644
--- a/src/gallium/include/pipe/p_state.h
+++ b/src/gallium/include/pipe/p_state.h
@@ -65,6 +65,8 @@ extern "C" {
 #define PIPE_MAX_TEXTURE_LEVELS   16
 #define PIPE_MAX_SO_BUFFERS        4
 
+#define PIPE_MAX_INDIRECT_ARRAYS  16
+
 
 struct pipe_reference
 {
@@ -205,11 +207,22 @@ struct pipe_stream_output_info
    } output[PIPE_MAX_SHADER_OUTPUTS];
 };
 
+struct pipe_shader_indirect_array {
+   unsigned index:16;
+   unsigned size:16;
+};
+
+struct pipe_shader_array_info
+{
+   struct pipe_shader_indirect_array arrays[PIPE_MAX_INDIRECT_ARRAYS];
+   unsigned num_arrays;
+};
 
 struct pipe_shader_state
 {
    const struct tgsi_token *tokens;
    struct pipe_stream_output_info stream_output;
+   struct pipe_shader_array_info array_info;
 };
 
 
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 1d96e90..4ded1be 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -110,6 +110,7 @@ public:
       this->index2D = 0;
       this->type = type ? type->base_type : GLSL_TYPE_ERROR;
       this->reladdr = NULL;
+      this->size = 0;
    }
 
    st_src_reg(gl_register_file file, int index, int type)
@@ -121,6 +122,7 @@ public:
       this->swizzle = SWIZZLE_XYZW;
       this->negate = 0;
       this->reladdr = NULL;
+      this->size = 0;
    }
 
    st_src_reg(gl_register_file file, int index, int type, int index2D)
@@ -132,6 +134,7 @@ public:
       this->swizzle = SWIZZLE_XYZW;
       this->negate = 0;
       this->reladdr = NULL;
+      this->size = 0;
    }
 
    st_src_reg()
@@ -143,6 +146,7 @@ public:
       this->swizzle = 0;
       this->negate = 0;
       this->reladdr = NULL;
+      this->size = 0;
    }
 
    explicit st_src_reg(st_dst_reg reg);
@@ -155,6 +159,7 @@ public:
    int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */
    /** Register index should be offset by the integer in this reg. */
    st_src_reg *reladdr;
+   int size;
 };
 
 class st_dst_reg {
@@ -244,8 +249,9 @@ public:
 
 class variable_storage : public exec_node {
 public:
-   variable_storage(ir_variable *var, gl_register_file file, int index)
-      : file(file), index(index), var(var)
+   variable_storage(ir_variable *var, gl_register_file file, int index,
+                    int size = 0)
+      : file(file), index(index), var(var), size(size)
    {
       /* empty */
    }
@@ -253,6 +259,7 @@ public:
    gl_register_file file;
    int index;
    ir_variable *var; /* variable that maps to this, if any */
+   int size;
 };
 
 class immediate_storage : public exec_node {
@@ -312,6 +319,7 @@ public:
    struct gl_program *prog;
    struct gl_shader_program *shader_program;
    struct gl_shader_compiler_options *options;
+   struct pipe_shader_array_info array_info;
 
    int next_temp;
 
@@ -445,6 +453,8 @@ public:
    void emit_block_mov(ir_assignment *ir, const struct glsl_type *type,
                        st_dst_reg *l, st_src_reg *r);
 
+   void add_array_info(const st_src_reg *src);
+
    void *mem_ctx;
 };
 
@@ -1004,7 +1014,8 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)
    src.file = PROGRAM_TEMPORARY;
    src.index = next_temp;
    src.reladdr = NULL;
-   next_temp += type_size(type);
+   src.size = type_size(type);
+   next_temp += src.size;
 
    if (type->is_array() || type->is_record()) {
       src.swizzle = SWIZZLE_NOOP;
@@ -1075,9 +1086,10 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)
          assert((int) ir->num_state_slots == type_size(ir->type));
 
          storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,
-        					 this->next_temp);
+                                                 this->next_temp,
+                                                 type_size(ir->type));
          this->variables.push_tail(storage);
-         this->next_temp += type_size(ir->type);
+         this->next_temp += storage->size;
 
          dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,
                native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT));
@@ -2029,10 +2041,10 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
       case ir_var_auto:
       case ir_var_temporary:
          entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,
-        				       this->next_temp);
+                                               this->next_temp,
+                                               type_size(var->type));
          this->variables.push_tail(entry);
-
-         next_temp += type_size(var->type);
+         next_temp += entry->size;
          break;
       }
 
@@ -2043,6 +2055,8 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
    }
 
    this->result = st_src_reg(entry->file, entry->index, var->type);
+   this->result.size = entry->size;
+
    if (!native_integers)
       this->result.type = GLSL_TYPE_FLOAT;
 }
@@ -2062,12 +2076,16 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
    if (index) {
       src.index += index->value.i[0] * element_size;
    } else {
+
       /* Variable index array dereference.  It eats the "vec4" of the
        * base of the array and an index that offsets the TGSI register
        * index.
        */
       ir->array_index->accept(this);
 
+      if (src.size > 1 && src.file == PROGRAM_TEMPORARY)
+         add_array_info(&src);
+
       st_src_reg index_reg;
 
       if (element_size == 1) {
@@ -2969,6 +2987,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()
    prog = NULL;
    shader_program = NULL;
    options = NULL;
+   array_info.num_arrays = 0;
 }
 
 glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()
@@ -3771,6 +3790,23 @@ glsl_to_tgsi_visitor::renumber_registers(void)
    this->next_temp = new_index;
 }
 
+void
+glsl_to_tgsi_visitor::add_array_info(const st_src_reg *src)
+{
+   unsigned i;
+
+   if (array_info.num_arrays == PIPE_MAX_INDIRECT_ARRAYS)
+      return;
+
+   for (i = 0; i < array_info.num_arrays; ++i) {
+      if (array_info.arrays[i].index == (unsigned)src->index)
+         return;
+   }
+   array_info.arrays[i].index = src->index;
+   array_info.arrays[i].size = src->size;
+   ++array_info.num_arrays;
+}
+
 /**
  * Returns a fragment program which implements the current pixel transfer ops.
  * Based on get_pixel_transfer_program in st_atom_pixeltransfer.c.
@@ -4798,6 +4834,11 @@ st_translate_program(
    }
 
    if (program->indirect_addr_temps) {
+      struct pipe_shader_array_info *ai =
+         &((struct st_fragment_program*) proginfo)->array_info;
+
+      memcpy(ai, &program->array_info, sizeof(struct pipe_shader_array_info));
+
       /* If temps are accessed with indirect addressing, declare temporaries
        * in sequential order.  Else, we declare them on demand elsewhere.
        * (Note: the number of temporaries is equal to program->next_temp)
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c
index a9111b5..1370c76 100644
--- a/src/mesa/state_tracker/st_program.c
+++ b/src/mesa/state_tracker/st_program.c
@@ -739,6 +739,10 @@ st_translate_fragment_program(struct st_context *st,
                                 fs_output_semantic_index, FALSE,
                                 key->clamp_color);
 
+   if (stfp->glsl_to_tgsi)
+      memcpy(&variant->tgsi.array_info, &stfp->array_info,
+             sizeof(struct pipe_shader_array_info));
+
    variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );
    ureg_destroy( ureg );
 
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h
index 23a262c..d6b2b0f 100644
--- a/src/mesa/state_tracker/st_program.h
+++ b/src/mesa/state_tracker/st_program.h
@@ -90,6 +90,7 @@ struct st_fragment_program
 {
    struct gl_fragment_program Base;
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;
+   struct pipe_shader_array_info array_info;
 
    struct st_fp_variant *variants;
 };
-- 
1.8.1



More information about the mesa-dev mailing list