diff --git a/lib/std/Target.zig b/lib/std/Target.zig index def304bc6c..4d3fa2a286 100644 --- a/lib/std/Target.zig +++ b/lib/std/Target.zig @@ -1479,7 +1479,7 @@ pub const Cpu = struct { .fs, .gs, .ss => arch == .x86_64 or arch == .x86, .global, .constant, .local, .shared => is_gpu, .param => is_nvptx, - .input, .output, .uniform => is_spirv, + .input, .output, .uniform, .push_constant => is_spirv, // TODO this should also check how many flash banks the cpu has .flash, .flash1, .flash2, .flash3, .flash4, .flash5 => arch == .avr, diff --git a/lib/std/builtin.zig b/lib/std/builtin.zig index d14675b2fc..d7f8876b24 100644 --- a/lib/std/builtin.zig +++ b/lib/std/builtin.zig @@ -514,6 +514,7 @@ pub const AddressSpace = enum(u5) { input, output, uniform, + push_constant, // AVR address spaces. flash, diff --git a/src/Sema.zig b/src/Sema.zig index fdf39b8305..e5c0dab815 100644 --- a/src/Sema.zig +++ b/src/Sema.zig @@ -37820,7 +37820,7 @@ pub fn analyzeAsAddressSpace( .gs, .fs, .ss => (arch == .x86 or arch == .x86_64) and ctx == .pointer, // TODO: check that .shared and .local are left uninitialized .param => is_nv, - .input, .output, .uniform => is_spirv, + .input, .output, .uniform, .push_constant => is_spirv, .global, .shared, .local => is_gpu, .constant => is_gpu and (ctx == .constant), // TODO this should also check how many flash banks the cpu has diff --git a/src/codegen/spirv.zig b/src/codegen/spirv.zig index 46c23d7d53..ecbf7bf523 100644 --- a/src/codegen/spirv.zig +++ b/src/codegen/spirv.zig @@ -897,7 +897,7 @@ const NavGen = struct { const result_ty_id = try self.resolveType(ty, repr); const ip = &zcu.intern_pool; - log.debug("lowering constant: ty = {}, val = {}", .{ ty.fmt(pt), val.fmtValue(pt) }); + log.debug("lowering constant: ty = {}, val = {}, key = {s}", .{ ty.fmt(pt), val.fmtValue(pt), @tagName(ip.indexToKey(val.toIntern())) }); if (val.isUndefDeep(zcu)) { return self.spv.constUndef(result_ty_id); } @@ -1167,7 +1167,6 @@ 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| { @@ -1211,10 +1210,6 @@ const NavGen = struct { 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 src_base_ty = parent_ptr_ty.arrayBase(zcu)[0]; - const dest_base_ty = oac.new_ptr_ty.arrayBase(zcu)[0]; - if (self.getTarget().os.tag == .vulkan and src_base_ty.toIntern() != dest_base_ty.toIntern()) break :disallow; - 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, .{ @@ -1224,7 +1219,7 @@ const NavGen = struct { }); return result_ptr_id; } - return self.fail("Cannot perform pointer cast: '{}' to '{}'", .{ + return self.fail("cannot perform pointer cast: '{}' to '{}'", .{ parent_ptr_ty.fmt(pt), oac.new_ptr_ty.fmt(pt), }); @@ -1308,12 +1303,12 @@ const NavGen = struct { .global, .invocation_global => spv_decl.result_id, }; - const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); - try self.addFunctionDep(spv_decl_index, final_storage_class); + const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); + try self.addFunctionDep(spv_decl_index, storage_class); - const decl_ptr_ty_id = try self.ptrType(nav_ty, final_storage_class); + const decl_ptr_ty_id = try self.ptrType(nav_ty, storage_class); - const ptr_id = switch (final_storage_class) { + const ptr_id = switch (storage_class) { .Generic => try self.castToGeneric(decl_ptr_ty_id, decl_id), else => decl_id, }; @@ -1399,6 +1394,10 @@ const NavGen = struct { const child_ty_id = try self.resolveType(child_ty, child_repr); + if (storage_class == .Uniform or storage_class == .PushConstant) { + try self.spv.decorate(child_ty_id, .Block); + } + try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpTypePointer, .{ .id_result = result_id, .storage_class = storage_class, @@ -1503,10 +1502,13 @@ const NavGen = struct { member_names[layout.padding_index] = "(padding)"; } - const result_id = try self.spv.structType(member_types[0..layout.total_fields], member_names[0..layout.total_fields]); + const result_id = self.spv.allocId(); + try self.spv.structType(result_id, member_types[0..layout.total_fields], member_names[0..layout.total_fields]); + const type_name = try self.resolveTypeName(ty); defer self.gpa.free(type_name); try self.spv.debugName(result_id, type_name); + return result_id; } @@ -1700,10 +1702,13 @@ const NavGen = struct { } const size_ty_id = try self.resolveType(Type.usize, .direct); - return self.spv.structType( + const result_id = self.spv.allocId(); + try self.spv.structType( + result_id, &.{ ptr_ty_id, size_ty_id }, &.{ "ptr", "len" }, ); + return result_id; }, .vector => { const elem_ty = ty.childType(zcu); @@ -1730,10 +1735,13 @@ const NavGen = struct { member_index += 1; } - const result_id = try self.spv.structType(member_types[0..member_index], null); + const result_id = self.spv.allocId(); + try self.spv.structType(result_id, member_types[0..member_index], null); + const type_name = try self.resolveTypeName(ty); defer self.gpa.free(type_name); try self.spv.debugName(result_id, type_name); + return result_id; }, .struct_type => ip.loadStructType(ty.toIntern()), @@ -1750,7 +1758,9 @@ const NavGen = struct { var member_names = std.ArrayList([]const u8).init(self.gpa); defer member_names.deinit(); + var index: u32 = 0; var it = struct_type.iterateRuntimeOrder(ip); + const result_id = self.spv.allocId(); while (it.next()) |field_index| { const field_ty = Type.fromInterned(struct_type.field_types.get(ip)[field_index]); if (!field_ty.hasRuntimeBitsIgnoreComptime(zcu)) { @@ -1758,16 +1768,25 @@ const NavGen = struct { continue; } + if (target.os.tag == .vulkan) { + try self.spv.decorateMember(result_id, index, .{ .Offset = .{ + .byte_offset = @intCast(ty.structFieldOffset(field_index, zcu)), + } }); + } const field_name = struct_type.fieldName(ip, field_index).unwrap() orelse try ip.getOrPutStringFmt(zcu.gpa, pt.tid, "{d}", .{field_index}, .no_embedded_nulls); try member_types.append(try self.resolveType(field_ty, .indirect)); try member_names.append(field_name.toSlice(ip)); + + index += 1; } - const result_id = try self.spv.structType(member_types.items, member_names.items); + try self.spv.structType(result_id, member_types.items, member_names.items); + const type_name = try self.resolveTypeName(ty); defer self.gpa.free(type_name); try self.spv.debugName(result_id, type_name); + return result_id; }, .optional => { @@ -1787,10 +1806,13 @@ const NavGen = struct { const bool_ty_id = try self.resolveType(Type.bool, .indirect); - return try self.spv.structType( + const result_id = self.spv.allocId(); + try self.spv.structType( + result_id, &.{ payload_ty_id, bool_ty_id }, &.{ "payload", "valid" }, ); + return result_id; }, .@"union" => return try self.resolveUnionType(ty), .error_set => return try self.resolveType(Type.u16, repr), @@ -1819,7 +1841,9 @@ const NavGen = struct { // TODO: ABI padding? } - return try self.spv.structType(&member_types, &member_names); + const result_id = self.spv.allocId(); + try self.spv.structType(result_id, &member_types, &member_names); + return result_id; }, .@"opaque" => { const type_name = try self.resolveTypeName(ty); @@ -1849,7 +1873,7 @@ const NavGen = struct { const target = self.getTarget(); return switch (as) { .generic => switch (target.os.tag) { - .vulkan => .Private, + .vulkan => .Function, .opencl => .Generic, else => unreachable, }, @@ -1861,6 +1885,7 @@ const NavGen = struct { else => unreachable, }, .constant => .UniformConstant, + .push_constant => .PushConstant, .input => .Input, .output => .Output, .uniform => .Uniform, @@ -2958,10 +2983,8 @@ const NavGen = struct { const spv_err_decl_index = try self.spv.allocDecl(.global); try self.spv.declareDeclDeps(spv_err_decl_index, &.{}); - const push_constant_struct_ty_id = try self.spv.structType( - &.{ptr_anyerror_ty_id}, - &.{"error_out_ptr"}, - ); + const push_constant_struct_ty_id = self.spv.allocId(); + try self.spv.structType(push_constant_struct_ty_id, &.{ptr_anyerror_ty_id}, &.{"error_out_ptr"}); try self.spv.decorate(push_constant_struct_ty_id, .Block); try self.spv.decorateMember(push_constant_struct_ty_id, 0, .{ .Offset = .{ .byte_offset = 0 } }); @@ -3145,15 +3168,15 @@ const NavGen = struct { }; assert(maybe_init_val == null); // TODO - const final_storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); - assert(final_storage_class != .Generic); // These should be instance globals + const storage_class = self.spvStorageClass(nav.status.resolved.@"addrspace"); + assert(storage_class != .Generic); // These should be instance globals - const ptr_ty_id = try self.ptrType(ty, final_storage_class); + const ptr_ty_id = try self.ptrType(ty, storage_class); try self.spv.sections.types_globals_constants.emit(self.spv.gpa, .OpVariable, .{ .id_result_type = ptr_ty_id, .id_result = result_id, - .storage_class = final_storage_class, + .storage_class = storage_class, }); try self.spv.debugName(result_id, nav.fqn.toSlice(ip)); diff --git a/src/codegen/spirv/Module.zig b/src/codegen/spirv/Module.zig index 94787e06b9..f4af74b3aa 100644 --- a/src/codegen/spirv/Module.zig +++ b/src/codegen/spirv/Module.zig @@ -402,9 +402,7 @@ pub fn resolveString(self: *Module, string: []const u8) !IdRef { return id; } -pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []const u8) !IdRef { - const result_id = self.allocId(); - +pub fn structType(self: *Module, result_id: IdResult, types: []const IdRef, maybe_names: ?[]const []const u8) !void { try self.sections.types_globals_constants.emit(self.gpa, .OpTypeStruct, .{ .id_result = result_id, .id_ref = types, @@ -416,8 +414,6 @@ pub fn structType(self: *Module, types: []const IdRef, maybe_names: ?[]const []c try self.memberDebugName(result_id, @intCast(i), name); } } - - return result_id; } pub fn boolType(self: *Module) !IdRef { diff --git a/src/link/SpirV.zig b/src/link/SpirV.zig index 045bd05d84..106b52a72c 100644 --- a/src/link/SpirV.zig +++ b/src/link/SpirV.zig @@ -296,7 +296,7 @@ fn writeCapabilities(spv: *SpvModule, target: std.Target) !void { // TODO: Integrate with a hypothetical feature system const caps: []const spec.Capability = switch (target.os.tag) { .opencl => &.{ .Kernel, .Addresses, .Int8, .Int16, .Int64, .Float64, .Float16, .Vector16, .GenericPointer }, - .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .StoragePushConstant16, .Int8, .Int16, .Int64, .Float64, .Float16 }, + .vulkan => &.{ .Shader, .PhysicalStorageBufferAddresses, .Int8, .Int16, .Int64, .Float64, .Float16 }, else => unreachable, }; diff --git a/src/target.zig b/src/target.zig index b0d2bdfe74..00e804d441 100644 --- a/src/target.zig +++ b/src/target.zig @@ -418,7 +418,7 @@ pub fn arePointersLogical(target: std.Target, as: AddressSpace) bool { .global => false, // TODO: Allowed with VK_KHR_variable_pointers. .shared => true, - .constant, .local, .input, .output, .uniform => true, + .constant, .local, .input, .output, .uniform, .push_constant => true, else => unreachable, }; }