diff --git a/src/plugins/cache/resource/embeded/shaders/pbr.wgsl b/src/plugins/cache/resource/embeded/shaders/pbr.wgsl index ea3d26c..38a2d2d 100644 --- a/src/plugins/cache/resource/embeded/shaders/pbr.wgsl +++ b/src/plugins/cache/resource/embeded/shaders/pbr.wgsl @@ -43,13 +43,13 @@ struct ModelUniform { // UNIFORMS // +// @group(0) @binding(0) +// var camera: CameraUniform; + +// @group(1) @binding(0) +// var model: ModelUniform; + @group(0) @binding(0) -var camera: CameraUniform; - -@group(1) @binding(0) -var model: ModelUniform; - -@group(2) @binding(0) var material: Material; // @@ -76,6 +76,8 @@ fn vs_main(in: VertexInput) -> VertexOutput { @fragment fn fs_main(out: VertexOutput) -> @location(0) vec4f { - return vec4f(out.uv, 0.3, 1.0); - // return vec4f(material.albedo); + var final_color: vec4f = material.albedo; + final_color.x += out.uv.x * 0.2; + final_color.y += out.uv.y * 0.2; + return vec4f(final_color); } diff --git a/src/plugins/cache/resource/pipeline_cache.zig b/src/plugins/cache/resource/pipeline_cache.zig index bc2714f..db9523a 100644 --- a/src/plugins/cache/resource/pipeline_cache.zig +++ b/src/plugins/cache/resource/pipeline_cache.zig @@ -6,7 +6,7 @@ const gtl = @import("gtl"); const wgpu = @import("wgpu"); const Self = @This(); -const Material = @import("../../common/component/material.zig"); +const Material = @import("../../renderer/template/material.zig"); const ShaderCache = @import("shader_cache.zig"); const ShaderID = ShaderCache.ShaderID; const Vertex = @import("mesh_cache.zig").Vertex; @@ -16,6 +16,8 @@ const Vertex = @import("mesh_cache.zig").Vertex; pub const GPUPipeline = struct { raw: *wgpu.WGPURenderPipelineImpl, 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 { buffer: *wgpu.WGPUBufferImpl, bind_group: *wgpu.WGPUBindGroupImpl, + dirty: bool = true, }; // @@ -61,7 +64,7 @@ pub fn init( pub fn deinit(self: *Self) void { // --- FREE PIPELINES --- for (self.pipelines.items()) |entry| { - // wgpu.wgpuPipelineLayoutRelease(entry.value.layout); + wgpu.wgpuPipelineLayoutRelease(entry.value.layout); wgpu.wgpuRenderPipelineRelease(entry.value.raw); } @@ -81,17 +84,25 @@ pub fn deinit(self: *Self) void { /// ---------------------------------------------------- pub fn getOrCreateMaterial( self: *Self, - material: Material, + material_handle: gtl.Handle(Material), ) !*GPUMaterial { - return try self.materials.getOrPut( - material.unique.shader, + return try self.materials_gpu.getOrPut( + material_handle, 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 --- const uniform = wgpu.wgpuDeviceCreateBuffer(self.device, &wgpu.WGPUBufferDescriptor{ .usage = wgpu.WGPUBufferUsage_CopyDst | wgpu.WGPUBufferUsage_Uniform, .size = @sizeOf(Material.Style), }) orelse return error.Buffer; + // --- WRITE TO UNIFORM --- wgpu.wgpuQueueWriteBuffer( self.queue, uniform, @@ -100,10 +111,25 @@ pub fn getOrCreateMaterial( @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 --- break :blk .{ - .bind_group = undefined, .buffer = uniform, + .bind_group = bind_group, + .dirty = false, }; }, ); @@ -111,25 +137,52 @@ pub fn getOrCreateMaterial( /// ---------------------------------------------------- /// ---------------------------------------------------- -pub fn getOrCreate( +pub fn getOrCreatePipeline( self: *Self, - key: Material, + material: *const Material, ) !*GPUPipeline { - return try self.pipelines.getOrPut(key.unique, blk: { - // const layout = wgpu.wgpuDeviceCreatePipelineLayout( - // self.device, - // &wgpu.WGPUPipelineLayoutDescriptor{ - // .bindGroupLayoutCount = 1, - // .bindGroupLayouts = &wgpu.WGPUBindGroupLayoutDescriptor{ - // .entryCount = 1, - // }, - // }, - // ) orelse return error.Layout; + return try self.pipelines.getOrPut(material.unique, blk: { + // --- # --- + if (self.pipelines.getByKey(material.unique)) |v| return v; + + // --- MATERIAL LAYOUT --- + const material_layout = wgpu.wgpuDeviceCreateBindGroupLayout(self.device, &wgpu.WGPUBindGroupLayoutDescriptor{ + .entryCount = 1, + .entries = &[_]wgpu.WGPUBindGroupLayoutEntry{ + .{ + .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 --- break :blk .{ - .raw = try self.createPipeline(key.unique, undefined), - .layout = undefined, + .raw = pipeline, + .layout = pipeline_layout, + .bind_group_layouts = .{ + material_layout, + }, }; }); } @@ -141,8 +194,6 @@ fn createPipeline( key: Material.Unique, layout: *wgpu.WGPUPipelineLayoutImpl, ) !*wgpu.WGPURenderPipelineImpl { - _ = layout; - // --- ENSURE SHADER MODULE --- const shader_module = try self.shader_cache.getOrCreate( key.shader, @@ -151,6 +202,7 @@ fn createPipeline( // --- RESULT --- return wgpu.wgpuDeviceCreateRenderPipeline(self.device, &wgpu.WGPURenderPipelineDescriptor{ .label = .{ .data = @tagName(key.shader), .length = wgpu.WGPU_STRLEN }, + .layout = layout, .vertex = .{ .module = shader_module.raw, .entryPoint = .{ .data = "vs_main", .length = wgpu.WGPU_STRLEN }, diff --git a/src/plugins/cache/system/lifetime.zig b/src/plugins/cache/system/lifetime.zig index 904b0e8..eb36512 100644 --- a/src/plugins/cache/system/lifetime.zig +++ b/src/plugins/cache/system/lifetime.zig @@ -38,53 +38,55 @@ pub fn init(app: *App) !void { res.device.queue, app.alloc, )); + _ = meshes; + _ = pipelines; // TODO: Remove or place it somewhere else, idk // --- TEST --- - _ = try pipelines.getOrCreate(.{}); - _ = try pipelines.getOrCreate(.{}); + // _ = try pipelines.getOrCreatePipeline(.{}); + // _ = try pipelines.getOrCreatePipeline(.{}); - _ = try pipelines.getOrCreate(.{ .unique = .{ .shader = .unlit } }); - _ = try pipelines.getOrCreate(.{ .unique = .{ .shader = .unlit } }); + // _ = try pipelines.getOrCreatePipeline(.{ .unique = .{ .shader = .unlit } }); + // _ = try pipelines.getOrCreatePipeline(.{ .unique = .{ .shader = .unlit } }); - { // DEBUG - std.debug.print("{s}┏━{s} PIPELINES\n", .{ gtl.ansi.blue, gtl.ansi.reset }); - 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( - \\{s}┃ ┏━{s} {} - \\{s}┃ ┃ {s}Shader: {s} - \\{s}┃ ┃ {s}Cull Mode: {s} - \\{s}┃ ┃ {s}Blend Mode: {s} - \\{s}┃ ┃ {s}Front Face: {s} - \\{s}┃ ┃ {s}Topology: {s} - \\ - , .{ - gtl.ansi.blue, - gtl.ansi.reset, - i, - gtl.ansi.blue, - gtl.ansi.reset, - @tagName(entry.key.shader), - gtl.ansi.blue, - gtl.ansi.reset, - @tagName(entry.key.cull_mode), - gtl.ansi.blue, - gtl.ansi.reset, - @tagName(entry.key.blend_mode), - gtl.ansi.blue, - gtl.ansi.reset, - @tagName(entry.key.front_face), - gtl.ansi.blue, - gtl.ansi.reset, - @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 }); - } + // { // DEBUG + // std.debug.print("{s}┏━{s} PIPELINES\n", .{ gtl.ansi.blue, gtl.ansi.reset }); + // 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( + // \\{s}┃ ┏━{s} {} + // \\{s}┃ ┃ {s}Shader: {s} + // \\{s}┃ ┃ {s}Cull Mode: {s} + // \\{s}┃ ┃ {s}Blend Mode: {s} + // \\{s}┃ ┃ {s}Front Face: {s} + // \\{s}┃ ┃ {s}Topology: {s} + // \\ + // , .{ + // gtl.ansi.blue, + // gtl.ansi.reset, + // i, + // gtl.ansi.blue, + // gtl.ansi.reset, + // @tagName(entry.key.shader), + // gtl.ansi.blue, + // gtl.ansi.reset, + // @tagName(entry.key.cull_mode), + // gtl.ansi.blue, + // gtl.ansi.reset, + // @tagName(entry.key.blend_mode), + // gtl.ansi.blue, + // gtl.ansi.reset, + // @tagName(entry.key.front_face), + // gtl.ansi.blue, + // gtl.ansi.reset, + // @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 }); + // } } /// ---------------------------------------------------- diff --git a/src/plugins/common/component/material.zig b/src/plugins/common/component/material.zig index d64534b..91f8efa 100644 --- a/src/plugins/common/component/material.zig +++ b/src/plugins/common/component/material.zig @@ -1,54 +1,5 @@ -//! ---------------------------------------------------- -//! ---------------------------------------------------- - 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 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, +value: Handle(Material), diff --git a/src/plugins/common/component/material.zig.old b/src/plugins/common/component/material.zig.old new file mode 100644 index 0000000..d64534b --- /dev/null +++ b/src/plugins/common/component/material.zig.old @@ -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, diff --git a/src/plugins/playground/root.zig b/src/plugins/playground/root.zig index e3c629a..84eeede 100644 --- a/src/plugins/playground/root.zig +++ b/src/plugins/playground/root.zig @@ -29,7 +29,7 @@ fn build( _: *App.plugin.Plugin, app: *App, ) !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(.{ Mesh{ .value = .square }, Material{ - .style = .{}, - .unique = .{}, - .value = try pipeline_cache.materials.put(.{}), + .value = try pipeline_cache.materials.put(.{ + .style = .{ + .albedo = .{ 0.8, 0.2, 0.2, 1 }, + }, + .unique = .{}, + }), + }, + 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{}, }); diff --git a/src/plugins/renderer/resource/renderer.zig b/src/plugins/renderer/resource/renderer.zig index f30cea3..f65191a 100644 --- a/src/plugins/renderer/resource/renderer.zig +++ b/src/plugins/renderer/resource/renderer.zig @@ -16,12 +16,12 @@ const Camera = struct {}; pub const DrawCMD = union(enum) { draw: struct { mesh: Mesh, - material: Material, + material: Handle(Material), }, draw_indexed: struct { mesh: Mesh, - material: Material, + material: Handle(Material), }, begin_pass: struct { @@ -79,33 +79,3 @@ pub fn draw( 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; -} diff --git a/src/plugins/renderer/system/frame.zig b/src/plugins/renderer/system/frame.zig index 265c82f..df8c9f7 100644 --- a/src/plugins/renderer/system/frame.zig +++ b/src/plugins/renderer/system/frame.zig @@ -1,9 +1,14 @@ //! ---------------------------------------------------- //! ---------------------------------------------------- +const std = @import("std"); const App = @import("app"); 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 { @@ -15,6 +20,30 @@ pub fn begin(app: *App) !void { // --- # --- 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 // // --- DRAW --- // try res.renderer.draw(.{ diff --git a/src/plugins/renderer/system/lifetime.zig b/src/plugins/renderer/system/lifetime.zig index 2b07b18..0a76dc2 100644 --- a/src/plugins/renderer/system/lifetime.zig +++ b/src/plugins/renderer/system/lifetime.zig @@ -9,22 +9,9 @@ const Renderer = @import("../resource/renderer.zig"); /// ---------------------------------------------------- pub fn init(app: *App) !void { // --- # --- - const zla = app.resources.getPtr(Zla) orelse return error.ZlaNotSet; - - // --- # --- - const renderer = try app.resources.getOrSet(Renderer.init( + try app.resources.set(Renderer.init( 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"); } /// ---------------------------------------------------- diff --git a/src/plugins/renderer/system/present.zig b/src/plugins/renderer/system/present.zig index 150199e..b1291c0 100644 --- a/src/plugins/renderer/system/present.zig +++ b/src/plugins/renderer/system/present.zig @@ -25,7 +25,6 @@ pub fn draw(app: *App) !void { }); { // TODO: Move this | Gather Materials - } // --- DO NONE ON WINDOW RESIZE --- @@ -121,15 +120,15 @@ pub fn draw(app: *App) !void { }, .draw => |v| { // --- ENSURE --- - const pipeline = try res.pipeline_cache.getOrCreate(v.material); - // const material = try res.pipeline_cache.getOrCreateMaterial(v.material); + const material = res.pipeline_cache.materials.get(v.material) orelse return error.MaterialNotFound; + 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); - // _ = material; - // --- BIND --- wgpu.wgpuRenderPassEncoderSetPipeline(render_pass, pipeline.raw); wgpu.wgpuRenderPassEncoderSetVertexBuffer(render_pass, 0, mesh.vbuf, 0, wgpu.wgpuBufferGetSize(mesh.vbuf)); + wgpu.wgpuRenderPassEncoderSetBindGroup(render_pass, 0, gpu_material.bind_group, 0, null); // --- DRAW --- if (mesh.ibuf) |ibuf| { diff --git a/src/plugins/renderer/template/material.zig b/src/plugins/renderer/template/material.zig new file mode 100644 index 0000000..9decce6 --- /dev/null +++ b/src/plugins/renderer/template/material.zig @@ -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 = .{},