From 3528dcdfa18d688ec3fc69132095e93a8fe380c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Marek=20Ol=C5=A1=C3=A1k?= Date: Sun, 2 Jan 2022 19:46:45 -0500 Subject: [PATCH] nir: add nir_io_semantics::no_varying, no_sysval_output, and helpers This is for drivers that have separate store instructions for varyings, system value outputs (such as clip distances), and transform feedback. The flags tell the driver not to store the output to those locations. This will be used by radeonsi initially, and then maybe by a new linker. Reviewed-by: Emma Anholt Part-of: --- src/compiler/nir/nir.c | 96 +++++++++++++++++++++++++++++++++ src/compiler/nir/nir.h | 18 ++++++- src/compiler/nir/nir_print.c | 6 +++ src/compiler/nir/nir_validate.c | 12 +++++ 4 files changed, 131 insertions(+), 1 deletion(-) diff --git a/src/compiler/nir/nir.c b/src/compiler/nir/nir.c index e9330f437b7..bd87c6eac1f 100644 --- a/src/compiler/nir/nir.c +++ b/src/compiler/nir/nir.c @@ -3410,3 +3410,99 @@ nir_instr_xfb_write_mask(nir_intrinsic_instr *instr) return mask; } + +/** + * Whether an output slot is consumed by fixed-function logic. + */ +bool +nir_slot_is_sysval_output(gl_varying_slot slot) +{ + return slot == VARYING_SLOT_POS || + slot == VARYING_SLOT_PSIZ || + slot == VARYING_SLOT_EDGE || + slot == VARYING_SLOT_CLIP_VERTEX || + slot == VARYING_SLOT_CLIP_DIST0 || + slot == VARYING_SLOT_CLIP_DIST1 || + slot == VARYING_SLOT_CULL_DIST0 || + slot == VARYING_SLOT_CULL_DIST1 || + slot == VARYING_SLOT_LAYER || + slot == VARYING_SLOT_VIEWPORT || + slot == VARYING_SLOT_TESS_LEVEL_OUTER || + slot == VARYING_SLOT_TESS_LEVEL_INNER || + slot == VARYING_SLOT_BOUNDING_BOX0 || + slot == VARYING_SLOT_BOUNDING_BOX1 || + slot == VARYING_SLOT_VIEW_INDEX || + slot == VARYING_SLOT_VIEWPORT_MASK || + slot == VARYING_SLOT_PRIMITIVE_SHADING_RATE || + slot == VARYING_SLOT_PRIMITIVE_COUNT || + slot == VARYING_SLOT_PRIMITIVE_INDICES || + slot == VARYING_SLOT_TASK_COUNT; +} + +/** + * Whether an input/output slot is consumed by the next shader stage, + * or written by the previous shader stage. + */ +bool +nir_slot_is_varying(gl_varying_slot slot) +{ + return slot >= VARYING_SLOT_VAR0 || + slot == VARYING_SLOT_COL0 || + slot == VARYING_SLOT_COL1 || + slot == VARYING_SLOT_BFC0 || + slot == VARYING_SLOT_BFC1 || + slot == VARYING_SLOT_FOGC || + (slot >= VARYING_SLOT_TEX0 && slot <= VARYING_SLOT_TEX7) || + slot == VARYING_SLOT_CLIP_DIST0 || + slot == VARYING_SLOT_CLIP_DIST1 || + slot == VARYING_SLOT_CULL_DIST0 || + slot == VARYING_SLOT_CULL_DIST1 || + slot == VARYING_SLOT_PRIMITIVE_ID || + slot == VARYING_SLOT_LAYER || + slot == VARYING_SLOT_VIEWPORT || + slot == VARYING_SLOT_TESS_LEVEL_OUTER || + slot == VARYING_SLOT_TESS_LEVEL_INNER; +} + +bool +nir_slot_is_sysval_output_and_varying(gl_varying_slot slot) +{ + return nir_slot_is_sysval_output(slot) && + nir_slot_is_varying(slot); +} + +/** + * This marks the output store instruction as not feeding the next shader + * stage. If the instruction has no other use, it's removed. + */ +void nir_remove_varying(nir_intrinsic_instr *intr) +{ + nir_io_semantics sem = nir_intrinsic_io_semantics(intr); + + if ((!sem.no_sysval_output && nir_slot_is_sysval_output(sem.location)) || + nir_instr_xfb_write_mask(intr)) { + /* Demote the store instruction. */ + sem.no_varying = true; + nir_intrinsic_set_io_semantics(intr, sem); + } else { + nir_instr_remove(&intr->instr); + } +} + +/** + * This marks the output store instruction as not feeding fixed-function + * logic. If the instruction has no other use, it's removed. + */ +void nir_remove_sysval_output(nir_intrinsic_instr *intr) +{ + nir_io_semantics sem = nir_intrinsic_io_semantics(intr); + + if ((!sem.no_varying && nir_slot_is_varying(sem.location)) || + nir_instr_xfb_write_mask(intr)) { + /* Demote the store instruction. */ + sem.no_sysval_output = true; + nir_intrinsic_set_io_semantics(intr, sem); + } else { + nir_instr_remove(&intr->instr); + } +} diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h index 9b4de2e09b3..de0528c9507 100644 --- a/src/compiler/nir/nir.h +++ b/src/compiler/nir/nir.h @@ -1767,7 +1767,17 @@ typedef struct nir_io_semantics { unsigned per_view:1; unsigned high_16bits:1; /* whether accessing low or high half of the slot */ unsigned invariant:1; /* The variable has the invariant flag set */ - unsigned _pad:5; + /* CLIP_DISTn, LAYER, VIEWPORT, and TESS_LEVEL_* have up to 3 uses: + * - an output consumed by the next stage + * - a system value output affecting fixed-func hardware, e.g. the clipper + * - a transform feedback output written to memory + * The following fields disable the first two. Transform feedback is disabled + * by transform feedback info. + */ + unsigned no_varying:1; /* whether this output isn't consumed by the next stage */ + unsigned no_sysval_output:1; /* whether this system value output has no + effect due to current pipeline states */ + unsigned _pad:3; } nir_io_semantics; /* Transform feedback info for 2 outputs. nir_intrinsic_store_output contains @@ -4431,6 +4441,12 @@ void nir_link_xfb_varyings(nir_shader *producer, nir_shader *consumer); bool nir_link_opt_varyings(nir_shader *producer, nir_shader *consumer); void nir_link_varying_precision(nir_shader *producer, nir_shader *consumer); +bool nir_slot_is_sysval_output(gl_varying_slot slot); +bool nir_slot_is_varying(gl_varying_slot slot); +bool nir_slot_is_sysval_output_and_varying(gl_varying_slot slot); +void nir_remove_varying(nir_intrinsic_instr *intr); +void nir_remove_sysval_output(nir_intrinsic_instr *intr); + bool nir_lower_amul(nir_shader *shader, int (*type_size)(const struct glsl_type *, bool)); diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c index c22727c8d37..24c50978ddf 100644 --- a/src/compiler/nir/nir_print.c +++ b/src/compiler/nir/nir_print.c @@ -1061,6 +1061,12 @@ print_intrinsic_instr(nir_intrinsic_instr *instr, print_state *state) if (io.high_16bits) fprintf(fp, " high_16bits"); + if (io.no_varying) + fprintf(fp, " no_varying"); + + if (io.no_sysval_output) + fprintf(fp, " no_sysval_output"); + if (state->shader && state->shader->info.stage == MESA_SHADER_GEOMETRY && (instr->intrinsic == nir_intrinsic_store_output || diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c index 5e4e7f16900..0895b32b893 100644 --- a/src/compiler/nir/nir_validate.c +++ b/src/compiler/nir/nir_validate.c @@ -840,6 +840,18 @@ validate_intrinsic_instr(nir_intrinsic_instr *instr, validate_state *state) used_mask |= xfb_mask; } } + + if (nir_intrinsic_has_io_semantics(instr) && + !nir_intrinsic_infos[instr->intrinsic].has_dest) { + nir_io_semantics sem = nir_intrinsic_io_semantics(instr); + + /* An output that has no effect shouldn't be present in the IR. */ + validate_assert(state, + (nir_slot_is_sysval_output(sem.location) && + !sem.no_sysval_output) || + (nir_slot_is_varying(sem.location) && !sem.no_varying) || + nir_instr_xfb_write_mask(instr)); + } } static void