use core::fmt;
use std::error::Error;
use crate::{backend::Image, DataType, ScalarType, VectorSize, VertexAttributes};
use super::{arguments::ArgumentGroupLayout, PixelFormat, Shader, VertexFormat};
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum LoadOp<T> {
Load,
Clear(T),
DontCare,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub enum StoreOp {
Store,
DontCare,
}
#[derive(Clone, Copy, Debug, PartialEq)]
pub struct ClearColor(pub f32, pub f32, pub f32, pub f32);
impl ClearColor {
pub const BLACK: Self = ClearColor(0.0, 0.0, 0.0, 1.0);
pub const TRANSPARENT: Self = ClearColor(0.0, 0.0, 0.0, 0.0);
pub const WHITE: Self = ClearColor(1.0, 1.0, 1.0, 1.0);
pub const RED: Self = ClearColor(1.0, 0.0, 0.0, 1.0);
pub const GREEN: Self = ClearColor(0.0, 1.0, 0.0, 1.0);
pub const BLUE: Self = ClearColor(0.0, 0.0, 1.0, 1.0);
pub const YELLOW: Self = ClearColor(1.0, 1.0, 0.0, 1.0);
pub const CYAN: Self = ClearColor(0.0, 1.0, 1.0, 1.0);
pub const MAGENTA: Self = ClearColor(1.0, 0.0, 1.0, 1.0);
pub const GRAY: Self = ClearColor(0.5, 0.5, 0.5, 1.0);
pub const DARK_GRAY: Self = ClearColor(0.25, 0.25, 0.25, 1.0);
pub const LIGHT_GRAY: Self = ClearColor(0.75, 0.75, 0.75, 1.0);
}
#[derive(Clone, Copy, Debug, PartialEq, Default)]
pub struct ClearDepthStencil {
pub depth: f32,
pub stencil: u32,
}
#[derive(Clone, Copy)]
pub struct AttachmentDesc<'a, T> {
pub image: &'a Image,
pub load: LoadOp<T>,
pub store: StoreOp,
}
impl<'a, T> AttachmentDesc<'a, T> {
pub fn new(image: &'a Image) -> Self {
AttachmentDesc {
image,
load: LoadOp::Load,
store: StoreOp::Store,
}
}
pub fn no_load(mut self) -> Self {
self.load = LoadOp::DontCare;
self
}
pub fn clear(mut self, color: T) -> Self {
self.load = LoadOp::Clear(color);
self
}
pub fn no_store(mut self) -> Self {
self.store = StoreOp::DontCare;
self
}
pub fn load_op(mut self, op: LoadOp<T>) -> Self {
self.load = op;
self
}
pub fn store_op(mut self, op: StoreOp) -> Self {
self.store = op;
self
}
}
impl<'a, T> From<&'a Image> for AttachmentDesc<'a, T> {
fn from(image: &'a Image) -> Self {
AttachmentDesc::new(image)
}
}
#[derive(Clone, Copy, Default)]
pub struct RenderPassDesc<'a> {
pub name: &'a str,
pub color_attachments: &'a [AttachmentDesc<'a, ClearColor>],
pub depth_stencil_attachment: Option<AttachmentDesc<'a, ClearDepthStencil>>,
}
impl<'a> RenderPassDesc<'a> {
pub const fn new() -> Self {
RenderPassDesc {
name: "",
color_attachments: &[],
depth_stencil_attachment: None,
}
}
pub fn name(mut self, name: &'a str) -> Self {
self.name = name;
self
}
pub fn color_attachments(mut self, attachments: &'a [AttachmentDesc<'a, ClearColor>]) -> Self {
self.color_attachments = attachments;
self
}
pub fn depth_stencil_attachment(
mut self,
attachment: AttachmentDesc<'a, ClearDepthStencil>,
) -> Self {
self.depth_stencil_attachment = Some(attachment);
self
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct VertexAttributeDesc {
pub buffer_index: u32,
pub format: VertexFormat,
pub offset: u32,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum VertexStepMode {
Vertex,
Instance { rate: u32 },
Constant,
}
impl Default for VertexStepMode {
fn default() -> Self {
VertexStepMode::Vertex
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct VertexLayoutDesc {
pub stride: u32,
pub step_mode: VertexStepMode,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum PrimitiveTopology {
Point,
Line,
#[default]
Triangle,
}
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct ColorTargetDesc {
pub format: PixelFormat,
pub blend: Option<BlendDesc>,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct BlendDesc {
pub mask: WriteMask,
pub color: Blend,
pub alpha: Blend,
}
impl Default for BlendDesc {
fn default() -> Self {
BlendDesc {
mask: WriteMask::all(),
color: Blend {
op: BlendOp::Add,
src: BlendFactor::One,
dst: BlendFactor::OneMinusSrcAlpha,
},
alpha: Blend {
op: BlendOp::Add,
src: BlendFactor::One,
dst: BlendFactor::OneMinusSrcAlpha,
},
}
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct Blend {
pub op: BlendOp,
pub src: BlendFactor,
pub dst: BlendFactor,
}
bitflags::bitflags! {
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct WriteMask: u8 {
const RED = 0x1;
const GREEN = 0x2;
const BLUE = 0x4;
const ALPHA = 0x8;
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BlendFactor {
Zero,
One,
SrcColor,
OneMinusSrcColor,
SrcAlpha,
OneMinusSrcAlpha,
DstColor,
OneMinusDstColor,
DstAlpha,
OneMinusDstAlpha,
SrcAlphaSaturated,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum BlendOp {
Add,
Subtract,
ReverseSubtract,
Min,
Max,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub struct DepthStencilDesc {
pub format: PixelFormat,
pub write_enabled: bool,
pub compare: CompareFunction,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash)]
pub enum CompareFunction {
Never,
Less,
Equal,
LessEqual,
Greater,
NotEqual,
GreaterEqual,
Always,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum FrontFace {
#[default]
Clockwise,
CounterClockwise,
}
#[derive(Clone, Copy, Debug, Default, PartialEq, Eq, Hash)]
pub enum Culling {
None,
Front,
#[default]
Back,
}
pub struct RenderPipelineDesc<'a> {
pub name: &'a str,
pub vertex_shader: Shader<'a>,
pub vertex_layouts: Vec<VertexLayoutDesc>,
pub vertex_attributes: Vec<VertexAttributeDesc>,
pub primitive_topology: PrimitiveTopology,
pub raster: Option<RasterDesc<'a>>,
pub constants: usize,
pub arguments: &'a [ArgumentGroupLayout<'a>],
}
pub struct RasterDesc<'a> {
pub fragment_shader: Option<Shader<'a>>,
pub color_targets: Vec<ColorTargetDesc>,
pub depth_stencil: Option<DepthStencilDesc>,
pub front_face: FrontFace,
pub culling: Culling,
}
#[derive(Debug)]
pub enum PipelineError {
InvalidShaderEntry,
Failure(String),
}
impl fmt::Display for PipelineError {
fn fmt(&self, f: &mut fmt::Formatter<'_>) -> fmt::Result {
match self {
PipelineError::InvalidShaderEntry => write!(f, "Invalid shader entry point"),
PipelineError::Failure(msg) => write!(f, "Failure: {}", msg),
}
}
}
impl Error for PipelineError {}
pub trait VertexBinding {
const LAYOUT: VertexLayoutDesc;
type AttributeDescs;
fn descs(buffer_index: u32) -> Self::AttributeDescs;
}