[Mesa-dev] [PATCH 3/3] glsl: don't always reject shaders with mismatching ifc blocks

Ilia Mirkin imirkin at alum.mit.edu
Tue Mar 8 15:37:25 UTC 2016


On Tue, Mar 8, 2016 at 8:47 AM, Timothy Arceri
<timothy.arceri at collabora.com> wrote:
> Since we store some member qualifiers in the interface type
> we need to be more careful about rejecting shaders just because
> the pointer doesn't match. Its perfectly valid for some qualifiers
> such as precision to not match across shader interfaces.
> ---
>  src/compiler/glsl/link_interface_blocks.cpp | 78 ++++++++++++++++++++++++++---
>  1 file changed, 72 insertions(+), 6 deletions(-)
>
> diff --git a/src/compiler/glsl/link_interface_blocks.cpp b/src/compiler/glsl/link_interface_blocks.cpp
> index 9d36836..f868c99 100644
> --- a/src/compiler/glsl/link_interface_blocks.cpp
> +++ b/src/compiler/glsl/link_interface_blocks.cpp
> @@ -81,6 +81,66 @@ intrastage_match(ir_variable *a,
>     return true;
>  }
>
> +/**
> + * Return true if interface members mismatch and its not allowed by GLSL.
> + */
> +static bool
> +interstage_member_mismatch(struct gl_shader_program *prog,
> +                           const glsl_type *c, const glsl_type *p) {
> +
> +   if (c->length != p->length)
> +      return true;
> +
> +   for (unsigned i = 0; i < c->length; i++) {
> +      if (c->fields.structure[i].type != p->fields.structure[i].type)
> +         return true;
> +      if (strcmp(c->fields.structure[i].name,
> +                 p->fields.structure[i].name) != 0)
> +         return true;
> +      if (c->fields.structure[i].location
> +          != p->fields.structure[i].location)
> +         return true;
> +      if (c->fields.structure[i].patch
> +          != p->fields.structure[i].patch)
> +         return true;
> +
> +      /* From Section 4.5 (Interpolation Qualifiers) of the GLSL 4.40 spec:
> +       *
> +       *    "It is a link-time error if, within the same stage, the
> +       *    interpolation qualifiers of variables of the same name do not
> +       *    match."
> +       */
> +      if (prog->IsES || prog->Version < 440)
> +         if (c->fields.structure[i].interpolation
> +             != p->fields.structure[i].interpolation)
> +            return true;
> +
> +      /* From Section 4.3.4 (Input Variables) of the GLSL ES 3.0 spec:
> +       *
> +       *    "The output of the vertex shader and the input of the fragment
> +       *    shader form an interface.  For this interface, vertex shader
> +       *    output variables and fragment shader input variables of the same
> +       *    name must match in type and qualification (other than precision
> +       *    and out matching to in).
> +       *
> +       * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.1 spec
> +       * says that centroid no longer needs to match for varyings.
> +       *
> +       * The table in Section 9.2.1 Linked Shaders of the GLSL ES 3.2 spec
> +       * says that sample need not match for varyings.
> +       */
> +      if (!prog->IsES || prog->Version < 310)
> +         if (c->fields.structure[i].centroid
> +             != p->fields.structure[i].centroid)
> +            return true;
> +      if (!prog->IsES || prog->Version < 320)
> +         if (c->fields.structure[i].sample
> +             != p->fields.structure[i].sample)
> +            return true;

Are you sure? The sample qualifier is added by
OES_shader_multisample_interpolation, which says "Also, the "sample"
qualifier may differ". And before that ext / ES 3.2, the sample
qualifier didn't exist. So I'd change this to just

if (!prog->IsES)

> +   }
> +
> +   return false;
> +}
>
>  /**
>   * Check if two interfaces match, according to interstage (in/out) interface
> @@ -91,9 +151,8 @@ intrastage_match(ir_variable *a,
>   * This is used for tessellation control and geometry shader consumers.
>   */
>  static bool
> -interstage_match(ir_variable *producer,
> -                 ir_variable *consumer,
> -                 bool extra_array_level)
> +interstage_match(struct gl_shader_program *prog, ir_variable *producer,
> +                 ir_variable *consumer, bool extra_array_level)
>  {
>     /* Unsized arrays should not occur during interstage linking.  They
>      * should have all been assigned a size by link_intrastage_shaders.
> @@ -106,9 +165,16 @@ interstage_match(ir_variable *producer,
>        /* Exception: if both the interface blocks are implicitly declared,
>         * don't force their types to match.  They might mismatch due to the two
>         * shaders using different GLSL versions, and that's ok.
> +       *
> +       * Also we store some member information in glsl_type that doesn't
> +       * always have to match across shaders such as interpolation so we need
> +       * to make a pass over members glsl_struct_field to make sure we don't
> +       * reject shaders where fields don't need to match.
>         */
> -      if (consumer->data.how_declared != ir_var_declared_implicitly ||
> -          producer->data.how_declared != ir_var_declared_implicitly)
> +      if ((consumer->data.how_declared != ir_var_declared_implicitly ||
> +           producer->data.how_declared != ir_var_declared_implicitly) &&
> +          interstage_member_mismatch(prog, consumer->get_interface_type(),
> +                                     producer->get_interface_type()))
>           return false;
>     }
>
> @@ -311,7 +377,7 @@ validate_interstage_inout_blocks(struct gl_shader_program *prog,
>        if (consumer_def == NULL)
>           continue;
>
> -      if (!interstage_match(var, consumer_def, extra_array_level)) {
> +      if (!interstage_match(prog, var, consumer_def, extra_array_level)) {
>           linker_error(prog, "definitions of interface block `%s' do not "
>                        "match\n", var->get_interface_type()->name);
>           return;
> --
> 2.5.0
>
> _______________________________________________
> mesa-dev mailing list
> mesa-dev at lists.freedesktop.org
> https://lists.freedesktop.org/mailman/listinfo/mesa-dev


More information about the mesa-dev mailing list