[Mesa-dev] [PATCH] nir/xfb: Properly align 64-bit values

Jason Ekstrand jason at jlekstrand.net
Tue Feb 12 19:22:48 UTC 2019


Fixes: 19064b8c "nir: Add a pass for gathering transform feedback info"
Cc: Alejandro PiƱeiro <apinheiro at igalia.com>
---
 src/compiler/nir/nir_gather_xfb_info.c | 44 ++++++++++++++++++++++++++
 1 file changed, 44 insertions(+)

diff --git a/src/compiler/nir/nir_gather_xfb_info.c b/src/compiler/nir/nir_gather_xfb_info.c
index 96f0ece5e75..fb736dfeb17 100644
--- a/src/compiler/nir/nir_gather_xfb_info.c
+++ b/src/compiler/nir/nir_gather_xfb_info.c
@@ -72,6 +72,50 @@ 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;
 
+      /* From version 4.60 of the GLSL spec:
+       *
+       *    "Variables and block members qualified with xfb_offset can be
+       *    scalars, vectors, matrices, structures, and (sized) arrays of
+       *    these. The offset must be a multiple of the size of the first
+       *    component of the first qualified variable or block member, or a
+       *    compile-time error results. Further, if applied to an aggregate
+       *    containing a double, the offset must also be a multiple of 8, and
+       *    the space taken in the buffer will be a multiple of 8. The given
+       *    offset applies to the first component of the first member of the
+       *    qualified entity. Then, within the qualified entity, subsequent
+       *    components are each assigned, in order, to the next available
+       *    offset aligned to a multiple of that component's size. Aggregate
+       *    types are flattened down to the component level to get this
+       *    sequence of components."
+       *
+       * We need to align each element to the component size in order to get
+       * the correct layout.  We do this at the component level and don't try
+       * to align entire aggregate types such as structs because of the last
+       * sentence which says that aggregate types are treated as flattened to
+       * components.  In other words, if we have
+       *
+       *    struct A {
+       *       int a;
+       *       double b;
+       *    };
+       *
+       *    struct B {
+       *       int b
+       *       A a;
+       *    };
+       *
+       *    layout (...) out B o;
+       *
+       * then we treat it as if struct A was embedded struct B and o.a.b has
+       * an offset of 8.  If we tried to apply the alignment rule to nested
+       * structs and didn't flatten, o.a would have an offset of 8 because it
+       * contains a double and o.a.b would then have an offset of 16.
+       * However, thanks to the above GLSL rule, o.b and o.a.a are tightly
+       * packed and there is no gap.
+       */
+      if (glsl_type_is_64bit(type))
+         *offset = ALIGN_POT(*offset, 8);
+
       assert(attrib_slots <= 2);
       for (unsigned s = 0; s < attrib_slots; s++) {
          nir_xfb_output_info *output = &xfb->outputs[xfb->output_count++];
-- 
2.20.1



More information about the mesa-dev mailing list