From ee1f0451a8d304bf172cbaae6a0626f3ca9b5b17 Mon Sep 17 00:00:00 2001 From: Lionel Landwerlin Date: Thu, 6 May 2021 22:16:21 +0300 Subject: [PATCH] spirv: deal with null pointers %2456 = some complicated struct... %8307 = OpTypeInt 32 0 %8308 = OpTypeInt 8 0 %8467 = OpTypePointer Generic %8308 %8500 = OpTypePointer Generic %2456 %8586 = OpConstantNull %8500 %8312 = OpConstant %8307 0 %8314 = OpConstant %8307 2 %9752 = OpInBoundsPtrAccessChain %8467 %8586 %8312 %8314 Right now the parser can't deal with this %8586. Let's create a value off the Null constant. v2: add helpers v3: Correctly create the Null value Signed-off-by: Lionel Landwerlin Cc: mesa-stable Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 6 +++--- src/compiler/spirv/vtn_private.h | 33 ++++++++++++++++++++++++++++++ src/compiler/spirv/vtn_variables.c | 31 ++++++++++++++-------------- 3 files changed, 51 insertions(+), 19 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index 3c261ba9f2e..26e7582bed5 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -225,7 +225,7 @@ vtn_undef_ssa_value(struct vtn_builder *b, const struct glsl_type *type) return val; } -static struct vtn_ssa_value * +struct vtn_ssa_value * vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant, const struct glsl_type *type) { @@ -3622,13 +3622,13 @@ vtn_handle_atomics(struct vtn_builder *b, SpvOp opcode, case SpvOpAtomicFMinEXT: case SpvOpAtomicFMaxEXT: case SpvOpAtomicFlagTestAndSet: - ptr = vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + ptr = vtn_pointer(b, w[3]); scope = vtn_constant_uint(b, w[4]); semantics = vtn_constant_uint(b, w[5]); break; case SpvOpAtomicFlagClear: case SpvOpAtomicStore: - ptr = vtn_value(b, w[1], vtn_value_type_pointer)->pointer; + ptr = vtn_pointer(b, w[1]); scope = vtn_constant_uint(b, w[2]); semantics = vtn_constant_uint(b, w[3]); break; diff --git a/src/compiler/spirv/vtn_private.h b/src/compiler/spirv/vtn_private.h index 0ddf34e4d8f..a2d2cdcdb16 100644 --- a/src/compiler/spirv/vtn_private.h +++ b/src/compiler/spirv/vtn_private.h @@ -737,6 +737,10 @@ struct vtn_pointer * vtn_pointer_from_ssa(struct vtn_builder *b, nir_ssa_def *ssa, struct vtn_type *ptr_type); +struct vtn_ssa_value * +vtn_const_ssa_value(struct vtn_builder *b, nir_constant *constant, + const struct glsl_type *type); + static inline struct vtn_value * vtn_untyped_value(struct vtn_builder *b, uint32_t value_id) { @@ -787,6 +791,35 @@ vtn_value(struct vtn_builder *b, uint32_t value_id, return val; } +static inline struct vtn_value * +vtn_pointer_value(struct vtn_builder *b, uint32_t value_id) +{ + struct vtn_value *val = vtn_untyped_value(b, value_id); + vtn_fail_if(val->value_type != vtn_value_type_pointer && + !val->is_null_constant, + "SPIR-V id %u is the wrong kind of value", value_id); + return val; +} + +static inline struct vtn_pointer * +vtn_value_to_pointer(struct vtn_builder *b, struct vtn_value *value) +{ + if (value->is_null_constant) { + vtn_assert(glsl_type_is_vector_or_scalar(value->type->type)); + nir_ssa_def *const_ssa = + vtn_const_ssa_value(b, value->constant, value->type->type)->def; + return vtn_pointer_from_ssa(b, const_ssa, value->type); + } + vtn_assert(value->value_type == vtn_value_type_pointer); + return value->pointer; +} + +static inline struct vtn_pointer * +vtn_pointer(struct vtn_builder *b, uint32_t value_id) +{ + return vtn_value_to_pointer(b, vtn_pointer_value(b, value_id)); +} + bool vtn_set_instruction_result_type(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count); diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c index f12ed7ec5c3..d2f5118a2ee 100644 --- a/src/compiler/spirv/vtn_variables.c +++ b/src/compiler/spirv/vtn_variables.c @@ -518,7 +518,7 @@ _vtn_local_load_store(struct vtn_builder *b, bool load, nir_deref_instr *deref, nir_deref_instr * vtn_nir_deref(struct vtn_builder *b, uint32_t id) { - struct vtn_pointer *ptr = vtn_value(b, id, vtn_value_type_pointer)->pointer; + struct vtn_pointer *ptr = vtn_pointer(b, id); return vtn_pointer_to_deref(b, ptr); } @@ -2417,8 +2417,8 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } struct vtn_type *ptr_type = vtn_get_type(b, w[1]); - struct vtn_pointer *base = - vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + + struct vtn_pointer *base = vtn_pointer(b, w[3]); /* Workaround for https://gitlab.freedesktop.org/mesa/mesa/-/issues/3406 */ access |= base->access & ACCESS_NON_UNIFORM; @@ -2431,10 +2431,10 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } case SpvOpCopyMemory: { - struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer); - struct vtn_value *src_val = vtn_value(b, w[2], vtn_value_type_pointer); - struct vtn_pointer *dest = dest_val->pointer; - struct vtn_pointer *src = src_val->pointer; + struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); + struct vtn_value *src_val = vtn_pointer_value(b, w[2]); + struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); + struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); vtn_assert_types_equal(b, opcode, dest_val->type->deref, src_val->type->deref); @@ -2463,11 +2463,11 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } case SpvOpCopyMemorySized: { - struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer); - struct vtn_value *src_val = vtn_value(b, w[2], vtn_value_type_pointer); + struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); + struct vtn_value *src_val = vtn_pointer_value(b, w[2]); nir_ssa_def *size = vtn_get_nir_ssa(b, w[3]); - struct vtn_pointer *dest = dest_val->pointer; - struct vtn_pointer *src = src_val->pointer; + struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); + struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); unsigned idx = 4, dest_alignment, src_alignment; SpvMemoryAccessMask dest_access, src_access; @@ -2498,7 +2498,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, case SpvOpLoad: { struct vtn_type *res_type = vtn_get_type(b, w[1]); struct vtn_value *src_val = vtn_value(b, w[3], vtn_value_type_pointer); - struct vtn_pointer *src = src_val->pointer; + struct vtn_pointer *src = vtn_value_to_pointer(b, src_val); vtn_assert_types_equal(b, opcode, res_type, src_val->type->deref); @@ -2515,8 +2515,8 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } case SpvOpStore: { - struct vtn_value *dest_val = vtn_value(b, w[1], vtn_value_type_pointer); - struct vtn_pointer *dest = dest_val->pointer; + struct vtn_value *dest_val = vtn_pointer_value(b, w[1]); + struct vtn_pointer *dest = vtn_value_to_pointer(b, dest_val); struct vtn_value *src_val = vtn_untyped_value(b, w[2]); /* OpStore requires us to actually have a storage type */ @@ -2558,8 +2558,7 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode, } case SpvOpArrayLength: { - struct vtn_pointer *ptr = - vtn_value(b, w[3], vtn_value_type_pointer)->pointer; + struct vtn_pointer *ptr = vtn_pointer(b, w[3]); const uint32_t field = w[4]; vtn_fail_if(ptr->type->base_type != vtn_base_type_struct,