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 <jason@jlekstrand.net>
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/7968>
This commit is contained in:
Connor Abbott 2020-12-07 14:54:25 +01:00 committed by Marge Bot
parent 07546c69b0
commit ed20e69b0c
1 changed files with 38 additions and 9 deletions

View File

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