Files
yawn/renderer/src/render_graph/contracts.rs
T

451 lines
12 KiB
Rust

#[derive(Clone, Copy, Debug, PartialEq, Eq, Hash, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum SemanticType {
MeshData,
Texture,
Bool,
F32,
U32,
Vec2,
Vec3,
Vec4,
Mat2,
Mat3,
Mat4,
U32x16,
LocalAabb,
}
impl SemanticType {
pub const fn is_virtual(self) -> bool {
!matches!(self, Self::MeshData | Self::Texture)
}
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum ExecutionClass {
Source,
Expression,
Render,
Frame,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub enum FullscreenPolicy {
Copy,
HdrSameExtent,
BloomExtract,
BloomComposite,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub struct InputCardinality {
pub min: u8,
pub max: u8,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(rename_all = "snake_case")]
pub enum InputDefaultPolicy {
None,
ParameterLiteral,
CompilerTexture,
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(tag = "kind", content = "types", rename_all = "snake_case")]
pub enum TypeConstraint {
Exact(SemanticType),
OneOf(&'static [SemanticType]),
}
#[derive(Clone, Copy, Debug, PartialEq, Eq, serde::Serialize)]
#[serde(tag = "kind", rename_all = "snake_case")]
pub enum InputRole {
SemanticRead,
UniformRead,
StorageRead,
IndirectRead,
SampledTexture,
ColorTarget { location: u32 },
DepthTarget,
Expression,
}
#[derive(Clone, Copy, Debug, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct InputSocketContract {
pub name: &'static str,
pub accepted: TypeConstraint,
pub cardinality: InputCardinality,
pub default_policy: InputDefaultPolicy,
pub role: InputRole,
}
#[derive(Clone, Copy, Debug, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct OutputSocketContract {
pub name: &'static str,
pub semantic_type: SemanticType,
}
#[derive(Clone, Debug, serde::Serialize)]
#[serde(rename_all = "camelCase")]
pub struct Contract {
pub key: &'static str,
pub version: u32,
pub execution: ExecutionClass,
pub inputs: &'static [InputSocketContract],
pub outputs: &'static [OutputSocketContract],
pub inherently_observable: bool,
#[serde(skip)]
pub fullscreen_policy: Option<FullscreenPolicy>,
}
impl Contract {
pub const fn is_raster_draw(&self) -> bool {
matches!(self.execution, ExecutionClass::Render) && self.fullscreen_policy.is_none()
}
}
use SemanticType::*;
const R: InputCardinality = InputCardinality { min: 1, max: 1 };
const O: InputCardinality = InputCardinality { min: 0, max: 1 };
const V: InputCardinality = InputCardinality { min: 0, max: 8 };
const fn i(
name: &'static str,
ty: SemanticType,
cardinality: InputCardinality,
role: InputRole,
) -> InputSocketContract {
let default_policy = match (cardinality.min, cardinality.max) {
(_, 2..) => InputDefaultPolicy::None,
(1, _) => InputDefaultPolicy::None,
_ => match role {
InputRole::ColorTarget { .. } | InputRole::DepthTarget => {
InputDefaultPolicy::CompilerTexture
}
_ => InputDefaultPolicy::ParameterLiteral,
},
};
InputSocketContract {
name,
accepted: TypeConstraint::Exact(ty),
cardinality,
default_policy,
role,
}
}
const fn o(name: &'static str, semantic_type: SemanticType) -> OutputSocketContract {
OutputSocketContract {
name,
semantic_type,
}
}
const NONE_I: &[InputSocketContract] = &[];
const NONE_O: &[OutputSocketContract] = &[];
const MESH_O: &[OutputSocketContract] = &[
o("mesh", MeshData),
o("type", U32x16),
o("localAabb", LocalAabb),
];
const TEXTURE_O: &[OutputSocketContract] = &[o("texture", Texture)];
const RASTER_I: &[InputSocketContract] = &[
i("mesh", MeshData, R, InputRole::SemanticRead),
i("predicate", Bool, O, InputRole::Expression),
i(
"colorTarget",
Texture,
O,
InputRole::ColorTarget { location: 0 },
),
i("depthTarget", Texture, O, InputRole::DepthTarget),
];
const RASTER_O: &[OutputSocketContract] = &[o("color", Texture), o("depth", Texture)];
const CULL_I: &[InputSocketContract] = &[
i("mesh", MeshData, R, InputRole::Expression),
i("localAabb", LocalAabb, R, InputRole::Expression),
];
const CULL_O: &[OutputSocketContract] = &[o("isFrustumCulled", Bool)];
const COPY_I: &[InputSocketContract] = &[
i("source", Texture, R, InputRole::SampledTexture),
i(
"colorTarget",
Texture,
R,
InputRole::ColorTarget { location: 0 },
),
];
const BLOOM_I: &[InputSocketContract] = &[
i("source", Texture, R, InputRole::SampledTexture),
i("bloom", Texture, R, InputRole::SampledTexture),
i(
"colorTarget",
Texture,
R,
InputRole::ColorTarget { location: 0 },
),
];
const COLOR_O: &[OutputSocketContract] = &[o("color", Texture)];
const FRAME_I: &[InputSocketContract] = &[i("color", Texture, R, InputRole::SampledTexture)];
macro_rules! ins { ($($n:literal:$t:ident),*) => { &[$(i($n,$t,O,InputRole::Expression)),*] } }
macro_rules! outs { ($($n:literal:$t:ident),*) => { &[$(o($n,$t)),*] } }
macro_rules! c {
($k:literal,$v:expr,$e:ident,$ins:expr,$outs:expr,$obs:expr,$policy:expr) => {
Contract {
key: $k,
version: $v,
execution: ExecutionClass::$e,
inputs: $ins,
outputs: $outs,
inherently_observable: $obs,
fullscreen_policy: $policy,
}
};
}
macro_rules! ex {
($k:literal,$ins:expr,$outs:expr) => {
c!($k, 1, Expression, $ins, $outs, false, None)
};
}
const BOOL_VARIADIC_I: &[InputSocketContract] = &[i("inputs", Bool, V, InputRole::Expression)];
pub static CONTRACTS: &[Contract] = &[
c!("mesh", 2, Source, NONE_I, MESH_O, false, None),
c!("texture", 2, Source, NONE_I, TEXTURE_O, false, None),
c!("frustum_cull", 2, Expression, CULL_I, CULL_O, false, None),
c!("ground_plane", 1, Render, RASTER_I, RASTER_O, false, None),
c!("gltf_standard", 1, Render, RASTER_I, RASTER_O, false, None),
c!(
"gltf_standard_double_sided",
1,
Render,
RASTER_I,
RASTER_O,
false,
None
),
c!(
"and",
2,
Expression,
BOOL_VARIADIC_I,
outs!("value":Bool),
false,
None
),
c!(
"or",
2,
Expression,
BOOL_VARIADIC_I,
outs!("value":Bool),
false,
None
),
ex!("not", ins!("operand":Bool), outs!("value":Bool)),
c!(
"xor",
2,
Expression,
BOOL_VARIADIC_I,
outs!("value":Bool),
false,
None
),
c!(
"xnor",
2,
Expression,
BOOL_VARIADIC_I,
outs!("value":Bool),
false,
None
),
ex!(
"greater_than_f32",
ins!("left":F32,"right":F32),
outs!("value":Bool)
),
ex!(
"less_than_f32",
ins!("left":F32,"right":F32),
outs!("value":Bool)
),
ex!(
"equals_f32",
ins!("left":F32,"right":F32),
outs!("value":Bool)
),
ex!(
"greater_than_u32",
ins!("left":U32,"right":U32),
outs!("value":Bool)
),
ex!(
"less_than_u32",
ins!("left":U32,"right":U32),
outs!("value":Bool)
),
ex!(
"equals_u32",
ins!("left":U32,"right":U32),
outs!("value":Bool)
),
ex!("separate_vec2", ins!("vector":Vec2), outs!("x":F32,"y":F32)),
ex!("combine_vec2", ins!("x":F32,"y":F32), outs!("vector":Vec2)),
ex!(
"separate_vec3",
ins!("vector":Vec3),
outs!("x":F32,"y":F32,"z":F32)
),
ex!(
"combine_vec3",
ins!("x":F32,"y":F32,"z":F32),
outs!("vector":Vec3)
),
ex!(
"separate_vec4",
ins!("vector":Vec4),
outs!("x":F32,"y":F32,"z":F32,"w":F32)
),
ex!(
"combine_vec4",
ins!("x":F32,"y":F32,"z":F32,"w":F32),
outs!("vector":Vec4)
),
ex!(
"separate_mat2",
ins!("matrix":Mat2),
outs!("column0":Vec2,"column1":Vec2)
),
ex!(
"combine_mat2",
ins!("column0":Vec2,"column1":Vec2),
outs!("matrix":Mat2)
),
ex!(
"separate_mat3",
ins!("matrix":Mat3),
outs!("column0":Vec3,"column1":Vec3,"column2":Vec3)
),
ex!(
"combine_mat3",
ins!("column0":Vec3,"column1":Vec3,"column2":Vec3),
outs!("matrix":Mat3)
),
ex!(
"separate_mat4",
ins!("matrix":Mat4),
outs!("column0":Vec4,"column1":Vec4,"column2":Vec4,"column3":Vec4)
),
ex!(
"combine_mat4",
ins!("column0":Vec4,"column1":Vec4,"column2":Vec4,"column3":Vec4),
outs!("matrix":Mat4)
),
ex!(
"separate_u32x16",
ins!("value":U32x16),
outs!("word0":U32,"word1":U32,"word2":U32,"word3":U32,"word4":U32,"word5":U32,"word6":U32,"word7":U32,"word8":U32,"word9":U32,"word10":U32,"word11":U32,"word12":U32,"word13":U32,"word14":U32,"word15":U32)
),
ex!(
"combine_u32x16",
ins!("word0":U32,"word1":U32,"word2":U32,"word3":U32,"word4":U32,"word5":U32,"word6":U32,"word7":U32,"word8":U32,"word9":U32,"word10":U32,"word11":U32,"word12":U32,"word13":U32,"word14":U32,"word15":U32),
outs!("value":U32x16)
),
ex!(
"separate_u32_bits",
ins!("value":U32),
outs!("bit0":Bool,"bit1":Bool,"bit2":Bool,"bit3":Bool,"bit4":Bool,"bit5":Bool,"bit6":Bool,"bit7":Bool,"bit8":Bool,"bit9":Bool,"bit10":Bool,"bit11":Bool,"bit12":Bool,"bit13":Bool,"bit14":Bool,"bit15":Bool,"bit16":Bool,"bit17":Bool,"bit18":Bool,"bit19":Bool,"bit20":Bool,"bit21":Bool,"bit22":Bool,"bit23":Bool,"bit24":Bool,"bit25":Bool,"bit26":Bool,"bit27":Bool,"bit28":Bool,"bit29":Bool,"bit30":Bool,"bit31":Bool)
),
ex!(
"combine_u32_bits",
ins!("bit0":Bool,"bit1":Bool,"bit2":Bool,"bit3":Bool,"bit4":Bool,"bit5":Bool,"bit6":Bool,"bit7":Bool,"bit8":Bool,"bit9":Bool,"bit10":Bool,"bit11":Bool,"bit12":Bool,"bit13":Bool,"bit14":Bool,"bit15":Bool,"bit16":Bool,"bit17":Bool,"bit18":Bool,"bit19":Bool,"bit20":Bool,"bit21":Bool,"bit22":Bool,"bit23":Bool,"bit24":Bool,"bit25":Bool,"bit26":Bool,"bit27":Bool,"bit28":Bool,"bit29":Bool,"bit30":Bool,"bit31":Bool),
outs!("value":U32)
),
ex!(
"separate_local_aabb",
ins!("value":LocalAabb),
outs!("min":Vec3,"max":Vec3)
),
c!(
"fullscreen_copy",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::Copy)
),
c!(
"color_balance",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!(
"exposure_contrast",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!(
"saturation",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!(
"channel_mixer",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!(
"bloom_extract",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::BloomExtract)
),
c!(
"bloom_blur",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!(
"bloom_composite",
1,
Render,
BLOOM_I,
COLOR_O,
false,
Some(FullscreenPolicy::BloomComposite)
),
c!(
"luminance_edge",
1,
Render,
COPY_I,
COLOR_O,
false,
Some(FullscreenPolicy::HdrSameExtent)
),
c!("frame_out", 3, Frame, FRAME_I, NONE_O, true, None),
];
pub fn contract(key: &str) -> Option<&'static Contract> {
CONTRACTS.iter().find(|c| c.key == key)
}