Backlog/engine/ui/src/sgpu/papyrusSgpu.zig

134 lines
4.1 KiB
Zig

pub const papyrus = @import("papyrus");
const core = @import("core");
const rend = @import("rend");
const std = @import("std");
const sdl = @import("sdl3");
const gpu = sdl.gpu;
allocator: std.mem.Allocator,
runtime: *papyrus.PapyrusRuntime,
screenContext: *papyrus.Context,
quadMesh: ?rend.IndexedMesh = null,
quadMeshName: core.Name,
stringArena: std.heap.ArenaAllocator,
drawList: papyrus.DrawList,
first: bool = true,
rectPipeline: *gpu.GPUGraphicsPipeline = undefined,
// textPipeline: *gpu.GPUGraphicsPipeline = undefined,
pub var NeonObjectTable: core.EngineObjectVTable = core.EngineObjectVTable.from(@This(), "ui.runtime");
pub fn create(allocator: std.mem.Allocator) !*@This() {
const self: *@This() = try allocator.create(@This());
core.engine_logs("UI module started");
self.* = .{
.allocator = allocator,
.screenContext = undefined,
.runtime = try papyrus.PapyrusRuntime.create(allocator),
.stringArena = std.heap.ArenaAllocator.init(allocator),
.quadMeshName = core.MakeName("m_screenPlane"),
.drawList = papyrus.DrawList.init(allocator),
};
self.screenContext = try self.runtime.addContext();
return self;
}
pub fn setup(self: *@This()) !void {
core.graphics_log("imgui startup", .{});
try rend.registerRendererObject(@This(), self);
}
pub fn destroy(self: *@This()) void {
self.screenContext.destroy();
self.runtime.destroy();
self.allocator.destroy(self);
}
pub fn createTextPipeline() !void {}
pub fn createRectPipeline(self: *@This()) !void {
const ctx = rend.context();
const vertex = try ctx.loadShader("rect.vert", rect_vert.LoadArgs);
const fragment = try ctx.loadShader("rect.frag", rect_frag.LoadArgs);
var pci = std.mem.zeroes(gpu.GPUGraphicsPipelineCreateInfo);
pci.vertex_shader = vertex;
pci.fragment_shader = fragment;
var attributes = try ctx.generateVertexAttributeList();
defer attributes.deinit();
pci.vertex_input_state = .{
.num_vertex_buffers = 1,
.vertex_buffer_descriptions = &[_]gpu.GPUVertexBufferDescription{
.{ .slot = 0, .pitch = @sizeOf(rend.MeshVertex), .input_rate = .vertexinputrateVertex, .instance_step_rate = 0 },
},
.num_vertex_attributes = @intCast(attributes.items.len),
.vertex_attributes = @ptrCast(attributes.items.ptr),
};
pci.target_info.num_color_targets = 1;
pci.target_info.color_target_descriptions = &[_]gpu.GPUColorTargetDescription{
.{
.format = ctx.swapchainTargetFormat,
.blend_state = std.mem.zeroes(gpu.GPUColorTargetBlendState),
},
};
pci.rasterizer_state.fill_mode = .fillmodeFill;
self.rectPipeline = ctx.device.createGPUGraphicsPipeline(&pci);
}
pub fn postRender(p: *anyopaque, cmd: *gpu.GPUCommandBuffer) void {
const self: *@This() = @ptrCast(@alignCast(p));
if (self.quadMesh == null) {
self.quadMesh = rend.getMeshByName(&self.quadMeshName);
}
self.drawToTarget(self.screenContext, rend.context().state.swapchainTargetTexture.?);
_ = cmd;
}
pub fn drawToTarget(self: *@This(), ctx: *papyrus.Context, targetTexture: *gpu.GPUTexture) void {
ctx.makeDrawList(&self.drawList, &self.stringArena) catch return;
if (self.first) {
self.first = false;
for (self.drawList.items) |item| {
core.engine_log("{any}", .{item});
}
}
const cmd = rend.context().state.cmd.?;
const targetInfo: gpu.GPUColorTargetInfo = std.mem.zeroInit(gpu.GPUColorTargetInfo, .{
.texture = targetTexture,
.load_op = .loadopLoad,
.store_op = .storeopStore,
});
const pass = cmd.beginGPURenderPass(&targetInfo, 1, null);
pass.bindGPUVertexBuffers(1, &.{ .buffer = rend.context().meshPool.vertexBuffer, .offset = 0 }, 1);
pass.bindGPUIndexBuffer(&.{ .buffer = rend.context().meshPool.indexBuffer, .offset = 0 }, .indexelementsize32bit);
for (self.drawList.items) |item| {
switch (item.primitive) {
.Rect => {},
.Text => {},
}
}
pass.endGPURenderPass();
}
pub const rect_frag = @import("rect.frag");
pub const rect_vert = @import("rect.vert");