summaryrefslogtreecommitdiffstats
path: root/src/glsl/lower_buffer_access.cpp
diff options
context:
space:
mode:
authorJordan Justen <[email protected]>2015-11-13 12:08:26 -0800
committerJordan Justen <[email protected]>2015-12-09 23:50:38 -0800
commit99c8196458dc8f299d0b49c8ee801d6e9a2bc1db (patch)
tree3bcd97750cf862fce632dc0feec83facaae7ba8c /src/glsl/lower_buffer_access.cpp
parentafa4129cf6ee0a64811b118d270f1b05d7d05325 (diff)
glsl ubo/ssbo: Move is_dereferenced_thing_row_major into lower_buffer_access
Signed-off-by: Jordan Justen <[email protected]> Reviewed-by: Iago Toral Quiroga <[email protected]> Reviewed-by: Kristian Høgsberg <[email protected]>
Diffstat (limited to 'src/glsl/lower_buffer_access.cpp')
-rw-r--r--src/glsl/lower_buffer_access.cpp90
1 files changed, 90 insertions, 0 deletions
diff --git a/src/glsl/lower_buffer_access.cpp b/src/glsl/lower_buffer_access.cpp
index 7428742adfc..0f5ba17bbf9 100644
--- a/src/glsl/lower_buffer_access.cpp
+++ b/src/glsl/lower_buffer_access.cpp
@@ -213,4 +213,94 @@ lower_buffer_access::emit_access(void *mem_ctx,
}
}
+/**
+ * Determine if a thing being dereferenced is row-major
+ *
+ * There is some trickery here.
+ *
+ * If the thing being dereferenced is a member of uniform block \b without an
+ * instance name, then the name of the \c ir_variable is the field name of an
+ * interface type. If this field is row-major, then the thing referenced is
+ * row-major.
+ *
+ * If the thing being dereferenced is a member of uniform block \b with an
+ * instance name, then the last dereference in the tree will be an
+ * \c ir_dereference_record. If that record field is row-major, then the
+ * thing referenced is row-major.
+ */
+bool
+lower_buffer_access::is_dereferenced_thing_row_major(const ir_rvalue *deref)
+{
+ bool matrix = false;
+ const ir_rvalue *ir = deref;
+
+ while (true) {
+ matrix = matrix || ir->type->without_array()->is_matrix();
+
+ switch (ir->ir_type) {
+ case ir_type_dereference_array: {
+ const ir_dereference_array *const array_deref =
+ (const ir_dereference_array *) ir;
+
+ ir = array_deref->array;
+ break;
+ }
+
+ case ir_type_dereference_record: {
+ const ir_dereference_record *const record_deref =
+ (const ir_dereference_record *) ir;
+
+ ir = record_deref->record;
+
+ const int idx = ir->type->field_index(record_deref->field);
+ assert(idx >= 0);
+
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(ir->type->fields.structure[idx].matrix_layout);
+
+ switch (matrix_layout) {
+ case GLSL_MATRIX_LAYOUT_INHERITED:
+ break;
+ case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+ return false;
+ case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+ return matrix || deref->type->without_array()->is_record();
+ }
+
+ break;
+ }
+
+ case ir_type_dereference_variable: {
+ const ir_dereference_variable *const var_deref =
+ (const ir_dereference_variable *) ir;
+
+ const enum glsl_matrix_layout matrix_layout =
+ glsl_matrix_layout(var_deref->var->data.matrix_layout);
+
+ switch (matrix_layout) {
+ case GLSL_MATRIX_LAYOUT_INHERITED:
+ assert(!matrix);
+ return false;
+ case GLSL_MATRIX_LAYOUT_COLUMN_MAJOR:
+ return false;
+ case GLSL_MATRIX_LAYOUT_ROW_MAJOR:
+ return matrix || deref->type->without_array()->is_record();
+ }
+
+ unreachable("invalid matrix layout");
+ break;
+ }
+
+ default:
+ return false;
+ }
+ }
+
+ /* The tree must have ended with a dereference that wasn't an
+ * ir_dereference_variable. That is invalid, and it should be impossible.
+ */
+ unreachable("invalid dereference tree");
+ return false;
+}
+
} /* namespace lower_buffer_access */