182 lines
5.4 KiB
Zig
182 lines
5.4 KiB
Zig
//! ----------------------------------------------------
|
|
//! SDL3 + Vulkan
|
|
//!
|
|
//! Used dear_bindings with docking imgui branch
|
|
//! https://mrscriptx.github.io/devlog/zig/2025/04/30/zig-linking-dear-imgui.html
|
|
//! ----------------------------------------------------
|
|
|
|
const im = @import("imgui");
|
|
const im_vk = @import("imgui_impl_vulkan");
|
|
const im_sdl = @import("imgui_impl_sdl3");
|
|
|
|
const std = @import("std");
|
|
const sdl = @import("sdl");
|
|
const Gfx = @import("gfx");
|
|
|
|
pub fn main(init: std.process.Init) !void {
|
|
|
|
//
|
|
// SDL
|
|
//
|
|
|
|
// --- # ---
|
|
if (!sdl.SDL_Init(sdl.SDL_INIT_VIDEO)) return error.FailedToInitSDL;
|
|
defer sdl.SDL_Quit();
|
|
|
|
// --- # ---
|
|
const window = sdl.SDL_CreateWindow("NYXGFX", 800, 600, sdl.SDL_WINDOW_VULKAN) orelse return error.FailedTomakeWindow;
|
|
defer sdl.SDL_DestroyWindow(window);
|
|
|
|
// --- # ---
|
|
const props = sdl.SDL_GetWindowProperties(window);
|
|
const display = sdl.SDL_GetPointerProperty(props, sdl.SDL_PROP_WINDOW_X11_DISPLAY_POINTER, null);
|
|
const xwindow = sdl.SDL_GetNumberProperty(props, sdl.SDL_PROP_WINDOW_X11_WINDOW_NUMBER, 0);
|
|
|
|
//
|
|
// GFX
|
|
//
|
|
|
|
// --- # ---
|
|
var gfx: Gfx = try .init(
|
|
init.gpa,
|
|
init.io,
|
|
);
|
|
defer gfx.deinit();
|
|
|
|
// --- # ---
|
|
const instance = try gfx.makeInstance(.{
|
|
.vulkan = .{
|
|
.api_version = .v1_3,
|
|
},
|
|
});
|
|
|
|
const surface = try gfx.makeSurface(.{
|
|
.xlib = .{
|
|
.window = @intCast(xwindow),
|
|
.display = display.?,
|
|
},
|
|
}, instance);
|
|
|
|
const adapter = try gfx.makeAdapter(.{}, instance);
|
|
const device = try gfx.makeDevice(adapter, surface);
|
|
const swapchain = try gfx.makeSwapchain(adapter, device, surface);
|
|
|
|
//
|
|
// IMGUI
|
|
//
|
|
|
|
// --- CREATE IMGUI CTX ---
|
|
const ctx = im.ImGui_CreateContext(null) orelse return error.FailedToCreateImGuiContext;
|
|
defer im.ImGui_DestroyContext(ctx);
|
|
|
|
// --- INIT IMGUI FOR SDL3 + VK ---
|
|
if (!im_sdl.cImGui_ImplSDL3_InitForVulkan(@ptrCast(window))) return error.FailedToImplImGuiForSDL;
|
|
defer im_sdl.cImGui_ImplSDL3_Shutdown();
|
|
|
|
// --- SET IO ---
|
|
const io = im.ImGui_GetIO() orelse return error.FailedToGetImGuiIO;
|
|
io.*.ConfigFlags |= im.ImGuiConfigFlags_NavEnableKeyboard;
|
|
io.*.ConfigFlags |= im.ImGuiConfigFlags_DockingEnable;
|
|
|
|
// --- GET VK RAW DEVICE ---
|
|
const raw_device = switch (try gfx.getRawDevice(device)) {
|
|
.vulkan => |v| v,
|
|
};
|
|
|
|
// --- GET VK RAW SWAPCHAIN ---
|
|
const raw_swapchain = try gfx.getRawSwapchain(swapchain);
|
|
|
|
// --- INIT IMGUI FOR VK ---
|
|
var color_format: im_vk.VkFormat = raw_swapchain.format;
|
|
var im_info: im_vk.ImGui_ImplVulkan_InitInfo = .{
|
|
.Instance = @ptrCast((try gfx.getRawInstance(instance)).vulkan),
|
|
.PhysicalDevice = blk: {
|
|
switch (try gfx.getRawAdapter(adapter)) {
|
|
.vulkan => |v| break :blk @ptrCast(v),
|
|
}
|
|
},
|
|
.Device = @ptrCast(raw_device.device),
|
|
.Queue = @ptrCast(raw_device.present_queue),
|
|
.DescriptorPoolSize = 1024,
|
|
.MinImageCount = 2,
|
|
.ImageCount = @intCast(raw_swapchain.images.len),
|
|
.PipelineInfoMain = .{
|
|
.MSAASamples = im_vk.VK_SAMPLE_COUNT_1_BIT,
|
|
.PipelineRenderingCreateInfo = .{
|
|
.sType = im_vk.VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
|
|
.colorAttachmentCount = 1,
|
|
.pColorAttachmentFormats = &color_format,
|
|
},
|
|
},
|
|
|
|
.UseDynamicRendering = true, // <--- vulkan implementation specific
|
|
};
|
|
if (!im_vk.cImGui_ImplVulkan_Init(&im_info)) return error.FailedToImplImGuiForVulkan;
|
|
defer {
|
|
_ = im_vk.vkDeviceWaitIdle(@ptrCast(raw_device.device));
|
|
im_vk.cImGui_ImplVulkan_Shutdown();
|
|
}
|
|
|
|
//
|
|
// MAIN LOOP
|
|
//
|
|
|
|
// --- MISC ---
|
|
var event: sdl.SDL_Event = undefined;
|
|
var running: bool = true;
|
|
|
|
while (running) {
|
|
// --- INPUTS ---
|
|
while (sdl.SDL_PollEvent(&event)) {
|
|
switch (event.type) {
|
|
sdl.SDL_EVENT_QUIT => running = false,
|
|
else => {},
|
|
}
|
|
_ = im_sdl.cImGui_ImplSDL3_ProcessEvent(@ptrCast(&event));
|
|
}
|
|
|
|
{ // IMGUI
|
|
// --- NEW IMGUI FRAME ---
|
|
im_sdl.cImGui_ImplSDL3_NewFrame();
|
|
im_vk.cImGui_ImplVulkan_NewFrame();
|
|
im.ImGui_NewFrame();
|
|
|
|
// --- UI ---
|
|
if (im.ImGui_Begin("Inspector", null, 0)) {
|
|
defer im.ImGui_End();
|
|
|
|
im.ImGui_Text("Hello World");
|
|
if (im.ImGui_Button("Click Me")) {}
|
|
}
|
|
|
|
// --- DEMO ---
|
|
im.ImGui_ShowDemoWindow(null);
|
|
|
|
// --- RENDER IMGUI ---
|
|
im.ImGui_Render();
|
|
}
|
|
|
|
// --- FRAME ---
|
|
try gfx.beginFrame(swapchain, device);
|
|
defer gfx.endFrame(swapchain, device) catch unreachable;
|
|
|
|
// --- NEW PASS ---
|
|
if (gfx.beginPass(swapchain, .{
|
|
.clear_color = .{ 0.01, 0.01, 0.01, 1.0 },
|
|
})) |pass| {
|
|
defer pass.end();
|
|
|
|
// --- RENDER IMGUI ---
|
|
switch (try gfx.getRawFrame()) {
|
|
.vulkan => |v| {
|
|
const draw_data = im.ImGui_GetDrawData() orelse return;
|
|
|
|
im_vk.cImGui_ImplVulkan_RenderDrawData(
|
|
@ptrCast(draw_data),
|
|
@ptrCast(v.cmd_buf),
|
|
);
|
|
},
|
|
}
|
|
}
|
|
}
|
|
}
|