good but wrong teardown order; device wait idle

This commit is contained in:
David Allemang
2024-07-09 16:09:22 -04:00
parent 59912a4bc6
commit 2bb3b71b2b
5 changed files with 133 additions and 9 deletions

View File

@@ -29,7 +29,7 @@ pub fn main() !void {
try nu.Render.init(alloc); try nu.Render.init(alloc);
defer nu.Render.deinit(); defer nu.Render.deinit();
try nu.ImGui.init(alloc); try nu.ImGui.init();
defer nu.ImGui.deinit(); defer nu.ImGui.deinit();
try App.init(alloc); try App.init(alloc);

View File

@@ -26,7 +26,11 @@ pub fn run(
if (@typeInfo(@TypeOf(module.frame)).Fn.return_type) |R| { if (@typeInfo(@TypeOf(module.frame)).Fn.return_type) |R| {
switch (@typeInfo(R)) { switch (@typeInfo(R)) {
.ErrorUnion => try module.frame(), .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 { } else {
module.frame(); module.frame();

View File

@@ -2,11 +2,105 @@
const std = @import("std"); 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 Render = @import("Render.zig");
const Window = @import("Window.zig");
pub fn init(alloc: std.mem.Allocator) !void { const im = @import("cimgui");
_ = alloc;
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 { 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,
);
} }

View File

@@ -30,11 +30,33 @@ pub const Options = struct {
var sc: au.SwapChain = undefined; var sc: au.SwapChain = undefined;
var flights: au.Flights = 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 { pub fn init(alloc: std.mem.Allocator) !void {
// todo pick apart au into helpers; not a sub-module filled with its own globals. // todo pick apart au into helpers; not a sub-module filled with its own globals.
try au.init(alloc); try au.init(alloc);
errdefer au.deinit(); errdefer au.deinit();
present_callbacks = std.ArrayList(PresentCallback).init(alloc);
errdefer present_callbacks.deinit();
sc = try au.SwapChain.init(alloc); sc = try au.SwapChain.init(alloc);
errdefer sc.deinit(); errdefer sc.deinit();
@@ -67,6 +89,9 @@ pub fn frame() !void {
try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } }); try cmd.beginCommandBuffer(&.{ .flags = .{ .one_time_submit_bit = true } });
target.begin_rendering(cmd, render_area); target.begin_rendering(cmd, render_area);
for (present_callbacks.items) |cb| {
cb(cmd);
}
target.end_rendering(cmd); target.end_rendering(cmd);
try cmd.endCommandBuffer(); try cmd.endCommandBuffer();
@@ -98,6 +123,7 @@ pub fn frame() !void {
} }
pub fn deinit() void { pub fn deinit() void {
present_callbacks.deinit();
au.D.deviceWaitIdle() catch {}; au.D.deviceWaitIdle() catch {};
flights.deinit(); flights.deinit();
sc.deinit(); sc.deinit();

View File

@@ -373,26 +373,26 @@ pub fn debug_callback(
return vk.FALSE; return vk.FALSE;
} }
extern fn glfwVulkanSupported() c_int; pub extern fn glfwVulkanSupported() c_int;
extern fn glfwGetInstanceProcAddress( pub extern fn glfwGetInstanceProcAddress(
instance: vk.Instance, instance: vk.Instance,
procname: [*:0]const u8, procname: [*:0]const u8,
) vk.PfnVoidFunction; ) vk.PfnVoidFunction;
extern fn glfwGetPhysicalDevicePresentationSupport( pub extern fn glfwGetPhysicalDevicePresentationSupport(
instance: vk.Instance, instance: vk.Instance,
pdev: vk.PhysicalDevice, pdev: vk.PhysicalDevice,
queuefamily: u32, queuefamily: u32,
) c_int; ) c_int;
extern fn glfwCreateWindowSurface( pub extern fn glfwCreateWindowSurface(
instance: vk.Instance, instance: vk.Instance,
window: *nu.Window.c.GLFWwindow, window: *nu.Window.c.GLFWwindow,
allocation_callbacks: ?*const vk.AllocationCallbacks, allocation_callbacks: ?*const vk.AllocationCallbacks,
surface: *vk.SurfaceKHR, surface: *vk.SurfaceKHR,
) vk.Result; ) vk.Result;
extern fn glfwGetRequiredInstanceExtensions( pub extern fn glfwGetRequiredInstanceExtensions(
count: *u32, count: *u32,
) [*][*:0]const u8; ) [*][*:0]const u8;