summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/compiler/nir/nir.c96
-rw-r--r--src/compiler/nir/nir.h18
-rw-r--r--src/compiler/nir/nir_print.c6
-rw-r--r--src/compiler/nir/nir_validate.c12
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