broadcom/compiler: fix robust buffer access
Our implemention was bogus, it was only putting a cap on the offset based on the aligned buffer size and this doesn't ensure the access to the buffer happens within its valid range. I think the only reason we have been passing the tests is that we align all buffers sizes to 256B and the tests create buffers with a size that is smaller than that (like 64B). When get the size of the buffer from the shader, we get the actual bound range (so 64B in this case) and by capping to that we don't ensure the access will stay within that range, but we ensure it will stay within the underlying memory bound to the buffer (256B), and this is fine by the spec, however, I think if the actual buffer range was the same as the underlying allocation we would fail the tests. A valid behavior for robust buffer access on an out-of-bounds access is to return any valid bytes within the buffer, so we can just make that offset 0. Reviewed-by: Alejandro Piñeiro <apinheiro@igalia.com> Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/18744>
This commit is contained in:
committed by
Marge Bot
parent
e7e989f62e
commit
b2bce9c98a
@@ -27,6 +27,7 @@
|
||||
static void
|
||||
rewrite_offset(nir_builder *b,
|
||||
nir_intrinsic_instr *instr,
|
||||
uint32_t type_sz,
|
||||
uint32_t buffer_idx,
|
||||
uint32_t offset_src,
|
||||
nir_intrinsic_op buffer_size_op)
|
||||
@@ -40,13 +41,20 @@ rewrite_offset(nir_builder *b,
|
||||
nir_ssa_dest_init(&size->instr, &size->dest, 1, 32, NULL);
|
||||
nir_builder_instr_insert(b, &size->instr);
|
||||
|
||||
/* All out TMU accesses are 32-bit aligned */
|
||||
nir_ssa_def *aligned_buffer_size =
|
||||
nir_iand(b, &size->dest.ssa, nir_imm_int(b, 0xfffffffc));
|
||||
/* Compute the maximum offset being accessed and if it is
|
||||
* out of bounds rewrite it to 0 to ensure the access is
|
||||
* within bounds.
|
||||
*/
|
||||
const uint32_t access_size = instr->num_components * type_sz;
|
||||
nir_ssa_def *max_access_offset =
|
||||
nir_iadd(b, instr->src[offset_src].ssa,
|
||||
nir_imm_int(b, access_size - 1));
|
||||
nir_ssa_def *offset =
|
||||
nir_bcsel(b, nir_uge(b, max_access_offset, &size->dest.ssa),
|
||||
nir_imm_int(b, 0),
|
||||
instr->src[offset_src].ssa);
|
||||
|
||||
/* Rewrite offset */
|
||||
nir_ssa_def *offset =
|
||||
nir_umin(b, instr->src[offset_src].ssa, aligned_buffer_size);
|
||||
nir_instr_rewrite_src(&instr->instr, &instr->src[offset_src],
|
||||
nir_src_for_ssa(offset));
|
||||
}
|
||||
@@ -56,6 +64,7 @@ lower_load(struct v3d_compile *c,
|
||||
nir_builder *b,
|
||||
nir_intrinsic_instr *instr)
|
||||
{
|
||||
uint32_t type_sz = nir_dest_bit_size(instr->dest) / 8;
|
||||
uint32_t index = nir_src_comp_as_uint(instr->src[0], 0);
|
||||
|
||||
nir_intrinsic_op op;
|
||||
@@ -67,7 +76,7 @@ lower_load(struct v3d_compile *c,
|
||||
op = nir_intrinsic_get_ssbo_size;
|
||||
}
|
||||
|
||||
rewrite_offset(b, instr, index, 1, op);
|
||||
rewrite_offset(b, instr, type_sz, index, 1, op);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -75,8 +84,9 @@ lower_store(struct v3d_compile *c,
|
||||
nir_builder *b,
|
||||
nir_intrinsic_instr *instr)
|
||||
{
|
||||
uint32_t type_sz = nir_src_bit_size(instr->src[0]) / 8;
|
||||
uint32_t index = nir_src_comp_as_uint(instr->src[1], 0);
|
||||
rewrite_offset(b, instr, index, 2, nir_intrinsic_get_ssbo_size);
|
||||
rewrite_offset(b, instr, type_sz, index, 2, nir_intrinsic_get_ssbo_size);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -85,7 +95,7 @@ lower_atomic(struct v3d_compile *c,
|
||||
nir_intrinsic_instr *instr)
|
||||
{
|
||||
uint32_t index = nir_src_comp_as_uint(instr->src[0], 0);
|
||||
rewrite_offset(b, instr, index, 1, nir_intrinsic_get_ssbo_size);
|
||||
rewrite_offset(b, instr, 4, index, 1, nir_intrinsic_get_ssbo_size);
|
||||
}
|
||||
|
||||
static void
|
||||
@@ -93,10 +103,25 @@ lower_shared(struct v3d_compile *c,
|
||||
nir_builder *b,
|
||||
nir_intrinsic_instr *instr)
|
||||
{
|
||||
uint32_t type_sz;
|
||||
if (instr->intrinsic == nir_intrinsic_load_shared) {
|
||||
type_sz = nir_dest_bit_size(instr->dest) / 8;
|
||||
} else {
|
||||
/* atomic */
|
||||
type_sz = 4;
|
||||
}
|
||||
|
||||
b->cursor = nir_before_instr(&instr->instr);
|
||||
nir_ssa_def *aligned_size =
|
||||
nir_imm_int(b, c->s->info.shared_size & 0xfffffffc);
|
||||
nir_ssa_def *offset = nir_umin(b, instr->src[0].ssa, aligned_size);
|
||||
const uint32_t access_size = instr->num_components * type_sz;
|
||||
nir_ssa_def *max_access_offset =
|
||||
nir_iadd(b, instr->src[0].ssa,
|
||||
nir_imm_int(b, access_size - 1));
|
||||
nir_ssa_def *offset =
|
||||
nir_bcsel(b, nir_uge(b, max_access_offset,
|
||||
nir_imm_int(b, c->s->info.shared_size)),
|
||||
nir_imm_int(b, 0),
|
||||
instr->src[0].ssa);
|
||||
|
||||
nir_instr_rewrite_src(&instr->instr, &instr->src[0],
|
||||
nir_src_for_ssa(offset));
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user