renderer interface
This commit is contained in:
parent
8cdac4e2e7
commit
b95ef81492
|
|
@ -274,59 +274,10 @@ pub fn loadIndexedMeshForPoolingGltf(allocator: std.mem.Allocator, meshName: cor
|
|||
return rv;
|
||||
}
|
||||
|
||||
pub const MeshPoolCreationSettings = struct {
|
||||
vertexCount: u32 = 4_000_000,
|
||||
indexCount: u32 = 16_000_000,
|
||||
};
|
||||
|
||||
pub const MeshUpdate = union(enum(u8)) {
|
||||
new: struct {
|
||||
vertices: []MeshVertex,
|
||||
indices: []u32,
|
||||
jointNames: []JointNameEntry,
|
||||
name: core.Name,
|
||||
skeletonName: ?core.Name,
|
||||
},
|
||||
|
||||
free: struct {
|
||||
vertices: core.Span,
|
||||
indices: core.Span,
|
||||
name: core.Name,
|
||||
},
|
||||
|
||||
pub fn deinit(self: @This(), allocator: std.mem.Allocator) void {
|
||||
switch (self) {
|
||||
.new => |new| {
|
||||
allocator.free(new.vertices);
|
||||
allocator.free(new.indices);
|
||||
for (new.jointNames) |entry| {
|
||||
entry.deinit(allocator);
|
||||
}
|
||||
allocator.free(new.jointNames);
|
||||
},
|
||||
.free => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const JointNameEntry = struct {
|
||||
name: []u8 = undefined,
|
||||
index: u32 = 0,
|
||||
|
||||
pub fn deinit(self: @This(), allocator: std.mem.Allocator) void {
|
||||
// const allocator = graphics.getContext().allocator;
|
||||
allocator.free(self.name);
|
||||
}
|
||||
};
|
||||
|
||||
pub const MeshVertex = extern struct {
|
||||
position: core.Vectorf = .{},
|
||||
normal: core.Vectorf = .{},
|
||||
color: core.colors.Color = .{},
|
||||
uv: core.Vector2f = .{},
|
||||
bones: [4]u8 = .{ 0, 0, 0, 0 },
|
||||
weights: [4]u8 = .{ 0, 0, 0, 0 },
|
||||
};
|
||||
const meshes = @import("meshes.zig");
|
||||
const MeshUpdate = meshes.MeshUpdate;
|
||||
const JointNameEntry = meshes.JointNameEntry;
|
||||
const MeshVertex = meshes.MeshVertex;
|
||||
|
||||
const core = @import("core");
|
||||
const std = @import("std");
|
||||
|
|
|
|||
|
|
@ -0,0 +1,59 @@
|
|||
pub const MeshVertex = extern struct {
|
||||
position: core.Vectorf = .{},
|
||||
normal: core.Vectorf = .{},
|
||||
color: core.colors.Color = .{},
|
||||
uv: core.Vector2f = .{},
|
||||
bones: [4]u8 = .{ 0, 0, 0, 0 },
|
||||
weights: [4]u8 = .{ 0, 0, 0, 0 },
|
||||
};
|
||||
|
||||
pub const MeshUpdate = union(enum(u8)) {
|
||||
new: struct {
|
||||
vertices: []MeshVertex,
|
||||
indices: []u32,
|
||||
jointNames: []JointNameEntry,
|
||||
name: core.Name,
|
||||
skeletonName: ?core.Name,
|
||||
},
|
||||
|
||||
free: struct {
|
||||
vertices: core.Span,
|
||||
indices: core.Span,
|
||||
name: core.Name,
|
||||
},
|
||||
|
||||
pub fn deinit(self: @This(), allocator: std.mem.Allocator) void {
|
||||
switch (self) {
|
||||
.new => |new| {
|
||||
allocator.free(new.vertices);
|
||||
allocator.free(new.indices);
|
||||
for (new.jointNames) |entry| {
|
||||
entry.deinit(allocator);
|
||||
}
|
||||
allocator.free(new.jointNames);
|
||||
},
|
||||
.free => {},
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
pub const JointNameEntry = struct {
|
||||
name: []u8 = undefined,
|
||||
index: u32 = 0,
|
||||
|
||||
pub fn deinit(self: @This(), allocator: std.mem.Allocator) void {
|
||||
// const allocator = graphics.getContext().allocator;
|
||||
allocator.free(self.name);
|
||||
}
|
||||
};
|
||||
|
||||
pub const IndexedMesh = struct {
|
||||
vertex: core.Span,
|
||||
index: core.Span,
|
||||
name: core.Name,
|
||||
jointRemap: ?[]u8, // this is NOT a string, they're joint indices.. which happen to be u8s
|
||||
};
|
||||
|
||||
const core = @import("core");
|
||||
const std = @import("std");
|
||||
const zgltf = @import("zgltf");
|
||||
|
|
@ -1,12 +1,24 @@
|
|||
const std = @import("std");
|
||||
pub const core = @import("core");
|
||||
const sgpu_renderer = @import("sgpu/renderer.zig");
|
||||
|
||||
// meshes api
|
||||
pub const meshes = @import("meshes/meshes.zig");
|
||||
pub const JointNameEntry = meshes.JointNameEntry;
|
||||
pub const MeshUpdate = meshes.MeshUpdate;
|
||||
pub const MeshVertex = meshes.MeshVertex;
|
||||
pub const IndexedMesh = meshes.IndexedMesh;
|
||||
|
||||
// asset loaders
|
||||
pub const gltfLoader = @import("meshes/gltfLoader.zig");
|
||||
|
||||
// switch out based on backend implementation
|
||||
pub const renderer = @import("sgpu/renderer.zig");
|
||||
pub const context = renderer.context; // context getter func
|
||||
|
||||
pub const MeshPool = renderer.MeshPool;
|
||||
|
||||
// controls glfw and general windowing
|
||||
// graphics depends on this one
|
||||
|
||||
pub const Module: core.ModuleDescription = .{
|
||||
.name = "rend",
|
||||
.enabledByDefault = true,
|
||||
|
|
@ -16,10 +28,10 @@ pub fn start_module(comptime programSpec: anytype, args: anytype, allocator: std
|
|||
_ = args;
|
||||
_ = programSpec;
|
||||
_ = allocator;
|
||||
try sgpu_renderer.start();
|
||||
try renderer.start();
|
||||
}
|
||||
|
||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||
_ = allocator;
|
||||
sgpu_renderer.shutdown();
|
||||
renderer.shutdown();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -0,0 +1,89 @@
|
|||
pub const MeshPool = struct {
|
||||
allocator: std.mem.Allocator,
|
||||
|
||||
meshMap: std.AutoHashMapUnmanaged(u32, rend.IndexedMesh) = .{},
|
||||
indexSpans: core.MergedSpans,
|
||||
vertexSpans: core.MergedSpans,
|
||||
|
||||
indexBuffer: *gpu.GPUBuffer = undefined,
|
||||
vertexBuffer: *gpu.GPUBuffer = undefined,
|
||||
|
||||
meshUpdates: core.RingQueue(rend.MeshUpdate),
|
||||
|
||||
device: *gpu.GPUDevice,
|
||||
|
||||
pub fn create(device: *gpu.GPUDevice, allocator: std.mem.Allocator, settings: MeshPoolCreationSettings) !*@This() {
|
||||
const self = try allocator.create(@This());
|
||||
|
||||
self.* = .{
|
||||
.allocator = allocator,
|
||||
.indexSpans = try core.MergedSpans.init(allocator, settings.indexCount),
|
||||
.vertexSpans = try core.MergedSpans.init(allocator, settings.vertexCount),
|
||||
.meshUpdates = try core.RingQueue(rend.MeshUpdate).init(allocator, 128),
|
||||
.device = device,
|
||||
};
|
||||
|
||||
self.vertexBuffer = self.device.createGPUBuffer(&.{
|
||||
.usage = .{ .bufferusageVertex = true },
|
||||
.size = settings.vertexCount * @sizeOf(rend.MeshVertex),
|
||||
.props = 0,
|
||||
});
|
||||
|
||||
self.indexBuffer = self.device.createGPUBuffer(&.{
|
||||
.usage = .{ .bufferusageIndex = true },
|
||||
.size = settings.indexCount * @sizeOf(u32),
|
||||
.props = 0,
|
||||
});
|
||||
|
||||
return self;
|
||||
}
|
||||
|
||||
pub fn onUpload(p: *anyopaque, copyPass: *gpu.GPUCopyPass) void {
|
||||
const self: *@This() = @ptrCast(@alignCast(p));
|
||||
if (self.meshUpdates.count() <= 0)
|
||||
return;
|
||||
_ = copyPass;
|
||||
}
|
||||
|
||||
// pushes the meshUpdate into the pool, either an insert or a free.
|
||||
pub fn pushMeshUpdate(self: *@This(), meshUpdate: rend.MeshUpdate) !void {
|
||||
self.meshUpdates.pushLocked(meshUpdate);
|
||||
}
|
||||
|
||||
pub fn destroy(p: *anyopaque) void {
|
||||
const self: *@This() = @ptrCast(@alignCast(p));
|
||||
|
||||
self.indexSpans.deinit();
|
||||
self.meshUpdates.deinit();
|
||||
self.vertexSpans.deinit();
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
|
||||
pub const MeshPoolCreationSettings = struct {
|
||||
vertexCount: u32 = 4_000_000,
|
||||
indexCount: u32 = 16_000_000,
|
||||
};
|
||||
};
|
||||
|
||||
var gMeshPool: *MeshPool = undefined;
|
||||
|
||||
pub fn getIndexedMesh(name: []const u8) ?rend.IndexedMesh {
|
||||
var n = core.MakeName(name);
|
||||
return getIndexedMeshByName(&n);
|
||||
}
|
||||
|
||||
pub fn getIndexedMeshByName(name: *core.Name) ?rend.IndexedMesh {
|
||||
// var name = _name;
|
||||
// gMeshPoolBuffer.vertexMapLock.lock();
|
||||
// defer gMeshPoolBuffer.vertexMapLock.unlock();
|
||||
// return gMeshPoolBuffer.vertexMap.get(name.handle());
|
||||
_ = name;
|
||||
return null;
|
||||
}
|
||||
|
||||
const sdl3 = @import("sdl3");
|
||||
const gpu = sdl3.gpu;
|
||||
const rend = @import("../rend.zig");
|
||||
const std = @import("std");
|
||||
const core = @import("core");
|
||||
const meshes = rend.meshes;
|
||||
|
|
@ -21,6 +21,11 @@ pub const Renderer = struct {
|
|||
colorBufferTransfer: *gpu.GPUTransferBuffer = undefined,
|
||||
window: *sdl3.Window = undefined,
|
||||
|
||||
meshPool: *MeshPool = undefined,
|
||||
|
||||
uploads: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCopyPass) void }) = .{},
|
||||
destroys: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
|
||||
|
||||
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
|
||||
|
||||
pub fn init(allocator: std.mem.Allocator) !*@This() {
|
||||
|
|
@ -38,6 +43,13 @@ pub const Renderer = struct {
|
|||
@as(*@This(), @ptrCast(@alignCast(p))).startRenderer() catch return error.BadInit;
|
||||
}
|
||||
|
||||
pub fn registerRendererObject(self: *@This(), T: type) !void {
|
||||
const object = try T.create(self.device, self.allocator, .{});
|
||||
|
||||
try self.uploads.append(self.allocator, .{ .ptr = object, .func = T.onUpload });
|
||||
try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy });
|
||||
}
|
||||
|
||||
pub fn startRenderer(self: *@This()) !void {
|
||||
self.device = gpu.createGPUDevice(.{
|
||||
.shaderformatSpirv = true,
|
||||
|
|
@ -55,6 +67,8 @@ pub const Renderer = struct {
|
|||
core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix});
|
||||
|
||||
try self.createPipeline();
|
||||
|
||||
try self.registerRendererObject(MeshPool);
|
||||
}
|
||||
|
||||
pub fn discoverFormats(self: *@This()) !void {
|
||||
|
|
@ -151,33 +165,37 @@ pub const Renderer = struct {
|
|||
return rv;
|
||||
}
|
||||
|
||||
pub fn frameUploads(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
||||
const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true);
|
||||
|
||||
var b: [*][4]f32 = @ptrCast(@alignCast(buffer));
|
||||
|
||||
b[0] = .{ @floatCast(std.math.sin(self.totalTime * 3 * 2 + 0.8) * 0.2 + 0.8), 0.4, 0.4, 1.0 };
|
||||
b[1] = .{ 0.4, @floatCast(std.math.sin(self.totalTime * 2 * 2 + 0.3) * 0.2 + 0.8), 0.4, 1.0 };
|
||||
b[2] = .{ 0.4, 0.4, @floatCast(std.math.sin(self.totalTime * 4 * 2) * 0.2 + 0.8), 1.0 };
|
||||
|
||||
self.device.unmapGPUTransferBuffer(self.colorBufferTransfer);
|
||||
|
||||
const copyPass = cmd.beginGPUCopyPass();
|
||||
defer copyPass.endGPUCopyPass();
|
||||
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{
|
||||
.buffer = self.colorBuffer,
|
||||
.offset = 0,
|
||||
.size = 4 * 12,
|
||||
}, true);
|
||||
|
||||
for (self.uploads.items) |upload| {
|
||||
upload.func(upload.ptr, copyPass);
|
||||
}
|
||||
}
|
||||
|
||||
pub fn tick(self: *@This(), dt: f64) void {
|
||||
self.totalTime += dt;
|
||||
|
||||
const cmd = self.device.acquireGPUCommandBuffer();
|
||||
self.frameUploads(cmd);
|
||||
|
||||
var swapchain_texture: *gpu.GPUTexture = undefined;
|
||||
{
|
||||
const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true);
|
||||
|
||||
var b: [*][4]f32 = @ptrCast(@alignCast(buffer));
|
||||
|
||||
b[0] = .{ @floatCast(std.math.sin(self.totalTime * 3 * 2 + 0.8) * 0.2 + 0.8), 0.4, 0.4, 1.0 };
|
||||
b[1] = .{ 0.4, @floatCast(std.math.sin(self.totalTime * 2 * 2 + 0.3) * 0.2 + 0.8), 0.4, 1.0 };
|
||||
b[2] = .{ 0.4, 0.4, @floatCast(std.math.sin(self.totalTime * 4 * 2) * 0.2 + 0.8), 1.0 };
|
||||
|
||||
self.device.unmapGPUTransferBuffer(self.colorBufferTransfer);
|
||||
}
|
||||
|
||||
{
|
||||
const copyPass = cmd.beginGPUCopyPass();
|
||||
defer copyPass.endGPUCopyPass();
|
||||
copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{
|
||||
.buffer = self.colorBuffer,
|
||||
.offset = 0,
|
||||
.size = 4 * 12,
|
||||
}, true);
|
||||
}
|
||||
|
||||
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchain_texture, null, null)) {
|
||||
var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo);
|
||||
targetInfo.texture = swapchain_texture;
|
||||
|
|
@ -197,6 +215,11 @@ pub const Renderer = struct {
|
|||
}
|
||||
|
||||
pub fn deinit(self: *@This()) void {
|
||||
for (self.destroys.items) |d| {
|
||||
d.func(d.ptr);
|
||||
}
|
||||
self.uploads.deinit(self.allocator);
|
||||
self.destroys.deinit(self.allocator);
|
||||
self.allocator.destroy(self);
|
||||
}
|
||||
};
|
||||
|
|
@ -211,8 +234,15 @@ pub fn start() !void {
|
|||
|
||||
pub fn shutdown() void {}
|
||||
|
||||
pub fn context() *Renderer {
|
||||
return gRenderer;
|
||||
}
|
||||
|
||||
const rend = @import("../rend.zig");
|
||||
|
||||
pub const mesh_pool = @import("mesh-pool.zig");
|
||||
pub const MeshPool = mesh_pool.MeshPool;
|
||||
|
||||
const std = @import("std");
|
||||
const core = @import("core");
|
||||
const platform = @import("platform");
|
||||
|
|
|
|||
Loading…
Reference in New Issue