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