Changed some architectural stuff | Some cleanup | Random stuff

This commit is contained in:
abux 2026-07-30 12:37:17 +02:00
parent 0eb9a44828
commit b8733f6782
11 changed files with 292 additions and 176 deletions

View file

@ -43,13 +43,13 @@ struct ModelUniform {
// UNIFORMS // UNIFORMS
// //
// @group(0) @binding(0)
// var<uniform> camera: CameraUniform;
// @group(1) @binding(0)
// var<uniform> model: ModelUniform;
@group(0) @binding(0) @group(0) @binding(0)
var<uniform> camera: CameraUniform;
@group(1) @binding(0)
var<uniform> model: ModelUniform;
@group(2) @binding(0)
var<uniform> material: Material; var<uniform> material: Material;
// //
@ -76,6 +76,8 @@ fn vs_main(in: VertexInput) -> VertexOutput {
@fragment @fragment
fn fs_main(out: VertexOutput) -> @location(0) vec4f { fn fs_main(out: VertexOutput) -> @location(0) vec4f {
return vec4f(out.uv, 0.3, 1.0); var final_color: vec4f = material.albedo;
// return vec4f(material.albedo); final_color.x += out.uv.x * 0.2;
final_color.y += out.uv.y * 0.2;
return vec4f(final_color);
} }

View file

@ -6,7 +6,7 @@ const gtl = @import("gtl");
const wgpu = @import("wgpu"); const wgpu = @import("wgpu");
const Self = @This(); const Self = @This();
const Material = @import("../../common/component/material.zig"); const Material = @import("../../renderer/template/material.zig");
const ShaderCache = @import("shader_cache.zig"); const ShaderCache = @import("shader_cache.zig");
const ShaderID = ShaderCache.ShaderID; const ShaderID = ShaderCache.ShaderID;
const Vertex = @import("mesh_cache.zig").Vertex; const Vertex = @import("mesh_cache.zig").Vertex;
@ -16,6 +16,8 @@ const Vertex = @import("mesh_cache.zig").Vertex;
pub const GPUPipeline = struct { pub const GPUPipeline = struct {
raw: *wgpu.WGPURenderPipelineImpl, raw: *wgpu.WGPURenderPipelineImpl,
layout: *wgpu.WGPUPipelineLayoutImpl, layout: *wgpu.WGPUPipelineLayoutImpl,
bind_group_layouts: [1]*wgpu.WGPUBindGroupLayoutImpl,
// bind_group_layouts: []const *wgpu.WGPUBindGroupLayoutImpl,
}; };
/// ---------------------------------------------------- /// ----------------------------------------------------
@ -23,6 +25,7 @@ pub const GPUPipeline = struct {
pub const GPUMaterial = struct { pub const GPUMaterial = struct {
buffer: *wgpu.WGPUBufferImpl, buffer: *wgpu.WGPUBufferImpl,
bind_group: *wgpu.WGPUBindGroupImpl, bind_group: *wgpu.WGPUBindGroupImpl,
dirty: bool = true,
}; };
// //
@ -61,7 +64,7 @@ pub fn init(
pub fn deinit(self: *Self) void { pub fn deinit(self: *Self) void {
// --- FREE PIPELINES --- // --- FREE PIPELINES ---
for (self.pipelines.items()) |entry| { for (self.pipelines.items()) |entry| {
// wgpu.wgpuPipelineLayoutRelease(entry.value.layout); wgpu.wgpuPipelineLayoutRelease(entry.value.layout);
wgpu.wgpuRenderPipelineRelease(entry.value.raw); wgpu.wgpuRenderPipelineRelease(entry.value.raw);
} }
@ -81,17 +84,25 @@ pub fn deinit(self: *Self) void {
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn getOrCreateMaterial( pub fn getOrCreateMaterial(
self: *Self, self: *Self,
material: Material, material_handle: gtl.Handle(Material),
) !*GPUMaterial { ) !*GPUMaterial {
return try self.materials.getOrPut( return try self.materials_gpu.getOrPut(
material.unique.shader, material_handle,
blk: { blk: {
// --- # ---
if (self.materials_gpu.getByKey(material_handle)) |v| return v;
const material = self.materials.get(material_handle) orelse return error.MaterialNotFound;
// --- ENSURE PIPELINE ---
const pipeline = try self.getOrCreatePipeline(material);
// --- UNIFORM --- // --- UNIFORM ---
const uniform = wgpu.wgpuDeviceCreateBuffer(self.device, &wgpu.WGPUBufferDescriptor{ const uniform = wgpu.wgpuDeviceCreateBuffer(self.device, &wgpu.WGPUBufferDescriptor{
.usage = wgpu.WGPUBufferUsage_CopyDst | wgpu.WGPUBufferUsage_Uniform, .usage = wgpu.WGPUBufferUsage_CopyDst | wgpu.WGPUBufferUsage_Uniform,
.size = @sizeOf(Material.Style), .size = @sizeOf(Material.Style),
}) orelse return error.Buffer; }) orelse return error.Buffer;
// --- WRITE TO UNIFORM ---
wgpu.wgpuQueueWriteBuffer( wgpu.wgpuQueueWriteBuffer(
self.queue, self.queue,
uniform, uniform,
@ -100,10 +111,25 @@ pub fn getOrCreateMaterial(
@sizeOf(Material.Style), @sizeOf(Material.Style),
); );
// --- BIND GROUP ---
const bind_group = wgpu.wgpuDeviceCreateBindGroup(self.device, &wgpu.WGPUBindGroupDescriptor{
.layout = pipeline.bind_group_layouts[0],
.entryCount = 1,
.entries = &[_]wgpu.WGPUBindGroupEntry{
.{
.binding = 0,
.buffer = uniform,
.offset = 0,
.size = @sizeOf(Material.Style),
},
},
}) orelse return error.BindGroup;
// --- RESULT --- // --- RESULT ---
break :blk .{ break :blk .{
.bind_group = undefined,
.buffer = uniform, .buffer = uniform,
.bind_group = bind_group,
.dirty = false,
}; };
}, },
); );
@ -111,25 +137,52 @@ pub fn getOrCreateMaterial(
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn getOrCreate( pub fn getOrCreatePipeline(
self: *Self, self: *Self,
key: Material, material: *const Material,
) !*GPUPipeline { ) !*GPUPipeline {
return try self.pipelines.getOrPut(key.unique, blk: { return try self.pipelines.getOrPut(material.unique, blk: {
// const layout = wgpu.wgpuDeviceCreatePipelineLayout( // --- # ---
// self.device, if (self.pipelines.getByKey(material.unique)) |v| return v;
// &wgpu.WGPUPipelineLayoutDescriptor{
// .bindGroupLayoutCount = 1, // --- MATERIAL LAYOUT ---
// .bindGroupLayouts = &wgpu.WGPUBindGroupLayoutDescriptor{ const material_layout = wgpu.wgpuDeviceCreateBindGroupLayout(self.device, &wgpu.WGPUBindGroupLayoutDescriptor{
// .entryCount = 1, .entryCount = 1,
// }, .entries = &[_]wgpu.WGPUBindGroupLayoutEntry{
// }, .{
// ) orelse return error.Layout; .binding = 0,
.visibility = wgpu.WGPUShaderStage_Vertex | wgpu.WGPUShaderStage_Fragment,
.buffer = .{
.type = wgpu.WGPUBufferBindingType_Uniform,
.minBindingSize = @sizeOf(Material.Style),
.hasDynamicOffset = 0,
},
},
},
}) orelse return error.BindGroupLayout;
// --- PIPELINE LAYOUT ---
const pipeline_layout = wgpu.wgpuDeviceCreatePipelineLayout(
self.device,
&wgpu.WGPUPipelineLayoutDescriptor{
.bindGroupLayoutCount = 1,
.bindGroupLayouts = &material_layout,
},
) orelse return error.Layout;
// --- CREATE PIPELINE ---
const pipeline = try self.createPipeline(
material.unique,
pipeline_layout,
);
// --- RESULT --- // --- RESULT ---
break :blk .{ break :blk .{
.raw = try self.createPipeline(key.unique, undefined), .raw = pipeline,
.layout = undefined, .layout = pipeline_layout,
.bind_group_layouts = .{
material_layout,
},
}; };
}); });
} }
@ -141,8 +194,6 @@ fn createPipeline(
key: Material.Unique, key: Material.Unique,
layout: *wgpu.WGPUPipelineLayoutImpl, layout: *wgpu.WGPUPipelineLayoutImpl,
) !*wgpu.WGPURenderPipelineImpl { ) !*wgpu.WGPURenderPipelineImpl {
_ = layout;
// --- ENSURE SHADER MODULE --- // --- ENSURE SHADER MODULE ---
const shader_module = try self.shader_cache.getOrCreate( const shader_module = try self.shader_cache.getOrCreate(
key.shader, key.shader,
@ -151,6 +202,7 @@ fn createPipeline(
// --- RESULT --- // --- RESULT ---
return wgpu.wgpuDeviceCreateRenderPipeline(self.device, &wgpu.WGPURenderPipelineDescriptor{ return wgpu.wgpuDeviceCreateRenderPipeline(self.device, &wgpu.WGPURenderPipelineDescriptor{
.label = .{ .data = @tagName(key.shader), .length = wgpu.WGPU_STRLEN }, .label = .{ .data = @tagName(key.shader), .length = wgpu.WGPU_STRLEN },
.layout = layout,
.vertex = .{ .vertex = .{
.module = shader_module.raw, .module = shader_module.raw,
.entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN }, .entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN },

View file

@ -38,53 +38,55 @@ pub fn init(app: *App) !void {
res.device.queue, res.device.queue,
app.alloc, app.alloc,
)); ));
_ = meshes; _ = meshes;
_ = pipelines;
// TODO: Remove or place it somewhere else, idk // TODO: Remove or place it somewhere else, idk
// --- TEST --- // --- TEST ---
_ = try pipelines.getOrCreate(.{}); // _ = try pipelines.getOrCreatePipeline(.{});
_ = try pipelines.getOrCreate(.{}); // _ = try pipelines.getOrCreatePipeline(.{});
_ = try pipelines.getOrCreate(.{ .unique = .{ .shader = .unlit } }); // _ = try pipelines.getOrCreatePipeline(.{ .unique = .{ .shader = .unlit } });
_ = try pipelines.getOrCreate(.{ .unique = .{ .shader = .unlit } }); // _ = try pipelines.getOrCreatePipeline(.{ .unique = .{ .shader = .unlit } });
{ // DEBUG // { // DEBUG
std.debug.print("{s}┏━{s} PIPELINES\n", .{ gtl.ansi.blue, gtl.ansi.reset }); // std.debug.print("{s}┏━{s} PIPELINES\n", .{ gtl.ansi.blue, gtl.ansi.reset });
for (pipelines.pipelines.items(), 0..) |entry, i| { // for (pipelines.pipelines.items(), 0..) |entry, i| {
// std.debug.print("\x1b[33m\x1b[0m {s:<12} {s}\n", .{ plugin.name, plugin.description }); // // std.debug.print("\x1b[33m\x1b[0m {s:<12} {s}\n", .{ plugin.name, plugin.description });
std.debug.print( // std.debug.print(
\\{s}┃ ┏━{s} {} // \\{s}┃ ┏━{s} {}
\\{s}┃ ┃ {s}Shader: {s} // \\{s}┃ ┃ {s}Shader: {s}
\\{s}┃ ┃ {s}Cull Mode: {s} // \\{s}┃ ┃ {s}Cull Mode: {s}
\\{s}┃ ┃ {s}Blend Mode: {s} // \\{s}┃ ┃ {s}Blend Mode: {s}
\\{s}┃ ┃ {s}Front Face: {s} // \\{s}┃ ┃ {s}Front Face: {s}
\\{s}┃ ┃ {s}Topology: {s} // \\{s}┃ ┃ {s}Topology: {s}
\\ // \\
, .{ // , .{
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
i, // i,
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
@tagName(entry.key.shader), // @tagName(entry.key.shader),
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
@tagName(entry.key.cull_mode), // @tagName(entry.key.cull_mode),
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
@tagName(entry.key.blend_mode), // @tagName(entry.key.blend_mode),
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
@tagName(entry.key.front_face), // @tagName(entry.key.front_face),
gtl.ansi.blue, // gtl.ansi.blue,
gtl.ansi.reset, // gtl.ansi.reset,
@tagName(entry.key.topology), // @tagName(entry.key.topology),
}); // });
std.debug.print("{s}┃ ┗━{s}\n", .{ gtl.ansi.blue, gtl.ansi.reset }); // std.debug.print("{s}┃ ┗━{s}\n", .{ gtl.ansi.blue, gtl.ansi.reset });
} // }
std.debug.print("{s}┗━{s}\n", .{ gtl.ansi.blue, gtl.ansi.reset }); // std.debug.print("{s}┗━{s}\n", .{ gtl.ansi.blue, gtl.ansi.reset });
} // }
} }
/// ---------------------------------------------------- /// ----------------------------------------------------

View file

@ -1,54 +1,5 @@
//! ----------------------------------------------------
//! ----------------------------------------------------
const gtl = @import("gtl"); const gtl = @import("gtl");
const ShaderID = @import("../../cache/resource/shader_cache.zig").ShaderID; const Material = @import("../../renderer/template/material.zig");
const Handle = gtl.Handle; const Handle = gtl.Handle;
const Self = @This();
/// ---------------------------------------------------- value: Handle(Material),
/// ----------------------------------------------------
pub const Style = struct {
albedo: @Vector(4, f32) = .{ 1, 1, 1, 1 },
metallic: f32 = 0.0,
roughness: f32 = 0.5,
_pad0: [2]f32 = .{ 0, 0 },
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Unique = struct {
shader: ShaderID = .pbr,
front_face: enum {
cw,
ccw,
} = .ccw,
cull_mode: enum {
back,
front,
none,
} = .back,
topology: enum {
triangle_list,
point_list,
line_list,
} = .triangle_list,
blend_mode: enum {
none,
alpha,
additive,
multiply,
} = .none,
};
//
// FIELDS
//
style: Style = .{},
unique: Unique = .{},
value: ?Handle(Self) = null,

View file

@ -0,0 +1,54 @@
//! ----------------------------------------------------
//! ----------------------------------------------------
const gtl = @import("gtl");
const ShaderID = @import("../../cache/resource/shader_cache.zig").ShaderID;
const Handle = gtl.Handle;
const Self = @This();
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Style = struct {
albedo: @Vector(4, f32) = .{ 1, 1, 1, 1 },
metallic: f32 = 0.0,
roughness: f32 = 0.5,
_pad0: [2]f32 = .{ 0, 0 },
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Unique = struct {
shader: ShaderID = .pbr,
front_face: enum {
cw,
ccw,
} = .ccw,
cull_mode: enum {
back,
front,
none,
} = .back,
topology: enum {
triangle_list,
point_list,
line_list,
} = .triangle_list,
blend_mode: enum {
none,
alpha,
additive,
multiply,
} = .none,
};
//
// FIELDS
//
style: Style = .{},
unique: Unique = .{},
value: ?Handle(Self) = null,

View file

@ -29,7 +29,7 @@ fn build(
_: *App.plugin.Plugin, _: *App.plugin.Plugin,
app: *App, app: *App,
) !void { ) !void {
try app.schedules.add(App.stage.init, start); try app.schedules.addAfter(App.stage.init, App.stage.init, start);
} }
/// ---------------------------------------------------- /// ----------------------------------------------------
@ -44,9 +44,26 @@ fn start(app: *App) !void {
try app.world.spawn(.{ try app.world.spawn(.{
Mesh{ .value = .square }, Mesh{ .value = .square },
Material{ Material{
.style = .{}, .value = try pipeline_cache.materials.put(.{
.style = .{
.albedo = .{ 0.8, 0.2, 0.2, 1 },
},
.unique = .{}, .unique = .{},
.value = try pipeline_cache.materials.put(.{}), }),
},
Transform3D{},
});
// --- # ---
try app.world.spawn(.{
Mesh{ .value = .triangle },
Material{
.value = try pipeline_cache.materials.put(.{
.style = .{
.albedo = .{ 0.2, 0.2, 0.8, 1 },
},
.unique = .{},
}),
}, },
Transform3D{}, Transform3D{},
}); });

View file

@ -16,12 +16,12 @@ const Camera = struct {};
pub const DrawCMD = union(enum) { pub const DrawCMD = union(enum) {
draw: struct { draw: struct {
mesh: Mesh, mesh: Mesh,
material: Material, material: Handle(Material),
}, },
draw_indexed: struct { draw_indexed: struct {
mesh: Mesh, mesh: Mesh,
material: Material, material: Handle(Material),
}, },
begin_pass: struct { begin_pass: struct {
@ -79,33 +79,3 @@ pub fn draw(
cmd, cmd,
); );
} }
//
// TESTING
//
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn beginPass(self: *Self) void {
self.draw(.{ .begin_pass = .{
.camera = undefined,
} }) catch unreachable;
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn endPass(self: *Self) void {
self.draw(.end_pass) catch unreachable;
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn drawTriangle(self: *Self) void {
self.draw(.{ .draw = .{ .material = .{}, .mesh = .triangle } }) catch unreachable;
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn drawSquare(self: *Self) void {
self.draw(.{ .draw = .{ .material = .{}, .mesh = .square } }) catch unreachable;
}

View file

@ -1,9 +1,14 @@
//! ---------------------------------------------------- //! ----------------------------------------------------
//! ---------------------------------------------------- //! ----------------------------------------------------
const std = @import("std");
const App = @import("app"); const App = @import("app");
const Renderer = @import("../resource/renderer.zig"); const Renderer = @import("../resource/renderer.zig");
const Mesh = @import("../../common/component/mesh.zig");
const Material = @import("../../common/component/material.zig");
const Transform3D = @import("../../common/component/transform3D.zig");
/// ---------------------------------------------------- /// ----------------------------------------------------
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn begin(app: *App) !void { pub fn begin(app: *App) !void {
@ -15,6 +20,30 @@ pub fn begin(app: *App) !void {
// --- # --- // --- # ---
res.renderer.clear(); res.renderer.clear();
// --- DRAW ---
try res.renderer.draw(.{
.begin_pass = .{
.camera = undefined,
.color = .{ 0.001, 0.001, 0.001, 1.0 },
},
});
defer res.renderer.draw(.end_pass) catch unreachable;
// --- QUERY ---
var query = app.world.query(struct {
mesh: *Mesh,
material: *Material,
transform3D: ?*Transform3D,
}, .{});
while (query.next()) |e| {
try res.renderer.draw(.{
.draw = .{
.material = e.material.value,
.mesh = e.mesh.value,
},
});
}
// { // TEST // { // TEST
// // --- DRAW --- // // --- DRAW ---
// try res.renderer.draw(.{ // try res.renderer.draw(.{

View file

@ -9,22 +9,9 @@ const Renderer = @import("../resource/renderer.zig");
/// ---------------------------------------------------- /// ----------------------------------------------------
pub fn init(app: *App) !void { pub fn init(app: *App) !void {
// --- # --- // --- # ---
const zla = app.resources.getPtr(Zla) orelse return error.ZlaNotSet; try app.resources.set(Renderer.init(
// --- # ---
const renderer = try app.resources.getOrSet(Renderer.init(
app.alloc, app.alloc,
)); ));
// --- REGISTER ---
zla.registerMethods(Renderer, &.{
.{ .name = "beginPass", .func = Renderer.beginPass },
.{ .name = "endPass", .func = Renderer.endPass },
.{ .name = "drawTriangle", .func = Renderer.drawTriangle },
.{ .name = "drawSquare", .func = Renderer.drawSquare },
});
zla.pushUserdata(renderer);
zla.setGlobal("ren");
} }
/// ---------------------------------------------------- /// ----------------------------------------------------

View file

@ -25,7 +25,6 @@ pub fn draw(app: *App) !void {
}); });
{ // TODO: Move this | Gather Materials { // TODO: Move this | Gather Materials
} }
// --- DO NONE ON WINDOW RESIZE --- // --- DO NONE ON WINDOW RESIZE ---
@ -121,15 +120,15 @@ pub fn draw(app: *App) !void {
}, },
.draw => |v| { .draw => |v| {
// --- ENSURE --- // --- ENSURE ---
const pipeline = try res.pipeline_cache.getOrCreate(v.material); const material = res.pipeline_cache.materials.get(v.material) orelse return error.MaterialNotFound;
// const material = try res.pipeline_cache.getOrCreateMaterial(v.material); const gpu_material = try res.pipeline_cache.getOrCreateMaterial(v.material);
const pipeline = try res.pipeline_cache.getOrCreatePipeline(material);
const mesh = try res.mesh_cache.getOrCreate(v.mesh); const mesh = try res.mesh_cache.getOrCreate(v.mesh);
// _ = material;
// --- BIND --- // --- BIND ---
wgpu.wgpuRenderPassEncoderSetPipeline(render_pass, pipeline.raw); wgpu.wgpuRenderPassEncoderSetPipeline(render_pass, pipeline.raw);
wgpu.wgpuRenderPassEncoderSetVertexBuffer(render_pass, 0, mesh.vbuf, 0, wgpu.wgpuBufferGetSize(mesh.vbuf)); wgpu.wgpuRenderPassEncoderSetVertexBuffer(render_pass, 0, mesh.vbuf, 0, wgpu.wgpuBufferGetSize(mesh.vbuf));
wgpu.wgpuRenderPassEncoderSetBindGroup(render_pass, 0, gpu_material.bind_group, 0, null);
// --- DRAW --- // --- DRAW ---
if (mesh.ibuf) |ibuf| { if (mesh.ibuf) |ibuf| {

View file

@ -0,0 +1,53 @@
//! ----------------------------------------------------
//! ----------------------------------------------------
const gtl = @import("gtl");
const ShaderID = @import("../../cache/resource/shader_cache.zig").ShaderID;
const Handle = gtl.Handle;
const Self = @This();
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Style = struct {
albedo: @Vector(4, f32) = .{ 1, 1, 1, 1 },
metallic: f32 = 0.0,
roughness: f32 = 0.5,
_pad0: [2]f32 = .{ 0, 0 },
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Unique = struct {
shader: ShaderID = .pbr,
front_face: enum {
cw,
ccw,
} = .ccw,
cull_mode: enum {
back,
front,
none,
} = .back,
topology: enum {
triangle_list,
point_list,
line_list,
} = .triangle_list,
blend_mode: enum {
none,
alpha,
additive,
multiply,
} = .none,
};
//
// FIELDS
//
style: Style = .{},
unique: Unique = .{},