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 {...@@ -1479,7 +1479,7 @@ pub const Cpu = struct {
1479 .fs, .gs, .ss => arch == .x86_64 or arch == .x86,1479 .fs, .gs, .ss => arch == .x86_64 or arch == .x86,
1480 .global, .constant, .local, .shared => is_gpu,1480 .global, .constant, .local, .shared => is_gpu,
1481 .param => is_nvptx,1481 .param => is_nvptx,
1482 .input, .output, .uniform => is_spirv,1482 .input, .output, .uniform, .push_constant => is_spirv,
1483 // TODO this should also check how many flash banks the cpu has1483 // TODO this should also check how many flash banks the cpu has
1484 .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,1484 .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr,
14851485
lib/std/builtin.zig+1
...@@ -514,6 +514,7 @@ pub const AddressSpace = enum(u5) {...@@ -514,6 +514,7 @@ pub const AddressSpace = enum(u5) {
514 input,514 input,
515 output,515 output,
516 uniform,516 uniform,
517 push_constant,
517518
518 // AVR address spaces.519 // AVR address spaces.
519 flash,520 flash,
lib/std/gpu.zig+11
...@@ -47,6 +47,17 @@ pub fn vertexIndex(comptime ptr: *addrspace(.input) u32) void {...@@ -47,6 +47,17 @@ pub fn vertexIndex(comptime ptr: *addrspace(.input) u32) void {
47 );47 );
48}48}
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
50/// Output fragment depth from a `Fragment` entrypoint61/// Output fragment depth from a `Fragment` entrypoint
51/// `ptr` must be a reference to variable or struct field.62/// `ptr` must be a reference to variable or struct field.
52pub fn fragmentCoord(comptime ptr: *addrspace(.input) @Vector(4, f32)) void {63pub fn fragmentCoord(comptime ptr: *addrspace(.input) @Vector(4, f32)) void {
src/Sema.zig+1-1
...@@ -37806,7 +37806,7 @@ pub fn analyzeAsAddressSpace(...@@ -37806,7 +37806,7 @@ pub fn analyzeAsAddressSpace(
37806 .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer,37806 .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer,
37807 // TODO: check that .shared and .local are left uninitialized37807 // TODO: check that .shared and .local are left uninitialized
37808 .param => is_nv,37808 .param => is_nv,
37809 .input, .output, .uniform => is_spirv,37809 .input, .output, .uniform, .push_constant => is_spirv,
37810 .global, .shared, .local => is_gpu,37810 .global, .shared, .local => is_gpu,
37811 .constant => is_gpu and (ctx == .constant),37811 .constant => is_gpu and (ctx == .constant),
37812 // TODO this should also check how many flash banks the cpu has37812 // 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 {...@@ -899,7 +899,7 @@ const NavGen = struct {
899 const result_ty_id = try self.resolveType(ty, repr);899 const result_ty_id = try self.resolveType(ty, repr);
900 const ip = &zcu.intern_pool;900 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())) });
903 if (val.isUndefDeep(zcu)) {903 if (val.isUndefDeep(zcu)) {
904 return self.spv.constUndef(result_ty_id);904 return self.spv.constUndef(result_ty_id);
905 }905 }
...@@ -1169,7 +1169,6 @@ const NavGen = struct {...@@ -1169,7 +1169,6 @@ const NavGen = struct {
11691169
1170 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {1170 fn derivePtr(self: *NavGen, derivation: Value.PointerDeriveStep) Error!IdRef {
1171 const pt = self.pt;1171 const pt = self.pt;
1172 const zcu = pt.zcu;
1173 switch (derivation) {1172 switch (derivation) {
1174 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,1173 .comptime_alloc_ptr, .comptime_field_ptr => unreachable,
1175 .int => |int| {1174 .int => |int| {
...@@ -1213,10 +1212,6 @@ const NavGen = struct {...@@ -1213,10 +1212,6 @@ const NavGen = struct {
1213 if (oac.byte_offset != 0) break :disallow;1212 if (oac.byte_offset != 0) break :disallow;
1214 // Allow changing the pointer type child only to restructure arrays.1213 // Allow changing the pointer type child only to restructure arrays.
1215 // e.g. [3][2]T to T is fine, as is [2]T -> [2][1]T.1214 // 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
1220 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);1215 const result_ty_id = try self.resolveType(oac.new_ptr_ty, .direct);
1221 const result_ptr_id = self.spv.allocId();1216 const result_ptr_id = self.spv.allocId();
1222 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{1217 try self.func.body.emit(self.spv.gpa, .OpBitcast, .{
...@@ -1226,7 +1221,7 @@ const NavGen = struct {...@@ -1226,7 +1221,7 @@ const NavGen = struct {
1226 });1221 });
1227 return result_ptr_id;1222 return result_ptr_id;
1228 }1223 }
1229 return self.fail("Cannot perform pointer cast: '{}' to '{}'", .{1224 return self.fail("cannot perform pointer cast: '{}' to '{}'", .{
1230 parent_ptr_ty.fmt(pt),1225 parent_ptr_ty.fmt(pt),
1231 oac.new_ptr_ty.fmt(pt),1226 oac.new_ptr_ty.fmt(pt),
1232 });1227 });
...@@ -1310,12 +1305,12 @@ const NavGen = struct {...@@ -1310,12 +1305,12 @@ const NavGen = struct {
1310 .global, .invocation_global => spv_decl.result_id,1305 .global, .invocation_global => spv_decl.result_id,
1311 };1306 };
13121307
1313 const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");1308 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
1314 try self.addFunctionDep(spv_decl_index, final_storage_class);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) {
1319 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),1314 .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id),
1320 else => decl_id,1315 else => decl_id,
1321 };1316 };
...@@ -1401,6 +1396,10 @@ const NavGen = struct {...@@ -1401,6 +1396,10 @@ const NavGen = struct {
14011396
1402 const child_ty_id = try self.resolveType(child_ty, child_repr);1397 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
1404 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{1403 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{
1405 .id_result = result_id,1404 .id_result = result_id,
1406 .storage_class = storage_class,1405 .storage_class = storage_class,
...@@ -1505,10 +1504,13 @@ const NavGen = struct {...@@ -1505,10 +1504,13 @@ const NavGen = struct {
1505 member_names[layout.padding_index] = "(padding)";1504 member_names[layout.padding_index] = "(padding)";
1506 }1505 }
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
1509 const type_name = try self.resolveTypeName(ty);1510 const type_name = try self.resolveTypeName(ty);
1510 defer self.gpa.free(type_name);1511 defer self.gpa.free(type_name);
1511 try self.spv.debugName(result_id, type_name);1512 try self.spv.debugName(result_id, type_name);
1513
1512 return result_id;1514 return result_id;
1513 }1515 }
15141516
...@@ -1640,7 +1642,9 @@ const NavGen = struct {...@@ -1640,7 +1642,9 @@ const NavGen = struct {
1640 // can be lowered to ptrAccessChain instead of manually performing the math.1642 // can be lowered to ptrAccessChain instead of manually performing the math.
1641 return try self.arrayType(1, elem_ty_id);1643 return try self.arrayType(1, elem_ty_id);
1642 } else {1644 } 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;
1644 }1648 }
1645 },1649 },
1646 .@"fn" => switch (repr) {1650 .@"fn" => switch (repr) {
...@@ -1702,10 +1706,13 @@ const NavGen = struct {...@@ -1702,10 +1706,13 @@ const NavGen = struct {
1702 }1706 }
17031707
1704 const size_ty_id = try self.resolveType(Type.usize, .direct);1708 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,
1706 &.{ ptr_ty_id, size_ty_id },1712 &.{ ptr_ty_id, size_ty_id },
1707 &.{ "ptr", "len" },1713 &.{ "ptr", "len" },
1708 );1714 );
1715 return result_id;
1709 },1716 },
1710 .vector => {1717 .vector => {
1711 const elem_ty = ty.childType(zcu);1718 const elem_ty = ty.childType(zcu);
...@@ -1732,10 +1739,13 @@ const NavGen = struct {...@@ -1732,10 +1739,13 @@ const NavGen = struct {
1732 member_index += 1;1739 member_index += 1;
1733 }1740 }
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
1736 const type_name = try self.resolveTypeName(ty);1745 const type_name = try self.resolveTypeName(ty);
1737 defer self.gpa.free(type_name);1746 defer self.gpa.free(type_name);
1738 try self.spv.debugName(result_id, type_name);1747 try self.spv.debugName(result_id, type_name);
1748
1739 return result_id;1749 return result_id;
1740 },1750 },
1741 .struct_type => ip.loadStructType(ty.toIntern()),1751 .struct_type => ip.loadStructType(ty.toIntern()),
...@@ -1752,7 +1762,9 @@ const NavGen = struct {...@@ -1752,7 +1762,9 @@ const NavGen = struct {
1752 var member_names = std.ArrayList([]const u8).init(self.gpa);1762 var member_names = std.ArrayList([]const u8).init(self.gpa);
1753 defer member_names.deinit();1763 defer member_names.deinit();
17541764
1765 var index: u32 = 0;
1755 var it = struct_type.iterateRuntimeOrder(ip);1766 var it = struct_type.iterateRuntimeOrder(ip);
1767 const result_id = self.spv.allocId();
1756 while (it.next()) |field_index| {1768 while (it.next()) |field_index| {
1757 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);1769 const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]);
1758 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {1770 if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) {
...@@ -1760,16 +1772,25 @@ const NavGen = struct {...@@ -1760,16 +1772,25 @@ const NavGen = struct {
1760 continue;1772 continue;
1761 }1773 }
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 }
1763 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse1780 const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse
1764 try ip.getOrPutStringFmt(zcu.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);1781 try ip.getOrPutStringFmt(zcu.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls);
1765 try member_types.append(try self.resolveType(field_ty, .indirect));1782 try member_types.append(try self.resolveType(field_ty, .indirect));
1766 try member_names.append(field_name.toSlice(ip));1783 try member_names.append(field_name.toSlice(ip));
1784
1785 index += 1;
1767 }1786 }
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
1770 const type_name = try self.resolveTypeName(ty);1790 const type_name = try self.resolveTypeName(ty);
1771 defer self.gpa.free(type_name);1791 defer self.gpa.free(type_name);
1772 try self.spv.debugName(result_id, type_name);1792 try self.spv.debugName(result_id, type_name);
1793
1773 return result_id;1794 return result_id;
1774 },1795 },
1775 .optional => {1796 .optional => {
...@@ -1789,10 +1810,13 @@ const NavGen = struct {...@@ -1789,10 +1810,13 @@ const NavGen = struct {
17891810
1790 const bool_ty_id = try self.resolveType(Type.bool, .indirect);1811 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,
1793 &.{ payload_ty_id, bool_ty_id },1816 &.{ payload_ty_id, bool_ty_id },
1794 &.{ "payload", "valid" },1817 &.{ "payload", "valid" },
1795 );1818 );
1819 return result_id;
1796 },1820 },
1797 .@"union" => return try self.resolveUnionType(ty),1821 .@"union" => return try self.resolveUnionType(ty),
1798 .error_set => return try self.resolveType(Type.u16, repr),1822 .error_set => return try self.resolveType(Type.u16, repr),
...@@ -1821,7 +1845,9 @@ const NavGen = struct {...@@ -1821,7 +1845,9 @@ const NavGen = struct {
1821 // TODO: ABI padding?1845 // TODO: ABI padding?
1822 }1846 }
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;
1825 },1851 },
1826 .@"opaque" => {1852 .@"opaque" => {
1827 const type_name = try self.resolveTypeName(ty);1853 const type_name = try self.resolveTypeName(ty);
...@@ -1851,7 +1877,7 @@ const NavGen = struct {...@@ -1851,7 +1877,7 @@ const NavGen = struct {
1851 const target = self.getTarget();1877 const target = self.getTarget();
1852 return switch (as) {1878 return switch (as) {
1853 .generic => switch (target.os.tag) {1879 .generic => switch (target.os.tag) {
1854 .vulkan => .Private,1880 .vulkan => .Function,
1855 .opencl => .Generic,1881 .opencl => .Generic,
1856 else => unreachable,1882 else => unreachable,
1857 },1883 },
...@@ -1863,6 +1889,7 @@ const NavGen = struct {...@@ -1863,6 +1889,7 @@ const NavGen = struct {
1863 else => unreachable,1889 else => unreachable,
1864 },1890 },
1865 .constant => .UniformConstant,1891 .constant => .UniformConstant,
1892 .push_constant => .PushConstant,
1866 .input => .Input,1893 .input => .Input,
1867 .output => .Output,1894 .output => .Output,
1868 .uniform => .Uniform,1895 .uniform => .Uniform,
...@@ -2954,10 +2981,8 @@ const NavGen = struct {...@@ -2954,10 +2981,8 @@ const NavGen = struct {
2954 const spv_err_decl_index = try self.spv.allocDecl(.global);2981 const spv_err_decl_index = try self.spv.allocDecl(.global);
2955 try self.spv.declareDeclDeps(spv_err_decl_index, &.{});2982 try self.spv.declareDeclDeps(spv_err_decl_index, &.{});
29562983
2957 const push_constant_struct_ty_id = try self.spv.structType(2984 const push_constant_struct_ty_id = self.spv.allocId();
2958 &.{ptr_anyerror_ty_id},2985 try self.spv.structType(push_constant_struct_ty_id, &.{ptr_anyerror_ty_id}, &.{"error_out_ptr"});
2959 &.{"error_out_ptr"},
2960 );
2961 try self.spv.decorate(push_constant_struct_ty_id, .Block);2986 try self.spv.decorate(push_constant_struct_ty_id, .Block);
2962 try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } });2987 try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } });
29632988
...@@ -3141,15 +3166,15 @@ const NavGen = struct {...@@ -3141,15 +3166,15 @@ const NavGen = struct {
3141 };3166 };
3142 assert(maybe_init_val == null); // TODO3167 assert(maybe_init_val == null); // TODO
31433168
3144 const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");3169 const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace");
3145 assert(final_storage_class != .Generic); // These should be instance globals3170 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
3149 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{3174 try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{
3150 .id_result_type = ptr_ty_id,3175 .id_result_type = ptr_ty_id,
3151 .id_result = result_id,3176 .id_result = result_id,
3152 .storage_class = final_storage_class,3177 .storage_class = storage_class,
3153 });3178 });
31543179
3155 try self.spv.debugName(result_id, nav.fqn.toSlice(ip));3180 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 {...@@ -402,9 +402,7 @@ pub fn resolveString(self: *Module, string: []const u8) !IdRef {
402 return id;402 return id;
403}403}
404404
405pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []const u8) !IdRef {405pub fn structType(self: *Module, result_id: IdResult, types: []const IdRef, maybe_names: ?[]const []const u8) !void {
406 const result_id = self.allocId();
407
408 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeStruct, .{406 try self.sections.types_globals_constants.emit(self.gpa, .OpTypeStruct, .{
409 .id_result = result_id,407 .id_result = result_id,
410 .id_ref = types,408 .id_ref = types,
...@@ -416,8 +414,6 @@ pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []c...@@ -416,8 +414,6 @@ pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []c
416 try self.memberDebugName(result_id, @intCast(i), name);414 try self.memberDebugName(result_id, @intCast(i), name);
417 }415 }
418 }416 }
419
420 return result_id;
421}417}
422418
423pub fn boolType(self: *Module) !IdRef {419pub fn boolType(self: *Module) !IdRef {
src/link/SpirV.zig+1-1
...@@ -296,7 +296,7 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void {...@@ -296,7 +296,7 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void {
296 // TODO: Integrate with a hypothetical feature system296 // TODO: Integrate with a hypothetical feature system
297 const caps: []const spec.Capability = switch (target.os.tag) {297 const caps: []const spec.Capability = switch (target.os.tag) {
298 .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .Vector16, .GenericPointer },298 .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 },
300 else => unreachable,300 else => unreachable,
301 };301 };
302302
src/target.zig+1-1
...@@ -418,7 +418,7 @@ pub fn arePointersLogical(target: std.Target, as: AddressSpace) bool {...@@ -418,7 +418,7 @@ pub fn arePointersLogical(target: std.Target, as: AddressSpace) bool {
418 .global => false,418 .global => false,
419 // TODO: Allowed with VK_KHR_variable_pointers.419 // TODO: Allowed with VK_KHR_variable_pointers.
420 .shared => true,420 .shared => true,
421 .constant, .local, .input, .output, .uniform => true,421 .constant, .local, .input, .output, .uniform, .push_constant => true,
422 else => unreachable,422 else => unreachable,
423 };423 };
424}424}