Backlog/engine/backlog.zig

191 lines
6.4 KiB
Zig

//pub const core = @import("core");
//pub const platform = @import("platform");
//pub const assets = @import("assets");
//pub const rend = @import("rend");
//pub const audio = @import("audio");
//pub const ui = @import("ui");
//pub const papyrus = @import("papyrus");
//pub const physics = @import("physics");
//pub const imgui = @import("imgui");
pub const core = @import("core").module;
pub const platform = @import("platform").module;
pub const assets = @import("assets").module;
pub const rend = @import("rend").module;
pub const audio = @import("audio").module;
pub const net = @import("net").module;
pub const ui = @import("ui").module;
pub const papyrus = @import("papyrus").module;
pub const physics = @import("physics").module;
pub const imgui = @import("imgui").module;
pub const sys = @import("sys").module;
const modulelist = @import("modulelist.zig").list;
const std = @import("std");
pub const NwArgs = struct {
useGPA: bool = false, // slower zig based memory allocator, provides detailed tracking of leaks and memory violations
vulkanValidation: bool = true,
fastTest: bool = false,
dmt: bool = false, // detailed memory tracking, implements a timeline for tracking all memory allocations
fatDump: bool = false, // takes a full fat minidump on crash, very large files are produced
};
pub fn getArgs() !NwArgs {
const a = try core.ParseArgs(NwArgs);
return a;
}
// entry function for a backlog program
// when this function is called it will use the settings specified by the program spec
// to conditionally start up feature modules within the engine
var shutdownList: std.ArrayListUnmanaged(*const fn (std.mem.Allocator) void) = .{};
var shutdownModuleNames: std.ArrayListUnmanaged([]const u8) = .{};
pub fn start_modules(spec: *core.SpecVariantMap, maybeArgs: ?NwArgs, allocator: std.mem.Allocator) !void {
const Backlog = @This();
var z = core.tracy.ZoneN(@src(), "Starting all Modules");
defer z.End();
inline for (modulelist) |feature| {
if (@hasDecl(Backlog, feature)) {
const Struct = @field(Backlog, feature);
if (core.isModuleEnabled(Struct.Module, spec)) {
var z1 = core.tracy.ZoneN(@src(), @ptrCast("Initializing Module"));
defer z1.End();
core.tracy.Message(Struct.Module.name);
if (maybeArgs) |args| {
try Struct.start_module(spec, args, allocator);
} else {
try Struct.start_module(spec, NwArgs{}, allocator);
}
try shutdownList.append(allocator, Struct.shutdown_module);
try shutdownModuleNames.append(allocator, feature);
core.engine_logs("module started >>>> " ++ feature ++ " <<<<");
}
}
}
}
pub const ModuleStartup = struct {
name: []const u8,
startupFunc: *const fn (map: *core.SpecVariantMap, args: anytype, allocator: std.mem.Allocator) core.ModuleStartupError!void,
shutdownFunc: *const fn (*const fn (std.mem.Allocator) void) void,
};
// read moduleList from root
pub fn start_modules_list(list: []const ModuleStartup, spec: *core.SpecVariantMap, maybeArgs: ?NwArgs, allocator: std.mem.Allocator) !void {
var z = core.tracy.ZoneN(@src(), "Starting all Modules");
defer z.End();
for (list) |feature| {
//if (@hasDecl(Backlog, feature)) {
core.engine_logs("starting module >> {s}", .{feature.name});
try feature.startupFunc(spec, maybeArgs orelse NwArgs{}, allocator);
try shutdownList.append(allocator, feature.shutdownFunc);
try shutdownModuleNames.append(allocator, feature.name);
core.engine_logs("module started {s}! ", .{feature.name});
}
//}
}
pub fn shutdown_modules(allocator: std.mem.Allocator) void {
var i: isize = @intCast(shutdownList.items.len - 1);
while (i >= 0) : (i -= 1) {
core.engine_log("module shutting down >>>> {s} <<<<", .{shutdownModuleNames.items[@intCast(i)]});
shutdownList.items[@intCast(i)](allocator);
}
shutdownList.deinit(allocator);
shutdownModuleNames.deinit(allocator);
}
pub fn start_everything(spec: *core.SpecVariantMap, allocator: std.mem.Allocator, maybeArgs: ?NwArgs) !void {
//if (maybeArgs) |args| {
// //if (args.vulkanValidation)
// // graphics.setStartupSettings("vulkanValidation", true);
//}
try start_modules(spec, maybeArgs, allocator);
}
pub fn shutdown_everything(allocator: std.mem.Allocator) void {
shutdown_modules(allocator);
}
pub fn run_everything_vtable(gameVtable: *core.EngineObjectVTable) !void {
core.engine_logs("creating Game context");
//_ = try core.createObject(GameContext, .{});
_ = try core.createObjectVTable(gameVtable, .{});
core.engine_logs("calling gEngine.run");
try core.getEngine().run();
while (!core.getEngine().exitFinished()) {
const z = core.tracy.ZoneN(@src(), "shutdown poll");
z.End();
}
}
pub fn run_everything(gameVtable: *const core.EngineObjectVTable) !void {
core.engine_logs("creating Game context");
//_ = try core.createObject(GameContext, .{});
_ = try core.createObjectVTable(gameVtable, .{});
core.engine_logs("calling gEngine.run");
try core.getEngine().run();
while (!core.getEngine().exitFinished()) {
const z = core.tracy.ZoneN(@src(), "shutdown poll");
z.End();
}
}
pub const createSpecVariant = core.createSpecVariant;
pub export fn initAndRun(vtable: *core.EngineObjectVTable, spec: *core.SpecVariantMap) bool {
const args = getArgs() catch return false;
var backingAllocator: std.mem.Allocator = std.heap.c_allocator;
var gpa: std.heap.GeneralPurposeAllocator(.{
.stack_trace_frames = 20,
}) = .{};
defer {
const cleanupStatus = gpa.deinit();
if (cleanupStatus == .leak) {
std.debug.print("gpa cleanup leaked memory\n", .{});
}
}
if (spec.get("useGPA")) |arg| {
if (arg.boolean == true) {
backingAllocator = gpa.allocator();
}
}
const memory = core.MemoryTracker;
memory.MTSetup(backingAllocator, .{ .timeline = args.dmt });
defer memory.MTShutdown();
var tracker = memory.MTGet().?;
const allocator = tracker.allocator();
start_everything(spec, allocator, args) catch return false;
defer shutdown_everything(allocator);
run_everything_vtable(vtable) catch return false;
return true;
}