runtime hooks
This commit is contained in:
@@ -9,9 +9,13 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
|||||||
_ = alloc;
|
_ = alloc;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn connect() !void {
|
||||||
|
try ImGui.hooks.frame.register(nu_imgui_frame);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit() void {}
|
pub fn deinit() void {}
|
||||||
|
|
||||||
pub fn nu_frame() void {}
|
// pub fn nu_frame() void {}
|
||||||
|
|
||||||
// pub fn nu_events(events: []const Bus.Event) void {
|
// pub fn nu_events(events: []const Bus.Event) void {
|
||||||
// std.debug.print("{any}\n", .{events});
|
// std.debug.print("{any}\n", .{events});
|
||||||
|
@@ -33,17 +33,20 @@ pub fn main() !void {
|
|||||||
defer _ = gpa.detectLeaks();
|
defer _ = gpa.detectLeaks();
|
||||||
const alloc = gpa.allocator();
|
const alloc = gpa.allocator();
|
||||||
|
|
||||||
|
nu.init(alloc);
|
||||||
|
defer nu.deinit();
|
||||||
|
|
||||||
try nu.Window.init(alloc);
|
try nu.Window.init(alloc);
|
||||||
defer nu.Window.deinit();
|
defer nu.Window.deinit();
|
||||||
|
|
||||||
try nu.Render.init(alloc);
|
try nu.Render.init(alloc);
|
||||||
defer nu.Render.deinit();
|
defer nu.Render.deinit();
|
||||||
|
|
||||||
try nu.ImGui.init();
|
try nu.ImGui.init(alloc);
|
||||||
defer nu.ImGui.deinit();
|
defer nu.ImGui.deinit();
|
||||||
|
|
||||||
try App.init(alloc);
|
try App.init(alloc);
|
||||||
defer App.deinit();
|
defer App.deinit();
|
||||||
|
|
||||||
try nu.run();
|
try nu.run(alloc);
|
||||||
}
|
}
|
||||||
|
98
src/nu.zig
98
src/nu.zig
@@ -5,6 +5,9 @@ pub const Window = @import("nu/Window.zig");
|
|||||||
pub const Render = @import("nu/Render.zig");
|
pub const Render = @import("nu/Render.zig");
|
||||||
pub const ImGui = @import("nu/ImGui.zig");
|
pub const ImGui = @import("nu/ImGui.zig");
|
||||||
|
|
||||||
|
pub const Bus = @import("nu/Bus.zig");
|
||||||
|
pub const Hook = @import("nu/hooks.zig").Hook;
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
window: Window.Options = .{},
|
window: Window.Options = .{},
|
||||||
render: Render.Options = .{},
|
render: Render.Options = .{},
|
||||||
@@ -15,44 +18,81 @@ pub const options: Options = if (@hasDecl(root, "nu_options")) root.nu_options e
|
|||||||
pub const modules = root.nu_modules;
|
pub const modules = root.nu_modules;
|
||||||
pub const driver = root.nu_driver;
|
pub const driver = root.nu_driver;
|
||||||
|
|
||||||
pub fn run() !void {
|
pub const Hooks = struct {
|
||||||
try invoke_hook("nu_enter", .{});
|
pub const Enter = Hook(fn () void);
|
||||||
|
pub const Events = Hook(fn ([]Bus.Event) void);
|
||||||
|
pub const Frame = Hook(fn () anyerror!void);
|
||||||
|
pub const Close = Hook(fn () void);
|
||||||
|
|
||||||
|
enter: Enter,
|
||||||
|
events: Events,
|
||||||
|
frame: Frame,
|
||||||
|
close: Close,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub var hooks: Hooks = undefined;
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) void {
|
||||||
|
hooks = .{
|
||||||
|
.enter = Hooks.Enter.init(alloc),
|
||||||
|
.events = Hooks.Events.init(alloc),
|
||||||
|
.frame = Hooks.Frame.init(alloc),
|
||||||
|
.close = Hooks.Close.init(alloc),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
hooks.enter.deinit();
|
||||||
|
hooks.events.deinit();
|
||||||
|
hooks.frame.deinit();
|
||||||
|
hooks.close.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn run(alloc: std.mem.Allocator) !void {
|
||||||
|
// todo hooks should execute in priority order; then hook.register accepts a "priority" argument.
|
||||||
|
inline for (modules) |module| {
|
||||||
|
try module.connect();
|
||||||
|
}
|
||||||
|
|
||||||
|
hooks.enter.invoke(.{});
|
||||||
|
|
||||||
while (driver.next()) |events| {
|
while (driver.next()) |events| {
|
||||||
if (events.len > 0) {
|
if (events.len > 0) {
|
||||||
try invoke_hook("nu_events", .{events});
|
hooks.events.invoke(.{events});
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo frame timer
|
// todo frame timer
|
||||||
try invoke_hook("nu_frame", .{});
|
const frame_results = try hooks.frame.invoke(alloc, .{});
|
||||||
|
defer alloc.free(frame_results);
|
||||||
|
for (frame_results) |result| result catch |err| return err;
|
||||||
|
|
||||||
// todo fixed timestep
|
// todo fixed timestep
|
||||||
}
|
}
|
||||||
|
|
||||||
try invoke_hook("nu_close", .{});
|
hooks.close.invoke(.{});
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo specify hook type.
|
// // todo specify hook type.
|
||||||
// - special handling for error unions
|
// // - special handling for error unions
|
||||||
// - allow per-hook state somehow declared in the handler
|
// // - allow per-hook state somehow declared in the handler
|
||||||
|
//
|
||||||
pub fn invoke_hook(comptime name: []const u8, args: anytype) !void {
|
// pub fn invoke_hook(comptime name: []const u8, args: anytype) !void {
|
||||||
inline for (modules) |module| {
|
// inline for (modules) |module| {
|
||||||
if (@hasDecl(module, name)) {
|
// if (@hasDecl(module, name)) {
|
||||||
try invoke(@field(module, name), args);
|
// try invoke(@field(module, name), args);
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
//
|
||||||
fn invoke(func: anytype, args: anytype) !void {
|
// fn invoke(func: anytype, args: anytype) !void {
|
||||||
if (@typeInfo(@TypeOf(func)).Fn.return_type) |R| {
|
// if (@typeInfo(@TypeOf(func)).Fn.return_type) |R| {
|
||||||
switch (@typeInfo(R)) {
|
// switch (@typeInfo(R)) {
|
||||||
.ErrorUnion => try @call(.auto, func, args),
|
// .ErrorUnion => try @call(.auto, func, args),
|
||||||
.Void => @call(.auto, func, args),
|
// .Void => @call(.auto, func, args),
|
||||||
else => {
|
// else => {
|
||||||
@compileLog(func, @typeInfo(R));
|
// @compileLog(func, @typeInfo(R));
|
||||||
@compileError("Invalid hook return type. Must be void or !void.");
|
// @compileError("Invalid hook return type. Must be void or !void.");
|
||||||
},
|
// },
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
}
|
// }
|
||||||
|
@@ -6,6 +6,7 @@ const vk = @import("vk");
|
|||||||
const nu = @import("../nu.zig");
|
const nu = @import("../nu.zig");
|
||||||
const au = @import("Render/au.zig");
|
const au = @import("Render/au.zig");
|
||||||
|
|
||||||
|
const Hook = @import("hooks.zig").Hook;
|
||||||
const Render = @import("Render.zig");
|
const Render = @import("Render.zig");
|
||||||
const Window = @import("Window.zig");
|
const Window = @import("Window.zig");
|
||||||
|
|
||||||
@@ -14,6 +15,11 @@ pub usingnamespace im;
|
|||||||
|
|
||||||
pub const Options = struct {};
|
pub const Options = struct {};
|
||||||
|
|
||||||
|
pub const Hooks = struct {
|
||||||
|
pub const Frame = Hook(fn () void);
|
||||||
|
frame: Frame,
|
||||||
|
};
|
||||||
|
|
||||||
pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction {
|
pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction {
|
||||||
return au.glfwGetInstanceProcAddress(au.I.handle, procname);
|
return au.glfwGetInstanceProcAddress(au.I.handle, procname);
|
||||||
}
|
}
|
||||||
@@ -21,7 +27,9 @@ pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.Pf
|
|||||||
var ctx: *im.ImGuiContext = undefined;
|
var ctx: *im.ImGuiContext = undefined;
|
||||||
var descriptor_pool: vk.DescriptorPool = undefined;
|
var descriptor_pool: vk.DescriptorPool = undefined;
|
||||||
|
|
||||||
pub fn init() !void {
|
pub var hooks: Hooks = undefined;
|
||||||
|
|
||||||
|
pub fn init(alloc: std.mem.Allocator) !void {
|
||||||
ctx = im.igCreateContext(null) orelse {
|
ctx = im.igCreateContext(null) orelse {
|
||||||
return error.igCreateContextFailed;
|
return error.igCreateContextFailed;
|
||||||
};
|
};
|
||||||
@@ -77,6 +85,24 @@ pub fn init() !void {
|
|||||||
if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) {
|
if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) {
|
||||||
return error.igVulkanFontTextureFailed;
|
return error.igVulkanFontTextureFailed;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
hooks = .{
|
||||||
|
.frame = Hooks.Frame.init(alloc),
|
||||||
|
};
|
||||||
|
errdefer hooks.frame.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
hooks.frame.deinit();
|
||||||
|
im.impl.ImGui_ImplVulkan_Shutdown();
|
||||||
|
au.D.destroyDescriptorPool(descriptor_pool, null);
|
||||||
|
im.impl.ImGui_ImplGlfw_Shutdown();
|
||||||
|
im.igDestroyContext(ctx);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect() !void {
|
||||||
|
try nu.hooks.frame.register(nu_frame);
|
||||||
|
try Render.hooks.present.register(nu_render_present);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nu_frame() !void {
|
pub fn nu_frame() !void {
|
||||||
@@ -84,7 +110,7 @@ pub fn nu_frame() !void {
|
|||||||
im.impl.ImGui_ImplVulkan_NewFrame();
|
im.impl.ImGui_ImplVulkan_NewFrame();
|
||||||
im.igNewFrame();
|
im.igNewFrame();
|
||||||
|
|
||||||
try nu.invoke_hook("nu_imgui_frame", .{});
|
hooks.frame.invoke(.{});
|
||||||
|
|
||||||
im.igEndFrame();
|
im.igEndFrame();
|
||||||
im.igRender();
|
im.igRender();
|
||||||
@@ -97,10 +123,3 @@ pub fn nu_render_present(cmd: au.CommandBufferProxy) void {
|
|||||||
null,
|
null,
|
||||||
);
|
);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
|
||||||
im.impl.ImGui_ImplVulkan_Shutdown();
|
|
||||||
au.D.destroyDescriptorPool(descriptor_pool, null);
|
|
||||||
im.impl.ImGui_ImplGlfw_Shutdown();
|
|
||||||
im.igDestroyContext(ctx);
|
|
||||||
}
|
|
||||||
|
@@ -9,6 +9,8 @@ const vk = @import("vk");
|
|||||||
const nu = @import("../nu.zig");
|
const nu = @import("../nu.zig");
|
||||||
const au = @import("Render/au.zig");
|
const au = @import("Render/au.zig");
|
||||||
|
|
||||||
|
const Hook = @import("hooks.zig").Hook;
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Options = struct {
|
||||||
app_name: [*:0]const u8 = "nu-au-app",
|
app_name: [*:0]const u8 = "nu-au-app",
|
||||||
app_version: struct {
|
app_version: struct {
|
||||||
@@ -27,6 +29,14 @@ pub const Options = struct {
|
|||||||
frames_in_flight: u8 = 3,
|
frames_in_flight: u8 = 3,
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const Hooks = struct {
|
||||||
|
pub const Present = Hook(fn (au.CommandBufferProxy) void);
|
||||||
|
|
||||||
|
present: Present,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub var hooks: Hooks = undefined;
|
||||||
|
|
||||||
var sc: au.SwapChain = undefined;
|
var sc: au.SwapChain = undefined;
|
||||||
var flights: au.Flights = undefined;
|
var flights: au.Flights = undefined;
|
||||||
|
|
||||||
@@ -40,6 +50,21 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
|||||||
|
|
||||||
flights = try au.Flights.init(alloc, nu.options.render.frames_in_flight);
|
flights = try au.Flights.init(alloc, nu.options.render.frames_in_flight);
|
||||||
errdefer flights.deinit();
|
errdefer flights.deinit();
|
||||||
|
|
||||||
|
hooks = .{ .present = Hooks.Present.init(alloc) };
|
||||||
|
errdefer hooks.present.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit() void {
|
||||||
|
hooks.present.deinit();
|
||||||
|
flights.deinit();
|
||||||
|
sc.deinit();
|
||||||
|
au.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn connect() !void {
|
||||||
|
try nu.hooks.frame.register(nu_frame);
|
||||||
|
try nu.hooks.close.register(nu_close);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nu_frame() !void {
|
pub fn nu_frame() !void {
|
||||||
@@ -70,7 +95,7 @@ pub fn nu_frame() !void {
|
|||||||
|
|
||||||
// todo manage frame in flight state for each hook; pass the current flight in as context.
|
// todo manage frame in flight state for each hook; pass the current flight in as context.
|
||||||
// will need some comptime -> anytype mapping.
|
// will need some comptime -> anytype mapping.
|
||||||
try nu.invoke_hook("nu_render_present", .{cmd});
|
hooks.present.invoke(.{cmd});
|
||||||
|
|
||||||
target.end_rendering(cmd);
|
target.end_rendering(cmd);
|
||||||
try cmd.endCommandBuffer();
|
try cmd.endCommandBuffer();
|
||||||
@@ -102,12 +127,8 @@ pub fn nu_frame() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nu_close() !void {
|
pub fn nu_close() void {
|
||||||
try au.D.deviceWaitIdle();
|
au.D.deviceWaitIdle() catch |err| {
|
||||||
}
|
std.debug.panic("Device wait failed: {!}", .{err});
|
||||||
|
};
|
||||||
pub fn deinit() void {
|
|
||||||
flights.deinit();
|
|
||||||
sc.deinit();
|
|
||||||
au.deinit();
|
|
||||||
}
|
}
|
||||||
|
@@ -21,7 +21,7 @@ pub const Options = struct {
|
|||||||
x11_instance_name: [*:0]const u8 = "floating_window",
|
x11_instance_name: [*:0]const u8 = "floating_window",
|
||||||
};
|
};
|
||||||
|
|
||||||
var bus: Bus = undefined;
|
var bus: Bus = undefined; // todo bus should probably move to engine.
|
||||||
pub var handle: *c.GLFWwindow = undefined;
|
pub var handle: *c.GLFWwindow = undefined;
|
||||||
var unfocused_rate: f32 = 1.0 / 20.0;
|
var unfocused_rate: f32 = 1.0 / 20.0;
|
||||||
|
|
||||||
|
Reference in New Issue
Block a user