From 2bb3b71b2b14edc1053e9283443a2027a4c91fee Mon Sep 17 00:00:00 2001 From: David Allemang Date: Tue, 9 Jul 2024 16:09:22 -0400 Subject: [PATCH] good but wrong teardown order; device wait idle --- src/main.zig | 2 +- src/nu.zig | 6 ++- src/nu/ImGui.zig | 98 +++++++++++++++++++++++++++++++++++++++++++- src/nu/Render.zig | 26 ++++++++++++ src/nu/Render/au.zig | 10 ++--- 5 files changed, 133 insertions(+), 9 deletions(-) diff --git a/src/main.zig b/src/main.zig index 2404851..6e82cc7 100644 --- a/src/main.zig +++ b/src/main.zig @@ -29,7 +29,7 @@ pub fn main() !void { try nu.Render.init(alloc); defer nu.Render.deinit(); - try nu.ImGui.init(alloc); + try nu.ImGui.init(); defer nu.ImGui.deinit(); try App.init(alloc); diff --git a/src/nu.zig b/src/nu.zig index 26be0d6..a977e4e 100644 --- a/src/nu.zig +++ b/src/nu.zig @@ -26,7 +26,11 @@ pub fn run( if (@typeInfo(@TypeOf(module.frame)).Fn.return_type) |R| { switch (@typeInfo(R)) { .ErrorUnion => try module.frame(), - else => @compileError("frame must be void or !void."), + .Void => module.frame(), + else => { + @compileLog(module.frame, @typeInfo(R)); + @compileError("frame must be void or !void."); + }, } } else { module.frame(); diff --git a/src/nu/ImGui.zig b/src/nu/ImGui.zig index e5f5c61..e5231bd 100644 --- a/src/nu/ImGui.zig +++ b/src/nu/ImGui.zig @@ -2,11 +2,105 @@ const std = @import("std"); +const vk = @import("vk"); +const nu = @import("../nu.zig"); +const au = @import("Render/au.zig"); const Render = @import("Render.zig"); +const Window = @import("Window.zig"); -pub fn init(alloc: std.mem.Allocator) !void { - _ = alloc; +const im = @import("cimgui"); + +pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { + return au.glfwGetInstanceProcAddress(au.I.handle, procname); +} + +var ctx: *im.c.ImGuiContext = undefined; +var descriptor_pool: vk.DescriptorPool = undefined; + +pub fn init() !void { + ctx = im.c.igCreateContext(null) orelse { + return error.igCreateContextFailed; + }; + errdefer im.c.igDestroyContext(ctx); + + if (!im.c.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null)) { + return error.igVulkanLoadFunctionsFailed; + } + + if (!im.c.ImGui_ImplGlfw_InitForVulkan(@ptrCast(Window.handle), true)) { + return error.igGlfwInitFailed; + } + errdefer im.c.ImGui_ImplGlfw_Shutdown(); + + descriptor_pool = try au.D.createDescriptorPool(&vk.DescriptorPoolCreateInfo{ + .flags = .{ .free_descriptor_set_bit = true }, + .pool_size_count = 1, + .p_pool_sizes = &.{vk.DescriptorPoolSize{ + .descriptor_count = 32, + .type = .combined_image_sampler, + }}, + .max_sets = 32, + }, null); + errdefer au.D.destroyDescriptorPool(descriptor_pool, null); + + if (im.c.ImGui_ImplVulkan_Init(@constCast(&im.c.ImGui_ImplVulkan_InitInfo{ + .Instance = @ptrFromInt(@intFromEnum(au.I.handle)), + .PhysicalDevice = @ptrFromInt(@intFromEnum(au.device_config.pdev)), + .Device = @ptrFromInt(@intFromEnum(au.D.handle)), + .QueueFamily = au.device_config.family, + .Queue = @ptrFromInt(@intFromEnum(au.Q.handle)), + .DescriptorPool = @ptrFromInt(@intFromEnum(descriptor_pool)), + .RenderPass = null, + .MinImageCount = 2, + .ImageCount = @intCast(nu.options.render.frames_in_flight), + .PipelineRenderingCreateInfo = @bitCast(vk.PipelineRenderingCreateInfo{ + .view_mask = 0, + .depth_attachment_format = .undefined, + .stencil_attachment_format = .undefined, + .color_attachment_count = 1, + .p_color_attachment_formats = &.{au.device_config.format.format}, + }), + .MSAASamples = 0, + .PipelineCache = null, + .Subpass = 0, + .UseDynamicRendering = true, + .Allocator = null, + })) != true) { + return error.igVulkanInitFailed; + } + errdefer im.c.ImGui_ImplVulkan_Shutdown(); + + if (!im.c.ImGui_ImplVulkan_CreateFontsTexture()) { + return error.igVulkanFontTextureFailed; + } + + try Render.add_present_callback(present); + errdefer Render.remove_present_callback(present); +} + +pub fn frame() void { + im.c.ImGui_ImplGlfw_NewFrame(); + im.c.ImGui_ImplVulkan_NewFrame(); + im.c.igNewFrame(); + + im.c.igShowDemoWindow(null); + + im.c.igEndFrame(); + im.c.igRender(); } pub fn deinit() void { + Render.remove_present_callback(present); + im.c.ImGui_ImplVulkan_Shutdown(); + au.D.destroyDescriptorPool(descriptor_pool, null); + im.c.ImGui_ImplGlfw_Shutdown(); + im.c.igDestroyContext(ctx); +} + +pub fn present(cmd: au.CommandBufferProxy) void { + im.c.ImGui_ImplVulkan_RenderDrawData( + im.c.igGetDrawData(), + @ptrFromInt(@intFromEnum(cmd.handle)), + null, + ); } diff --git a/src/nu/Render.zig b/src/nu/Render.zig index 43dc9f0..952db90 100644 --- a/src/nu/Render.zig +++ b/src/nu/Render.zig @@ -30,11 +30,33 @@ pub const Options = struct { var sc: au.SwapChain = undefined; var flights: au.Flights = undefined; +const PresentCallback = *const fn (au.CommandBufferProxy) void; +var present_callbacks: std.ArrayList(PresentCallback) = undefined; + +pub fn add_present_callback(cb: PresentCallback) !void { + if (std.mem.indexOfScalar(PresentCallback, present_callbacks.items, cb)) |_| { + return; + } else { + try present_callbacks.append(cb); + } +} + +pub fn remove_present_callback(cb: PresentCallback) void { + if (std.mem.indexOfScalar(PresentCallback, present_callbacks.items, cb)) |idx| { + _ = present_callbacks.orderedRemove(idx); + } else { + return; + } +} + pub fn init(alloc: std.mem.Allocator) !void { // todo pick apart au into helpers; not a sub-module filled with its own globals. try au.init(alloc); errdefer au.deinit(); + present_callbacks = std.ArrayList(PresentCallback).init(alloc); + errdefer present_callbacks.deinit(); + sc = try au.SwapChain.init(alloc); errdefer sc.deinit(); @@ -67,6 +89,9 @@ pub fn frame() !void { try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } }); target.begin_rendering(cmd, render_area); + for (present_callbacks.items) |cb| { + cb(cmd); + } target.end_rendering(cmd); try cmd.endCommandBuffer(); @@ -98,6 +123,7 @@ pub fn frame() !void { } pub fn deinit() void { + present_callbacks.deinit(); au.D.deviceWaitIdle() catch {}; flights.deinit(); sc.deinit(); diff --git a/src/nu/Render/au.zig b/src/nu/Render/au.zig index 94705b4..2b54aa9 100644 --- a/src/nu/Render/au.zig +++ b/src/nu/Render/au.zig @@ -373,26 +373,26 @@ pub fn debug_callback( return vk.FALSE; } -extern fn glfwVulkanSupported() c_int; +pub extern fn glfwVulkanSupported() c_int; -extern fn glfwGetInstanceProcAddress( +pub extern fn glfwGetInstanceProcAddress( instance: vk.Instance, procname: [*:0]const u8, ) vk.PfnVoidFunction; -extern fn glfwGetPhysicalDevicePresentationSupport( +pub extern fn glfwGetPhysicalDevicePresentationSupport( instance: vk.Instance, pdev: vk.PhysicalDevice, queuefamily: u32, ) c_int; -extern fn glfwCreateWindowSurface( +pub extern fn glfwCreateWindowSurface( instance: vk.Instance, window: *nu.Window.c.GLFWwindow, allocation_callbacks: ?*const vk.AllocationCallbacks, surface: *vk.SurfaceKHR, ) vk.Result; -extern fn glfwGetRequiredInstanceExtensions( +pub extern fn glfwGetRequiredInstanceExtensions( count: *u32, ) [*][*:0]const u8;