--- src/glsl/ast.h | 25 ++++++ src/glsl/ast_to_hir.cpp | 43 ++++++++++- src/glsl/glsl_parser.yy | 162 +++++++++++++++++++++++++++++++++++++++ src/glsl/glsl_parser_extras.h | 5 + src/mesa/program/ir_to_mesa.cpp | 5 + 5 files changed, 239 insertions(+), 1 deletions(-)
diff --git a/src/glsl/ast.h b/src/glsl/ast.h index d1de227..81ba927 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,22 @@ public: int invariant; }; +class ast_uniform_buffer_object : public ast_node { +public: + ast_uniform_buffer_object(ast_declarator_list* adl,char* block_name=NULL, ast_expression* block_length=NULL) : components(adl),name(block_name),length(block_length) { + + } + + virtual ir_rvalue *hir(exec_list *instructions, + struct _mesa_glsl_parse_state *state); + + ast_declarator_list* components; + ast_type_qualifier layout_qualifier; + const char* name; + ast_expression* length; + +}; + 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..13e60fd 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,11 @@ 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; + var->removable_uniform = true; + } if (state->all_invariant && (state->current_function == NULL)) { switch (state->target) { @@ -2812,6 +2816,43 @@ 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(); + + ir_rvalue* result = components->hir(instructions,state); + + /** Count the number or variable in UBO. + * Could be done inside ast_declarator_list::hir + */ + int var_count = 0; + foreach_list_typed (ast_declaration, decl, link, &this->components->declarations) { + var_count++; + } + + ubo& current_ubo = state->UniformBufferObjects[state->ubo_count]; + current_ubo.number_of_variables = var_count; + current_ubo.storage_layout = (UBOVariableInfo*) malloc(var_count * sizeof(UBOVariableInfo)); + current_ubo.name = strdup(this->name); + + int var_position = 0; + foreach_list_typed (ast_declaration, decl, link, &this->components->declarations) { + ir_variable* var = state->symbols->get_variable(decl->identifier); + var->mode = ir_var_uniform; + var->removable_uniform = false; + current_ubo.storage_layout[var_position].name = strdup(decl->identifier); + current_ubo.storage_layout[var_position].Type = var->type; + current_ubo.storage_layout[var_position].index = var_position; + + var_position++; + } + state->ubo_count++; + + return result; +} + 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..feb98c7 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; @@ -195,6 +196,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 +783,10 @@ declaration: $3->is_precision_statement = true; $$ = $3; } + | uniform_buffer_object ';' + { + $$ = $1; + } ; function_prototype: @@ -1042,6 +1052,134 @@ single_declaration: } ; + + +uniform_buffer_object: + uniform_buffer_object_block + { + $$ = $1; + } + | layout_qualifier uniform_buffer_object_block + { + $2->layout_qualifier = $1; + $$ = $2; + } + | uniform_buffer_object_block any_identifier + { + $$ = $1; + } + | layout_qualifier uniform_buffer_object_block any_identifier + { + $2->layout_qualifier = $1; + $$ = $2; + } + | uniform_buffer_object_block any_identifier '[' constant_expression ']' + { + $$ = $1; + } + | layout_qualifier uniform_buffer_object_block any_identifier '[' constant_expression ']' + { + $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; + } + | uniform_buffer_object_declaration_list ubo_variables_declarator_list ';' + { + $1->declarations.append_list(&($2->declarations)); + $$ = $1; + } +; + +// 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 +1272,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); diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 8f843eb..4a43291 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -42,6 +42,8 @@ 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 +198,9 @@ 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; }; typedef struct YYLTYPE { diff --git a/src/mesa/program/ir_to_mesa.cpp b/src/mesa/program/ir_to_mesa.cpp index 6820e4c..65bfc49 100644 --- a/src/mesa/program/ir_to_mesa.cpp +++ b/src/mesa/program/ir_to_mesa.cpp @@ -3370,6 +3370,11 @@ _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; + 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.3 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev