141 lines
4.3 KiB
Zig
141 lines
4.3 KiB
Zig
allocator: std.mem.Allocator,
|
|
|
|
ssboScene: *gpu.GPUBuffer = undefined,
|
|
ssboSceneUpload: *gpu.GPUTransferBuffer = undefined,
|
|
spans: std.ArrayListUnmanaged(core.Span) = .{},
|
|
|
|
renderInfo: std.ArrayListUnmanaged(SgpuParticleRenderInfo) = .{},
|
|
|
|
lastParticleCount: u32 = 0,
|
|
|
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "rend.ParticleRenderer");
|
|
|
|
const SgpuParticleRenderInfo = struct {
|
|
mesh: rend.IndexedMesh,
|
|
texture: *rend.Texture,
|
|
};
|
|
|
|
pub fn init(self: *@This(), allocator: std.mem.Allocator, first: bool) !void {
|
|
if (!first)
|
|
return;
|
|
|
|
self.* = .{
|
|
.allocator = allocator,
|
|
};
|
|
|
|
const device = rend.context().device;
|
|
|
|
const MaxParticleCount = core.configVar(u32, "rend.particles.maxCount", 200_000);
|
|
|
|
self.ssboScene = device.createGPUBuffer(&.{
|
|
.usage = .{
|
|
.bufferusageGraphicsStorageRead = true,
|
|
.bufferusageVertex = true,
|
|
},
|
|
.size = MaxParticleCount * @sizeOf(meshes_vert.Scene),
|
|
.props = 0,
|
|
});
|
|
|
|
self.ssboSceneUpload = rend.renderer.createGPUTransferBuffer(&.{
|
|
.usage = .transferbufferusageUpload,
|
|
.size = MaxParticleCount * @sizeOf(meshes_vert.Scene),
|
|
.props = 0,
|
|
});
|
|
}
|
|
|
|
pub fn uploadSsbos(self: *@This(), copyPass: *gpu.GPUCopyPass) !void {
|
|
self.spans.clearRetainingCapacity();
|
|
self.renderInfo.clearRetainingCapacity();
|
|
|
|
var offset: usize = 0;
|
|
|
|
const device = rend.context().device;
|
|
|
|
const uploadMapped: [*]meshes_vert.Scene = @ptrCast(@alignCast(device.mapGPUTransferBuffer(self.ssboSceneUpload, true)));
|
|
defer device.unmapGPUTransferBuffer(self.ssboSceneUpload);
|
|
|
|
for (rend.ParticleEmitter.BaseContainer.dense.items) |*c| {
|
|
const emitter = &c.value;
|
|
|
|
for (emitter.finals.items, 0..) |final, i| {
|
|
const size = emitter.size.items[i];
|
|
|
|
uploadMapped[i + offset] = .{
|
|
.Model = final,
|
|
.textureMode = if (emitter.billboard) 0x2 else 0x0, //0x2, // default 0x2 is fullbright
|
|
.animation = -1,
|
|
.float0 = size,
|
|
.flags = if (emitter.billboard) 0x4 else 0, //0x4 for billboard mode
|
|
};
|
|
}
|
|
|
|
try self.renderInfo.append(self.allocator, .{ .texture = emitter.texture, .mesh = emitter.mesh });
|
|
try self.spans.append(self.allocator, .{ .start = @intCast(offset), .size = @intCast(emitter.finals.items.len) });
|
|
offset += emitter.finals.items.len;
|
|
}
|
|
|
|
self.lastParticleCount = @intCast(offset);
|
|
|
|
if (self.renderInfo.items.len == 0)
|
|
return;
|
|
|
|
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.ssboSceneUpload, .offset = 0 }, &.{
|
|
.buffer = self.ssboScene,
|
|
.offset = 0,
|
|
.size = @intCast(offset * @sizeOf(meshes_vert.Scene)),
|
|
}, true);
|
|
}
|
|
|
|
pub fn postMesh(p: *anyopaque, cmd: *gpu.GPUCommandBuffer, renderpass: *gpu.GPURenderPass) void {
|
|
const self: *@This() = @ptrCast(@alignCast(p));
|
|
_ = cmd;
|
|
|
|
renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 1);
|
|
renderpass.bindGPUFragmentStorageBuffers(0, &self.ssboScene, 1);
|
|
|
|
const ctx = rend.context();
|
|
|
|
for (self.spans.items, 0..) |span, i| {
|
|
const ri = self.renderInfo.items[i];
|
|
const mesh = ri.mesh;
|
|
const _t = ri.texture;
|
|
|
|
var sampler: *gpu.GPUSampler = undefined;
|
|
switch (_t.samplerMode) {
|
|
.blocky => {
|
|
sampler = ctx.blockySampler;
|
|
},
|
|
.linear => {
|
|
sampler = ctx.linearSampler;
|
|
},
|
|
}
|
|
|
|
renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 0);
|
|
renderpass.bindGPUFragmentSamplers(0, &.{ .texture = _t.texture, .sampler = sampler }, 1);
|
|
renderpass.drawGPUIndexedPrimitives(mesh.index.size, span.size, mesh.index.start, @intCast(mesh.vertex.start), @intCast(span.start));
|
|
}
|
|
}
|
|
|
|
pub fn setup(self: *@This(), device: *gpu.GPUDevice) !void {
|
|
_ = self;
|
|
_ = device;
|
|
}
|
|
|
|
pub fn deinit(self: *@This()) void {
|
|
self.spans.deinit(self.allocator);
|
|
self.renderInfo.deinit(self.allocator);
|
|
}
|
|
|
|
const assets = @import("assets");
|
|
const core = @import("core");
|
|
const std = @import("std");
|
|
|
|
const rend = @import("../rend.zig");
|
|
const renderer = rend.renderer;
|
|
|
|
const particles = rend.particles;
|
|
const sdl3 = @import("sdl3");
|
|
const gpu = sdl3.gpu;
|
|
|
|
const meshes_vert = @import("meshes.vert");
|