diff options
Diffstat (limited to 'src/glsl/ast_to_hir.cpp')
-rw-r--r-- | src/glsl/ast_to_hir.cpp | 18 |
1 files changed, 15 insertions, 3 deletions
diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 47fe7a32c3c..6e8a1fd1daa 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -1668,9 +1668,21 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, string); } else { var->explicit_location = true; - var->location = (state->target == vertex_shader) - ? (qual->location + VERT_ATTRIB_GENERIC0) - : (qual->location + FRAG_RESULT_DATA0); + + /* This bit of silliness is needed because invalid explicit locations + * are supposed to be flagged during linking. Small negative values + * biased by VERT_ATTRIB_GENERIC0 or FRAG_RESULT_DATA0 could alias + * built-in values (e.g., -16+VERT_ATTRIB_GENERIC0 = VERT_ATTRIB_POS). + * The linker needs to be able to differentiate these cases. This + * ensures that negative values stay negative. + */ + if (qual->location >= 0) { + var->location = (state->target == vertex_shader) + ? (qual->location + VERT_ATTRIB_GENERIC0) + : (qual->location + FRAG_RESULT_DATA0); + } else { + var->location = qual->location; + } } } |