diff --git a/gpu/examples/main.zig b/gpu/examples/main.zig index e4ae9b80..7412e17f 100644 --- a/gpu/examples/main.zig +++ b/gpu/examples/main.zig @@ -142,6 +142,9 @@ const FrameParams = struct { }; fn frame(params: FrameParams) !void { + const pool = try sample_utils.AutoReleasePool.init(); + defer sample_utils.AutoReleasePool.release(pool); + try glfw.pollEvents(); const pl = params.window.getUserPointer(WindowData).?; if (pl.swap_chain == null or !std.meta.eql(pl.current_desc, pl.target_desc)) { diff --git a/gpu/examples/sample_utils.zig b/gpu/examples/sample_utils.zig index 0458b736..270c563d 100644 --- a/gpu/examples/sample_utils.zig +++ b/gpu/examples/sample_utils.zig @@ -99,7 +99,7 @@ pub fn setup(allocator: std.mem.Allocator) !Setup { .force_fallback_adapter = false, }, &response, requestAdapterCallback); if (response.?.status != .success) { - std.debug.print("failed to create GPU adapter: {s}\n", .{response.?.message}); + std.debug.print("failed to create GPU adapter: {s}\n", .{response.?.message.?}); std.process.exit(1); } @@ -204,6 +204,29 @@ pub fn createSurfaceForWindow( }); } +pub const AutoReleasePool = opaque { + pub fn init() error{OutOfMemory}!?*AutoReleasePool { + if (!@import("builtin").target.isDarwin()) return null; + + // pool = [NSAutoreleasePool alloc]; + var pool = msgSend(objc.objc_getClass("NSAutoreleasePool"), "alloc", .{}, ?*AutoReleasePool); + if (pool == null) return error.OutOfMemory; + + // pool = [pool init]; + pool = msgSend(pool, "init", .{}, ?*AutoReleasePool); + if (pool == null) unreachable; + + return pool; + } + + pub fn release(pool: ?*AutoReleasePool) void { + if (!@import("builtin").target.isDarwin()) return; + + // [pool release]; + msgSend(pool, "release", .{}, void); + } +}; + // Borrowed from https://github.com/hazeycode/zig-objcrt pub fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnType: type) ReturnType { const args_meta = @typeInfo(@TypeOf(args)).Struct.fields; diff --git a/src/platform/native.zig b/src/platform/native.zig index ae5cc8b0..8871e192 100644 --- a/src/platform/native.zig +++ b/src/platform/native.zig @@ -593,6 +593,11 @@ pub fn main() !void { defer app.deinit(core); while (!core.internal.window.shouldClose()) { + // On Darwin targets, Dawn requires an NSAutoreleasePool per frame to release + // some resources. See Dawn's CHelloWorld example. + const pool = try util.AutoReleasePool.init(); + defer util.AutoReleasePool.release(pool); + try coreUpdate(core, null); try app.update(core); diff --git a/src/platform/util.zig b/src/platform/util.zig index 291a027a..4f1466d1 100644 --- a/src/platform/util.zig +++ b/src/platform/util.zig @@ -137,6 +137,29 @@ pub fn createSurfaceForWindow( }); } +pub const AutoReleasePool = opaque { + pub fn init() error{OutOfMemory}!?*AutoReleasePool { + if (!@import("builtin").target.isDarwin()) return null; + + // pool = [NSAutoreleasePool alloc]; + var pool = msgSend(objc.objc_getClass("NSAutoreleasePool"), "alloc", .{}, ?*AutoReleasePool); + if (pool == null) return error.OutOfMemory; + + // pool = [pool init]; + pool = msgSend(pool, "init", .{}, ?*AutoReleasePool); + if (pool == null) unreachable; + + return pool; + } + + pub fn release(pool: ?*AutoReleasePool) void { + if (!@import("builtin").target.isDarwin()) return; + + // [pool release]; + msgSend(pool, "release", .{}, void); + } +}; + // Borrowed from https://github.com/hazeycode/zig-objcrt fn msgSend(obj: anytype, sel_name: [:0]const u8, args: anytype, comptime ReturnType: type) ReturnType { const args_meta = @typeInfo(@TypeOf(args)).Struct.fields;