[Mesa-dev] [PATCH] glsl: Checks for interpolation into its own function.

Samuel Iglesias Gonsálvez siglesias at igalia.com
Tue Apr 26 10:16:05 UTC 2016


On 04/04/16 18:50, Andres Gomez wrote:
> This generalizes the validation also to be done for variables inside
> interface blocks, which, for some cases, was missing.
> 
> For a discussion about the additional validation cases included see
> https://lists.freedesktop.org/archives/mesa-dev/2016-March/109117.html
> and Khronos bug #15671.
> 

Do we have news about this Khronos bug? Are the piglit tests pushed
upstream?

Assuming no piglit/dEQP regressions, this patch is:

Reviewed-by: Samuel Iglesias Gonsálvez <siglesias at igalia.com>

Sam

> Signed-off-by: Andres Gomez <agomez at igalia.com>
> ---
>  src/compiler/glsl/ast_to_hir.cpp | 316 +++++++++++++++++++++------------------
>  1 file changed, 171 insertions(+), 145 deletions(-)
> 
> diff --git a/src/compiler/glsl/ast_to_hir.cpp b/src/compiler/glsl/ast_to_hir.cpp
> index 7c9be81..e4ebc6b 100644
> --- a/src/compiler/glsl/ast_to_hir.cpp
> +++ b/src/compiler/glsl/ast_to_hir.cpp
> @@ -2792,8 +2792,164 @@ apply_explicit_binding(struct _mesa_glsl_parse_state *state,
>  }
>  
>  
> +static void
> +validate_interpolation_qualifier(struct _mesa_glsl_parse_state *state,
> +                                 YYLTYPE *loc,
> +                                 const glsl_interp_qualifier interpolation,
> +                                 const struct ast_type_qualifier *qual,
> +                                 const struct glsl_type *var_type,
> +                                 ir_variable_mode mode)
> +{
> +   /* Interpolation qualifiers can only apply to shader inputs or outputs, but
> +    * not to vertex shader inputs nor fragment shader outputs.
> +    *
> +    * From section 4.3 ("Storage Qualifiers") of the GLSL 1.30 spec:
> +    *    "Outputs from a vertex shader (out) and inputs to a fragment
> +    *    shader (in) can be further qualified with one or more of these
> +    *    interpolation qualifiers"
> +    *    ...
> +    *    "These interpolation qualifiers may only precede the qualifiers in,
> +    *    centroid in, out, or centroid out in a declaration. They do not apply
> +    *    to the deprecated storage qualifiers varying or centroid
> +    *    varying. They also do not apply to inputs into a vertex shader or
> +    *    outputs from a fragment shader."
> +    *
> +    * From section 4.3 ("Storage Qualifiers") of the GLSL ES 3.00 spec:
> +    *    "Outputs from a shader (out) and inputs to a shader (in) can be
> +    *    further qualified with one of these interpolation qualifiers."
> +    *    ...
> +    *    "These interpolation qualifiers may only precede the qualifiers
> +    *    in, centroid in, out, or centroid out in a declaration. They do
> +    *    not apply to inputs into a vertex shader or outputs from a
> +    *    fragment shader."
> +    */
> +   if (state->is_version(130, 300)
> +       && interpolation != INTERP_QUALIFIER_NONE) {
> +      const char *i = interpolation_string(interpolation);
> +      if (mode != ir_var_shader_in && mode != ir_var_shader_out)
> +         _mesa_glsl_error(loc, state,
> +                          "interpolation qualifier `%s' can only be applied to "
> +                          "shader inputs or outputs.", i);
> +
> +      switch (state->stage) {
> +      case MESA_SHADER_VERTEX:
> +         if (mode == ir_var_shader_in) {
> +            _mesa_glsl_error(loc, state,
> +                             "interpolation qualifier '%s' cannot be applied to "
> +                             "vertex shader inputs", i);
> +         }
> +         break;
> +      case MESA_SHADER_FRAGMENT:
> +         if (mode == ir_var_shader_out) {
> +            _mesa_glsl_error(loc, state,
> +                             "interpolation qualifier '%s' cannot be applied to "
> +                             "fragment shader outputs", i);
> +         }
> +         break;
> +      default:
> +         break;
> +      }
> +   }
> +
> +   /* Interpolation qualifiers cannot be applied to 'centroid' and
> +    * 'centroid varying'.
> +    *
> +    * From section 4.3 ("Storage Qualifiers") of the GLSL 1.30 spec:
> +    *    "interpolation qualifiers may only precede the qualifiers in,
> +    *    centroid in, out, or centroid out in a declaration. They do not apply
> +    *    to the deprecated storage qualifiers varying or centroid varying."
> +    *
> +    * These deprecated storage qualifiers do not exist in GLSL ES 3.00.
> +    */
> +   if (state->is_version(130, 0)
> +       && interpolation != INTERP_QUALIFIER_NONE
> +       && qual->flags.q.varying) {
> +
> +      const char *i = interpolation_string(interpolation);
> +      const char *s;
> +      if (qual->flags.q.centroid)
> +         s = "centroid varying";
> +      else
> +         s = "varying";
> +
> +      _mesa_glsl_error(loc, state,
> +                       "qualifier '%s' cannot be applied to the "
> +                       "deprecated storage qualifier '%s'", i, s);
> +   }
> +
> +   /* Integer fragment inputs must be qualified with 'flat'.  In GLSL ES,
> +    * so must integer vertex outputs.
> +    *
> +    * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec:
> +    *    "Fragment shader inputs that are signed or unsigned integers or
> +    *    integer vectors must be qualified with the interpolation qualifier
> +    *    flat."
> +    *
> +    * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec:
> +    *    "Fragment shader inputs that are, or contain, signed or unsigned
> +    *    integers or integer vectors must be qualified with the
> +    *    interpolation qualifier flat."
> +    *
> +    * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec:
> +    *    "Vertex shader outputs that are, or contain, signed or unsigned
> +    *    integers or integer vectors must be qualified with the
> +    *    interpolation qualifier flat."
> +    *
> +    * Note that prior to GLSL 1.50, this requirement applied to vertex
> +    * outputs rather than fragment inputs.  That creates problems in the
> +    * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all
> +    * desktop GL shaders.  For GLSL ES shaders, we follow the spec and
> +    * apply the restriction to both vertex outputs and fragment inputs.
> +    *
> +    * Note also that the desktop GLSL specs are missing the text "or
> +    * contain"; this is presumably an oversight, since there is no
> +    * reasonable way to interpolate a fragment shader input that contains
> +    * an integer. See Khronos bug #15671.
> +    */
> +   if (state->is_version(130, 300)
> +       && var_type->contains_integer()
> +       && interpolation != INTERP_QUALIFIER_FLAT
> +       && ((state->stage == MESA_SHADER_FRAGMENT && mode == ir_var_shader_in)
> +           || (state->stage == MESA_SHADER_VERTEX && mode == ir_var_shader_out
> +               && state->es_shader))) {
> +      const char *shader_var_type = (state->stage == MESA_SHADER_VERTEX) ?
> +         "vertex output" : "fragment input";
> +      _mesa_glsl_error(loc, state, "if a %s is (or contains) "
> +                       "an integer, then it must be qualified with 'flat'",
> +                       shader_var_type);
> +   }
> +
> +   /* Double fragment inputs must be qualified with 'flat'.
> +    *
> +    * From the "Overview" of the ARB_gpu_shader_fp64 extension spec:
> +    *    "This extension does not support interpolation of double-precision
> +    *    values; doubles used as fragment shader inputs must be qualified as
> +    *    "flat"."
> +    *
> +    * From section 4.3.4 ("Inputs") of the GLSL 4.00 spec:
> +    *    "Fragment shader inputs that are signed or unsigned integers, integer
> +    *    vectors, or any double-precision floating-point type must be
> +    *    qualified with the interpolation qualifier flat."
> +    *
> +    * Note that the GLSL specs are missing the text "or contain"; this is
> +    * presumably an oversight. See Khronos bug #15671.
> +    *
> +    * The 'double' type does not exist in GLSL ES so far.
> +    */
> +   if ((state->ARB_gpu_shader_fp64_enable
> +        || state->is_version(400, 0))
> +       && var_type->contains_double()
> +       && interpolation != INTERP_QUALIFIER_FLAT
> +       && state->stage == MESA_SHADER_FRAGMENT
> +       && mode == ir_var_shader_in) {
> +      _mesa_glsl_error(loc, state, "if a fragment input is (or contains) "
> +                       "a double, then it must be qualified with 'flat'");
> +   }
> +}
> +
>  static glsl_interp_qualifier
>  interpret_interpolation_qualifier(const struct ast_type_qualifier *qual,
> +                                  const struct glsl_type *var_type,
>                                    ir_variable_mode mode,
>                                    struct _mesa_glsl_parse_state *state,
>                                    YYLTYPE *loc)
> @@ -2805,37 +2961,23 @@ interpret_interpolation_qualifier(const struct ast_type_qualifier *qual,
>        interpolation = INTERP_QUALIFIER_NOPERSPECTIVE;
>     else if (qual->flags.q.smooth)
>        interpolation = INTERP_QUALIFIER_SMOOTH;
> -   else
> -      interpolation = INTERP_QUALIFIER_NONE;
> -
> -   if (interpolation != INTERP_QUALIFIER_NONE) {
> -      if (mode != ir_var_shader_in && mode != ir_var_shader_out) {
> -         _mesa_glsl_error(loc, state,
> -                          "interpolation qualifier `%s' can only be applied to "
> -                          "shader inputs or outputs.",
> -                          interpolation_string(interpolation));
> -
> -      }
> -
> -      if ((state->stage == MESA_SHADER_VERTEX && mode == ir_var_shader_in) ||
> -          (state->stage == MESA_SHADER_FRAGMENT && mode == ir_var_shader_out)) {
> -         _mesa_glsl_error(loc, state,
> -                          "interpolation qualifier `%s' cannot be applied to "
> -                          "vertex shader inputs or fragment shader outputs",
> -                          interpolation_string(interpolation));
> -      }
> -   } else if (state->es_shader &&
> -              ((mode == ir_var_shader_in &&
> -                state->stage != MESA_SHADER_VERTEX) ||
> -               (mode == ir_var_shader_out &&
> -                state->stage != MESA_SHADER_FRAGMENT))) {
> +   else if (state->es_shader &&
> +            ((mode == ir_var_shader_in &&
> +              state->stage != MESA_SHADER_VERTEX) ||
> +             (mode == ir_var_shader_out &&
> +              state->stage != MESA_SHADER_FRAGMENT)))
>        /* Section 4.3.9 (Interpolation) of the GLSL ES 3.00 spec says:
>         *
>         *    "When no interpolation qualifier is present, smooth interpolation
>         *    is used."
>         */
>        interpolation = INTERP_QUALIFIER_SMOOTH;
> -   }
> +   else
> +      interpolation = INTERP_QUALIFIER_NONE;
> +
> +   validate_interpolation_qualifier(state, loc,
> +                                    interpolation,
> +                                    qual, var_type, mode);
>  
>     return interpolation;
>  }
> @@ -3575,7 +3717,8 @@ apply_type_qualifier_to_variable(const struct ast_type_qualifier *qual,
>     }
>  
>     var->data.interpolation =
> -      interpret_interpolation_qualifier(qual, (ir_variable_mode) var->data.mode,
> +      interpret_interpolation_qualifier(qual, var->type,
> +                                        (ir_variable_mode) var->data.mode,
>                                          state, loc);
>  
>     /* Does the declaration use the deprecated 'attribute' or 'varying'
> @@ -4745,124 +4888,6 @@ ast_declarator_list::hir(exec_list *instructions,
>           var->data.how_declared = ir_var_hidden;
>        }
>  
> -      /* Integer fragment inputs must be qualified with 'flat'.  In GLSL ES,
> -       * so must integer vertex outputs.
> -       *
> -       * From section 4.3.4 ("Inputs") of the GLSL 1.50 spec:
> -       *    "Fragment shader inputs that are signed or unsigned integers or
> -       *    integer vectors must be qualified with the interpolation qualifier
> -       *    flat."
> -       *
> -       * From section 4.3.4 ("Input Variables") of the GLSL 3.00 ES spec:
> -       *    "Fragment shader inputs that are, or contain, signed or unsigned
> -       *    integers or integer vectors must be qualified with the
> -       *    interpolation qualifier flat."
> -       *
> -       * From section 4.3.6 ("Output Variables") of the GLSL 3.00 ES spec:
> -       *    "Vertex shader outputs that are, or contain, signed or unsigned
> -       *    integers or integer vectors must be qualified with the
> -       *    interpolation qualifier flat."
> -       *
> -       * Note that prior to GLSL 1.50, this requirement applied to vertex
> -       * outputs rather than fragment inputs.  That creates problems in the
> -       * presence of geometry shaders, so we adopt the GLSL 1.50 rule for all
> -       * desktop GL shaders.  For GLSL ES shaders, we follow the spec and
> -       * apply the restriction to both vertex outputs and fragment inputs.
> -       *
> -       * Note also that the desktop GLSL specs are missing the text "or
> -       * contain"; this is presumably an oversight, since there is no
> -       * reasonable way to interpolate a fragment shader input that contains
> -       * an integer.
> -       */
> -      if (state->is_version(130, 300) &&
> -          var->type->contains_integer() &&
> -          var->data.interpolation != INTERP_QUALIFIER_FLAT &&
> -          ((state->stage == MESA_SHADER_FRAGMENT && var->data.mode == ir_var_shader_in)
> -           || (state->stage == MESA_SHADER_VERTEX && var->data.mode == ir_var_shader_out
> -               && state->es_shader))) {
> -         const char *var_type = (state->stage == MESA_SHADER_VERTEX) ?
> -            "vertex output" : "fragment input";
> -         _mesa_glsl_error(&loc, state, "if a %s is (or contains) "
> -                          "an integer, then it must be qualified with 'flat'",
> -                          var_type);
> -      }
> -
> -      /* Double fragment inputs must be qualified with 'flat'. */
> -      if (var->type->contains_double() &&
> -          var->data.interpolation != INTERP_QUALIFIER_FLAT &&
> -          state->stage == MESA_SHADER_FRAGMENT &&
> -          var->data.mode == ir_var_shader_in) {
> -         _mesa_glsl_error(&loc, state, "if a fragment input is (or contains) "
> -                          "a double, then it must be qualified with 'flat'",
> -                          var_type);
> -      }
> -
> -      /* Interpolation qualifiers cannot be applied to 'centroid' and
> -       * 'centroid varying'.
> -       *
> -       * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
> -       *    "interpolation qualifiers may only precede the qualifiers in,
> -       *    centroid in, out, or centroid out in a declaration. They do not apply
> -       *    to the deprecated storage qualifiers varying or centroid varying."
> -       *
> -       * These deprecated storage qualifiers do not exist in GLSL ES 3.00.
> -       */
> -      if (state->is_version(130, 0)
> -          && this->type->qualifier.has_interpolation()
> -          && this->type->qualifier.flags.q.varying) {
> -
> -         const char *i = interpolation_string(var->data.interpolation);
> -         const char *s;
> -         if (this->type->qualifier.flags.q.centroid)
> -            s = "centroid varying";
> -         else
> -            s = "varying";
> -
> -         _mesa_glsl_error(&loc, state,
> -                          "qualifier '%s' cannot be applied to the "
> -                          "deprecated storage qualifier '%s'", i, s);
> -      }
> -
> -
> -      /* Interpolation qualifiers can only apply to vertex shader outputs and
> -       * fragment shader inputs.
> -       *
> -       * From page 29 (page 35 of the PDF) of the GLSL 1.30 spec:
> -       *    "Outputs from a vertex shader (out) and inputs to a fragment
> -       *    shader (in) can be further qualified with one or more of these
> -       *    interpolation qualifiers"
> -       *
> -       * From page 31 (page 37 of the PDF) of the GLSL ES 3.00 spec:
> -       *    "These interpolation qualifiers may only precede the qualifiers
> -       *    in, centroid in, out, or centroid out in a declaration. They do
> -       *    not apply to inputs into a vertex shader or outputs from a
> -       *    fragment shader."
> -       */
> -      if (state->is_version(130, 300)
> -          && this->type->qualifier.has_interpolation()) {
> -
> -         const char *i = interpolation_string(var->data.interpolation);
> -         switch (state->stage) {
> -         case MESA_SHADER_VERTEX:
> -            if (this->type->qualifier.flags.q.in) {
> -               _mesa_glsl_error(&loc, state,
> -                                "qualifier '%s' cannot be applied to vertex "
> -                                "shader inputs", i);
> -            }
> -            break;
> -         case MESA_SHADER_FRAGMENT:
> -            if (this->type->qualifier.flags.q.out) {
> -               _mesa_glsl_error(&loc, state,
> -                                "qualifier '%s' cannot be applied to fragment "
> -                                "shader outputs", i);
> -            }
> -            break;
> -         default:
> -            break;
> -         }
> -      }
> -
> -
>        /* From section 4.3.4 of the GLSL 4.00 spec:
>         *    "Input variables may not be declared using the patch in qualifier
>         *    in tessellation control or geometry shaders."
> @@ -6597,7 +6622,8 @@ ast_process_struct_or_iface_block_members(exec_list *instructions,
>           fields[i].type = field_type;
>           fields[i].name = decl->identifier;
>           fields[i].interpolation =
> -            interpret_interpolation_qualifier(qual, var_mode, state, &loc);
> +            interpret_interpolation_qualifier(qual, field_type,
> +                                              var_mode, state, &loc);
>           fields[i].centroid = qual->flags.q.centroid ? 1 : 0;
>           fields[i].sample = qual->flags.q.sample ? 1 : 0;
>           fields[i].patch = qual->flags.q.patch ? 1 : 0;
> 


More information about the mesa-dev mailing list