Mesa (main): d3d12: When adding new output varyings, write 0s

GitLab Mirror gitlab-mirror at kemper.freedesktop.org
Fri Feb 4 21:01:15 UTC 2022


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

Author: Jesse Natalie <jenatali at microsoft.com>
Date:   Fri Feb  4 08:24:02 2022 -0800

d3d12: When adding new output varyings, write 0s

This avoids undefined behavior in some cases, and in the case
where the new output varying is actually a sysval like viewport
index, the DXIL validator will require it to be written.

Reviewed-by: Sil Vilerino <sivileri at microsoft.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/14881>

---

 src/gallium/drivers/d3d12/d3d12_compiler.cpp |  3 ++
 src/gallium/drivers/d3d12/d3d12_nir_passes.c | 58 ++++++++++++++++++++++++++++
 src/gallium/drivers/d3d12/d3d12_nir_passes.h |  3 ++
 3 files changed, 64 insertions(+)

diff --git a/src/gallium/drivers/d3d12/d3d12_compiler.cpp b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
index 20e18b1c50d..2975adc485f 100644
--- a/src/gallium/drivers/d3d12/d3d12_compiler.cpp
+++ b/src/gallium/drivers/d3d12/d3d12_compiler.cpp
@@ -535,6 +535,9 @@ create_varying_from_info(nir_shader *nir, struct d3d12_varying_info *info,
    if (patch)
       var->data.location += VARYING_SLOT_PATCH0;
 
+   if (mode == nir_var_shader_out)
+      NIR_PASS_V(nir, d3d12_write_0_to_new_varying, var);
+
    return var;
 }
 
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.c b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
index 4a8ca704eea..b2a28834a4f 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.c
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.c
@@ -1142,3 +1142,61 @@ d3d12_split_multistream_varyings(nir_shader *s)
 
    return progress;
 }
+
+static void
+write_0(nir_builder *b, nir_deref_instr *deref)
+{
+   if (glsl_type_is_array_or_matrix(deref->type)) {
+      for (unsigned i = 0; i < glsl_get_length(deref->type); ++i)
+         write_0(b, nir_build_deref_array_imm(b, deref, i));
+   } else if (glsl_type_is_struct(deref->type)) {
+      for (unsigned i = 0; i < glsl_get_length(deref->type); ++i)
+         write_0(b, nir_build_deref_struct(b, deref, i));
+   } else {
+      nir_ssa_def *scalar = nir_imm_intN_t(b, 0, glsl_get_bit_size(deref->type));
+      nir_ssa_def *scalar_arr[NIR_MAX_VEC_COMPONENTS];
+      unsigned num_comps = glsl_get_components(deref->type);
+      unsigned writemask = (1 << num_comps) - 1;
+      for (unsigned i = 0; i < num_comps; ++i)
+         scalar_arr[i] = scalar;
+      nir_ssa_def *zero_val = nir_vec(b, scalar_arr, num_comps);
+      nir_store_deref(b, deref, zero_val, writemask);
+   }
+}
+
+void
+d3d12_write_0_to_new_varying(nir_shader *s, nir_variable *var)
+{
+   /* Skip per-vertex HS outputs */
+   if (s->info.stage == MESA_SHADER_TESS_CTRL && !var->data.patch)
+      return;
+
+   nir_foreach_function(func, s) {
+      if (!func->impl)
+         continue;
+
+      nir_builder b;
+      nir_builder_init(&b, func->impl);
+
+      nir_foreach_block(block, func->impl) {
+         b.cursor = nir_before_block(block);
+         if (s->info.stage != MESA_SHADER_GEOMETRY) {
+            write_0(&b, nir_build_deref_var(&b, var));
+            break;
+         }
+
+         nir_foreach_instr_safe(instr, block) {
+            if (instr->type != nir_instr_type_intrinsic)
+               continue;
+            nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr);
+            if (intr->intrinsic != nir_intrinsic_emit_vertex)
+               continue;
+
+            b.cursor = nir_before_instr(instr);
+            write_0(&b, nir_build_deref_var(&b, var));
+         }
+      }
+
+      nir_metadata_preserve(func->impl, nir_metadata_block_index | nir_metadata_dominance);
+   }
+}
diff --git a/src/gallium/drivers/d3d12/d3d12_nir_passes.h b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
index 4550dc253a0..dca85e4ff95 100644
--- a/src/gallium/drivers/d3d12/d3d12_nir_passes.h
+++ b/src/gallium/drivers/d3d12/d3d12_nir_passes.h
@@ -117,6 +117,9 @@ d3d12_disable_multisampling(nir_shader *s);
 bool
 d3d12_split_multistream_varyings(nir_shader *s);
 
+void
+d3d12_write_0_to_new_varying(nir_shader *s, nir_variable *var);
+
 #ifdef __cplusplus
 }
 #endif



More information about the mesa-commit mailing list