diff options
Diffstat (limited to 'mesalib/src/glsl')
-rw-r--r-- | mesalib/src/glsl/ast.h | 23 | ||||
-rw-r--r-- | mesalib/src/glsl/ast_type.cpp | 45 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser.yy | 65 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.cpp | 18 | ||||
-rw-r--r-- | mesalib/src/glsl/glsl_parser_extras.h | 24 | ||||
-rw-r--r-- | mesalib/src/glsl/link_uniforms.cpp | 19 | ||||
-rw-r--r-- | mesalib/src/glsl/linker.cpp | 34 |
7 files changed, 169 insertions, 59 deletions
diff --git a/mesalib/src/glsl/ast.h b/mesalib/src/glsl/ast.h index 3c0a2b838..bba2481a0 100644 --- a/mesalib/src/glsl/ast.h +++ b/mesalib/src/glsl/ast.h @@ -342,6 +342,25 @@ enum { }; struct ast_type_qualifier { + /* Callers of this ralloc-based new need not call delete. It's + * easier to just ralloc_free 'ctx' (or any of its ancestors). */ + static void* operator new(size_t size, void *ctx) + { + void *node; + + node = rzalloc_size(ctx, size); + assert(node != NULL); + + return node; + } + + /* If the user *does* call delete, that's OK, we will just + * ralloc_free in that case. */ + static void operator delete(void *table) + { + ralloc_free(table); + } + union { struct { unsigned invariant:1; @@ -428,6 +447,10 @@ struct ast_type_qualifier { * returned string is undefined but not null. */ const char *interpolation_string() const; + + bool merge_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q); }; class ast_declarator_list; diff --git a/mesalib/src/glsl/ast_type.cpp b/mesalib/src/glsl/ast_type.cpp index 6c44f8c41..29493e2f6 100644 --- a/mesalib/src/glsl/ast_type.cpp +++ b/mesalib/src/glsl/ast_type.cpp @@ -71,3 +71,48 @@ ast_type_qualifier::interpolation_string() const else return NULL; } + +bool +ast_type_qualifier::merge_qualifier(YYLTYPE *loc, + _mesa_glsl_parse_state *state, + ast_type_qualifier q) +{ + ast_type_qualifier ubo_mat_mask; + ubo_mat_mask.flags.i = 0; + ubo_mat_mask.flags.q.row_major = 1; + ubo_mat_mask.flags.q.column_major = 1; + + ast_type_qualifier ubo_layout_mask; + ubo_layout_mask.flags.i = 0; + ubo_layout_mask.flags.q.std140 = 1; + ubo_layout_mask.flags.q.packed = 1; + ubo_layout_mask.flags.q.shared = 1; + + /* Uniform block layout qualifiers get to overwrite each + * other (rightmost having priority), while all other + * qualifiers currently don't allow duplicates. + */ + + if ((this->flags.i & q.flags.i & ~(ubo_mat_mask.flags.i | + ubo_layout_mask.flags.i)) != 0) { + _mesa_glsl_error(loc, state, + "duplicate layout qualifiers used\n"); + return false; + } + + if ((q.flags.i & ubo_mat_mask.flags.i) != 0) + this->flags.i &= ~ubo_mat_mask.flags.i; + if ((q.flags.i & ubo_layout_mask.flags.i) != 0) + this->flags.i &= ~ubo_layout_mask.flags.i; + + this->flags.i |= q.flags.i; + + if (q.flags.q.explicit_location) + this->location = q.location; + + if (q.flags.q.explicit_index) + this->index = q.index; + + return true; +} + diff --git a/mesalib/src/glsl/glsl_parser.yy b/mesalib/src/glsl/glsl_parser.yy index f61d6b8dd..04c64f096 100644 --- a/mesalib/src/glsl/glsl_parser.yy +++ b/mesalib/src/glsl/glsl_parser.yy @@ -29,6 +29,7 @@ #include "ast.h" #include "glsl_parser_extras.h" #include "glsl_types.h" +#include "main/context.h" #define YYLEX_PARAM state->scanner @@ -259,19 +260,25 @@ version_statement: switch ($2) { case 100: state->es_shader = true; - supported = state->Const.GLSL_100ES; + supported = state->ctx->API == API_OPENGLES2 || + state->ctx->Extensions.ARB_ES2_compatibility; break; case 110: - supported = state->Const.GLSL_110; - break; case 120: - supported = state->Const.GLSL_120; - break; + /* FINISHME: Once the OpenGL 3.0 'forward compatible' context or + * the OpenGL 3.2 Core context is supported, this logic will need + * change. Older versions of GLSL are no longer supported + * outside the compatibility contexts of 3.x. + */ case 130: - supported = state->Const.GLSL_130; - break; case 140: - supported = state->Const.GLSL_140; + case 150: + case 330: + case 400: + case 410: + case 420: + supported = _mesa_is_desktop_gl(state->ctx) && + ((unsigned) $2) <= state->ctx->Const.GLSLVersion; break; default: supported = false; @@ -291,6 +298,10 @@ version_statement: state->version_string, state->supported_version_string); } + + if (state->language_version >= 140) { + state->ARB_uniform_buffer_object_enable = true; + } } ; @@ -301,7 +312,7 @@ pragma_statement: | PRAGMA_OPTIMIZE_OFF EOL | PRAGMA_INVARIANT_ALL EOL { - if (state->language_version < 120 && !state->Const.GLSL_100ES) { + if (state->language_version == 110) { _mesa_glsl_warning(& @1, state, "pragma `invariant(all)' not supported in %s", state->version_string); @@ -1102,20 +1113,10 @@ layout_qualifier_id_list: layout_qualifier_id | layout_qualifier_id_list ',' layout_qualifier_id { - if (($1.flags.i & $3.flags.i) != 0) { - _mesa_glsl_error(& @3, state, - "duplicate layout qualifiers used\n"); + $$ = $1; + if (!$$.merge_qualifier(& @3, state, $3)) { YYERROR; } - - $$ = $1; - $$.flags.i |= $3.flags.i; - - if ($3.flags.q.explicit_location) - $$.location = $3.location; - - if ($3.flags.q.explicit_index) - $$.index = $3.index; } ; @@ -1905,6 +1906,7 @@ external_declaration: function_definition { $$ = $1; } | declaration { $$ = $1; } | pragma_statement { $$ = NULL; } + | layout_defaults { $$ = NULL; } ; function_definition: @@ -1925,14 +1927,18 @@ uniform_block: UNIFORM NEW_IDENTIFIER '{' member_list '}' ';' { void *ctx = state; - ast_type_qualifier no_qual; - memset(&no_qual, 0, sizeof(no_qual)); - $$ = new(ctx) ast_uniform_block(no_qual, $2, $4); + $$ = new(ctx) ast_uniform_block(*state->default_uniform_qualifier, + $2, $4); } | layout_qualifier UNIFORM NEW_IDENTIFIER '{' member_list '}' ';' { void *ctx = state; - $$ = new(ctx) ast_uniform_block($1, $3, $5); + + ast_type_qualifier qual = *state->default_uniform_qualifier; + if (!qual.merge_qualifier(& @1, state, $1)) { + YYERROR; + } + $$ = new(ctx) ast_uniform_block(qual, $3, $5); } ; @@ -1986,3 +1992,12 @@ member_declaration: $$->declarations.push_degenerate_list_at_head(& $3->link); } ; + +layout_defaults: + layout_qualifier UNIFORM ';' + { + if (!state->default_uniform_qualifier->merge_qualifier(& @1, state, + $1)) { + YYERROR; + } + } diff --git a/mesalib/src/glsl/glsl_parser_extras.cpp b/mesalib/src/glsl/glsl_parser_extras.cpp index 7a9b22197..09e1e590d 100644 --- a/mesalib/src/glsl/glsl_parser_extras.cpp +++ b/mesalib/src/glsl/glsl_parser_extras.cpp @@ -85,23 +85,11 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, this->Const.MaxDrawBuffers = ctx->Const.MaxDrawBuffers; - /* Note: Once the OpenGL 3.0 'forward compatible' context or the OpenGL 3.2 - * Core context is supported, this logic will need change. Older versions of - * GLSL are no longer supported outside the compatibility contexts of 3.x. - */ - this->Const.GLSL_100ES = (ctx->API == API_OPENGLES2) - || ctx->Extensions.ARB_ES2_compatibility; - bool is_desktop_gl = _mesa_is_desktop_gl(ctx); - this->Const.GLSL_110 = is_desktop_gl; - this->Const.GLSL_120 = is_desktop_gl && (ctx->Const.GLSLVersion >= 120); - this->Const.GLSL_130 = is_desktop_gl && (ctx->Const.GLSLVersion >= 130); - this->Const.GLSL_140 = is_desktop_gl && (ctx->Const.GLSLVersion >= 140); - const unsigned lowest_version = (ctx->API == API_OPENGLES2) || ctx->Extensions.ARB_ES2_compatibility ? 100 : 110; const unsigned highest_version = - is_desktop_gl ? ctx->Const.GLSLVersion : 100; + _mesa_is_desktop_gl(ctx) ? ctx->Const.GLSLVersion : 100; char *supported = ralloc_strdup(this, ""); for (unsigned ver = lowest_version; ver <= highest_version; ver += 10) { @@ -119,6 +107,10 @@ _mesa_glsl_parse_state::_mesa_glsl_parse_state(struct gl_context *_ctx, if (ctx->Const.ForceGLSLExtensionsWarn) _mesa_glsl_process_extension("all", NULL, "warn", NULL, this); + + this->default_uniform_qualifier = new(this) ast_type_qualifier(); + this->default_uniform_qualifier->flags.q.shared = 1; + this->default_uniform_qualifier->flags.q.column_major = 1; } const char * diff --git a/mesalib/src/glsl/glsl_parser_extras.h b/mesalib/src/glsl/glsl_parser_extras.h index cf6dfbe3b..5fc243ffe 100644 --- a/mesalib/src/glsl/glsl_parser_extras.h +++ b/mesalib/src/glsl/glsl_parser_extras.h @@ -96,6 +96,13 @@ struct _mesa_glsl_parse_state { enum _mesa_glsl_parser_targets target; /** + * Default uniform layout qualifiers tracked during parsing. + * Currently affects uniform blocks and uniform buffer variables in + * those blocks. + */ + class ast_type_qualifier *default_uniform_qualifier; + + /** * Printable list of GLSL versions supported by the current context * * \note @@ -126,23 +133,6 @@ struct _mesa_glsl_parse_state { /* ARB_draw_buffers */ unsigned MaxDrawBuffers; - - /** - * Set of GLSL versions supported by the current context - * - * Knowing that version X is supported doesn't mean that versions before - * X are also supported. Version 1.00 is only supported in an ES2 - * context or when GL_ARB_ES2_compatibility is supported. In an OpenGL - * 3.0 "forward compatible" context, GLSL 1.10 and 1.20 are \b not - * supported. - */ - /*@{*/ - unsigned GLSL_100ES:1; - unsigned GLSL_110:1; - unsigned GLSL_120:1; - unsigned GLSL_130:1; - unsigned GLSL_140:1; - /*@}*/ } Const; /** diff --git a/mesalib/src/glsl/link_uniforms.cpp b/mesalib/src/glsl/link_uniforms.cpp index 307f5de09..7c3d74b82 100644 --- a/mesalib/src/glsl/link_uniforms.cpp +++ b/mesalib/src/glsl/link_uniforms.cpp @@ -328,10 +328,21 @@ private: this->uniforms[id].offset = this->ubo_byte_offset; this->ubo_byte_offset += type->std140_size(ubo_var->RowMajor); - this->uniforms[id].array_stride = 0; - this->uniforms[id].matrix_stride = 0; - this->uniforms[id].row_major = base_type->is_matrix() && - ubo_var->RowMajor; + if (type->is_array()) { + this->uniforms[id].array_stride = + align(type->fields.array->std140_size(ubo_var->RowMajor), 16); + } else { + this->uniforms[id].array_stride = 0; + } + + if (type->is_matrix() || + (type->is_array() && type->fields.array->is_matrix())) { + this->uniforms[id].matrix_stride = 16; + this->uniforms[id].row_major = ubo_var->RowMajor; + } else { + this->uniforms[id].matrix_stride = 0; + this->uniforms[id].row_major = false; + } } else { this->uniforms[id].block_index = -1; this->uniforms[id].offset = -1; diff --git a/mesalib/src/glsl/linker.cpp b/mesalib/src/glsl/linker.cpp index bfdde4023..34ce13372 100644 --- a/mesalib/src/glsl/linker.cpp +++ b/mesalib/src/glsl/linker.cpp @@ -2324,6 +2324,12 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) 0 /* FINISHME: Geometry shaders. */ }; + const unsigned max_uniform_blocks[MESA_SHADER_TYPES] = { + ctx->Const.VertexProgram.MaxUniformBlocks, + ctx->Const.FragmentProgram.MaxUniformBlocks, + ctx->Const.GeometryProgram.MaxUniformBlocks, + }; + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { struct gl_shader *sh = prog->_LinkedShaders[i]; @@ -2348,6 +2354,34 @@ check_resources(struct gl_context *ctx, struct gl_shader_program *prog) } } + unsigned blocks[MESA_SHADER_TYPES] = {0}; + unsigned total_uniform_blocks = 0; + + for (unsigned i = 0; i < prog->NumUniformBlocks; i++) { + for (unsigned j = 0; j < MESA_SHADER_TYPES; j++) { + if (prog->UniformBlockStageIndex[j][i] != -1) { + blocks[j]++; + total_uniform_blocks++; + } + } + + if (total_uniform_blocks > ctx->Const.MaxCombinedUniformBlocks) { + linker_error(prog, "Too many combined uniform blocks (%d/%d)", + prog->NumUniformBlocks, + ctx->Const.MaxCombinedUniformBlocks); + } else { + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + if (blocks[i] > max_uniform_blocks[i]) { + linker_error(prog, "Too many %s uniform blocks (%d/%d)", + shader_names[i], + blocks[i], + max_uniform_blocks[i]); + break; + } + } + } + } + return prog->LinkStatus; } |