From ea9deafff4a74ebc01e8a9a4b428cc98e4198adc Mon Sep 17 00:00:00 2001 From: Caio Oliveira Date: Thu, 10 Jul 2025 08:07:10 -0700 Subject: [PATCH] spirv: Add more restrictions around Blocks And take advantage of the new restriction to skip the ptr_as_array case for Blocks. Reviewed-by: Faith Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 7 +++++- src/compiler/spirv/vtn_variables.c | 40 ++++++++++++++++++++++++------ 2 files changed, 39 insertions(+), 8 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 9679ebda091..6c956ea5c8c 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -1454,7 +1454,12 @@ array_stride_decoration_cb(struct vtn_builder *b, struct vtn_type *type = val->type; if (dec->decoration == SpvDecorationArrayStride) { - if (vtn_type_contains_block(b, type)) { + if (type->base_type == vtn_base_type_pointer && + (type->pointed->block || type->pointed->buffer_block)) { + vtn_warn("A pointer to a structure decorated with *Block* or " + "*BufferBlock* must not have an *ArrayStride* decoration"); + /* Ignore the decoration */ + } else if (vtn_type_contains_block(b, type)) { vtn_warn("The ArrayStride decoration cannot be applied to an array " "type which contains a structure type decorated Block " "or BufferBlock"); diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index b4f60e27339..f2e30c8880f 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -2718,12 +2718,42 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, case SpvOpPtrAccessChain: case SpvOpInBoundsAccessChain: case SpvOpInBoundsPtrAccessChain: { - struct vtn_access_chain *chain = vtn_access_chain_create(b, count - 4); + bool ptr_as_array = opcode == SpvOpPtrAccessChain || + opcode == SpvOpInBoundsPtrAccessChain; + + struct vtn_type *ptr_type = vtn_get_type(b, w[1]); + struct vtn_pointer *base = vtn_pointer(b, w[3]); + + unsigned first_idx = 4; + + /* The SPIR-V spec says + * + * "OpPtrAccessChain: If _Base_ points to a structure decorated with + * *Block* or *BufferBlock* and the value of 'Element' is not zero + * then the behavior is undefined." + */ + if (ptr_as_array && + (base->type->pointed->block || base->type->pointed->buffer_block)) { + + struct vtn_value *val = vtn_untyped_value(b, w[first_idx]); + if (val->value_type == vtn_value_type_constant && + vtn_constant_int(b, w[first_idx]) != 0) { + vtn_warn("OpPtrAccessChain on a block with non-zero Element."); + } + + /* Any value other than zero for Element results in undefined + * behavior so we can just ignore the ptr_as_array part. + */ + first_idx++; + ptr_as_array = false; + } + enum gl_access_qualifier access = 0; - chain->ptr_as_array = (opcode == SpvOpPtrAccessChain || opcode == SpvOpInBoundsPtrAccessChain); + struct vtn_access_chain *chain = vtn_access_chain_create(b, count - first_idx); + chain->ptr_as_array = ptr_as_array; unsigned idx = 0; - for (int i = 4; i < count; i++) { + for (int i = first_idx; i < count; i++) { struct vtn_value *link_val = vtn_untyped_value(b, w[i]); if (link_val->value_type == vtn_value_type_constant) { chain->link[idx].mode = vtn_access_mode_literal; @@ -2739,10 +2769,6 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, idx++; } - struct vtn_type *ptr_type = vtn_get_type(b, w[1]); - - struct vtn_pointer *base = vtn_pointer(b, w[3]); - chain->in_bounds = (opcode == SpvOpInBoundsAccessChain || opcode == SpvOpInBoundsPtrAccessChain); /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */