diff --git a/src/engine.zig b/src/engine.zig index 9e9b80bc..f1af4661 100644 --- a/src/engine.zig +++ b/src/engine.zig @@ -9,20 +9,34 @@ const allocator = gpa.allocator(); /// The main Mach engine ECS module. pub const Engine = struct { device: *gpu.Device, + queue: *gpu.Queue, exit: bool, + pass: *gpu.RenderPassEncoder, + encoder: *gpu.CommandEncoder, pub const name = .engine; pub fn engineInit(world: *World) !void { core.allocator = allocator; try core.init(.{}); - world.mod.engine.state.device = core.device; - world.mod.engine.state.exit = false; + const state = &world.mod.engine.state; + state.device = core.device; + state.queue = core.device.getQueue(); + state.exit = false; + state.encoder = state.device.createCommandEncoder(&gpu.CommandEncoder.Descriptor{ + .label = "engine.state.encoder", + }); try world.send(.init, .{}); } - pub fn engineDeinit(world: *World) !void { + pub fn engineDeinit( + world: *World, + engine: *World.Mod(.engine), + ) !void { + // TODO: this triggers a device loss error, which we should handle correctly + // engine.state.device.release(); + engine.state.queue.release(); try world.send(.deinit, .{}); core.deinit(); world.deinit(); @@ -33,6 +47,48 @@ pub const Engine = struct { try world.send(.exit, .{}); world.mod.engine.state.exit = true; } + + pub fn engineBeginPass( + engine: *World.Mod(.engine), + clear_color: gpu.Color, + ) !void { + const back_buffer_view = core.swap_chain.getCurrentTextureView().?; + defer back_buffer_view.release(); + + // TODO: expose options + const color_attachment = gpu.RenderPassColorAttachment{ + .view = back_buffer_view, + .clear_value = clear_color, + .load_op = .clear, + .store_op = .store, + }; + const pass_info = gpu.RenderPassDescriptor.init(.{ + .color_attachments = &.{color_attachment}, + }); + + engine.state.pass = engine.state.encoder.beginRenderPass(&pass_info); + } + + pub fn engineEndPass( + engine: *World.Mod(.engine), + ) !void { + // End this pass + engine.state.pass.end(); + engine.state.pass.release(); + + var command = engine.state.encoder.finish(null); + defer command.release(); + engine.state.queue.submit(&[_]*gpu.CommandBuffer{command}); + + // Prepare for next pass + engine.state.encoder = engine.state.device.createCommandEncoder(&gpu.CommandEncoder.Descriptor{ + .label = "engine.state.encoder", + }); + } + + pub fn enginePresent() !void { + core.swap_chain.present(); + } }; pub const App = struct {