From b3c093c79c2ec49c36af37aa290d5ae452149f6e Mon Sep 17 00:00:00 2001 From: Eric Anholt <eric@anholt.net> Date: Thu, 26 Apr 2012 18:21:43 -0700 Subject: glsl: Translate the AST for uniform blocks into some IR structures. We're going to need this structure to cross-validate the uniform blocks between shader stages, since unused ir_variables might get dropped. It's also the place we store the RowMajor qualifier, which is not part of the GLSL type (since that would cause a bunch of type equality checks to fail). Reviewed-by: Ian Romanick <ian.d.romanick@intel.com> --- src/glsl/ast_to_hir.cpp | 67 +++++++++++++++++++++++++++++++++++++++++++ src/glsl/glsl_parser_extras.h | 4 +++ src/glsl/ir.cpp | 1 + src/glsl/ir.h | 13 ++++++++- src/glsl/ir_clone.cpp | 1 + src/mesa/main/mtypes.h | 18 ++++++++++++ 6 files changed, 103 insertions(+), 1 deletion(-) (limited to 'src') diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 8c739653fbe..1c54991cf74 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -3994,6 +3994,25 @@ ast_struct_specifier::hir(exec_list *instructions, return NULL; } +static struct gl_uniform_block * +get_next_uniform_block(struct _mesa_glsl_parse_state *state) +{ + if (state->num_uniform_blocks >= state->uniform_block_array_size) { + state->uniform_block_array_size *= 2; + if (state->uniform_block_array_size <= 4) + state->uniform_block_array_size = 4; + + state->uniform_blocks = reralloc(state, + state->uniform_blocks, + struct gl_uniform_block, + state->uniform_block_array_size); + } + + memset(&state->uniform_blocks[state->num_uniform_blocks], + 0, sizeof(*state->uniform_blocks)); + return &state->uniform_blocks[state->num_uniform_blocks++]; +} + ir_rvalue * ast_uniform_block::hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) @@ -4002,11 +4021,59 @@ ast_uniform_block::hir(exec_list *instructions, * need to turn those into ir_variables with an association * with this uniform block. */ + struct gl_uniform_block *ubo = get_next_uniform_block(state); + ubo->Name = ralloc_strdup(state->uniform_blocks, this->block_name); + + 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; + + 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) { + struct 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->Buffer = ubo - state->uniform_blocks; + ubo_var->Offset = 0; /* Assigned at link time. */ + 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"); + } + } + instructions->append_list(&declared_variables); } diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index d97217ef943..fc5d11cb97c 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -82,6 +82,10 @@ struct _mesa_glsl_parse_state { exec_list translation_unit; glsl_symbol_table *symbols; + unsigned num_uniform_blocks; + unsigned uniform_block_array_size; + struct gl_uniform_block *uniform_blocks; + bool es_shader; unsigned language_version; const char *version_string; diff --git a/src/glsl/ir.cpp b/src/glsl/ir.cpp index 1c9eec6e2d1..b0e38d820e6 100644 --- a/src/glsl/ir.cpp +++ b/src/glsl/ir.cpp @@ -1491,6 +1491,7 @@ ir_variable::ir_variable(const struct glsl_type *type, const char *name, this->explicit_location = false; this->has_initializer = false; this->location = -1; + this->uniform_block = -1; this->warn_extension = NULL; this->constant_value = NULL; this->constant_initializer = NULL; diff --git a/src/glsl/ir.h b/src/glsl/ir.h index 9bbf3b7efae..8506f604058 100644 --- a/src/glsl/ir.h +++ b/src/glsl/ir.h @@ -453,7 +453,8 @@ public: * - Vertex shader output: one of the values from \c gl_vert_result. * - Fragment shader input: one of the values from \c gl_frag_attrib. * - Fragment shader output: one of the values from \c gl_frag_result. - * - Uniforms: Per-stage uniform slot number. + * - Uniforms: Per-stage uniform slot number for default uniform block. + * - Uniforms: Index within the uniform block definition for UBO members. * - Other: This field is not currently used. * * If the variable is a uniform, shader input, or shader output, and the @@ -461,6 +462,16 @@ public: */ int location; + /** + * Uniform block number for uniforms. + * + * This index is into the shader's list of uniform blocks, not the + * linked program's merged list. + * + * If the variable is not in a uniform block, the value will be -1. + */ + int uniform_block; + /** * output index for dual source blending. */ diff --git a/src/glsl/ir_clone.cpp b/src/glsl/ir_clone.cpp index 591fe7b7756..4314efa76d4 100644 --- a/src/glsl/ir_clone.cpp +++ b/src/glsl/ir_clone.cpp @@ -54,6 +54,7 @@ ir_variable::clone(void *mem_ctx, struct hash_table *ht) const var->interpolation = this->interpolation; var->location = this->location; var->index = this->index; + var->uniform_block = this->uniform_block; var->warn_extension = this->warn_extension; var->origin_upper_left = this->origin_upper_left; var->pixel_center_integer = this->pixel_center_integer; diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 4769e106631..b39a8dcd75b 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2237,6 +2237,24 @@ typedef enum MESA_SHADER_TYPES = 3 } gl_shader_type; +struct gl_uniform_buffer_variable +{ + char *Name; + const struct glsl_type *Type; + unsigned int Buffer; + unsigned int Offset; + GLboolean RowMajor; +}; + +struct gl_uniform_block +{ + /** Declared name of the uniform block */ + char *Name; + + /** Array of supplemental information about UBO ir_variables. */ + struct gl_uniform_buffer_variable *Uniforms; + GLuint NumUniforms; +}; /** * A GLSL program object. -- cgit v1.2.3