diff options
author | Ian Romanick <[email protected]> | 2010-06-23 11:23:01 -0700 |
---|---|---|
committer | Ian Romanick <[email protected]> | 2010-06-23 11:24:26 -0700 |
commit | 0e59b2698a7609183221e1266c1209611040609a (patch) | |
tree | 4d2aceefe87d9ce112029c5177306c4d6b88cbfb /linker.cpp | |
parent | 9342d269a4818bf18296b07baa98f577efd1735c (diff) |
linker: Initial implementation of varying slot allocation
Diffstat (limited to 'linker.cpp')
-rw-r--r-- | linker.cpp | 79 |
1 files changed, 76 insertions, 3 deletions
diff --git a/linker.cpp b/linker.cpp index 76c3e9de8aa..500a329e7d6 100644 --- a/linker.cpp +++ b/linker.cpp @@ -662,6 +662,79 @@ assign_attribute_locations(glsl_shader *sh, void +assign_varying_locations(glsl_shader *producer, glsl_shader *consumer) +{ + /* FINISHME: Set dynamically when geometry shader support is added. */ + unsigned output_index = VERT_RESULT_VAR0; + unsigned input_index = FRAG_ATTRIB_VAR0; + + /* Operate in a total of three passes. + * + * 1. Assign locations for any matching inputs and outputs. + * + * 2. Mark output variables in the producer that do not have locations as + * not being outputs. This lets the optimizer eliminate them. + * + * 3. Mark input variables in the consumer that do not have locations as + * not being inputs. This lets the optimizer eliminate them. + */ + + invalidate_variable_locations(producer, ir_var_out, VERT_RESULT_VAR0); + invalidate_variable_locations(consumer, ir_var_in, FRAG_ATTRIB_VAR0); + + foreach_list(node, &producer->ir) { + ir_variable *const output_var = ((ir_instruction *) node)->as_variable(); + + if ((output_var == NULL) || (output_var->mode != ir_var_out) + || (output_var->location != -1)) + continue; + + ir_variable *const input_var = + consumer->symbols->get_variable(output_var->name); + + if ((input_var == NULL) || (input_var->mode != ir_var_in)) + continue; + + assert(input_var->location == -1); + + /* FINISHME: Location assignment will need some changes when arrays, + * FINISHME: matrices, and structures are allowed as shader inputs / + * FINISHME: outputs. + */ + output_var->location = output_index; + input_var->location = input_index; + + output_index++; + input_index++; + } + + foreach_list(node, &producer->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_out)) + continue; + + /* An 'out' variable is only really a shader output if its value is read + * by the following stage. + */ + var->shader_out = (var->location != -1); + } + + foreach_list(node, &consumer->ir) { + ir_variable *const var = ((ir_instruction *) node)->as_variable(); + + if ((var == NULL) || (var->mode != ir_var_in)) + continue; + + /* An 'in' variable is only really a shader input if its value is written + * by the previous stage. + */ + var->shader_in = (var->location != -1); + } +} + + +void link_shaders(struct glsl_program *prog) { prog->LinkStatus = false; @@ -750,9 +823,9 @@ link_shaders(struct glsl_program *prog) 16)) goto done; - /* FINISHME: Assign vertex shader output / fragment shader input - * FINISHME: locations. - */ + for (unsigned i = 1; i < prog->_NumLinkedShaders; i++) + assign_varying_locations(prog->_LinkedShaders[i - 1], + prog->_LinkedShaders[i]); /* FINISHME: Assign fragment shader output locations. */ |