summaryrefslogtreecommitdiffstats
path: root/src/glsl/linker.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/glsl/linker.cpp')
-rw-r--r--src/glsl/linker.cpp99
1 files changed, 54 insertions, 45 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index c778d9a4467..88c81c41b06 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1426,12 +1426,12 @@ private:
/**
* True if the declaration in orig_name represents an array.
*/
- bool is_array;
+ bool is_subscripted;
/**
- * If is_array is true, the array index that was specified in orig_name.
+ * If is_subscripted is true, the subscript that was specified in orig_name.
*/
- unsigned array_index;
+ unsigned array_subscript;
/**
* Which component to extract from the vertex shader output location that
@@ -1460,6 +1460,12 @@ private:
/** Type of the varying returned by glGetTransformFeedbackVarying() */
GLenum type;
+
+ /**
+ * If location != -1, the size that should be returned by
+ * glGetTransformFeedbackVarying().
+ */
+ unsigned size;
};
@@ -1484,14 +1490,14 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
if (bracket) {
this->var_name = ralloc_strndup(mem_ctx, input, bracket - input);
- if (sscanf(bracket, "[%u]", &this->array_index) != 1) {
+ if (sscanf(bracket, "[%u]", &this->array_subscript) != 1) {
linker_error(prog, "Cannot parse transform feedback varying %s", input);
return false;
}
- this->is_array = true;
+ this->is_subscripted = true;
} else {
this->var_name = ralloc_strdup(mem_ctx, input);
- this->is_array = false;
+ this->is_subscripted = false;
}
/* For drivers that lower gl_ClipDistance to gl_ClipDistanceMESA, we need
@@ -1501,8 +1507,10 @@ tfeedback_decl::init(struct gl_context *ctx, struct gl_shader_program *prog,
if (ctx->ShaderCompilerOptions[MESA_SHADER_VERTEX].LowerClipDistance &&
strcmp(this->var_name, "gl_ClipDistance") == 0) {
this->var_name = "gl_ClipDistanceMESA";
- this->single_component = this->array_index % 4;
- this->array_index /= 4;
+ if (this->is_subscripted) {
+ this->single_component = this->array_subscript % 4;
+ this->array_subscript /= 4;
+ }
}
return true;
@@ -1518,9 +1526,9 @@ tfeedback_decl::is_same(const tfeedback_decl &x, const tfeedback_decl &y)
{
if (strcmp(x.var_name, y.var_name) != 0)
return false;
- if (x.is_array != y.is_array)
+ if (x.is_subscripted != y.is_subscripted)
return false;
- if (x.is_array && x.array_index != y.array_index)
+ if (x.is_subscripted && x.array_subscript != y.array_subscript)
return false;
if (x.single_component != y.single_component)
return false;
@@ -1542,37 +1550,39 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
{
if (output_var->type->is_array()) {
/* Array variable */
- if (!this->is_array) {
- linker_error(prog, "Transform feedback varying %s found, "
- "but array dereference required for varying %s[%d]).",
- this->orig_name,
- output_var->name, output_var->type->length);
- return false;
- }
- /* Check array bounds. */
- if (this->array_index >=
- (unsigned) output_var->type->array_size()) {
- linker_error(prog, "Transform feedback varying %s has index "
- "%i, but the array size is %i.",
- this->orig_name, this->array_index,
- output_var->type->array_size());
- return false;
- }
const unsigned matrix_cols =
output_var->type->fields.array->matrix_columns;
- this->location = output_var->location + this->array_index * matrix_cols;
+
+ if (this->is_subscripted) {
+ /* Check array bounds. */
+ if (this->array_subscript >=
+ (unsigned) output_var->type->array_size()) {
+ linker_error(prog, "Transform feedback varying %s has index "
+ "%i, but the array size is %i.",
+ this->orig_name, this->array_subscript,
+ output_var->type->array_size());
+ return false;
+ }
+ this->location =
+ output_var->location + this->array_subscript * matrix_cols;
+ this->size = 1;
+ } else {
+ this->location = output_var->location;
+ this->size = (unsigned) output_var->type->array_size();
+ }
this->vector_elements = output_var->type->fields.array->vector_elements;
this->matrix_columns = matrix_cols;
- this->type = GL_NONE;
+ this->type = output_var->type->fields.array->gl_type;
} else {
/* Regular variable (scalar, vector, or matrix) */
- if (this->is_array) {
+ if (this->is_subscripted) {
linker_error(prog, "Transform feedback varying %s found, "
"but it's an array ([] expected).",
this->orig_name);
return false;
}
this->location = output_var->location;
+ this->size = 1;
this->vector_elements = output_var->type->vector_elements;
this->matrix_columns = output_var->type->matrix_columns;
this->type = output_var->type->gl_type;
@@ -1621,26 +1631,25 @@ tfeedback_decl::store(struct gl_shader_program *prog,
this->orig_name);
return false;
}
- for (unsigned v = 0; v < this->matrix_columns; ++v) {
- unsigned num_components =
- this->single_component >= 0 ? 1 : this->vector_elements;
- info->Outputs[info->NumOutputs].OutputRegister = this->location + v;
- info->Outputs[info->NumOutputs].NumComponents = num_components;
- info->Outputs[info->NumOutputs].OutputBuffer = buffer;
- info->Outputs[info->NumOutputs].DstOffset = info->BufferStride[buffer];
- info->Outputs[info->NumOutputs].ComponentOffset =
- this->single_component >= 0 ? this->single_component : 0;
- ++info->NumOutputs;
- info->BufferStride[buffer] += num_components;
+ for (unsigned index = 0; index < this->size; ++index) {
+ for (unsigned v = 0; v < this->matrix_columns; ++v) {
+ unsigned num_components =
+ this->single_component >= 0 ? 1 : this->vector_elements;
+ 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->Outputs[info->NumOutputs].ComponentOffset =
+ this->single_component >= 0 ? this->single_component : 0;
+ ++info->NumOutputs;
+ info->BufferStride[buffer] += num_components;
+ }
}
info->Varyings[varying].Name = ralloc_strdup(prog, this->orig_name);
info->Varyings[varying].Type = this->type;
- /* Since we require that transform feedback varyings dereference
- * arrays, there's always only one element of the GL datatype above
- * present in this varying.
- */
- info->Varyings[varying].Size = 1;
+ info->Varyings[varying].Size = this->size;
info->NumVarying++;
return true;