[Mesa-dev] [PATCH 3/5] glsl: Linker fills ir_variable::complete_location
Vincent Lejeune
vljn at ovi.com
Tue Jan 24 13:05:12 PST 2012
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
More information about the mesa-dev
mailing list