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:
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);