const std = @import("std"); const vk = @import("vulkan"); const VkError = @import("error_set.zig").VkError; pub fn NonDispatchable(comptime T: type) type { return struct { const Self = @This(); object_type: vk.ObjectType, object: *T, pub fn wrap(allocator: std.mem.Allocator, object: *T) VkError!*Self { const self = allocator.create(Self) catch return VkError.OutOfHostMemory; self.* = .{ .object_type = T.ObjectType, .object = object, }; std.log.debug("Created non dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) }); return self; } pub fn intrusiveDestroy(self: *Self, allocator: std.mem.Allocator) void { self.object.destroy(allocator); allocator.destroy(self); std.log.debug("Destroyed non dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) }); } pub fn destroy(self: *Self, allocator: std.mem.Allocator) void { allocator.destroy(self); std.log.debug("Destroyed non dispatchable handle of type '{s}' at 0x{X}", .{ @typeName(T), @intFromPtr(self) }); } pub inline fn toHandle(self: *Self) usize { return @intFromPtr(self); } pub inline fn toVkHandle(self: *Self, comptime VkT: type) VkT { return @enumFromInt(@intFromPtr(self)); } pub fn fromHandle(vk_handle: anytype) VkError!*Self { const handle = @intFromEnum(vk_handle); if (handle == 0) { return VkError.InvalidHandleDrv; } const non_dispatchable: *Self = @ptrFromInt(handle); if (non_dispatchable.object_type != T.ObjectType) { return VkError.InvalidHandleDrv; } return non_dispatchable; } pub inline fn fromHandleObject(handle: anytype) VkError!*T { const non_dispatchable_handle = try Self.fromHandle(handle); return non_dispatchable_handle.object; } pub inline fn checkHandleValidity(handle: anytype) VkError!void { _ = try Self.fromHandle(handle); } }; }