//! all imgui code through this path const std = @import("std"); const vk = @import("vk"); const nu = @import("../nu.zig"); const au = @import("Render/au.zig"); const Hook = @import("hooks.zig").Hook; const Render = @import("Render.zig"); const Window = @import("Window.zig"); const im = @import("cimgui"); pub usingnamespace im; pub const Options = struct {}; pub const Hooks = struct { pub const Frame = Hook(fn () void); frame: Frame, }; pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { return au.glfwGetInstanceProcAddress(au.I.handle, procname); } var ctx: *im.ImGuiContext = undefined; var descriptor_pool: vk.DescriptorPool = undefined; pub var hooks: Hooks = undefined; pub fn init(alloc: std.mem.Allocator) !void { ctx = im.igCreateContext(null) orelse { return error.igCreateContextFailed; }; errdefer im.igDestroyContext(ctx); if (!im.impl.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null)) { return error.igVulkanLoadFunctionsFailed; } if (!im.impl.ImGui_ImplGlfw_InitForVulkan(@ptrCast(Window.handle), true)) { return error.igGlfwInitFailed; } errdefer im.impl.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.impl.ImGui_ImplVulkan_Init(@constCast(&im.impl.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.impl.ImGui_ImplVulkan_Shutdown(); if (!im.impl.ImGui_ImplVulkan_CreateFontsTexture()) { return error.igVulkanFontTextureFailed; } hooks = .{ .frame = Hooks.Frame.init(alloc), }; errdefer hooks.frame.deinit(); } pub fn deinit() void { hooks.frame.deinit(); im.impl.ImGui_ImplVulkan_Shutdown(); au.D.destroyDescriptorPool(descriptor_pool, null); im.impl.ImGui_ImplGlfw_Shutdown(); im.igDestroyContext(ctx); } pub fn connect() !void { try nu.hooks.frame.register(nu_frame); try Render.hooks.present.register(nu_render_present); } pub fn nu_frame() !void { im.impl.ImGui_ImplGlfw_NewFrame(); im.impl.ImGui_ImplVulkan_NewFrame(); im.igNewFrame(); hooks.frame.invoke(.{}); im.igEndFrame(); im.igRender(); } pub fn nu_render_present(cmd: au.CommandBufferProxy) void { im.impl.ImGui_ImplVulkan_RenderDrawData( @ptrCast(im.igGetDrawData()), @ptrFromInt(@intFromEnum(cmd.handle)), null, ); }