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); }