diff options
Diffstat (limited to 'src')
-rw-r--r-- | src/glsl/linker.cpp | 103 |
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, |