microsoft/compiler: Improve linking helpers

* Take masks instead of shaders
* Be more aggressive at removing sysvals
* Handle loading from outputs

Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/28535>
This commit is contained in:
Jesse Natalie 2024-04-01 09:41:20 -07:00 committed by Marge Bot
parent d4a15a048b
commit ed757b010a
4 changed files with 93 additions and 63 deletions

View file

@ -2812,12 +2812,35 @@ dxil_nir_lower_coherent_loads_and_stores(nir_shader *s)
NULL);
}
struct undefined_varying_masks {
uint64_t io_mask;
uint32_t patch_io_mask;
};
static bool
is_dead_in_variable(nir_variable *var, void *data)
{
switch (var->data.location) {
/* Only these values can be system generated values in addition to varyings */
case VARYING_SLOT_PRIMITIVE_ID:
case VARYING_SLOT_FACE:
case VARYING_SLOT_VIEW_INDEX:
return false;
/* Tessellation input vars must remain untouched */
case VARYING_SLOT_TESS_LEVEL_INNER:
case VARYING_SLOT_TESS_LEVEL_OUTER:
return false;
default:
return true;
}
}
static bool
kill_undefined_varyings(struct nir_builder *b,
nir_instr *instr,
void *data)
{
const nir_shader *prev_stage_nir = data;
const struct undefined_varying_masks *masks = data;
if (instr->type != nir_instr_type_intrinsic)
return false;
@ -2831,18 +2854,14 @@ kill_undefined_varyings(struct nir_builder *b,
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)
if (!is_dead_in_variable(var, NULL))
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;
uint32_t loc = var->data.patch && var->data.location >= VARYING_SLOT_PATCH0 ?
var->data.location - VARYING_SLOT_PATCH0 :
var->data.location;
uint64_t written = var->data.patch && var->data.location >= VARYING_SLOT_PATCH0 ?
masks->patch_io_mask : masks->io_mask;
if (BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & written)
return false;
@ -2862,20 +2881,32 @@ kill_undefined_varyings(struct nir_builder *b,
}
bool
dxil_nir_kill_undefined_varyings(nir_shader *shader,
const nir_shader *prev_stage_shader)
dxil_nir_kill_undefined_varyings(nir_shader *shader, uint64_t prev_stage_written_mask, uint32_t prev_stage_patch_written_mask)
{
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;
struct undefined_varying_masks masks = { .io_mask = prev_stage_written_mask, .patch_io_mask = prev_stage_patch_written_mask };
bool progress = nir_shader_instructions_pass(shader,
kill_undefined_varyings,
nir_metadata_dominance |
nir_metadata_block_index |
nir_metadata_loop_analysis,
(void *)&masks);
if (progress) {
nir_opt_dce(shader);
nir_remove_dead_derefs(shader);
}
nir_remove_dead_derefs(shader);
nir_remove_dead_variables(shader, nir_var_shader_in, NULL);
return true;
const struct nir_remove_dead_variables_options options = {
.can_remove_var = is_dead_in_variable,
.can_remove_var_data = &masks,
};
progress |= nir_remove_dead_variables(shader, nir_var_shader_in, &options);
return progress;
}
static bool
is_dead_out_variable(nir_variable *var, void *data)
{
return !nir_slot_is_sysval_output(var->data.location, MESA_SHADER_NONE);
}
static bool
@ -2883,68 +2914,66 @@ kill_unused_outputs(struct nir_builder *b,
nir_instr *instr,
void *data)
{
uint64_t kill_mask = *((uint64_t *)data);
const struct undefined_varying_masks *masks = 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)
if (intr->intrinsic != nir_intrinsic_store_deref &&
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_out)
if (!var || var->data.mode != nir_var_shader_out ||
/* always_active_io can mean two things: xfb or GL separable shaders. We can't delete
* varyings that are used for xfb (we'll just sort them last), but we must delete varyings
* that are mismatching between TCS and TES. Fortunately TCS can't do xfb, so we can ignore
the always_active_io bit for TCS outputs. */
(b->shader->info.stage != MESA_SHADER_TESS_CTRL && var->data.always_active_io))
return false;
unsigned loc = var->data.patch ?
if (!is_dead_out_variable(var, NULL))
return false;
unsigned loc = var->data.patch && var->data.location >= VARYING_SLOT_PATCH0 ?
var->data.location - VARYING_SLOT_PATCH0 :
var->data.location;
if (!(BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & kill_mask))
uint64_t read = var->data.patch && var->data.location >= VARYING_SLOT_PATCH0 ?
masks->patch_io_mask : masks->io_mask;
if (BITFIELD64_RANGE(loc, glsl_varying_count(var->type)) & read)
return false;
if (intr->intrinsic == nir_intrinsic_load_deref) {
b->cursor = nir_after_instr(&intr->instr);
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_unused_outputs(nir_shader *shader,
const nir_shader *next_stage_shader)
dxil_nir_kill_unused_outputs(nir_shader *shader, uint64_t next_stage_read_mask, uint32_t next_stage_patch_read_mask)
{
uint64_t kill_var_mask =
shader->info.outputs_written & ~next_stage_shader->info.inputs_read;
bool progress = false;
struct undefined_varying_masks masks = { .io_mask = next_stage_read_mask, .patch_io_mask = next_stage_patch_read_mask };
/* 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;
}
bool progress = nir_shader_instructions_pass(shader,
kill_unused_outputs,
nir_metadata_dominance |
nir_metadata_block_index |
nir_metadata_loop_analysis,
(void *)&masks);
if (progress) {
nir_opt_dce(shader);
nir_remove_dead_derefs(shader);
nir_remove_dead_variables(shader, nir_var_shader_out, NULL);
}
const struct nir_remove_dead_variables_options options = {
.can_remove_var = is_dead_out_variable,
.can_remove_var_data = &masks,
};
progress |= nir_remove_dead_variables(shader, nir_var_shader_out, &options);
return progress;
}

View file

@ -89,8 +89,8 @@ 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);
bool dxil_nir_kill_undefined_varyings(nir_shader *shader, uint64_t prev_stage_written_mask, uint32_t prev_stage_patch_written_mask);
bool dxil_nir_kill_unused_outputs(nir_shader *shader, uint64_t next_stage_read_mask, uint32_t next_stage_patch_read_mask);
#ifdef __cplusplus
}

View file

@ -769,8 +769,8 @@ dxil_spirv_nir_link(nir_shader *nir, nir_shader *prev_stage_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_PASS_V(nir, dxil_nir_kill_undefined_varyings, prev_stage_nir->info.outputs_written, prev_stage_nir->info.patch_outputs_written);
NIR_PASS_V(prev_stage_nir, dxil_nir_kill_unused_outputs, nir->info.inputs_read, nir->info.patch_inputs_read);
nir->info.inputs_read =
dxil_reassign_driver_locations(nir, nir_var_shader_in,

View file

@ -414,6 +414,7 @@ dzn_pipeline_compile_shader(struct dzn_device *device,
struct blob dxil_blob;
VkResult result = VK_SUCCESS;
nir_shader_gather_info(nir, nir_shader_get_entrypoint(nir));
if (instance->debug_flags & DZN_DEBUG_NIR)
nir_print_shader(nir, stderr);