diff options
-rw-r--r-- | src/compiler/nir/nir.c | 96 | ||||
-rw-r--r-- | src/compiler/nir/nir.h | 18 | ||||
-rw-r--r-- | src/compiler/nir/nir_print.c | 6 | ||||
-rw-r--r-- | src/compiler/nir/nir_validate.c | 12 |
4 files changed, 131 insertions, 1 deletions
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 |