core: add mach.Core module API

Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
Stephen Gutekanst 2024-04-08 22:54:13 -07:00 committed by Stephen Gutekanst
parent 69b749879d
commit 013546b189
8 changed files with 309 additions and 41 deletions

View file

@ -7,6 +7,30 @@ pub const Timer = @import("Timer.zig");
const Frequency = @import("Frequency.zig");
const platform = @import("platform.zig");
const mach = @import("../main.zig");
pub var mods: mach.Modules = undefined;
pub fn initModule() !void {
// Initialize the global set of Mach modules used in the program.
try mods.init(std.heap.c_allocator);
mods.mod.mach_core.send(.init, .{});
}
/// Tick runs a single step of the main loop on the main OS thread.
///
/// Returns true if tick() should be called again, false if the application should exit.
pub fn tick() !bool {
mods.mod.mach_core.send(.main_thread_tick, .{});
// Dispatch events until this .mach_core.main_thread_tick_done is sent
try mods.dispatch(.{ .until = .{
.module_name = mods.moduleNameToID(.mach_core),
.local_event = mods.localEventToID(.mach_core, .main_thread_tick_done),
} });
return !mods.mod.mach_core.state().should_exit;
}
/// Returns the error set that the function F returns.
fn ErrorSet(comptime F: type) type {
return @typeInfo(@typeInfo(F).Fn.return_type.?).ErrorUnion.error_set;

View file

@ -581,13 +581,16 @@ pub fn appUpdateThreadTick(self: *Core, app: anytype) bool {
});
}
if (app.update() catch unreachable) {
self.done.set();
const use_app = @typeInfo(@TypeOf(app)) == .Pointer;
if (use_app) {
if (app.update() catch unreachable) {
self.done.set();
// Wake the main thread from any event handling, so there is not e.g. a one second delay
// in exiting the application.
glfw.postEmptyEvent();
return false;
// Wake the main thread from any event handling, so there is not e.g. a one second delay
// in exiting the application.
glfw.postEmptyEvent();
return false;
}
}
self.gpu_device.tick();
self.gpu_device.machWaitForCommandsToBeScheduled();
@ -605,10 +608,13 @@ pub fn appUpdateThread(self: *Core, app: anytype) void {
// Called on the main thread
pub fn update(self: *Core, app: anytype) !bool {
if (self.done.isSet()) return true;
if (!self.app_update_thread_started) {
self.app_update_thread_started = true;
const thread = try std.Thread.spawn(.{}, appUpdateThread, .{ self, app });
thread.detach();
const use_app = @typeInfo(@TypeOf(app)) == .Pointer;
if (use_app) {
if (!self.app_update_thread_started) {
self.app_update_thread_started = true;
const thread = try std.Thread.spawn(.{}, appUpdateThread, .{ self, app });
thread.detach();
}
}
if (self.state_update.isSet()) {
@ -748,14 +754,18 @@ pub fn update(self: *Core, app: anytype) !bool {
}
}
const frequency_delay = @as(f32, @floatFromInt(self.input.delay_ns)) / @as(f32, @floatFromInt(std.time.ns_per_s));
glfw.waitEventsTimeout(frequency_delay);
if (use_app) {
const frequency_delay = @as(f32, @floatFromInt(self.input.delay_ns)) / @as(f32, @floatFromInt(std.time.ns_per_s));
glfw.waitEventsTimeout(frequency_delay);
if (@hasDecl(std.meta.Child(@TypeOf(app)), "updateMainThread")) {
if (app.updateMainThread() catch unreachable) {
self.done.set();
return true;
if (@hasDecl(std.meta.Child(@TypeOf(app)), "updateMainThread")) {
if (app.updateMainThread() catch unreachable) {
self.done.set();
return true;
}
}
} else {
glfw.pollEvents();
}
glfw.getErrorCode() catch |err| switch (err) {
@ -764,6 +774,8 @@ pub fn update(self: *Core, app: anytype) !bool {
else => unreachable,
};
self.input.tick();
if (!use_app) return !self.appUpdateThreadTick(app);
return false;
}