This patch brings 2 new structures: - gl_shader_ubo_variable which holds name and type of a variable inside an ubo - gl_uniform_buffer_object which holds UBO wide and variable informations in the form of a gl_shader_ubo_variable array. This patch also updates parser front-end to fill these structures on a shader scope. --- src/glsl/ast.h | 23 ++++++ src/glsl/ast_to_hir.cpp | 75 +++++++++++++++++- src/glsl/glsl_lexer.ll | 3 +- src/glsl/glsl_parser.yy | 165 ++++++++++++++++++++++++++++++++++++++- src/glsl/glsl_parser_extras.cpp | 5 + src/glsl/glsl_parser_extras.h | 7 ++ src/mesa/main/mtypes.h | 46 +++++++++++ src/mesa/program/ir_to_mesa.cpp | 7 ++ 8 files changed, 328 insertions(+), 3 deletions(-)
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index d899bc6..8effa5b 100644 --- a/src/glsl/ast.h +++ b/src/glsl/ast.h @@ -351,6 +351,15 @@ struct ast_type_qualifier { */ unsigned explicit_location:1; + /** UBO Layout, should be 2 enum but using bit instead + * to be coherent with struct definition + */ + unsigned std140:1; + unsigned packed:1; + unsigned shared:1; + unsigned column_major:1; + unsigned row_major:1; + /** \name Layout qualifiers for GL_AMD_conservative_depth */ /** \{ */ unsigned depth_any:1; @@ -539,6 +548,20 @@ public: int invariant; }; +class ast_uniform_buffer_object : public ast_node { +public: + ast_uniform_buffer_object(ast_declarator_list* lst,char* n) : name(n) { + components.push_degenerate_list_at_head(& lst->link); + } + + virtual ir_rvalue *hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state); + + exec_list components; + ast_type_qualifier layout_qualifier; + const char* name; +}; + class ast_parameter_declarator : public ast_node { public: diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index d5b04e9..c2f8796 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -81,6 +81,7 @@ _mesa_ast_to_hir(exec_list *instructions, struct _mesa_glsl_parse_state *state) * by the linker. */ state->symbols->push_scope(); + state->ubo_count = 0; foreach_list_typed (ast_node, ast, link, & state->translation_unit) ast->hir(instructions, state); @@ -1967,8 +1968,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, else if (qual->flags.q.out || (qual->flags.q.varying && (state->target == vertex_shader))) var->mode = ir_var_out; - else if (qual->flags.q.uniform) + else if (qual->flags.q.uniform) { var->mode = ir_var_uniform; + } if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { @@ -2915,6 +2917,77 @@ ast_declarator_list::hir(exec_list *instructions, return result; } +ir_rvalue * +ast_uniform_buffer_object::hir(exec_list *instructions, _mesa_glsl_parse_state *state) +{ + void *ctx = state; + YYLTYPE loc = this->get_location(); + +#if FEATURE_ARB_uniform_buffer_object + + /** + * Counting variable the hard way. + */ + int var_count = 0; + foreach_list_typed (ast_declarator_list, decl_list, link, + &this->components) { + decl_list->hir(instructions,state); + + foreach_list_typed (ast_declaration, decl, link, + &decl_list->declarations) { + var_count++; + } + } + + if(state->ubo_count == 0) + state->UniformBufferObjects = (struct gl_uniform_buffer_object*) + ralloc_array_size(ctx, sizeof(gl_uniform_buffer_object),1); + else + state->UniformBufferObjects = (struct gl_uniform_buffer_object*) + reralloc_array_size(ctx, state->UniformBufferObjects, sizeof(gl_uniform_buffer_object), state->ubo_count + 1); + + gl_uniform_buffer_object& new_ubo = state->UniformBufferObjects[state->ubo_count]; + + state->ubo_count++; + + void* inner_ctx = (void*) state->UniformBufferObjects; + new_ubo.NumberOfVariables = var_count; + new_ubo.Variables = (struct gl_shader_ubo_variable*) ralloc_array_size(inner_ctx,sizeof(gl_shader_ubo_variable),var_count); + new_ubo.Name = ralloc_strdup(inner_ctx,this->name); + + int var_position = 0; + foreach_list_typed (ast_declarator_list, decl_list, link, + &this->components) { + foreach_list_typed (ast_declaration, decl, link, + &decl_list->declarations) { + struct gl_shader_ubo_variable& var_ubo = new_ubo.Variables[var_position]; + var_ubo.Name = ralloc_strdup(inner_ctx,decl->identifier); + + ir_variable* var = state->symbols->get_variable(var_ubo.Name); + var->mode = ir_var_uniform; + var->is_ubo_variable = true; + var_ubo.Type = var->type; + + var_position++; + } + } + + if(this->layout_qualifier.flags.q.std140) + new_ubo.Layout = UBO_LAYOUT_SDT140; + if(this->layout_qualifier.flags.q.packed) + new_ubo.Layout = UBO_LAYOUT_PACKED; + if(this->layout_qualifier.flags.q.shared) + new_ubo.Layout = UBO_LAYOUT_SHARED; + if(this->layout_qualifier.flags.q.column_major) + new_ubo.Layout = UBO_MATRIX_LAYOUT_COLUMN_MAJOR; + if(this->layout_qualifier.flags.q.row_major) + new_ubo.Layout = UBO_MATRIX_LAYOUT_ROW_MAJOR; + +#endif + + return NULL; +} + ir_rvalue * ast_parameter_declarator::hir(exec_list *instructions, diff --git a/src/glsl/glsl_lexer.ll b/src/glsl/glsl_lexer.ll index c7cfedd..c5d0ec4 100644 --- a/src/glsl/glsl_lexer.ll +++ b/src/glsl/glsl_lexer.ll @@ -312,7 +312,8 @@ layout { || yyextra->AMD_conservative_depth_enable || yyextra->ARB_conservative_depth_enable || yyextra->ARB_explicit_attrib_location_enable - || yyextra->ARB_fragment_coord_conventions_enable) { + || yyextra->ARB_fragment_coord_conventions_enable + || yyextra->ARB_uniform_buffer_object_enable) { return LAYOUT_TOK; } else { yylval->identifier = strdup(yytext); diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 71ab039..24fe42a 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -72,6 +72,7 @@ ast_case_label_list *case_label_list; ast_case_statement *case_statement; ast_case_statement_list *case_statement_list; + ast_uniform_buffer_object *uniform_buffer_object; struct { ast_node *cond; @@ -142,6 +143,7 @@ %type <node> statement_list %type <node> simple_statement %type <n> precision_qualifier +%type <node> layout_defaults %type <type_qualifier> type_qualifier %type <type_qualifier> storage_qualifier %type <type_qualifier> interpolation_qualifier @@ -201,6 +203,11 @@ %type <node> external_declaration %type <declarator_list> init_declarator_list %type <declarator_list> single_declaration +%type <uniform_buffer_object> uniform_buffer_object +%type <uniform_buffer_object> uniform_buffer_object_block +%type <declarator_list> uniform_buffer_object_declaration_list +%type <declarator_list> ubo_variables_declarator_list +%type <declarator_list> ubo_single_declaration %type <expression> initializer %type <node> declaration %type <node> declaration_statement @@ -789,6 +796,11 @@ declaration: $3->is_precision_statement = true; $$ = $3; } + | uniform_buffer_object ';' + { + $$ = $1; + } + | layout_defaults { $$ = NULL;} ; function_prototype: @@ -1054,6 +1066,126 @@ single_declaration: } ; + + +uniform_buffer_object: + uniform_buffer_object_block + { + $1->layout_qualifier = *(state->default_layout); + $$ = $1; + } + | layout_qualifier uniform_buffer_object_block + { + $2->layout_qualifier = $1; + $$ = $2; + } +; + +// IDENTIFIER is more accurate than any_identifier, resulting in absence of shift/reduce conflict +uniform_buffer_object_block: + UNIFORM NEW_IDENTIFIER '{' uniform_buffer_object_declaration_list '}' + { + void *ctx = state; + ast_uniform_buffer_object *ubo = new (ctx) ast_uniform_buffer_object($4,$2); + $$ = ubo; + } + | UNIFORM NEW_IDENTIFIER '{' uniform_buffer_object_declaration_list '}' NEW_IDENTIFIER + { + _mesa_glsl_error(& @1, state, "Instance name not supported"); + } + | UNIFORM NEW_IDENTIFIER '{' uniform_buffer_object_declaration_list '}' NEW_IDENTIFIER '[' expression ']' + { + _mesa_glsl_error(& @1, state, "Array of UBO not supported"); + } +; + + +uniform_buffer_object_declaration_list: + ubo_variables_declarator_list ';' + { + $$ = $1; + $1->link.self_link(); + } + | uniform_buffer_object_declaration_list ubo_variables_declarator_list ';' + { + $$ = $1; + $$->link.insert_before(& $2->link); + } +; + +// No initializer here... +ubo_variables_declarator_list: + ubo_single_declaration + | ubo_variables_declarator_list ',' any_identifier + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($3, false, NULL, NULL); + decl->set_location(yylloc); + + $$ = $1; + $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + } + | ubo_variables_declarator_list ',' any_identifier '[' ']' + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($3, true, NULL, NULL); + decl->set_location(yylloc); + + $$ = $1; + $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + } + | ubo_variables_declarator_list ',' any_identifier '[' constant_expression ']' + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($3, true, $5, NULL); + decl->set_location(yylloc); + + $$ = $1; + $$->declarations.push_tail(&decl->link); + state->symbols->add_variable(new(state) ir_variable(NULL, $3, ir_var_auto)); + } + ; + +// No initializer here +ubo_single_declaration: + fully_specified_type + { + void *ctx = state; + /* Empty declaration list is valid. */ + $$ = new(ctx) ast_declarator_list($1); + $$->set_location(yylloc); + } + | fully_specified_type any_identifier + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($2, false, NULL, NULL); + + $$ = new(ctx) ast_declarator_list($1); + $$->set_location(yylloc); + $$->declarations.push_tail(&decl->link); + } + | fully_specified_type any_identifier '[' ']' + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($2, true, NULL, NULL); + + $$ = new(ctx) ast_declarator_list($1); + $$->set_location(yylloc); + $$->declarations.push_tail(&decl->link); + } + | fully_specified_type any_identifier '[' constant_expression ']' + { + void *ctx = state; + ast_declaration *decl = new(ctx) ast_declaration($2, true, $4, NULL); + + $$ = new(ctx) ast_declarator_list($1); + $$->set_location(yylloc); + $$->declarations.push_tail(&decl->link); + } + ; + fully_specified_type: type_specifier { @@ -1153,6 +1285,30 @@ layout_qualifier_id: } } + /* Layout qualifiers for UBO */ + if (!got_one) { + if (strcmp($1, "std140") == 0) { + got_one = true; + $$.flags.q.std140 = 1; + } + else if (strcmp($1, "packed") == 0) { + got_one = true; + $$.flags.q.packed = 1; + } + else if (strcmp($1, "shared") == 0) { + got_one = true; + $$.flags.q.shared = 1; + } + else if (strcmp($1, "column_major") == 0) { + got_one = true; + $$.flags.q.column_major = 1; + } + else if (strcmp($1, "row_major") == 0) { + got_one = true; + $$.flags.q.row_major = 1; + } + } + if (!got_one) { _mesa_glsl_error(& @1, state, "unrecognized layout identifier " "`%s'\n", $1); @@ -1531,13 +1687,20 @@ statement: | simple_statement ; +layout_defaults: + layout_qualifier UNIFORM ';' + { + *(state->default_layout) = $1; + } + ; + simple_statement: declaration_statement | expression_statement | selection_statement | switch_statement | iteration_statement - | jump_statement + | jump_statement ; compound_statement: diff --git a/src/glsl/glsl_parser_extras.cpp b/src/glsl/glsl_parser_extras.cpp index 71b4c5c..6b7eee2 100644 --- a/src/glsl/glsl_parser_extras.cpp +++ b/src/glsl/glsl_parser_extras.cpp @@ -36,6 +36,8 @@ extern "C" { #include "ir_optimization.h" #include "loop_analysis.h" +static ast_type_qualifier layout_container[1]; + _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx, GLenum target, void *mem_ctx) { @@ -114,6 +116,9 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *ctx, } this->supported_version_string = supported; + this->default_layout = layout_container; + default_layout->flags.q.column_major = 1; + default_layout->flags.q.shared = 1; } const char * diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 572e614..8eb2ffc 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -42,6 +42,9 @@ enum _mesa_glsl_parser_targets { struct gl_context; +#include <main/mtypes.h> + + struct _mesa_glsl_parse_state { _mesa_glsl_parse_state(struct gl_context *ctx, GLenum target, void *mem_ctx); @@ -204,6 +207,10 @@ struct _mesa_glsl_parse_state { /** Shaders containing built-in functions that are used for linking. */ struct gl_shader *builtins_to_link[16]; unsigned num_builtins_to_link; + + struct gl_uniform_buffer_object* UniformBufferObjects; + unsigned ubo_count; + struct ast_type_qualifier * default_layout; }; typedef struct YYLTYPE { diff --git a/src/mesa/main/mtypes.h b/src/mesa/main/mtypes.h index 08cd80a..c4b5e28 100644 --- a/src/mesa/main/mtypes.h +++ b/src/mesa/main/mtypes.h @@ -2127,6 +2127,50 @@ struct gl_sl_pragmas GLboolean Debug; /**< defaults off */ }; +/** + * Uniform Buffer Object variable informations. + * This come in 2 flavors : + * As layout informations (Size,Offset,...) are defined per program and not per shader, + * shaders_ubo_variable only store the relevant information to preserve memory. + * program_ubo_variable stores everything that can be retrieved by GetActiveUniformsiv + * (which makes it bigger than the data it refers to...). + */ + +struct gl_shader_ubo_variable +{ + char* Name; + const struct glsl_type* Type; +}; + + +enum UBOLayout { + UBO_LAYOUT_PACKED, + UBO_LAYOUT_SHARED, + UBO_LAYOUT_SDT140, +}; + +enum UBOMatrixLayout { + UBO_MATRIX_LAYOUT_ROW_MAJOR, + UBO_MATRIX_LAYOUT_COLUMN_MAJOR, +}; + +/** + * Uniform Buffer Object Information. + * This struct is used by shader and program struct ; + * For StorageLayout, Compact form is used in shader, + * Full form is used in program. + */ + +struct gl_uniform_buffer_object +{ + char* Name; + GLuint Index; + struct gl_shader_ubo_variable* Variables; /** Malloced array */ + GLuint Layout; /** packed, shared or std140 */ + GLuint MatrixLayout; /** rowmajor or columnmajor */ + GLuint NumberOfVariables; /**< number of UBOVariableInfo in StorageLayout */ +}; + /** * A GLSL vertex or fragment shader object. @@ -2162,6 +2206,8 @@ struct gl_shader /** Shaders containing built-in functions that are used for linking. */ struct gl_shader *builtins_to_link[16]; unsigned num_builtins_to_link; + struct gl_uniform_buffer_object* UniformBufferObjects; + unsigned UBOCount; }; diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 79dfe46..a5f8eea 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3387,6 +3387,13 @@ _mesa_glsl_compile_shader(struct gl_context *ctx, struct gl_shader *shader) sizeof(shader->builtins_to_link[0]) * state->num_builtins_to_link); shader->num_builtins_to_link = state->num_builtins_to_link; + +#if FEATURE_ARB_uniform_buffer_object + shader->UBOCount = state->ubo_count; + shader->UniformBufferObjects = state->UniformBufferObjects; + ralloc_steal(shader,shader->UniformBufferObjects); +#endif + if (ctx->Shader.Flags & GLSL_LOG) { _mesa_write_shader_to_file(shader); } -- 1.7.7 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev