NYXGFX/src/gfx.zig

254 lines
7 KiB
Zig
Raw Normal View History

2026-08-09 14:17:49 +01:00
//! ----------------------------------------------------
//! Low cortisol graphics
//! ----------------------------------------------------
2026-08-11 21:06:28 +01:00
// --- # ---
2026-08-09 14:17:49 +01:00
const std = @import("std");
const gtl = @import("gtl");
const vk = @import("vulkan");
2026-08-11 21:06:28 +01:00
const common = @import("rhi/root.zig");
const Handle = gtl.Handle;
const Self = @This();
// --- CONFIGS ---
const PipelineConfig = common.PipelineConfig;
const BufferUsage = common.BufferUsage;
2026-08-09 14:17:49 +01:00
2026-08-11 21:06:28 +01:00
// --- HANDLES ---
2026-08-09 14:17:49 +01:00
const Window = @import("rhi/root.zig").Window;
2026-08-11 21:06:28 +01:00
const Adapter = common.Adapter;
const Device = common.Device;
const Buffer = common.Buffer;
const Surface = common.Surface;
const Swapchain = common.Swapchain;
2026-08-09 14:17:49 +01:00
2026-08-11 21:06:28 +01:00
const Shader = common.Shader;
const Pipeline = common.Pipeline;
2026-08-09 14:17:49 +01:00
2026-08-11 21:06:28 +01:00
// --- RHI ---
const VulkanRHI = @import("rhi/vulkan/vulkan.zig");
2026-08-09 14:17:49 +01:00
/// ----------------------------------------------------
/// ----------------------------------------------------
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,
2026-08-11 21:06:28 +01:00
2026-08-09 14:17:49 +01:00
alloc: std.mem.Allocator,
2026-08-11 21:06:28 +01:00
io: std.Io,
2026-08-09 14:17:49 +01:00
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn init(
config: Config,
alloc: std.mem.Allocator,
2026-08-11 21:06:28 +01:00
io: std.Io,
2026-08-09 14:17:49 +01:00
) !Self {
const backend_ctx: BackendCTX = switch (config.backend) {
2026-08-11 21:06:28 +01:00
.vulkan => .{ .vulkan = try .init(config, alloc, io) },
2026-08-09 14:17:49 +01:00
};
return .{
.config = config,
.ctx = backend_ctx,
.alloc = alloc,
2026-08-11 21:06:28 +01:00
.io = io,
2026-08-09 14:17:49 +01:00
};
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn deinit(self: *Self) void {
switch (self.ctx) {
.vulkan => |*v| v.deinit(),
}
}
2026-08-11 21:06:28 +01:00
/// ----------------------------------------------------
/// ----------------------------------------------------
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);
}
},
}
}