[Mesa-dev] [PATCH 6/9] glsl: parser now aware of UBO
vlj
vljn at ovi.com
Sun Oct 16 15:37:19 PDT 2011
---
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
More information about the mesa-dev
mailing list