diff options
Diffstat (limited to 'src/compiler/glsl/link_varyings.cpp')
-rw-r--r-- | src/compiler/glsl/link_varyings.cpp | 50 |
1 files changed, 50 insertions, 0 deletions
diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp index 4b63f7693f6..4757825c244 100644 --- a/src/compiler/glsl/link_varyings.cpp +++ b/src/compiler/glsl/link_varyings.cpp @@ -1373,6 +1373,21 @@ tfeedback_decl::find_candidate(gl_shader_program *prog, return this->matched_candidate; } +/** + * Force a candidate over the previously matched one. It happens when a new + * varying needs to be created to match the xfb declaration, for example, + * to fullfil an alignment criteria. + */ +void +tfeedback_decl::set_lowered_candidate(const tfeedback_candidate *candidate) +{ + this->matched_candidate = candidate; + + /* The subscript part is no longer relevant */ + this->is_subscripted = false; + this->array_subscript = 0; +} + /** * Parse all the transform feedback declarations that were passed to @@ -2779,6 +2794,41 @@ assign_varying_locations(struct gl_context *ctx, return false; } + /* A new output varying is needed, and the matched candidate should be + * replaced, if varying packing is disabled for xfb and the current + * declaration is not aligned within the top level varying + * (e.g. vec3_arr[1]). + */ + const unsigned dmul = + matched_candidate->type->without_array()->is_64bit() ? 2 : 1; + if (disable_xfb_packing && + !tfeedback_decls[i].is_aligned(dmul, matched_candidate->offset)) { + ir_variable *new_var; + tfeedback_candidate *new_candidate = NULL; + + new_var = lower_xfb_varying(mem_ctx, producer, tfeedback_decls[i].name()); + if (new_var == NULL) { + ralloc_free(hash_table_ctx); + return false; + } + + /* Create new candidate and replace matched_candidate */ + new_candidate = rzalloc(mem_ctx, tfeedback_candidate); + new_candidate->toplevel_var = new_var; + new_candidate->toplevel_var->data.is_unmatched_generic_inout = 1; + new_candidate->type = new_var->type; + new_candidate->offset = 0; + _mesa_hash_table_insert(tfeedback_candidates, + ralloc_strdup(mem_ctx, new_var->name), + new_candidate); + + tfeedback_decls[i].set_lowered_candidate(new_candidate); + matched_candidate = new_candidate; + } + + /* Mark as xfb varying */ + matched_candidate->toplevel_var->data.is_xfb = 1; + /* Mark xfb varyings as always active */ matched_candidate->toplevel_var->data.always_active_io = 1; |