imgui working on the new sdl renderer

This commit is contained in:
Peter Li 2025-04-19 21:36:38 -07:00
parent 0ca5592b40
commit 64c87ba3cc
12 changed files with 351 additions and 404 deletions

View File

@ -1,17 +1,25 @@
const std = @import("std");
pub const core = @import("core");
pub const cimgui = @import("cimgui");
pub const api = @import("cimgui");
const rend = @import("rend");
const Impl = @import("sgpu/backend_impl.zig").Impl;
pub const Module: core.ModuleDescription = .{
.name = "imgui",
.enabledByDefault = false,
};
var gImgui: *Impl = undefined;
pub fn start_module(comptime programSpec: anytype, args: anytype, allocator: std.mem.Allocator) !void {
_ = allocator;
_ = args;
_ = programSpec;
// gImgui = try rend.createRendererObject(Impl);
// try gImgui.setup();
gImgui = try core.createObject(Impl, .{});
try gImgui.setup();
}
pub fn shutdown_module(allocator: std.mem.Allocator) void {

View File

@ -1,37 +1,73 @@
pub const ImguiImpl = struct {
pub const Impl = struct {
allocator: std.mem.Allocator,
device: *gpu.GPUDevice,
device: *gpu.GPUDevice = undefined,
drawData: [*c]ig.DrawData = undefined,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This());
pub const Settings = struct {
x: u32 = 0,
};
// renderer plugin
pub fn create(device: *gpu.GPUDevice, allocator: std.mem.Allocator, settings: struct {}) !*@This() {
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self = try allocator.create(@This());
self.* = .{
.allocator = allocator,
.device = device,
};
_ = settings;
return self;
}
pub fn setup(self: *@This()) !void {
core.graphics_log("imgui startup", .{});
self.device = rend.context().device;
try rend.registerRendererObject(@This(), self);
c.Imgui_SDL3_Init(@ptrCast(platform.getInstance().window), @ptrCast(self.device));
try platform.getInstance().addSDLProcessFunction(processSDLEvents);
}
pub fn processSDLEvents(event: *sdl3.Event) void {
c.Imgui_SDL3_ProcessEvent(@ptrCast(event));
}
pub fn onPreDraw(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void {
const self: *@This() = @ptrCast(@alignCast(p));
ig.render();
self.drawData = ig.getDrawData();
c.Imgui_SDL3_PrepareRender(@ptrCast(self.drawData), @ptrCast(cmd));
}
pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer, renderPass: *gpu.GPURenderPass) void {
const self: *@This() = @ptrCast(@alignCast(p));
c.ImGui_SDLGPU3_RenderDrawData(
@ptrCast(self.drawData),
@ptrCast(cmd),
@ptrCast(renderPass),
);
}
pub fn preTick(_: *@This(), _: f64) core.EngineDataEventError!void {
c.ImGui_ImplGlfw_NewFrame();
c.cImGui_vk_NewFrame();
core.engine_logs("imgui pretick");
c.Imgui_SDL3_NewFrame();
c.igNewFrame();
}
// renderer plugin
pub fn destroy(p: *anyopaque) void {
const self: *@This() = @ptrCast(@alignCast(p));
pub fn destroy(self: *@This()) void {
self.allocator.destroy(self);
}
};
const c = @import("cimgui").c;
const ig = @import("cimgui").cimgui;
const ig = @import("cimgui");
const sdl3 = @import("sdl3");
const gpu = sdl3.gpu;
const rend = @import("rend");
const platform = @import("platform");
const std = @import("std");
const core = @import("core");

View File

@ -6,7 +6,7 @@ pub const list = [_][]const u8{
"physics",
"rend",
// "imgui",
"imgui",
// to be implemented
// "graphics",
// "ui",

View File

@ -75,9 +75,12 @@ pub const PlatformInstance = struct {
windowDestroyed: bool = false,
processFuncs: std.ArrayListUnmanaged(*const fn (*sdl3.Event) void) = .{},
pub fn deinit(self: *@This()) void {
self.allocator.free(self.windowName);
self.allocator.free(self.iconPath);
self.processFuncs.deinit(self.allocator);
// shutdown
}
@ -105,6 +108,10 @@ pub const PlatformInstance = struct {
return self;
}
pub fn addSDLProcessFunction(self: *@This(), processFunc: *const fn (*sdl3.Event) void) !void {
try self.processFuncs.append(self.allocator, processFunc);
}
pub fn setupWindow(self: *@This()) core.EngineDataEventError!void {
sdl3.init(.{ .video = true, .gamepad = true }) catch return error.BadInit;
self.window = sdl3.c.SDL_CreateWindow(self.windowName, self.windowExtent.x, self.windowExtent.y, 0).?; // resizeable
@ -130,7 +137,8 @@ pub const PlatformInstance = struct {
pub fn processEvents(ptr: *anyopaque, frameNumber: u64) core.EngineDataEventError!void {
_ = frameNumber;
_ = ptr;
const self: *@This() = @ptrCast(@alignCast(ptr));
// const self: *@This() = @ptrCast(@alignCast(ptr));
var t1 = tracy.ZoneN(@src(), "Pumping Events");
defer t1.End();
@ -142,6 +150,10 @@ pub const PlatformInstance = struct {
inputStack.routeEvent(converted);
}
for (self.processFuncs.items) |func| {
func(@ptrCast(event));
}
switch (event.type) {
sdl3.events.quit => {
core.exitNow();

View File

@ -27,6 +27,9 @@ pub const getMeshByName = renderer.getMeshByName;
// camera API
pub const setActiveCamera = renderer.setActiveCamera;
pub const createRendererObject = renderer.createRendererObject;
pub const registerRendererObject = renderer.registerRendererObject;
var rendAllocator: std.mem.Allocator = undefined;
pub fn getAllocator() std.mem.Allocator {
return rendAllocator;

View File

@ -30,7 +30,10 @@ pub const Renderer = struct {
uploads: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCopyPass) void }) = .{},
uploadCleanup: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
postRenders: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer, *gpu.GPURenderPass) void }) = .{},
destroys: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque) void }) = .{},
preDraws: std.ArrayListUnmanaged(struct { ptr: *anyopaque, func: *const fn (*anyopaque, *gpu.GPUCommandBuffer) void }) = .{},
depthTexture: *gpu.GPUTexture = undefined,
@ -51,12 +54,34 @@ pub const Renderer = struct {
return self;
}
pub fn registerRendererObject(self: *@This(), T: type) !*T {
// pub fn createRendererObjectArgs(self: *@This(), T: type) !*T {
// registers a pre-existing render object, does not add to destroys
pub fn registerRendererObject(self: *@This(), T: type, object: *anyopaque) !void {
if (@hasDecl(T, "onUpload")) {
try self.uploads.append(self.allocator, .{ .ptr = object, .func = T.onUpload });
}
if (@hasDecl(T, "onUploadCleanup")) {
try self.uploadCleanup.append(self.allocator, .{ .ptr = object, .func = T.onUploadCleanup });
}
if (@hasDecl(T, "postRender")) {
try self.postRenders.append(self.allocator, .{ .ptr = object, .func = T.postRender });
}
if (@hasDecl(T, "onPreDraw")) {
try self.preDraws.append(self.allocator, .{ .ptr = object, .func = T.onPreDraw });
}
}
pub fn createRendererObject(self: *@This(), T: type) !*T {
const object = try T.create(self.device, self.allocator, .{});
try self.uploads.append(self.allocator, .{ .ptr = object, .func = T.onUpload });
try self.uploadCleanup.append(self.allocator, .{ .ptr = object, .func = T.onUploadCleanup });
try self.registerRendererObject(T, object);
try self.destroys.append(self.allocator, .{ .ptr = object, .func = T.destroy });
return object;
}
@ -94,7 +119,7 @@ pub const Renderer = struct {
try self.createMeshPipeline();
try self.createDepthTexture();
self.meshPool = try self.registerRendererObject(MeshPool);
self.meshPool = try self.createRendererObject(MeshPool);
}
pub fn discoverFormats(self: *@This()) !void {
@ -345,6 +370,10 @@ pub const Renderer = struct {
self.frameUploads();
try self.uploadUniforms(cmd);
for (self.preDraws.items) |interface| {
interface.func(interface.ptr, cmd);
}
var swapchainTexture: *gpu.GPUTexture = undefined;
if (cmd.waitAndAcquireGPUSwapchainTexture(self.window, &swapchainTexture, null, null)) {
var targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroes(gpu.GPUColorTargetInfo);
@ -391,6 +420,10 @@ pub const Renderer = struct {
}
}
for (self.postRenders.items) |interface| {
interface.func(interface.ptr, cmd, renderpass);
}
// renderpass.drawGPUPrimitives(3, 1, 0, 0);
renderpass.endGPURenderPass();
@ -465,6 +498,14 @@ pub fn setActiveCamera(camera: ?*rend.CameraComponent) void {
gRenderer.activeCamera = camera;
}
pub fn createRendererObject(comptime T: type) !*T {
return try gRenderer.createRendererObject(T);
}
pub fn registerRendererObject(comptime T: type, object: *anyopaque) !void {
return try gRenderer.registerRendererObject(T, object);
}
pub const getMesh = mesh_pool.getMesh;
pub const getMeshByName = mesh_pool.getMeshByName;

View File

@ -12,6 +12,11 @@ pub fn build(b: *std.Build) void {
.root_source_file = b.path("src/cimgui.zig"),
});
mod.addIncludePath(b.path("cimgui/imgui"));
mod.addIncludePath(b.path("cimgui/SDL/include"));
mod.addIncludePath(b.path("cimplot"));
mod.addIncludePath(b.path("cimplot/implot"));
const cimgui = b.addStaticLibrary(.{
.name = "cimgui",
.target = target,
@ -34,7 +39,7 @@ pub fn build(b: *std.Build) void {
.root = b.path("cimgui/imgui"),
.files = &[_][]const u8{
"cimgui.cpp",
// "cimgui_compat.cpp", replace with cimgui_compat_sdlgpu
"cimgui_compat.cpp", // replace with cimgui_compat_sdlgpu
"imgui.cpp",
"imgui_demo.cpp",
"imgui_draw.cpp",

View File

@ -0,0 +1,55 @@
#include "imgui.h"
#include "imgui_impl_sdl3.h"
#include "imgui_impl_sdlgpu3.h"
#include <stdio.h> // printf, fprintf
#include <stdlib.h> // abort
extern "C" void Imgui_SDL3_Init(SDL_Window* window, SDL_GPUDevice* gpu_device)
{
ImGui::CreateContext();
ImGuiIO& io = ImGui::GetIO(); (void)io;
io.ConfigFlags |= ImGuiConfigFlags_NavEnableKeyboard; // Enable Keyboard Controls
io.ConfigFlags |= ImGuiConfigFlags_NavEnableGamepad; // Enable Gamepad Controls
io.ConfigFlags |= ImGuiConfigFlags_DockingEnable; // Enable Docking
io.ConfigFlags |= ImGuiConfigFlags_ViewportsEnable; // Enable Multi-Viewport / Platform Windows
// Setup Dear ImGui style
ImGui::StyleColorsDark();
//ImGui::StyleColorsLight();
// When viewports are enabled we tweak WindowRounding/WindowBg so platform windows can look identical to regular ones.
ImGuiStyle& style = ImGui::GetStyle();
if (io.ConfigFlags & ImGuiConfigFlags_ViewportsEnable)
{
style.WindowRounding = 0.0f;
style.Colors[ImGuiCol_WindowBg].w = 1.0f;
}
// Setup Platform/Renderer backends
ImGui_ImplSDL3_InitForSDLGPU(window);
ImGui_ImplSDLGPU3_InitInfo init_info = {};
init_info.Device = gpu_device;
init_info.ColorTargetFormat = SDL_GetGPUSwapchainTextureFormat(gpu_device, window);
init_info.MSAASamples = SDL_GPU_SAMPLECOUNT_1;
ImGui_ImplSDLGPU3_Init(&init_info);}
extern "C" void Imgui_SDL3_ProcessEvent(SDL_Event* Event)
{
ImGui_ImplSDL3_ProcessEvent(Event);
}
extern "C" void Imgui_SDL3_NewFrame()
{
ImGui_ImplSDLGPU3_NewFrame();
ImGui_ImplSDL3_NewFrame();
}
extern "C" void ImGui_SDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass, SDL_GPUGraphicsPipeline* pipeline)
{
ImGui_ImplSDLGPU3_RenderDrawData(draw_data, command_buffer, render_pass, nullptr);
}
extern "C" void Imgui_SDL3_PrepareRender(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer)
{
Imgui_ImplSDLGPU3_PrepareDrawData(draw_data, command_buffer);
}

16
lib/cimgui/cimgui/imgui/cimgui_compat.h vendored Normal file
View File

@ -0,0 +1,16 @@
#pragma once
#include <SDL3/SDL.h>
#if __cplusplus
extern "C"{
#endif
void Imgui_SDL3_Init(SDL_Window* window, SDL_GPUDevice* gpu_device);
void Imgui_SDL3_ProcessEvent(SDL_Event* Event);
void Imgui_SDL3_NewFrame();
void ImGui_SDLGPU3_RenderDrawData(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer, SDL_GPURenderPass* render_pass);
void Imgui_SDL3_PrepareRender(ImDrawData* draw_data, SDL_GPUCommandBuffer* command_buffer);
#if __cplusplus
}
#endif

View File

@ -28,11 +28,11 @@ typedef struct ImVector_ImS64 {int Size;int Capacity;ImS64* Data;} ImVector_ImS6
typedef struct ImVector_ImS8 {int Size;int Capacity;ImS8* Data;} ImVector_ImS8;
typedef struct ImVector_ImU16 {int Size;int Capacity;ImU16* Data;} ImVector_ImU16;
// typedef struct ImVector_ImU16 {int Size;int Capacity;ImU16* Data;} ImVector_ImU16;
typedef struct ImVector_ImU64 {int Size;int Capacity;ImU64* Data;} ImVector_ImU64;
typedef struct ImVector_ImU8 {int Size;int Capacity;ImU8* Data;} ImVector_ImU8;
// typedef struct ImVector_ImU8 {int Size;int Capacity;ImU8* Data;} ImVector_ImU8;
struct ImPlotContext;
typedef int ImAxis;

File diff suppressed because it is too large Load Diff

View File

@ -118,6 +118,10 @@ pub fn tick(self: *@This(), dt: f64) void {
scene.getPosRot().position = scene.getPosRot().position.add(vector.fmul(self.cameraSpeed * fdt));
// core.engine_log(" camera position >> {any}", .{scene.getPosRot().position});
}
var show: bool = true;
ig.showDemoWindow(&show);
}
pub fn deinit(self: *@This()) void {
@ -138,5 +142,6 @@ const std = @import("std");
const backlog = @import("Backlog");
const assets = backlog.assets;
const core = backlog.core;
const ig = backlog.imgui.api;
const rend = backlog.rend;
const script = core.script;