nir: Add per_view attribute to nir_variable
If a nir_variable is tagged with per_view, it must be an array with
size corresponding to the number of views. For slot-tracking, it is
considered to take just the slot for a single element -- drivers will
take care of expanding this appropriately.
This will be used to implement the ability of having per-view position
in a vertex shader in Intel platforms.
Acked-by: Rafael Antognolli <rafael.antognolli@intel.com>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/2313>
diff --git a/src/compiler/nir/nir.h b/src/compiler/nir/nir.h
index 4d3c0d0..c76d009 100644
--- a/src/compiler/nir/nir.h
+++ b/src/compiler/nir/nir.h
@@ -454,6 +454,12 @@
unsigned how_declared:2;
/**
+ * Is this variable per-view? If so, we know it must be an array with
+ * size corresponding to the number of views.
+ */
+ unsigned per_view:1;
+
+ /**
* \brief Layout qualifier for gl_FragDepth.
*
* This is not equal to \c ir_depth_layout_none if and only if this
diff --git a/src/compiler/nir/nir_gather_info.c b/src/compiler/nir/nir_gather_info.c
index ef5d053..e80a65f 100644
--- a/src/compiler/nir/nir_gather_info.c
+++ b/src/compiler/nir/nir_gather_info.c
@@ -161,6 +161,17 @@
type = glsl_get_array_element(type);
}
+ if (var->data.per_view) {
+ /* TODO: Per view and Per Vertex are not currently used together. When
+ * they start to be used (e.g. when adding Primitive Replication for GS
+ * on Intel), verify that "peeling" the type twice is correct. This
+ * assert ensures we remember it.
+ */
+ assert(!nir_is_per_vertex_io(var, shader->info.stage));
+ assert(glsl_type_is_array(type));
+ type = glsl_get_array_element(type);
+ }
+
const unsigned slots =
var->data.compact ? DIV_ROUND_UP(glsl_get_length(type), 4)
: glsl_count_attribute_slots(type, false);
@@ -209,6 +220,10 @@
type = glsl_get_array_element(type);
}
+ /* Per view variables will be considered as a whole. */
+ if (var->data.per_view)
+ return false;
+
/* The code below only handles:
*
* - Indexing into matrices
diff --git a/src/compiler/nir/nir_linking_helpers.c b/src/compiler/nir/nir_linking_helpers.c
index ec1bd77..d187096 100644
--- a/src/compiler/nir/nir_linking_helpers.c
+++ b/src/compiler/nir/nir_linking_helpers.c
@@ -50,7 +50,7 @@
assert(var->data.location >= 0);
const struct glsl_type *type = var->type;
- if (nir_is_per_vertex_io(var, stage)) {
+ if (nir_is_per_vertex_io(var, stage) || var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
@@ -279,7 +279,7 @@
var->data.location - VARYING_SLOT_VAR0 < MAX_VARYINGS_INCL_PATCH) {
const struct glsl_type *type = var->type;
- if (nir_is_per_vertex_io(var, stage)) {
+ if (nir_is_per_vertex_io(var, stage) || var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
@@ -376,7 +376,7 @@
var->data.location - VARYING_SLOT_VAR0 < MAX_VARYINGS_INCL_PATCH) {
const struct glsl_type *type = var->type;
- if (nir_is_per_vertex_io(var, stage)) {
+ if (nir_is_per_vertex_io(var, stage) || var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
@@ -500,7 +500,7 @@
continue;
const struct glsl_type *type = var->type;
- if (nir_is_per_vertex_io(var, producer->info.stage)) {
+ if (nir_is_per_vertex_io(var, producer->info.stage) || var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
@@ -557,7 +557,8 @@
if (!vc_info->initialised) {
const struct glsl_type *type = in_var->type;
- if (nir_is_per_vertex_io(in_var, consumer->info.stage)) {
+ if (nir_is_per_vertex_io(in_var, consumer->info.stage) ||
+ in_var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
@@ -1096,7 +1097,7 @@
bool last_partial = false;
nir_foreach_variable(var, var_list) {
const struct glsl_type *type = var->type;
- if (nir_is_per_vertex_io(var, stage)) {
+ if (nir_is_per_vertex_io(var, stage) || var->data.per_view) {
assert(glsl_type_is_array(type));
type = glsl_get_array_element(type);
}
diff --git a/src/compiler/nir/nir_lower_io_arrays_to_elements.c b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
index c4c7c5c..e49abef 100644
--- a/src/compiler/nir/nir_lower_io_arrays_to_elements.c
+++ b/src/compiler/nir/nir_lower_io_arrays_to_elements.c
@@ -293,6 +293,10 @@
if (var->data.compact)
continue;
+ /* Per-view variables are expected to remain arrays. */
+ if (var->data.per_view)
+ continue;
+
/* Skip indirects */
int loc = var->data.location * 4 + var->data.location_frac;
if (BITSET_TEST(indirects, loc))
diff --git a/src/compiler/nir/nir_lower_io_to_vector.c b/src/compiler/nir/nir_lower_io_to_vector.c
index 05412e2..f85e53a 100644
--- a/src/compiler/nir/nir_lower_io_to_vector.c
+++ b/src/compiler/nir/nir_lower_io_to_vector.c
@@ -84,6 +84,9 @@
if (a->data.compact || b->data.compact)
return false;
+ if (a->data.per_view || b->data.per_view)
+ return false;
+
const struct glsl_type *a_type_tail = a->type;
const struct glsl_type *b_type_tail = b->type;
diff --git a/src/compiler/nir/nir_print.c b/src/compiler/nir/nir_print.c
index 41a60ae..6fc8fc9 100644
--- a/src/compiler/nir/nir_print.c
+++ b/src/compiler/nir/nir_print.c
@@ -461,8 +461,10 @@
const char *const samp = (var->data.sample) ? "sample " : "";
const char *const patch = (var->data.patch) ? "patch " : "";
const char *const inv = (var->data.invariant) ? "invariant " : "";
- fprintf(fp, "%s%s%s%s%s %s ",
- cent, samp, patch, inv, get_variable_mode_str(var->data.mode, false),
+ const char *const per_view = (var->data.per_view) ? "per_view " : "";
+ fprintf(fp, "%s%s%s%s%s%s %s ",
+ cent, samp, patch, inv, per_view,
+ get_variable_mode_str(var->data.mode, false),
glsl_interp_mode_name(var->data.interpolation));
enum gl_access_qualifier access = var->data.access;
diff --git a/src/compiler/nir/nir_validate.c b/src/compiler/nir/nir_validate.c
index 3ef4bbc..410f590 100644
--- a/src/compiler/nir/nir_validate.c
+++ b/src/compiler/nir/nir_validate.c
@@ -1134,6 +1134,9 @@
validate_assert(state, var->members != NULL);
}
+ if (var->data.per_view)
+ validate_assert(state, glsl_type_is_array(var->type));
+
/*
* TODO validate some things ir_validate.cpp does (requires more GLSL type
* support)