From ed20e69b0c110aabb0d7d2a535641730db993901 Mon Sep 17 00:00:00 2001 From: Connor Abbott Date: Mon, 7 Dec 2020 14:54:25 +0100 Subject: [PATCH] vtn: Handle ZeroExtend/SignExtend image operands These decorations allow you to override the signedness of image instructions. This means that we have to override the type we get from the sampled image. Apparently both Intel and AMD get the type from the descriptor rather than the instruction, but this appears to not be the case with Adreno, which is why this wasn't noticed until now. So this probably won't fix any preexisting bugs, but it's required to fix dEQP-VK.image.extend_operands_spirv1p4.* when exposing VK_KHR_spirv_1_4 on turnip. Reviewed-by: Jason Ekstrand Part-of: --- src/compiler/spirv/spirv_to_nir.c | 47 +++++++++++++++++++++++++------ 1 file changed, 38 insertions(+), 9 deletions(-) diff --git a/src/compiler/spirv/spirv_to_nir.c b/src/compiler/spirv/spirv_to_nir.c index d79582b16b2..b261a3e081e 100644 --- a/src/compiler/spirv/spirv_to_nir.c +++ b/src/compiler/spirv/spirv_to_nir.c @@ -2542,6 +2542,28 @@ non_uniform_decoration_cb(struct vtn_builder *b, } } +/* Apply SignExtend/ZeroExtend operands to get the actual result type for + * image read/sample operations and source type for write operations. + */ +static nir_alu_type +get_image_type(struct vtn_builder *b, nir_alu_type type, unsigned operands) +{ + unsigned extend_operands = + operands & (SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask); + vtn_fail_if(nir_alu_type_get_base_type(type) == nir_type_float && extend_operands, + "SignExtend/ZeroExtend used on floating-point texel type"); + vtn_fail_if(extend_operands == + (SpvImageOperandsSignExtendMask | SpvImageOperandsZeroExtendMask), + "SignExtend and ZeroExtend both specified"); + + if (operands & SpvImageOperandsSignExtendMask) + return nir_type_int | nir_alu_type_get_type_size(type); + if (operands & SpvImageOperandsZeroExtendMask) + return nir_type_uint | nir_alu_type_get_type_size(type); + + return type; +} + static void vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, const uint32_t *w, unsigned count) @@ -2826,8 +2848,9 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, /* Now we need to handle some number of optional arguments */ struct vtn_value *gather_offsets = NULL; + uint32_t operands = SpvImageOperandsMaskNone; if (idx < count) { - uint32_t operands = w[idx]; + operands = w[idx]; if (operands & SpvImageOperandsBiasMask) { vtn_assert(texop == nir_texop_tex || @@ -2958,6 +2981,7 @@ vtn_handle_texture(struct vtn_builder *b, SpvOp opcode, "SPIR-V return type mismatches image type. This is only valid " "for untyped images (OpenCL)."); dest_type = nir_get_nir_type_for_glsl_base_type(ret_base); + dest_type = get_image_type(b, dest_type, operands); } instr->dest_type = dest_type; @@ -3104,6 +3128,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, struct vtn_image_pointer image; SpvScope scope = SpvScopeInvocation; SpvMemorySemanticsMask semantics = 0; + SpvImageOperandsMask operands = SpvImageOperandsMaskNone; enum gl_access_qualifier access = 0; @@ -3174,8 +3199,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, image.image = vtn_get_image(b, w[3], &access); image.coord = get_image_coord(b, w[4]); - const SpvImageOperandsMask operands = - count > 5 ? w[5] : SpvImageOperandsMaskNone; + operands = count > 5 ? w[5] : SpvImageOperandsMaskNone; if (operands & SpvImageOperandsSampleMask) { uint32_t arg = image_operand_arg(b, w, count, 5, @@ -3215,8 +3239,7 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, /* texel = w[3] */ - const SpvImageOperandsMask operands = - count > 4 ? w[4] : SpvImageOperandsMaskNone; + operands = count > 4 ? w[4] : SpvImageOperandsMaskNone; if (operands & SpvImageOperandsSampleMask) { uint32_t arg = image_operand_arg(b, w, count, 4, @@ -3364,8 +3387,11 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, */ intrin->src[4] = nir_src_for_ssa(image.lod); - if (opcode == SpvOpImageWrite) - nir_intrinsic_set_src_type(intrin, nir_get_nir_type_for_glsl_type(value->type)); + if (opcode == SpvOpImageWrite) { + nir_alu_type src_type = + get_image_type(b, nir_get_nir_type_for_glsl_type(value->type), operands); + nir_intrinsic_set_src_type(intrin, src_type); + } break; } @@ -3442,8 +3468,11 @@ vtn_handle_image(struct vtn_builder *b, SpvOp opcode, vtn_push_nir_ssa(b, w[2], result); } - if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead) - nir_intrinsic_set_dest_type(intrin, nir_get_nir_type_for_glsl_type(type->type)); + if (opcode == SpvOpImageRead || opcode == SpvOpImageSparseRead) { + nir_alu_type dest_type = + get_image_type(b, nir_get_nir_type_for_glsl_type(type->type), operands); + nir_intrinsic_set_dest_type(intrin, dest_type); + } } else { nir_builder_instr_insert(&b->nb, &intrin->instr); }