[Mesa-dev] [PATCH 07/28] spirv/nir: don't set interface_type if it is not a struct

Timothy Arceri tarceri at itsqueeze.com
Tue Nov 6 06:20:42 UTC 2018


On 22/10/18 11:24 pm, Alejandro PiƱeiro wrote:
> vnt_variables uses interface_type on several use cases, but on nir
> variable it is more limited. From nir.h:
> 
>     /**
>       * For variables that are in an interface block or are an instance of an
>       * interface block, this is the \c GLSL_TYPE_INTERFACE type for that block.
>       *
>       * \sa ir_variable::location
>       */
> 
> But interface blocks expects the type to be an struct, so those cases
> should not be filled. For example, glsl checks if a variable is in an
> uniform block if it is an uniform and has an interface type.
> 
> One example of why this is needed: gl_PatchVerticesIn is lowered to an
> uniform. Without this change, it would include a interface_type. Then,
> we would try to initialize the uniform block, and find that it doesn't
> have any component.
> ---
>   src/compiler/spirv/vtn_variables.c | 2 ++
>   1 file changed, 2 insertions(+)
> 
> diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
> index 957ef0610b7..9a4ddeaa822 100644
> --- a/src/compiler/spirv/vtn_variables.c
> +++ b/src/compiler/spirv/vtn_variables.c
> @@ -1818,6 +1818,8 @@ vtn_create_variable(struct vtn_builder *b, struct vtn_value *val,
>               var->var->members[i].mode = nir_mode;
>               var->var->members[i].patch = var->patch;
>            }
> +      } else {
> +         var->var->interface_type = NULL;
>         }
>   
>         /* For inputs and outputs, we need to grab locations and builtin
> 

Please don't do these bandaid style changes, they make the code hard to 
follow and error prone. We should instead change the code so that 
interface_type is never set unless we are processing a struct:


       var->var = rzalloc(b->shader, nir_variable);
       var->var->name = ralloc_strdup(var->var, val->name);
       var->var->type = var->type->type;
       var->var->data.mode = nir_mode;
       var->var->data.patch = var->patch;

       /* For inputs and outputs, we immediately split structures.  This
        * is for a couple of reasons.  For one, builtins may all come in
        * a struct and we really want those split out into separate
        * variables.  For another, interpolation qualifiers can be
        * applied to members of the top-level struct ane we need to be
        * able to preserve that information.
        */

       struct vtn_type *interface_type = var->type;
       if (is_per_vertex_inout(var, b->shader->info.stage)) {
          /* In Geometry shaders (and some tessellation), inputs come
           * in per-vertex arrays.  However, some builtins come in
           * non-per-vertex, hence the need for the is_array check.  In
           * any case, there are no non-builtin arrays allowed so this
           * check should be sufficient.
           */
          interface_type = var->type->array_element;
       }

       if (glsl_type_is_struct(interface_type->type)) {
          var->var->interface_type = interface_type->type;

          /* It's a struct.  Set it up as per-member. */
          var->var->num_members = glsl_get_length(interface_type->type);
          var->var->members = rzalloc_array(var->var, struct 
nir_variable_data,
                                            var->var->num_members);

          for (unsigned i = 0; i < var->var->num_members; i++) {
             var->var->members[i].mode = nir_mode;
             var->var->members[i].patch = var->patch;
          }
       }

With that change this is:

Reviewed-by: Timothy Arceri <tarceri at itsqueeze.com>


More information about the mesa-dev mailing list