nir/xfb: Work in terms of components rather than slots
authorJason Ekstrand <jason.ekstrand@intel.com>
Wed, 13 Feb 2019 22:22:37 +0000 (16:22 -0600)
committerJason Ekstrand <jason@jlekstrand.net>
Thu, 21 Feb 2019 00:08:42 +0000 (00:08 +0000)
We needed to better handle cases where a chunk of a variable starts at
some non-zero location_frac and rolls over into the next slot but may
not be more than 4 dwords.  For example, if gl_CullDistance is an array
of 3 things and has location_frac = 2, it will span across two vec4s but
is not, itself, bigger than a vec4.  If you ignore the clip/cull special
case, it's not allowed to happen for anything else because the only
things that can span more than one slot is dvec3 and dvec4 and they're
both bigger than a vec4.  The current code uses this attrib_slot thing
where we count attribute slots and iterate over them.  However, that
doesn't work in the case above because gl_CullDistance will have an
attrib_slot count of 1 even though it does span two slots.  We could fix
this by adjusting attrib_slot but we already have comp_mask and it's
easier to just handle it that way.

Reviewed-by: Alejandro PiƱeiro <apinheiro@igalia.com>
src/compiler/nir/nir_gather_xfb_info.c

index 446b7ac0495bf59ab04756a0691c7dcb2cdd79b6..081ef77b48a3896ca39decd497bd811da432fb19 100644 (file)
@@ -76,18 +76,18 @@ add_var_xfb_outputs(nir_xfb_info *xfb,
       assert(var->data.location_frac + comp_slots <= 8);
       uint8_t comp_mask = ((1 << comp_slots) - 1) << var->data.location_frac;
 
-      assert(attrib_slots <= 2);
-      for (unsigned s = 0; s < attrib_slots; s++) {
+      while (comp_mask) {
          nir_xfb_output_info *output = &xfb->outputs[xfb->output_count++];
 
          output->buffer = buffer;
-         output->offset = *offset + s * 16;
+         output->offset = *offset;
          output->location = *location;
-         output->component_mask = (comp_mask >> (s * 4)) & 0xf;
+         output->component_mask = comp_mask & 0xf;
 
+         *offset += util_bitcount(output->component_mask) * 4;
          (*location)++;
+         comp_mask >>= 4;
       }
-      *offset += comp_slots * 4;
    }
 }