use super::super::Handle;
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GpuBackendType {
Auto = 0,
OpenGL = 1,
Vulkan = 2,
Metal = 3,
DirectX11 = 4,
DirectX12 = 5,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GpuFormat {
Rgba8 = 0,
Bgra8 = 1,
Rgb8 = 2,
R8 = 3,
Rgba16f = 4,
Rgba32f = 5,
}
impl GpuFormat {
pub fn bytes_per_pixel(&self) -> usize {
match self {
GpuFormat::Rgba8 | GpuFormat::Bgra8 => 4,
GpuFormat::Rgb8 => 3,
GpuFormat::R8 => 1,
GpuFormat::Rgba16f => 8,
GpuFormat::Rgba32f => 16,
}
}
pub fn components(&self) -> usize {
match self {
GpuFormat::Rgba8 | GpuFormat::Bgra8 | GpuFormat::Rgba16f | GpuFormat::Rgba32f => 4,
GpuFormat::Rgb8 => 3,
GpuFormat::R8 => 1,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum GpuBlendMode {
#[default]
Normal = 0,
Multiply = 1,
Screen = 2,
Overlay = 3,
Darken = 4,
Lighten = 5,
ColorDodge = 6,
ColorBurn = 7,
HardLight = 8,
SoftLight = 9,
Difference = 10,
Exclusion = 11,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GpuBufferUsage {
Vertex = 0,
Index = 1,
Uniform = 2,
Storage = 3,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash)]
pub enum GpuShaderType {
Vertex = 0,
Fragment = 1,
Compute = 2,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum GpuFilter {
Nearest = 0,
#[default]
Linear = 1,
}
#[repr(C)]
#[derive(Debug, Clone, Copy, PartialEq, Eq, Hash, Default)]
pub enum GpuWrap {
#[default]
ClampToEdge = 0,
Repeat = 1,
MirroredRepeat = 2,
}
#[derive(Debug)]
pub struct GpuTexture {
pub native_handle: u64,
pub width: u32,
pub height: u32,
pub format: GpuFormat,
pub min_filter: GpuFilter,
pub mag_filter: GpuFilter,
pub wrap_s: GpuWrap,
pub wrap_t: GpuWrap,
pub backend: GpuBackendType,
}
impl GpuTexture {
pub fn new(width: u32, height: u32, format: GpuFormat, backend: GpuBackendType) -> Self {
Self {
native_handle: 0,
width,
height,
format,
min_filter: GpuFilter::Linear,
mag_filter: GpuFilter::Linear,
wrap_s: GpuWrap::ClampToEdge,
wrap_t: GpuWrap::ClampToEdge,
backend,
}
}
pub fn size_bytes(&self) -> usize {
(self.width as usize) * (self.height as usize) * self.format.bytes_per_pixel()
}
}
#[derive(Debug)]
pub struct GpuShader {
pub native_handle: u64,
pub name: String,
pub backend: GpuBackendType,
}
impl GpuShader {
pub fn new(name: impl Into<String>, backend: GpuBackendType) -> Self {
Self {
native_handle: 0,
name: name.into(),
backend,
}
}
}
#[derive(Debug)]
pub struct GpuBuffer {
pub native_handle: u64,
pub size: usize,
pub usage: GpuBufferUsage,
pub backend: GpuBackendType,
}
impl GpuBuffer {
pub fn new(size: usize, usage: GpuBufferUsage, backend: GpuBackendType) -> Self {
Self {
native_handle: 0,
size,
usage,
backend,
}
}
}
#[derive(Debug, Clone)]
pub struct GpuCapabilities {
pub max_texture_size: u32,
pub max_texture_units: u32,
pub compute_shaders: bool,
pub geometry_shaders: bool,
pub tessellation: bool,
pub max_msaa_samples: u32,
pub float_textures: bool,
pub instancing: bool,
pub vram_mb: u32,
pub device_name: String,
pub vendor_name: String,
pub driver_version: String,
}
impl Default for GpuCapabilities {
fn default() -> Self {
Self {
max_texture_size: 4096,
max_texture_units: 8,
compute_shaders: false,
geometry_shaders: false,
tessellation: false,
max_msaa_samples: 1,
float_textures: false,
instancing: false,
vram_mb: 0,
device_name: String::new(),
vendor_name: String::new(),
driver_version: String::new(),
}
}
}
#[derive(Debug, Clone)]
pub struct GpuRenderPass {
pub color_attachments: Vec<Handle>,
pub depth_attachment: Handle,
pub clear_color: [f32; 4],
pub clear_depth: f32,
pub clear_color_enabled: bool,
pub clear_depth_enabled: bool,
}
impl Default for GpuRenderPass {
fn default() -> Self {
Self {
color_attachments: Vec::new(),
depth_attachment: 0,
clear_color: [1.0, 1.0, 1.0, 1.0],
clear_depth: 1.0,
clear_color_enabled: true,
clear_depth_enabled: true,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct GpuViewport {
pub x: f32,
pub y: f32,
pub width: f32,
pub height: f32,
pub min_depth: f32,
pub max_depth: f32,
}
impl GpuViewport {
pub fn new(x: f32, y: f32, width: f32, height: f32) -> Self {
Self {
x,
y,
width,
height,
min_depth: 0.0,
max_depth: 1.0,
}
}
}
#[repr(C)]
#[derive(Debug, Clone, Copy, Default)]
pub struct GpuScissor {
pub x: i32,
pub y: i32,
pub width: u32,
pub height: u32,
}
#[derive(Debug, Clone)]
pub enum GpuError {
BackendNotAvailable(GpuBackendType),
InitializationFailed(String),
ShaderCompilationFailed(String),
OutOfMemory,
InvalidOperation(String),
NotSupported(String),
DeviceLost,
Other(String),
}
impl std::fmt::Display for GpuError {
fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
match self {
GpuError::BackendNotAvailable(b) => write!(f, "GPU backend {:?} not available", b),
GpuError::InitializationFailed(s) => write!(f, "GPU initialization failed: {}", s),
GpuError::ShaderCompilationFailed(s) => write!(f, "Shader compilation failed: {}", s),
GpuError::OutOfMemory => write!(f, "Out of GPU memory"),
GpuError::InvalidOperation(s) => write!(f, "Invalid GPU operation: {}", s),
GpuError::NotSupported(s) => write!(f, "GPU feature not supported: {}", s),
GpuError::DeviceLost => write!(f, "GPU device lost"),
GpuError::Other(s) => write!(f, "GPU error: {}", s),
}
}
}
impl std::error::Error for GpuError {}
pub type GpuResult<T> = Result<T, GpuError>;