From 4670f874f55623868763cad67d896148799cc592 Mon Sep 17 00:00:00 2001 From: Peter Li Date: Fri, 18 Apr 2025 22:07:31 -0700 Subject: [PATCH] rendering component seems to be working but odd transforms are happening with the perspective --- engine/rend/src/meshes/MeshComponent.zig | 6 ++ engine/rend/src/sgpu/mesh-pool.zig | 5 +- engine/rend/src/sgpu/renderer.zig | 129 ++++++++++++++++++----- lib/sdl3/src/gpu.zig | 15 ++- projects/sampleGame/main.zig | 42 ++++++-- 5 files changed, 154 insertions(+), 43 deletions(-) diff --git a/engine/rend/src/meshes/MeshComponent.zig b/engine/rend/src/meshes/MeshComponent.zig index d22ab1d..84f9ed1 100644 --- a/engine/rend/src/meshes/MeshComponent.zig +++ b/engine/rend/src/meshes/MeshComponent.zig @@ -24,6 +24,12 @@ pub fn initECS(self: *@This(), handle: core.SetHandle) void { } } +pub fn updateMesh(self: *@This()) void { + if (self.meshName.handle() != 0) { + self.setMeshByName(&self.meshName); + } +} + pub fn setMeshByName(self: *@This(), meshName: *core.Name) void { self.mesh = rend.getMeshByName(meshName); self.meshName = meshName.*; diff --git a/engine/rend/src/sgpu/mesh-pool.zig b/engine/rend/src/sgpu/mesh-pool.zig index 92776c7..bf90cec 100644 --- a/engine/rend/src/sgpu/mesh-pool.zig +++ b/engine/rend/src/sgpu/mesh-pool.zig @@ -73,6 +73,8 @@ pub const MeshPool = struct { var name = new.name; core.graphics_log("uploading {d} vertices and {d} indices", .{ vertexSpan.size, indexSpan.size }); + + core.engine_log("install mesh by name {d}", .{name.handle()}); try self.installedMeshes.put(self.allocator, name.handle(), .{ .vertex = vertexSpan, .index = indexSpan, @@ -123,7 +125,7 @@ pub const MeshPool = struct { //copyPass.uploadToGPUBuffer(source: [*c]const GPUTransferBufferLocation, destination: [*c]const GPUBufferRegion, cycle: bool) copyPass.uploadToGPUBuffer( &.{ .transfer_buffer = upload, .offset = 0 }, - &.{ .buffer = destBuffer, .offset = newSpan.start, .size = newSpan.size }, + &.{ .buffer = destBuffer, .offset = newSpan.start, .size = newSpan.size * @sizeOf(T) }, false, ); @@ -164,6 +166,7 @@ pub fn getMesh(name: []const u8) ?rend.IndexedMesh { } pub fn getMeshByName(name: *core.Name) ?rend.IndexedMesh { + core.engine_log("getMeshByName {d}", .{name.handle()}); return gMeshPool.installedMeshes.get(name.handle()); } diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index 7348db6..528db70 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -32,6 +32,8 @@ pub const Renderer = struct { uploadCleanup: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, destroys: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, + depthTexture: *gpu.GPUTexture = undefined, + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); pub const MaxObjectCount = 50000; @@ -51,12 +53,27 @@ pub const Renderer = struct { self.startRenderer() catch return error.BadInit; } - pub fn registerRendererObject(self: *@This(), T: type) !void { + pub fn registerRendererObject(self: *@This(), T: type) !*T { const object = try T.create(self.device, self.allocator, .{}); try self.uploads.append(self.allocator, .{ .ptr = object, .func = T.onUpload }); try self.uploadCleanup.append(self.allocator, .{ .ptr = object, .func = T.onUploadCleanup }); try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy }); + return object; + } + + fn createDepthTexture(self: *@This()) !void { + var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); + + gci.type = .texturetype2d; + gci.format = .textureformatD16Unorm; + gci.width = @intCast(self.scissor.w); + gci.height = @intCast(self.scissor.h); + gci.layer_count_or_depth = 1; + gci.num_levels = 1; + gci.usage = .{ .textureusageDepthStencilTarget = true }; + + self.depthTexture = self.device.createGPUTexture(&gci); } pub fn startRenderer(self: *@This()) !void { @@ -75,10 +92,11 @@ pub const Renderer = struct { core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix}); - try self.createPipeline(); + // try self.createPipeline(); try self.createMeshPipeline(); + try self.createDepthTexture(); - try self.registerRendererObject(MeshPool); + self.meshPool = try self.registerRendererObject(MeshPool); } pub fn discoverFormats(self: *@This()) !void { @@ -101,7 +119,7 @@ pub const Renderer = struct { } fn addAttribute(list: *std.ArrayList(gpu.GPUVertexAttribute), offset: *u32, size: u32, format: gpu.GPUVertexElementFormat) !void { - try list.append(.{ .location = @intCast(list.items.len), .offset = offset.* + size, .format = format, .buffer_slot = 0 }); + try list.append(.{ .location = @intCast(list.items.len), .offset = offset.*, .format = format, .buffer_slot = 0 }); offset.* = offset.* + size; } @@ -134,6 +152,13 @@ pub const Renderer = struct { .vertex_attributes = @ptrCast(attributes.items.ptr), }; + pci.depth_stencil_state.compare_op = .compareopLess; + pci.depth_stencil_state.enable_depth_test = true; + pci.depth_stencil_state.enable_depth_write = true; + pci.depth_stencil_state.write_mask = 0xff; + + pci.target_info.has_depth_stencil_target = true; + pci.target_info.depth_stencil_format = .textureformatD16Unorm; pci.target_info.num_color_targets = 1; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ @@ -161,16 +186,16 @@ pub const Renderer = struct { }); } - pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) void { - const uploadMapped: [*]meshes_vert.Scene = self.device.mapGPUTransferBuffer(self.ssboSceneUpload, true); + pub fn uploadSSBOs(self: *@This(), copyPass: *gpu.GPUCopyPass) !void { + const uploadMapped: [*]meshes_vert.Scene = @ptrCast(@alignCast(self.device.mapGPUTransferBuffer(self.ssboSceneUpload, true))); self.device.unmapGPUTransferBuffer(self.ssboSceneUpload); - const container = &rend.MeshComponent.BaseContainer; + const container = rend.MeshComponent.BaseContainer; const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount); for (0..uploadCount) |i| { // const object = &container.dense.items[i].value; const objectId = container.dense.items[i].sparseIndex; - var transform = core.Transform.identity(); + var transform = core.zm.identity(); if (core.Scene.SceneObjectContainer.get(objectId, ._repr)) |repr| { transform = repr.transform; @@ -178,10 +203,13 @@ pub const Renderer = struct { uploadMapped[i].Model = @bitCast(transform); } + if (uploadCount == 0) + return; + copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.ssboSceneUpload, .offset = 0 }, &.{ .buffer = self.ssboScene, .offset = 0, - .size = uploadCount * @sizeOf(meshes_vert.Scene), + .size = @intCast(uploadCount * @sizeOf(meshes_vert.Scene)), }, true); } @@ -194,6 +222,8 @@ pub const Renderer = struct { pci.vertex_shader = vertex; pci.target_info.num_color_targets = 1; + pci.target_info.has_depth_stencil_target = true; + pci.target_info.depth_stencil_format = .textureformatD16Unorm; pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{ .{ .format = self.device.getGPUSwapchainTextureFormat(self.window), @@ -259,29 +289,42 @@ pub const Renderer = struct { return rv; } + pub fn uploadUniforms(self: *@This(), cmd: *gpu.GPUCommandBuffer) !void { + var data = std.mem.zeroes([@sizeOf(meshes_vert.Uniforms) / 8 + 1]usize); + const ptr: *meshes_vert.Uniforms = @ptrCast(@alignCast(&data)); + if (self.activeCamera) |camera| { + ptr.ViewProjection = @bitCast(camera.final); + } + + ptr.time = @floatCast(self.totalTime); + + cmd.pushGPUVertexUniformData(0, &data, @sizeOf(meshes_vert.Uniforms)); + } + pub fn frameUploads(self: *@This()) void { const cmd = self.device.acquireGPUCommandBuffer(); - const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true); + // const buffer = self.device.mapGPUTransferBuffer(self.colorBufferTransfer, true); - var b: [*][4]f32 = @ptrCast(@alignCast(buffer)); + // 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 }; + // 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); + // self.device.unmapGPUTransferBuffer(self.colorBufferTransfer); if (self.activeCamera) |camera| { camera.resolve(); } - // map and upload Uniforms here const copyPass = cmd.beginGPUCopyPass(); - copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{ - .buffer = self.colorBuffer, - .offset = 0, - .size = 4 * 12, - }, true); + // copyPass.uploadToGPUBuffer(&.{ .transfer_buffer = self.colorBufferTransfer, .offset = 0 }, &.{ + // .buffer = self.colorBuffer, + // .offset = 0, + // .size = 4 * 12, + // }, true); + + try self.uploadSSBOs(copyPass); for (self.uploads.items) |upload| { upload.func(upload.ptr, copyPass); @@ -302,6 +345,7 @@ pub const Renderer = struct { const cmd = self.device.acquireGPUCommandBuffer(); self.frameUploads(); + try self.uploadUniforms(cmd); var swapchainTexture: *gpu.GPUTexture = undefined; if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchainTexture, null, null)) { @@ -311,11 +355,44 @@ pub const Renderer = struct { targetInfo.load_op = .loadopClear; targetInfo.store_op = .storeopStore; - const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, null); - renderpass.bindGPUGraphicsPipeline(self.testPipeline); - renderpass.bindGPUVertexStorageBuffers(0, &self.colorBuffer, 1); + var depthTarget = std.mem.zeroes(gpu.GPUDepthStencilTargetInfo); + depthTarget.texture = self.depthTexture; + depthTarget.load_op = .loadopClear; + depthTarget.store_op = .storeopDontCare; + depthTarget.clear_depth = 1.0; + depthTarget.clear_stencil = 0; + + const renderpass = cmd.beginGPURenderPass(&targetInfo, 1, &depthTarget); + //renderpass.bindGPUGraphicsPipeline(self.testPipeline); + renderpass.bindGPUGraphicsPipeline(self.meshPipe); + + renderpass.bindGPUVertexStorageBuffers(0, &self.ssboScene, 1); + renderpass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1); + renderpass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit); + renderpass.setGPUScissor(&self.scissor); - renderpass.drawGPUPrimitives(3, 1, 0, 0); + + //rendering each mesh + { + const container = rend.MeshComponent.BaseContainer; + const uploadCount: usize = @min(container.dense.items.len, MaxObjectCount); + for (0..uploadCount) |i| { + // core.engine_log("pushing draw {d}", .{i}); + const component = &container.dense.items[i].value; + + if (component.mesh == null) { + component.updateMesh(); + } + + if (component.mesh) |mesh| { + // core.engine_log("pushing draw for instance {d}", .{i}); + renderpass.drawGPUIndexedPrimitives(mesh.index.size, 1, mesh.index.start, @intCast(mesh.vertex.start), @intCast(i)); + } + } + } + + // renderpass.drawGPUPrimitives(3, 1, 0, 0); + renderpass.endGPURenderPass(); } @@ -323,7 +400,7 @@ pub const Renderer = struct { } pub fn deinit(self: *@This()) void { - self.device.releaseGPUGraphicsPipeline(self.testPipeline); + // self.device.releaseGPUGraphicsPipeline(self.testPipeline); for (self.destroys.items) |d| { d.func(d.ptr); diff --git a/lib/sdl3/src/gpu.zig b/lib/sdl3/src/gpu.zig index 835a590..cf696e9 100644 --- a/lib/sdl3/src/gpu.zig +++ b/lib/sdl3/src/gpu.zig @@ -959,17 +959,17 @@ pub const GPUCommandBuffer = opaque { } // SDL_PushGPUVertexUniformData - pub inline fn pushGPUVertexUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + pub inline fn pushGPUVertexUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void { c.SDL_PushGPUVertexUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); } // SDL_PushGPUFragmentUniformData - pub inline fn pushGPUFragmentUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + pub inline fn pushGPUFragmentUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void { c.SDL_PushGPUFragmentUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); } // SDL_PushGPUComputeUniformData - pub inline fn pushGPUComputeUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: [*c]const void, length: u32) void { + pub inline fn pushGPUComputeUniformData(command_buffer: *GPUCommandBuffer, slot_index: u32, data: ?*anyopaque, length: u32) void { c.SDL_PushGPUComputeUniformData(@ptrCast(command_buffer), @bitCast(slot_index), @ptrCast(data), @bitCast(length)); } @@ -1051,13 +1051,18 @@ pub const GPURenderPass = opaque { } // SDL_BindGPUVertexBuffers - pub inline fn bindGPUVertexBuffers(render_pass: *GPURenderPass, first_slot: u32, bindings: [*c]const GPUBufferBinding, num_bindings: u32) void { + pub inline fn bindGPUVertexBuffers( + render_pass: *GPURenderPass, + first_slot: u32, + bindings: [*c]const GPUBufferBinding, + num_bindings: u32, + ) void { c.SDL_BindGPUVertexBuffers(@ptrCast(render_pass), @bitCast(first_slot), @ptrCast(bindings), @bitCast(num_bindings)); } // SDL_BindGPUIndexBuffer pub inline fn bindGPUIndexBuffer(render_pass: *GPURenderPass, binding: [*c]const GPUBufferBinding, index_element_size: GPUIndexElementSize) void { - c.SDL_BindGPUIndexBuffer(@ptrCast(render_pass), @ptrCast(binding), @bitCast(index_element_size)); + c.SDL_BindGPUIndexBuffer(@ptrCast(render_pass), @ptrCast(binding), @intFromEnum(index_element_size)); } // SDL_BindGPUVertexSamplers diff --git a/projects/sampleGame/main.zig b/projects/sampleGame/main.zig index 7934bc4..90dfcaa 100644 --- a/projects/sampleGame/main.zig +++ b/projects/sampleGame/main.zig @@ -1,12 +1,14 @@ allocator: std.mem.Allocator, camera: core.Entity = undefined, -cameraSpeed: f32 = 10.0, +cameraSpeed: f32 = 100.0, moveInput: *core.Axis2dBinding = undefined, moveVector: core.Vectorf = .{}, +verticalMove: f32 = 0.0, + pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This()); pub fn init(allocator: std.mem.Allocator) !*@This() { @@ -23,11 +25,11 @@ const assetReferences = [_]assets.AssetImportReference{ "m_empire", .{ .path = "meshes/lost_empire.obj" }, ), - assets.MakeImportRefOptions( - "Mesh", - "m_fox", - .{ .path = "gltf-samples/Fox/glTF/Fox.gltf" }, - ), + // assets.MakeImportRefOptions( + // "Mesh", + // "m_fox", + // .{ .path = "gltf-samples/Fox/glTF/Fox.gltf" }, + // ), }; pub fn prepare(self: *@This()) !void { @@ -46,9 +48,14 @@ pub fn prepare(self: *@This()) !void { exitInput.activate(); self.camera = try core.createEntity(); - const scene = self.camera.addComponent(core.Scene).?; - _ = scene; + _ = self.camera.addComponent(core.Scene).?; const camera = self.camera.addComponent(rend.CameraComponent).?; + + const lostEmpire = try core.createEntity(); + _ = lostEmpire.addComponent(core.Scene); + const empireMesh = lostEmpire.addComponent(rend.MeshComponent).?; + empireMesh.setMesh("m_empire"); + rend.setActiveCamera(camera); self.moveInput = try core.Axis2dBinding.create(core.MakeName("movement")); @@ -60,6 +67,18 @@ pub fn prepare(self: *@This()) !void { _ = self.moveInput.data.addListener(self, onMove); self.moveInput.activate(); + + const verticalInput = try core.Axis1dBinding.create(core.MakeName("movementVertical")); + verticalInput.addKey(.e, 1.0); + verticalInput.addKey(.q, -1.0); + + _ = verticalInput.data.addListener(self, verticalMovement); + verticalInput.activate(); +} + +fn verticalMovement(ctx: ?*anyopaque, axis: f32) void { + const self: *@This() = @ptrCast(@alignCast(ctx)); + self.verticalMove = axis; } fn onMove(ctx: ?*anyopaque, axis: core.Vector2f) void { @@ -77,8 +96,9 @@ pub fn onExit(ctx: ?*anyopaque, action: core.ActionEvent) void { pub fn tick(self: *@This(), dt: f64) void { const fdt: f32 = @floatCast(dt); if (self.camera.get(core.Scene)) |scene| { - scene.getPosRot().position = scene.getPosRot().position.add(self.moveVector.fmul(self.cameraSpeed * fdt)); - core.engine_log(" camera position >> {any}", .{scene.getPosRot().position}); + const vector = core.Vectorf{ .x = self.moveVector.x, .z = self.moveVector.z, .y = self.verticalMove }; + scene.getPosRot().position = scene.getPosRot().position.add(vector.fmul(self.cameraSpeed * fdt)); + // core.engine_log(" camera position >> {any}", .{scene.getPosRot().position}); } } @@ -88,7 +108,7 @@ pub fn deinit(self: *@This()) void { pub fn main() anyerror!void { try backlog.initializeAndRunStandardProgram(@This(), .{ - .name = "Hello World", + .name = "SDL GPU IS HERE TO LOVE YOUR MOTHER", .enabledModules = .{ .physics = true, },