diff --git a/build.zig b/build.zig index 6855569..5e00d6e 100644 --- a/build.zig +++ b/build.zig @@ -29,9 +29,9 @@ const engineDepList = [_][]const u8{ "papyrus", "platform", "rend", + "ui", "imgui", "physics", - "ui", "sys", }; @@ -274,9 +274,9 @@ pub const moduleOrder: []const []const u8 = &.{ "physics", "audio", "rend", + "ui", "imgui", "papyrus", - "ui", }; pub const DynamicModule = struct { diff --git a/engine/rend/src/sgpu/TextureList.zig b/engine/rend/src/sgpu/TextureList.zig index e4b43c4..46cc3a9 100644 --- a/engine/rend/src/sgpu/TextureList.zig +++ b/engine/rend/src/sgpu/TextureList.zig @@ -35,6 +35,7 @@ pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?asse core.engine_log("loading texture {s}", .{name.utf8()}); if (propertiesBag) |bag| { self.requestMap.put(self.allocator, name.handle(), true) catch return error.UnableToLoad; // its always true in here. + // var installed: *Texture = undefined; if (bag.textureCube) { @@ -53,6 +54,8 @@ pub fn loadAsset(self: *@This(), assetRef: assets.AssetRef, propertiesBag: ?asse installed = self.uploadTextureFromPath(name, bag.path) catch return error.UnableToLoad; } + installed.samplerMode = if (bag.textureUseBlockySampler) .blocky else .linear; + self.map.put(self.allocator, name.handle(), installed) catch return error.UnableToLoad; } } diff --git a/engine/rend/src/sgpu/renderer.zig b/engine/rend/src/sgpu/renderer.zig index c02237c..8b8c20d 100644 --- a/engine/rend/src/sgpu/renderer.zig +++ b/engine/rend/src/sgpu/renderer.zig @@ -36,6 +36,8 @@ pub const Renderer = struct { destroys: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, preDraws: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer) void }) = .{}, + shaderReloads: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{}, + depthTexture: *gpu.GPUTexture = undefined, depthFormat: gpu.GPUTextureFormat = .textureformatD32Float, @@ -108,6 +110,12 @@ pub const Renderer = struct { }; } + pub fn reloadPluginShaders(self: *@This()) void { + for (self.shaderReloads.items) |interface| { + interface.func(interface.ptr); + } + } + pub fn createRenderTargets(self: *@This()) !void { var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo); @@ -318,6 +326,10 @@ pub const Renderer = struct { if (@hasDecl(T, "onPreDraw")) { try self.preDraws.append(self.allocator, .{ .ptr = object, .func = T.onPreDraw }); } + + if (@hasDecl(T, "onShaderReload")) { + try self.shaderReloads.append(self.allocator, .{ .ptr = object, .func = T.onShaderReload }); + } } pub fn createRendererEngineObject(self: *@This(), T: type) !*T { @@ -833,8 +845,23 @@ pub const Renderer = struct { } if (component.mesh) |mesh| { + // TODO put the sampler onto the texture itself - renderpass.bindGPUFragmentSamplers(0, &.{ .texture = t.?.texture, .sampler = self.linearSampler }, 1); + + if (t) |_t| { + var sampler: *gpu.GPUSampler = undefined; + + switch (_t.samplerMode) { + .blocky => { + sampler = self.blockySampler; + }, + .linear => { + sampler = self.linearSampler; + }, + } + + renderpass.bindGPUFragmentSamplers(0, &.{ .texture = _t.texture, .sampler = sampler }, 1); + } if (component.cmrf) |cmrf| { cmrf(component.cmrf_ctx); @@ -925,6 +952,7 @@ pub const Renderer = struct { self.uploadCleanup.deinit(self.allocator); self.preDraws.deinit(self.allocator); self.postRenders.deinit(self.allocator); + self.shaderReloads.deinit(self.allocator); self.uploads.deinit(self.allocator); self.destroys.deinit(self.allocator); self.allocator.destroy(self); @@ -975,6 +1003,7 @@ pub fn reloadShaders() !void { try context().createMeshPipeline(); try context().createPostProcessingPipeline(); try context().ssaoSystem.createPipeline(); + context().reloadPluginShaders(); } // ====== renderer API ======= diff --git a/engine/rend/src/texture/texture.zig b/engine/rend/src/texture/texture.zig index b10bf66..a39ab1b 100644 --- a/engine/rend/src/texture/texture.zig +++ b/engine/rend/src/texture/texture.zig @@ -2,6 +2,12 @@ pub const TextureFormat = enum(u8) { f32_rgba, u8_rgba, }; + +pub const SamplerMode = enum(u8) { + blocky, + linear, +}; + pub const TextureUsage = struct { mesh: bool = false, cube: bool = false, @@ -15,6 +21,7 @@ pub const Texture = struct { size: core.Vector2u, name: core.Name, texture: *GPUTextureType, + samplerMode: SamplerMode = .linear, }; const core = @import("core"); diff --git a/engine/ui/shaders/rect.vert.hlsl b/engine/ui/shaders/rect.vert.hlsl index 050793a..27b4c0b 100644 --- a/engine/ui/shaders/rect.vert.hlsl +++ b/engine/ui/shaders/rect.vert.hlsl @@ -39,16 +39,17 @@ VertexOut main(Input v) float2 finalSize = (s.imageSize / Extents); //float zLevel = objectBuffer.objects[gl_BaseInstance].zLevel; - float2 finalPos = ((s.imagePosition / Extents) * 2 - 1) - s.anchorPoint * finalSize * s.scale; + float2 finalPos = (((s.imagePosition) / Extents) * 2 - 1) - s.anchorPoint * finalSize * s.scale; o.Color = s.baseColor; float4 fp = float4( finalPos.x + ( v.Position.x * finalSize.x * s.scale.x), - finalPos.y + (-v.Position.y * finalSize.y * s.scale.y), + finalPos.y + ( v.Position.y * finalSize.y * s.scale.y), v.Position.z, 1.0 ); + fp.y = -fp.y; o.Position = fp; o.UV = float2(1 - v.UV.x, v.UV.y); o.pixelPosition = (v.Position.xy - s.anchorPoint) / 2 * s.imageSize; diff --git a/engine/ui/src/sgpu/papyrusSgpu.zig b/engine/ui/src/sgpu/papyrusSgpu.zig index a20f66f..aed7ff3 100644 --- a/engine/ui/src/sgpu/papyrusSgpu.zig +++ b/engine/ui/src/sgpu/papyrusSgpu.zig @@ -185,6 +185,11 @@ pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void { self.drawToTarget(cmd, self.screenContext, rend.context().state.swapchainTargetTexture.?); } +pub fn onShaderReload(p: *anyopaque) void { + const self: *@This() = @ptrCast(@alignCast(p)); + self.createRectPipeline() catch return; // you think i give a remote fuck about leaks? this is a debug function son. +} + pub fn drawToTarget(self: *@This(), cmd: *gpu.GPUCommandBuffer, ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void { ctx.makeDrawList(&self.drawList, &self.stringArena) catch return; diff --git a/lib/sdl3/build.zig b/lib/sdl3/build.zig index 0e6610e..2b59a49 100644 --- a/lib/sdl3/build.zig +++ b/lib/sdl3/build.zig @@ -8,12 +8,19 @@ pub fn addShaderDefinition( shaderName: []const u8, jsonPath: std.Build.LazyPath, ) *std.Build.Module { - const reflectedZig = b.addSystemCommand(&[_][]const u8{"python"}); - reflectedZig.addArg(sdl3Path ++ "/spvreflect/spvreflect.py"); - reflectedZig.addFileArg(jsonPath); - reflectedZig.addArg("--output"); + // Create the spvReflect2 executable + const spvReflect = b.addExecutable(.{ + .name = "spvReflect2", + .target = b.graph.host, + .optimize = .ReleaseFast, + .root_source_file = b.path(sdl3Path ++ "/spvreflect/spvReflect2.zig"), + }); - const reflectedZigOut = reflectedZig.addOutputFileArg(b.fmt("reflected/{s}.zig", .{shaderName})); + // Run the spvReflect2 executable + const runReflect = b.addRunArtifact(spvReflect); + runReflect.addFileArg(jsonPath); + + const reflectedZigOut = runReflect.addOutputFileArg(b.fmt("reflected/{s}.zig", .{shaderName})); const module = b.createModule(.{ .root_source_file = reflectedZigOut, .optimize = optimize }); const dep = b.dependency("shaderTypes", .{ diff --git a/lib/sdl3/spvreflect/spvReflect2.zig b/lib/sdl3/spvreflect/spvReflect2.zig index edfbe30..abe2139 100644 --- a/lib/sdl3/spvreflect/spvReflect2.zig +++ b/lib/sdl3/spvreflect/spvReflect2.zig @@ -1,12 +1,20 @@ const std = @import("std"); fn printLog(comptime fmt: []const u8, args: anytype) void { - //_ = fmt; - // _ = args; - std.debug.print(fmt ++ "\n", args); + _ = fmt; + _ = args; + // std.debug.print(fmt ++ "\n", args); } +// so bad but its fun +var workingFileName: []const u8 = "Unknown File"; +var first: bool = true; + fn printErr(comptime fmt: []const u8, args: anytype) void { + if (first) { + std.debug.print("Error in {s}:\n", .{workingFileName}); + first = false; + } std.debug.print(fmt ++ "\n", args); } @@ -275,7 +283,6 @@ const UboList = struct { pub fn parseFromJson(self: *@This(), parsed: std.json.Parsed(std.json.Value), map: *const TypeMap) !void { const root = parsed.value.object; const list = root.get("ubos") orelse { - printErr("missing ubos entry", .{}); return; }; @@ -358,7 +365,6 @@ const SsboList = struct { pub fn parseFromJson(self: *@This(), parsed: std.json.Parsed(std.json.Value), map: *const TypeMap) !void { const root = parsed.value.object; const list = root.get("ssbos") orelse { - printErr("missing ssbos entry", .{}); return; }; @@ -562,7 +568,7 @@ const OutputFile = struct { try writer.print("\n pub const Buffer: BufferInfo = .{{ .storage = {d} }};\n", .{ssbo.binding}); - try writer.print("\n pub const FieldDetails: []shaderTypes.FieldDetail = &.{{ \n", .{}); + try writer.print("\n pub const FieldDetails: []const shaderTypes.FieldDetail = &.{{ \n", .{}); for (ssboType.fields.items) |field| { try writer.print(" " ** 8, .{}); try writer.print(".{{ .name = \"{s}\", .offset = {d}, .size = {d} }},\n", .{ field.name, field.offset, self.typeMap.getFieldSize(field) }); @@ -601,7 +607,7 @@ const OutputFile = struct { // generate buffer info using .uniform instead of .storage try writer.print("\n pub const Buffer: BufferInfo = .{{ .uniform = {d} }};\n", .{ubo.binding}); - try writer.print("\n pub const FieldDetails: []shaderTypes.FieldDetail = &.{{ \n", .{}); + try writer.print("\n pub const FieldDetails: []const shaderTypes.FieldDetail = &.{{ \n", .{}); for (uboType.fields.items) |field| { try writer.print(" " ** 8, .{}); try writer.print(".{{ .name = \"{s}\", .offset = {d}, .size = {d} }},\n", .{ field.name, field.offset, self.typeMap.getFieldSize(field) }); @@ -664,6 +670,7 @@ pub fn main() !void { } const jsonFilePath = args[1]; + workingFileName = jsonFilePath; const file = std.fs.cwd().openFile(jsonFilePath, .{}) catch |err| { printErr("Error opening file '{s}': {}", .{ jsonFilePath, err }); @@ -710,7 +717,7 @@ pub fn main() !void { try outputfile.generateSsbos(); try outputfile.generateUbos(); try outputfile.generateLoadArguments(); - printLog("{s}", .{outputfile.output.items}); + // printLog("{s}", .{outputfile.output.items}); try outputfile.finalize(); try outputfile.writeOut(args[2]); defer outputfile.deinit(); diff --git a/lib/sdl3/spvreflect/spvreflect.py b/lib/sdl3/spvreflect/spvreflect.py index 338d83b..acfa351 100644 --- a/lib/sdl3/spvreflect/spvreflect.py +++ b/lib/sdl3/spvreflect/spvreflect.py @@ -3,6 +3,8 @@ import argparse import subprocess import json +# THIS IS OLD, DO NOT USE + # quick and dirty dependency-free script to # build and output reflected zig files for # creating definitions for use with the json defs created diff --git a/projects/content/_shaders/dxil/rect.vert.dxil b/projects/content/_shaders/dxil/rect.vert.dxil index 1bc9fec..a1d162e 100644 Binary files a/projects/content/_shaders/dxil/rect.vert.dxil and b/projects/content/_shaders/dxil/rect.vert.dxil differ diff --git a/projects/content/_shaders/msl/rect.vert.msl b/projects/content/_shaders/msl/rect.vert.msl index 23538c3..477773d 100644 --- a/projects/content/_shaders/msl/rect.vert.msl +++ b/projects/content/_shaders/msl/rect.vert.msl @@ -47,13 +47,16 @@ vertex main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Uniform main0_out out = {}; float2 _63 = scene._m0[gl_InstanceIndex]._imageSize / Uniforms.Extents; float2 _69 = (((scene._m0[gl_InstanceIndex].imagePosition / Uniforms.Extents) * 2.0) - float2(1.0)) - ((scene._m0[gl_InstanceIndex].anchorPoint * _63) * scene._m0[gl_InstanceIndex].scale); - float2 _99 = ((in.in_var_TEXCOORD0.xy - scene._m0[gl_InstanceIndex].anchorPoint) * float2(0.5)) * scene._m0[gl_InstanceIndex]._imageSize; - _99.y = scene._m0[gl_InstanceIndex]._imageSize.y - _99.y; + float _85 = _69.y + ((in.in_var_TEXCOORD0.y * _63.y) * scene._m0[gl_InstanceIndex].scale.y); + float4 _88 = float4(_69.x + ((in.in_var_TEXCOORD0.x * _63.x) * scene._m0[gl_InstanceIndex].scale.x), _85, in.in_var_TEXCOORD0.z, 1.0); + _88.y = -_85; + float2 _100 = ((in.in_var_TEXCOORD0.xy - scene._m0[gl_InstanceIndex].anchorPoint) * float2(0.5)) * scene._m0[gl_InstanceIndex]._imageSize; + _100.y = scene._m0[gl_InstanceIndex]._imageSize.y - _100.y; out.out_var_TEXCOORD0 = scene._m0[gl_InstanceIndex].baseColor; out.out_var_TEXCOORD1 = float2(1.0 - in.in_var_TEXCOORD3.x, in.in_var_TEXCOORD3.y); - out.out_var_TEXCOORD2 = _99; + out.out_var_TEXCOORD2 = _100; out.out_var_TEXCOORD3 = gl_InstanceIndex; - out.gl_Position = float4(_69.x + ((in.in_var_TEXCOORD0.x * _63.x) * scene._m0[gl_InstanceIndex].scale.x), _69.y + (((-in.in_var_TEXCOORD0.y) * _63.y) * scene._m0[gl_InstanceIndex].scale.y), in.in_var_TEXCOORD0.z, 1.0); + out.gl_Position = _88; return out; } diff --git a/projects/content/_shaders/spv/rect.vert.spv b/projects/content/_shaders/spv/rect.vert.spv index 7fcf962..0839336 100644 Binary files a/projects/content/_shaders/spv/rect.vert.spv and b/projects/content/_shaders/spv/rect.vert.spv differ