intel/fs: bound subgroup invocation read to dispatch size

This is to avoid out of bound register accesses (potentially leading
to hangs) when the dispatch size is smaller than when is reported in
the NIR subgroup_size.

v2: Implement bounding with a mask (since workgroup sizes are powers of 2) (Faith)

Signed-off-by: Lionel Landwerlin <lionel.g.landwerlin@intel.com>
Fixes: 530de844ef ("intel,anv,iris,crocus: Drop subgroup size from the shader key")
Reviewed-by: Faith Ekstrand <faith.ekstrand@collabora.com>
Reviewed-by: Kenneth Graunke <kenneth@whitecape.org>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/21282>
This commit is contained in:
Lionel Landwerlin
2023-02-08 20:48:25 +02:00
committed by Marge Bot
parent 0d445cfb7e
commit 9ac192d79d

View File

@@ -5398,10 +5398,22 @@ fs_visitor::nir_emit_intrinsic(const fs_builder &bld, nir_intrinsic_instr *instr
case nir_intrinsic_read_invocation: {
const fs_reg value = get_nir_src(instr->src[0]);
const fs_reg invocation = get_nir_src(instr->src[1]);
fs_reg tmp = bld.vgrf(value.type);
/* When for some reason the subgroup_size picked by NIR is larger than
* the dispatch size picked by the backend (this could happen in RT,
* FS), bound the invocation to the dispatch size.
*/
fs_reg bound_invocation;
if (bld.dispatch_width() < bld.shader->nir->info.subgroup_size) {
bound_invocation = bld.vgrf(BRW_REGISTER_TYPE_UD);
bld.AND(bound_invocation, invocation, brw_imm_ud(dispatch_width - 1));
} else {
bound_invocation = invocation;
}
bld.exec_all().emit(SHADER_OPCODE_BROADCAST, tmp, value,
bld.emit_uniformize(invocation));
bld.emit_uniformize(bound_invocation));
bld.MOV(retype(dest, value.type), fs_reg(component(tmp, 0)));
break;