mirror of
https://gitlab.freedesktop.org/mesa/mesa.git
synced 2025-12-22 22:10:10 +01:00
glsl: Correctly determine when the field of a UBO is row-major
Previously if a field of an block with an instance name was marked row-major (but block itself was not), we would think the field (and it's sub-fields) were column-major. Fixes gles3conform failures in: ES3-CTS.shaders.uniform_block.random.basic_types.7 ES3-CTS.shaders.uniform_block.random.basic_types.9 ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.1 ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.3 ES3-CTS.shaders.uniform_block.random.nested_structs.3 ES3-CTS.shaders.uniform_block.random.nested_structs.5 ES3-CTS.shaders.uniform_block.random.nested_structs.8 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.3 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.6 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.7 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.8 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays.9 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.0 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.1 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.2 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.3 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.4 ES3-CTS.shaders.uniform_block.random.nested_structs_instance_arrays.6 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.0 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.1 ES3-CTS.shaders.uniform_block.random.nested_structs_arrays_instance_arrays.5 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.0 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.4 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.7 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.8 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.12 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.14 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.15 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.16 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.1 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.8 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.9 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.10 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.11 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.13 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.14 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.15 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.16 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.17 Fixes gles3conform failures (caused by previous commits) in: ES3-CTS.shaders.uniform_block.random.basic_types.8 ES3-CTS.shaders.uniform_block.random.basic_arrays.3 ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.0 ES3-CTS.shaders.uniform_block.random.basic_instance_arrays.2 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.9 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.13 ES3-CTS.shaders.uniform_block.random.all_per_block_buffers.18 ES3-CTS.shaders.uniform_block.random.all_shared_buffer.4 v2: Fix rebase failure noticed by Matt. v3: Use without_array() instead of older predicates. v4: s/GLSL_MATRIX_LAYOUT_DEFAULT/GLSL_MATRIX_LAYOUT_INHERITED/g Signed-off-by: Ian Romanick <ian.d.romanick@intel.com> Reviewed-by: Matt Turner <mattst88@gmail.com> [v2]
This commit is contained in:
parent
b71f149a44
commit
b17a4d5dab
1 changed files with 120 additions and 15 deletions
|
|
@ -40,6 +40,96 @@
|
||||||
|
|
||||||
using namespace ir_builder;
|
using namespace ir_builder;
|
||||||
|
|
||||||
|
/**
|
||||||
|
* 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.
|
||||||
|
*/
|
||||||
|
static bool
|
||||||
|
is_dereferenced_thing_row_major(const ir_dereference *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->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 {
|
namespace {
|
||||||
class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor {
|
class lower_ubo_reference_visitor : public ir_rvalue_enter_visitor {
|
||||||
public:
|
public:
|
||||||
|
|
@ -50,7 +140,7 @@ public:
|
||||||
|
|
||||||
void handle_rvalue(ir_rvalue **rvalue);
|
void handle_rvalue(ir_rvalue **rvalue);
|
||||||
void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset,
|
void emit_ubo_loads(ir_dereference *deref, ir_variable *base_offset,
|
||||||
unsigned int deref_offset);
|
unsigned int deref_offset, bool row_major);
|
||||||
ir_expression *ubo_load(const struct glsl_type *type,
|
ir_expression *ubo_load(const struct glsl_type *type,
|
||||||
ir_rvalue *offset);
|
ir_rvalue *offset);
|
||||||
|
|
||||||
|
|
@ -174,7 +264,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||||
|
|
||||||
ir_rvalue *offset = new(mem_ctx) ir_constant(0u);
|
ir_rvalue *offset = new(mem_ctx) ir_constant(0u);
|
||||||
unsigned const_offset = 0;
|
unsigned const_offset = 0;
|
||||||
bool row_major = ubo_var->RowMajor;
|
bool row_major = is_dereferenced_thing_row_major(deref);
|
||||||
|
|
||||||
/* Calculate the offset to the start of the region of the UBO
|
/* Calculate the offset to the start of the region of the UBO
|
||||||
* dereferenced by *rvalue. This may be a variable offset if an
|
* dereferenced by *rvalue. This may be a variable offset if an
|
||||||
|
|
@ -240,14 +330,24 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||||
unsigned max_field_align = 16;
|
unsigned max_field_align = 16;
|
||||||
for (unsigned int i = 0; i < struct_type->length; i++) {
|
for (unsigned int i = 0; i < struct_type->length; i++) {
|
||||||
const glsl_type *type = struct_type->fields.structure[i].type;
|
const glsl_type *type = struct_type->fields.structure[i].type;
|
||||||
unsigned field_align = type->std140_base_alignment(row_major);
|
|
||||||
|
ir_dereference_record *field_deref =
|
||||||
|
new(mem_ctx) ir_dereference_record(deref_record->record,
|
||||||
|
struct_type->fields.structure[i].name);
|
||||||
|
const bool field_row_major =
|
||||||
|
is_dereferenced_thing_row_major(field_deref);
|
||||||
|
|
||||||
|
ralloc_free(field_deref);
|
||||||
|
|
||||||
|
unsigned field_align = type->std140_base_alignment(field_row_major);
|
||||||
|
|
||||||
max_field_align = MAX2(field_align, max_field_align);
|
max_field_align = MAX2(field_align, max_field_align);
|
||||||
intra_struct_offset = glsl_align(intra_struct_offset, field_align);
|
intra_struct_offset = glsl_align(intra_struct_offset, field_align);
|
||||||
|
|
||||||
if (strcmp(struct_type->fields.structure[i].name,
|
if (strcmp(struct_type->fields.structure[i].name,
|
||||||
deref_record->field) == 0)
|
deref_record->field) == 0)
|
||||||
break;
|
break;
|
||||||
intra_struct_offset += type->std140_size(row_major);
|
intra_struct_offset += type->std140_size(field_row_major);
|
||||||
}
|
}
|
||||||
|
|
||||||
const_offset = glsl_align(const_offset, max_field_align);
|
const_offset = glsl_align(const_offset, max_field_align);
|
||||||
|
|
@ -279,7 +379,7 @@ lower_ubo_reference_visitor::handle_rvalue(ir_rvalue **rvalue)
|
||||||
base_ir->insert_before(assign(load_offset, offset));
|
base_ir->insert_before(assign(load_offset, offset));
|
||||||
|
|
||||||
deref = new(mem_ctx) ir_dereference_variable(load_var);
|
deref = new(mem_ctx) ir_dereference_variable(load_var);
|
||||||
emit_ubo_loads(deref, load_offset, const_offset);
|
emit_ubo_loads(deref, load_offset, const_offset, row_major);
|
||||||
*rvalue = deref;
|
*rvalue = deref;
|
||||||
|
|
||||||
progress = true;
|
progress = true;
|
||||||
|
|
@ -309,7 +409,8 @@ lower_ubo_reference_visitor::ubo_load(const glsl_type *type,
|
||||||
void
|
void
|
||||||
lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||||
ir_variable *base_offset,
|
ir_variable *base_offset,
|
||||||
unsigned int deref_offset)
|
unsigned int deref_offset,
|
||||||
|
bool row_major)
|
||||||
{
|
{
|
||||||
if (deref->type->is_record()) {
|
if (deref->type->is_record()) {
|
||||||
unsigned int field_offset = 0;
|
unsigned int field_offset = 0;
|
||||||
|
|
@ -323,18 +424,19 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||||
|
|
||||||
field_offset =
|
field_offset =
|
||||||
glsl_align(field_offset,
|
glsl_align(field_offset,
|
||||||
field->type->std140_base_alignment(ubo_var->RowMajor));
|
field->type->std140_base_alignment(row_major));
|
||||||
|
|
||||||
emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset);
|
emit_ubo_loads(field_deref, base_offset, deref_offset + field_offset,
|
||||||
|
row_major);
|
||||||
|
|
||||||
field_offset += field->type->std140_size(ubo_var->RowMajor);
|
field_offset += field->type->std140_size(row_major);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (deref->type->is_array()) {
|
if (deref->type->is_array()) {
|
||||||
unsigned array_stride =
|
unsigned array_stride =
|
||||||
glsl_align(deref->type->fields.array->std140_size(ubo_var->RowMajor),
|
glsl_align(deref->type->fields.array->std140_size(row_major),
|
||||||
16);
|
16);
|
||||||
|
|
||||||
for (unsigned i = 0; i < deref->type->length; i++) {
|
for (unsigned i = 0; i < deref->type->length; i++) {
|
||||||
|
|
@ -343,7 +445,8 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||||
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
||||||
element);
|
element);
|
||||||
emit_ubo_loads(element_deref, base_offset,
|
emit_ubo_loads(element_deref, base_offset,
|
||||||
deref_offset + i * array_stride);
|
deref_offset + i * array_stride,
|
||||||
|
row_major);
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
@ -355,16 +458,18 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||||
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
new(mem_ctx) ir_dereference_array(deref->clone(mem_ctx, NULL),
|
||||||
col);
|
col);
|
||||||
|
|
||||||
if (ubo_var->RowMajor) {
|
if (row_major) {
|
||||||
/* For a row-major matrix, the next column starts at the next
|
/* For a row-major matrix, the next column starts at the next
|
||||||
* element.
|
* element.
|
||||||
*/
|
*/
|
||||||
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4);
|
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 4,
|
||||||
|
row_major);
|
||||||
} else {
|
} else {
|
||||||
/* std140 always rounds the stride of arrays (and matrices) to a
|
/* std140 always rounds the stride of arrays (and matrices) to a
|
||||||
* vec4, so matrices are always 16 between columns/rows.
|
* vec4, so matrices are always 16 between columns/rows.
|
||||||
*/
|
*/
|
||||||
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16);
|
emit_ubo_loads(col_deref, base_offset, deref_offset + i * 16,
|
||||||
|
row_major);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
return;
|
return;
|
||||||
|
|
@ -373,7 +478,7 @@ lower_ubo_reference_visitor::emit_ubo_loads(ir_dereference *deref,
|
||||||
assert(deref->type->is_scalar() ||
|
assert(deref->type->is_scalar() ||
|
||||||
deref->type->is_vector());
|
deref->type->is_vector());
|
||||||
|
|
||||||
if (!ubo_var->RowMajor) {
|
if (!row_major) {
|
||||||
ir_rvalue *offset = add(base_offset,
|
ir_rvalue *offset = add(base_offset,
|
||||||
new(mem_ctx) ir_constant(deref_offset));
|
new(mem_ctx) ir_constant(deref_offset));
|
||||||
base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
|
base_ir->insert_before(assign(deref->clone(mem_ctx, NULL),
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue