wip polymorphic modules
This commit is contained in:
26
src/App.zig
26
src/App.zig
@@ -5,24 +5,24 @@ const Bus = @import("nu/Bus.zig");
|
|||||||
const Render = @import("nu/Render.zig");
|
const Render = @import("nu/Render.zig");
|
||||||
const ImGui = @import("nu/ImGui.zig");
|
const ImGui = @import("nu/ImGui.zig");
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !void {
|
pub fn module() nu.Module {
|
||||||
_ = alloc;
|
return nu.Module{
|
||||||
|
.name = "App",
|
||||||
|
// .dependencies = &.{ Render.module(), ImGui.module() },
|
||||||
|
.setup = setup,
|
||||||
|
.teardown = teardown,
|
||||||
|
.update = update,
|
||||||
|
};
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect() !void {
|
pub fn setup(_: std.mem.Allocator) !void {
|
||||||
try ImGui.hooks.frame.register(nu_imgui_frame);
|
try ImGui.gui.register(gui);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {}
|
pub fn teardown() void {}
|
||||||
|
|
||||||
// pub fn nu_frame() void {}
|
pub fn update() !void {}
|
||||||
|
|
||||||
// pub fn nu_events(events: []const Bus.Event) void {
|
pub fn gui() void {
|
||||||
// std.debug.print("{any}\n", .{events});
|
|
||||||
// }
|
|
||||||
|
|
||||||
// pub fn nu_render_present(_: Render.au.CommandBufferProxy) void {}
|
|
||||||
|
|
||||||
pub fn nu_imgui_frame() void {
|
|
||||||
ImGui.igShowMetricsWindow(null);
|
ImGui.igShowMetricsWindow(null);
|
||||||
}
|
}
|
||||||
|
48
src/main.zig
48
src/main.zig
@@ -23,30 +23,32 @@ pub const nu_options: nu.Options = .{
|
|||||||
|
|
||||||
pub const nu_driver = nu.Window;
|
pub const nu_driver = nu.Window;
|
||||||
pub const nu_modules = .{
|
pub const nu_modules = .{
|
||||||
App,
|
|
||||||
nu.ImGui,
|
|
||||||
nu.Render,
|
nu.Render,
|
||||||
|
nu.ImGui,
|
||||||
|
App,
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn main() !void {
|
pub const main = nu.main;
|
||||||
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
|
||||||
defer _ = gpa.detectLeaks();
|
|
||||||
const alloc = gpa.allocator();
|
|
||||||
|
|
||||||
nu.init(alloc);
|
// pub fn main() !void {
|
||||||
defer nu.deinit();
|
// var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
|
// defer _ = gpa.detectLeaks();
|
||||||
try nu.Window.init(alloc);
|
// const alloc = gpa.allocator();
|
||||||
defer nu.Window.deinit();
|
//
|
||||||
|
// nu.init(alloc);
|
||||||
try nu.Render.init(alloc);
|
// defer nu.deinit();
|
||||||
defer nu.Render.deinit();
|
//
|
||||||
|
// try nu.Window.init(alloc);
|
||||||
try nu.ImGui.init(alloc);
|
// defer nu.Window.deinit();
|
||||||
defer nu.ImGui.deinit();
|
//
|
||||||
|
// try nu.Render.init(alloc);
|
||||||
try App.init(alloc);
|
// defer nu.Render.deinit();
|
||||||
defer App.deinit();
|
//
|
||||||
|
// try nu.ImGui.init(alloc);
|
||||||
try nu.run(alloc);
|
// defer nu.ImGui.deinit();
|
||||||
}
|
//
|
||||||
|
// try App.init(alloc);
|
||||||
|
// defer App.deinit();
|
||||||
|
//
|
||||||
|
// try nu.run(alloc);
|
||||||
|
// }
|
||||||
|
133
src/nu.zig
133
src/nu.zig
@@ -8,91 +8,80 @@ pub const ImGui = @import("nu/ImGui.zig");
|
|||||||
pub const Bus = @import("nu/Bus.zig");
|
pub const Bus = @import("nu/Bus.zig");
|
||||||
pub const Hook = @import("nu/hooks.zig").Hook;
|
pub const Hook = @import("nu/hooks.zig").Hook;
|
||||||
|
|
||||||
pub const Options = struct {
|
const Config = struct {
|
||||||
window: Window.Options = .{},
|
window: Window.Config = .{},
|
||||||
render: Render.Options = .{},
|
render: Render.Config = .{},
|
||||||
imgui: ImGui.Options = .{},
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const options: Options = if (@hasDecl(root, "nu_options")) root.nu_options else .{};
|
pub const config: Config = if (@hasDecl(root, "nu_config")) root.nu_config else .{};
|
||||||
pub const modules = root.nu_modules;
|
|
||||||
pub const driver = root.nu_driver;
|
|
||||||
|
|
||||||
pub const Hooks = struct {
|
pub const Module = struct {
|
||||||
pub const Enter = Hook(fn () void);
|
// todo dependencies
|
||||||
pub const Events = Hook(fn ([]Bus.Event) void);
|
name: []const u8,
|
||||||
pub const Frame = Hook(fn () anyerror!void);
|
setup: *const fn (alloc: std.mem.Allocator) anyerror!void,
|
||||||
pub const Close = Hook(fn () void);
|
teardown: *const fn () void,
|
||||||
|
update: ?*const fn () anyerror!void = null,
|
||||||
enter: Enter,
|
frame: ?*const fn () anyerror!void = null,
|
||||||
events: Events,
|
dependencies: []const Module = &.{},
|
||||||
frame: Frame,
|
|
||||||
close: Close,
|
|
||||||
};
|
};
|
||||||
|
|
||||||
pub var hooks: Hooks = undefined;
|
pub const Driver = struct {
|
||||||
|
module: Module,
|
||||||
|
next: *const fn () bool, // events? callbacks?
|
||||||
|
};
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) void {
|
fn enable(modules: *std.StringArrayHashMap(Module), module: Module) void {
|
||||||
hooks = .{
|
// this doesn't handle dependencies correctly. need to do real topological sort.
|
||||||
.enter = Hooks.Enter.init(alloc),
|
|
||||||
.events = Hooks.Events.init(alloc),
|
if (modules.contains(module.name)) return;
|
||||||
.frame = Hooks.Frame.init(alloc),
|
for (module.dependencies) |dep| enable(modules, dep);
|
||||||
.close = Hooks.Close.init(alloc),
|
modules.putNoClobber(module.name, module) catch @panic("OOM");
|
||||||
};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn main() void {
|
||||||
hooks.enter.deinit();
|
var gpa = std.heap.GeneralPurposeAllocator(.{}){};
|
||||||
hooks.events.deinit();
|
const alloc = gpa.allocator();
|
||||||
hooks.frame.deinit();
|
|
||||||
hooks.close.deinit();
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn run(alloc: std.mem.Allocator) !void {
|
var modules = std.StringArrayHashMap(Module).init(alloc);
|
||||||
// todo hooks should execute in priority order; then hook.register accepts a "priority" argument.
|
defer modules.deinit();
|
||||||
inline for (modules) |module| {
|
|
||||||
try module.connect();
|
const driver = root.nu_driver.driver();
|
||||||
|
enable(&modules, driver.module);
|
||||||
|
inline for (root.nu_modules) |mod| {
|
||||||
|
enable(&modules, mod.module());
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.enter.invoke(.{});
|
for (modules.values()) |mod| {
|
||||||
|
std.log.debug("{s}.setup", .{mod.name});
|
||||||
|
mod.setup(alloc) catch |err| {
|
||||||
|
std.debug.panic("Module {s} setup error: {!}", .{ mod.name, err });
|
||||||
|
};
|
||||||
|
}
|
||||||
|
defer {
|
||||||
|
var rev = std.mem.reverseIterator(modules.values());
|
||||||
|
while (rev.next()) |mod| {
|
||||||
|
std.log.debug("{s}.teardown", .{mod.name});
|
||||||
|
mod.teardown();
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
while (driver.next()) |events| {
|
std.log.info("Loaded modules: {s}", .{modules.keys()});
|
||||||
if (events.len > 0) {
|
|
||||||
hooks.events.invoke(.{events});
|
while (driver.next()) {
|
||||||
|
for (modules.values()) |mod| {
|
||||||
|
if (mod.update) |update| {
|
||||||
|
update() catch |err| {
|
||||||
|
std.debug.panic("Module {s} update event error: {!}", .{ mod.name, err });
|
||||||
|
};
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// todo frame timer
|
for (modules.values()) |mod| {
|
||||||
const frame_results = try hooks.frame.invoke(alloc, .{});
|
if (mod.frame) |frame| {
|
||||||
defer alloc.free(frame_results);
|
frame() catch |err| {
|
||||||
for (frame_results) |result| result catch |err| return err;
|
std.debug.panic("Module {s} frame event error: {!}", .{ mod.name, err });
|
||||||
|
};
|
||||||
// todo fixed timestep
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
hooks.close.invoke(.{});
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// // todo specify hook type.
|
|
||||||
// // - special handling for error unions
|
|
||||||
// // - allow per-hook state somehow declared in the handler
|
|
||||||
//
|
|
||||||
// pub fn invoke_hook(comptime name: []const u8, args: anytype) !void {
|
|
||||||
// inline for (modules) |module| {
|
|
||||||
// if (@hasDecl(module, name)) {
|
|
||||||
// try invoke(@field(module, name), args);
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
//
|
|
||||||
// fn invoke(func: anytype, args: anytype) !void {
|
|
||||||
// if (@typeInfo(@TypeOf(func)).Fn.return_type) |R| {
|
|
||||||
// switch (@typeInfo(R)) {
|
|
||||||
// .ErrorUnion => try @call(.auto, func, args),
|
|
||||||
// .Void => @call(.auto, func, args),
|
|
||||||
// else => {
|
|
||||||
// @compileLog(func, @typeInfo(R));
|
|
||||||
// @compileError("Invalid hook return type. Must be void or !void.");
|
|
||||||
// },
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
// }
|
|
||||||
|
@@ -13,23 +13,33 @@ const Window = @import("Window.zig");
|
|||||||
const im = @import("cimgui");
|
const im = @import("cimgui");
|
||||||
pub usingnamespace im;
|
pub usingnamespace im;
|
||||||
|
|
||||||
pub const Options = struct {};
|
pub const Config = struct {};
|
||||||
|
const config = nu.config.imgui;
|
||||||
|
|
||||||
pub const Hooks = struct {
|
pub fn module() nu.Module {
|
||||||
pub const Frame = Hook(fn () void);
|
return nu.Module{
|
||||||
frame: Frame,
|
.name = "ImGui",
|
||||||
};
|
// .dependencies = &.{Render.module()},
|
||||||
|
.setup = setup,
|
||||||
|
.teardown = teardown,
|
||||||
|
.update = update,
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
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);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub var gui: Hook(fn () void) = undefined;
|
||||||
var ctx: *im.ImGuiContext = undefined;
|
var ctx: *im.ImGuiContext = undefined;
|
||||||
var descriptor_pool: vk.DescriptorPool = undefined;
|
var descriptor_pool: vk.DescriptorPool = undefined;
|
||||||
|
|
||||||
pub var hooks: Hooks = undefined;
|
pub fn setup(alloc: std.mem.Allocator) !void {
|
||||||
|
gui = @TypeOf(gui).init(alloc);
|
||||||
|
errdefer gui.deinit();
|
||||||
|
|
||||||
|
try Render.present.register(present);
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !void {
|
|
||||||
ctx = im.igCreateContext(null) orelse {
|
ctx = im.igCreateContext(null) orelse {
|
||||||
return error.igCreateContextFailed;
|
return error.igCreateContextFailed;
|
||||||
};
|
};
|
||||||
@@ -64,7 +74,7 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
|||||||
.DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)),
|
.DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)),
|
||||||
.RenderPass = null,
|
.RenderPass = null,
|
||||||
.MinImageCount = 2,
|
.MinImageCount = 2,
|
||||||
.ImageCount = @intCast(nu.options.render.frames_in_flight),
|
.ImageCount = @intCast(nu.config.render.frames_in_flight),
|
||||||
.PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{
|
.PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{
|
||||||
.view_mask = 0,
|
.view_mask = 0,
|
||||||
.depth_attachment_format = .undefined,
|
.depth_attachment_format = .undefined,
|
||||||
@@ -85,38 +95,30 @@ pub fn init(alloc: std.mem.Allocator) !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 {
|
pub fn teardown() void {
|
||||||
hooks.frame.deinit();
|
au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
|
||||||
|
|
||||||
im.impl.ImGui_ImplVulkan_Shutdown();
|
im.impl.ImGui_ImplVulkan_Shutdown();
|
||||||
au.D.destroyDescriptorPool(descriptor_pool, null);
|
au.D.destroyDescriptorPool(descriptor_pool, null);
|
||||||
im.impl.ImGui_ImplGlfw_Shutdown();
|
im.impl.ImGui_ImplGlfw_Shutdown();
|
||||||
im.igDestroyContext(ctx);
|
im.igDestroyContext(ctx);
|
||||||
|
gui.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect() !void {
|
pub fn update() !void {
|
||||||
try nu.hooks.frame.register(nu_frame);
|
|
||||||
try Render.hooks.present.register(nu_render_present);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nu_frame() !void {
|
|
||||||
im.impl.ImGui_ImplGlfw_NewFrame();
|
im.impl.ImGui_ImplGlfw_NewFrame();
|
||||||
im.impl.ImGui_ImplVulkan_NewFrame();
|
im.impl.ImGui_ImplVulkan_NewFrame();
|
||||||
im.igNewFrame();
|
im.igNewFrame();
|
||||||
|
|
||||||
hooks.frame.invoke(.{});
|
gui.invoke(.{});
|
||||||
|
|
||||||
im.igEndFrame();
|
im.igEndFrame();
|
||||||
im.igRender();
|
im.igRender();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nu_render_present(cmd: au.CommandBufferProxy) void {
|
pub fn present(cmd: au.CommandBufferProxy) void {
|
||||||
im.impl.ImGui_ImplVulkan_RenderDrawData(
|
im.impl.ImGui_ImplVulkan_RenderDrawData(
|
||||||
@ptrCast(im.igGetDrawData()),
|
@ptrCast(im.igGetDrawData()),
|
||||||
@ptrFromInt(@intFromEnum(cmd.handle)),
|
@ptrFromInt(@intFromEnum(cmd.handle)),
|
||||||
|
@@ -9,9 +9,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;
|
pub const Config = 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 {
|
||||||
variant: u3 = 0,
|
variant: u3 = 0,
|
||||||
@@ -27,20 +25,29 @@ pub const Options = struct {
|
|||||||
patch: u12 = 0,
|
patch: u12 = 0,
|
||||||
} = .{},
|
} = .{},
|
||||||
frames_in_flight: u8 = 3,
|
frames_in_flight: u8 = 3,
|
||||||
|
use_debug_messenger: bool = switch (builtin.mode) {
|
||||||
|
.Debug, .ReleaseSafe => true,
|
||||||
|
.ReleaseSmall, .ReleaseFast => false,
|
||||||
|
},
|
||||||
};
|
};
|
||||||
|
const config = nu.config.render;
|
||||||
|
|
||||||
pub const Hooks = struct {
|
pub fn module() nu.Module {
|
||||||
pub const Present = Hook(fn (au.CommandBufferProxy) void);
|
return nu.Module{
|
||||||
|
.name = "Render",
|
||||||
present: Present,
|
.setup = setup,
|
||||||
};
|
.teardown = teardown,
|
||||||
|
.frame = frame,
|
||||||
pub var hooks: Hooks = undefined;
|
.dependencies = &.{nu.Window.driver().module},
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
var sc: au.SwapChain = undefined;
|
var sc: au.SwapChain = undefined;
|
||||||
var flights: au.Flights = undefined;
|
var flights: au.Flights = undefined;
|
||||||
|
|
||||||
pub fn init(alloc: std.mem.Allocator) !void {
|
pub var present: nu.Hook(fn (au.CommandBufferProxy) void) = undefined;
|
||||||
|
|
||||||
|
pub fn setup(alloc: std.mem.Allocator) !void {
|
||||||
// todo pick apart au into helpers; not a sub-module filled with its own globals.
|
// todo pick apart au into helpers; not a sub-module filled with its own globals.
|
||||||
try au.init(alloc);
|
try au.init(alloc);
|
||||||
errdefer au.deinit();
|
errdefer au.deinit();
|
||||||
@@ -48,26 +55,22 @@ pub fn init(alloc: std.mem.Allocator) !void {
|
|||||||
sc = try au.SwapChain.init(alloc);
|
sc = try au.SwapChain.init(alloc);
|
||||||
errdefer sc.deinit();
|
errdefer sc.deinit();
|
||||||
|
|
||||||
flights = try au.Flights.init(alloc, nu.options.render.frames_in_flight);
|
flights = try au.Flights.init(alloc, config.frames_in_flight);
|
||||||
errdefer flights.deinit();
|
errdefer flights.deinit();
|
||||||
|
|
||||||
hooks = .{ .present = Hooks.Present.init(alloc) };
|
present = @TypeOf(present).init(alloc);
|
||||||
errdefer hooks.present.deinit();
|
errdefer present.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub fn teardown() void {
|
||||||
hooks.present.deinit();
|
au.D.deviceWaitIdle() catch |err| std.debug.panic("Device wait failed: {!}", .{err});
|
||||||
|
errdefer present.deinit();
|
||||||
flights.deinit();
|
flights.deinit();
|
||||||
sc.deinit();
|
sc.deinit();
|
||||||
au.deinit();
|
au.deinit();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn connect() !void {
|
pub fn frame() !void {
|
||||||
try nu.hooks.frame.register(nu_frame);
|
|
||||||
try nu.hooks.close.register(nu_close);
|
|
||||||
}
|
|
||||||
|
|
||||||
pub fn nu_frame() !void {
|
|
||||||
const flight: au.Flights.Flight = flights.next();
|
const flight: au.Flights.Flight = flights.next();
|
||||||
try flight.wait();
|
try flight.wait();
|
||||||
|
|
||||||
@@ -95,7 +98,8 @@ 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.
|
||||||
hooks.present.invoke(.{cmd});
|
|
||||||
|
present.invoke(.{cmd});
|
||||||
|
|
||||||
target.end_rendering(cmd);
|
target.end_rendering(cmd);
|
||||||
try cmd.endCommandBuffer();
|
try cmd.endCommandBuffer();
|
||||||
@@ -126,9 +130,3 @@ pub fn nu_frame() !void {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn nu_close() void {
|
|
||||||
au.D.deviceWaitIdle() catch |err| {
|
|
||||||
std.debug.panic("Device wait failed: {!}", .{err});
|
|
||||||
};
|
|
||||||
}
|
|
||||||
|
@@ -8,10 +8,7 @@ pub const SwapChain = @import("au/SwapChain.zig");
|
|||||||
pub const Flights = @import("au/Flights.zig");
|
pub const Flights = @import("au/Flights.zig");
|
||||||
pub const VkAllocator = @import("au/VkAllocator.zig");
|
pub const VkAllocator = @import("au/VkAllocator.zig");
|
||||||
|
|
||||||
pub const use_debug_messenger = switch (builtin.mode) {
|
const config = nu.config.render;
|
||||||
.Debug, .ReleaseSafe => true,
|
|
||||||
.ReleaseSmall, .ReleaseFast => false,
|
|
||||||
};
|
|
||||||
|
|
||||||
pub const apis: []const vk.ApiInfo = &.{
|
pub const apis: []const vk.ApiInfo = &.{
|
||||||
vk.features.version_1_0,
|
vk.features.version_1_0,
|
||||||
@@ -21,7 +18,7 @@ pub const apis: []const vk.ApiInfo = &.{
|
|||||||
vk.extensions.khr_surface,
|
vk.extensions.khr_surface,
|
||||||
vk.extensions.khr_swapchain,
|
vk.extensions.khr_swapchain,
|
||||||
vk.extensions.khr_dynamic_rendering,
|
vk.extensions.khr_dynamic_rendering,
|
||||||
if (use_debug_messenger) vk.extensions.ext_debug_utils else .{},
|
if (config.use_debug_messenger) vk.extensions.ext_debug_utils else .{},
|
||||||
};
|
};
|
||||||
|
|
||||||
pub const device_extensions: []const [*:0]const u8 = &.{
|
pub const device_extensions: []const [*:0]const u8 = &.{
|
||||||
@@ -82,7 +79,7 @@ fn init_base() !void {
|
|||||||
if (glfwVulkanSupported() != nu.Window.c.GLFW_TRUE)
|
if (glfwVulkanSupported() != nu.Window.c.GLFW_TRUE)
|
||||||
return error.glfwNoVulkan;
|
return error.glfwNoVulkan;
|
||||||
|
|
||||||
if (use_debug_messenger) {
|
if (config.use_debug_messenger) {
|
||||||
_bw = try BaseWrapper.load(glfwGetInstanceProcAddress);
|
_bw = try BaseWrapper.load(glfwGetInstanceProcAddress);
|
||||||
} else {
|
} else {
|
||||||
_bw = BaseWrapper.loadNoFail(glfwGetInstanceProcAddress);
|
_bw = BaseWrapper.loadNoFail(glfwGetInstanceProcAddress);
|
||||||
@@ -98,7 +95,7 @@ fn init_instance(alloc: std.mem.Allocator) !void {
|
|||||||
var layers = std.ArrayList([*:0]const u8).init(alloc);
|
var layers = std.ArrayList([*:0]const u8).init(alloc);
|
||||||
defer layers.deinit();
|
defer layers.deinit();
|
||||||
|
|
||||||
if (use_debug_messenger) {
|
if (config.use_debug_messenger) {
|
||||||
try extensions.appendSlice(&.{
|
try extensions.appendSlice(&.{
|
||||||
vk.extensions.ext_debug_utils.name,
|
vk.extensions.ext_debug_utils.name,
|
||||||
});
|
});
|
||||||
@@ -132,19 +129,19 @@ fn init_instance(alloc: std.mem.Allocator) !void {
|
|||||||
|
|
||||||
_instance = try B.createInstance(&.{
|
_instance = try B.createInstance(&.{
|
||||||
.p_application_info = &.{
|
.p_application_info = &.{
|
||||||
.p_application_name = nu.options.render.app_name,
|
.p_application_name = config.app_name,
|
||||||
.application_version = vk.makeApiVersion(
|
.application_version = vk.makeApiVersion(
|
||||||
nu.options.render.app_version.variant,
|
config.app_version.variant,
|
||||||
nu.options.render.app_version.major,
|
config.app_version.major,
|
||||||
nu.options.render.app_version.minor,
|
config.app_version.minor,
|
||||||
nu.options.render.app_version.patch,
|
config.app_version.patch,
|
||||||
),
|
),
|
||||||
.p_engine_name = nu.options.render.engine_name,
|
.p_engine_name = config.engine_name,
|
||||||
.engine_version = vk.makeApiVersion(
|
.engine_version = vk.makeApiVersion(
|
||||||
nu.options.render.engine_version.variant,
|
config.engine_version.variant,
|
||||||
nu.options.render.engine_version.major,
|
config.engine_version.major,
|
||||||
nu.options.render.engine_version.minor,
|
config.engine_version.minor,
|
||||||
nu.options.render.engine_version.patch,
|
config.engine_version.patch,
|
||||||
),
|
),
|
||||||
.api_version = vk.API_VERSION_1_3,
|
.api_version = vk.API_VERSION_1_3,
|
||||||
},
|
},
|
||||||
@@ -152,10 +149,10 @@ fn init_instance(alloc: std.mem.Allocator) !void {
|
|||||||
.pp_enabled_extension_names = extensions.items.ptr,
|
.pp_enabled_extension_names = extensions.items.ptr,
|
||||||
.enabled_layer_count = @intCast(layers.items.len),
|
.enabled_layer_count = @intCast(layers.items.len),
|
||||||
.pp_enabled_layer_names = layers.items.ptr,
|
.pp_enabled_layer_names = layers.items.ptr,
|
||||||
.p_next = if (use_debug_messenger) &mci else null,
|
.p_next = if (config.use_debug_messenger) &mci else null,
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
if (use_debug_messenger) {
|
if (config.use_debug_messenger) {
|
||||||
_iw = try InstanceWrapper.load(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
_iw = try InstanceWrapper.load(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
||||||
} else {
|
} else {
|
||||||
_iw = InstanceWrapper.loadNoFail(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
_iw = InstanceWrapper.loadNoFail(_instance, _bw.dispatch.vkGetInstanceProcAddr);
|
||||||
@@ -306,7 +303,7 @@ fn init_device(alloc: std.mem.Allocator) !void {
|
|||||||
},
|
},
|
||||||
}, null);
|
}, null);
|
||||||
|
|
||||||
if (use_debug_messenger) {
|
if (config.use_debug_messenger) {
|
||||||
_dw = try DeviceWrapper.load(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
_dw = try DeviceWrapper.load(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
||||||
} else {
|
} else {
|
||||||
_dw = DeviceWrapper.loadNoFail(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
_dw = DeviceWrapper.loadNoFail(_device, _iw.dispatch.vkGetDeviceProcAddr);
|
||||||
|
@@ -13,61 +13,62 @@ pub const c = @cImport({
|
|||||||
|
|
||||||
pub const Bus = @import("Bus.zig");
|
pub const Bus = @import("Bus.zig");
|
||||||
|
|
||||||
pub const Options = struct {
|
pub const Config = struct {
|
||||||
title: [*:0]const u8 = "Hello World",
|
title: [*:0]const u8 = "Hello World",
|
||||||
width: u32 = 1280,
|
width: u32 = 1280,
|
||||||
height: u32 = 720,
|
height: u32 = 720,
|
||||||
x11_class_name: [*:0]const u8 = "floating_window",
|
x11_class_name: [*:0]const u8 = "floating_window",
|
||||||
x11_instance_name: [*:0]const u8 = "floating_window",
|
x11_instance_name: [*:0]const u8 = "floating_window",
|
||||||
|
unfocused_wait: f32 = 1.0 / 20.0,
|
||||||
};
|
};
|
||||||
|
const config: Config = nu.config.window;
|
||||||
|
|
||||||
var bus: Bus = undefined; // todo bus should probably move to engine.
|
pub fn driver() nu.Driver {
|
||||||
pub var handle: *c.GLFWwindow = undefined;
|
return nu.Driver{
|
||||||
var unfocused_rate: f32 = 1.0 / 20.0;
|
.module = .{
|
||||||
|
.name = "Window",
|
||||||
pub fn init(alloc: std.mem.Allocator) !void {
|
.dependencies = &.{}, // todo bus
|
||||||
if (c.glfwInit() != c.GLFW_TRUE)
|
.setup = setup,
|
||||||
return error.glfwInitFailed;
|
.teardown = teardown,
|
||||||
errdefer c.glfwTerminate();
|
},
|
||||||
|
.next = next,
|
||||||
bus = Bus.init(alloc);
|
};
|
||||||
errdefer bus.deinit();
|
|
||||||
|
|
||||||
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
|
||||||
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, nu.options.window.x11_class_name);
|
|
||||||
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, nu.options.window.x11_instance_name);
|
|
||||||
|
|
||||||
handle = c.glfwCreateWindow(
|
|
||||||
@intCast(nu.options.window.width),
|
|
||||||
@intCast(nu.options.window.height),
|
|
||||||
nu.options.window.title,
|
|
||||||
null,
|
|
||||||
null,
|
|
||||||
) orelse
|
|
||||||
return error.glfWCreateWindowFailed;
|
|
||||||
errdefer c.glfwDestroyWindow(handle);
|
|
||||||
|
|
||||||
bus.connect(handle);
|
|
||||||
errdefer bus.disconnect(handle);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn deinit() void {
|
pub var handle: *c.GLFWwindow = undefined;
|
||||||
bus.deinit();
|
|
||||||
|
pub fn setup(_: std.mem.Allocator) !void {
|
||||||
|
if (c.glfwInit() != c.GLFW_TRUE) std.debug.panic("GLFW Init Failed", .{});
|
||||||
|
|
||||||
|
c.glfwWindowHint(c.GLFW_CLIENT_API, c.GLFW_NO_API);
|
||||||
|
c.glfwWindowHintString(c.GLFW_X11_CLASS_NAME, config.x11_class_name);
|
||||||
|
c.glfwWindowHintString(c.GLFW_X11_INSTANCE_NAME, config.x11_instance_name);
|
||||||
|
handle = c.glfwCreateWindow(
|
||||||
|
@intCast(config.width),
|
||||||
|
@intCast(config.height),
|
||||||
|
config.title,
|
||||||
|
null,
|
||||||
|
null,
|
||||||
|
) orelse std.debug.panic("GLFW Create Window Failed", .{});
|
||||||
|
|
||||||
|
// bus.connect(handle);
|
||||||
|
// errdefer bus.disconnect(handle);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn teardown() void {
|
||||||
c.glfwDestroyWindow(handle);
|
c.glfwDestroyWindow(handle);
|
||||||
c.glfwTerminate();
|
c.glfwTerminate();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn next() ?[]Bus.Event {
|
pub fn next() bool {
|
||||||
bus.clear();
|
|
||||||
|
|
||||||
if (c.glfwWindowShouldClose(handle) == c.GLFW_TRUE)
|
if (c.glfwWindowShouldClose(handle) == c.GLFW_TRUE)
|
||||||
return null;
|
return false;
|
||||||
|
|
||||||
if (c.glfwGetWindowAttrib(handle, c.GLFW_FOCUSED) == c.GLFW_TRUE) {
|
if (c.glfwGetWindowAttrib(handle, c.GLFW_FOCUSED) == c.GLFW_TRUE) {
|
||||||
c.glfwPollEvents();
|
c.glfwPollEvents();
|
||||||
} else {
|
} else {
|
||||||
c.glfwWaitEventsTimeout(unfocused_rate);
|
c.glfwWaitEventsTimeout(config.unfocused_wait);
|
||||||
}
|
}
|
||||||
|
|
||||||
return bus.events.items;
|
return true;
|
||||||
}
|
}
|
||||||
|
@@ -28,7 +28,7 @@ pub fn Hook(ftype: type) type {
|
|||||||
_ = self.handlers.orderedRemove(f);
|
_ = self.handlers.orderedRemove(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke(self: Self, args: anytype) void {
|
pub fn invoke(self: Self, args: anytype) void {
|
||||||
for (self.handlers.keys()) |handler| {
|
for (self.handlers.keys()) |handler| {
|
||||||
@call(.auto, handler, args);
|
@call(.auto, handler, args);
|
||||||
}
|
}
|
||||||
@@ -57,7 +57,7 @@ pub fn Hook(ftype: type) type {
|
|||||||
_ = self.handlers.orderedRemove(f);
|
_ = self.handlers.orderedRemove(f);
|
||||||
}
|
}
|
||||||
|
|
||||||
fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result {
|
pub fn invoke(self: Self, alloc: std.mem.Allocator, args: anytype) ![]Result {
|
||||||
const results = try alloc.alloc(Result, self.handlers.count());
|
const results = try alloc.alloc(Result, self.handlers.count());
|
||||||
for (self.handlers.keys(), results) |handler, *result| {
|
for (self.handlers.keys(), results) |handler, *result| {
|
||||||
result.* = @call(.auto, handler, args);
|
result.* = @call(.auto, handler, args);
|
||||||
|
Reference in New Issue
Block a user