Mesa (main): zink: add an optimizer pass to enforce bo bounds

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Tue Jul 5 21:18:29 UTC 2022


Module: Mesa
Branch: main
Commit: ab9e423c4f4c02e39f9121c76fea7503c6f6b915
URL:    http://cgit.freedesktop.org/mesa/mesa/commit/?id=ab9e423c4f4c02e39f9121c76fea7503c6f6b915

Author: Mike Blumenkrantz <michael.blumenkrantz at gmail.com>
Date:   Fri Jun 24 11:23:16 2022 -0400

zink: add an optimizer pass to enforce bo bounds

this eliminates (some) out-of-bounds bo access and will ensure that
bo sizing is always accurate by breaking all the cases where it isn't

Reviewed-by: Dave Airlie <airlied at redhat.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/17239>

---

 src/gallium/drivers/zink/zink_compiler.c | 70 ++++++++++++++++++++++++++++++++
 1 file changed, 70 insertions(+)

diff --git a/src/gallium/drivers/zink/zink_compiler.c b/src/gallium/drivers/zink/zink_compiler.c
index 917f91aa9d9..128f1e5f16f 100644
--- a/src/gallium/drivers/zink/zink_compiler.c
+++ b/src/gallium/drivers/zink/zink_compiler.c
@@ -502,6 +502,74 @@ get_bo_vars(struct zink_shader *zs, nir_shader *shader)
    return bo;
 }
 
+static bool
+bound_bo_access_instr(nir_builder *b, nir_instr *instr, void *data)
+{
+   struct bo_vars *bo = data;
+   if (instr->type != nir_instr_type_intrinsic)
+      return false;
+   nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+   nir_variable *var = NULL;
+   nir_ssa_def *offset = NULL;
+   bool is_load = true;
+   b->cursor = nir_before_instr(instr);
+
+   switch (intr->intrinsic) {
+   case nir_intrinsic_store_ssbo:
+      var = bo->ssbo[nir_dest_bit_size(intr->dest) >> 4];
+      offset = intr->src[2].ssa;
+      is_load = false;
+      break;
+   case nir_intrinsic_load_ssbo:
+      var = bo->ssbo[nir_dest_bit_size(intr->dest) >> 4];
+      offset = intr->src[1].ssa;
+      break;
+   case nir_intrinsic_load_ubo:
+      if (nir_src_is_const(intr->src[0]) && nir_src_as_const_value(intr->src[0])->u32 == 0)
+         var = bo->uniforms[nir_dest_bit_size(intr->dest) >> 4];
+      else
+         var = bo->ubo[nir_dest_bit_size(intr->dest) >> 4];
+      offset = intr->src[1].ssa;
+      break;
+   default:
+      return false;
+   }
+   nir_src offset_src = nir_src_for_ssa(offset);
+   if (!nir_src_is_const(offset_src))
+      return false;
+
+   unsigned offset_bytes = nir_src_as_const_value(offset_src)->u32;
+   const struct glsl_type *strct_type = glsl_get_array_element(var->type);
+   unsigned size = glsl_array_size(glsl_get_struct_field(strct_type, 0));
+   bool has_unsized = glsl_array_size(glsl_get_struct_field(strct_type, glsl_get_length(strct_type) - 1)) == 0;
+   if (has_unsized || offset_bytes + intr->num_components - 1 < size)
+      return false;
+
+   unsigned rewrites = 0;
+   nir_ssa_def *result[2];
+   for (unsigned i = 0; i < intr->num_components; i++) {
+      if (offset_bytes + i >= size) {
+         rewrites++;
+         if (is_load)
+            result[i] = nir_imm_zero(b, 1, nir_dest_bit_size(intr->dest));
+      }
+   }
+   assert(rewrites == intr->num_components);
+   if (is_load) {
+      nir_ssa_def *load = nir_vec(b, result, intr->num_components);
+      nir_ssa_def_rewrite_uses(&intr->dest.ssa, load);
+   }
+   nir_instr_remove(instr);
+   return true;
+}
+
+static bool
+bound_bo_access(nir_shader *shader, struct zink_shader *zs)
+{
+   struct bo_vars bo = get_bo_vars(zs, shader);
+   return nir_shader_instructions_pass(shader, bound_bo_access_instr, nir_metadata_dominance, &bo);
+}
+
 static void
 optimize_nir(struct nir_shader *s, struct zink_shader *zs)
 {
@@ -528,6 +596,8 @@ optimize_nir(struct nir_shader *s, struct zink_shader *zs)
       NIR_PASS(progress, s, nir_opt_constant_folding);
       NIR_PASS(progress, s, nir_opt_undef);
       NIR_PASS(progress, s, zink_nir_lower_b2b);
+      if (zs)
+         NIR_PASS(progress, s, bound_bo_access, zs);
    } while (progress);
 
    do {



More information about the mesa-commit mailing list