spirv: Add support for OpBitcast in OpSpecConstantOp
Some checks are pending
macOS-CI / macOS-CI (dri) (push) Waiting to run
macOS-CI / macOS-CI (xlib) (push) Waiting to run

This is required for OpenCL but not Vulkan.  This fixes a bunch of
OpenCL CTS fails using the SPIR-V back-end in LLVM as opposed to
SPIRV-LLVM-Translator.

Reviewed-by: Karol Herbst <kherbst@redhat.com>
Cc: mesa-stable
Part-of: <https://gitlab.freedesktop.org/mesa/mesa/-/merge_requests/37555>
This commit is contained in:
Faith Ekstrand 2025-09-24 17:31:50 -04:00 committed by Marge Bot
parent 7df6431bf7
commit 8ef811b02a

View file

@ -2652,6 +2652,54 @@ vtn_handle_constant(struct vtn_builder *b, SpvOp opcode,
vtn_foreach_decoration(b, val, spec_constant_decoration_cb, &u32op);
SpvOp opcode = u32op.u32;
switch (opcode) {
case SpvOpBitcast: {
struct vtn_value *src = &b->values[w[4]];
vtn_assert(src->value_type == vtn_value_type_constant ||
src->value_type == vtn_value_type_undef);
unsigned src_len = glsl_get_vector_elements(src->type->type);
unsigned dst_len = glsl_get_vector_elements(val->type->type);
unsigned src_bit_size = glsl_get_bit_size(src->type->type);
unsigned dst_bit_size = glsl_get_bit_size(val->type->type);
vtn_assert(src_len * src_bit_size == dst_len * dst_bit_size);
/* This will end up being zero */
if (src->value_type == vtn_value_type_undef)
break;
if (src_bit_size == dst_bit_size) {
/* This is just a copy */
for (unsigned i = 0; i < src_len; i++)
val->constant->values[i] = src->constant->values[i];
} else {
/* You can't non-trivially bitcast booleans */
vtn_assert(src_bit_size >= 8 && dst_bit_size >= 8);
const unsigned src_byte_size = src_bit_size / 8;
const unsigned dst_byte_size = dst_bit_size / 8;
vtn_assert(src_len <= NIR_MAX_VEC_COMPONENTS &&
dst_len <= NIR_MAX_VEC_COMPONENTS);
uint8_t bits[NIR_MAX_VEC_COMPONENTS * sizeof(nir_const_value)];
for (unsigned i = 0; i < src_len; i++) {
uint64_t v = nir_const_value_as_int(src->constant->values[i],
src_bit_size);
memcpy(bits + i * src_byte_size, &v, src_byte_size);
}
for (unsigned i = 0; i < dst_len; i++) {
uint64_t v = 0;
memcpy(&v, bits + i * dst_byte_size, dst_byte_size);
val->constant->values[i] =
nir_const_value_for_uint(v, dst_bit_size);
}
}
break;
}
case SpvOpVectorShuffle: {
struct vtn_value *v0 = &b->values[w[4]];
struct vtn_value *v1 = &b->values[w[5]];