From 019a59b2642f403203d8bc8ea980efeeffcd6462 Mon Sep 17 00:00:00 2001 From: Ian Romanick Date: Mon, 21 Jun 2010 16:10:42 -0700 Subject: [PATCH] linker: Initial implementation of uniform slot allocation --- linker.cpp | 100 ++++++++++++++++++++++++++++++++++++++++++++++++++++- 1 file changed, 99 insertions(+), 1 deletion(-) diff --git a/linker.cpp b/linker.cpp index dadc0d92a05..0c07b6d35f5 100644 --- a/linker.cpp +++ b/linker.cpp @@ -69,7 +69,9 @@ #include "glsl_symbol_table.h" #include "glsl_parser_extras.h" #include "ir.h" +#include "ir_optimization.h" #include "program.h" +#include "hash_table.h" /** * Visitor that determines whether or not a variable is ever written. @@ -318,6 +320,101 @@ cross_validate_outputs_to_inputs(glsl_shader *producer, glsl_shader *consumer) } +struct uniform_node { + exec_node link; + struct gl_uniform *u; + unsigned slots; +}; + +struct gl_uniform_list * +assign_uniform_locations(struct glsl_shader **shaders, unsigned num_shaders) +{ + /* */ + exec_list uniforms; + unsigned total_uniforms = 0; + hash_table *ht = hash_table_ctor(32, hash_table_string_hash, + hash_table_string_compare); + + for (unsigned i = 0; i < num_shaders; i++) { + unsigned next_position = 0; + + foreach_list(node, &shaders[i]->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_uniform)) + continue; + + const unsigned vec4_slots = (var->component_slots() + 3) / 4; + assert(vec4_slots != 0); + + uniform_node *n = (uniform_node *) hash_table_find(ht, var->name); + if (n == NULL) { + n = (uniform_node *) calloc(1, sizeof(struct uniform_node)); + n->u = (gl_uniform *) calloc(vec4_slots, sizeof(struct gl_uniform)); + n->slots = vec4_slots; + + n->u[0].Name = strdup(var->name); + for (unsigned j = 1; j < vec4_slots; j++) + n->u[j].Name = n->u[0].Name; + + hash_table_insert(ht, n, n->u[0].Name); + uniforms.push_tail(& n->link); + total_uniforms += vec4_slots; + } + + if (var->constant_value != NULL) + for (unsigned j = 0; j < vec4_slots; j++) + n->u[j].Initialized = true; + + var->location = next_position; + + for (unsigned j = 0; j < vec4_slots; j++) { + switch (shaders[i]->Type) { + case GL_VERTEX_SHADER: + n->u[j].VertPos = next_position; + break; + case GL_FRAGMENT_SHADER: + n->u[j].FragPos = next_position; + break; + case GL_GEOMETRY_SHADER: + /* FINISHME: Support geometry shaders. */ + assert(shaders[i]->Type != GL_GEOMETRY_SHADER); + break; + } + + next_position++; + } + } + } + + gl_uniform_list *ul = (gl_uniform_list *) + calloc(1, sizeof(gl_uniform_list)); + + ul->Size = total_uniforms; + ul->NumUniforms = total_uniforms; + ul->Uniforms = (gl_uniform *) calloc(total_uniforms, sizeof(gl_uniform)); + + unsigned idx = 0; + uniform_node *next; + for (uniform_node *node = (uniform_node *) uniforms.head + ; node->link.next != NULL + ; node = next) { + next = (uniform_node *) node->link.next; + + node->link.remove(); + memcpy(&ul->Uniforms[idx], node->u, sizeof(gl_uniform) * node->slots); + idx += node->slots; + + free(node->u); + free(node); + } + + hash_table_dtor(ht); + + return ul; +} + + void link_shaders(struct glsl_program *prog) { @@ -394,7 +491,8 @@ link_shaders(struct glsl_program *prog) /* FINISHME: Perform whole-program optimization here. */ - /* FINISHME: Assign uniform locations. */ + prog->Uniforms = assign_uniform_locations(shader_executables, + num_shader_executables); /* FINISHME: Assign vertex shader input locations. */ -- 2.30.2