summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorIan Romanick <ian.d.romanick@intel.com>2010-06-29 18:47:11 -0700
committerIan Romanick <ian.d.romanick@intel.com>2010-07-12 18:51:55 -0700
commite2e5d0def490ed03970efa0a7468fef0623ae617 (patch)
tree1d193252d212acbae6954e39bdc451f9751b402d
parentd74c9ff046c9cf8ee33c202eb5eba3dfc7f8e06e (diff)
linker: Refactor cross_validate_uniforms into cross_validate_globals
The later, more generic function will be used in the intra-stage linker.
-rw-r--r--src/glsl/linker.cpp67
1 files changed, 54 insertions, 13 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index e70fa31a2b..04b4efd84b 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -242,42 +242,72 @@ validate_fragment_shader_executable(struct gl_shader_program *prog,
/**
- * Perform validation of uniforms used across multiple shader stages
+ * Generate a string describing the mode of a variable
+ */
+static const char *
+mode_string(const ir_variable *var)
+{
+ switch (var->mode) {
+ case ir_var_auto:
+ return (var->read_only) ? "global constant" : "global variable";
+
+ case ir_var_uniform: return "uniform";
+ case ir_var_in: return "shader input";
+ case ir_var_out: return "shader output";
+ case ir_var_inout: return "shader inout";
+ default:
+ assert(!"Should not get here.");
+ return "invalid variable";
+ }
+}
+
+
+/**
+ * Perform validation of global variables used across multiple shaders
*/
bool
-cross_validate_uniforms(struct gl_shader_program *prog)
+cross_validate_globals(struct gl_shader_program *prog,
+ struct gl_shader **shader_list,
+ unsigned num_shaders,
+ bool uniforms_only)
{
/* Examine all of the uniforms in all of the shaders and cross validate
* them.
*/
- glsl_symbol_table uniforms;
- for (unsigned i = 0; i < prog->_NumLinkedShaders; i++) {
- foreach_list(node, prog->_LinkedShaders[i]->ir) {
+ glsl_symbol_table variables;
+ for (unsigned i = 0; i < num_shaders; i++) {
+ foreach_list(node, shader_list[i]->ir) {
ir_variable *const var = ((ir_instruction *) node)->as_variable();
- if ((var == NULL) || (var->mode != ir_var_uniform))
+ if (var == NULL)
continue;
- /* If a uniform with this name has already been seen, verify that the
- * new instance has the same type. In addition, if the uniforms have
+ if (uniforms_only && (var->mode != ir_var_uniform))
+ continue;
+
+ /* If a global with this name has already been seen, verify that the
+ * new instance has the same type. In addition, if the globals have
* initializers, the values of the initializers must be the same.
*/
- ir_variable *const existing = uniforms.get_variable(var->name);
+ ir_variable *const existing = variables.get_variable(var->name);
if (existing != NULL) {
if (var->type != existing->type) {
- linker_error_printf(prog, "uniform `%s' declared as type "
+ linker_error_printf(prog, "%s `%s' declared as type "
"`%s' and type `%s'\n",
+ mode_string(var),
var->name, var->type->name,
existing->type->name);
return false;
}
+ /* FINISHME: Handle non-constant initializers.
+ */
if (var->constant_value != NULL) {
if (existing->constant_value != NULL) {
if (!var->constant_value->has_value(existing->constant_value)) {
- linker_error_printf(prog, "initializers for uniform "
+ linker_error_printf(prog, "initializers for %s "
"`%s' have differing values\n",
- var->name);
+ mode_string(var), var->name);
return false;
}
} else
@@ -289,7 +319,7 @@ cross_validate_uniforms(struct gl_shader_program *prog)
(ir_constant *)var->constant_value->clone(NULL);
}
} else
- uniforms.add_variable(var->name, var);
+ variables.add_variable(var->name, var);
}
}
@@ -298,6 +328,17 @@ cross_validate_uniforms(struct gl_shader_program *prog)
/**
+ * Perform validation of uniforms used across multiple shader stages
+ */
+bool
+cross_validate_uniforms(struct gl_shader_program *prog)
+{
+ return cross_validate_globals(prog, prog->_LinkedShaders,
+ prog->_NumLinkedShaders, true);
+}
+
+
+/**
* Validate that outputs from one stage match inputs of another
*/
bool