[Mesa-dev] [PATCH v2] glsl: disallow mixed varying types within a location

Timothy Arceri tarceri at itsqueeze.com
Mon Sep 11 00:03:35 UTC 2017


At the risk of sounding like a broken record. Why not just 
update/re-factor cross_validate_outputs_to_inputs()?

If there is a good reason not to have these checks in a single location 
that's fine but you haven't answered the question yet.

On 10/09/17 03:09, Ilia Mirkin wrote:
> The enhanced layouts spec has all kinds of restrictions about what can
> and cannot be mixed in a location. Integer/float(/presumably double)
> can't occupy a single location, interpolation has to be the same, as
> well as auxiliary storage (including patch!).
> 
> The implication of this is ... don't specify explicit locations/components
> if you want better packing, since the auto-packer doesn't care at all
> about most of these restrictions. Sad. (Auto-packer, of course, also
> can't always do its magic, e.g. SSO.)
> 
> This fixes:
> 
> KHR-GL45.enhanced_layouts.varying_location_aliasing_with_mixed_types
> KHR-GL45.enhanced_layouts.varying_location_aliasing_with_mixed_interpolation
> KHR-GL45.enhanced_layouts.varying_location_aliasing_with_mixed_auxiliary_storage
> 
> See https://github.com/KhronosGroup/OpenGL-API/issues/13 for some more
> info, where I asked about patch vs non-patch locations.
> 
> Signed-off-by: Ilia Mirkin <imirkin at alum.mit.edu>
> ---
> 
> v1 -> v2: move to link_varyings.cpp, per tarceri
> 
>   src/compiler/glsl/link_varyings.cpp | 90 +++++++++++++++++++++++++++++++++++++
>   1 file changed, 90 insertions(+)
> 
> diff --git a/src/compiler/glsl/link_varyings.cpp b/src/compiler/glsl/link_varyings.cpp
> index 528506fd0eb..0aab083010e 100644
> --- a/src/compiler/glsl/link_varyings.cpp
> +++ b/src/compiler/glsl/link_varyings.cpp
> @@ -2438,6 +2438,87 @@ check_against_input_limit(struct gl_context *ctx,
>      return true;
>   }
>   
> +static void
> +check_location_mixing(struct gl_shader_program *prog,
> +                      struct gl_linked_shader *shader)
> +{
> +   struct data_type {
> +      // 0: unused, 1: float, 2: int, 3: 64-bit
> +      unsigned var_type:2;
> +      unsigned interpolation:2;
> +      bool centroid:1;
> +      bool sample:1;
> +      bool patch:1;
> +   } data_types[2][MAX_VARYING] = {};
> +
> +   foreach_in_list(ir_instruction, node, shader->ir) {
> +      ir_variable *var = node->as_variable();
> +      if (!var || !var->data.explicit_location)
> +         continue;
> +
> +      if (var->data.mode != ir_var_shader_in &&
> +          var->data.mode != ir_var_shader_out)
> +         continue;
> +
> +      bool output = var->data.mode == ir_var_shader_out;
> +      int var_slot;
> +      if (!output && shader->Stage == MESA_SHADER_VERTEX) {
> +         var_slot = var->data.location - VERT_ATTRIB_GENERIC0;
> +         if (var_slot >= VERT_ATTRIB_GENERIC_MAX)
> +            continue;
> +      } else if (var->data.patch) {
> +         var_slot = var->data.location - VARYING_SLOT_PATCH0;
> +         if (var_slot >= MAX_VARYING)
> +            continue;
> +      } else {
> +         var_slot = var->data.location - VARYING_SLOT_VAR0;
> +         if (var_slot >= MAX_VARYING)
> +            continue;
> +      }
> +
> +      if (var_slot < 0)
> +         continue;
> +
> +      const glsl_type *type = get_varying_type(var, shader->Stage);
> +      const glsl_type *type_without_array = type->without_array();
> +      unsigned num_elements = type->count_attribute_slots(false);
> +      unsigned var_type;
> +      if (glsl_base_type_is_64bit(type_without_array->base_type))
> +         var_type = 3;
> +      else if (glsl_base_type_is_integer(type_without_array->base_type))
> +         var_type = 2;
> +      else
> +         var_type = 1;
> +
> +      const char *var_dir = output ? "out" : "in";
> +
> +      for (unsigned i = 0; i < num_elements; i++, var_slot++) {
> +         data_type& existing = data_types[output][var_slot];
> +
> +         if (existing.var_type) {
> +            if (existing.var_type != var_type)
> +               linker_error(prog, "Mismatching %s varying types at location=%d",
> +                            var_dir, var_slot);
> +            if (existing.interpolation != var->data.interpolation)
> +               linker_error(prog, "Mismatching %s varying interpolation at location=%d",
> +                            var_dir, var_slot);
> +            if (existing.centroid != var->data.centroid ||
> +                existing.sample != var->data.sample ||
> +                existing.patch != var->data.patch)
> +               linker_error(prog, "Mismatching %s varying auxiliary storage at location=%d",
> +                            var_dir, var_slot);
> +         } else {
> +            existing.var_type = var_type;
> +            existing.interpolation = var->data.interpolation;
> +            existing.centroid = var->data.centroid;
> +            existing.sample = var->data.sample;
> +            existing.patch = var->data.patch;
> +         }
> +      }
> +   }
> +}
> +
> +
>   bool
>   link_varyings(struct gl_shader_program *prog, unsigned first, unsigned last,
>                 struct gl_context *ctx, void *mem_ctx)
> @@ -2447,6 +2528,15 @@ link_varyings(struct gl_shader_program *prog, unsigned first, unsigned last,
>      char **varying_names = NULL;
>      tfeedback_decl *tfeedback_decls = NULL;
>   
> +   /* Ensure that no illegal type/interp/storage mixing exists within
> +    * explicitly-specified varying/attribute locations.
> +    */
> +   for (int i = MESA_SHADER_FRAGMENT - 1; i >= 0; i--)
> +      if (prog->_LinkedShaders[i] != NULL)
> +         check_location_mixing(prog, prog->_LinkedShaders[i]);
> +   if (!prog->data->LinkStatus)
> +      return false;
> +
>      /* From the ARB_enhanced_layouts spec:
>       *
>       *    "If the shader used to record output variables for transform feedback
> 


More information about the mesa-dev mailing list