diff options
-rw-r--r-- | src/compiler/spirv/spirv_to_nir.c | 99 |
1 files changed, 66 insertions, 33 deletions
diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index b54d259e14b..8c85eac5875 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -1101,10 +1101,18 @@ static void vtn_handle_type(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) { - struct vtn_value *val = vtn_push_value(b, w[1], vtn_value_type_type); + struct vtn_value *val = NULL; - val->type = rzalloc(b, struct vtn_type); - val->type->id = w[1]; + /* In order to properly handle forward declarations, we have to defer + * allocation for pointer types. + */ + if (opcode != SpvOpTypePointer && opcode != SpvOpTypeForwardPointer) { + val = vtn_push_value(b, w[1], vtn_value_type_type); + vtn_fail_if(val->type != NULL, + "Only pointers can have forward declarations"); + val->type = rzalloc(b, struct vtn_type); + val->type->id = w[1]; + } switch (opcode) { case SpvOpTypeVoid: @@ -1274,46 +1282,70 @@ vtn_handle_type(struct vtn_builder *b, SpvOp opcode, break; } - case SpvOpTypePointer: { + case SpvOpTypePointer: + case SpvOpTypeForwardPointer: { + /* We can't blindly push the value because it might be a forward + * declaration. + */ + val = vtn_untyped_value(b, w[1]); + SpvStorageClass storage_class = w[2]; - struct vtn_type *deref_type = - vtn_value(b, w[3], vtn_value_type_type)->type; - val->type->base_type = vtn_base_type_pointer; - val->type->storage_class = storage_class; - val->type->deref = deref_type; + if (val->value_type == vtn_value_type_invalid) { + val->value_type = vtn_value_type_type; + val->type = rzalloc(b, struct vtn_type); + val->type->id = w[1]; + val->type->base_type = vtn_base_type_pointer; + val->type->storage_class = storage_class; - vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); + /* These can actually be stored to nir_variables and used as SSA + * values so they need a real glsl_type. + */ + switch (storage_class) { + case SpvStorageClassUniform: + val->type->type = b->options->ubo_ptr_type; + break; + case SpvStorageClassStorageBuffer: + val->type->type = b->options->ssbo_ptr_type; + break; + case SpvStorageClassPushConstant: + val->type->type = b->options->push_const_ptr_type; + break; + case SpvStorageClassWorkgroup: + val->type->type = b->options->shared_ptr_type; + break; + default: + /* In this case, no variable pointers are allowed so all deref + * chains are complete back to the variable and it doesn't matter + * what type gets used so we leave it NULL. + */ + break; + } + } else { + vtn_fail_if(val->type->storage_class != storage_class, + "The storage classes of an OpTypePointer and any " + "OpTypeForwardPointers that provide forward " + "declarations of it must match."); + } - /* These can actually be stored to nir_variables and used as SSA - * values so they need a real glsl_type. - */ - switch (storage_class) { - case SpvStorageClassUniform: - val->type->type = b->options->ubo_ptr_type; - break; - case SpvStorageClassStorageBuffer: - val->type->type = b->options->ssbo_ptr_type; - break; - case SpvStorageClassPushConstant: - val->type->type = b->options->push_const_ptr_type; - break; - case SpvStorageClassWorkgroup: - val->type->type = b->options->shared_ptr_type; - if (b->options->lower_workgroup_access_to_offsets) { + if (opcode == SpvOpTypePointer) { + vtn_fail_if(val->type->deref != NULL, + "While OpTypeForwardPointer can be used to provide a " + "forward declaration of a pointer, OpTypePointer can " + "only be used once for a given id."); + + val->type->deref = vtn_value(b, w[3], vtn_value_type_type)->type; + + vtn_foreach_decoration(b, val, array_stride_decoration_cb, NULL); + + if (storage_class == SpvStorageClassWorkgroup && + b->options->lower_workgroup_access_to_offsets) { uint32_t size, align; val->type->deref = vtn_type_layout_std430(b, val->type->deref, &size, &align); val->type->length = size; val->type->align = align; } - break; - default: - /* In this case, no variable pointers are allowed so all deref chains - * are complete back to the variable and it doesn't matter what type - * gets used so we leave it NULL. - */ - break; } break; } @@ -3931,6 +3963,7 @@ vtn_handle_variable_or_type_instruction(struct vtn_builder *b, SpvOp opcode, case SpvOpTypeStruct: case SpvOpTypeOpaque: case SpvOpTypePointer: + case SpvOpTypeForwardPointer: case SpvOpTypeFunction: case SpvOpTypeEvent: case SpvOpTypeDeviceEvent: |