added split between transparent and opaque renderpasses
This commit is contained in:
parent
7664349913
commit
c008e5232d
|
|
@ -325,7 +325,7 @@ pub fn defineComponent(comptime Component: type, allocator: std.mem.Allocator) !
|
||||||
const ContainerType = @TypeOf(Component.BaseContainer.*);
|
const ContainerType = @TypeOf(Component.BaseContainer.*);
|
||||||
Component.BaseContainer = try ContainerType.create(allocator);
|
Component.BaseContainer = try ContainerType.create(allocator);
|
||||||
|
|
||||||
core.engine_log("Component container created " ++ @typeName(Component) ++ " @{x}", .{@intFromPtr(Component.BaseContainer)});
|
core.engine_log("Component container created " ++ @typeName(Component) ++ " @{x} component size = {d} containerType = {s}", .{ @intFromPtr(Component.BaseContainer), @sizeOf(Component), @TypeOf(Component.BaseContainer.*).EcsContainerInterfaceVTable.containerTypeName });
|
||||||
const container = makeEcsContainerRef(Component.BaseContainer);
|
const container = makeEcsContainerRef(Component.BaseContainer);
|
||||||
try registerEcsContainer(container, core.MakeName(Component.ComponentName));
|
try registerEcsContainer(container, core.MakeName(Component.ComponentName));
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -406,7 +406,7 @@ pub const Engine = struct {
|
||||||
pub const NeonObjectParams = struct {
|
pub const NeonObjectParams = struct {
|
||||||
can_tick: ?bool = null,
|
can_tick: ?bool = null,
|
||||||
responds_to_events: bool = false,
|
responds_to_events: bool = false,
|
||||||
isCore: bool = false,
|
isCore: bool = false, // if set true, object destruction order matters.
|
||||||
};
|
};
|
||||||
|
|
||||||
const Src = std.builtin.SourceLocation;
|
const Src = std.builtin.SourceLocation;
|
||||||
|
|
|
||||||
|
|
@ -35,5 +35,6 @@ pub const PrimitiveText = struct {
|
||||||
fontHandle: u32, // this is just a core.Name handle
|
fontHandle: u32, // this is just a core.Name handle
|
||||||
flags: packed struct {
|
flags: packed struct {
|
||||||
setSourceGeometry: bool,
|
setSourceGeometry: bool,
|
||||||
|
debugText: bool = false,
|
||||||
},
|
},
|
||||||
};
|
};
|
||||||
|
|
|
||||||
|
|
@ -1251,7 +1251,7 @@ pub const Context = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
try drawList.append(.{
|
try drawList.append(.{
|
||||||
.node = .{},
|
.node = .{ .index = @intCast(i) },
|
||||||
.primitive = .{
|
.primitive = .{
|
||||||
.Text = .{
|
.Text = .{
|
||||||
.text = LocText.fromUtf8Z(textData),
|
.text = LocText.fromUtf8Z(textData),
|
||||||
|
|
@ -1263,6 +1263,7 @@ pub const Context = struct {
|
||||||
.fontHandle = fontHandle,
|
.fontHandle = fontHandle,
|
||||||
.flags = .{
|
.flags = .{
|
||||||
.setSourceGeometry = false,
|
.setSourceGeometry = false,
|
||||||
|
.debugText = true,
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
},
|
},
|
||||||
|
|
|
||||||
|
|
@ -6,6 +6,7 @@ const dependencyList = [_][]const u8{
|
||||||
"assets",
|
"assets",
|
||||||
"sdl3",
|
"sdl3",
|
||||||
"platform",
|
"platform",
|
||||||
|
"sys",
|
||||||
"shaderTypes",
|
"shaderTypes",
|
||||||
"objLoader",
|
"objLoader",
|
||||||
"zgltf",
|
"zgltf",
|
||||||
|
|
|
||||||
|
|
@ -5,6 +5,7 @@
|
||||||
.core = .{ .path = "../core" },
|
.core = .{ .path = "../core" },
|
||||||
.assets = .{ .path = "../assets" },
|
.assets = .{ .path = "../assets" },
|
||||||
.platform = .{ .path = "../platform" },
|
.platform = .{ .path = "../platform" },
|
||||||
|
.sys = .{.path = "../sys"},
|
||||||
|
|
||||||
.sdl3 = .{ .path = "../../lib/sdl3" },
|
.sdl3 = .{ .path = "../../lib/sdl3" },
|
||||||
.ozz = .{ .path = "../../lib/ozz" },
|
.ozz = .{ .path = "../../lib/ozz" },
|
||||||
|
|
|
||||||
|
|
@ -187,6 +187,7 @@ PixelOutput main(
|
||||||
float4 s;
|
float4 s;
|
||||||
|
|
||||||
int texMode = scene[Instance].textureMode;
|
int texMode = scene[Instance].textureMode;
|
||||||
|
int flags = scene[Instance].flags;
|
||||||
if ((texMode & 0xf0) == 0x10) // YUV
|
if ((texMode & 0xf0) == 0x10) // YUV
|
||||||
{
|
{
|
||||||
float3 offset = float3(-0.0625, -0.5, -0.5);
|
float3 offset = float3(-0.0625, -0.5, -0.5);
|
||||||
|
|
@ -247,10 +248,11 @@ PixelOutput main(
|
||||||
PixelOutput o;
|
PixelOutput o;
|
||||||
|
|
||||||
o.Position = float4(WorldPos, 1.0);
|
o.Position = float4(WorldPos, 1.0);
|
||||||
|
|
||||||
o.Normal = float4(ScreenNormal, 1.0);
|
o.Normal = float4(ScreenNormal, 1.0);
|
||||||
|
|
||||||
o.Color = float4(c2, alpha);
|
o.Color = float4(c2, alpha);
|
||||||
o.Emissive = float4(0.0, 0.0, 0.0, 1.0);
|
o.Emissive = float4(0.0, 0.0, 0.0, 0.0);
|
||||||
if(c2.x > 1.0) o.Emissive.x = c2.x;
|
if(c2.x > 1.0) o.Emissive.x = c2.x;
|
||||||
if(c2.y > 1.0) o.Emissive.y = c2.y;
|
if(c2.y > 1.0) o.Emissive.y = c2.y;
|
||||||
if(c2.z > 1.0) o.Emissive.z = c2.z;
|
if(c2.z > 1.0) o.Emissive.z = c2.z;
|
||||||
|
|
|
||||||
|
|
@ -133,7 +133,8 @@ float4 main(float2 UV : TEXCOORD0) : SV_Target0
|
||||||
|
|
||||||
#if 0
|
#if 0
|
||||||
float4 ssao = SsaoTexture.Sample(Sampler2, uv);
|
float4 ssao = SsaoTexture.Sample(Sampler2, uv);
|
||||||
c = ssao.xyz;
|
//c.x += (1.0 - ssao.x) * 0.7;
|
||||||
|
c = ssao;
|
||||||
#else
|
#else
|
||||||
|
|
||||||
float3 ssao = blurSSAO(uv);
|
float3 ssao = blurSSAO(uv);
|
||||||
|
|
@ -143,8 +144,6 @@ float4 main(float2 UV : TEXCOORD0) : SV_Target0
|
||||||
//float4 x = SsaoTexture.Sample(Sampler2, uv);
|
//float4 x = SsaoTexture.Sample(Sampler2, uv);
|
||||||
//c = x;
|
//c = x;
|
||||||
|
|
||||||
// c = float3(ssao, ssao, ssao);
|
|
||||||
|
|
||||||
c.x *= 1.0 + 0.000001 * EmissiveTexture.Sample(Sampler1, uv).x;
|
c.x *= 1.0 + 0.000001 * EmissiveTexture.Sample(Sampler1, uv).x;
|
||||||
c.x *= 1.0 + 0.000001 * ColorTexture.Sample(Sampler0, uv).x;
|
c.x *= 1.0 + 0.000001 * ColorTexture.Sample(Sampler0, uv).x;
|
||||||
c.x *= 1.0 + 0.000001 * SsaoTexture.Sample(Sampler2, uv).x;
|
c.x *= 1.0 + 0.000001 * SsaoTexture.Sample(Sampler2, uv).x;
|
||||||
|
|
|
||||||
|
|
@ -5,7 +5,7 @@ struct Scene
|
||||||
uint textureMode; // 0 = regular triple,
|
uint textureMode; // 0 = regular triple,
|
||||||
// 0x10 = video yuv,
|
// 0x10 = video yuv,
|
||||||
// bit 0 == srgb correction
|
// bit 0 == srgb correction
|
||||||
// bit 1 == fullbright
|
// bit 1 == fullbright // 0x2
|
||||||
// bit 2 = reserved
|
// bit 2 = reserved
|
||||||
// bit 3 = reserved
|
// bit 3 = reserved
|
||||||
// bit 4 - 7 = color space:
|
// bit 4 - 7 = color space:
|
||||||
|
|
|
||||||
|
|
@ -98,7 +98,12 @@ float4 main(float2 UV: TEXCOORD0) : SV_Target0
|
||||||
// float x = length(c);
|
// float x = length(c);
|
||||||
// c = float4(x, x, x, 1.0);
|
// c = float4(x, x, x, 1.0);
|
||||||
|
|
||||||
|
#if 1
|
||||||
c = occlusion;
|
c = occlusion;
|
||||||
|
#else
|
||||||
|
|
||||||
|
c = mul(View, PositionTexture.Sample(Sampler0, uv)).z / 100; // texture(gPosition, offset.xy).z; // get depth value of kernel sample
|
||||||
|
#endif
|
||||||
//float j = x.z;
|
//float j = x.z;
|
||||||
//c = float4(x, 1.0);
|
//c = float4(x, 1.0);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -433,7 +433,6 @@ pub const AnimationSystem = struct {
|
||||||
Animator.allocator = alloc;
|
Animator.allocator = alloc;
|
||||||
|
|
||||||
core.engine_logs("Animation System initialized");
|
core.engine_logs("Animation System initialized");
|
||||||
try core.defineComponent(Animator, alloc);
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -464,7 +463,6 @@ pub const AnimationSystem = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.slots.deinit();
|
self.slots.deinit();
|
||||||
core.undefineComponent(Animator);
|
|
||||||
self.arena.deinit();
|
self.arena.deinit();
|
||||||
self.skeletons.deinit(self.backingAllocator);
|
self.skeletons.deinit(self.backingAllocator);
|
||||||
self.animTracks.deinit(self.backingAllocator);
|
self.animTracks.deinit(self.backingAllocator);
|
||||||
|
|
|
||||||
|
|
@ -101,6 +101,52 @@ pub const RenderInfo = struct {
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
pub const ParticleTimelineBurst = struct {
|
||||||
|
count: u32,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const ParticleTimeline = struct { func: ParticleTimelineFunc = .{} };
|
||||||
|
|
||||||
|
pub const ParticleTimelineFunc = union(enum(u8)) { burst: ParticleTimelineBurst };
|
||||||
|
|
||||||
|
pub const VfxEmitter = struct {
|
||||||
|
emitter: ParticleEmitter,
|
||||||
|
timeline: ParticleTimeline,
|
||||||
|
parent: u32,
|
||||||
|
transform: core.Mat,
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const VfxComponent = struct {
|
||||||
|
// aims to replace the ParticleEmitter
|
||||||
|
// instead of having just one particle emitter, the VfxComponent manages scenes for multiple particle emitters
|
||||||
|
|
||||||
|
pub var BaseContainer: *core.SparseSet(VfxComponent) = undefined;
|
||||||
|
pub const ComponentName = "rend.VfxComponent";
|
||||||
|
pub const ScriptExports: []const []const u8 = &.{};
|
||||||
|
|
||||||
|
entity: core.Entity = undefined,
|
||||||
|
emitterList: std.MultiArrayList(VfxEmitter) = .{},
|
||||||
|
|
||||||
|
pub fn initECS(self: *@This(), handle: core.SetHandle) void {
|
||||||
|
self.entity = core.Entity{ .handle = handle };
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn addEmitter(self: *@This()) *ParticleEmitter {
|
||||||
|
_ = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn update(self: *@This(), dt: f64) void {
|
||||||
|
_ = dt;
|
||||||
|
_ = self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinitECS(self: *@This(), handle: core.SetHandle) void {
|
||||||
|
for (self.emitters.items) |emitter| {
|
||||||
|
emitter.deinitECS(handle);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
pub const ParticleEmitter = struct {
|
pub const ParticleEmitter = struct {
|
||||||
pub var BaseContainer: *core.SparseSet(ParticleEmitter) = undefined;
|
pub var BaseContainer: *core.SparseSet(ParticleEmitter) = undefined;
|
||||||
pub const ComponentName = "ParticleEmitter";
|
pub const ComponentName = "ParticleEmitter";
|
||||||
|
|
@ -324,7 +370,7 @@ pub const ParticleEmitter = struct {
|
||||||
var t_whiteName: core.Name = core.DefineName("t_white");
|
var t_whiteName: core.Name = core.DefineName("t_white");
|
||||||
var m_quad: core.Name = core.DefineName("m_screenPlane");
|
var m_quad: core.Name = core.DefineName("m_screenPlane");
|
||||||
|
|
||||||
pub fn initECS(self: *@This(), handle: core.SetHandle) void {
|
pub fn initECS(self: *@This(), handle: core.ObjectHandle) void {
|
||||||
// get the mesh component
|
// get the mesh component
|
||||||
self.entity = core.Entity{ .handle = handle };
|
self.entity = core.Entity{ .handle = handle };
|
||||||
|
|
||||||
|
|
@ -338,15 +384,21 @@ pub const ParticleEmitter = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn deinitECS(self: *@This(), handle: core.ObjectHandle) void {
|
||||||
|
_ = handle;
|
||||||
|
self.deinit();
|
||||||
|
}
|
||||||
|
|
||||||
pub fn deinit(self: *@This()) void {
|
pub fn deinit(self: *@This()) void {
|
||||||
_ = self;
|
self.life.deinit(gParticleAllocator);
|
||||||
|
self.particlesPVA.deinit(gParticleAllocator);
|
||||||
|
self.finals.deinit(gParticleAllocator);
|
||||||
|
self.size.deinit(gParticleAllocator);
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
var gParticleAllocator: std.mem.Allocator = undefined;
|
var gParticleAllocator: std.mem.Allocator = undefined;
|
||||||
|
|
||||||
pub const Effect = struct {};
|
|
||||||
|
|
||||||
pub const ParticleSystem = struct {
|
pub const ParticleSystem = struct {
|
||||||
particleArena: std.heap.ArenaAllocator,
|
particleArena: std.heap.ArenaAllocator,
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
|
|
@ -366,8 +418,6 @@ pub const ParticleSystem = struct {
|
||||||
ParticleRandRangef.randomEngine = std.Random.DefaultPrng.init(0x1234);
|
ParticleRandRangef.randomEngine = std.Random.DefaultPrng.init(0x1234);
|
||||||
ParticleRandRangef.randomFunc = ParticleRandRangef.randomEngine.random();
|
ParticleRandRangef.randomFunc = ParticleRandRangef.randomEngine.random();
|
||||||
|
|
||||||
try core.defineComponent(ParticleEmitter, allocator);
|
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -383,8 +433,6 @@ pub const ParticleSystem = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn destroy(self: *@This()) void {
|
pub fn destroy(self: *@This()) void {
|
||||||
core.undefineComponent(ParticleEmitter);
|
|
||||||
|
|
||||||
self.particleArena.deinit();
|
self.particleArena.deinit();
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -80,6 +80,8 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me
|
||||||
pub const ComponentList = struct {
|
pub const ComponentList = struct {
|
||||||
pub const _MeshComponent = MeshComponent;
|
pub const _MeshComponent = MeshComponent;
|
||||||
pub const _CameraComponent = CameraComponent;
|
pub const _CameraComponent = CameraComponent;
|
||||||
|
pub const _Animator = Animator;
|
||||||
|
pub const _ParticleEmitter = ParticleEmitter;
|
||||||
};
|
};
|
||||||
|
|
||||||
pub fn setupFromModule() void {
|
pub fn setupFromModule() void {
|
||||||
|
|
|
||||||
|
|
@ -15,7 +15,8 @@ pub const Renderer = struct {
|
||||||
shaderformat: gpu.GPUShaderFormat = undefined,
|
shaderformat: gpu.GPUShaderFormat = undefined,
|
||||||
entrypoint: []const u8 = "main",
|
entrypoint: []const u8 = "main",
|
||||||
testPipeline: *gpu.GPUGraphicsPipeline = undefined,
|
testPipeline: *gpu.GPUGraphicsPipeline = undefined,
|
||||||
meshPipe: *gpu.GPUGraphicsPipeline = undefined,
|
opaquePipe: *gpu.GPUGraphicsPipeline = undefined,
|
||||||
|
transparentPipe: *gpu.GPUGraphicsPipeline = undefined,
|
||||||
|
|
||||||
scissor: gpu.Rect = undefined, // .{ .x = 0, .y = 0, .w = 1600, .h = 900 },
|
scissor: gpu.Rect = undefined, // .{ .x = 0, .y = 0, .w = 1600, .h = 900 },
|
||||||
colorBuffer: *gpu.GPUBuffer = undefined,
|
colorBuffer: *gpu.GPUBuffer = undefined,
|
||||||
|
|
@ -40,6 +41,7 @@ pub const Renderer = struct {
|
||||||
preDraws: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer) 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 }) = .{},
|
shaderReloads: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
|
||||||
|
shaderReloadFinished: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
|
||||||
|
|
||||||
depthTexture: *gpu.GPUTexture = undefined,
|
depthTexture: *gpu.GPUTexture = undefined,
|
||||||
depthFormat: gpu.GPUTextureFormat = .textureformatD32Float,
|
depthFormat: gpu.GPUTextureFormat = .textureformatD32Float,
|
||||||
|
|
@ -122,6 +124,12 @@ pub const Renderer = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reloadPluginShadersFinished(self: *@This()) void {
|
||||||
|
for (self.shaderReloadFinished.items) |interface| {
|
||||||
|
interface.func(interface.ptr);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
pub fn createRenderTargets(self: *@This()) !void {
|
pub fn createRenderTargets(self: *@This()) !void {
|
||||||
var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo);
|
var gci = std.mem.zeroes(gpu.GPUTextureCreateInfo);
|
||||||
|
|
||||||
|
|
@ -145,6 +153,9 @@ pub const Renderer = struct {
|
||||||
|
|
||||||
gci.format = self.normalTargetFormat;
|
gci.format = self.normalTargetFormat;
|
||||||
self.state.normalTarget = self.device.createGPUTexture(&gci);
|
self.state.normalTarget = self.device.createGPUTexture(&gci);
|
||||||
|
|
||||||
|
self.swapchainTargetFormat = self.device.getGPUSwapchainTextureFormat(self.window);
|
||||||
|
core.graphics_log("swapchain format: {any}", .{self.swapchainTargetFormat});
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn startRenderer(self: *@This()) !void {
|
pub fn startRenderer(self: *@This()) !void {
|
||||||
|
|
@ -165,7 +176,8 @@ pub const Renderer = struct {
|
||||||
core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix});
|
core.engine_log("sgpu device created, using shader format: {s}", .{self.shaderSuffix});
|
||||||
core.engine_log("using renderer... scientist", .{});
|
core.engine_log("using renderer... scientist", .{});
|
||||||
|
|
||||||
try self.createMeshPipeline();
|
try self.createOpaquePipeline();
|
||||||
|
try self.createTransparentsPipeline();
|
||||||
try self.createBuffers();
|
try self.createBuffers();
|
||||||
try self.createDepthTexture();
|
try self.createDepthTexture();
|
||||||
try self.createRenderTargets();
|
try self.createRenderTargets();
|
||||||
|
|
@ -350,6 +362,7 @@ pub const Renderer = struct {
|
||||||
|
|
||||||
if (@hasDecl(T, "onShaderReload")) {
|
if (@hasDecl(T, "onShaderReload")) {
|
||||||
try self.shaderReloads.append(self.allocator, .{ .ptr = object, .func = T.onShaderReload });
|
try self.shaderReloads.append(self.allocator, .{ .ptr = object, .func = T.onShaderReload });
|
||||||
|
try self.shaderReloadFinished.append(self.allocator, .{ .ptr = object, .func = T.onShaderReloadFinished });
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -480,69 +493,120 @@ pub const Renderer = struct {
|
||||||
self.shadowCastingPipeline = self.device.createGPUGraphicsPipeline(&pci);
|
self.shadowCastingPipeline = self.device.createGPUGraphicsPipeline(&pci);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createMeshPipeline(self: *@This()) !void {
|
const CreatePipelineInfo = struct {
|
||||||
const vertex = try self.loadShader("meshes.vert", meshes_vert.LoadArgs);
|
attributes: ?std.ArrayList(gpu.GPUVertexAttribute) = null,
|
||||||
const fragment = try self.loadShader("lit_mesh.frag", lit_mesh_frag.LoadArgs);
|
pci: gpu.GPUGraphicsPipelineCreateInfo = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo),
|
||||||
|
vertexBuffers: std.ArrayListUnmanaged(gpu.GPUVertexBufferDescription) = .{},
|
||||||
|
colorTargets: std.ArrayListUnmanaged(gpu.GPUColorTargetDescription) = .{},
|
||||||
|
|
||||||
var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo);
|
pub fn init() @This() {
|
||||||
pci.vertex_shader = vertex;
|
return .{};
|
||||||
pci.fragment_shader = fragment;
|
}
|
||||||
|
|
||||||
//var attributes = try self.generateVertexAttributeList();
|
pub fn addMeshPci(self: *@This(), vertexShader: []const u8, fragmentShader: []const u8) !void {
|
||||||
var attributes = try self.addVertexAttributes(&pci);
|
const ctx = context();
|
||||||
defer attributes.deinit();
|
const pci = &self.pci;
|
||||||
|
|
||||||
pci.vertex_input_state = .{
|
const vertex = try ctx.loadShader(vertexShader, meshes_vert.LoadArgs);
|
||||||
.num_vertex_buffers = 1,
|
const fragment = try ctx.loadShader(fragmentShader, lit_mesh_frag.LoadArgs);
|
||||||
.vertex_buffer_descriptions = &[_]gpu.GPUVertexBufferDescription{
|
pci.vertex_shader = vertex;
|
||||||
.{ .slot = 0, .pitch = @sizeOf(rend.MeshVertex), .input_rate = .vertexinputrateVertex, .instance_step_rate = 0 },
|
pci.fragment_shader = fragment;
|
||||||
},
|
|
||||||
.num_vertex_attributes = @intCast(attributes.items.len),
|
|
||||||
.vertex_attributes = @ptrCast(attributes.items.ptr),
|
|
||||||
};
|
|
||||||
|
|
||||||
pci.depth_stencil_state.compare_op = .compareopLess;
|
self.attributes = try addVertexAttributesFromStruct(rend.MeshVertex, pci);
|
||||||
pci.depth_stencil_state.enable_depth_test = true;
|
|
||||||
pci.depth_stencil_state.enable_depth_write = true;
|
|
||||||
pci.depth_stencil_state.write_mask = 0xff;
|
|
||||||
|
|
||||||
self.swapchainTargetFormat = self.device.getGPUSwapchainTextureFormat(self.window);
|
try self.vertexBuffers.appendSlice(ctx.allocator, &[_]gpu.GPUVertexBufferDescription{
|
||||||
core.graphics_log("swapchain format: {any}", .{self.swapchainTargetFormat});
|
.{
|
||||||
pci.target_info.has_depth_stencil_target = true;
|
.slot = 0,
|
||||||
pci.target_info.depth_stencil_format = self.depthFormat;
|
.pitch = @sizeOf(rend.MeshVertex),
|
||||||
pci.target_info.num_color_targets = 4;
|
.input_rate = .vertexinputrateVertex,
|
||||||
pci.target_info.color_target_descriptions = &[4]gpu.GPUColorTargetDescription{
|
.instance_step_rate = 0,
|
||||||
.{
|
},
|
||||||
.format = self.hdrTextureFormat,
|
});
|
||||||
//.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
|
||||||
.blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{
|
|
||||||
.alpha_blend_op = .blendopAdd,
|
|
||||||
.color_blend_op = .blendopAdd,
|
|
||||||
.src_color_blendfactor = .blendfactorSrcAlpha,
|
|
||||||
.dst_color_blendfactor = .blendfactorOneMinusSrcAlpha,
|
|
||||||
.src_alpha_blendfactor = .blendfactorSrcAlpha,
|
|
||||||
.dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha,
|
|
||||||
.enable_blend = true,
|
|
||||||
}),
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.format = self.hdrTextureFormat,
|
|
||||||
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.format = self.positionTargetFormat,
|
|
||||||
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
|
||||||
},
|
|
||||||
.{
|
|
||||||
.format = self.normalTargetFormat,
|
|
||||||
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
|
||||||
},
|
|
||||||
};
|
|
||||||
|
|
||||||
pci.rasterizer_state.fill_mode = .fillmodeFill;
|
pci.vertex_input_state = .{
|
||||||
pci.rasterizer_state.cull_mode = .cullmodeBack;
|
.num_vertex_buffers = 1,
|
||||||
pci.rasterizer_state.front_face = .frontfaceClockwise;
|
.vertex_buffer_descriptions = self.vertexBuffers.items.ptr,
|
||||||
self.meshPipe = self.device.createGPUGraphicsPipeline(&pci);
|
.num_vertex_attributes = @intCast(self.attributes.?.items.len),
|
||||||
|
.vertex_attributes = @ptrCast(self.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 = ctx.depthFormat;
|
||||||
|
pci.target_info.num_color_targets = 4;
|
||||||
|
|
||||||
|
try self.colorTargets.appendSlice(ctx.allocator, &[4]gpu.GPUColorTargetDescription{
|
||||||
|
.{
|
||||||
|
.format = ctx.hdrTextureFormat,
|
||||||
|
//.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
||||||
|
.blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{
|
||||||
|
.alpha_blend_op = .blendopAdd,
|
||||||
|
.color_blend_op = .blendopAdd,
|
||||||
|
.src_color_blendfactor = .blendfactorSrcAlpha,
|
||||||
|
.dst_color_blendfactor = .blendfactorOneMinusSrcAlpha,
|
||||||
|
.src_alpha_blendfactor = .blendfactorSrcAlpha,
|
||||||
|
.dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha,
|
||||||
|
.enable_blend = true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.format = ctx.hdrTextureFormat,
|
||||||
|
// .blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
||||||
|
.blend_state = std.mem.zeroInit(gpu.GPUColorTargetBlendState, .{
|
||||||
|
.alpha_blend_op = .blendopAdd,
|
||||||
|
.color_blend_op = .blendopAdd,
|
||||||
|
.src_color_blendfactor = .blendfactorSrcAlpha,
|
||||||
|
.dst_color_blendfactor = .blendfactorOneMinusSrcAlpha,
|
||||||
|
.src_alpha_blendfactor = .blendfactorSrcAlpha,
|
||||||
|
.dst_alpha_blendfactor = .blendfactorOneMinusSrcAlpha,
|
||||||
|
.enable_blend = true,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.format = ctx.positionTargetFormat,
|
||||||
|
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
||||||
|
},
|
||||||
|
.{
|
||||||
|
.format = ctx.normalTargetFormat,
|
||||||
|
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
pci.target_info.color_target_descriptions = self.colorTargets.items.ptr;
|
||||||
|
|
||||||
|
pci.rasterizer_state.fill_mode = .fillmodeFill;
|
||||||
|
pci.rasterizer_state.cull_mode = .cullmodeBack;
|
||||||
|
pci.rasterizer_state.front_face = .frontfaceClockwise;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn deinit(self: *@This()) void {
|
||||||
|
if (self.attributes) |*a| {
|
||||||
|
a.deinit();
|
||||||
|
}
|
||||||
|
self.vertexBuffers.deinit(context().allocator);
|
||||||
|
self.colorTargets.deinit(context().allocator);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
pub fn createTransparentsPipeline(self: *@This()) !void {
|
||||||
|
var createInfo = CreatePipelineInfo.init();
|
||||||
|
try createInfo.addMeshPci("meshes.vert", "lit_mesh.frag");
|
||||||
|
defer createInfo.deinit();
|
||||||
|
|
||||||
|
createInfo.pci.depth_stencil_state.enable_depth_write = false;
|
||||||
|
|
||||||
|
self.transparentPipe = self.device.createGPUGraphicsPipeline(&createInfo.pci);
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn createOpaquePipeline(self: *@This()) !void {
|
||||||
|
var createInfo = CreatePipelineInfo.init();
|
||||||
|
try createInfo.addMeshPci("meshes.vert", "lit_mesh.frag");
|
||||||
|
defer createInfo.deinit();
|
||||||
|
|
||||||
|
self.opaquePipe = self.device.createGPUGraphicsPipeline(&createInfo.pci);
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn createBuffers(self: *@This()) !void {
|
pub fn createBuffers(self: *@This()) !void {
|
||||||
|
|
@ -864,34 +928,39 @@ pub const Renderer = struct {
|
||||||
renderpass.endGPURenderPass();
|
renderpass.endGPURenderPass();
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawMeshes(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
var meshRenderPassTargetInfo: ?[4]gpu.GPUColorTargetInfo = null;
|
||||||
// can cache this
|
|
||||||
const targetInfo: [4]gpu.GPUColorTargetInfo = .{
|
|
||||||
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
|
||||||
.texture = self.state.targetTexture,
|
|
||||||
.load_op = .loadopLoad,
|
|
||||||
.store_op = .storeopStore,
|
|
||||||
}),
|
|
||||||
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
|
||||||
.texture = self.state.emissiveTarget,
|
|
||||||
.load_op = .loadopClear,
|
|
||||||
.store_op = .storeopStore,
|
|
||||||
}),
|
|
||||||
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
|
||||||
.texture = self.state.positionTarget,
|
|
||||||
.load_op = .loadopClear,
|
|
||||||
.store_op = .storeopStore,
|
|
||||||
}),
|
|
||||||
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
|
||||||
.texture = self.state.normalTarget,
|
|
||||||
.load_op = .loadopClear,
|
|
||||||
.store_op = .storeopStore,
|
|
||||||
}),
|
|
||||||
};
|
|
||||||
|
|
||||||
const depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{
|
pub fn beginMeshRenderPass(self: *@This(), cmd: *gpu.GPUCommandBuffer, pipeline: *gpu.GPUGraphicsPipeline, clearDepth: bool) *gpu.GPURenderPass {
|
||||||
|
if (meshRenderPassTargetInfo == null) {
|
||||||
|
meshRenderPassTargetInfo = .{
|
||||||
|
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
||||||
|
.texture = self.state.targetTexture,
|
||||||
|
.load_op = .loadopLoad,
|
||||||
|
.store_op = .storeopStore,
|
||||||
|
}),
|
||||||
|
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
||||||
|
.texture = self.state.emissiveTarget,
|
||||||
|
.load_op = .loadopClear,
|
||||||
|
.store_op = .storeopStore,
|
||||||
|
}),
|
||||||
|
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
||||||
|
.texture = self.state.positionTarget,
|
||||||
|
.load_op = .loadopClear,
|
||||||
|
.store_op = .storeopStore,
|
||||||
|
}),
|
||||||
|
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
||||||
|
.texture = self.state.normalTarget,
|
||||||
|
.load_op = .loadopClear,
|
||||||
|
.store_op = .storeopStore,
|
||||||
|
}),
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
|
const targetInfo = meshRenderPassTargetInfo.?;
|
||||||
|
|
||||||
|
var depthTarget = std.mem.zeroInit(gpu.GPUDepthStencilTargetInfo, .{
|
||||||
.texture = self.depthTexture,
|
.texture = self.depthTexture,
|
||||||
.load_op = .loadopClear,
|
.load_op = .loadopLoad,
|
||||||
.store_op = .storeopDontCare,
|
.store_op = .storeopDontCare,
|
||||||
.stencil_load_op = .loadopDontCare,
|
.stencil_load_op = .loadopDontCare,
|
||||||
.stencil_store_op = .storeopDontCare,
|
.stencil_store_op = .storeopDontCare,
|
||||||
|
|
@ -899,6 +968,10 @@ pub const Renderer = struct {
|
||||||
.clear_stencil = 0,
|
.clear_stencil = 0,
|
||||||
});
|
});
|
||||||
|
|
||||||
|
if (clearDepth) {
|
||||||
|
depthTarget.load_op = .loadopClear;
|
||||||
|
}
|
||||||
|
|
||||||
self.state.pass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget);
|
self.state.pass = cmd.beginGPURenderPass(&targetInfo, 4, &depthTarget);
|
||||||
const renderpass = self.state.pass.?;
|
const renderpass = self.state.pass.?;
|
||||||
renderpass.setGPUScissor(&self.scissor);
|
renderpass.setGPUScissor(&self.scissor);
|
||||||
|
|
@ -913,10 +986,14 @@ pub const Renderer = struct {
|
||||||
renderpass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1);
|
renderpass.bindGPUVertexBuffers(0, &.{ .buffer = self.meshPool.vertexBuffer, .offset = 0 }, 1);
|
||||||
renderpass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit);
|
renderpass.bindGPUIndexBuffer(&.{ .buffer = self.meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit);
|
||||||
|
|
||||||
renderpass.bindGPUGraphicsPipeline(self.meshPipe);
|
renderpass.bindGPUGraphicsPipeline(pipeline);
|
||||||
renderpass.bindGPUFragmentSamplers(self.shadowDepthTextureSlot, &.{ .texture = self.shadowDepthTexture, .sampler = self.blockySampler }, 1);
|
renderpass.bindGPUFragmentSamplers(self.shadowDepthTextureSlot, &.{ .texture = self.shadowDepthTexture, .sampler = self.blockySampler }, 1);
|
||||||
|
|
||||||
try self.uploadUniforms(cmd);
|
return renderpass;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawOpaques(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
||||||
|
const renderpass = self.beginMeshRenderPass(cmd, self.opaquePipe, true);
|
||||||
|
|
||||||
//rendering each mesh
|
//rendering each mesh
|
||||||
{
|
{
|
||||||
|
|
@ -959,6 +1036,13 @@ pub const Renderer = struct {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
renderpass.endGPURenderPass();
|
||||||
|
self.state.pass = null;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn drawTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
||||||
|
const renderpass = self.beginMeshRenderPass(cmd, self.transparentPipe, false);
|
||||||
|
|
||||||
for (self.postMesh.items) |interface| {
|
for (self.postMesh.items) |interface| {
|
||||||
interface.func(interface.ptr, cmd, renderpass);
|
interface.func(interface.ptr, cmd, renderpass);
|
||||||
}
|
}
|
||||||
|
|
@ -967,6 +1051,14 @@ pub const Renderer = struct {
|
||||||
self.state.pass = null;
|
self.state.pass = null;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn drawMeshes(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
||||||
|
// can cache this
|
||||||
|
try self.uploadUniforms(cmd);
|
||||||
|
|
||||||
|
self.drawOpaques(cmd);
|
||||||
|
self.drawTransparents(cmd);
|
||||||
|
}
|
||||||
|
|
||||||
pub fn renderTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
pub fn renderTransparents(self: *@This(), cmd: *gpu.GPUCommandBuffer) void {
|
||||||
const targetInfo: [4]gpu.GPUColorTargetInfo = .{
|
const targetInfo: [4]gpu.GPUColorTargetInfo = .{
|
||||||
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
|
||||||
|
|
@ -1080,6 +1172,8 @@ pub const Renderer = struct {
|
||||||
self.preDraws.deinit(self.allocator);
|
self.preDraws.deinit(self.allocator);
|
||||||
self.postRenders.deinit(self.allocator);
|
self.postRenders.deinit(self.allocator);
|
||||||
self.shaderReloads.deinit(self.allocator);
|
self.shaderReloads.deinit(self.allocator);
|
||||||
|
self.shaderReloadFinished.deinit(self.allocator);
|
||||||
|
|
||||||
self.uploads.deinit(self.allocator);
|
self.uploads.deinit(self.allocator);
|
||||||
self.destroys.deinit(self.allocator);
|
self.destroys.deinit(self.allocator);
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
|
|
@ -1123,16 +1217,37 @@ const SkyboxSystem = @import("SkyboxSystem.zig");
|
||||||
// debug api
|
// debug api
|
||||||
|
|
||||||
pub fn reloadShaders() !void {
|
pub fn reloadShaders() !void {
|
||||||
_ = core.shell.runCmd(context().allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch {
|
if (core.BuildOption("static_build")) {
|
||||||
core.graphics_logs("shader cook script failed");
|
core.graphics_logs("skipping shader hotreload, not available in static build");
|
||||||
return;
|
return;
|
||||||
};
|
}
|
||||||
try context().createMeshPipeline();
|
|
||||||
try context().createPostProcessingPipeline();
|
// _ = core.shell.runCmd(context().allocator, &.{ "python", "../tools/scripts/cookShaders.py" }, ".") catch {
|
||||||
try context().ssaoSystem.createPipeline();
|
// core.graphics_logs("shader cook script failed");
|
||||||
|
// return;
|
||||||
|
// };
|
||||||
|
try sys.start_CompileShaders(null, reloadShadersFinished);
|
||||||
context().reloadPluginShaders();
|
context().reloadPluginShaders();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn reloadShadersFinished(ctx: ?*anyopaque) void {
|
||||||
|
_ = ctx;
|
||||||
|
|
||||||
|
context().createOpaquePipeline() catch {
|
||||||
|
core.engine_errs("unable to rebuild pipeline");
|
||||||
|
};
|
||||||
|
context().createTransparentsPipeline() catch {
|
||||||
|
core.engine_errs("unable to rebuild pipeline");
|
||||||
|
};
|
||||||
|
context().createPostProcessingPipeline() catch {
|
||||||
|
core.engine_errs("unable to rebuild pipeline");
|
||||||
|
};
|
||||||
|
context().ssaoSystem.createPipeline() catch {
|
||||||
|
core.engine_errs("unable to rebuild pipeline");
|
||||||
|
};
|
||||||
|
context().reloadPluginShadersFinished();
|
||||||
|
}
|
||||||
|
|
||||||
// ====== renderer API =======
|
// ====== renderer API =======
|
||||||
pub fn createInstance() !void {
|
pub fn createInstance() !void {
|
||||||
_ = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true });
|
_ = try core.createObject(Renderer, .{ .can_tick = true, .isCore = true });
|
||||||
|
|
@ -1199,6 +1314,7 @@ const tracy = core.tracy;
|
||||||
|
|
||||||
const animationSystem = rend.animationSystem;
|
const animationSystem = rend.animationSystem;
|
||||||
|
|
||||||
|
const sys = @import("sys");
|
||||||
const builtin = @import("builtin");
|
const builtin = @import("builtin");
|
||||||
pub const SsaoSystem = @import("ssao.zig");
|
pub const SsaoSystem = @import("ssao.zig");
|
||||||
pub const ParticleRenderer = @import("ParticleRenderer.zig");
|
pub const ParticleRenderer = @import("ParticleRenderer.zig");
|
||||||
|
|
|
||||||
|
|
@ -1,9 +1,13 @@
|
||||||
const std = @import("std");
|
const std = @import("std");
|
||||||
pub const core = @import("core");
|
pub const core = @import("core");
|
||||||
|
pub const systemProc = @import("systemProc.zig");
|
||||||
|
|
||||||
pub const SubprocessTask = @import("systemProc.zig").SubprocessTask;
|
pub const SubprocessTask = systemProc.SubprocessTask;
|
||||||
|
pub const SystemRunner = systemProc.SystemRunner;
|
||||||
pub const runCommand = SubprocessTask.runCommand;
|
pub const runCommand = SubprocessTask.runCommand;
|
||||||
|
|
||||||
|
pub const start_CompileShaders = systemProc.start_CompileShaders;
|
||||||
|
|
||||||
// TODO get rid of core.ModuleDescription
|
// TODO get rid of core.ModuleDescription
|
||||||
// it's really not needed anymore with the
|
// it's really not needed anymore with the
|
||||||
// new backlog API
|
// new backlog API
|
||||||
|
|
@ -26,8 +30,12 @@ pub fn start_module(spec: *core.SpecVariantMap, args: anytype, allocator: std.me
|
||||||
_ = args;
|
_ = args;
|
||||||
_ = spec;
|
_ = spec;
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
|
|
||||||
|
_ = try core.createObject(SystemRunner, .{ .can_tick = true });
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn setupFromModule() void {}
|
||||||
|
|
||||||
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
pub fn shutdown_module(allocator: std.mem.Allocator) void {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
}
|
}
|
||||||
|
|
|
||||||
|
|
@ -39,12 +39,12 @@ pub const SubprocessTask = struct {
|
||||||
self.mutex.lock();
|
self.mutex.lock();
|
||||||
self.stderr = .{};
|
self.stderr = .{};
|
||||||
self.stdout = .{};
|
self.stdout = .{};
|
||||||
debugPrint("running task", .{});
|
core.engine_log("running task", .{});
|
||||||
for (self.args) |arg| {
|
for (self.args) |arg| {
|
||||||
debugPrint("{s}", .{arg});
|
core.engine_log("{s}", .{arg});
|
||||||
}
|
}
|
||||||
|
|
||||||
debugPrint("cwd = {s}", .{self.workingDir.?});
|
core.engine_log("cwd = {s}", .{self.workingDir.?});
|
||||||
self.child = std.process.Child.init(self.args, self.allocator);
|
self.child = std.process.Child.init(self.args, self.allocator);
|
||||||
self.child.?.stdout_behavior = .Inherit;
|
self.child.?.stdout_behavior = .Inherit;
|
||||||
self.child.?.stderr_behavior = .Inherit;
|
self.child.?.stderr_behavior = .Inherit;
|
||||||
|
|
@ -77,7 +77,7 @@ pub const SubprocessTask = struct {
|
||||||
self.mutex.lock();
|
self.mutex.lock();
|
||||||
if (self.child) |*child| {
|
if (self.child) |*child| {
|
||||||
_ = child;
|
_ = child;
|
||||||
debugPrint("destroying child process", .{});
|
core.engine_log("destroying child process", .{});
|
||||||
}
|
}
|
||||||
self.mutex.unlock();
|
self.mutex.unlock();
|
||||||
self.stdout.deinit(self.allocator);
|
self.stdout.deinit(self.allocator);
|
||||||
|
|
@ -141,3 +141,162 @@ pub const SubprocessTask = struct {
|
||||||
return task;
|
return task;
|
||||||
}
|
}
|
||||||
};
|
};
|
||||||
|
|
||||||
|
fn findRootDir(allocator: std.mem.Allocator) ![]u8 {
|
||||||
|
var current_dir = std.fs.cwd();
|
||||||
|
|
||||||
|
// Start from current directory and walk up
|
||||||
|
var path_components = std.ArrayList([]const u8).init(allocator);
|
||||||
|
defer path_components.deinit();
|
||||||
|
|
||||||
|
// Try current directory first
|
||||||
|
current_dir.access("content.txt", .{}) catch {
|
||||||
|
// content.txt not found, need to walk up
|
||||||
|
var temp_dir = current_dir;
|
||||||
|
|
||||||
|
while (true) {
|
||||||
|
// Try to go up one directory
|
||||||
|
const parent_dir = temp_dir.openDir("..", .{}) catch return error.RootNotFound;
|
||||||
|
temp_dir = parent_dir;
|
||||||
|
|
||||||
|
// Check if content.txt exists in parent directory
|
||||||
|
temp_dir.access("content.txt", .{}) catch {
|
||||||
|
continue;
|
||||||
|
};
|
||||||
|
|
||||||
|
// Found content.txt, get the absolute path
|
||||||
|
return try temp_dir.realpathAlloc(allocator, ".");
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
||||||
|
// content.txt found in current directory
|
||||||
|
return try current_dir.realpathAlloc(allocator, ".");
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn start_CompileShaders(context: ?*anyopaque, callback: ?*const fn (?*anyopaque) void) !void {
|
||||||
|
const self = core.EngineObject(SystemRunner).get();
|
||||||
|
|
||||||
|
const root_dir = findRootDir(self.allocator) catch {
|
||||||
|
core.engine_log("Could not find BacklogEngine root directory (content.txt not found)", .{});
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
|
||||||
|
defer self.allocator.free(root_dir);
|
||||||
|
core.engine_log("Found root directory: {s}", .{root_dir});
|
||||||
|
|
||||||
|
const compile_shaders_dir = try std.fs.path.join(self.allocator, &.{ root_dir, "tools", "compileShaders" });
|
||||||
|
defer self.allocator.free(compile_shaders_dir);
|
||||||
|
|
||||||
|
var compile_shaders_name = core.MakeName(compile_shaders_dir);
|
||||||
|
|
||||||
|
core.engine_log("CompileShaders directory: {s}", .{compile_shaders_dir});
|
||||||
|
|
||||||
|
const exe_path = try std.fs.path.join(self.allocator, &.{ compile_shaders_dir, "zig-out", "bin", "compileShaders.exe" });
|
||||||
|
defer self.allocator.free(exe_path);
|
||||||
|
core.engine_log("Looking for executable at: {s}", .{exe_path});
|
||||||
|
|
||||||
|
// Check if compileShaders.exe exists
|
||||||
|
if (std.fs.cwd().access(exe_path, .{})) |_| {
|
||||||
|
// File exists, run it directly
|
||||||
|
core.engine_log("CompileShaders executable found, running directly", .{});
|
||||||
|
try self.commandQueue.pushLocked(.{ .subprocess = .{
|
||||||
|
.onComplete = callback,
|
||||||
|
.context = context,
|
||||||
|
.task = try SubprocessTask.runCommand(
|
||||||
|
self.allocator,
|
||||||
|
&.{"zig-out/bin/compileShaders.exe"},
|
||||||
|
compile_shaders_name.utf8(),
|
||||||
|
),
|
||||||
|
} });
|
||||||
|
} else |_| {
|
||||||
|
// File doesn't exist, build it first
|
||||||
|
core.engine_log("CompileShaders executable not found, building first", .{});
|
||||||
|
try self.commandQueue.pushLocked(.{
|
||||||
|
.subprocess = .{ .task = try SubprocessTask.runCommand(
|
||||||
|
self.allocator,
|
||||||
|
&.{ "zig", "build", "install" },
|
||||||
|
compile_shaders_name.utf8(),
|
||||||
|
) },
|
||||||
|
});
|
||||||
|
|
||||||
|
// Then run it
|
||||||
|
core.engine_log("Queuing compileShaders execution after build", .{});
|
||||||
|
try self.commandQueue.pushLocked(.{
|
||||||
|
.subprocess = .{
|
||||||
|
.context = context,
|
||||||
|
.onComplete = callback,
|
||||||
|
.task = try SubprocessTask.runCommand(
|
||||||
|
self.allocator,
|
||||||
|
&.{"zig-out/bin/compileShaders.exe"},
|
||||||
|
compile_shaders_name.utf8(),
|
||||||
|
),
|
||||||
|
},
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
const Task = union(enum(u8)) {
|
||||||
|
subprocess: struct {
|
||||||
|
task: *SubprocessTask,
|
||||||
|
onComplete: ?*const fn (?*anyopaque) void = null,
|
||||||
|
context: ?*anyopaque = null,
|
||||||
|
},
|
||||||
|
};
|
||||||
|
|
||||||
|
pub const SystemRunner = struct {
|
||||||
|
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "sys.SystemRunner");
|
||||||
|
|
||||||
|
allocator: std.mem.Allocator,
|
||||||
|
|
||||||
|
commandQueue: core.RingQueue(Task),
|
||||||
|
activeCommand: ?Task = null,
|
||||||
|
|
||||||
|
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||||
|
const self = try allocator.create(@This());
|
||||||
|
|
||||||
|
self.* = .{
|
||||||
|
.allocator = allocator,
|
||||||
|
.commandQueue = try core.RingQueue(Task).init(self.allocator, 256),
|
||||||
|
};
|
||||||
|
|
||||||
|
return self;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn tick(self: *@This(), dt: f64) void {
|
||||||
|
_ = dt;
|
||||||
|
if (self.activeCommand == null) {
|
||||||
|
if (self.commandQueue.popFromLocked()) |task| {
|
||||||
|
switch (task) {
|
||||||
|
.subprocess => |t| {
|
||||||
|
self.activeCommand = task;
|
||||||
|
// core.engine_log("starting task {any}", .{t.args});
|
||||||
|
t.task.run() catch {
|
||||||
|
self.activeCommand = null;
|
||||||
|
return;
|
||||||
|
};
|
||||||
|
},
|
||||||
|
//.func => |f| {
|
||||||
|
//f(self);
|
||||||
|
// },
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (self.activeCommand) |active| {
|
||||||
|
if (active.subprocess.task.checkComplete()) {
|
||||||
|
if (active.subprocess.onComplete) |onComplete| {
|
||||||
|
onComplete(active.subprocess.context);
|
||||||
|
}
|
||||||
|
|
||||||
|
active.subprocess.task.destroy();
|
||||||
|
core.engine_logs("task complete");
|
||||||
|
self.activeCommand = null;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn destroy(self: *@This()) void {
|
||||||
|
self.commandQueue.deinit();
|
||||||
|
self.allocator.destroy(self);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
|
|
||||||
|
|
@ -25,6 +25,8 @@ fontTextures: std.AutoHashMapUnmanaged(u32, *rend.Texture) = .{},
|
||||||
|
|
||||||
textRenderers: std.AutoHashMapUnmanaged(*papyrus.Context, *TextRenderer) = .{},
|
textRenderers: std.AutoHashMapUnmanaged(*papyrus.Context, *TextRenderer) = .{},
|
||||||
|
|
||||||
|
reloadingShaders: bool = false,
|
||||||
|
|
||||||
const DrawCommand = union(enum(u8)) {
|
const DrawCommand = union(enum(u8)) {
|
||||||
rect: struct {
|
rect: struct {
|
||||||
ssboIndex: u32,
|
ssboIndex: u32,
|
||||||
|
|
@ -126,6 +128,12 @@ pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
pub fn tick(self: *@This(), dt: f64) void {
|
||||||
|
self.screenContext.tick(dt) catch {
|
||||||
|
core.engine_errs("unable to tick papyrus");
|
||||||
|
};
|
||||||
|
}
|
||||||
|
|
||||||
pub fn setup(self: *@This()) !void {
|
pub fn setup(self: *@This()) !void {
|
||||||
core.graphics_log("imgui startup", .{});
|
core.graphics_log("imgui startup", .{});
|
||||||
|
|
||||||
|
|
@ -269,9 +277,15 @@ pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void {
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn onShaderReload(p: *anyopaque) void {
|
pub fn onShaderReload(p: *anyopaque) void {
|
||||||
|
const self: *@This() = @ptrCast(@alignCast(p));
|
||||||
|
self.reloadingShaders = true;
|
||||||
|
}
|
||||||
|
|
||||||
|
pub fn onShaderReloadFinished(p: *anyopaque) void {
|
||||||
const self: *@This() = @ptrCast(@alignCast(p));
|
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.
|
self.createRectPipeline() catch return; // you think i give a remote fuck about leaks? this is a debug function son.
|
||||||
self.createTextPipeline() catch return;
|
self.createTextPipeline() catch return;
|
||||||
|
self.reloadingShaders = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn getTextRenderer(self: *@This(), ctx: *papyrus.Context) ?*TextRenderer {
|
pub fn getTextRenderer(self: *@This(), ctx: *papyrus.Context) ?*TextRenderer {
|
||||||
|
|
@ -294,7 +308,17 @@ pub fn getFontSampler(self: *@This(), fontHandle: u32) ?gpu.GPUTextureSamplerBin
|
||||||
}
|
}
|
||||||
|
|
||||||
pub fn drawToTarget(self: *@This(), cmd: *gpu.GPUCommandBuffer, ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void {
|
pub fn drawToTarget(self: *@This(), cmd: *gpu.GPUCommandBuffer, ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void {
|
||||||
|
const stashedDrawDebug = ctx.drawDebug;
|
||||||
|
|
||||||
|
if (self.reloadingShaders) {
|
||||||
|
ctx.pushDebugText("recompiling shaders...", .{}) catch {};
|
||||||
|
ctx.pushDebugText("...", .{}) catch {};
|
||||||
|
}
|
||||||
|
|
||||||
|
ctx.drawDebug = stashedDrawDebug or self.reloadingShaders;
|
||||||
|
|
||||||
ctx.makeDrawList(&self.drawList, &self.stringArena) catch return;
|
ctx.makeDrawList(&self.drawList, &self.stringArena) catch return;
|
||||||
|
ctx.drawDebug = stashedDrawDebug;
|
||||||
|
|
||||||
const textRenderer = self.getTextRenderer(ctx);
|
const textRenderer = self.getTextRenderer(ctx);
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -96,6 +96,7 @@ pub const TextRenderer = struct {
|
||||||
textInstances: std.ArrayListUnmanaged(*TextMeshBuffer) = .{},
|
textInstances: std.ArrayListUnmanaged(*TextMeshBuffer) = .{},
|
||||||
deadList: std.ArrayListUnmanaged(*TextMeshBuffer) = .{},
|
deadList: std.ArrayListUnmanaged(*TextMeshBuffer) = .{},
|
||||||
assignedBuffers: std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = .{},
|
assignedBuffers: std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = .{},
|
||||||
|
linearBuffers: std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = .{}, // set of mesh buffers for linearlly allocated text
|
||||||
allocator: std.mem.Allocator,
|
allocator: std.mem.Allocator,
|
||||||
lastUpdateTime: f64 = 0,
|
lastUpdateTime: f64 = 0,
|
||||||
|
|
||||||
|
|
@ -298,8 +299,10 @@ pub const TextRenderer = struct {
|
||||||
pub fn getOrAllocMeshBuffer(self: *@This(), node: papyrus.NodeHandle, text: papyrus.DrawCommand.PrimitiveText) !*TextMeshBuffer {
|
pub fn getOrAllocMeshBuffer(self: *@This(), node: papyrus.NodeHandle, text: papyrus.DrawCommand.PrimitiveText) !*TextMeshBuffer {
|
||||||
const textLen = text.text.getRead().len;
|
const textLen = text.text.getRead().len;
|
||||||
|
|
||||||
|
const assignedBuffers: *std.AutoHashMapUnmanaged(papyrus.NodeHandle, *TextMeshBuffer) = if (text.flags.debugText) &self.linearBuffers else &self.assignedBuffers;
|
||||||
|
|
||||||
// 1. get the assigned buffer;
|
// 1. get the assigned buffer;
|
||||||
if (self.assignedBuffers.get(node)) |buffer| {
|
if (assignedBuffers.get(node)) |buffer| {
|
||||||
if (textLen <= buffer.capacity) {
|
if (textLen <= buffer.capacity) {
|
||||||
return buffer;
|
return buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -307,7 +310,7 @@ pub const TextRenderer = struct {
|
||||||
core.engine_log("recycling text buffer {any}", .{node});
|
core.engine_log("recycling text buffer {any}", .{node});
|
||||||
// if the buffer is too small for the text, dont use that one and add it to the dead list.
|
// if the buffer is too small for the text, dont use that one and add it to the dead list.
|
||||||
try self.deadList.append(self.allocator, buffer);
|
try self.deadList.append(self.allocator, buffer);
|
||||||
_ = self.assignedBuffers.remove(node);
|
_ = assignedBuffers.remove(node);
|
||||||
}
|
}
|
||||||
|
|
||||||
// 2. if no text renderer is available, search through the deadList until you find a TextMeshBuffer
|
// 2. if no text renderer is available, search through the deadList until you find a TextMeshBuffer
|
||||||
|
|
@ -318,7 +321,7 @@ pub const TextRenderer = struct {
|
||||||
|
|
||||||
for (self.deadList.items, 0..) |buffer, i| {
|
for (self.deadList.items, 0..) |buffer, i| {
|
||||||
if (textLen <= buffer.capacity) {
|
if (textLen <= buffer.capacity) {
|
||||||
try self.assignedBuffers.put(self.allocator, node, buffer);
|
try assignedBuffers.put(self.allocator, node, buffer);
|
||||||
foundIndex = i;
|
foundIndex = i;
|
||||||
foundBuffer = buffer;
|
foundBuffer = buffer;
|
||||||
}
|
}
|
||||||
|
|
@ -344,7 +347,7 @@ pub const TextRenderer = struct {
|
||||||
|
|
||||||
core.engine_log("creating text buffer {any} with length {d} for textLen = {d}", .{ node, newBufferLength, textLen });
|
core.engine_log("creating text buffer {any} with length {d} for textLen = {d}", .{ node, newBufferLength, textLen });
|
||||||
const newBuffer = try TextMeshBuffer.create(self.allocator, newBufferLength);
|
const newBuffer = try TextMeshBuffer.create(self.allocator, newBufferLength);
|
||||||
try self.assignedBuffers.put(self.allocator, node, newBuffer);
|
try assignedBuffers.put(self.allocator, node, newBuffer);
|
||||||
try self.textInstances.append(self.allocator, newBuffer);
|
try self.textInstances.append(self.allocator, newBuffer);
|
||||||
return newBuffer;
|
return newBuffer;
|
||||||
}
|
}
|
||||||
|
|
@ -369,6 +372,7 @@ pub const TextRenderer = struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
self.geo.destroy();
|
self.geo.destroy();
|
||||||
|
self.linearBuffers.deinit(self.allocator);
|
||||||
self.assignedBuffers.deinit(self.allocator);
|
self.assignedBuffers.deinit(self.allocator);
|
||||||
self.textInstances.deinit(self.allocator);
|
self.textInstances.deinit(self.allocator);
|
||||||
self.allocator.destroy(self);
|
self.allocator.destroy(self);
|
||||||
|
|
|
||||||
|
|
@ -139,8 +139,6 @@ pub const TBMap = struct {
|
||||||
}
|
}
|
||||||
self.colliderSpecs.deinit(self.allocator);
|
self.colliderSpecs.deinit(self.allocator);
|
||||||
|
|
||||||
physics.context().system.update(0.001, .{}) catch {};
|
|
||||||
|
|
||||||
self.shapes.deinit(self.allocator);
|
self.shapes.deinit(self.allocator);
|
||||||
self.root.destroy();
|
self.root.destroy();
|
||||||
|
|
||||||
|
|
|
||||||
|
|
@ -21,6 +21,7 @@ pub fn build(b: *std.Build) void {
|
||||||
sampleGame.setModuleEnabled("audio", true);
|
sampleGame.setModuleEnabled("audio", true);
|
||||||
sampleGame.setModuleEnabled("physics", true);
|
sampleGame.setModuleEnabled("physics", true);
|
||||||
sampleGame.setModuleEnabled("ui", true);
|
sampleGame.setModuleEnabled("ui", true);
|
||||||
|
sampleGame.setModuleEnabled("sys", true);
|
||||||
sampleGame.addExtraModule("gameExtras");
|
sampleGame.addExtraModule("gameExtras");
|
||||||
sampleGame.addExtraModule("videoplayer");
|
sampleGame.addExtraModule("videoplayer");
|
||||||
sampleGame.addExtraModule("doomplayer");
|
sampleGame.addExtraModule("doomplayer");
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -159,13 +159,13 @@ fragment main0_out main0(main0_in in [[stage_in]], constant type_Uniforms& Unifo
|
||||||
float4 _289;
|
float4 _289;
|
||||||
if (_272.x > 1.0)
|
if (_272.x > 1.0)
|
||||||
{
|
{
|
||||||
float4 _288 = float4(0.0, 0.0, 0.0, 1.0);
|
float4 _288 = float4(0.0);
|
||||||
_288.x = _272.x;
|
_288.x = _272.x;
|
||||||
_289 = _288;
|
_289 = _288;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
{
|
{
|
||||||
_289 = float4(0.0, 0.0, 0.0, 1.0);
|
_289 = float4(0.0);
|
||||||
}
|
}
|
||||||
float4 _294;
|
float4 _294;
|
||||||
if (_272.y > 1.0)
|
if (_272.y > 1.0)
|
||||||
|
|
|
||||||
Binary file not shown.
|
|
@ -3,6 +3,7 @@ pub export fn startup(p_allocator: *anyopaque, p_a: ?*anyopaque) bool {
|
||||||
_ = allocator;
|
_ = allocator;
|
||||||
imgui.setupFromModule();
|
imgui.setupFromModule();
|
||||||
platform.setupFromModule();
|
platform.setupFromModule();
|
||||||
|
sys.setupFromModule();
|
||||||
rend.setupFromModule();
|
rend.setupFromModule();
|
||||||
backlog.physics.setupFromModule();
|
backlog.physics.setupFromModule();
|
||||||
// TODO backlog.setupFromModule
|
// TODO backlog.setupFromModule
|
||||||
|
|
@ -70,7 +71,6 @@ pub const ExternGameObject = struct {
|
||||||
core.engine_log("map loaded", .{});
|
core.engine_log("map loaded", .{});
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
pub fn create(allocator: std.mem.Allocator) !*@This() {
|
||||||
const self = try Slack.create(allocator);
|
const self = try Slack.create(allocator);
|
||||||
self.* = .{
|
self.* = .{
|
||||||
|
|
@ -254,6 +254,7 @@ const imgui = backlog.imgui;
|
||||||
const physics = backlog.physics;
|
const physics = backlog.physics;
|
||||||
const rend = backlog.rend;
|
const rend = backlog.rend;
|
||||||
const ig = imgui.api;
|
const ig = imgui.api;
|
||||||
|
const sys = backlog.sys;
|
||||||
const ui = backlog.ui;
|
const ui = backlog.ui;
|
||||||
const platform = backlog.platform;
|
const platform = backlog.platform;
|
||||||
const extras = @import("gameExtras");
|
const extras = @import("gameExtras");
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue