diff options
author | Kenneth Graunke <[email protected]> | 2013-07-16 12:03:28 -0700 |
---|---|---|
committer | Kenneth Graunke <[email protected]> | 2013-07-18 16:57:23 -0700 |
commit | 5e5e12040beb40ff93797d55c913ebe6cd00c2ae (patch) | |
tree | 089c08f2de05c0a6985414dc761ad653bd86db14 /src/glsl/ast_to_hir.cpp | |
parent | 0418846a07b02d39e129987580e7ea50fb422ee0 (diff) |
glsl: Add validation for the "binding" qualifier.
The "binding" qualifier only applies to UBO blocks and samplers, along
with arrays of those types. (It would also apply to images and atomic
counters, but we don't support those yet.)
This also validates sampler bindings against the maximum number of
texture units, and UBO bindings against the number of uniform buffer
binding points.
Signed-off-by: Kenneth Graunke <[email protected]>
Reviewed-by: Paul Berry <[email protected]>
Diffstat (limited to 'src/glsl/ast_to_hir.cpp')
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 81 |
1 files changed, 81 insertions, 0 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index e8ed77a86aa..4a04b608bfb 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1850,6 +1850,84 @@ validate_matrix_layout_for_type(struct _mesa_glsl_parse_state *state, } } +static bool +validate_binding_qualifier(struct _mesa_glsl_parse_state *state, + YYLTYPE *loc, + ir_variable *var, + const ast_type_qualifier *qual) +{ + if (var->mode != ir_var_uniform) { + _mesa_glsl_error(loc, state, + "the \"binding\" qualifier only applies to uniforms.\n"); + return false; + } + + if (qual->binding < 0) { + _mesa_glsl_error(loc, state, "binding values must be >= 0.\n"); + return false; + } + + const struct gl_context *const ctx = state->ctx; + unsigned elements = var->type->is_array() ? var->type->length : 1; + unsigned max_index = qual->binding + elements - 1; + + if (var->type->is_interface()) { + /* UBOs. From page 60 of the GLSL 4.20 specification: + * "If the binding point for any uniform block instance is less than zero, + * or greater than or equal to the implementation-dependent maximum + * number of uniform buffer bindings, a compilation error will occur. + * When the binding identifier is used with a uniform block instanced as + * an array of size N, all elements of the array from binding through + * binding + N – 1 must be within this range." + * + * The implementation-dependent maximum is GL_MAX_UNIFORM_BUFFER_BINDINGS. + */ + if (max_index >= ctx->Const.MaxUniformBufferBindings) { + _mesa_glsl_error(loc, state, "layout(binding = %d) for %d UBOs exceeds " + "the maximum number of UBO binding points (%d).\n", + qual->binding, elements, + ctx->Const.MaxUniformBufferBindings); + return false; + } + } else if (var->type->is_sampler() || + (var->type->is_array() && var->type->fields.array->is_sampler())) { + /* Samplers. From page 63 of the GLSL 4.20 specification: + * "If the binding is less than zero, or greater than or equal to the + * implementation-dependent maximum supported number of units, a + * compilation error will occur. When the binding identifier is used + * with an array of size N, all elements of the array from binding + * through binding + N - 1 must be within this range." + */ + unsigned limit; + switch (state->target) { + case vertex_shader: + limit = ctx->Const.VertexProgram.MaxTextureImageUnits; + break; + case geometry_shader: + limit = ctx->Const.GeometryProgram.MaxTextureImageUnits; + break; + case fragment_shader: + limit = ctx->Const.FragmentProgram.MaxTextureImageUnits; + break; + } + + if (max_index >= limit) { + _mesa_glsl_error(loc, state, "layout(binding = %d) for %d samplers " + "exceeds the maximum number of texture image units " + "(%d).\n", qual->binding, elements, limit); + + return false; + } + } else { + _mesa_glsl_error(loc, state, + "the \"binding\" qualifier only applies to uniform " + "blocks, samplers, or arrays of samplers.\n"); + return false; + } + + return true; +} + static void apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, ir_variable *var, @@ -2080,6 +2158,9 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, "explicit index requires explicit location\n"); } + if (qual->flags.q.explicit_binding) + validate_binding_qualifier(state, loc, var, qual); + /* Does the declaration use the deprecated 'attribute' or 'varying' * keywords? */ |