NYXGFX/src/gfx.zig
2026-08-11 21:26:15 +01:00

253 lines
7 KiB
Zig

//! ----------------------------------------------------
//! Low cortisol graphics
//! ----------------------------------------------------
// --- # ---
const std = @import("std");
const gtl = @import("gtl");
const vk = @import("vulkan");
const common = @import("rhi/root.zig");
const Handle = gtl.Handle;
const Self = @This();
// --- CONFIGS ---
const PipelineConfig = common.PipelineConfig;
const BufferUsage = common.BufferUsage;
// --- HANDLES ---
const Window = @import("rhi/root.zig").Window;
const Adapter = common.Adapter;
const Device = common.Device;
const Buffer = common.Buffer;
const Surface = common.Surface;
const Swapchain = common.Swapchain;
const Shader = common.Shader;
const Pipeline = common.Pipeline;
// --- RHI ---
const VulkanRHI = @import("rhi/vulkan/vulkan.zig");
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Backend = enum { vulkan };
/// ----------------------------------------------------
/// ----------------------------------------------------
const BackendCTX = union(Backend) {
vulkan: VulkanRHI,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Config = struct {
app_name: []const u8 = "NYXGFX",
engine_name: []const u8 = "NYX",
enable_validation: bool = true,
window: Window,
backend: Backend = .vulkan,
};
//
// FIELDS
//
ctx: BackendCTX,
config: Config,
alloc: std.mem.Allocator,
io: std.Io,
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn init(
config: Config,
alloc: std.mem.Allocator,
io: std.Io,
) !Self {
const backend_ctx: BackendCTX = switch (config.backend) {
.vulkan => .{ .vulkan = try .init(config, alloc, io) },
};
return .{
.config = config,
.ctx = backend_ctx,
.alloc = alloc,
.io = io,
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn deinit(self: *Self) void {
switch (self.ctx) {
.vulkan => |*v| v.deinit(),
}
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createAdapter(self: *Self) !Handle(Adapter) {
return try switch (self.ctx) {
.vulkan => |*v| v.createAdapter(),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createDevice(
self: *Self,
adapter: Handle(Adapter),
surface: Handle(Surface),
) !Handle(Device) {
return try switch (self.ctx) {
.vulkan => |*v| v.createDevice(adapter, surface),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn destroyDevice(self: *Self, device: Handle(Device)) !void {
try switch (self.ctx) {
.vulkan => |*v| v.destroyDevice(device),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createBuffer(
self: *Self,
value: anytype,
usage: BufferUsage,
adapter: Handle(Adapter),
device: Handle(Device),
) !Buffer {
const size = @sizeOf(@TypeOf(value));
const handle = try switch (self.ctx) {
.vulkan => |*v| v.createBuffer(size, usage, .exclusive, adapter, device),
};
var buffer: Buffer = .{
.handle = handle,
.device = device,
.gfx = self,
};
try buffer.set(value);
return buffer;
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createSurface(self: *Self) !Handle(Surface) {
return try switch (self.ctx) {
.vulkan => |*v| v.createSurface(),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createSwapchain(
self: *Self,
adapter: Handle(Adapter),
device: Handle(Device),
surface: Handle(Surface),
) !Handle(Swapchain) {
return try switch (self.ctx) {
.vulkan => |*v| v.createSwapchain(adapter, device, surface),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createShader(
self: *Self,
vert_spv_path: []const u8,
frag_spv_path: []const u8,
device: Handle(Device),
) !Handle(Shader) {
return try switch (self.ctx) {
.vulkan => |*v| v.createShader(vert_spv_path, frag_spv_path, device),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn createPipeline(self: *Self, config: PipelineConfig) !Pipeline {
return .{
.handle = try switch (self.ctx) {
.vulkan => |*v| v.createPipeline(config),
},
.device = config.device,
.gfx = self,
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn beginFrame(
self: *Self,
swapchain: Handle(Swapchain),
device: Handle(Device),
) !void {
try switch (self.ctx) {
.vulkan => |*v| v.beginFrame(swapchain, device),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn endFrame(
self: *Self,
swapchain: Handle(Swapchain),
device: Handle(Device),
) !void {
try switch (self.ctx) {
.vulkan => |*v| v.endFrame(swapchain, device),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn beginRendering(
self: *Self,
swapchain: Handle(Swapchain),
) !void {
try switch (self.ctx) {
.vulkan => |*v| v.beginRendering(swapchain),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn endRendering(
self: *Self,
swapchain: Handle(Swapchain),
) !void {
try switch (self.ctx) {
.vulkan => |*v| v.endRendering(swapchain),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn draw(self: *Self, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) !void {
try switch (self.ctx) {
.vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance),
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn drawIndexed(self: *Self, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32) !void {
switch (self.ctx) {
.vulkan => |*v| {
const frame = v.currentFrame();
if (frame.cmd_buf) |cmd| {
vk.vkCmdDrawIndexed(cmd, index_count, instance_count, first_index, vertex_offset, first_instance);
}
},
}
}