summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/linker.cpp93
1 files changed, 56 insertions, 37 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index 55d23d1c342..1ae8fad22d0 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1601,6 +1601,17 @@ private:
int location;
/**
+ * If non-zero, then this variable may be packed along with other variables
+ * into a single varying slot, so this offset should be applied when
+ * accessing components. For example, an offset of 1 means that the x
+ * component of this variable is actually stored in component y of the
+ * location specified by \c location.
+ *
+ * Only valid if location != -1.
+ */
+ unsigned location_frac;
+
+ /**
* If location != -1, the number of vector elements in this variable, or 1
* if this variable is a scalar.
*/
@@ -1739,6 +1750,8 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
/* Array variable */
const unsigned matrix_cols =
output_var->type->fields.array->matrix_columns;
+ const unsigned vector_elements =
+ output_var->type->fields.array->vector_elements;
unsigned actual_array_size = this->is_clip_distance_mesa ?
prog->Vert.ClipDistanceArraySize : output_var->type->array_size();
@@ -1754,16 +1767,22 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
if (this->is_clip_distance_mesa) {
this->location =
output_var->location + this->array_subscript / 4;
+ this->location_frac = this->array_subscript % 4;
} else {
- this->location =
- output_var->location + this->array_subscript * matrix_cols;
+ unsigned fine_location
+ = output_var->location * 4 + output_var->location_frac;
+ unsigned array_elem_size = vector_elements * matrix_cols;
+ fine_location += array_elem_size * this->array_subscript;
+ this->location = fine_location / 4;
+ this->location_frac = fine_location % 4;
}
this->size = 1;
} else {
this->location = output_var->location;
+ this->location_frac = output_var->location_frac;
this->size = actual_array_size;
}
- this->vector_elements = output_var->type->fields.array->vector_elements;
+ this->vector_elements = vector_elements;
this->matrix_columns = matrix_cols;
if (this->is_clip_distance_mesa)
this->type = GL_FLOAT;
@@ -1778,6 +1797,7 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
return false;
}
this->location = output_var->location;
+ this->location_frac = output_var->location_frac;
this->size = 1;
this->vector_elements = output_var->type->vector_elements;
this->matrix_columns = output_var->type->matrix_columns;
@@ -1812,11 +1832,7 @@ tfeedback_decl::get_num_outputs() const
return 0;
}
- unsigned translated_size = this->size;
- if (this->is_clip_distance_mesa)
- translated_size = (translated_size + 3) / 4;
-
- return translated_size * this->matrix_columns;
+ return (this->num_components() + this->location_frac + 3)/4;
}
@@ -1854,35 +1870,23 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
return false;
}
- unsigned translated_size = this->size;
- if (this->is_clip_distance_mesa)
- translated_size = (translated_size + 3) / 4;
- unsigned components_so_far = 0;
- for (unsigned index = 0; index < translated_size; ++index) {
- 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;
- if (this->is_clip_distance_mesa) {
- if (this->is_subscripted) {
- num_components = 1;
- info->Outputs[info->NumOutputs].ComponentOffset =
- this->array_subscript % 4;
- } else {
- num_components = MIN2(4, this->size - components_so_far);
- }
- }
- info->Outputs[info->NumOutputs].OutputRegister =
- this->location + v + index * this->matrix_columns;
- info->Outputs[info->NumOutputs].NumComponents = num_components;
- info->Outputs[info->NumOutputs].OutputBuffer = buffer;
- info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
- ++info->NumOutputs;
- info->BufferStride[buffer] += num_components;
- components_so_far += num_components;
- }
+ unsigned location = this->location;
+ unsigned location_frac = this->location_frac;
+ unsigned num_components = this->num_components();
+ while (num_components > 0) {
+ unsigned output_size = MIN2(num_components, 4 - location_frac);
+ assert(info->NumOutputs < max_outputs);
+ info->Outputs[info->NumOutputs].ComponentOffset = location_frac;
+ info->Outputs[info->NumOutputs].OutputRegister = location;
+ info->Outputs[info->NumOutputs].NumComponents = output_size;
+ info->Outputs[info->NumOutputs].OutputBuffer = buffer;
+ info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
+ ++info->NumOutputs;
+ info->BufferStride[buffer] += output_size;
+ num_components -= output_size;
+ location++;
+ location_frac = 0;
}
- assert(components_so_far == this->num_components());
info->Varyings[info->NumVarying].Name = ralloc_strdup(prog, this->orig_name);
info->Varyings[info->NumVarying].Type = this->type;
@@ -2330,7 +2334,7 @@ assign_varying_locations(struct gl_context *ctx,
}
}
- matches.assign_locations();
+ const unsigned slots_used = matches.assign_locations();
matches.store_locations(producer_base, consumer_base);
for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
@@ -2344,6 +2348,21 @@ assign_varying_locations(struct gl_context *ctx,
return false;
}
+ if (ctx->Const.DisableVaryingPacking) {
+ /* Transform feedback code assumes varyings are packed, so if the driver
+ * has disabled varying packing, make sure it does not support transform
+ * feedback.
+ */
+ assert(!ctx->Extensions.EXT_transform_feedback);
+ } else {
+ lower_packed_varyings(ctx, producer_base, slots_used, ir_var_out,
+ producer);
+ if (consumer) {
+ lower_packed_varyings(ctx, consumer_base, slots_used, ir_var_in,
+ consumer);
+ }
+ }
+
unsigned varying_vectors = 0;
if (consumer) {