summaryrefslogtreecommitdiffstats
path: root/src/compiler/spirv/vtn_variables.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/compiler/spirv/vtn_variables.c')
-rw-r--r--src/compiler/spirv/vtn_variables.c73
1 files changed, 73 insertions, 0 deletions
diff --git a/src/compiler/spirv/vtn_variables.c b/src/compiler/spirv/vtn_variables.c
index 17f067133dd..4f7e2a15af9 100644
--- a/src/compiler/spirv/vtn_variables.c
+++ b/src/compiler/spirv/vtn_variables.c
@@ -2150,6 +2150,44 @@ vtn_assert_types_equal(struct vtn_builder *b, SpvOp opcode,
glsl_get_type_name(src_type->type));
}
+static nir_ssa_def *
+nir_shrink_zero_pad_vec(nir_builder *b, nir_ssa_def *val,
+ unsigned num_components)
+{
+ if (val->num_components == num_components)
+ return val;
+
+ nir_ssa_def *comps[NIR_MAX_VEC_COMPONENTS];
+ for (unsigned i = 0; i < num_components; i++) {
+ if (i < val->num_components)
+ comps[i] = nir_channel(b, val, i);
+ else
+ comps[i] = nir_imm_intN_t(b, 0, val->bit_size);
+ }
+ return nir_vec(b, comps, num_components);
+}
+
+static nir_ssa_def *
+nir_sloppy_bitcast(nir_builder *b, nir_ssa_def *val,
+ const struct glsl_type *type)
+{
+ const unsigned num_components = glsl_get_vector_elements(type);
+ const unsigned bit_size = glsl_get_bit_size(type);
+
+ /* First, zero-pad to ensure that the value is big enough that when we
+ * bit-cast it, we don't loose anything.
+ */
+ if (val->bit_size < bit_size) {
+ const unsigned src_num_components_needed =
+ vtn_align_u32(val->num_components, bit_size / val->bit_size);
+ val = nir_shrink_zero_pad_vec(b, val, src_num_components_needed);
+ }
+
+ val = nir_bitcast_vector(b, val, bit_size);
+
+ return nir_shrink_zero_pad_vec(b, val, num_components);
+}
+
void
vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
const uint32_t *w, unsigned count)
@@ -2352,6 +2390,41 @@ vtn_handle_variables(struct vtn_builder *b, SpvOp opcode,
break;
}
+ case SpvOpConvertPtrToU: {
+ struct vtn_value *u_val = vtn_push_value(b, w[2], vtn_value_type_ssa);
+
+ vtn_fail_if(u_val->type->base_type != vtn_base_type_vector &&
+ u_val->type->base_type != vtn_base_type_scalar,
+ "OpConvertPtrToU can only be used to cast to a vector or "
+ "scalar type");
+
+ /* The pointer will be converted to an SSA value automatically */
+ nir_ssa_def *ptr_ssa = vtn_ssa_value(b, w[3])->def;
+
+ u_val->ssa = vtn_create_ssa_value(b, u_val->type->type);
+ u_val->ssa->def = nir_sloppy_bitcast(&b->nb, ptr_ssa, u_val->type->type);
+ break;
+ }
+
+ case SpvOpConvertUToPtr: {
+ struct vtn_value *ptr_val =
+ vtn_push_value(b, w[2], vtn_value_type_pointer);
+ struct vtn_value *u_val = vtn_value(b, w[3], vtn_value_type_ssa);
+
+ vtn_fail_if(ptr_val->type->type == NULL,
+ "OpConvertUToPtr can only be used on physical pointers");
+
+ vtn_fail_if(u_val->type->base_type != vtn_base_type_vector &&
+ u_val->type->base_type != vtn_base_type_scalar,
+ "OpConvertUToPtr can only be used to cast from a vector or "
+ "scalar type");
+
+ nir_ssa_def *ptr_ssa = nir_sloppy_bitcast(&b->nb, u_val->ssa->def,
+ ptr_val->type->type);
+ ptr_val->pointer = vtn_pointer_from_ssa(b, ptr_ssa, ptr_val->type);
+ break;
+ }
+
case SpvOpCopyMemorySized:
default:
vtn_fail("Unhandled opcode");