mach: eliminate heap allocation of Core

Prior to this change `mach.Core.init` would heap allocate the structure, returning `*Core`:

```zig
app.core = try mach.Core.init(allocator, .{});
```

This was obviously not ideal, but wasn't possible to eliminate before due to how Core was
entangled with the platform abstraction. Now that it has been removed, we can reduce Core
initialization to take a `*Core` to initialize. In practice this means initialization looks
something like this:

```zig
try mach.Core.init(&app.core, alloctor, .{});
```

Or more simply:

```zig
try app.core.init(allocator, .{});
```

And we eliminate the `*Core` allocation entirely in most cases.

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2023-01-17 00:05:16 -07:00 committed by Stephen Gutekanst
parent f54d584991
commit 8082228186
4 changed files with 16 additions and 27 deletions

View file

@ -5,7 +5,7 @@ const platform = @import("platform.zig");
pub const Core = @This(); pub const Core = @This();
internal: *platform.Core, internal: platform.Core,
pub const Options = struct { pub const Options = struct {
is_app: bool = false, is_app: bool = false,
@ -16,10 +16,8 @@ pub const Options = struct {
required_limits: ?gpu.Limits = null, required_limits: ?gpu.Limits = null,
}; };
pub fn init(allocator: std.mem.Allocator, options: Options) !Core { pub fn init(core: *Core, allocator: std.mem.Allocator, options: Options) !void {
return .{ try platform.Core.init(&core.internal, allocator, options);
.internal = try platform.Core.init(allocator, options),
};
} }
pub fn deinit(core: *Core) void { pub fn deinit(core: *Core) void {

View file

@ -25,15 +25,16 @@ pub fn App(
return struct { return struct {
engine: ecs.World(modules), engine: ecs.World(modules),
core: Core,
pub fn init(app: *@This()) !void { pub fn init(app: *@This()) !void {
try app.core.init(allocator, .{});
app.* = .{ app.* = .{
.core = app.core,
.engine = try ecs.World(modules).init(allocator), .engine = try ecs.World(modules).init(allocator),
}; };
var core = try allocator.create(Core); app.engine.set(.mach, .core, &app.core);
core.* = try Core.init(allocator, .{}); app.engine.set(.mach, .device, app.core.device());
app.engine.set(.mach, .core, core);
app.engine.set(.mach, .device, core.device());
try app_init(&app.engine); try app_init(&app.engine);
} }

View file

@ -52,7 +52,7 @@ const UserPtr = struct {
self: *Core, self: *Core,
}; };
pub fn init(allocator: std.mem.Allocator, options: Options) !*Core { pub fn init(core: *Core, allocator: std.mem.Allocator, options: Options) !void {
const backend_type = try util.detectBackendType(allocator); const backend_type = try util.detectBackendType(allocator);
glfw.setErrorCallback(errorCallback); glfw.setErrorCallback(errorCallback);
@ -153,9 +153,7 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !*Core {
}; };
const swap_chain = gpu_device.createSwapChain(surface, &swap_chain_desc); const swap_chain = gpu_device.createSwapChain(surface, &swap_chain_desc);
const self: *Core = try allocator.create(Core); core.* = .{
errdefer allocator.destroy(self);
self.* = .{
.allocator = allocator, .allocator = allocator,
.window = window, .window = window,
.backend_type = backend_type, .backend_type = backend_type,
@ -186,14 +184,12 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !*Core {
.linux_gamemode = null, .linux_gamemode = null,
}; };
self.setSizeLimit(self.size_limit); core.setSizeLimit(core.size_limit);
self.initCallbacks(); core.initCallbacks();
if (builtin.os.tag == .linux and !options.is_app and if (builtin.os.tag == .linux and !options.is_app and
self.linux_gamemode == null and try activateGamemode(self.allocator)) core.linux_gamemode == null and try activateGamemode(core.allocator))
self.linux_gamemode = initLinuxGamemode(); core.linux_gamemode = initLinuxGamemode();
return self;
} }
fn initCallbacks(self: *Core) void { fn initCallbacks(self: *Core) void {
@ -316,8 +312,6 @@ pub fn deinit(self: *Core) void {
self.linux_gamemode != null and self.linux_gamemode != null and
self.linux_gamemode.?) self.linux_gamemode.?)
deinitLinuxGamemode(); deinitLinuxGamemode();
self.allocator.destroy(self);
} }
pub fn hasEvent(self: *Core) bool { pub fn hasEvent(self: *Core) bool {

View file

@ -25,14 +25,12 @@ id: js.CanvasId,
last_cursor_position: Position, last_cursor_position: Position,
last_key_mods: KeyMods, last_key_mods: KeyMods,
pub fn init(allocator: std.mem.Allocator, options: Options) !*Core { pub fn init(core: *Core, allocator: std.mem.Allocator, options: Options) !*Core {
_ = options; _ = options;
var selector = [1]u8{0} ** 15; var selector = [1]u8{0} ** 15;
const id = js.machCanvasInit(&selector[0]); const id = js.machCanvasInit(&selector[0]);
const self: *Core = try allocator.create(Core); core.* = Core{
errdefer allocator.destroy(self);
self.* = Core{
.allocator = allocator, .allocator = allocator,
.id = id, .id = id,
@ -50,8 +48,6 @@ pub fn init(allocator: std.mem.Allocator, options: Options) !*Core {
.num_lock = false, .num_lock = false,
}, },
}; };
return self;
} }
pub fn deinit(self: *Core) void { pub fn deinit(self: *Core) void {