summaryrefslogtreecommitdiffstats
path: root/src/glsl/linker.cpp
diff options
context:
space:
mode:
authorIan Romanick <[email protected]>2011-10-31 14:31:07 -0700
committerIan Romanick <[email protected]>2011-11-03 13:36:00 -0700
commitf37b1ad937dd2c420f4c9fd9aa5887942bd31f3f (patch)
tree0c38d85df0163c05fdb6a36f72be914aa5c32a47 /src/glsl/linker.cpp
parentd3b39194dc60fa933f5e8df30bcd8d1cb64dbc4c (diff)
linker: Check that initializers for global variables match
This requires tracking a couple extra fields in ir_variable: * A flag to indicate that a variable had an initializer. * For non-const variables, a field to track the constant value of the variable's initializer. For variables non-constant initalizers, ir_variable::has_initializer will be true, but ir_variable::constant_initializer will be NULL. The linker can use the values of these fields to check adherence to the GLSL 4.20 rules for shared global variables: "If a shared global has multiple initializers, the initializers must all be constant expressions, and they must all have the same value. Otherwise, a link error will result. (A shared global having only one initializer does not require that initializer to be a constant expression.)" Previous to 4.20 the GLSL spec simply said that initializers must have the same value. In this case of non-constant initializers, this was impossible to determine. As a result, no vendor actually implemented that behavior. The 4.20 behavior matches the behavior of NVIDIA's shipping implementations. NOTE: This is candidate for the 7.11 branch. This patch also needs the preceding patch "glsl: Refactor generate_ARB_draw_buffers_variables to use add_builtin_constant" Signed-off-by: Ian Romanick <[email protected]> Bugzilla: https://bugs.freedesktop.org/show_bug.cgi?id=34687 Reviewed-by: Kenneth Graunke <[email protected]> Acked-by: Paul Berry <[email protected]>
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r--src/glsl/linker.cpp48
1 files changed, 41 insertions, 7 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index a595c9c5f7a..915d5bbcf7d 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -448,17 +448,30 @@ cross_validate_globals(struct gl_shader_program *prog,
}
}
- /* FINISHME: Handle non-constant initializers.
+ /* Page 35 (page 41 of the PDF) of the GLSL 4.20 spec says:
+ *
+ * "If a shared global has multiple initializers, the
+ * initializers must all be constant expressions, and they
+ * must all have the same value. Otherwise, a link error will
+ * result. (A shared global having only one initializer does
+ * not require that initializer to be a constant expression.)"
+ *
+ * Previous to 4.20 the GLSL spec simply said that initializers
+ * must have the same value. In this case of non-constant
+ * initializers, this was impossible to determine. As a result,
+ * no vendor actually implemented that behavior. The 4.20
+ * behavior matches the implemented behavior of at least one other
+ * vendor, so we'll implement that for all GLSL versions.
*/
- if (var->constant_value != NULL) {
- if (existing->constant_value != NULL) {
- if (!var->constant_value->has_value(existing->constant_value)) {
+ if (var->constant_initializer != NULL) {
+ if (existing->constant_initializer != NULL) {
+ if (!var->constant_initializer->has_value(existing->constant_initializer)) {
linker_error(prog, "initializers for %s "
"`%s' have differing values\n",
mode_string(var), var->name);
return false;
}
- } else
+ } else {
/* If the first-seen instance of a particular uniform did not
* have an initializer but a later instance does, copy the
* initializer to the version stored in the symbol table.
@@ -471,8 +484,29 @@ cross_validate_globals(struct gl_shader_program *prog,
* FINISHME: modify the shader, and linking with the second
* FINISHME: will fail.
*/
- existing->constant_value =
- var->constant_value->clone(ralloc_parent(existing), NULL);
+ existing->constant_initializer =
+ var->constant_initializer->clone(ralloc_parent(existing),
+ NULL);
+ }
+ }
+
+ if (var->has_initializer) {
+ if (existing->has_initializer
+ && (var->constant_initializer == NULL
+ || existing->constant_initializer == NULL)) {
+ linker_error(prog,
+ "shared global variable `%s' has multiple "
+ "non-constant initializers.\n",
+ var->name);
+ return false;
+ }
+
+ /* Some instance had an initializer, so keep track of that. In
+ * this location, all sorts of initializers (constant or
+ * otherwise) will propagate the existence to the variable
+ * stored in the symbol table.
+ */
+ existing->has_initializer = true;
}
if (existing->invariant != var->invariant) {