spirv: allow offset_and_cast for vectors when possible

This commit is contained in:
Ali Cheraghi 2025-04-25 03:02:20 +03:30
parent fc55c1b7a1
commit 296b17f37b

View File

@ -1065,6 +1065,7 @@ const NavGen = struct {
fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {
const pt = self.pt;
const zcu = pt.zcu;
switch (derivation) {
.comptime_alloc_ptr, .comptime_field_ptr => unreachable,
.int => |int| {
@ -1104,23 +1105,36 @@ const NavGen = struct {
.offset_and_cast => |oac| {
const parent_ptr_id = try self.derivePtr(oac.parent.*);
const parent_ptr_ty = try oac.parent.ptrType(pt);
disallow: {
if (oac.byte_offset != 0) break :disallow;
// Allow changing the pointer type child only to restructure arrays.
// e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
const result_ptr_id = self.spv.allocId();
try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
.id_result_type = result_ty_id,
.id_result = result_ptr_id,
.operand = parent_ptr_id,
});
return result_ptr_id;
const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
if (oac.byte_offset != 0) {
const child_size = oac.new_ptr_ty.childType(zcu).abiSize(zcu);
if (oac.byte_offset % child_size != 0) {
return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
parent_ptr_ty.fmt(pt),
oac.new_ptr_ty.fmt(pt),
});
}
// Vector element ptr accesses are derived as offset_and_cast.
// We can just use OpAccessChain.
assert(parent_ptr_ty.childType(zcu).zigTypeTag(zcu) == .vector);
return self.accessChain(
result_ty_id,
parent_ptr_id,
&.{@intCast(@divExact(oac.byte_offset, child_size))},
);
}
return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
parent_ptr_ty.fmt(pt),
oac.new_ptr_ty.fmt(pt),
// Allow changing the pointer type child only to restructure arrays.
// e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
const result_ptr_id = self.spv.allocId();
try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
.id_result_type = result_ty_id,
.id_result = result_ptr_id,
.operand = parent_ptr_id,
});
return result_ptr_id;
},
}
}