authorgravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2024-02-01 19:38:23+03:30
committergravatar for alichraghi@proton.meAli Chraghi <alichraghi@proton.me> 2024-02-05 11:55:14+03:30
logb41aad019364b2c99934339d70aa4f37d945f248
tree276d1ace6840a8e25eccb838e744b8e3c2231333
parentafa779335186acf10f79848775afaf55698d8d88

spirv: emit vectors whenever we can


2 files changed, 59 insertions(+), 7 deletions(-)

src/codegen/spirv.zig+52-7
...@@ -744,6 +744,30 @@ const DeclGen = struct {...@@ -744,6 +744,30 @@ const DeclGen = struct {
744 return try self.load(ty, ptr_composite_id, .{});744 return try self.load(ty, ptr_composite_id, .{});
745 }745 }
746746
747 /// Construct a vector at runtime.
748 /// ty must be an vector type.
749 /// Constituents should be in `indirect` representation (as the elements of an vector should be).
750 /// Result is in `direct` representation.
751 fn constructVector(self: *DeclGen, ty: Type, constituents: []const IdRef) !IdRef {
752 // The Khronos LLVM-SPIRV translator crashes because it cannot construct structs which'
753 // operands are not constant.
754 // See https://github.com/KhronosGroup/SPIRV-LLVM-Translator/issues/1349
755 // For now, just initialize the struct by setting the fields manually...
756 // TODO: Make this OpCompositeConstruct when we can
757 const mod = self.module;
758 const ptr_composite_id = try self.alloc(ty, .{ .storage_class = .Function });
759 const ptr_elem_ty_ref = try self.ptrType(ty.elemType2(mod), .Function);
760 for (constituents, 0..) |constitent_id, index| {
761 const ptr_id = try self.accessChain(ptr_elem_ty_ref, ptr_composite_id, &.{@as(u32, @intCast(index))});
762 try self.func.body.emit(self.spv.gpa, .OpStore, .{
763 .pointer = ptr_id,
764 .object = constitent_id,
765 });
766 }
767
768 return try self.load(ty, ptr_composite_id, .{});
769 }
770
747 /// Construct an array at runtime.771 /// Construct an array at runtime.
748 /// ty must be an array type.772 /// ty must be an array type.
749 /// Constituents should be in `indirect` representation (as the elements of an array should be).773 /// Constituents should be in `indirect` representation (as the elements of an array should be).
...@@ -963,13 +987,16 @@ const DeclGen = struct {...@@ -963,13 +987,16 @@ const DeclGen = struct {
963 }987 }
964988
965 switch (tag) {989 switch (tag) {
966 inline .array_type => if (array_type.sentinel != .none) {990 inline .array_type => {
967 constituents[constituents.len - 1] = try self.constant(elem_ty, Value.fromInterned(array_type.sentinel), .indirect);991 if (array_type.sentinel != .none) {
992 const sentinel = Value.fromInterned(array_type.sentinel);
993 constituents[constituents.len - 1] = try self.constant(elem_ty, sentinel, .indirect);
994 }
995 return self.constructArray(ty, constituents);
968 },996 },
969 else => {},997 inline .vector_type => return self.constructVector(ty, constituents),
998 else => unreachable,
970 }999 }
971
972 return try self.constructArray(ty, constituents);
973 },1000 },
974 .struct_type => {1001 .struct_type => {
975 const struct_type = mod.typeToStruct(ty).?;1002 const struct_type = mod.typeToStruct(ty).?;
...@@ -1492,8 +1519,14 @@ const DeclGen = struct {...@@ -1492,8 +1519,14 @@ const DeclGen = struct {
14921519
1493 const elem_ty = ty.childType(mod);1520 const elem_ty = ty.childType(mod);
1494 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);1521 const elem_ty_ref = try self.resolveType(elem_ty, .indirect);
1522 const len = ty.vectorLen(mod);
1523 const is_scalar = elem_ty.isNumeric(mod) or elem_ty.toIntern() == .bool_type;
1524
1525 const ty_ref = if (is_scalar and len > 1 and len <= 4)
1526 try self.spv.vectorType(ty.vectorLen(mod), elem_ty_ref)
1527 else
1528 try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref);
14951529
1496 const ty_ref = try self.spv.arrayType(ty.vectorLen(mod), elem_ty_ref);
1497 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });1530 try self.type_map.put(self.gpa, ty.toIntern(), .{ .ty_ref = ty_ref });
1498 return ty_ref;1531 return ty_ref;
1499 },1532 },
...@@ -3688,7 +3721,19 @@ const DeclGen = struct {...@@ -3688,7 +3721,19 @@ const DeclGen = struct {
3688 constituents[0..index],3721 constituents[0..index],
3689 );3722 );
3690 },3723 },
3691 .Vector, .Array => {3724 .Vector => {
3725 const n_elems = result_ty.vectorLen(mod);
3726 const elem_ids = try self.gpa.alloc(IdRef, n_elems);
3727 defer self.gpa.free(elem_ids);
3728
3729 for (elements, 0..) |element, i| {
3730 const id = try self.resolve(element);
3731 elem_ids[i] = try self.convertToIndirect(result_ty.childType(mod), id);
3732 }
3733
3734 return try self.constructVector(result_ty, elem_ids);
3735 },
3736 .Array => {
3692 const array_info = result_ty.arrayInfo(mod);3737 const array_info = result_ty.arrayInfo(mod);
3693 const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod));3738 const n_elems: usize = @intCast(result_ty.arrayLenIncludingSentinel(mod));
3694 const elem_ids = try self.gpa.alloc(IdRef, n_elems);3739 const elem_ids = try self.gpa.alloc(IdRef, n_elems);
src/codegen/spirv/Module.zig+7
...@@ -508,6 +508,13 @@ pub fn intType(self: *Module, signedness: std.builtin.Signedness, bits: u16) !Ca...@@ -508,6 +508,13 @@ pub fn intType(self: *Module, signedness: std.builtin.Signedness, bits: u16) !Ca
508 } });508 } });
509}509}
510510
511pub fn vectorType(self: *Module, len: u32, elem_ty_ref: CacheRef) !CacheRef {
512 return try self.resolve(.{ .vector_type = .{
513 .component_type = elem_ty_ref,
514 .component_count = len,
515 } });
516}
517
511pub fn arrayType(self: *Module, len: u32, elem_ty_ref: CacheRef) !CacheRef {518pub fn arrayType(self: *Module, len: u32, elem_ty_ref: CacheRef) !CacheRef {
512 const len_ty_ref = try self.resolve(.{ .int_type = .{519 const len_ty_ref = try self.resolve(.{ .int_type = .{
513 .signedness = .unsigned,520 .signedness = .unsigned,