//! ---------------------------------------------------- //! ---------------------------------------------------- const vk = @import("vulkan"); const gtl = @import("gtl"); const Gfx = @import("../gfx.zig"); const Handle = gtl.Handle; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const Window = union(enum) { win32: struct { hwnd: *anyopaque, hinstance: *anyopaque, }, xcb: struct { connection: *anyopaque, window: u32, }, xlib: struct { display: *anyopaque, window: c_ulong, }, wayland: struct { display: *anyopaque, surface: *anyopaque, }, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const GpuType = enum { any, discrete, integrated, software, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const AdapterConfig = struct { /// Preferred class of GPU /// `.any` disables filtering by class gpu_type: GpuType = .discrete, /// Select the adapter at a specific enumeration index /// `null` picks the first suitable one index: ?u32 = null, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const DeviceConfig = struct { adapter: Handle(Adapter), surface: Handle(Surface), }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const Format = enum { int, float, vec2, vec3, vec4, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const VertexBinding = struct { binding: u32 = 0, stride: u32, input_rate: enum { vertex, instance, } = .vertex, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const VertexAttribute = struct { location: u32, binding: u32 = 0, offset: u32, format: Format, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const UniformDesc = struct { name: []const u8, offset: u32, size: u32, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const PipelineConfig = struct { vert_shader: Handle(Shader), frag_shader: Handle(Shader), swapchain: Handle(Swapchain), device: Handle(Device), vertex_binding: ?VertexBinding = null, vertex_attributes: []const VertexAttribute = &.{}, uniforms: []const UniformDesc = &.{}, topology: enum { triangle_list, line_list, } = .triangle_list, cull_mode: enum { front_and_back, front, back, none, } = .back, front_face: enum { ccw, cw, } = .cw, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const Pass = struct { swapchain: Handle(Swapchain), gfx: *Gfx, pub fn end(self: *const Pass) void { switch (self.gfx.ctx) { .vulkan => |*v| v.endRendering(self.swapchain), } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn draw(self: *const Pass, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void { switch (self.gfx.ctx) { .vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance) catch {}, } } /// ---------------------------------------------------- /// ---------------------------------------------------- pub fn drawIndexed(self: *const Pass, index_count: u32, instance_count: u32, first_index: u32, vertex_offset: i32, first_instance: u32) void { switch (self.gfx.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); } }, } } }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const LoadOp = enum { clear, load, dont_care, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const StoreOp = enum { store, dont_care, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const RenderPassConfig = struct { clear_color: [4]f32 = .{ 0.0, 0.0, 0.0, 1.0 }, load_op: LoadOp = .clear, store_op: StoreOp = .store, width: ?u32 = null, height: ?u32 = null, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const BufferUsage = enum { vertex, index, }; /// ---------------------------------------------------- /// ---------------------------------------------------- pub const BufferSharingMode = enum { exclusive, }; // // HANDLE TYPES // pub const Adapter = struct {}; pub const Device = struct {}; pub const Surface = struct {}; pub const Swapchain = struct {}; pub const Buffer = struct { handle: Handle(Buffer), device: Handle(Device), gfx: *Gfx, pub fn set(self: *const Buffer, value: anytype) !void { switch (self.gfx.ctx) { .vulkan => |*v| { const raw = v.resource.buffers.get(self.handle) orelse return error.BufferNotFound; try raw.set(value, @sizeOf(@TypeOf(value))); }, } } pub fn bind(self: *const Buffer) !void { switch (self.gfx.ctx) { .vulkan => |*v| { const raw = v.resource.buffers.get(self.handle) orelse return error.BufferNotFound; const frame = v.currentFrame(); if (frame.cmd_buf) |cmd| { const buffers = [_]vk.VkBuffer{raw.raw}; const offsets = [_]vk.VkDeviceSize{0}; switch (raw.usage) { .vertex => vk.vkCmdBindVertexBuffers(cmd, 0, 1, &buffers, &offsets), .index => vk.vkCmdBindIndexBuffer(cmd, raw.raw, 0, vk.VK_INDEX_TYPE_UINT32), } } }, } } }; pub const Image = struct {}; pub const ImageView = struct {}; pub const Sampler = struct {}; pub const Shader = struct {}; pub const PipelineLayout = struct {}; pub const Pipeline = struct { handle: Handle(Pipeline), device: Handle(Device), gfx: *Gfx, pub fn bind(self: *const Pipeline) !void { try switch (self.gfx.ctx) { .vulkan => |*v| v.bindPipeline(self.handle), }; } pub fn setUniform(self: *const Pipeline, name: []const u8, value: anytype) !void { try switch (self.gfx.ctx) { .vulkan => |*v| v.setUniform(self.handle, name, value), }; } };