From ca08255ec28b847b71b4fc5107bce5b377d53005 Mon Sep 17 00:00:00 2001 From: Stephen Gutekanst Date: Wed, 1 May 2024 20:17:16 -0700 Subject: [PATCH] {gfx,examples}: fix refcounting bugs, improve sysgpu compatability Signed-off-by: Stephen Gutekanst --- examples/core-custom-entrypoint/App.zig | 1 + examples/custom-renderer/App.zig | 3 ++- examples/custom-renderer/Renderer.zig | 17 ++++++++++------- examples/glyphs/App.zig | 5 ++--- examples/glyphs/Glyphs.zig | 4 +--- examples/piano/App.zig | 1 + examples/sprite/App.zig | 2 -- examples/text/App.zig | 1 - src/gfx/Sprite.zig | 1 + src/gfx/SpritePipeline.zig | 8 +++++--- src/gfx/TextPipeline.zig | 20 ++++++++++++++++---- 11 files changed, 39 insertions(+), 24 deletions(-) diff --git a/examples/core-custom-entrypoint/App.zig b/examples/core-custom-entrypoint/App.zig index ee768714..9b28503d 100644 --- a/examples/core-custom-entrypoint/App.zig +++ b/examples/core-custom-entrypoint/App.zig @@ -96,6 +96,7 @@ fn tick(core: *mach.Core.Mod, game: *Mod) !void { .label = label, .color_attachments = &color_attachments, })); + defer render_pass.release(); // Draw render_pass.setPipeline(game.state().pipeline); diff --git a/examples/custom-renderer/App.zig b/examples/custom-renderer/App.zig index de5804c5..bc254e41 100644 --- a/examples/custom-renderer/App.zig +++ b/examples/custom-renderer/App.zig @@ -38,7 +38,8 @@ pub const name = .app; // Note that Mod.state() returns an instance of our module struct. pub const Mod = mach.Mod(@This()); -pub fn deinit(core: *mach.Core.Mod) void { +pub fn deinit(core: *mach.Core.Mod, renderer: *Renderer.Mod) void { + renderer.send(.deinit, .{}); core.send(.deinit, .{}); } diff --git a/examples/custom-renderer/Renderer.zig b/examples/custom-renderer/Renderer.zig index 0a2cba2f..3c159be2 100644 --- a/examples/custom-renderer/Renderer.zig +++ b/examples/custom-renderer/Renderer.zig @@ -14,7 +14,6 @@ const num_bind_groups = 1024 * 32; const uniform_offset = 256; pipeline: *gpu.RenderPipeline, -queue: *gpu.Queue, bind_groups: [num_bind_groups]*gpu.BindGroup, uniform_buffer: *gpu.Buffer, @@ -44,6 +43,7 @@ fn init( ) !void { const device = core.state().device; const shader_module = device.createShaderModuleWGSL("shader.wgsl", @embedFile("shader.wgsl")); + defer shader_module.release(); // Fragment state const blend = gpu.BlendState{}; @@ -65,6 +65,7 @@ fn init( .size = @sizeOf(UniformBufferObject) * uniform_offset * num_bind_groups, .mapped_at_creation = .false, }); + const bind_group_layout_entry = gpu.BindGroupLayout.Entry.buffer(0, .{ .vertex = true }, .uniform, true, 0); const bind_group_layout = device.createBindGroupLayout( &gpu.BindGroupLayout.Descriptor.init(.{ @@ -72,6 +73,8 @@ fn init( .entries = &.{bind_group_layout_entry}, }), ); + defer bind_group_layout.release(); + var bind_groups: [num_bind_groups]*gpu.BindGroup = undefined; for (bind_groups, 0..) |_, i| { bind_groups[i] = device.createBindGroup( @@ -93,7 +96,9 @@ fn init( .label = label, .bind_group_layouts = &bind_group_layouts, })); - const pipeline_descriptor = gpu.RenderPipeline.Descriptor{ + defer pipeline_layout.release(); + + const pipeline = device.createRenderPipeline(&gpu.RenderPipeline.Descriptor{ .label = label, .fragment = &fragment, .layout = pipeline_layout, @@ -101,22 +106,19 @@ fn init( .module = shader_module, .entry_point = "vertex_main", }, - }; + }); renderer.init(.{ - .pipeline = device.createRenderPipeline(&pipeline_descriptor), - .queue = device.getQueue(), + .pipeline = pipeline, .bind_groups = bind_groups, .uniform_buffer = uniform_buffer, }); - shader_module.release(); } fn deinit( renderer: *Mod, ) !void { renderer.state().pipeline.release(); - renderer.state().queue.release(); for (renderer.state().bind_groups) |bind_group| bind_group.release(); renderer.state().uniform_buffer.release(); } @@ -168,6 +170,7 @@ fn renderFrame( .label = label, .color_attachments = &color_attachments, })); + defer render_pass.release(); // Draw for (renderer.state().bind_groups[0..num_entities]) |bind_group| { diff --git a/examples/glyphs/App.zig b/examples/glyphs/App.zig index 5af2a882..d81117e7 100644 --- a/examples/glyphs/App.zig +++ b/examples/glyphs/App.zig @@ -222,8 +222,6 @@ fn tick( .load_op = .clear, .store_op = .store, }}; - // TODO: can we eliminate this assignment - game.state().frame_encoder = core.state().device.createCommandEncoder(&.{ .label = label }); game.state().frame_render_pass = game.state().frame_encoder.beginRenderPass(&gpu.RenderPassDescriptor.init(.{ .label = label, .color_attachments = &color_attachments, @@ -244,9 +242,10 @@ fn endFrame(game: *Mod, core: *mach.Core.Mod) !void { game.state().frame_render_pass.end(); const label = @tagName(name) ++ ".endFrame"; var command = game.state().frame_encoder.finish(&.{ .label = label }); - game.state().frame_encoder.release(); defer command.release(); core.state().queue.submit(&[_]*gpu.CommandBuffer{command}); + game.state().frame_encoder.release(); + game.state().frame_render_pass.release(); // Present the frame core.send(.present_frame, .{}); diff --git a/examples/glyphs/Glyphs.zig b/examples/glyphs/Glyphs.zig index bf9a34db..83140b89 100644 --- a/examples/glyphs/Glyphs.zig +++ b/examples/glyphs/Glyphs.zig @@ -76,8 +76,6 @@ fn init( } fn prepare(core: *mach.Core.Mod, glyphs: *Mod) !void { - const device = core.state().device; - const queue = device.getQueue(); var s = glyphs.state(); // Prepare which glyphs we will render @@ -126,5 +124,5 @@ fn prepare(core: *mach.Core.Mod, glyphs: *Mod) !void { .bytes_per_row = @as(u32, @intCast(img_size.width * 4)), .rows_per_image = @as(u32, @intCast(img_size.height)), }; - queue.writeTexture(&.{ .texture = s.texture }, &data_layout, &img_size, s.texture_atlas.data); + core.state().queue.writeTexture(&.{ .texture = s.texture }, &data_layout, &img_size, s.texture_atlas.data); } diff --git a/examples/piano/App.zig b/examples/piano/App.zig index de9128e7..13570a58 100644 --- a/examples/piano/App.zig +++ b/examples/piano/App.zig @@ -162,6 +162,7 @@ fn tick( .label = label, .color_attachments = &color_attachments, })); + defer render_pass.release(); // Draw nothing diff --git a/examples/sprite/App.zig b/examples/sprite/App.zig index 3f200506..7499531b 100644 --- a/examples/sprite/App.zig +++ b/examples/sprite/App.zig @@ -207,8 +207,6 @@ fn tick( .load_op = .clear, .store_op = .store, }}; - // TODO: can we eliminate this assignment - game.state().frame_encoder = core.state().device.createCommandEncoder(&.{ .label = label }); game.state().frame_render_pass = game.state().frame_encoder.beginRenderPass(&gpu.RenderPassDescriptor.init(.{ .label = label, .color_attachments = &color_attachments, diff --git a/examples/text/App.zig b/examples/text/App.zig index b04bfcd2..e091eafa 100644 --- a/examples/text/App.zig +++ b/examples/text/App.zig @@ -251,7 +251,6 @@ fn tick( .load_op = .clear, .store_op = .store, }}; - game.state().frame_encoder = core.state().device.createCommandEncoder(&.{ .label = label }); game.state().frame_render_pass = game.state().frame_encoder.beginRenderPass(&gpu.RenderPassDescriptor.init(.{ .label = label, .color_attachments = &color_attachments, diff --git a/src/gfx/Sprite.zig b/src/gfx/Sprite.zig index 968aab2f..74d7199c 100644 --- a/src/gfx/Sprite.zig +++ b/src/gfx/Sprite.zig @@ -107,6 +107,7 @@ fn updatePipeline( encoder.writeBuffer(built.transforms, 0, gfx.SpritePipeline.cp_transforms[0..i]); encoder.writeBuffer(built.uv_transforms, 0, gfx.SpritePipeline.cp_uv_transforms[0..i]); encoder.writeBuffer(built.sizes, 0, gfx.SpritePipeline.cp_sizes[0..i]); + var command = encoder.finish(&.{ .label = label }); defer command.release(); core.state().queue.submit(&[_]*gpu.CommandBuffer{command}); diff --git a/src/gfx/SpritePipeline.zig b/src/gfx/SpritePipeline.zig index dc3a8cd5..9c1edd53 100644 --- a/src/gfx/SpritePipeline.zig +++ b/src/gfx/SpritePipeline.zig @@ -60,7 +60,7 @@ pub const components = .{ }; pub const events = .{ - .init = .{ .handler = fn () void }, + .init = .{ .handler = init }, .deinit = .{ .handler = deinit }, .update = .{ .handler = update }, .pre_render = .{ .handler = preRender }, @@ -119,6 +119,10 @@ pub const BuiltPipeline = struct { } }; +fn init(sprite_pipeline: *Mod) void { + sprite_pipeline.init(.{}); +} + fn deinit(sprite_pipeline: *Mod) void { var archetypes_iter = sprite_pipeline.entities.query(.{ .all = &.{ .{ .mach_gfx_sprite_pipeline = &.{ @@ -131,8 +135,6 @@ fn deinit(sprite_pipeline: *Mod) void { } fn update(core: *mach.Core.Mod, sprite_pipeline: *Mod) !void { - sprite_pipeline.init(.{}); - // Destroy all sprite render pipelines. We will rebuild them all. deinit(sprite_pipeline); diff --git a/src/gfx/TextPipeline.zig b/src/gfx/TextPipeline.zig index bbddb756..78a10736 100644 --- a/src/gfx/TextPipeline.zig +++ b/src/gfx/TextPipeline.zig @@ -267,10 +267,22 @@ fn buildPipeline( .label = label, .layout = bind_group_layout, .entries = &.{ - gpu.BindGroup.Entry.buffer(0, uniforms, 0, @sizeOf(Uniforms)), - gpu.BindGroup.Entry.buffer(1, transforms, 0, @sizeOf(math.Mat4x4) * texts_buffer_cap), - gpu.BindGroup.Entry.buffer(2, colors, 0, @sizeOf(math.Vec4) * texts_buffer_cap), - gpu.BindGroup.Entry.buffer(3, glyphs, 0, @sizeOf(Glyph) * texts_buffer_cap), + if (mach.use_sysgpu) + gpu.BindGroup.Entry.buffer(0, uniforms, 0, @sizeOf(Uniforms), @sizeOf(Uniforms)) + else + gpu.BindGroup.Entry.buffer(0, uniforms, 0, @sizeOf(Uniforms)), + if (mach.use_sysgpu) + gpu.BindGroup.Entry.buffer(1, transforms, 0, @sizeOf(math.Mat4x4) * texts_buffer_cap, @sizeOf(math.Mat4x4)) + else + gpu.BindGroup.Entry.buffer(1, transforms, 0, @sizeOf(math.Mat4x4) * texts_buffer_cap), + if (mach.use_sysgpu) + gpu.BindGroup.Entry.buffer(2, colors, 0, @sizeOf(math.Vec4) * texts_buffer_cap, @sizeOf(math.Vec4)) + else + gpu.BindGroup.Entry.buffer(2, colors, 0, @sizeOf(math.Vec4) * texts_buffer_cap), + if (mach.use_sysgpu) + gpu.BindGroup.Entry.buffer(3, glyphs, 0, @sizeOf(Glyph) * texts_buffer_cap, @sizeOf(Glyph)) + else + gpu.BindGroup.Entry.buffer(3, glyphs, 0, @sizeOf(Glyph) * texts_buffer_cap), gpu.BindGroup.Entry.sampler(4, texture_sampler), gpu.BindGroup.Entry.textureView(5, texture_view), },