nir: fix lowering arrays to elements for XFB outputs
authorSamuel Pitoiset <samuel.pitoiset@gmail.com>
Mon, 10 Sep 2018 19:59:31 +0000 (21:59 +0200)
committerJason Ekstrand <jason.ekstrand@intel.com>
Tue, 22 Jan 2019 16:42:56 +0000 (10:42 -0600)
If we have a transform feedback output like:

float[2] x2_out (VARYING_SLOT_VAR1.x, 0, 0)

which is lowered by nir_lower_io_arrays_to_elements to,

float x2_out (VARYING_SLOT_VAR1.x, 0, 0)
float x2_out@5 (VARYING_SLOT_VAR2.x, 0, 0)

We have to update the destination offset to avoid overwriting
the same value.

v2 (Jason Ekstrand):
 - Compute the correct offsets for arrays of vectors and/or doubles

Reviewed-by: Jason Ekstrand <jason@jlekstrand.net>
Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
src/compiler/nir/nir_lower_io_arrays_to_elements.c

index 9051d397fbcf48a4ce5e3d1a4e550e99e4aa1494..73b6810b763de5fadf64491c0af84995ea0c5901 100644 (file)
@@ -34,7 +34,8 @@
 
 static unsigned
 get_io_offset(nir_builder *b, nir_deref_instr *deref, nir_variable *var,
-              unsigned *element_index, nir_ssa_def **vertex_index)
+              unsigned *element_index, unsigned *xfb_offset,
+              nir_ssa_def **vertex_index)
 {
    nir_deref_path path;
    nir_deref_path_init(&path, deref, NULL);
@@ -51,6 +52,7 @@ get_io_offset(nir_builder *b, nir_deref_instr *deref, nir_variable *var,
    }
 
    unsigned offset = 0;
+   *xfb_offset = 0;
    for (; *p; p++) {
       if ((*p)->deref_type == nir_deref_type_array) {
          /* must not be indirect dereference */
@@ -59,6 +61,8 @@ get_io_offset(nir_builder *b, nir_deref_instr *deref, nir_variable *var,
          unsigned size = glsl_count_attribute_slots((*p)->type, false);
          offset += size * index;
 
+         xfb_offset += index * glsl_get_component_slots((*p)->type) * 4;
+
          unsigned num_elements = glsl_type_is_array((*p)->type) ?
             glsl_get_aoa_size((*p)->type) : 1;
 
@@ -116,14 +120,19 @@ lower_array(nir_builder *b, nir_intrinsic_instr *intr, nir_variable *var,
 
    nir_ssa_def *vertex_index = NULL;
    unsigned elements_index = 0;
+   unsigned xfb_offset = 0;
    unsigned io_offset = get_io_offset(b, nir_src_as_deref(intr->src[0]),
-                                      var, &elements_index, &vertex_index);
+                                      var, &elements_index, &xfb_offset,
+                                      &vertex_index);
 
    nir_variable *element = elements[elements_index];
    if (!element) {
          element = nir_variable_clone(var, b->shader);
          element->data.location =  var->data.location + io_offset;
 
+         if (var->data.explicit_offset)
+            element->data.offset = var->data.offset + xfb_offset;
+
          const struct glsl_type *type = glsl_without_array(element->type);
 
          /* This pass also splits matrices so we need give them a new type. */