render-zig

A 3D rendering engine written in Zig
git clone git://git.christianermann.dev/render-zig
Log | Files | Refs

commit 9c9f54c06951604f8b7821a082693fb9a2e00a8d
parent 3f164f4e03c5760ada8c0169014b5aeec9b23e09
Author: Christian Ermann <christianermann@gmail.com>
Date:   Sat, 18 May 2024 14:40:42 -0400

Add render pass struct

Diffstat:
Msrc/main.zig | 41++++++++++++-----------------------------
Asrc/render_pass.zig | 79+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 91 insertions(+), 29 deletions(-)

diff --git a/src/main.zig b/src/main.zig @@ -3,6 +3,8 @@ const glfw = @import("mach_glfw"); const gpu = @import("mach_gpu"); const builtin = @import("builtin"); +const RenderPass = @import("render_pass.zig").RenderPass; +const ForwardScreenPass = @import("render_pass.zig").ForwardScreenPass; const RenderPipeline = @import("render_pipeline.zig").RenderPipeline; const MeshRenderPipeline = @import("render_pipeline.zig").MeshRenderPipeline; const SkyBoxRenderPipeline = @import("render_pipeline.zig").SkyBoxRenderPipeline; @@ -240,7 +242,7 @@ pub const App = struct { return sc.gpu_swap_chain.?; } - pub fn frame(app: *App, pipelines: []const RenderPipeline) !void { + pub fn frame(app: *App, passes: []const RenderPass) !void { app.device.tick(); const swap_chain = app.getCurrentSwapChain(); defer swap_chain.present(); @@ -251,32 +253,8 @@ pub const App = struct { { const encoder = app.device.createCommandEncoder(null); defer encoder.release(); - - const color_attachment = gpu.RenderPassColorAttachment{ - .view = back_buffer_view, - .resolve_target = null, - .clear_value = gpu.Color{ .r = 1, .g = 1, .b = 1, .a = 1 }, - .load_op = .clear, - .store_op = .store, - }; - const render_pass_info = gpu.RenderPassDescriptor.init(.{ - .color_attachments = &.{color_attachment}, - .depth_stencil_attachment = &.{ - .view = app.depth_texture_view, - .depth_clear_value = 1.0, - .depth_load_op = .clear, - .depth_store_op = .store, - }, - }); - - { - const pass = encoder.beginRenderPass(&render_pass_info); - defer pass.release(); - defer pass.end(); - - for (pipelines) |pipeline| { - pipeline.frame(pass); - } + for (passes) |pass| { + pass.frame(encoder, back_buffer_view); } { @@ -575,7 +553,12 @@ pub fn main() !void { var rp = try MeshRenderPipeline.init(&app, &mesh_buffer, allocator); var skybox = SkyBoxRenderPipeline.init(&app, cube_map); - const pipelines = [_]RenderPipeline{ rp.pipeline(), skybox.pipeline() }; + var fp = ForwardScreenPass.init(.{ + .depth = app.depth_texture_view, + .pipelines = &.{ rp.pipeline(), skybox.pipeline() }, + }); + + const passes = [_]RenderPass{fp.renderPass()}; try app.inputs.append(camera.input.userInput()); @@ -600,7 +583,7 @@ pub fn main() !void { camera.invProj(&skybox_uniform.inv_proj); app.queue.writeBuffer(skybox.uniform_buffer, 0, &[1]SkyBoxRenderPipeline.UniformData{skybox_uniform}); - try app.frame(&pipelines); + try app.frame(&passes); } } diff --git a/src/render_pass.zig b/src/render_pass.zig @@ -0,0 +1,79 @@ +const std = @import("std"); +const gpu = @import("mach_gpu"); + +const RenderPipeline = @import("render_pipeline.zig").RenderPipeline; + +pub const RenderPass = struct { + ptr: *anyopaque, + frameFn: *const fn ( + ptr: *anyopaque, + encoder: *gpu.CommandEncoder, + current_view: *gpu.TextureView, + ) void, + + pub fn frame( + self: *const RenderPass, + encoder: *gpu.CommandEncoder, + current_view: *gpu.TextureView, + ) void { + return self.frameFn(self.ptr, encoder, current_view); + } +}; + +pub const ForwardScreenPass = struct { + depth: gpu.RenderPassDepthStencilAttachment, + pipelines: []const RenderPipeline, + + const Self = @This(); + + pub const Args = struct { + depth: *gpu.TextureView, + pipelines: []const RenderPipeline, + }; + + pub fn init(args: Args) Self { + return .{ + .depth = .{ + .view = args.depth, + .depth_clear_value = 1.0, + .depth_load_op = .clear, + .depth_store_op = .store, + }, + .pipelines = args.pipelines, + }; + } + + pub fn frame( + ptr: *anyopaque, + encoder: *gpu.CommandEncoder, + current_view: *gpu.TextureView, + ) void { + const self: *Self = @ptrCast(@alignCast(ptr)); + + const color_attachment = gpu.RenderPassColorAttachment{ + .view = current_view, + .resolve_target = null, + .clear_value = gpu.Color{ .r = 1, .g = 1, .b = 1, .a = 1 }, + .load_op = .clear, + .store_op = .store, + }; + const descriptor = gpu.RenderPassDescriptor.init(.{ + .color_attachments = &.{color_attachment}, + .depth_stencil_attachment = &self.depth, + }); + const pass = encoder.beginRenderPass(&descriptor); + defer pass.release(); + defer pass.end(); + + for (self.pipelines) |pipeline| { + pipeline.frame(pass); + } + } + + pub fn renderPass(self: *Self) RenderPass { + return .{ + .ptr = self, + .frameFn = frame, + }; + } +};