authorgravatar for robin@voetter.nlRobin Voetter <robin@voetter.nl> 2024-11-01 03:44:37+01:00
committergravatar for noreply@github.comGitHub <noreply@github.com> 2024-11-01 03:44:37+01:00
logba5f57616f69c01aa6faa5bcabab2d58969cf335
tree8b9b301c895be30f53f74a9a7e70b12cddcb534b
parent3f7fac5fff9beed535a7674679a5e2c1f3cd74d2
parent38345d590949b0c88d83bccb259364f02a59a90e
signaturebadge-check Signed by PGP key B5690EEEBB952194

Merge pull request #21861 from alichraghi/master

spirv: push constants and small fixes

8 files changed, 69 insertions(+), 36 deletions(-)

lib/std/Target.zig+1-1
......@@ -1479,7 +1479,7 @@ pub const Cpu = struct {
14791479 .fs, .gs, .ss => arch == .x86_64 or arch == .x86,
14801480 .global, .constant, .local, .shared => is_gpu,
14811481 .param => is_nvptx,
1482 .input, .output, .uniform => is_spirv,
1482 .input, .output, .uniform, .push_constant => is_spirv,
14831483 // TODO this should also check how many flash banks the cpu has
14841484 .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
14851485
lib/std/builtin.zig+1
......@@ -514,6 +514,7 @@ pub const AddressSpace = enum(u5) {
514514 input,
515515 output,
516516 uniform,
517 push_constant,
517518
518519 // AVR address spaces.
519520 flash,
lib/std/gpu.zig+11
......@@ -47,6 +47,17 @@ pub fn vertexIndex(comptime ptr: *addrspace(.input) u32) void {
4747 );
4848}
4949
50/// Will make `ptr` contain the index of the instance that is
51/// being processed by the current vertex shader invocation.
52/// `ptr` must be a reference to variable or struct field.
53pub fn instanceIndex(comptime ptr: *addrspace(.input) u32) void {
54 asm volatile (
55 \\OpDecorate %ptr BuiltIn InstanceIndex
56 :
57 : [ptr] "" (ptr),
58 );
59}
60
5061/// Output fragment depth from a `Fragment` entrypoint
5162/// `ptr` must be a reference to variable or struct field.
5263pub fn fragmentCoord(comptime ptr: *addrspace(.input) @Vector(4, f32)) void {
src/Sema.zig+1-1
......@@ -37806,7 +37806,7 @@ pub fn analyzeAsAddressSpace(
3780637806 .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer,
3780737807 // TODO: check that .shared and .local are left uninitialized
3780837808 .param => is_nv,
37809 .input, .output, .uniform => is_spirv,
37809 .input, .output, .uniform, .push_constant => is_spirv,
3781037810 .global, .shared, .local => is_gpu,
3781137811 .constant => is_gpu and (ctx == .constant),
3781237812 // TODO this should also check how many flash banks the cpu has
src/codegen/spirv.zig+52-27
......@@ -899,7 +899,7 @@ const NavGen = struct {
899899 const result_ty_id = try self.resolveType(ty, repr);
900900 const ip = &zcu.intern_pool;
901901
902 log.debug("lowering constant: ty = {}, val = {}", .{ ty.fmt(pt), val.fmtValue(pt) });
902 log.debug("lowering constant: ty = {}, val = {}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) });
903903 if (val.isUndefDeep(zcu)) {
904904 return self.spv.constUndef(result_ty_id);
905905 }
......@@ -1169,7 +1169,6 @@ const NavGen = struct {
11691169
11701170 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {
11711171 const pt = self.pt;
1172 const zcu = pt.zcu;
11731172 switch (derivation) {
11741173 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,
11751174 .int => |int| {
......@@ -1213,10 +1212,6 @@ const NavGen = struct {
12131212 if (oac.byte_offset != 0) break :disallow;
12141213 // Allow changing the pointer type child only to restructure arrays.
12151214 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.
1216 const src_base_ty = parent_ptr_ty.arrayBase(zcu)[0];
1217 const dest_base_ty = oac.new_ptr_ty.arrayBase(zcu)[0];
1218 if (self.getTarget().os.tag == .vulkan and src_base_ty.toIntern() != dest_base_ty.toIntern()) break :disallow;
1219
12201215 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
12211216 const result_ptr_id = self.spv.allocId();
12221217 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
......@@ -1226,7 +1221,7 @@ const NavGen = struct {
12261221 });
12271222 return result_ptr_id;
12281223 }
1229 return self.fail("Cannot perform pointer cast: '{}' to '{}'", .{
1224 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
12301225 parent_ptr_ty.fmt(pt),
12311226 oac.new_ptr_ty.fmt(pt),
12321227 });
......@@ -1310,12 +1305,12 @@ const NavGen = struct {
13101305 .global, .invocation_global => spv_decl.result_id,
13111306 };
13121307
1313 const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
1314 try self.addFunctionDep(spv_decl_index, final_storage_class);
1308 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
1309 try self.addFunctionDep(spv_decl_index, storage_class);
13151310
1316 const decl_ptr_ty_id = try self.ptrType(nav_ty, final_storage_class);
1311 const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class);
13171312
1318 const ptr_id = switch (final_storage_class) {
1313 const ptr_id = switch (storage_class) {
13191314 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),
13201315 else => decl_id,
13211316 };
......@@ -1401,6 +1396,10 @@ const NavGen = struct {
14011396
14021397 const child_ty_id = try self.resolveType(child_ty, child_repr);
14031398
1399 if (storage_class == .Uniform or storage_class == .PushConstant) {
1400 try self.spv.decorate(child_ty_id, .Block);
1401 }
1402
14041403 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
14051404 .id_result = result_id,
14061405 .storage_class = storage_class,
......@@ -1505,10 +1504,13 @@ const NavGen = struct {
15051504 member_names[layout.padding_index] = "(padding)";
15061505 }
15071506
1508 const result_id = try self.spv.structType(member_types[0..layout.total_fields], member_names[0..layout.total_fields]);
1507 const result_id = self.spv.allocId();
1508 try self.spv.structType(result_id, member_types[0..layout.total_fields], member_names[0..layout.total_fields]);
1509
15091510 const type_name = try self.resolveTypeName(ty);
15101511 defer self.gpa.free(type_name);
15111512 try self.spv.debugName(result_id, type_name);
1513
15121514 return result_id;
15131515 }
15141516
......@@ -1640,7 +1642,9 @@ const NavGen = struct {
16401642 // can be lowered to ptrAccessChain instead of manually performing the math.
16411643 return try self.arrayType(1, elem_ty_id);
16421644 } else {
1643 return try self.arrayType(total_len, elem_ty_id);
1645 const result_id = try self.arrayType(total_len, elem_ty_id);
1646 try self.spv.decorate(result_id, .{ .ArrayStride = .{ .array_stride = @intCast(elem_ty.abiSize(zcu)) } });
1647 return result_id;
16441648 }
16451649 },
16461650 .@"fn" => switch (repr) {
......@@ -1702,10 +1706,13 @@ const NavGen = struct {
17021706 }
17031707
17041708 const size_ty_id = try self.resolveType(Type.usize, .direct);
1705 return self.spv.structType(
1709 const result_id = self.spv.allocId();
1710 try self.spv.structType(
1711 result_id,
17061712 &.{ ptr_ty_id, size_ty_id },
17071713 &.{ "ptr", "len" },
17081714 );
1715 return result_id;
17091716 },
17101717 .vector => {
17111718 const elem_ty = ty.childType(zcu);
......@@ -1732,10 +1739,13 @@ const NavGen = struct {
17321739 member_index += 1;
17331740 }
17341741
1735 const result_id = try self.spv.structType(member_types[0..member_index], null);
1742 const result_id = self.spv.allocId();
1743 try self.spv.structType(result_id, member_types[0..member_index], null);
1744
17361745 const type_name = try self.resolveTypeName(ty);
17371746 defer self.gpa.free(type_name);
17381747 try self.spv.debugName(result_id, type_name);
1748
17391749 return result_id;
17401750 },
17411751 .struct_type => ip.loadStructType(ty.toIntern()),
......@@ -1752,7 +1762,9 @@ const NavGen = struct {
17521762 var member_names = std.ArrayList([]const u8).init(self.gpa);
17531763 defer member_names.deinit();
17541764
1765 var index: u32 = 0;
17551766 var it = struct_type.iterateRuntimeOrder(ip);
1767 const result_id = self.spv.allocId();
17561768 while (it.next()) |field_index| {
17571769 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
17581770 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
......@@ -1760,16 +1772,25 @@ const NavGen = struct {
17601772 continue;
17611773 }
17621774
1775 if (target.os.tag == .vulkan) {
1776 try self.spv.decorateMember(result_id, index, .{ .Offset = .{
1777 .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)),
1778 } });
1779 }
17631780 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
17641781 try ip.getOrPutStringFmt(zcu.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
17651782 try member_types.append(try self.resolveType(field_ty, .indirect));
17661783 try member_names.append(field_name.toSlice(ip));
1784
1785 index += 1;
17671786 }
17681787
1769 const result_id = try self.spv.structType(member_types.items, member_names.items);
1788 try self.spv.structType(result_id, member_types.items, member_names.items);
1789
17701790 const type_name = try self.resolveTypeName(ty);
17711791 defer self.gpa.free(type_name);
17721792 try self.spv.debugName(result_id, type_name);
1793
17731794 return result_id;
17741795 },
17751796 .optional => {
......@@ -1789,10 +1810,13 @@ const NavGen = struct {
17891810
17901811 const bool_ty_id = try self.resolveType(Type.bool, .indirect);
17911812
1792 return try self.spv.structType(
1813 const result_id = self.spv.allocId();
1814 try self.spv.structType(
1815 result_id,
17931816 &.{ payload_ty_id, bool_ty_id },
17941817 &.{ "payload", "valid" },
17951818 );
1819 return result_id;
17961820 },
17971821 .@"union" => return try self.resolveUnionType(ty),
17981822 .error_set => return try self.resolveType(Type.u16, repr),
......@@ -1821,7 +1845,9 @@ const NavGen = struct {
18211845 // TODO: ABI padding?
18221846 }
18231847
1824 return try self.spv.structType(&member_types, &member_names);
1848 const result_id = self.spv.allocId();
1849 try self.spv.structType(result_id, &member_types, &member_names);
1850 return result_id;
18251851 },
18261852 .@"opaque" => {
18271853 const type_name = try self.resolveTypeName(ty);
......@@ -1851,7 +1877,7 @@ const NavGen = struct {
18511877 const target = self.getTarget();
18521878 return switch (as) {
18531879 .generic => switch (target.os.tag) {
1854 .vulkan => .Private,
1880 .vulkan => .Function,
18551881 .opencl => .Generic,
18561882 else => unreachable,
18571883 },
......@@ -1863,6 +1889,7 @@ const NavGen = struct {
18631889 else => unreachable,
18641890 },
18651891 .constant => .UniformConstant,
1892 .push_constant => .PushConstant,
18661893 .input => .Input,
18671894 .output => .Output,
18681895 .uniform => .Uniform,
......@@ -2954,10 +2981,8 @@ const NavGen = struct {
29542981 const spv_err_decl_index = try self.spv.allocDecl(.global);
29552982 try self.spv.declareDeclDeps(spv_err_decl_index, &.{});
29562983
2957 const push_constant_struct_ty_id = try self.spv.structType(
2958 &.{ptr_anyerror_ty_id},
2959 &.{"error_out_ptr"},
2960 );
2984 const push_constant_struct_ty_id = self.spv.allocId();
2985 try self.spv.structType(push_constant_struct_ty_id, &.{ptr_anyerror_ty_id}, &.{"error_out_ptr"});
29612986 try self.spv.decorate(push_constant_struct_ty_id, .Block);
29622987 try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } });
29632988
......@@ -3141,15 +3166,15 @@ const NavGen = struct {
31413166 };
31423167 assert(maybe_init_val == null); // TODO
31433168
3144 const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
3145 assert(final_storage_class != .Generic); // These should be instance globals
3169 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
3170 assert(storage_class != .Generic); // These should be instance globals
31463171
3147 const ptr_ty_id = try self.ptrType(ty, final_storage_class);
3172 const ptr_ty_id = try self.ptrType(ty, storage_class);
31483173
31493174 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
31503175 .id_result_type = ptr_ty_id,
31513176 .id_result = result_id,
3152 .storage_class = final_storage_class,
3177 .storage_class = storage_class,
31533178 });
31543179
31553180 try self.spv.debugName(result_id, nav.fqn.toSlice(ip));
src/codegen/spirv/Module.zig+1-5
......@@ -402,9 +402,7 @@ pub fn resolveString(self: *Module, string: []const u8) !IdRef {
402402 return id;
403403}
404404
405pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []const u8) !IdRef {
406 const result_id = self.allocId();
407
405pub fn structType(self: *Module, result_id: IdResult, types: []const IdRef, maybe_names: ?[]const []const u8) !void {
408406 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeStruct, .{
409407 .id_result = result_id,
410408 .id_ref = types,
......@@ -416,8 +414,6 @@ pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []c
416414 try self.memberDebugName(result_id, @intCast(i), name);
417415 }
418416 }
419
420 return result_id;
421417}
422418
423419pub fn boolType(self: *Module) !IdRef {
src/link/SpirV.zig+1-1
......@@ -296,7 +296,7 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void {
296296 // TODO: Integrate with a hypothetical feature system
297297 const caps: []const spec.Capability = switch (target.os.tag) {
298298 .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .Vector16, .GenericPointer },
299 .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .StoragePushConstant16, .Int8, .Int16, .Int64, .Float64, .Float16 },
299 .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .Int8, .Int16, .Int64, .Float64, .Float16 },
300300 else => unreachable,
301301 };
302302
src/target.zig+1-1
......@@ -418,7 +418,7 @@ pub fn arePointersLogical(target: std.Target, as: AddressSpace) bool {
418418 .global => false,
419419 // TODO: Allowed with VK_KHR_variable_pointers.
420420 .shared => true,
421 .constant, .local, .input, .output, .uniform => true,
421 .constant, .local, .input, .output, .uniform, .push_constant => true,
422422 else => unreachable,
423423 };
424424}