summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--src/glsl/linker.cpp103
1 files changed, 48 insertions, 55 deletions
diff --git a/src/glsl/linker.cpp b/src/glsl/linker.cpp
index b13a6aa1ab6..e4d31d79d69 100644
--- a/src/glsl/linker.cpp
+++ b/src/glsl/linker.cpp
@@ -1537,18 +1537,12 @@ public:
static bool is_same(const tfeedback_decl &x, const tfeedback_decl &y);
bool assign_location(struct gl_context *ctx, struct gl_shader_program *prog,
ir_variable *output_var);
- bool accumulate_num_outputs(struct gl_shader_program *prog, unsigned *count);
+ unsigned get_num_outputs() const;
bool store(struct gl_context *ctx, struct gl_shader_program *prog,
struct gl_transform_feedback_info *info, unsigned buffer,
const unsigned max_outputs) const;
-
- /**
- * True if assign_location() has been called for this object.
- */
- bool is_assigned() const
- {
- return this->location != -1;
- }
+ ir_variable *find_output_var(gl_shader_program *prog,
+ gl_shader *producer) const;
bool is_next_buffer_separator() const
{
@@ -1561,19 +1555,8 @@ public:
}
/**
- * Determine whether this object refers to the variable var.
- */
- bool matches_var(ir_variable *var) const
- {
- if (this->is_clip_distance_mesa)
- return strcmp(var->name, "gl_ClipDistanceMESA") == 0;
- else
- return strcmp(var->name, this->var_name) == 0;
- }
-
- /**
* The total number of varying components taken up by this variable. Only
- * valid if is_assigned() is true.
+ * valid if assign_location() has been called.
*/
unsigned num_components() const
{
@@ -1822,34 +1805,18 @@ tfeedback_decl::assign_location(struct gl_context *ctx,
}
-bool
-tfeedback_decl::accumulate_num_outputs(struct gl_shader_program *prog,
- unsigned *count)
+unsigned
+tfeedback_decl::get_num_outputs() const
{
if (!this->is_varying()) {
- return true;
- }
-
- if (!this->is_assigned()) {
- /* From GL_EXT_transform_feedback:
- * A program will fail to link if:
- *
- * * any variable name specified in the <varyings> array is not
- * declared as an output in the geometry shader (if present) or
- * the vertex shader (if no geometry shader is present);
- */
- linker_error(prog, "Transform feedback varying %s undeclared.",
- this->orig_name);
- return false;
+ return 0;
}
unsigned translated_size = this->size;
if (this->is_clip_distance_mesa)
translated_size = (translated_size + 3) / 4;
- *count += translated_size * this->matrix_columns;
-
- return true;
+ return translated_size * this->matrix_columns;
}
@@ -1926,6 +1893,29 @@ tfeedback_decl::store(struct gl_context *ctx, struct gl_shader_program *prog,
}
+ir_variable *
+tfeedback_decl::find_output_var(gl_shader_program *prog,
+ gl_shader *producer) const
+{
+ const char *name = this->is_clip_distance_mesa
+ ? "gl_ClipDistanceMESA" : this->var_name;
+ ir_variable *var = producer->symbols->get_variable(name);
+ if (var && var->mode == ir_var_out)
+ return var;
+
+ /* From GL_EXT_transform_feedback:
+ * A program will fail to link if:
+ *
+ * * any variable name specified in the <varyings> array is not
+ * declared as an output in the geometry shader (if present) or
+ * the vertex shader (if no geometry shader is present);
+ */
+ linker_error(prog, "Transform feedback varying %s undeclared.",
+ this->orig_name);
+ return NULL;
+}
+
+
/**
* Parse all the transform feedback declarations that were passed to
* glTransformFeedbackVaryings() and store them in tfeedback_decl objects.
@@ -2110,21 +2100,25 @@ assign_varying_locations(struct gl_context *ctx,
assign_varying_location(input_var, output_var, &input_index,
&output_index);
}
+ }
- for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
- if (!tfeedback_decls[i].is_varying())
- continue;
+ for (unsigned i = 0; i < num_tfeedback_decls; ++i) {
+ if (!tfeedback_decls[i].is_varying())
+ continue;
- if (!tfeedback_decls[i].is_assigned() &&
- tfeedback_decls[i].matches_var(output_var)) {
- if (output_var->is_unmatched_generic_inout) {
- assign_varying_location(input_var, output_var, &input_index,
- &output_index);
- }
- if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
- return false;
- }
+ ir_variable *output_var
+ = tfeedback_decls[i].find_output_var(prog, producer);
+
+ if (output_var == NULL)
+ return false;
+
+ if (output_var->is_unmatched_generic_inout) {
+ assign_varying_location(NULL, output_var, &input_index,
+ &output_index);
}
+
+ if (!tfeedback_decls[i].assign_location(ctx, prog, output_var))
+ return false;
}
unsigned varying_vectors = 0;
@@ -2233,8 +2227,7 @@ store_tfeedback_info(struct gl_context *ctx, struct gl_shader_program *prog,
unsigned num_outputs = 0;
for (unsigned i = 0; i < num_tfeedback_decls; ++i)
- if (!tfeedback_decls[i].accumulate_num_outputs(prog, &num_outputs))
- return false;
+ num_outputs += tfeedback_decls[i].get_num_outputs();
prog->LinkedTransformFeedback.Outputs =
rzalloc_array(prog,