interface_field_name(void *mem_ctx, char *base_name, ir_rvalue *d,
ir_rvalue **nonconst_block_index)
{
- ir_rvalue *previous_index = NULL;
*nonconst_block_index = NULL;
+ char *name_copy = NULL;
+ size_t base_length = 0;
+
+ /* Loop back through the IR until we find the uniform block */
+ ir_rvalue *ir = d;
+ while (ir != NULL) {
+ switch (ir->ir_type) {
+ case ir_type_dereference_variable: {
+ /* Exit loop */
+ ir = NULL;
+ break;
+ }
+
+ case ir_type_dereference_record: {
+ ir_dereference_record *r = (ir_dereference_record *) ir;
+ ir = r->record->as_dereference();
+
+ /* If we got here it means any previous array subscripts belong to
+ * block members and not the block itself so skip over them in the
+ * next pass.
+ */
+ d = ir;
+ break;
+ }
+
+ case ir_type_dereference_array: {
+ ir_dereference_array *a = (ir_dereference_array *) ir;
+ ir = a->array->as_dereference();
+ break;
+ }
+
+ case ir_type_swizzle: {
+ ir_swizzle *s = (ir_swizzle *) ir;
+ ir = s->val->as_dereference();
+ /* Skip swizzle in the next pass */
+ d = ir;
+ break;
+ }
+
+ default:
+ assert(!"Should not get here.");
+ break;
+ }
+ }
while (d != NULL) {
switch (d->ir_type) {
case ir_type_dereference_variable: {
ir_dereference_variable *v = (ir_dereference_variable *) d;
- if (previous_index
- && v->var->is_interface_instance()
- && v->var->type->is_array()) {
-
- ir_constant *const_index = previous_index->as_constant();
- if (!const_index) {
- *nonconst_block_index = previous_index;
- return ralloc_asprintf(mem_ctx, "%s[0]", base_name);
- } else {
- return ralloc_asprintf(mem_ctx,
- "%s[%d]",
- base_name,
- const_index->get_uint_component(0));
- }
+ if (name_copy != NULL &&
+ v->var->is_interface_instance() &&
+ v->var->type->is_array()) {
+ return name_copy;
} else {
+ *nonconst_block_index = NULL;
return base_name;
}
break;
}
- case ir_type_dereference_record: {
- ir_dereference_record *r = (ir_dereference_record *) d;
-
- d = r->record->as_dereference();
- break;
- }
-
case ir_type_dereference_array: {
ir_dereference_array *a = (ir_dereference_array *) d;
+ size_t new_length;
+
+ if (name_copy == NULL) {
+ name_copy = ralloc_strdup(mem_ctx, base_name);
+ base_length = strlen(name_copy);
+ }
+
+ /* For arrays of arrays we start at the innermost array and work our
+ * way out so we need to insert the subscript at the base of the
+ * name string rather than just attaching it to the end.
+ */
+ new_length = base_length;
+ ir_constant *const_index = a->array_index->as_constant();
+ char *end = ralloc_strdup(NULL, &name_copy[new_length]);
+ if (!const_index) {
+ ir_rvalue *array_index = a->array_index;
+ if (array_index->type != glsl_type::uint_type)
+ array_index = i2u(array_index);
+
+ if (a->array->type->is_array() &&
+ a->array->type->fields.array->is_array()) {
+ ir_constant *base_size = new(mem_ctx)
+ ir_constant(a->array->type->fields.array->arrays_of_arrays_size());
+ array_index = mul(array_index, base_size);
+ }
+
+ if (*nonconst_block_index) {
+ *nonconst_block_index = add(*nonconst_block_index, array_index);
+ } else {
+ *nonconst_block_index = array_index;
+ }
+
+ ralloc_asprintf_rewrite_tail(&name_copy, &new_length, "[0]%s",
+ end);
+ } else {
+ ralloc_asprintf_rewrite_tail(&name_copy, &new_length, "[%d]%s",
+ const_index->get_uint_component(0),
+ end);
+ }
+ ralloc_free(end);
d = a->array->as_dereference();
- previous_index = a->array_index;
break;
}
- case ir_type_swizzle: {
- ir_swizzle *s = (ir_swizzle *) d;
- d = s->val->as_dereference();
- break;
- }
default:
assert(!"Should not get here.");
break;
interface_field_name(mem_ctx, (char *) var->get_interface_type()->name,
deref, &nonconst_block_index);
- /* Locate the ubo block by interface name */
+ /* Locate the block by interface name */
+ this->is_shader_storage = var->is_in_shader_storage_block();
+ unsigned num_blocks;
+ struct gl_uniform_block **blocks;
+ if (this->is_shader_storage) {
+ num_blocks = shader->NumShaderStorageBlocks;
+ blocks = shader->ShaderStorageBlocks;
+ } else {
+ num_blocks = shader->NumUniformBlocks;
+ blocks = shader->UniformBlocks;
+ }
this->uniform_block = NULL;
- for (unsigned i = 0; i < shader->NumUniformBlocks; i++) {
- if (strcmp(field_name, shader->UniformBlocks[i].Name) == 0) {
+ for (unsigned i = 0; i < num_blocks; i++) {
+ if (strcmp(field_name, blocks[i]->Name) == 0) {
ir_constant *index = new(mem_ctx) ir_constant(i);
if (nonconst_block_index) {
- if (nonconst_block_index->type != glsl_type::uint_type)
- nonconst_block_index = i2u(nonconst_block_index);
this->uniform_block = add(nonconst_block_index, index);
} else {
this->uniform_block = index;
}
- this->is_shader_storage = shader->UniformBlocks[i].IsShaderStorage;
-
- struct gl_uniform_block *block = &shader->UniformBlocks[i];
-
this->ubo_var = var->is_interface_instance()
- ? &block->Uniforms[0] : &block->Uniforms[var->data.location];
+ ? &blocks[i]->Uniforms[0] : &blocks[i]->Uniforms[var->data.location];
break;
}
if (deref_array->array->type->is_double())
array_stride *= 2;
*matrix_columns = deref_array->array->type->matrix_columns;
- } else if (deref_array->type->is_interface()) {
+ } else if (deref_array->type->without_array()->is_interface()) {
/* We're processing an array dereference of an interface instance
* array. The thing being dereferenced *must* be a variable
* dereference because interfaces cannot be embedded in other
* interface instance array will have the same offsets relative to
* the base of the block that backs them.
*/
- assert(deref_array->array->as_dereference_variable());
deref = deref_array->array->as_dereference();
break;
} else {
* or 32 depending on the number of columns.
*/
assert(matrix_columns <= 4);
- unsigned matrix_stride = glsl_align(matrix_columns * N, 16);
+ unsigned matrix_stride = 0;
+ /* Matrix stride for std430 mat2xY matrices are not rounded up to
+ * vec4 size. From OpenGL 4.3 spec, section 7.6.2.2 "Standard Uniform
+ * Block Layout":
+ *
+ * "2. If the member is a two- or four-component vector with components
+ * consuming N basic machine units, the base alignment is 2N or 4N,
+ * respectively." [...]
+ * "4. If the member is an array of scalars or vectors, the base alignment
+ * and array stride are set to match the base alignment of a single array
+ * element, according to rules (1), (2), and (3), and rounded up to the
+ * base alignment of a vec4." [...]
+ * "7. If the member is a row-major matrix with C columns and R rows, the
+ * matrix is stored identically to an array of R row vectors with C
+ * components each, according to rule (4)." [...]
+ * "When using the std430 storage layout, shader storage blocks will be
+ * laid out in buffer storage identically to uniform and shader storage
+ * blocks using the std140 layout, except that the base alignment and
+ * stride of arrays of scalars and vectors in rule 4 and of structures in
+ * rule 9 are not rounded up a multiple of the base alignment of a vec4."
+ */
+ if (packing == GLSL_INTERFACE_PACKING_STD430 && matrix_columns == 2)
+ matrix_stride = 2 * N;
+ else
+ matrix_stride = glsl_align(matrix_columns * N, 16);
const glsl_type *deref_type = deref->type->base_type == GLSL_TYPE_FLOAT ?
glsl_type::float_type : glsl_type::double_type;
add(base_offset,
new(mem_ctx) ir_constant(deref_offset + i * matrix_stride));
if (is_write) {
+ /* If the component is not in the writemask, then don't
+ * store any value.
+ */
+ if (!((1 << i) & write_mask))
+ continue;
+
base_ir->insert_after(ssbo_store(swizzle(deref, i, 1), chan_offset, 1));
} else {
if (!this->is_shader_storage) {
case ir_type_dereference_record:
{
ir_dereference_record *deref_record = (ir_dereference_record *) deref;
- const struct glsl_type *deref_record_type =
- deref_record->record->as_dereference()->type;
- unsigned record_length = deref_record_type->length;
+ ir_dereference *interface_deref =
+ deref_record->record->as_dereference();
+ assert(interface_deref != NULL);
+ const struct glsl_type *interface_type = interface_deref->type;
+ unsigned record_length = interface_type->length;
/* Unsized array is always the last element of the interface */
const struct glsl_type *unsized_array_type =
- deref_record_type->fields.structure[record_length - 1].type->fields.array;
+ interface_type->fields.structure[record_length - 1].type->fields.array;
const bool array_row_major =
is_dereferenced_thing_row_major(deref_record);
} /* unnamed namespace */
void
-lower_ubo_reference(struct gl_shader *shader, exec_list *instructions)
+lower_ubo_reference(struct gl_shader *shader)
{
lower_ubo_reference_visitor v(shader);
*/
do {
v.progress = false;
- visit_list_elements(&v, instructions);
+ visit_list_elements(&v, shader->ir);
} while (v.progress);
}