//! ---------------------------------------------------- //! 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); } }, } }