From cc22c5a5447d1d710e49524ee61b76268c7da6b9 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Fri, 18 Jun 2010 17:13:42 -0700 Subject: linker: Initial implementation of interstage uniform validation --- linker.cpp | 70 +++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 69 insertions(+), 1 deletion(-) diff --git a/linker.cpp b/linker.cpp index 0a1afcf034..a7eff556cf 100644 --- a/linker.cpp +++ b/linker.cpp @@ -170,6 +170,60 @@ validate_fragment_shader_executable(struct glsl_shader *shader) } +/** + * Perform validation of uniforms used across multiple shader stages + */ +bool +cross_validate_uniforms(struct glsl_shader **shaders, unsigned num_shaders) +{ + /* Examine all of the uniforms in all of the shaders and cross validate + * them. + */ + glsl_symbol_table uniforms; + for (unsigned i = 0; i < num_shaders; i++) { + foreach_list(node, &shaders[i]->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_uniform)) + 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 + * initializers, the values of the initializers must be the same. + */ + ir_variable *const existing = uniforms.get_variable(var->name); + if (existing != NULL) { + if (var->type != existing->type) { + printf("error: uniform `%s' declared as type `%s' and " + "type `%s'\n", + var->name, var->type->name, existing->type->name); + return false; + } + + if (var->constant_value != NULL) { + if (existing->constant_value != NULL) { + if (!var->constant_value->has_value(existing->constant_value)) { + printf("error: initializers for uniform `%s' have " + "differing values\n", + var->name); + return false; + } + } 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. + */ + existing->constant_value = var->constant_value->clone(); + } + } else + uniforms.add_variable(var->name, var); + } + } + + return true; +} + + void link_shaders(struct glsl_program *prog) { @@ -217,8 +271,22 @@ link_shaders(struct glsl_program *prog) /* FINISHME: Perform inter-stage linking. */ + glsl_shader *shader_executables[2]; + unsigned num_shader_executables; + + num_shader_executables = 0; + if (num_vert_shaders > 0) { + shader_executables[num_shader_executables] = vert_shader_list[0]; + num_shader_executables++; + } + + if (num_frag_shaders > 0) { + shader_executables[num_shader_executables] = frag_shader_list[0]; + num_shader_executables++; + } - prog->LinkStatus = true; + if (cross_validate_uniforms(shader_executables, num_shader_executables)) + prog->LinkStatus = true; done: free(vert_shader_list); -- cgit v1.2.3