From b83b71e2b2899c73e31c4d13e7c73fa0ed36a3ff Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Sun, 10 Sep 2023 19:03:07 -0700 Subject: [PATCH] engine: add render pass / encoder / queue management Signed-off-by: Stephen Gutekanst --- src/engine.zig | 62 +++++++++++++++++++++++++++++++++++++++++++++++--- 1 file changed, 59 insertions(+), 3 deletions(-) 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 {