#![allow(
clippy::new_without_default,
clippy::unneeded_field_pattern,
clippy::match_like_matches_macro
)]
#![allow(clippy::manual_strip, clippy::unknown_clippy_lints)]
#![deny(clippy::panic)]
mod arena;
pub mod back;
pub mod front;
pub mod proc;
pub use crate::arena::{Arena, Handle};
use std::{
collections::{HashMap, HashSet},
hash::BuildHasherDefault,
num::NonZeroU32,
};
#[cfg(feature = "deserialize")]
use serde::Deserialize;
#[cfg(feature = "serialize")]
use serde::Serialize;
pub type FastHashMap<K, T> = HashMap<K, T, BuildHasherDefault<fxhash::FxHasher>>;
pub type FastHashSet<K> = HashSet<K, BuildHasherDefault<fxhash::FxHasher>>;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Header {
pub version: (u8, u8, u8),
pub generator: u32,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct EarlyDepthTest {
conservative: Option<ConservativeDepth>,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ConservativeDepth {
GreaterEqual,
LessEqual,
Unchanged,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[allow(missing_docs)]
pub enum ShaderStage {
Vertex,
Fragment,
Compute,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[allow(missing_docs)]
pub enum StorageClass {
Function,
Input,
Output,
Private,
WorkGroup,
Uniform,
Storage,
Handle,
PushConstant,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum BuiltIn {
BaseInstance,
BaseVertex,
ClipDistance,
InstanceIndex,
PointSize,
Position,
VertexIndex,
FragCoord,
FragDepth,
FrontFacing,
SampleIndex,
SampleMaskIn,
SampleMaskOut,
GlobalInvocationId,
LocalInvocationId,
LocalInvocationIndex,
WorkGroupId,
WorkGroupSize,
}
pub type Bytes = u8;
#[repr(u8)]
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum VectorSize {
Bi = 2,
Tri = 3,
Quad = 4,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ScalarKind {
Sint,
Uint,
Float,
Bool,
}
#[repr(u8)]
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ArraySize {
Constant(Handle<Constant>),
Dynamic,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum Interpolation {
Perspective,
Linear,
Flat,
Patch,
Centroid,
Sample,
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct StructMember {
pub name: Option<String>,
pub span: Option<NonZeroU32>,
pub ty: Handle<Type>,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ImageDimension {
D1,
D2,
D3,
Cube,
}
bitflags::bitflags! {
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
#[derive(Default)]
pub struct StorageAccess: u32 {
const LOAD = 0x1;
const STORE = 0x2;
}
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum StorageFormat {
R8Unorm,
R8Snorm,
R8Uint,
R8Sint,
R16Uint,
R16Sint,
R16Float,
Rg8Unorm,
Rg8Snorm,
Rg8Uint,
Rg8Sint,
R32Uint,
R32Sint,
R32Float,
Rg16Uint,
Rg16Sint,
Rg16Float,
Rgba8Unorm,
Rgba8Snorm,
Rgba8Uint,
Rgba8Sint,
Rgb10a2Unorm,
Rg11b10Float,
Rg32Uint,
Rg32Sint,
Rg32Float,
Rgba16Uint,
Rgba16Sint,
Rgba16Float,
Rgba32Uint,
Rgba32Sint,
Rgba32Float,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ImageClass {
Sampled {
kind: ScalarKind,
multi: bool,
},
Depth,
Storage(StorageFormat),
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Type {
pub name: Option<String>,
pub inner: TypeInner,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum TypeInner {
Scalar { kind: ScalarKind, width: Bytes },
Vector {
size: VectorSize,
kind: ScalarKind,
width: Bytes,
},
Matrix {
columns: VectorSize,
rows: VectorSize,
width: Bytes,
},
Pointer {
base: Handle<Type>,
class: StorageClass,
},
Array {
base: Handle<Type>,
size: ArraySize,
stride: Option<NonZeroU32>,
},
Struct {
block: bool,
members: Vec<StructMember>,
},
Image {
dim: ImageDimension,
arrayed: bool,
class: ImageClass,
},
Sampler { comparison: bool },
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Constant {
pub name: Option<String>,
pub specialization: Option<u32>,
pub inner: ConstantInner,
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ScalarValue {
Sint(i64),
Uint(u64),
Float(f64),
Bool(bool),
}
#[derive(Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum ConstantInner {
Scalar {
width: Bytes,
value: ScalarValue,
},
Composite {
ty: Handle<Type>,
components: Vec<Handle<Constant>>,
},
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum Binding {
BuiltIn(BuiltIn),
Location(u32),
Resource { group: u32, binding: u32 },
}
bitflags::bitflags! {
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct GlobalUse: u8 {
const READ = 0x1;
const WRITE = 0x2;
}
}
#[derive(Clone, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct GlobalVariable {
pub name: Option<String>,
pub class: StorageClass,
pub binding: Option<Binding>,
pub ty: Handle<Type>,
pub init: Option<Handle<Constant>>,
pub interpolation: Option<Interpolation>,
pub storage_access: StorageAccess,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct LocalVariable {
pub name: Option<String>,
pub ty: Handle<Type>,
pub init: Option<Handle<Constant>>,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum UnaryOperator {
Negate,
Not,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum BinaryOperator {
Add,
Subtract,
Multiply,
Divide,
Modulo,
Equal,
NotEqual,
Less,
LessEqual,
Greater,
GreaterEqual,
And,
ExclusiveOr,
InclusiveOr,
LogicalAnd,
LogicalOr,
ShiftLeft,
ShiftRight,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum DerivativeAxis {
X,
Y,
Width,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum RelationalFunction {
All,
Any,
IsNan,
IsInf,
IsFinite,
IsNormal,
}
#[derive(Clone, Copy, Debug, Hash, Eq, Ord, PartialEq, PartialOrd)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum MathFunction {
Abs,
Min,
Max,
Clamp,
Cos,
Cosh,
Sin,
Sinh,
Tan,
Tanh,
Acos,
Asin,
Atan,
Atan2,
Ceil,
Floor,
Round,
Fract,
Trunc,
Modf,
Frexp,
Ldexp,
Exp,
Exp2,
Log,
Log2,
Pow,
Dot,
Outer,
Cross,
Distance,
Length,
Normalize,
FaceForward,
Reflect,
Sign,
Fma,
Mix,
Step,
SmoothStep,
Sqrt,
InverseSqrt,
Transpose,
Determinant,
CountOneBits,
ReverseBits,
}
#[derive(Clone, Copy, Debug, PartialEq)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum SampleLevel {
Auto,
Zero,
Exact(Handle<Expression>),
Bias(Handle<Expression>),
Gradient {
x: Handle<Expression>,
y: Handle<Expression>,
},
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum Expression {
Access {
base: Handle<Expression>,
index: Handle<Expression>,
},
AccessIndex {
base: Handle<Expression>,
index: u32,
},
Constant(Handle<Constant>),
Compose {
ty: Handle<Type>,
components: Vec<Handle<Expression>>,
},
FunctionArgument(u32),
GlobalVariable(Handle<GlobalVariable>),
LocalVariable(Handle<LocalVariable>),
Load { pointer: Handle<Expression> },
ImageSample {
image: Handle<Expression>,
sampler: Handle<Expression>,
coordinate: Handle<Expression>,
array_index: Option<Handle<Expression>>,
offset: Option<Handle<Constant>>,
level: SampleLevel,
depth_ref: Option<Handle<Expression>>,
},
ImageLoad {
image: Handle<Expression>,
coordinate: Handle<Expression>,
array_index: Option<Handle<Expression>>,
index: Option<Handle<Expression>>,
},
Unary {
op: UnaryOperator,
expr: Handle<Expression>,
},
Binary {
op: BinaryOperator,
left: Handle<Expression>,
right: Handle<Expression>,
},
Select {
condition: Handle<Expression>,
accept: Handle<Expression>,
reject: Handle<Expression>,
},
Derivative {
axis: DerivativeAxis,
expr: Handle<Expression>,
},
Relational {
fun: RelationalFunction,
argument: Handle<Expression>,
},
Math {
fun: MathFunction,
arg: Handle<Expression>,
arg1: Option<Handle<Expression>>,
arg2: Option<Handle<Expression>>,
},
As {
expr: Handle<Expression>,
kind: ScalarKind,
convert: bool,
},
Call {
function: Handle<Function>,
arguments: Vec<Handle<Expression>>,
},
ArrayLength(Handle<Expression>),
}
pub type Block = Vec<Statement>;
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct SwitchCase {
pub value: i32,
pub body: Block,
pub fall_through: bool,
}
#[derive(Clone, Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub enum Statement {
Block(Block),
If {
condition: Handle<Expression>,
accept: Block,
reject: Block,
},
Switch {
selector: Handle<Expression>,
cases: Vec<SwitchCase>,
default: Block,
},
Loop { body: Block, continuing: Block },
Break,
Continue,
Return { value: Option<Handle<Expression>> },
Kill,
Store {
pointer: Handle<Expression>,
value: Handle<Expression>,
},
}
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct FunctionArgument {
pub name: Option<String>,
pub ty: Handle<Type>,
}
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Function {
pub name: Option<String>,
pub arguments: Vec<FunctionArgument>,
pub return_type: Option<Handle<Type>>,
pub global_usage: Vec<GlobalUse>,
pub local_variables: Arena<LocalVariable>,
pub expressions: Arena<Expression>,
pub body: Block,
}
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct EntryPoint {
pub early_depth_test: Option<EarlyDepthTest>,
pub workgroup_size: [u32; 3],
pub function: Function,
}
#[derive(Debug)]
#[cfg_attr(feature = "serialize", derive(Serialize))]
#[cfg_attr(feature = "deserialize", derive(Deserialize))]
pub struct Module {
pub header: Header,
pub types: Arena<Type>,
pub constants: Arena<Constant>,
pub global_variables: Arena<GlobalVariable>,
pub functions: Arena<Function>,
pub entry_points: FastHashMap<(ShaderStage, String), EntryPoint>,
}