--- src/glsl/ast.h | 23 ++++++ src/glsl/ast_to_hir.cpp | 64 ++++++++++++++++- src/glsl/glsl_parser.yy | 157 ++++++++++++++++++++++++++++++++++++++- src/glsl/glsl_parser_extras.cpp | 5 + src/glsl/glsl_parser_extras.h | 7 ++ src/mesa/program/ir_to_mesa.cpp | 7 ++ 6 files changed, 261 insertions(+), 2 deletions(-)
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index d1de227..53d97ba 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; @@ -538,6 +547,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 9e7496b..531faaf 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -82,6 +82,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); @@ -1892,8 +1893,10 @@ 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; + var->UBO = NULL; + } if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { @@ -2812,6 +2815,65 @@ 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(); + + /** + * 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++; + } + } + + ubo& current_ubo = state->UniformBufferObjects[state->ubo_count]; + current_ubo.NumberOfVariables = var_count; + current_ubo.StorageLayout = (UBOVariableInfo*) malloc(var_count * sizeof(UBOVariableInfo)); + current_ubo.Name = strdup(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) { + ir_variable* var = state->symbols->get_variable(decl->identifier); + var->mode = ir_var_uniform; + var->UBO = &(current_ubo.StorageLayout[var_position]); + current_ubo.StorageLayout[var_position].Name = strdup(decl->identifier); + current_ubo.StorageLayout[var_position].Type = var->type; + current_ubo.StorageLayout[var_position].UBO = &state->UniformBufferObjects[state->ubo_count]; + current_ubo.StorageLayout[var_position].IndexInUBO = var_position; + + var_position++; + } + } + + if(this->layout_qualifier.flags.q.std140) + current_ubo.Layout = std140; + if(this->layout_qualifier.flags.q.packed) + current_ubo.Layout = packed; + if(this->layout_qualifier.flags.q.shared) + current_ubo.Layout = shared; + if(this->layout_qualifier.flags.q.column_major) + current_ubo.Layout = columnmajor; + if(this->layout_qualifier.flags.q.row_major) + current_ubo.Layout = rowmajor; + + state->ubo_count++; + + return NULL; +} + ir_rvalue * ast_parameter_declarator::hir(exec_list *instructions, diff --git a/src/glsl/glsl_parser.yy b/src/glsl/glsl_parser.yy index 25d02fb..01d8fc4 100644 --- a/src/glsl/glsl_parser.yy +++ b/src/glsl/glsl_parser.yy @@ -67,6 +67,7 @@ ast_declarator_list *declarator_list; ast_struct_specifier *struct_specifier; ast_declaration *declaration; + ast_uniform_buffer_object *uniform_buffer_object; struct { ast_node *cond; @@ -136,6 +137,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 @@ -195,6 +197,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 @@ -777,6 +784,11 @@ declaration: $3->is_precision_statement = true; $$ = $3; } + | uniform_buffer_object ';' + { + $$ = $1; + } + | layout_defaults { $$ = NULL;} ; function_prototype: @@ -1042,6 +1054,118 @@ 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_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 { @@ -1134,6 +1258,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); @@ -1511,6 +1659,13 @@ statement: | simple_statement ; +layout_defaults: + layout_qualifier UNIFORM ';' + { + *(state->default_layout) = $1; + } + ; + simple_statement: declaration_statement | expression_statement @@ -1518,7 +1673,7 @@ simple_statement: | switch_statement { $$ = NULL; } | case_label { $$ = NULL; } | 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 61e3933..62fb495 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) { @@ -111,6 +113,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 8f843eb..b7a27ff 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); @@ -196,6 +199,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; + + ubo UniformBufferObjects[MAX_UBO_IN_SHADER]; + unsigned ubo_count; + struct ast_type_qualifier * default_layout; }; typedef struct YYLTYPE { diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 6820e4c..9e6e66d 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3370,6 +3370,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; + shader->UBOCount = state->ubo_count; + if(!shader->UniformBufferObjects) + shader->UniformBufferObjects = (struct ubo*) malloc(MAX_UBO_IN_SHADER * sizeof(struct ubo)); + for(unsigned i = 0; i<state->ubo_count;i++) { + shader->UniformBufferObjects[i] = state->UniformBufferObjects[i]; + } + if (ctx->Shader.Flags & GLSL_LOG) { _mesa_write_shader_to_file(shader); } -- 1.7.6.4 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev