[Mesa-dev] [PATCH 6/9] glsl: parser now aware of UBO

vlj vljn at ovi.com
Fri Sep 23 06:53:11 PDT 2011


---
 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



More information about the mesa-dev mailing list