NYXGFX/src/rhi/common.zig

482 lines
12 KiB
Zig

//! ----------------------------------------------------
//! Shared Handles and Configs across every backend
//! ----------------------------------------------------
const vk = @import("vulkan");
const gtl = @import("gtl");
const Gfx = @import("../gfx.zig");
const Handle = gtl.Handle;
pub const Backend = enum { vulkan };
pub const VKAPIVersion = enum {
v1_0,
v1_1,
v1_2,
v1_3,
v1_4,
};
pub const VK11Features = struct {
shader_draw_parameters: bool = true,
};
pub const VK13Features = struct {
dynamic_rendering: bool = true,
synchronization2: bool = true,
};
pub const VK14Features = struct {
dynamic_rendering_local_read: bool = true,
};
pub const DeviceType = enum {
discrete,
integrated,
software,
};
pub const VKInstanceConfig = struct {
api_version: VKAPIVersion = .v1_3,
vk_11_features: VK11Features = .{},
vk_13_features: VK13Features = .{},
vk_14_features: VK14Features = .{},
};
pub const InstanceConfig = union(Backend) {
vulkan: VKInstanceConfig,
};
//
// RAW
//
pub const RawInstance = union(Backend) {
vulkan: *vk.VkInstance_T,
};
pub const RawFrame = union(Backend) {
vulkan: struct {
cmd_buf: *vk.VkCommandBuffer_T,
image_index: u32 = 0,
image_available: *vk.VkSemaphore_T,
fence: *vk.VkFence_T,
},
};
pub const RawAdapter = union(Backend) {
vulkan: *vk.VkPhysicalDevice_T,
};
pub const RawDevice = union(Backend) {
vulkan: struct {
device: *vk.VkDevice_T,
graphics_queue: *vk.VkQueue_T,
present_queue: *vk.VkQueue_T,
},
};
pub const RawBuffer = union(Backend) {
vulkan: *vk.VkBuffer_T,
};
pub const RawShader = union(Backend) {
vulkan: *vk.VkShaderModule_T,
};
pub const RawPipeline = union(Backend) {
vulkan: struct {
pipeline: *vk.VkPipeline_T,
descriptor_pool: *vk.VkDescriptorPool_T,
},
};
//
// INFOS
//
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const AdapterInfo = struct {
name: [256]u8,
gpu_type: DeviceType,
device_id: u32,
vendor_id: u32,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
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 AdapterConfig = struct {
device_type: DeviceType = .discrete,
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,
size: u32,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const CompareOp = enum {
never,
less,
equal,
less_equal,
greater,
not_equal,
greater_equal,
always,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const DepthFormat = enum {
d16_unorm,
d24_unorm_s8,
d32_sfloat,
};
/// ----------------------------------------------------
/// TODO: Mabe mabe use this for slang shader
/// ----------------------------------------------------
pub const ShaderDescriptor = struct {
shaders: []const Handle(Shader),
vert_entry_point_name: ?[]const u8 = null,
frag_entry_point_name: ?[]const u8 = null,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const PipelineConfig = struct {
vert_shader: Handle(Shader),
frag_shader: Handle(Shader),
vert_entry_point_name: ?[]const u8 = null,
frag_entry_point_name: ?[]const u8 = null,
swapchain: Handle(Swapchain),
device: Handle(Device),
vertex_binding: ?VertexBinding = null,
vertex_attributes: []const VertexAttribute = &.{},
uniforms: []const UniformDesc = &.{},
textures: []const Handle(Texture) = &.{},
topology: enum {
triangle_list,
line_list,
} = .triangle_list,
cull_mode: enum {
front_and_back,
front,
back,
none,
} = .back,
front_face: enum {
ccw,
cw,
} = .ccw,
blend_mode: enum {
none,
alpha,
} = .none,
depth_format: ?DepthFormat = null,
depth_test: bool = true,
depth_write: bool = true,
depth_compare: CompareOp = .less,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Pass = struct {
swapchain: Handle(Swapchain),
gfx: *Gfx,
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn end(self: *const Pass) void {
switch ((self.gfx.getBackend() catch return).*) {
.vulkan => |*v| v.endPass(self.swapchain),
}
}
/// ----------------------------------------------------
/// ----------------------------------------------------
pub fn draw(self: *const Pass, vertex_count: u32, instance_count: u32, first_vertex: u32, first_instance: u32) void {
switch ((self.gfx.getBackend() catch return).*) {
.vulkan => |*v| v.draw(vertex_count, instance_count, first_vertex, first_instance),
}
}
/// ----------------------------------------------------
/// ----------------------------------------------------
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.getBackend() catch return).*) {
.vulkan => |*v| v.drawIndexed(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 },
/// Optional texture to render into instead of the swapchain image
render_target: ?Handle(Texture) = null,
depth_enabled: bool = false,
depth_format: DepthFormat = .d32_sfloat,
depth_load_op: LoadOp = .clear,
depth_store_op: StoreOp = .dont_care,
clear_depth: f32 = 1.0,
clear_stencil: u8 = 0,
load_op: LoadOp = .clear,
store_op: StoreOp = .store,
width: ?u32 = null,
height: ?u32 = null,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const BufferUsage = enum {
vertex,
index,
image,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const BufferSharingMode = enum {
exclusive,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const PixelFormat = enum {
rgba8_unorm,
rgba8_srgb,
bgra8_unorm,
bgra8_srgb,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const Filter = enum {
nearest,
linear,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const MipmapMode = enum {
nearest,
linear,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const AddressMode = enum {
repeat,
mirrored_repeat,
clamp_to_edge,
clamp_to_border,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const ImageUsage = enum {
texture,
render_target,
depth,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const ImageConfig = struct {
/// Read a file from disk with `stb_image`
path: ?[]const u8 = null,
/// Raw pixel bytes (overrides `path`)
data: ?[]const u8 = null,
/// Required for `.data`. `null` = use source dimensions
size: ?[2]u32 = null,
vertical_flip: bool = false,
format: PixelFormat = .rgba8_srgb,
usage: ImageUsage = .texture,
mip_levels: u32 = 1,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const SamplerConfig = struct {
min_filter: Filter = .linear,
mag_filter: Filter = .linear,
mipmap_mode: MipmapMode = .linear,
address_u: AddressMode = .repeat,
address_v: AddressMode = .repeat,
address_w: AddressMode = .repeat,
max_anisotropy: f32 = 1.0,
max_lod: f32 = 0,
};
/// ----------------------------------------------------
/// ----------------------------------------------------
pub const TextureConfig = struct {
image: ImageConfig = .{},
sampler: SamplerConfig = .{},
};
//
// HANDLE TYPES
//
pub const Instance = struct {};
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 ((try self.gfx.getBackend()).*) {
.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 ((try self.gfx.getBackend()).*) {
.vulkan => |*v| try v.bindBuffer(self.handle),
}
}
};
pub const Image = struct {};
pub const ImageView = struct {};
pub const Sampler = struct {};
pub const Texture = 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 ((try self.gfx.getBackend()).*) {
.vulkan => |*v| v.bindPipeline(self.handle),
};
}
pub fn setUniform(self: *const Pipeline, name: []const u8, value: anytype) !void {
try switch ((try self.gfx.getBackend()).*) {
.vulkan => |*v| v.setUniform(self.handle, name, value),
};
}
};