190 lines
5.5 KiB
Zig
190 lines
5.5 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,
|
|
screenBuffers: ScreenBuffers,
|
|
|
|
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,
|
|
|
|
tempDrawCommand: std.ArrayListUnmanaged(DrawCommand) = .{},
|
|
|
|
const DrawCommand = union(enum(u8)) {
|
|
rect: struct {
|
|
ssboIndex: u32,
|
|
},
|
|
text: struct {
|
|
ssboIndex: u32,
|
|
},
|
|
};
|
|
|
|
const SsboBuffer = struct {
|
|
buffer: *gpu.GPUBuffer,
|
|
staging: *gpu.GPUTransferBuffer,
|
|
|
|
pub fn init(device: *gpu.GPUDevice, elementSize: u32, count: u32) @This() {
|
|
var self: @This() = undefined;
|
|
|
|
{
|
|
const bci = gpu.GPUBufferCreateInfo{
|
|
.size = elementSize * count,
|
|
.usage = .{
|
|
.bufferusageGraphicsStorageRead = true,
|
|
},
|
|
};
|
|
self.buffer = device.createGPUBuffer(&bci);
|
|
}
|
|
|
|
{
|
|
const bci = gpu.GPUTransferBufferCreateInfo{
|
|
.usage = .transferbufferusageUpload,
|
|
.size = elementSize * count,
|
|
};
|
|
|
|
self.staging = device.createGPUTransferBuffer(&bci);
|
|
}
|
|
return self;
|
|
}
|
|
};
|
|
|
|
const ScreenBuffers = struct {
|
|
text: SsboBuffer,
|
|
rect: SsboBuffer,
|
|
|
|
pub fn init(device: *gpu.GPUDevice) @This() {
|
|
return .{
|
|
.rect = SsboBuffer.init(device, @sizeOf(rect_frag.Scene), 4096),
|
|
.text = 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),
|
|
.screenBuffers = undefined,
|
|
};
|
|
|
|
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);
|
|
|
|
self.screenBuffers = ScreenBuffers.init(ctx.device);
|
|
}
|
|
|
|
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");
|