const std = @import("std"); const Base = @import("Base.zig"); const Instance = @import("instance.zig").Instance; const Display = @import("display.zig").Display; const Window = @import("display.zig").Window; const Device = @import("device.zig").Device; const memory = @import("memory.zig"); const framebuffer = @import("framebuffer.zig"); const Swapchain = @import("swapchain.zig").Swapchain; const Context = @import("Context.zig"); const MainPass = @import("MainPass.zig"); const Command = @import("Command.zig"); const Targets = @import("Targets.zig"); const Bindings = @import("Bindings.zig"); const meshes = @import("meshes.zig"); const ui = @import("../../ui/ui.zig"); instance: Instance, window: Window, device: Device, swapchain: Swapchain, // sampler: Sampler, TODO // tex_table: TexTable, TODO // im_sys: ImSys, TODO const Self = @This(); pub fn init() !Self { errdefer { std.debug.print("failed to init VulkanRenderer\n", .{}); } try Base.init(); const instance = try Instance.init(); errdefer instance.deinit(); var window = try windowInit(&instance); errdefer window.deinit(&instance); try ui.init(&window); const device = try Device.init(&instance, &window); errdefer device.deinit(); try memory.init(&instance, &device); errdefer memory.deinit(&device); try framebuffer.init(); errdefer framebuffer.deinit(&device); var swapchain = try Swapchain.init(&instance, &window, &device, null); errdefer swapchain.deinit(&device); Context.init(); errdefer Context.deinit(); // try self.sampler.init(); // try self.texTable.init(); try Bindings.init(&device); try Targets.init(&device, &swapchain); try meshes.init(); // try self.imSys.init(); try MainPass.init(&device, &swapchain); return Self{ .instance = instance, .window = window, .device = device, .swapchain = swapchain, }; } pub fn update(self: *Self) !void { // TODO profiling // base system update { _ = try self.swapchain.acquireSync(&self.device); _ = try self.swapchain.acquireImage(&self.device); try memory.update(&self.device); } // system update { // TODO: sampler/meshsys/imsys update } // setup phase { try MainPass.setup(&self.device, &self.swapchain); // TODO textable update try Command.flush(&self.device); Bindings.update(&self.device, &self.swapchain); } // execute phase try MainPass.execute(&self.device, &self.swapchain); // present phase // currently only graphics queue try self.swapchain.submit(try Command.Buffer.get(.graphics, &self.device), &self.device); // background work { // TODO upload lightmaps, imsys clear try Command.flush(&self.device); } } pub fn deinit(self: Self) void { self.device.waitIdle() catch {}; // TODO: delete lightmap pack MainPass.deinit(&self.device); // self.imSys.deinit(); meshes.deinit(); Targets.deinit(&self.device); Bindings.deinit(&self.device); // self.texTable.deinit(); // self.sampler.deinit(); // clear other passes here. memory.finalize(&self.device) catch {}; Context.deinit(); self.swapchain.deinit(&self.device); framebuffer.deinit(&self.device); self.window.deinit(&self.instance); memory.deinit(&self.device); self.device.deinit(); self.instance.deinit(); } fn windowInit(instance: *const Instance) !Window { // TODO: convar cv_fullscreen const fullscreen = false; const extents = try Display.getSize(fullscreen); var window = try Window.init(instance, "efemra", extents.width, extents.height, fullscreen); return window; } fn windowUpdate(self: Self) !void { if (!self.window.isOpen()) { return error.WindowNotOpen; } // TODO: convar fullscreen change check if (0) { self.device.waitIdle(); // TODO: UI pass del self.swapchain.deinit(&self.device); self.window.deinit(); self.window.init(); self.swapchain.init(null); // TODO: UI pass new } if (self.window.updateSize()) { try self.swapchain.recreate(); // TODO set r_width/r_height convar } if (!self.swapchain.handle) { return error.NoSwapchainHandle; } self.targets.maybeRecreate(); }