line_render_pipeline.zig (4920B)
1 const std = @import("std"); 2 const gpu = @import("mach_gpu"); 3 4 const App = @import("main.zig").App; 5 const RenderData = @import("render_data.zig"); 6 const UniformData = @import("main.zig").UniformData; 7 const f32x4 = @import("main.zig").f32x4; 8 const mat4 = @import("main.zig").mat4; 9 const CubeMap = @import("cubemap.zig"); 10 const Textures = @import("textures.zig"); 11 const RenderPipeline = @import("render_pipeline.zig").RenderPipeline; 12 const Buffer = @import("main.zig").Buffer; 13 14 const Self = @This(); 15 16 pub const Buffers = struct { 17 positions: *const Buffer(f32x4), 18 indices: *const Buffer(u32), 19 object_data: *const Buffer(RenderData.ObjectData), 20 indirect: *const Buffer([5]u32), 21 }; 22 23 gpu_pipeline: *gpu.RenderPipeline, 24 buffers: Buffers, 25 bind_group: *gpu.BindGroup, 26 uniform_buffer: *gpu.Buffer, 27 28 pub fn init( 29 app: *App, 30 buffers: Buffers, 31 comptime shader_path: []const u8, 32 ) !Self { 33 const src = @embedFile(shader_path); 34 35 const module = app.device.createShaderModuleWGSL("line shader", src); 36 defer module.release(); 37 38 const layouts = Self.bufferLayouts(); 39 const vertex = gpu.VertexState.init(.{ 40 .module = module, 41 .entry_point = "vertex", 42 .buffers = &layouts, 43 }); 44 45 const blend: gpu.BlendState = .{}; 46 const color_target = gpu.ColorTargetState{ 47 .format = app.swap_chain.format, 48 .blend = &blend, 49 .write_mask = gpu.ColorWriteMaskFlags.all, 50 }; 51 const fragment = gpu.FragmentState.init(.{ 52 .module = module, 53 .entry_point = "fragment", 54 .targets = &.{color_target}, 55 }); 56 57 const buffer_descriptor = gpu.Buffer.Descriptor{ 58 .size = @sizeOf(UniformData), 59 .usage = .{ .uniform = true, .copy_dst = true }, 60 .mapped_at_creation = .false, 61 }; 62 const uniform_buffer = app.device.createBuffer(&buffer_descriptor); 63 64 const bind_group_layout = Self.bindGroupLayout(app.device); 65 const bind_group_descriptor = gpu.BindGroup.Descriptor.init(.{ 66 .layout = bind_group_layout, 67 .entries = &.{ 68 gpu.BindGroup.Entry.buffer(0, buffers.object_data.data, 0, buffers.object_data.size), 69 gpu.BindGroup.Entry.buffer(1, uniform_buffer, 0, @sizeOf(UniformData)), 70 }, 71 }); 72 const bind_group = app.device.createBindGroup(&bind_group_descriptor); 73 74 const pipeline_layout_descriptor = gpu.PipelineLayout.Descriptor.init(.{ 75 .bind_group_layouts = &.{bind_group_layout}, 76 }); 77 const pipeline_layout = app.device.createPipelineLayout(&pipeline_layout_descriptor); 78 defer pipeline_layout.release(); 79 80 const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ 81 .label = "line render pipeline", 82 .fragment = &fragment, 83 .layout = pipeline_layout, 84 .depth_stencil = &.{ 85 .format = .depth24_plus, 86 .depth_write_enabled = .true, 87 .depth_compare = .less, 88 }, 89 .vertex = vertex, 90 .multisample = .{}, 91 .primitive = .{ 92 .topology = .line_list, 93 .front_face = .ccw, 94 .cull_mode = .back, 95 }, 96 }; 97 98 return .{ 99 .gpu_pipeline = app.device.createRenderPipeline(&pipeline_descriptor), 100 .buffers = buffers, 101 .bind_group = bind_group, 102 .uniform_buffer = uniform_buffer, 103 }; 104 } 105 106 fn bufferLayouts() [1]gpu.VertexBufferLayout { 107 const positions = gpu.VertexBufferLayout.init(.{ 108 .array_stride = @sizeOf(f32x4), 109 .step_mode = .vertex, 110 .attributes = &.{ 111 .{ .format = .float32x4, .shader_location = 0, .offset = 0 }, 112 }, 113 }); 114 return .{positions}; 115 } 116 117 fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { 118 const descriptor = gpu.BindGroupLayout.Descriptor.init(.{ 119 .entries = &.{ 120 gpu.BindGroupLayout.Entry.buffer(0, .{ 121 .vertex = true, 122 .fragment = true, 123 }, .read_only_storage, false, 0), 124 gpu.BindGroupLayout.Entry.buffer(1, .{ 125 .vertex = true, 126 .fragment = false, 127 }, .uniform, false, 0), 128 }, 129 }); 130 return device.createBindGroupLayout(&descriptor); 131 } 132 133 pub fn frame(ptr: *anyopaque, pass: *gpu.RenderPassEncoder) void { 134 const self: *Self = @ptrCast(@alignCast(ptr)); 135 pass.setPipeline(self.gpu_pipeline); 136 137 pass.setVertexBuffer(0, self.buffers.positions.data, 0, self.buffers.positions.size); 138 pass.setIndexBuffer(self.buffers.indices.data, .uint32, 0, self.buffers.indices.size); 139 pass.setBindGroup(0, self.bind_group, null); 140 141 const num_indirect = self.buffers.indirect.count(); 142 for (0..num_indirect) |idx| { 143 const offset = idx * self.buffers.indirect.attrib_size; 144 pass.drawIndexedIndirect(self.buffers.indirect.data, offset); 145 } 146 } 147 148 pub fn pipeline(self: *Self) RenderPipeline { 149 return .{ 150 .ptr = self, 151 .frameFn = frame, 152 }; 153 }