diff --git a/src/microsoft/compiler/dxil_nir.c b/src/microsoft/compiler/dxil_nir.c index dba218ca7b5..49359965692 100644 --- a/src/microsoft/compiler/dxil_nir.c +++ b/src/microsoft/compiler/dxil_nir.c @@ -2842,3 +2842,140 @@ dxil_nir_lower_coherent_loads_and_stores(nir_shader *s) nir_metadata_block_index | nir_metadata_dominance | nir_metadata_loop_analysis, NULL); } + +static bool +kill_undefined_varyings(struct nir_builder *b, + nir_instr *instr, + void *data) +{ + const nir_shader *prev_stage_nir = data; + + if (instr->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + if (intr->intrinsic != nir_intrinsic_load_deref) + return false; + + nir_variable *var = nir_intrinsic_get_var(intr, 0); + if (!var || var->data.mode != nir_var_shader_in) + return false; + + /* Ignore most builtins for now, some of them get default values + * when not written from previous stages. + */ + if (var->data.location < VARYING_SLOT_VAR0 && + var->data.location != VARYING_SLOT_POS) + return false; + + uint32_t loc = var->data.patch ? + var->data.location - VARYING_SLOT_PATCH0 : var->data.location; + uint64_t written = var->data.patch ? + prev_stage_nir->info.patch_outputs_written : + prev_stage_nir->info.outputs_written; + if (BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & written) + return false; + + b->cursor = nir_after_instr(instr); + /* Note: zero is used instead of undef, because optimization is not run here, but is + * run later on. If we load an undef here, and that undef ends up being used to store + * to position later on, that can cause some or all of the components in that position + * write to be removed, which is problematic especially in the case of all components, + * since that would remove the store instruction, and would make it tricky to satisfy + * the DXIL requirements of writing all position components. + */ + nir_def *zero = nir_imm_zero(b, intr->def.num_components, + intr->def.bit_size); + nir_def_rewrite_uses(&intr->def, zero); + nir_instr_remove(instr); + return true; +} + +bool +dxil_nir_kill_undefined_varyings(nir_shader *shader, + const nir_shader *prev_stage_shader) +{ + if (!nir_shader_instructions_pass(shader, + kill_undefined_varyings, + nir_metadata_dominance | + nir_metadata_block_index | + nir_metadata_loop_analysis, + (void *)prev_stage_shader)) + return false; + + nir_remove_dead_derefs(shader); + nir_remove_dead_variables(shader, nir_var_shader_in, NULL); + return true; +} + +static bool +kill_unused_outputs(struct nir_builder *b, + nir_instr *instr, + void *data) +{ + uint64_t kill_mask = *((uint64_t *)data); + + if (instr->type != nir_instr_type_intrinsic) + return false; + + nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); + + if (intr->intrinsic != nir_intrinsic_store_deref) + return false; + + nir_variable *var = nir_intrinsic_get_var(intr, 0); + if (!var || var->data.mode != nir_var_shader_out) + return false; + + unsigned loc = var->data.patch ? + var->data.location - VARYING_SLOT_PATCH0 : + var->data.location; + if (!(BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & kill_mask)) + return false; + + nir_instr_remove(instr); + return true; +} + +bool +dxil_nir_kill_unused_outputs(nir_shader *shader, + const nir_shader *next_stage_shader) +{ + uint64_t kill_var_mask = + shader->info.outputs_written & ~next_stage_shader->info.inputs_read; + bool progress = false; + + /* Don't kill buitin vars */ + kill_var_mask &= BITFIELD64_MASK(MAX_VARYING) << VARYING_SLOT_VAR0; + + if (nir_shader_instructions_pass(shader, + kill_unused_outputs, + nir_metadata_dominance | + nir_metadata_block_index | + nir_metadata_loop_analysis, + (void *)&kill_var_mask)) + progress = true; + + if (shader->info.stage == MESA_SHADER_TESS_CTRL) { + kill_var_mask = + (shader->info.patch_outputs_written | + shader->info.patch_outputs_read) & + ~next_stage_shader->info.patch_inputs_read; + if (nir_shader_instructions_pass(shader, + kill_unused_outputs, + nir_metadata_dominance | + nir_metadata_block_index | + nir_metadata_loop_analysis, + (void *)&kill_var_mask)) + progress = true; + } + + if (progress) { + nir_opt_dce(shader); + nir_remove_dead_derefs(shader); + nir_remove_dead_variables(shader, nir_var_shader_out, NULL); + } + + return progress; +} diff --git a/src/microsoft/compiler/dxil_nir.h b/src/microsoft/compiler/dxil_nir.h index f85568fb144..bf55a52a488 100644 --- a/src/microsoft/compiler/dxil_nir.h +++ b/src/microsoft/compiler/dxil_nir.h @@ -89,6 +89,9 @@ bool dxil_nir_analyze_io_dependencies(struct dxil_module *mod, nir_shader *s); bool dxil_nir_guess_image_formats(nir_shader *s); bool dxil_nir_lower_coherent_loads_and_stores(nir_shader *s); +bool dxil_nir_kill_undefined_varyings(nir_shader *shader, const nir_shader *prev_stage_shader); +bool dxil_nir_kill_unused_outputs(nir_shader *shader, const nir_shader *next_stage_shader); + #ifdef __cplusplus } #endif diff --git a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c index 47d17ea0740..45a00f5eac4 100644 --- a/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c +++ b/src/microsoft/spirv_to_dxil/dxil_spirv_nir.c @@ -551,143 +551,6 @@ dxil_spirv_nir_discard_point_size_var(nir_shader *shader) return true; } -static bool -kill_undefined_varyings(struct nir_builder *b, - nir_instr *instr, - void *data) -{ - const nir_shader *prev_stage_nir = data; - - if (instr->type != nir_instr_type_intrinsic) - return false; - - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - - if (intr->intrinsic != nir_intrinsic_load_deref) - return false; - - nir_variable *var = nir_intrinsic_get_var(intr, 0); - if (!var || var->data.mode != nir_var_shader_in) - return false; - - /* Ignore most builtins for now, some of them get default values - * when not written from previous stages. - */ - if (var->data.location < VARYING_SLOT_VAR0 && - var->data.location != VARYING_SLOT_POS) - return false; - - uint32_t loc = var->data.patch ? - var->data.location - VARYING_SLOT_PATCH0 : var->data.location; - uint64_t written = var->data.patch ? - prev_stage_nir->info.patch_outputs_written : - prev_stage_nir->info.outputs_written; - if (BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & written) - return false; - - b->cursor = nir_after_instr(instr); - /* Note: zero is used instead of undef, because optimization is not run here, but is - * run later on. If we load an undef here, and that undef ends up being used to store - * to position later on, that can cause some or all of the components in that position - * write to be removed, which is problematic especially in the case of all components, - * since that would remove the store instruction, and would make it tricky to satisfy - * the DXIL requirements of writing all position components. - */ - nir_def *zero = nir_imm_zero(b, intr->def.num_components, - intr->def.bit_size); - nir_def_rewrite_uses(&intr->def, zero); - nir_instr_remove(instr); - return true; -} - -static bool -dxil_spirv_nir_kill_undefined_varyings(nir_shader *shader, - const nir_shader *prev_stage_shader) -{ - if (!nir_shader_instructions_pass(shader, - kill_undefined_varyings, - nir_metadata_dominance | - nir_metadata_block_index | - nir_metadata_loop_analysis, - (void *)prev_stage_shader)) - return false; - - nir_remove_dead_derefs(shader); - nir_remove_dead_variables(shader, nir_var_shader_in, NULL); - return true; -} - -static bool -kill_unused_outputs(struct nir_builder *b, - nir_instr *instr, - void *data) -{ - uint64_t kill_mask = *((uint64_t *)data); - - if (instr->type != nir_instr_type_intrinsic) - return false; - - nir_intrinsic_instr *intr = nir_instr_as_intrinsic(instr); - - if (intr->intrinsic != nir_intrinsic_store_deref) - return false; - - nir_variable *var = nir_intrinsic_get_var(intr, 0); - if (!var || var->data.mode != nir_var_shader_out) - return false; - - unsigned loc = var->data.patch ? - var->data.location - VARYING_SLOT_PATCH0 : - var->data.location; - if (!(BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & kill_mask)) - return false; - - nir_instr_remove(instr); - return true; -} - -static bool -dxil_spirv_nir_kill_unused_outputs(nir_shader *shader, - nir_shader *next_stage_shader) -{ - uint64_t kill_var_mask = - shader->info.outputs_written & ~next_stage_shader->info.inputs_read; - bool progress = false; - - /* Don't kill buitin vars */ - kill_var_mask &= BITFIELD64_MASK(MAX_VARYING) << VARYING_SLOT_VAR0; - - if (nir_shader_instructions_pass(shader, - kill_unused_outputs, - nir_metadata_dominance | - nir_metadata_block_index | - nir_metadata_loop_analysis, - (void *)&kill_var_mask)) - progress = true; - - if (shader->info.stage == MESA_SHADER_TESS_CTRL) { - kill_var_mask = - (shader->info.patch_outputs_written | - shader->info.patch_outputs_read) & - ~next_stage_shader->info.patch_inputs_read; - if (nir_shader_instructions_pass(shader, - kill_unused_outputs, - nir_metadata_dominance | - nir_metadata_block_index | - nir_metadata_loop_analysis, - (void *)&kill_var_mask)) - progress = true; - } - - if (progress) { - nir_opt_dce(shader); - nir_remove_dead_derefs(shader); - nir_remove_dead_variables(shader, nir_var_shader_out, NULL); - } - - return progress; -} - struct lower_pntc_data { const struct dxil_spirv_runtime_conf *conf; nir_variable *pntc; @@ -906,8 +769,8 @@ dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_nir, } } - NIR_PASS_V(nir, dxil_spirv_nir_kill_undefined_varyings, prev_stage_nir); - NIR_PASS_V(prev_stage_nir, dxil_spirv_nir_kill_unused_outputs, nir); + NIR_PASS_V(nir, dxil_nir_kill_undefined_varyings, prev_stage_nir); + NIR_PASS_V(prev_stage_nir, dxil_nir_kill_unused_outputs, nir); nir->info.inputs_read = dxil_reassign_driver_locations(nir, nir_var_shader_in,