From 17e6f1904444be019cafa208495e3fe479cb86fd Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Tue, 11 Dec 2012 12:14:03 -0800 Subject: [PATCH] glsl: Generate an interface type for uniform blocks If the block has an instance name, add the instance name to the symbol table instead of the individual fields. Fixes the piglit test interface-name-access-without-interface-name.vert for real. v2: Update the comment before the assertion that interface block definitions won't generate instructions. Suggested by Paul Berry. Signed-off-by: Ian Romanick Reviewed-by: Paul Berry --- src/glsl/ast_to_hir.cpp | 167 ++++++++++++++++++++++++++++------------ 1 file changed, 118 insertions(+), 49 deletions(-) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 788108dcb0b..163c39aeb93 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -4034,7 +4034,9 @@ ast_process_structure_or_interface_block(exec_list *instructions, struct _mesa_glsl_parse_state *state, exec_list *declarations, YYLTYPE &loc, - glsl_struct_field **fields_ret) + glsl_struct_field **fields_ret, + bool is_interface, + bool block_row_major) { unsigned decl_count = 0; @@ -4076,7 +4078,32 @@ ast_process_structure_or_interface_block(exec_list *instructions, foreach_list_typed (ast_declaration, decl, link, &decl_list->declarations) { - const struct glsl_type *field_type = decl_type; + /* From the GL_ARB_uniform_buffer_object spec: + * + * "Sampler types are not allowed inside of uniform + * blocks. All other types, arrays, and structures + * allowed for uniforms are allowed within a uniform + * block." + */ + const struct glsl_type *field_type = decl_type; + + if (is_interface && field_type->contains_sampler()) { + YYLTYPE loc = decl_list->get_location(); + _mesa_glsl_error(&loc, state, + "Uniform in non-default uniform block contains sampler\n"); + } + + const struct ast_type_qualifier *const qual = + & decl_list->type->qualifier; + if (qual->flags.q.std140 || + qual->flags.q.packed || + qual->flags.q.shared) { + _mesa_glsl_error(&loc, state, + "uniform block layout qualifiers std140, packed, and " + "shared can only be applied to uniform blocks, not " + "members"); + } + if (decl->is_array) { field_type = process_array_type(&loc, decl_type, decl->array_size, state); @@ -4084,6 +4111,26 @@ ast_process_structure_or_interface_block(exec_list *instructions, fields[i].type = (field_type != NULL) ? field_type : glsl_type::error_type; fields[i].name = decl->identifier; + + if (qual->flags.q.row_major || qual->flags.q.column_major) { + if (!field_type->is_matrix() && !field_type->is_record()) { + _mesa_glsl_error(&loc, state, + "uniform block layout qualifiers row_major and " + "column_major can only be applied to matrix and " + "structure types"); + } else + validate_matrix_layout_for_type(state, &loc, field_type); + } + + if (field_type->is_matrix() || + (field_type->is_array() && field_type->fields.array->is_matrix())) { + fields[i].row_major = block_row_major; + if (qual->flags.q.row_major) + fields[i].row_major = true; + else if (qual->flags.q.column_major) + fields[i].row_major = false; + } + i++; } } @@ -4106,7 +4153,9 @@ ast_struct_specifier::hir(exec_list *instructions, state, &this->declarations, loc, - &fields); + &fields, + false, + false); const glsl_type *t = glsl_type::get_record_instance(fields, decl_count, this->name); @@ -4152,6 +4201,8 @@ ir_rvalue * ast_uniform_block::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) { + YYLTYPE loc = this->get_location(); + /* The ast_uniform_block has a list of ast_declarator_lists. We * need to turn those into ir_variables with an association * with this uniform block. @@ -4175,60 +4226,78 @@ ast_uniform_block::hir(exec_list *instructions, ubo->_Packing = ubo_packing_std140; } - unsigned int num_variables = 0; - foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { - foreach_list_const(node, &decl_list->declarations) { - num_variables++; + bool block_row_major = this->layout.flags.q.row_major; + exec_list declared_variables; + glsl_struct_field *fields; + unsigned int num_variables = + ast_process_structure_or_interface_block(&declared_variables, + state, + &this->declarations, + loc, + &fields, + true, + block_row_major); + + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_STD140) + == unsigned(ubo_packing_std140)); + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_SHARED) + == unsigned(ubo_packing_shared)); + STATIC_ASSERT(unsigned(GLSL_INTERFACE_PACKING_PACKED) + == unsigned(ubo_packing_packed)); + + const glsl_type *block_type = + glsl_type::get_interface_instance(fields, + num_variables, + (enum glsl_interface_packing) ubo->_Packing, + this->block_name); + + /* Since interface blocks cannot contain statements, it should be + * impossible for the block to generate any instructions. + */ + assert(declared_variables.is_empty()); + + /* Page 39 (page 45 of the PDF) of section 4.3.7 in the GLSL ES 3.00 spec + * says: + * + * "If an instance name (instance-name) is used, then it puts all the + * members inside a scope within its own name space, accessed with the + * field selector ( . ) operator (analogously to structures)." + */ + if (this->instance_name) { + ir_variable *var = new(state) ir_variable(block_type, + this->instance_name, + ir_var_uniform); + + state->symbols->add_variable(var); + instructions->push_tail(var); + } else { + for (unsigned i = 0; i < num_variables; i++) { + ir_variable *var = + new(state) ir_variable(fields[i].type, + ralloc_strdup(state, fields[i].name), + ir_var_uniform); + var->uniform_block = ubo - state->uniform_blocks; + + state->symbols->add_variable(var); + instructions->push_tail(var); } } - bool block_row_major = this->layout.flags.q.row_major; - + /* FINISHME: Eventually the rest of this code needs to be moved into the + * FINISHME: linker. + */ ubo->Uniforms = rzalloc_array(state->uniform_blocks, struct gl_uniform_buffer_variable, num_variables); - foreach_list_typed(ast_declarator_list, decl_list, link, &declarations) { - exec_list declared_variables; - - decl_list->hir(&declared_variables, state); - - foreach_list_const(node, &declared_variables) { - ir_variable *var = (ir_variable *)node; - - struct gl_uniform_buffer_variable *ubo_var = - &ubo->Uniforms[ubo->NumUniforms++]; - - var->uniform_block = ubo - state->uniform_blocks; - - ubo_var->Name = ralloc_strdup(state->uniform_blocks, var->name); - ubo_var->Type = var->type; - ubo_var->Offset = 0; /* Assigned at link time. */ - - if (var->type->is_matrix() || - (var->type->is_array() && var->type->fields.array->is_matrix())) { - ubo_var->RowMajor = block_row_major; - if (decl_list->type->qualifier.flags.q.row_major) - ubo_var->RowMajor = true; - else if (decl_list->type->qualifier.flags.q.column_major) - ubo_var->RowMajor = false; - } - - /* From the GL_ARB_uniform_buffer_object spec: - * - * "Sampler types are not allowed inside of uniform - * blocks. All other types, arrays, and structures - * allowed for uniforms are allowed within a uniform - * block." - */ - if (var->type->contains_sampler()) { - YYLTYPE loc = decl_list->get_location(); - _mesa_glsl_error(&loc, state, - "Uniform in non-default uniform block contains sampler\n"); - } - } + for (unsigned i = 0; i < num_variables; i++) { + struct gl_uniform_buffer_variable *ubo_var = + &ubo->Uniforms[ubo->NumUniforms++]; - instructions->append_list(&declared_variables); + ubo_var->Name = ralloc_strdup(state->uniform_blocks, fields[i].name); + ubo_var->Type = fields[i].type; + ubo_var->Offset = 0; /* Assigned at link time. */ + ubo_var->RowMajor = fields[i].row_major; } return NULL; -- 2.30.2