diff options
-rw-r--r-- | src/glsl/link_uniforms.cpp | 95 | ||||
-rw-r--r-- | src/glsl/linker.h | 3 |
2 files changed, 98 insertions, 0 deletions
diff --git a/src/glsl/link_uniforms.cpp b/src/glsl/link_uniforms.cpp index 7fe463f104f..b9d5361b032 100644 --- a/src/glsl/link_uniforms.cpp +++ b/src/glsl/link_uniforms.cpp @@ -237,3 +237,98 @@ private: public: union gl_constant_value *values; }; + +void +link_assign_uniform_locations(struct gl_shader_program *prog) +{ + ralloc_free(prog->UniformStorage); + prog->UniformStorage = NULL; + prog->NumUserUniformStorage = 0; + + if (prog->UniformHash != NULL) { + prog->UniformHash->clear(); + } else { + prog->UniformHash = new string_to_uint_map; + } + + for (unsigned i = 0; i < Elements(prog->SamplerUnits); i++) { + prog->SamplerUnits[i] = i; + } + + /* First pass: Count the uniform resources used by the user-defined + * uniforms. While this happens, each active uniform will have an index + * assigned to it. + * + * Note: this is *NOT* the index that is returned to the application by + * glGetUniformLocation. + */ + count_uniform_size uniform_size(prog->UniformHash); + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + + foreach_list(node, prog->_LinkedShaders[i]->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_uniform)) + continue; + + /* FINISHME: Update code to process built-in uniforms! + */ + if (strncmp("gl_", var->name, 3) == 0) + continue; + + uniform_size.process(var); + } + } + + const unsigned num_user_uniforms = uniform_size.num_active_uniforms; + const unsigned num_data_slots = uniform_size.num_values; + + /* On the outside chance that there were no uniforms, bail out. + */ + if (num_user_uniforms == 0) + return; + + struct gl_uniform_storage *uniforms = + rzalloc_array(prog, struct gl_uniform_storage, num_user_uniforms); + union gl_constant_value *data = + rzalloc_array(uniforms, union gl_constant_value, num_data_slots); +#ifndef NDEBUG + union gl_constant_value *data_end = &data[num_data_slots]; +#endif + + parcel_out_uniform_storage parcel(prog->UniformHash, uniforms, data); + + for (unsigned i = 0; i < MESA_SHADER_TYPES; i++) { + if (prog->_LinkedShaders[i] == NULL) + continue; + + foreach_list(node, prog->_LinkedShaders[i]->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_uniform)) + continue; + + /* FINISHME: Update code to process built-in uniforms! + */ + if (strncmp("gl_", var->name, 3) == 0) + continue; + + parcel.process(var); + } + } + +#ifndef NDEBUG + for (unsigned i = 0; i < num_user_uniforms; i++) { + assert(uniforms[i].storage != NULL); + } +#endif + + assert(parcel.values == data_end); + + prog->NumUserUniformStorage = num_user_uniforms; + prog->UniformStorage = uniforms; + + return; +} diff --git a/src/glsl/linker.h b/src/glsl/linker.h index 669549bf0c5..433c63be246 100644 --- a/src/glsl/linker.h +++ b/src/glsl/linker.h @@ -34,6 +34,9 @@ extern void link_invalidate_variable_locations(gl_shader *sh, enum ir_variable_mode mode, int generic_base); +extern void +link_assign_uniform_locations(struct gl_shader_program *prog); + /** * Class for processing all of the leaf fields of an uniform * |