render-zig

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

commit 520f7e4d8ff0e3eee977a6c32d3a37e1b499338f
parent 6e7f83c0ff4b16c3b156a031e09457108880fffe
Author: Christian Ermann <christianermann@gmail.com>
Date:   Fri,  6 Dec 2024 16:16:57 -0800

Add instance id to model id mapping buffer

Diffstat:
Msrc/line_render_pipeline.zig | 2+-
Msrc/main.zig | 39++++++++++++++++++++++++++++++++-------
Msrc/mesh_render_pipeline.zig | 7++++++-
Msrc/shaders/mesh_clusters.wgsl | 9++++++++-
4 files changed, 47 insertions(+), 10 deletions(-)

diff --git a/src/line_render_pipeline.zig b/src/line_render_pipeline.zig @@ -10,7 +10,7 @@ const CubeMap = @import("cubemap.zig"); const Textures = @import("textures.zig"); const RenderPipeline = @import("render_pipeline.zig").RenderPipeline; const Buffer = @import("main.zig").Buffer; -const InstanceData = @import("main.zig").InstanceData; +const InstanceData = @import("main.zig").MeshInstanceData; const Self = @This(); diff --git a/src/main.zig b/src/main.zig @@ -288,7 +288,11 @@ pub const f32x3 = @Vector(3, f32); pub const f32x4 = @Vector(4, f32); pub const mat4 = [4]@Vector(4, f32); -pub const InstanceData = struct { +pub const ClusterInstanceData = struct { + mesh_id: u32, +}; + +pub const MeshInstanceData = struct { model_matrix: mat4, material: Material, }; @@ -395,12 +399,14 @@ pub const MeshBuffer = struct { bitangents: Buffer(f32x4), indices: Buffer(u32), - instances: Buffer(InstanceData), + cluster_instances: Buffer(ClusterInstanceData), + mesh_instances: Buffer(MeshInstanceData), indirect: Buffer([5]u32), meshes: std.ArrayList(RenderMesh), lines: std.ArrayList(RenderLines), + lines_instances: Buffer(MeshInstanceData), lines_indirect: Buffer([5]u32), pub fn init(options: MeshBufferOptions) MeshBuffer { @@ -447,7 +453,13 @@ pub const MeshBuffer = struct { .{ .index = true, .copy_dst = true }, false, ), - .instances = Buffer(InstanceData).init( + .cluster_instances = Buffer(ClusterInstanceData).init( + 2000, + device, + .{ .storage = true, .copy_dst = true }, + false, + ), + .mesh_instances = Buffer(MeshInstanceData).init( options.n_meshes, device, .{ .storage = true, .copy_dst = true }, @@ -528,10 +540,10 @@ pub const MeshBuffer = struct { .offset = options.offset, }; - const instances = [_]InstanceData{ + const instances = [_]MeshInstanceData{ mesh.instanceData(), }; - _ = try self.instances.allocWrite(&instances, self.queue); + _ = try self.mesh_instances.allocWrite(&instances, self.queue); if (mesh_data.descriptors != null) { const descriptors = mesh_data.descriptors.?; @@ -539,6 +551,12 @@ pub const MeshBuffer = struct { const indirect_args = try allocator.alloc([5]u32, num_clusters); defer allocator.free(indirect_args); + const cluster_instances = try allocator.alloc( + ClusterInstanceData, + num_clusters, + ); + defer allocator.free(cluster_instances); + var instance_id = self.indirect.count(); for (descriptors, 0..) |descriptor, i| { indirect_args[i] = .{ @@ -548,10 +566,16 @@ pub const MeshBuffer = struct { offset_p, instance_id, }; + cluster_instances[i] = .{ .mesh_id = @intCast(self.meshes.items.len) }; instance_id += 1; } + _ = try self.cluster_instances.allocWrite(cluster_instances, self.queue); _ = try self.indirect.allocWrite(indirect_args, self.queue); } else { + const cluster_instances = [_]ClusterInstanceData{ + .{ .mesh_id = @intCast(self.meshes.items.len) }, + }; + const instance_id = self.indirect.count(); const indirect_args = [_][5]u32{.{ @intCast(num_indices), @@ -560,6 +584,7 @@ pub const MeshBuffer = struct { offset_p, instance_id, }}; + _ = try self.cluster_instances.allocWrite(&cluster_instances, self.queue); _ = try self.indirect.allocWrite(&indirect_args, self.queue); } @@ -572,8 +597,8 @@ pub const MeshBuffer = struct { if (!mesh.dirty) { continue; } - const instances = [_]InstanceData{mesh.instanceData()}; - self.instances.write(&instances, self.queue, @intCast(i)); + const instances = [_]MeshInstanceData{mesh.instanceData()}; + self.mesh_instances.write(&instances, self.queue, @intCast(i)); mesh.dirty = false; } } diff --git a/src/mesh_render_pipeline.zig b/src/mesh_render_pipeline.zig @@ -58,10 +58,11 @@ pub fn init( const bind_group_descriptor = gpu.BindGroup.Descriptor.init(.{ .layout = bind_group_layout, .entries = &.{ - gpu.BindGroup.Entry.buffer(0, mesh_buffer.instances.data, 0, mesh_buffer.instances.size), + gpu.BindGroup.Entry.buffer(0, mesh_buffer.mesh_instances.data, 0, mesh_buffer.mesh_instances.size), gpu.BindGroup.Entry.buffer(1, uniform_buffer, 0, @sizeOf(UniformData)), gpu.BindGroup.Entry.sampler(2, textures.sampler), gpu.BindGroup.Entry.textureView(3, textures.view), + gpu.BindGroup.Entry.buffer(4, mesh_buffer.cluster_instances.data, 0, mesh_buffer.cluster_instances.size), }, }); const bind_group = app.device.createBindGroup(&bind_group_descriptor); @@ -156,6 +157,10 @@ fn bindGroupLayout(device: *gpu.Device) *gpu.BindGroupLayout { .vertex = false, .fragment = true, }, .float, .dimension_2d_array, false), + gpu.BindGroupLayout.Entry.buffer(4, .{ + .vertex = true, + .fragment = true, + }, .read_only_storage, false, 0), }, }); return device.createBindGroupLayout(&descriptor); diff --git a/src/shaders/mesh_clusters.wgsl b/src/shaders/mesh_clusters.wgsl @@ -28,6 +28,12 @@ struct Material { metalness: u32, }; +@group(0) @binding(4) +var<storage, read> clusters: array<Cluster>; +struct Cluster { + model_id: u32, +}; + @group(0) @binding(1) var<uniform> uniform_data: UniformData; struct UniformData { @@ -40,7 +46,8 @@ struct UniformData { in: VertexInput, @builtin(instance_index) idx: u32, ) -> VertexOutput { - let model_matrix = instances[0].model_matrix; + let model_id = clusters[idx].model_id; + let model_matrix = instances[model_id].model_matrix; let camera_matrix = uniform_data.proj_matrix * uniform_data.view_matrix; let t = normalize((model_matrix * vec4(in.tangent, 0.0)).xyz);