microsoft/compiler: Move kill-unused/undefined varying pass from spirv to common
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28535>
This commit is contained in:
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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,
|
||||
|
||||
Reference in New Issue
Block a user