[Mesa-dev] [PATCH] spirv: Handle patch decorations up-front

Kenneth Graunke kenneth at whitecape.org
Thu Jan 12 02:42:37 UTC 2017


On Wednesday, January 11, 2017 6:32:34 PM PST Jason Ekstrand wrote:
> Once again, SPIR-V is insane... It allows you to place "patch"
> decorations on structure members.  Presumably, this is so that you can
> do something such as
> 
> out struct S {
>    layout(location = 0) patch vec4 thing1;
>    layout(location = 0) vec4 thing2;
> } str;
> 
> And have your I/O "nicely" organized.  While this is a bit silly, it's
> allowed and well-defined so whatever.  Where it really gets interesting
> is when you have an array of struct.  SPIR-V says nothing about not
> allowing you to have those qualifiers on the members of a struct that's
> inside an array and GLSLang does this.  Specifically, if you have
> 
> layout(location = 0) out patch struct S {
>    vec4 thing1;
>    vec4 thing2;
> } str[2];
> 
> then GLSLang will place the "patch" decorations on the struct members.
> This is ridiculous there is no way that having some of them be patch and
> some not would be well-defined given that patch and non-patch outputs
> are in effectively different storage classes.  This commit moves around
> the way we handle the "patch" decoration so that we can detect even the
> crazy cases and handle them.
> 
> Fixes: dEQP-VK.tessellation.user_defined_io.per_patch_block_array.*
> ---
>  src/compiler/spirv/vtn_variables.c | 23 +++++++++++++++++++++++
>  1 file changed, 23 insertions(+)
> 
> diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
> index 3ecb54f..91e5b13 100644
> --- a/src/compiler/spirv/vtn_variables.c
> +++ b/src/compiler/spirv/vtn_variables.c
> @@ -1359,8 +1359,29 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
>  
>        case vtn_variable_mode_input:
>        case vtn_variable_mode_output: {
> +         /* In order to know whether or not we're a per-vertex inout, we need
> +          * the patch qualifier.  This means walking the variable decorations
> +          * early before we actually create any variables.  Not a big deal.
> +          *
> +          * GLSLang really likes to place decorations in the most interior
> +          * thing it possibly can.  In particular, if you have a struct, it
> +          * will place the patch decorations on the struct members.  This
> +          * should be handled by the variable splitting below just fine.
> +          *
> +          * If you have an array-of-struct, things get even more wierd as it

weird

> +          * will place the patch decorations on the struct even though it's
> +          * inside an array and some of the members being patch and others not
> +          * makes no sense whatsoever.  Since the only sensible thing is for
> +          * it to be all or nothing, we'll call it patch if any of the members
> +          * are declared patch.
> +          */

I wonder if we could emit a warning if they don't match.  That would be
nice, although not essential...

It would be nice if SPIR-V on glslang were less crazy in this regard
but I don't expect either of those to realistically happen.  I think
your approach is reasonable.

Thank you so much for fixing this for me.

Reviewed-by: Kenneth Graunke <kenneth at whitecape.org>

>           var->patch = false;
>           vtn_foreach_decoration(b, val, var_is_patch_cb, &var->patch);
> +         if (glsl_type_is_array(var->type->type) &&
> +             glsl_type_is_struct(without_array->type)) {
> +            vtn_foreach_decoration(b, without_array->val,
> +                                   var_is_patch_cb, &var->patch);
> +         }
>  
>           /* For inputs and outputs, we immediately split structures.  This
>            * is for a couple of reasons.  For one, builtins may all come in
> @@ -1400,6 +1421,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
>                 var->members[i]->interface_type =
>                    interface_type->members[i]->type;
>                 var->members[i]->data.mode = nir_mode;
> +               var->members[i]->data.patch = var->patch;
>              }
>           } else {
>              var->var = rzalloc(b->shader, nir_variable);
> @@ -1407,6 +1429,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
>              var->var->type = var->type->type;
>              var->var->interface_type = interface_type->type;
>              var->var->data.mode = nir_mode;
> +            var->var->data.patch = var->patch;
>           }
>  
>           /* For inputs and outputs, we need to grab locations and builtin
> 

-------------- next part --------------
A non-text attachment was scrubbed...
Name: signature.asc
Type: application/pgp-signature
Size: 833 bytes
Desc: This is a digitally signed message part.
URL: <https://lists.freedesktop.org/archives/mesa-dev/attachments/20170111/d4e69262/attachment.sig>


More information about the mesa-dev mailing list