Hi,<div><br></div><div>I'm not very familiar with the code, but I should mention that this should really help with the lima compiler backend. In fact, I was thinking of this very problem recently when figuring out how to translate TGSI into our backend. Fragment shaders on the Mali 200/400 have 6 vector registers, which cannot be indirectly addressed, and a large array of temporaries which can (and a similar situation for vertex shaders), so we need this information to determine whether we should use a register or temporary to hold each value. Basically, something like this is a prerequisite for a lima Gallium3D driver (assuming we go down that path).</div>
<div><br></div><div>Connor Abbott<br><br><div class="gmail_quote">On Mon, Jan 21, 2013 at 3:10 PM, Vadim Girlin <span dir="ltr"><<a href="mailto:vadimgirlin@gmail.com" target="_blank">vadimgirlin@gmail.com</a>></span> wrote:<br>
<blockquote class="gmail_quote" style="margin:0 0 0 .8ex;border-left:1px #ccc solid;padding-left:1ex">Provide the information about indirectly addressable arrays (ranges of temps) in<br>
the shader to the drivers. TGSI representation itself isn't modified, array<br>
information is passed as an additional data in the pipe_shader_state, so the<br>
drivers can use it as a hint for optimization.<br>
---<br>
<br>
It's far from being an ideal solution, but I saw the discussions about that<br>
problem starting from 2009 IIRC, and we still have no solution (neither good<br>
nor bad) despite the years passed. I hope we can use this not very intrusive<br>
approach until we get something better.<br>
<br>
 src/gallium/auxiliary/tgsi/tgsi_ureg.c     |  2 ++<br>
 src/gallium/include/pipe/p_state.h         | 13 +++++++<br>
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 57 +++++++++++++++++++++++++-----<br>
 src/mesa/state_tracker/st_program.c        |  4 +++<br>
 src/mesa/state_tracker/st_program.h        |  1 +<br>
 5 files changed, 69 insertions(+), 8 deletions(-)<br>
<br>
diff --git a/src/gallium/auxiliary/tgsi/tgsi_ureg.c b/src/gallium/auxiliary/tgsi/tgsi_ureg.c<br>
index 3c2a923..61db431 100644<br>
--- a/src/gallium/auxiliary/tgsi/tgsi_ureg.c<br>
+++ b/src/gallium/auxiliary/tgsi/tgsi_ureg.c<br>
@@ -1658,6 +1658,8 @@ void *ureg_create_shader( struct ureg_program *ureg,<br>
    else<br>
       memset(&state.stream_output, 0, sizeof(state.stream_output));<br>
<br>
+   memset(&state.array_info, 0, sizeof(state.array_info));<br>
+<br>
    if (ureg->processor == TGSI_PROCESSOR_VERTEX)<br>
       return pipe->create_vs_state( pipe, &state );<br>
    else<br>
diff --git a/src/gallium/include/pipe/p_state.h b/src/gallium/include/pipe/p_state.h<br>
index ab49cab..4490f2e 100644<br>
--- a/src/gallium/include/pipe/p_state.h<br>
+++ b/src/gallium/include/pipe/p_state.h<br>
@@ -65,6 +65,8 @@ extern "C" {<br>
 #define PIPE_MAX_TEXTURE_LEVELS   16<br>
 #define PIPE_MAX_SO_BUFFERS        4<br>
<br>
+#define PIPE_MAX_INDIRECT_ARRAYS  16<br>
+<br>
<br>
 struct pipe_reference<br>
 {<br>
@@ -205,11 +207,22 @@ struct pipe_stream_output_info<br>
    } output[PIPE_MAX_SHADER_OUTPUTS];<br>
 };<br>
<br>
+struct pipe_shader_indirect_array {<br>
+   unsigned index:16;<br>
+   unsigned size:16;<br>
+};<br>
+<br>
+struct pipe_shader_array_info<br>
+{<br>
+   struct pipe_shader_indirect_array arrays[PIPE_MAX_INDIRECT_ARRAYS];<br>
+   unsigned num_arrays;<br>
+};<br>
<br>
 struct pipe_shader_state<br>
 {<br>
    const struct tgsi_token *tokens;<br>
    struct pipe_stream_output_info stream_output;<br>
+   struct pipe_shader_array_info array_info;<br>
 };<br>
<br>
<br>
diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp<br>
index 1d96e90..4ded1be 100644<br>
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp<br>
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp<br>
@@ -110,6 +110,7 @@ public:<br>
       this->index2D = 0;<br>
       this->type = type ? type->base_type : GLSL_TYPE_ERROR;<br>
       this->reladdr = NULL;<br>
+      this->size = 0;<br>
    }<br>
<br>
    st_src_reg(gl_register_file file, int index, int type)<br>
@@ -121,6 +122,7 @@ public:<br>
       this->swizzle = SWIZZLE_XYZW;<br>
       this->negate = 0;<br>
       this->reladdr = NULL;<br>
+      this->size = 0;<br>
    }<br>
<br>
    st_src_reg(gl_register_file file, int index, int type, int index2D)<br>
@@ -132,6 +134,7 @@ public:<br>
       this->swizzle = SWIZZLE_XYZW;<br>
       this->negate = 0;<br>
       this->reladdr = NULL;<br>
+      this->size = 0;<br>
    }<br>
<br>
    st_src_reg()<br>
@@ -143,6 +146,7 @@ public:<br>
       this->swizzle = 0;<br>
       this->negate = 0;<br>
       this->reladdr = NULL;<br>
+      this->size = 0;<br>
    }<br>
<br>
    explicit st_src_reg(st_dst_reg reg);<br>
@@ -155,6 +159,7 @@ public:<br>
    int type; /** GLSL_TYPE_* from GLSL IR (enum glsl_base_type) */<br>
    /** Register index should be offset by the integer in this reg. */<br>
    st_src_reg *reladdr;<br>
+   int size;<br>
 };<br>
<br>
 class st_dst_reg {<br>
@@ -244,8 +249,9 @@ public:<br>
<br>
 class variable_storage : public exec_node {<br>
 public:<br>
-   variable_storage(ir_variable *var, gl_register_file file, int index)<br>
-      : file(file), index(index), var(var)<br>
+   variable_storage(ir_variable *var, gl_register_file file, int index,<br>
+                    int size = 0)<br>
+      : file(file), index(index), var(var), size(size)<br>
    {<br>
       /* empty */<br>
    }<br>
@@ -253,6 +259,7 @@ public:<br>
    gl_register_file file;<br>
    int index;<br>
    ir_variable *var; /* variable that maps to this, if any */<br>
+   int size;<br>
 };<br>
<br>
 class immediate_storage : public exec_node {<br>
@@ -312,6 +319,7 @@ public:<br>
    struct gl_program *prog;<br>
    struct gl_shader_program *shader_program;<br>
    struct gl_shader_compiler_options *options;<br>
+   struct pipe_shader_array_info array_info;<br>
<br>
    int next_temp;<br>
<br>
@@ -445,6 +453,8 @@ public:<br>
    void emit_block_mov(ir_assignment *ir, const struct glsl_type *type,<br>
                        st_dst_reg *l, st_src_reg *r);<br>
<br>
+   void add_array_info(const st_src_reg *src);<br>
+<br>
    void *mem_ctx;<br>
 };<br>
<br>
@@ -1004,7 +1014,8 @@ glsl_to_tgsi_visitor::get_temp(const glsl_type *type)<br>
    src.file = PROGRAM_TEMPORARY;<br>
    src.index = next_temp;<br>
    src.reladdr = NULL;<br>
-   next_temp += type_size(type);<br>
+   src.size = type_size(type);<br>
+   next_temp += src.size;<br>
<br>
    if (type->is_array() || type->is_record()) {<br>
       src.swizzle = SWIZZLE_NOOP;<br>
@@ -1075,9 +1086,10 @@ glsl_to_tgsi_visitor::visit(ir_variable *ir)<br>
          assert((int) ir->num_state_slots == type_size(ir->type));<br>
<br>
          storage = new(mem_ctx) variable_storage(ir, PROGRAM_TEMPORARY,<br>
-                                                this->next_temp);<br>
+                                                 this->next_temp,<br>
+                                                 type_size(ir->type));<br>
          this->variables.push_tail(storage);<br>
-         this->next_temp += type_size(ir->type);<br>
+         this->next_temp += storage->size;<br>
<br>
          dst = st_dst_reg(st_src_reg(PROGRAM_TEMPORARY, storage->index,<br>
                native_integers ? ir->type->base_type : GLSL_TYPE_FLOAT));<br>
@@ -2029,10 +2041,10 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)<br>
       case ir_var_auto:<br>
       case ir_var_temporary:<br>
          entry = new(mem_ctx) variable_storage(var, PROGRAM_TEMPORARY,<br>
-                                              this->next_temp);<br>
+                                               this->next_temp,<br>
+                                               type_size(var->type));<br>
          this->variables.push_tail(entry);<br>
-<br>
-         next_temp += type_size(var->type);<br>
+         next_temp += entry->size;<br>
          break;<br>
       }<br>
<br>
@@ -2043,6 +2055,8 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)<br>
    }<br>
<br>
    this->result = st_src_reg(entry->file, entry->index, var->type);<br>
+   this->result.size = entry->size;<br>
+<br>
    if (!native_integers)<br>
       this->result.type = GLSL_TYPE_FLOAT;<br>
 }<br>
@@ -2062,12 +2076,16 @@ glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)<br>
    if (index) {<br>
       src.index += index->value.i[0] * element_size;<br>
    } else {<br>
+<br>
       /* Variable index array dereference.  It eats the "vec4" of the<br>
        * base of the array and an index that offsets the TGSI register<br>
        * index.<br>
        */<br>
       ir->array_index->accept(this);<br>
<br>
+      if (src.size > 1 && src.file == PROGRAM_TEMPORARY)<br>
+         add_array_info(&src);<br>
+<br>
       st_src_reg index_reg;<br>
<br>
       if (element_size == 1) {<br>
@@ -2969,6 +2987,7 @@ glsl_to_tgsi_visitor::glsl_to_tgsi_visitor()<br>
    prog = NULL;<br>
    shader_program = NULL;<br>
    options = NULL;<br>
+   array_info.num_arrays = 0;<br>
 }<br>
<br>
 glsl_to_tgsi_visitor::~glsl_to_tgsi_visitor()<br>
@@ -3771,6 +3790,23 @@ glsl_to_tgsi_visitor::renumber_registers(void)<br>
    this->next_temp = new_index;<br>
 }<br>
<br>
+void<br>
+glsl_to_tgsi_visitor::add_array_info(const st_src_reg *src)<br>
+{<br>
+   unsigned i;<br>
+<br>
+   if (array_info.num_arrays == PIPE_MAX_INDIRECT_ARRAYS)<br>
+      return;<br>
+<br>
+   for (i = 0; i < array_info.num_arrays; ++i) {<br>
+      if (array_info.arrays[i].index == (unsigned)src->index)<br>
+         return;<br>
+   }<br>
+   array_info.arrays[i].index = src->index;<br>
+   array_info.arrays[i].size = src->size;<br>
+   ++array_info.num_arrays;<br>
+}<br>
+<br>
 /**<br>
  * Returns a fragment program which implements the current pixel transfer ops.<br>
  * Based on get_pixel_transfer_program in st_atom_pixeltransfer.c.<br>
@@ -4798,6 +4834,11 @@ st_translate_program(<br>
    }<br>
<br>
    if (program->indirect_addr_temps) {<br>
+      struct pipe_shader_array_info *ai =<br>
+         &((struct st_fragment_program*) proginfo)->array_info;<br>
+<br>
+      memcpy(ai, &program->array_info, sizeof(struct pipe_shader_array_info));<br>
+<br>
       /* If temps are accessed with indirect addressing, declare temporaries<br>
        * in sequential order.  Else, we declare them on demand elsewhere.<br>
        * (Note: the number of temporaries is equal to program->next_temp)<br>
diff --git a/src/mesa/state_tracker/st_program.c b/src/mesa/state_tracker/st_program.c<br>
index a9111b5..1370c76 100644<br>
--- a/src/mesa/state_tracker/st_program.c<br>
+++ b/src/mesa/state_tracker/st_program.c<br>
@@ -739,6 +739,10 @@ st_translate_fragment_program(struct st_context *st,<br>
                                 fs_output_semantic_index, FALSE,<br>
                                 key->clamp_color);<br>
<br>
+   if (stfp->glsl_to_tgsi)<br>
+      memcpy(&variant->tgsi.array_info, &stfp->array_info,<br>
+             sizeof(struct pipe_shader_array_info));<br>
+<br>
    variant->tgsi.tokens = ureg_get_tokens( ureg, NULL );<br>
    ureg_destroy( ureg );<br>
<br>
diff --git a/src/mesa/state_tracker/st_program.h b/src/mesa/state_tracker/st_program.h<br>
index 23a262c..d6b2b0f 100644<br>
--- a/src/mesa/state_tracker/st_program.h<br>
+++ b/src/mesa/state_tracker/st_program.h<br>
@@ -90,6 +90,7 @@ struct st_fragment_program<br>
 {<br>
    struct gl_fragment_program Base;<br>
    struct glsl_to_tgsi_visitor* glsl_to_tgsi;<br>
+   struct pipe_shader_array_info array_info;<br>
<br>
    struct st_fp_variant *variants;<br>
 };<br>
<span class="HOEnZb"><font color="#888888">--<br>
1.8.1<br>
<br>
_______________________________________________<br>
mesa-dev mailing list<br>
<a href="mailto:mesa-dev@lists.freedesktop.org">mesa-dev@lists.freedesktop.org</a><br>
<a href="http://lists.freedesktop.org/mailman/listinfo/mesa-dev" target="_blank">http://lists.freedesktop.org/mailman/listinfo/mesa-dev</a><br>
</font></span></blockquote></div><br></div>