nir/gl_nir_lower_buffers: Set up align_mul/offset on UBOs.
nir_lower_to_explicit_io will give us good alignments if we have the
cast's alignment information known, and it's trivial: Just the offset of
the UBO variable that is at the base of the deref. Otherwise, explicit io
assumes the load is aligned just to the size of a scalar value in it.
The change in freedreno is in the noise.
Reviewed-by: Rob Clark <robdclark@chromium.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/6612>
diff --git a/src/compiler/glsl/gl_nir_lower_buffers.c b/src/compiler/glsl/gl_nir_lower_buffers.c
index b83df08..d78473d 100644
--- a/src/compiler/glsl/gl_nir_lower_buffers.c
+++ b/src/compiler/glsl/gl_nir_lower_buffers.c
@@ -182,6 +182,7 @@
b.cursor = nir_before_instr(&deref->instr);
+ unsigned offset = 0;
nir_ssa_def *ptr;
if (deref->deref_type == nir_deref_type_var &&
!glsl_type_is_interface(glsl_without_array(deref->var->type))) {
@@ -189,7 +190,7 @@
* containing one. We need the block index and its offset
* inside that block
*/
- unsigned index, offset;
+ unsigned index;
get_block_index_offset(deref->var, shader_program,
b.shader->info.stage,
&index, &offset);
@@ -201,7 +202,7 @@
*/
nir_ssa_def *index = get_block_array_index(&b, deref,
shader_program);
- ptr = nir_vec2(&b, index, nir_imm_int(&b, 0));
+ ptr = nir_vec2(&b, index, nir_imm_int(&b, offset));
} else {
/* This will get handled by nir_lower_explicit_io(). */
break;
@@ -209,6 +210,14 @@
nir_deref_instr *cast = nir_build_deref_cast(&b, ptr, deref->mode,
deref->type, 0);
+ /* Set the alignment on the cast so that we get good alignment out
+ * of nir_lower_explicit_io. Our offset to the start of the UBO
+ * variable is always a constant, so we can use the maximum
+ * align_mul.
+ */
+ cast->cast.align_mul = NIR_ALIGN_MUL_MAX;
+ cast->cast.align_offset = offset % NIR_ALIGN_MUL_MAX;
+
nir_ssa_def_rewrite_uses(&deref->dest.ssa,
nir_src_for_ssa(&cast->dest.ssa));
nir_deref_instr_remove_if_unused(deref);