[Mesa-dev] [PATCH 09/13] st/glsl_to_tgsi: mark "gaps" in input/output arrays as used

Nicolai Hähnle nhaehnle at gmail.com
Fri Oct 7 19:55:20 UTC 2016


From: Nicolai Hähnle <nicolai.haehnle at amd.com>

In some cases, a shader may have an input/output array but not use some
entries in the middle. This happens with eON games, for example.

We emit declarations that cover the entire array range even if there are
some unused gaps. This patch now reflects that in the InputsRead etc.
fields to ensure the various input/outputMapping arrays are actually
correct, which will be important when we re-jiggle the way declarations
are emitted.
---
 src/mesa/state_tracker/st_glsl_to_tgsi.cpp | 32 ++++++++++++++++++++++--------
 1 file changed, 24 insertions(+), 8 deletions(-)

diff --git a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
index 66ce24c..aac80ee 100644
--- a/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
+++ b/src/mesa/state_tracker/st_glsl_to_tgsi.cpp
@@ -2451,68 +2451,84 @@ glsl_to_tgsi_visitor::visit(ir_dereference_variable *ir)
    this->result = st_src_reg(entry->file, entry->index, var->type);
    this->result.array_id = entry->array_id;
    if (this->shader->Stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_in && var->type->is_double())
       this->result.is_double_vertex_input = true;
    if (!native_integers)
       this->result.type = GLSL_TYPE_FLOAT;
 }
 
 static void
 shrink_array_declarations(struct array_decl *arrays, unsigned count,
-                          GLbitfield64 usage_mask,
+                          GLbitfield64* usage_mask,
                           GLbitfield64 double_usage_mask,
-                          GLbitfield patch_usage_mask)
+                          GLbitfield* patch_usage_mask)
 {
    unsigned i;
    int j;
 
    /* Fix array declarations by removing unused array elements at both ends
     * of the arrays. For example, mat4[3] where only mat[1] is used.
     */
    for (i = 0; i < count; i++) {
       struct array_decl *decl = &arrays[i];
 
       /* Shrink the beginning. */
       for (j = 0; j < (int)decl->array_size; j++) {
          if (decl->mesa_index >= VARYING_SLOT_PATCH0) {
-            if (patch_usage_mask &
+            if (*patch_usage_mask &
                 BITFIELD64_BIT(decl->mesa_index - VARYING_SLOT_PATCH0 + j))
                break;
          }
          else {
-            if (usage_mask & BITFIELD64_BIT(decl->mesa_index+j))
+            if (*usage_mask & BITFIELD64_BIT(decl->mesa_index+j))
                break;
             if (double_usage_mask & BITFIELD64_BIT(decl->mesa_index+j-1))
                break;
          }
 
          decl->mesa_index++;
          decl->array_size--;
          j--;
       }
 
       /* Shrink the end. */
       for (j = decl->array_size-1; j >= 0; j--) {
          if (decl->mesa_index >= VARYING_SLOT_PATCH0) {
-            if (patch_usage_mask &
+            if (*patch_usage_mask &
                 BITFIELD64_BIT(decl->mesa_index - VARYING_SLOT_PATCH0 + j))
                break;
          }
          else {
-            if (usage_mask & BITFIELD64_BIT(decl->mesa_index+j))
+            if (*usage_mask & BITFIELD64_BIT(decl->mesa_index+j))
                break;
             if (double_usage_mask & BITFIELD64_BIT(decl->mesa_index+j-1))
                break;
          }
 
          decl->array_size--;
       }
+
+      /* When not all entries of an array are accessed, we mark them as uesd
+       * here anyway, to ensure that the input/output mapping logic doesn't get
+       * confused.
+       *
+       * TODO This happens when an array isn't used via indirect access, which
+       * some game ports do (at least eON-based). There is an optimization
+       * opportunity here by replacing the array declaration with non-array
+       * declarations of those slots that are actually used.
+       */
+      for (j = 1; j < (int)decl->array_size; ++j) {
+         if (decl->mesa_index >= VARYING_SLOT_PATCH0)
+            *patch_usage_mask |= BITFIELD64_BIT(decl->mesa_index - VARYING_SLOT_PATCH0 + j);
+         else
+            *usage_mask |= BITFIELD64_BIT(decl->mesa_index + j);
+      }
    }
 }
 
 void
 glsl_to_tgsi_visitor::visit(ir_dereference_array *ir)
 {
    ir_constant *index;
    st_src_reg src;
    int element_size = type_size(ir->type);
    bool is_2D = false;
@@ -6624,23 +6640,23 @@ get_mesa_program_tgsi(struct gl_context *ctx,
              shader_program->Name);
       _mesa_print_ir(_mesa_get_log_file(), shader->ir, NULL);
       _mesa_log("\n\n");
    }
 
    prog->Instructions = NULL;
    prog->NumInstructions = 0;
 
    do_set_program_inouts(shader->ir, prog, shader->Stage);
    shrink_array_declarations(v->input_arrays, v->num_input_arrays,
-                             prog->InputsRead, prog->DoubleInputsRead, prog->PatchInputsRead);
+                             &prog->InputsRead, prog->DoubleInputsRead, &prog->PatchInputsRead);
    shrink_array_declarations(v->output_arrays, v->num_output_arrays,
-                             prog->OutputsWritten, 0ULL, prog->PatchOutputsWritten);
+                             &prog->OutputsWritten, 0ULL, &prog->PatchOutputsWritten);
    count_resources(v, prog);
 
    /* The GLSL IR won't be needed anymore. */
    ralloc_free(shader->ir);
    shader->ir = NULL;
 
    /* This must be done before the uniform storage is associated. */
    if (shader->Stage == MESA_SHADER_FRAGMENT &&
        (prog->InputsRead & VARYING_BIT_POS ||
         prog->SystemValuesRead & (1 << SYSTEM_VALUE_FRAG_COORD))) {
-- 
2.7.4



More information about the mesa-dev mailing list