This patch modify the assign_varying_locations function so that it populates ir_variable::complete_location instead of ir_variable::location. The final layout remains unchanged though. Tfb_declaration is also updated to handles the use of the new field. --- src/glsl/builtin_variables.cpp | 2 + src/glsl/ir_set_program_inouts.cpp | 13 ++++- src/glsl/linker.cpp | 115 +++++++++++++++++++++++++++++++----- 3 files changed, 112 insertions(+), 18 deletions(-)
diff --git a/src/glsl/builtin_variables.cpp b/src/glsl/builtin_variables.cpp index ed6b922..68aa81d 100644 --- a/src/glsl/builtin_variables.cpp +++ b/src/glsl/builtin_variables.cpp @@ -408,6 +408,8 @@ add_variable(exec_list *instructions, glsl_symbol_table *symtab, var->location = slot; var->explicit_location = (slot >= 0); + var->complete_location = location_tree_create(var, var->type); + set_vanilla_location_to_variable(var->complete_location, var->type, slot); /* Once the variable is created an initialized, add it to the symbol table * and add the declaration to the IR stream. diff --git a/src/glsl/ir_set_program_inouts.cpp b/src/glsl/ir_set_program_inouts.cpp index 8c2bc30..e629705 100644 --- a/src/glsl/ir_set_program_inouts.cpp +++ b/src/glsl/ir_set_program_inouts.cpp @@ -81,12 +81,21 @@ mark(struct gl_program *prog, ir_variable *var, int offset, int len, */ for (int i = 0; i < len; i++) { - GLbitfield64 bitfield = BITFIELD64_BIT(var->location + offset + i); + unsigned location; + if (var->complete_location) { + unsigned size; + const struct register_info* tmp = get_register_info(var->complete_location,var->type,size); + location = tmp[0].index; + ralloc_free((void *)tmp); + } else { + location = var->location; + } + GLbitfield64 bitfield = BITFIELD64_BIT(location + offset + i); if (var->mode == ir_var_in) { prog->InputsRead |= bitfield; if (is_fragment_shader) { gl_fragment_program *fprog = (gl_fragment_program *) prog; - fprog->InterpQualifier[var->location + offset + i] = + fprog->InterpQualifier[location + offset + i] = (glsl_interp_qualifier) var->interpolation; } } else if (var->mode == ir_var_system_value) { diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp index 5095751..9c65f92 100644 --- a/src/glsl/linker.cpp +++ b/src/glsl/linker.cpp @@ -1459,6 +1459,7 @@ private: */ int location; + unsigned component_offset; /** * If location != -1, the number of vector elements in this variable, or 1 * if this variable is a scalar. @@ -1555,6 +1556,10 @@ tfeedback_decl::assign_location(struct gl_context *ctx, struct gl_shader_program *prog, ir_variable *output_var) { + unsigned size; + const register_info *output_regs = get_register_info(output_var->complete_location, output_var->type, size); + unsigned output_var_location = output_regs[0].index; + this->component_offset = output_regs[0].writemask_offset; if (output_var->type->is_array()) { /* Array variable */ const unsigned matrix_cols = @@ -1573,14 +1578,14 @@ tfeedback_decl::assign_location(struct gl_context *ctx, } if (this->is_clip_distance_mesa) { this->location = - output_var->location + this->array_subscript / 4; + output_var_location + this->array_subscript / 4; } else { this->location = - output_var->location + this->array_subscript * matrix_cols; + output_var_location + this->array_subscript * matrix_cols; } this->size = 1; } else { - this->location = output_var->location; + this->location = output_var_location; this->size = actual_array_size; } this->vector_elements = output_var->type->fields.array->vector_elements; @@ -1597,7 +1602,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx, this->orig_name, this->var_name); return false; } - this->location = output_var->location; + this->location = output_var_location; this->size = 1; this->vector_elements = output_var->type->vector_elements; this->matrix_columns = output_var->type->matrix_columns; @@ -1687,7 +1692,7 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog, for (unsigned v = 0; v < this->matrix_columns; ++v) { unsigned num_components = this->vector_elements; assert(info->NumOutputs < max_outputs); - info->Outputs[info->NumOutputs].ComponentOffset = 0; + info->Outputs[info->NumOutputs].ComponentOffset = this->component_offset; if (this->is_clip_distance_mesa) { if (this->is_subscripted) { num_components = 1; @@ -1811,6 +1816,29 @@ assign_varying_location(ir_variable *input_var, ir_variable *output_var, /** + * "Default" packing function, that in fact does pack any varyings. + * It affects location in order with a single field per reg. + */ +void +default_packing_function(ir_variable **produced_var, + ir_variable **consumed_var, + unsigned size, + int *first_produced_index, + int *first_consumed_index) +{ + int p_index = *first_produced_index; + int c_index = *first_consumed_index; + for (unsigned i = 0; i < size; i++) { + set_vanilla_location_to_variable(produced_var[i]->complete_location, produced_var[i]->type, p_index); + if (consumed_var) + set_vanilla_location_to_variable(consumed_var[i]->complete_location, consumed_var[i]->type, c_index); + } + *first_produced_index = p_index; + *first_consumed_index = c_index; +} + + +/** * Assign locations for all variables that are produced in one pipeline stage * (the "producer") and consumed in the next stage (the "consumer"). * @@ -1838,9 +1866,22 @@ assign_varying_locations(struct gl_context *ctx, tfeedback_decl *tfeedback_decls) { /* FINISHME: Set dynamically when geometry shader support is added. */ - unsigned output_index = VERT_RESULT_VAR0; - unsigned input_index = FRAG_ATTRIB_VAR0; - + int output_index = VERT_RESULT_VAR0; + int input_index = FRAG_ATTRIB_VAR0; + void *array_context = ralloc_context(NULL); + ir_variable **tfb_output_array = rzalloc_array(array_context, class ir_variable *, 1); + unsigned tfb_output_array_shadow_size = 1; + unsigned *tfb_index = rzalloc_array(array_context, unsigned, 1); + unsigned tfb_index_shadow_size = 1; + unsigned tfb_size = 0; + ir_variable **output_array = rzalloc_array(array_context, class ir_variable *, 1); + unsigned output_array_shadow_size = 1; + ir_variable **input_array = rzalloc_array(array_context, class ir_variable *, 1); + unsigned input_array_shadow_size = 1; + unsigned varying_size = 0; + ir_variable **not_paired_output = rzalloc_array(array_context, class ir_variable *, 1); + unsigned not_paired_output_shadow_size = 1; + unsigned not_paired_output_size = 0; /* Operate in a total of three passes. * * 1. Assign locations for any matching inputs and outputs. @@ -1869,23 +1910,65 @@ assign_varying_locations(struct gl_context *ctx, input_var = NULL; if (input_var) { - assign_varying_location(input_var, output_var, &input_index, - &output_index); + varying_size ++; + DYNAMIC_RESIZE(array_context, output_array, class ir_variable *, varying_size, output_array_shadow_size); + output_array[varying_size - 1] = output_var; + DYNAMIC_RESIZE(array_context, input_array, class ir_variable *, varying_size, input_array_shadow_size); + input_array[varying_size - 1] = input_var; + output_var->complete_location = location_tree_create(output_var, output_var->type); + input_var->complete_location = location_tree_create(input_var, input_var->type); + continue; } for (unsigned i = 0; i < num_tfeedback_decls; ++i) { if (!tfeedback_decls[i].is_assigned() && tfeedback_decls[i].matches_var(output_var)) { - if (output_var->location == -1) { - assign_varying_location(input_var, output_var, &input_index, - &output_index); - } - if (!tfeedback_decls[i].assign_location(ctx, prog, output_var)) - return false; + tfb_size ++; + DYNAMIC_RESIZE(array_context, tfb_output_array, class ir_variable *, tfb_size, tfb_output_array_shadow_size); + tfb_output_array[tfb_size - 1] = output_var; + DYNAMIC_RESIZE(array_context, tfb_index, unsigned, tfb_size, tfb_index_shadow_size); + tfb_index[tfb_size - 1] = i; + // If output has no associated input and is not a built-in varying, it needs to be affected a location, too. + if (!output_var->complete_location) { + not_paired_output_size ++; + DYNAMIC_RESIZE(array_context, not_paired_output, class ir_variable *, not_paired_output_size, not_paired_output_shadow_size); + not_paired_output[not_paired_output_size - 1] = output_var; + output_var->complete_location = location_tree_create(output_var, output_var->type); + } } } } + vec_packing_function(output_array, input_array, varying_size, &output_index, &input_index); + + // Fills ir_variable::location to tells linker this var is used + for (unsigned i = 0; i < varying_size; i++) { + unsigned idx_in; + unsigned idx_out; + assign_varying_location(input_array[i], output_array[i], &idx_in, + &idx_out); + } + + vec_packing_function(not_paired_output, NULL, not_paired_output_size, &output_index, &input_index); + + // Fills ir_variable::location to tells linker this var is used + for (unsigned i = 0; i < not_paired_output_size; i++) { + unsigned to_ditch; + assign_varying_location(NULL, not_paired_output[i], &to_ditch, + &to_ditch); + } + + // Propagate the changes to tfb + for (unsigned i = 0; i < tfb_size; i++) { + unsigned idx_ditch; + assign_varying_location(NULL, tfb_output_array[i], &idx_ditch, + &idx_ditch); + if (!tfeedback_decls[tfb_index[i]].assign_location(ctx, prog, tfb_output_array[i])) + return false; + } + + ralloc_free(array_context); + unsigned varying_vectors = 0; if (consumer) { -- 1.7.7 _______________________________________________ mesa-dev mailing list mesa-dev@lists.freedesktop.org http://lists.freedesktop.org/mailman/listinfo/mesa-dev