summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorKenneth Graunke <kenneth@whitecape.org>2013-07-16 12:03:28 -0700
committerKenneth Graunke <kenneth@whitecape.org>2013-07-18 16:57:23 -0700
commit5e5e12040beb40ff93797d55c913ebe6cd00c2ae (patch)
tree089c08f2de05c0a6985414dc761ad653bd86db14
parent0418846a07b02d39e129987580e7ea50fb422ee0 (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 <kenneth@whitecape.org> Reviewed-by: Paul Berry <stereotype441@gmail.com>
-rw-r--r--src/glsl/ast_to_hir.cpp81
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?
*/