Deinit devmode more cleanly

This commit is contained in:
Mitchell Hashimoto
2022-11-06 17:26:01 -08:00
parent 135b859b8f
commit fd304c9338
4 changed files with 45 additions and 34 deletions

View File

@ -32,6 +32,9 @@ config: *const Config,
/// this is a blocking queue so if it is full you will get errors (or block).
mailbox: *Mailbox,
/// Set to true once we're quitting. This never goes false again.
quit: bool,
/// Initialize the main app instance. This creates the main window, sets
/// up the renderer state, compiles the shaders, etc. This is the primary
/// "startup" logic.
@ -47,6 +50,7 @@ pub fn create(alloc: Allocator, config: *const Config) !*App {
.windows = .{},
.config = config,
.mailbox = mailbox,
.quit = false,
};
errdefer app.windows.deinit(alloc);
@ -74,8 +78,7 @@ pub fn wakeup(self: App) void {
/// Run the main event loop for the application. This blocks until the
/// application quits or every window is closed.
pub fn run(self: *App) !void {
var quit: bool = false;
while (!quit and self.windows.items.len > 0) {
while (!self.quit and self.windows.items.len > 0) {
// Block for any glfw events.
try glfw.waitEvents();
@ -87,11 +90,6 @@ pub fn run(self: *App) !void {
while (i < self.windows.items.len) {
const window = self.windows.items[i];
if (window.shouldClose()) {
// If this was our final window, deinitialize the renderer
if (self.windows.items.len == 1) {
renderer.Renderer.lastWindowDeinit();
}
window.destroy();
_ = self.windows.swapRemove(i);
continue;
@ -100,13 +98,13 @@ pub fn run(self: *App) !void {
i += 1;
}
// Drain our mailbox
try self.drainMailbox(&quit);
// Drain our mailbox only if we're not quitting.
if (!self.quit) try self.drainMailbox();
}
}
/// Drain the mailbox.
fn drainMailbox(self: *App, quit: *bool) !void {
fn drainMailbox(self: *App) !void {
var drain = self.mailbox.drain();
defer drain.deinit();
@ -114,7 +112,7 @@ fn drainMailbox(self: *App, quit: *bool) !void {
log.debug("mailbox message={}", .{message});
switch (message) {
.new_window => try self.newWindow(),
.quit => quit.* = true,
.quit => try self.setQuit(),
}
}
}
@ -125,10 +123,16 @@ fn newWindow(self: *App) !void {
errdefer window.destroy();
try self.windows.append(self.alloc, window);
errdefer _ = self.windows.pop();
}
// This was the first window, so we need to initialize our renderer.
if (self.windows.items.len == 1) {
try window.renderer.firstWindowInit(window.window);
/// Start quitting
fn setQuit(self: *App) !void {
if (self.quit) return;
self.quit = true;
// Mark that all our windows should close
for (self.windows.items) |window| {
window.window.setShouldClose(true);
}
}

View File

@ -393,6 +393,9 @@ pub fn create(alloc: Allocator, app: *App, config: *const Config) !*Window {
// Add our window to the instance if it isn't set.
DevMode.instance.window = self;
// Let our renderer setup
try renderer_impl.initDevMode(window);
}
// Give the renderer one more opportunity to finalize any window
@ -427,11 +430,11 @@ pub fn destroy(self: *Window) void {
self.renderer.threadEnter(self.window) catch unreachable;
self.renderer_thread.deinit();
// Deinit our renderer
self.renderer.deinit();
}
// If we are devmode-owning, clean that up.
if (DevMode.enabled and DevMode.instance.window == self) {
// Let our renderer clean up
self.renderer.deinitDevMode();
// Clear the window
DevMode.instance.window = null;
@ -439,6 +442,10 @@ pub fn destroy(self: *Window) void {
self.imgui_ctx.destroy();
}
// Deinit our renderer
self.renderer.deinit();
}
{
// Stop our IO thread
self.io_thread.stop.send() catch |err|

View File

@ -265,10 +265,8 @@ pub fn finalizeWindowInit(self: *const Metal, window: glfw.Window) !void {
layer.setProperty("contentsScale", scaleFactor);
}
/// This is called only after the first window is opened. This may be
/// called multiple times if all windows are closed and a new one is
/// reopened.
pub fn firstWindowInit(self: *const Metal, window: glfw.Window) !void {
/// This is called if this renderer runs DevMode.
pub fn initDevMode(self: *const Metal, window: glfw.Window) !void {
if (DevMode.enabled) {
// Initialize for our window
assert(imgui.ImplGlfw.initForOther(
@ -279,8 +277,10 @@ pub fn firstWindowInit(self: *const Metal, window: glfw.Window) !void {
}
}
/// This is called only when the last window is destroyed.
pub fn lastWindowDeinit() void {
/// This is called if this renderer runs DevMode.
pub fn deinitDevMode(self: *const Metal) void {
_ = self;
if (DevMode.enabled) {
imgui.ImplMetal.shutdown();
imgui.ImplGlfw.shutdown();

View File

@ -387,10 +387,8 @@ pub fn finalizeWindowInit(self: *const OpenGL, window: glfw.Window) !void {
_ = window;
}
/// This is called only after the first window is opened. This may be
/// called multiple times if all windows are closed and a new one is
/// reopened.
pub fn firstWindowInit(self: *const OpenGL, window: glfw.Window) !void {
/// This is called if this renderer runs DevMode.
pub fn initDevMode(self: *const OpenGL, window: glfw.Window) !void {
_ = self;
if (DevMode.enabled) {
@ -403,8 +401,10 @@ pub fn firstWindowInit(self: *const OpenGL, window: glfw.Window) !void {
}
}
/// This is called only when the last window is destroyed.
pub fn lastWindowDeinit() void {
/// This is called if this renderer runs DevMode.
pub fn deinitDevMode(self: *const OpenGL) void {
_ = self;
if (DevMode.enabled) {
imgui.ImplOpenGL3.shutdown();
imgui.ImplGlfw.shutdown();