From 072a79b18893a09a2ffc44cc9ce7898a26af14f9 Mon Sep 17 00:00:00 2001 From: Anuj Phogat Date: Tue, 4 Feb 2014 10:38:18 -0800 Subject: glsl: Compile error if fs defines conflicting qualifiers for gl_FragCoord GLSL 1.50 spec says: "If gl_FragCoord is redeclared in any fragment shader in a program, it must be redeclared in all the fragment shaders in that program that have a static use gl_FragCoord. All redeclarations of gl_FragCoord in all fragment shaders in a single program must have the same set of qualifiers." This patch makes the glsl compiler to generate an error if we have a fragment shader defined with conflicting layout qualifier declarations for gl_FragCoord. For example: layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; layout(pixel_center_integer) in vec4 gl_FragCoord; void main() { } V2: Some code refactoring for better readability. Add compiler error conditions for redeclarations like: layout(origin_upper_left) in vec4 gl_FragCoord; layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; and in vec4 gl_FragCoord; layout(origin_upper_left, pixel_center_integer) in vec4 gl_FragCoord; V3: Simplify function is_conflicting_fragcoord_redeclaration() V4: Check for null pointer before doing strcmp(var->name, "gl_FragCoord"). Signed-off-by: Anuj Phogat Cc: Reviewed-by: Ian Romanick (cherry picked from commit 581e4acb0d68eb1063df3919e19e0ef9d86eebff) --- src/glsl/ast_to_hir.cpp | 58 +++++++++++++++++++++++++++++++++++++++++++ src/glsl/glsl_parser_extras.h | 12 +++++++++ 2 files changed, 70 insertions(+) diff --git a/src/glsl/ast_to_hir.cpp b/src/glsl/ast_to_hir.cpp index 3a9c124e03b..c04b6aeb16d 100644 --- a/src/glsl/ast_to_hir.cpp +++ b/src/glsl/ast_to_hir.cpp @@ -2203,6 +2203,34 @@ validate_explicit_location(const struct ast_type_qualifier *qual, return; } +static inline const char* +get_layout_qualifier_string(bool origin_upper_left, bool pixel_center_integer) +{ + if (origin_upper_left && pixel_center_integer) + return "origin_upper_left, pixel_center_integer"; + else if (origin_upper_left) + return "origin_upper_left"; + else if (pixel_center_integer) + return "pixel_center_integer"; + else + return " "; +} + +static inline bool +is_conflicting_fragcoord_redeclaration(struct _mesa_glsl_parse_state *state, + const struct ast_type_qualifier *qual) +{ + /* If gl_FragCoord was previously declared, and the qualifiers were + * different in any way, return true. + */ + if (state->fs_redeclares_gl_fragcoord) { + return (state->fs_pixel_center_integer != qual->flags.q.pixel_center_integer + || state->fs_origin_upper_left != qual->flags.q.origin_upper_left); + } + + return false; +} + static void apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, ir_variable *var, @@ -2357,6 +2385,36 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual, qual_string); } + if (var->name != NULL && strcmp(var->name, "gl_FragCoord") == 0) { + + /* Make sure all gl_FragCoord redeclarations specify the same layout + * qualifiers. + */ + if (is_conflicting_fragcoord_redeclaration(state, qual)) { + const char *const qual_string = + get_layout_qualifier_string(qual->flags.q.origin_upper_left, + qual->flags.q.pixel_center_integer); + + const char *const state_string = + get_layout_qualifier_string(state->fs_origin_upper_left, + state->fs_pixel_center_integer); + + _mesa_glsl_error(loc, state, + "gl_FragCoord redeclared with different layout " + "qualifiers (%s) and (%s) ", + state_string, + qual_string); + } + state->fs_origin_upper_left = qual->flags.q.origin_upper_left; + state->fs_pixel_center_integer = qual->flags.q.pixel_center_integer; + state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers = + !qual->flags.q.origin_upper_left && !qual->flags.q.pixel_center_integer; + state->fs_redeclares_gl_fragcoord = + state->fs_origin_upper_left || + state->fs_pixel_center_integer || + state->fs_redeclares_gl_fragcoord_with_no_layout_qualifiers; + } + if (qual->flags.q.explicit_location) { validate_explicit_location(qual, var, state, loc); } else if (qual->flags.q.explicit_index) { diff --git a/src/glsl/glsl_parser_extras.h b/src/glsl/glsl_parser_extras.h index 8a4cbf14c91..82a83a5cc2a 100644 --- a/src/glsl/glsl_parser_extras.h +++ b/src/glsl/glsl_parser_extras.h @@ -181,6 +181,18 @@ struct _mesa_glsl_parse_state { */ struct ast_type_qualifier *default_uniform_qualifier; + /** + * Variables to track different cases if a fragment shader redeclares + * built-in variable gl_FragCoord. + * + * Note: These values are computed at ast_to_hir time rather than at parse + * time. + */ + bool fs_redeclares_gl_fragcoord; + bool fs_origin_upper_left; + bool fs_pixel_center_integer; + bool fs_redeclares_gl_fragcoord_with_no_layout_qualifiers; + /** * True if a geometry shader input primitive type was specified using a * layout directive. -- cgit v1.2.3