Core: use an explicit .start event sent by app to begin .tick events
Signed-off-by: Stephen Gutekanst <stephen@hexops.com>
This commit is contained in:
parent
8089d3356e
commit
15fd2c3a64
8 changed files with 67 additions and 25 deletions
|
|
@ -58,6 +58,8 @@ fn init(game: *Mod, core: *mach.Core.Mod) !void {
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
});
|
});
|
||||||
try updateWindowTitle(core);
|
try updateWindowTitle(core);
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(important): remove need for returning an error here
|
// TODO(important): remove need for returning an error here
|
||||||
|
|
|
||||||
|
|
@ -74,6 +74,8 @@ fn init(
|
||||||
.spawn_timer = try mach.Timer.start(),
|
.spawn_timer = try mach.Timer.start(),
|
||||||
.player = player,
|
.player = player,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// TODO(important): remove need for returning an error here
|
// TODO(important): remove need for returning an error here
|
||||||
|
|
|
||||||
|
|
@ -46,7 +46,7 @@ fn deinit(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs
|
||||||
core.send(.deinit, .{});
|
core.send(.deinit, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn init(sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mod) !void {
|
fn init(core: *mach.Core.Mod, sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mod) !void {
|
||||||
sprite_pipeline.send(.init, .{});
|
sprite_pipeline.send(.init, .{});
|
||||||
glyphs.send(.init, .{});
|
glyphs.send(.init, .{});
|
||||||
|
|
||||||
|
|
@ -55,6 +55,8 @@ fn init(sprite_pipeline: *gfx.SpritePipeline.Mod, glyphs: *Glyphs.Mod, game: *Mo
|
||||||
|
|
||||||
// Run our init code after glyphs module is initialized.
|
// Run our init code after glyphs module is initialized.
|
||||||
game.send(.after_init, .{});
|
game.send(.after_init, .{});
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn afterInit(
|
fn afterInit(
|
||||||
|
|
|
||||||
|
|
@ -36,7 +36,7 @@ pub const components = .{
|
||||||
|
|
||||||
ghost_key_mode: bool = false,
|
ghost_key_mode: bool = false,
|
||||||
|
|
||||||
fn init(audio: *mach.Audio.Mod, app: *Mod) void {
|
fn init(core: *mach.Core.Mod, audio: *mach.Audio.Mod, app: *Mod) void {
|
||||||
// Initialize audio module, telling it to send our module's .audio_state_change event when an
|
// Initialize audio module, telling it to send our module's .audio_state_change event when an
|
||||||
// entity's sound stops playing
|
// entity's sound stops playing
|
||||||
audio.send(.init, .{app.event(.audio_state_change)});
|
audio.send(.init, .{app.event(.audio_state_change)});
|
||||||
|
|
@ -49,6 +49,8 @@ fn init(audio: *mach.Audio.Mod, app: *Mod) void {
|
||||||
std.debug.print("[spacebar] enable ghost-key mode (demonstrate seamless back-to-back sound playback)\n", .{});
|
std.debug.print("[spacebar] enable ghost-key mode (demonstrate seamless back-to-back sound playback)\n", .{});
|
||||||
std.debug.print("[arrow up] increase volume 10%\n", .{});
|
std.debug.print("[arrow up] increase volume 10%\n", .{});
|
||||||
std.debug.print("[arrow down] decrease volume 10%\n", .{});
|
std.debug.print("[arrow down] decrease volume 10%\n", .{});
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(core: *mach.Core.Mod, audio: *mach.Audio.Mod) void {
|
fn deinit(core: *mach.Core.Mod, audio: *mach.Audio.Mod) void {
|
||||||
|
|
|
||||||
|
|
@ -89,6 +89,8 @@ fn init(
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tick(
|
fn tick(
|
||||||
|
|
|
||||||
|
|
@ -127,6 +127,8 @@ fn init(
|
||||||
.allocator = allocator,
|
.allocator = allocator,
|
||||||
.pipeline = pipeline,
|
.pipeline = pipeline,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
core.send(.start, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn tick(
|
fn tick(
|
||||||
|
|
|
||||||
61
src/Core.zig
61
src/Core.zig
|
|
@ -11,6 +11,10 @@ pub const name = .mach_core;
|
||||||
pub const Mod = mach.Mod(@This());
|
pub const Mod = mach.Mod(@This());
|
||||||
|
|
||||||
pub const events = .{
|
pub const events = .{
|
||||||
|
.start = .{ .handler = start, .description =
|
||||||
|
\\ Send this once your app is initialized and ready for .app.tick events.
|
||||||
|
},
|
||||||
|
|
||||||
.update = .{ .handler = update, .description =
|
.update = .{ .handler = update, .description =
|
||||||
\\ Send this when window entities have been updated and you want the new values respected.
|
\\ Send this when window entities have been updated and you want the new values respected.
|
||||||
},
|
},
|
||||||
|
|
@ -19,15 +23,24 @@ pub const events = .{
|
||||||
\\ Send this when rendering has finished and the swapchain should be presented.
|
\\ Send this when rendering has finished and the swapchain should be presented.
|
||||||
},
|
},
|
||||||
|
|
||||||
.init = .{ .handler = init },
|
.exit = .{ .handler = exit, .description =
|
||||||
.init_done = .{ .handler = fn () void },
|
\\ Send this when you would like to exit the application.
|
||||||
|
\\
|
||||||
|
\\ When the next .present_frame occurs, then .app.deinit will be sent giving your app a chance
|
||||||
|
\\ to deinitialize itself and .app.tick will no longer be sent. Once your app is done with
|
||||||
|
\\ deinitialization, you should send the final .mach_core.deinit event which will cause the
|
||||||
|
\\ application to finish.
|
||||||
|
},
|
||||||
|
|
||||||
|
.deinit = .{ .handler = deinit, .description =
|
||||||
|
\\ Send this once your app is fully deinitialized and ready to exit for good.
|
||||||
|
},
|
||||||
|
|
||||||
// TODO(important): need some way to tie event execution to a specific thread once we have a
|
// TODO(important): need some way to tie event execution to a specific thread once we have a
|
||||||
// multithreaded dispatch implementation
|
// multithreaded dispatch implementation
|
||||||
|
.init = .{ .handler = init },
|
||||||
.main_thread_tick = .{ .handler = mainThreadTick },
|
.main_thread_tick = .{ .handler = mainThreadTick },
|
||||||
.main_thread_tick_done = .{ .handler = fn () void },
|
.main_thread_tick_done = .{ .handler = fn () void },
|
||||||
.deinit = .{ .handler = deinit },
|
|
||||||
.exit = .{ .handler = exit },
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const components = .{
|
pub const components = .{
|
||||||
|
|
@ -81,14 +94,25 @@ allocator: std.mem.Allocator,
|
||||||
device: *mach.gpu.Device,
|
device: *mach.gpu.Device,
|
||||||
queue: *mach.gpu.Queue,
|
queue: *mach.gpu.Queue,
|
||||||
main_window: mach.EntityID,
|
main_window: mach.EntityID,
|
||||||
should_exit: bool = false,
|
run_state: enum {
|
||||||
|
initialized,
|
||||||
|
running,
|
||||||
|
exiting,
|
||||||
|
deinitializing,
|
||||||
|
exited,
|
||||||
|
} = .initialized,
|
||||||
|
|
||||||
|
fn start(core: *Mod) !void {
|
||||||
|
core.state().run_state = .running;
|
||||||
|
}
|
||||||
|
|
||||||
fn init(core: *Mod) !void {
|
fn init(core: *Mod) !void {
|
||||||
|
mach.core.allocator = gpa.allocator(); // TODO: banish this global allocator
|
||||||
|
|
||||||
// Initialize GPU implementation
|
// Initialize GPU implementation
|
||||||
if (comptime !mach.use_sysgpu) try mach.wgpu.Impl.init(mach.core.allocator, .{});
|
if (comptime !mach.use_sysgpu) try mach.wgpu.Impl.init(mach.core.allocator, .{});
|
||||||
if (comptime mach.use_sysgpu) try mach.sysgpu.Impl.init(mach.core.allocator, .{});
|
if (comptime mach.use_sysgpu) try mach.sysgpu.Impl.init(mach.core.allocator, .{});
|
||||||
|
|
||||||
mach.core.allocator = gpa.allocator(); // TODO: banish this global allocator
|
|
||||||
try mach.core.init(.{});
|
try mach.core.init(.{});
|
||||||
|
|
||||||
// TODO(important): update this information upon framebuffer resize events
|
// TODO(important): update this information upon framebuffer resize events
|
||||||
|
|
@ -105,7 +129,6 @@ fn init(core: *Mod) !void {
|
||||||
});
|
});
|
||||||
|
|
||||||
mach.core.mods.send(.app, .init, .{});
|
mach.core.mods.send(.app, .init, .{});
|
||||||
core.send(.init_done, .{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
fn update(core: *Mod) !void {
|
fn update(core: *Mod) !void {
|
||||||
|
|
@ -130,16 +153,24 @@ fn update(core: *Mod) !void {
|
||||||
}
|
}
|
||||||
|
|
||||||
fn presentFrame(core: *Mod) !void {
|
fn presentFrame(core: *Mod) !void {
|
||||||
|
switch (core.state().run_state) {
|
||||||
|
.running => {
|
||||||
mach.core.swap_chain.present();
|
mach.core.swap_chain.present();
|
||||||
|
|
||||||
// Signal that mainThreadTick is done
|
// Signal that mainThreadTick is done
|
||||||
core.send(.main_thread_tick_done, .{});
|
core.send(.main_thread_tick_done, .{});
|
||||||
|
},
|
||||||
|
.exiting => {
|
||||||
|
// Exit opportunity is here, deinitialize now
|
||||||
|
core.state().run_state = .deinitializing;
|
||||||
|
mach.core.mods.send(.app, .deinit, .{});
|
||||||
|
},
|
||||||
|
else => return,
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
fn deinit(core: *Mod) void {
|
fn deinit(core: *Mod) void {
|
||||||
core.state().queue.release();
|
core.state().queue.release();
|
||||||
// TODO: this triggers a device loss error, which we should handle correctly
|
|
||||||
// core.state().device.release();
|
|
||||||
mach.core.deinit();
|
mach.core.deinit();
|
||||||
|
|
||||||
var archetypes_iter = core.entities.query(.{ .all = &.{
|
var archetypes_iter = core.entities.query(.{ .all = &.{
|
||||||
|
|
@ -152,14 +183,18 @@ fn deinit(core: *Mod) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
_ = gpa.deinit();
|
_ = gpa.deinit();
|
||||||
core.state().should_exit = true;
|
core.state().run_state = .exited;
|
||||||
|
|
||||||
|
// Signal that mainThreadTick is done
|
||||||
|
core.send(.main_thread_tick_done, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn mainThreadTick() !void {
|
fn mainThreadTick(core: *Mod) !void {
|
||||||
|
if (core.state().run_state != .running) return;
|
||||||
_ = try mach.core.update(null);
|
_ = try mach.core.update(null);
|
||||||
mach.core.mods.send(.app, .tick, .{});
|
mach.core.mods.send(.app, .tick, .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
fn exit() void {
|
fn exit(core: *Mod) void {
|
||||||
mach.core.mods.send(.app, .deinit, .{});
|
core.state().run_state = .exiting;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -15,13 +15,8 @@ var stack_space: [8 * 1024 * 1024]u8 = undefined;
|
||||||
pub fn initModule() !void {
|
pub fn initModule() !void {
|
||||||
// Initialize the global set of Mach modules used in the program.
|
// Initialize the global set of Mach modules used in the program.
|
||||||
try mods.init(std.heap.c_allocator);
|
try mods.init(std.heap.c_allocator);
|
||||||
mods.send(.mach_core, .init, .{});
|
|
||||||
|
|
||||||
// Dispatch events until this .mach_core.init_done is sent
|
mods.send(.mach_core, .init, .{});
|
||||||
try mods.dispatch(&stack_space, .{ .until = .{
|
|
||||||
.module_name = mods.moduleNameToID(.mach_core),
|
|
||||||
.local_event = mods.localEventToID(.mach_core, .init_done),
|
|
||||||
} });
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Tick runs a single step of the main loop on the main OS thread.
|
/// Tick runs a single step of the main loop on the main OS thread.
|
||||||
|
|
@ -36,7 +31,7 @@ pub fn tick() !bool {
|
||||||
.local_event = mods.localEventToID(.mach_core, .main_thread_tick_done),
|
.local_event = mods.localEventToID(.mach_core, .main_thread_tick_done),
|
||||||
} });
|
} });
|
||||||
|
|
||||||
return !mods.mod.mach_core.state().should_exit;
|
return mods.mod.mach_core.state().run_state != .exited;
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Returns the error set that the function F returns.
|
/// Returns the error set that the function F returns.
|
||||||
|
|
|
||||||
Loading…
Add table
Add a link
Reference in a new issue