From 154427d5bc2629313799b5488a24d29a5bc365d1 Mon Sep 17 00:00:00 2001 From: David Allemang Date: Mon, 1 Jul 2024 17:24:04 -0400 Subject: [PATCH] ImGui demo window --- .gitignore | 2 + build.zig | 3 ++ build.zig.zon | 3 ++ cimgui/build.zig | 93 ++++++++++++++++++++++++++++++++++++++++++++ cimgui/build.zig.zon | 19 +++++++++ cimgui/src/root.zig | 10 +++++ src/au.zig | 2 +- src/main.zig | 68 ++++++++++++++++++++++++++++++-- 8 files changed, 196 insertions(+), 4 deletions(-) create mode 100644 cimgui/build.zig create mode 100644 cimgui/build.zig.zon create mode 100644 cimgui/src/root.zig diff --git a/.gitignore b/.gitignore index 3516d89..c33569d 100644 --- a/.gitignore +++ b/.gitignore @@ -45,3 +45,5 @@ build-*/ docgen_tmp/ .idea/ + +imgui.ini diff --git a/build.zig b/build.zig index c213265..c6d8fbb 100644 --- a/build.zig +++ b/build.zig @@ -11,12 +11,15 @@ pub fn build(b: *std.Build) void { }); const vkmod = vk.module("vulkan-zig"); + const cimgui = b.dependency("cimgui", .{}); + const exe = b.addExecutable(.{ .name = "scratchzig", .root_source_file = b.path("src/main.zig"), .target = target, .optimize = optimize, }); + exe.root_module.addImport("cimgui", cimgui.module("cimgui")); const shaders = vkgen.ShaderCompileStep.create( b, diff --git a/build.zig.zon b/build.zig.zon index 43a3b53..6942b2e 100644 --- a/build.zig.zon +++ b/build.zig.zon @@ -7,6 +7,9 @@ .url = "https://github.com/Snektron/vulkan-zig/archive/f2c2e0ff80374563357cc4fe72bf7d8a2c956824.tar.gz", .hash = "1220cf0972c6fe05437c1a8689b955084385eb7ca1f8c14010d49ca5a89570a5d90d", }, + .cimgui = .{ + .path="cimgui", + }, }, .paths = .{ diff --git a/cimgui/build.zig b/cimgui/build.zig new file mode 100644 index 0000000..11349b1 --- /dev/null +++ b/cimgui/build.zig @@ -0,0 +1,93 @@ +const std = @import("std"); +const vkgen = @import("vulkan-zig"); + +pub fn build(b: *std.Build) !void { + const target = b.standardTargetOptions(.{}); + const optimize = b.standardOptimizeOption(.{}); + + const imgui_dep = b.dependency("imgui", .{}); + const cimgui_dep = b.dependency("cimgui", .{}); + + const luajit = try b.findProgram(&.{"luajit"}, &.{}); + + const gen = b.addSystemCommand(&.{luajit}); + gen.setCwd(cimgui_dep.path("generator/")); + gen.addFileArg(cimgui_dep.path("generator/generator.lua")); + gen.addArgs(&.{ + "zig cc", + "comments internal noimstrv", + "glfw", + "vulkan", + }); + _ = gen.captureStdOut(); // to quiet output + + { + const relpath = try std.fs.path.relative( + b.allocator, + cimgui_dep.path("generator").getPath(b), + imgui_dep.path("").getPath(b), + ); + defer b.allocator.free(relpath); + gen.setEnvironmentVariable( + "IMGUI_PATH", + relpath, + ); + } + + const copy = b.addWriteFiles(); + copy.step.dependOn(&gen.step); + _ = copy.addCopyDirectory(imgui_dep.path(""), "imgui", .{ + .include_extensions = &.{ ".h", ".cpp" }, + }); + _ = copy.addCopyFile(cimgui_dep.path("cimgui.h"), "cimgui.h"); + _ = copy.addCopyFile(cimgui_dep.path("cimgui.cpp"), "cimgui.cpp"); + _ = copy.addCopyFile(cimgui_dep.path("generator/output/cimgui_impl.h"), "cimgui_impl.h"); + + const cimgui = b.addSharedLibrary(.{ + .name = "cimgui", + .target = target, + .optimize = optimize, + }); + cimgui.step.dependOn(©.step); + cimgui.linkLibC(); + cimgui.linkLibCpp(); + cimgui.addIncludePath(copy.getDirectory()); + cimgui.addIncludePath(copy.getDirectory().path(b, "imgui")); + cimgui.addCSourceFiles(.{ + .root = copy.getDirectory(), + .files = &.{ + "cimgui.cpp", + "imgui/imgui.cpp", + "imgui/imgui_tables.cpp", + "imgui/imgui_widgets.cpp", + "imgui/imgui_demo.cpp", + "imgui/imgui_draw.cpp", + "imgui/backends/imgui_impl_glfw.cpp", + "imgui/backends/imgui_impl_vulkan.cpp", + }, + .flags = &.{ + "-DIMGUI_IMPL_VULKAN_NO_PROTOTYPES", + "-DCIMGUI_USE_GLFW", + "-DCIMGUI_USE_VULKAN", + "-DIMGUI_IMPL_API=extern \"C\"", + }, + }); + cimgui.installHeader(copy.getDirectory().path(b, "cimgui.h"), "cimgui.h"); + cimgui.installHeader(copy.getDirectory().path(b, "cimgui_impl.h"), "cimgui_impl.h"); + + // todo separate impls into different shared libraries for easier linkage + cimgui.linkSystemLibrary2("glfw3", .{ + .needed = true, + .preferred_link_mode = .static, + .use_pkg_config = .force, + }); + + b.installArtifact(cimgui); + + const cimgui_mod = b.addModule("cimgui", .{ + .target = target, + .optimize = optimize, + .root_source_file = b.path("src/root.zig"), + }); + cimgui_mod.linkLibrary(cimgui); +} diff --git a/cimgui/build.zig.zon b/cimgui/build.zig.zon new file mode 100644 index 0000000..935c753 --- /dev/null +++ b/cimgui/build.zig.zon @@ -0,0 +1,19 @@ +.{ + .name = "cimgui", + .version = "0.0.0", + + .dependencies = .{ + .cimgui = .{ + .url = "https://github.com/cimgui/cimgui/archive/refs/tags/1.90.8dock.tar.gz", + .hash = "12207ee69164f88f4b41ee5d44edf3835ec4dab0c0cd885799da67d56668f4a3d46b", + }, + .imgui = .{ + .url = "https://github.com/ocornut/imgui/archive/refs/tags/v1.90.8-docking.tar.gz", + .hash = "122065151b97161e25abb71c9df2fd9fba42aaca8c33d689a480b883d82411c8fabe", + }, + }, + + .paths = .{ + "", + }, +} diff --git a/cimgui/src/root.zig b/cimgui/src/root.zig new file mode 100644 index 0000000..bd5d960 --- /dev/null +++ b/cimgui/src/root.zig @@ -0,0 +1,10 @@ +pub const c = @cImport({ + @cDefine("CIMGUI_DEFINE_ENUMS_AND_STRUCTS", {}); + @cInclude("cimgui.h"); + + @cInclude("vulkan/vulkan.h"); + + @cDefine("CIMGUI_USE_VULKAN", {}); + @cDefine("CIMGUI_USE_GLFW", {}); + @cInclude("cimgui_impl.h"); +}); diff --git a/src/au.zig b/src/au.zig index 11a1815..79e1a37 100644 --- a/src/au.zig +++ b/src/au.zig @@ -31,7 +31,7 @@ pub const device_extensions: []const [*:0]const u8 = &.{ }; pub const app_info: vk.ApplicationInfo = .{ - .p_application_name = "zig-glfw-vulkan", + .p_application_name = "hey tildes!", .application_version = vk.makeApiVersion(0, 0, 0, 0), .p_engine_name = "zig-glfw-vulkan", .engine_version = vk.makeApiVersion(0, 0, 0, 0), diff --git a/src/main.zig b/src/main.zig index a1169d5..2cc82d4 100644 --- a/src/main.zig +++ b/src/main.zig @@ -5,8 +5,7 @@ const shaders = @import("shaders"); const Allocator = std.mem.Allocator; const au = @import("au.zig"); - -const app_name = "vulkan-zig triangle example"; +const im = @import("cimgui"); const Vertex = extern struct { const binding_description = vk.VertexInputBindingDescription{ @@ -50,7 +49,6 @@ const vertices = [_]Vertex{ const indices = [_]Index{ 4, 5, 6, 6, 5, 7 }; - const Frame = struct { pub fn init() !Frame { return .{}; @@ -132,6 +130,8 @@ const Frame = struct { // vkd.cmdBindIndexBuffer(cmdbuf, index_buffer, 0, .uint16); // vkd.cmdDrawIndexed(cmdbuf, indices.len, 1, 0, 0, 0); + im.c.ImGui_ImplVulkan_RenderDrawData(im.c.igGetDrawData(), @ptrFromInt(@intFromEnum(cmd.handle)), null); + cmd.endRendering(); cmd.pipelineBarrier( @@ -163,6 +163,10 @@ const Frame = struct { } }; +pub fn loader_wrapper(procname: [*c]const u8, _: ?*anyopaque) callconv(.C) vk.PfnVoidFunction { + return c.glfwGetInstanceProcAddress(au.I.handle, procname); +} + pub fn main() !void { var gpa = std.heap.GeneralPurposeAllocator(.{}){}; defer _ = gpa.detectLeaks(); @@ -177,7 +181,65 @@ pub fn main() !void { var flights = try au.Flights(Frame).init(alloc, 3); // FRAMES IN FLIGHT defer flights.deinit(); + const ctx = im.c.igCreateContext(null) orelse return error.igCreateContextFailed; + defer im.c.igDestroyContext(ctx); + + // _ = im.c.ImGui_ImplGlfw_InitForOther(@ptrCast(au.W.handle), true); + // defer im.c.ImGui_ImplGlfw_Shutdown(); + + const descriptorPool = 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); + defer au.D.destroyDescriptorPool(descriptorPool, null); + + _ = im.c.ImGui_ImplVulkan_LoadFunctions(loader_wrapper, null); + _ = im.c.ImGui_ImplGlfw_InitForVulkan(@ptrCast(au.W.handle), true); + defer im.c.ImGui_ImplGlfw_Shutdown(); + + _ = try sc.rebuild(); + + const prci: 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}, + }; + + var info: 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(descriptorPool)), + .RenderPass = null, + .MinImageCount = sc.cinfo.min_image_count, + .ImageCount = @intCast(sc.images.items.len), + .PipelineRenderingCreateInfo = @bitCast(prci), + .MSAASamples = 0, + .PipelineCache = null, + .Subpass = 0, + .UseDynamicRendering = true, + .Allocator = null, + }; + _ = im.c.ImGui_ImplVulkan_Init(&info); + _ = im.c.ImGui_ImplVulkan_CreateFontsTexture(); + defer im.c.ImGui_ImplVulkan_Shutdown(); + while (!au.W.should_close()) { + im.c.ImGui_ImplGlfw_NewFrame(); + im.c.ImGui_ImplVulkan_NewFrame(); + im.c.igNewFrame(); + im.c.igShowDemoWindow(null); + im.c.igEndFrame(); + im.c.igRender(); + const flight = flights.next(); const events = if (au.W.focused())