[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