#[macro_export]
macro_rules! pipeline {{
$module:ident {
$( $field:ident: $ty:ty, )*
}
} => {
pub mod $module {
#![allow(non_snake_case, unused_imports)]
use $crate::{Global, RenderTarget, TextureSampler};
use $crate::gfx::pso::{DataLink, DataBind, Descriptor, InitError, RawDataSet, AccessInfo, PipelineInit, PipelineData};
#[derive(Clone, Debug, PartialEq)]
pub struct Data<'a> {
$( pub $field: &'a <$ty as DataBind<$crate::R>>::Data, )*
}
#[derive(Clone, Debug, Hash, PartialEq)]
pub struct Meta {
$( $field: $ty, )*
}
#[derive(Clone, Debug, PartialEq)]
pub struct Init<'a> {
$( pub $field: <$ty as DataLink<'a>>::Init, )*
}
impl<'a> PipelineInit for Init<'a> {
type Meta = Meta;
fn link_to<'s>(&self, desc: &mut Descriptor, info: &'s $crate::gfx::ProgramInfo)
-> ::std::result::Result<Self::Meta, InitError<&'s str>>
{
let mut meta = Meta {
$( $field: <$ty as DataLink<'a>>::new(), )*
};
let mut _num_vb = 0;
$(
if let Some(d) = meta.$field.link_vertex_buffer(_num_vb, &self.$field) {
assert!(meta.$field.is_active());
desc.vertex_buffers[_num_vb as usize] = Some(d);
_num_vb += 1;
}
)*
for at in &info.vertex_attributes {
$(
match meta.$field.link_input(at, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.attributes[at.slot as usize] = Some(d);
continue;
},
Some(Err(fm)) => return Err(
InitError::VertexImport(&at.name, Some(fm))
),
None => (),
}
)*
return Err(InitError::VertexImport(&at.name, None));
}
for cb in &info.constant_buffers {
$(
match meta.$field.link_constant_buffer(cb, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.constant_buffers[cb.slot as usize] = Some(d);
continue;
},
Some(Err(e)) => return Err(
InitError::ConstantBuffer(&cb.name, Some(e))
),
None => (),
}
)*
return Err(InitError::ConstantBuffer(&cb.name, None));
}
for gc in &info.globals {
$(
match meta.$field.link_global_constant(gc, &self.$field) {
Some(Ok(())) => {
assert!(meta.$field.is_active());
continue;
},
Some(Err(e)) => return Err(
InitError::GlobalConstant(&gc.name, Some(e))
),
None => (),
}
)*
return Err(InitError::GlobalConstant(&gc.name, None));
}
for srv in &info.textures {
$(
match meta.$field.link_resource_view(srv, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.resource_views[srv.slot as usize] = Some(d);
continue;
},
Some(Err(_)) => return Err(
InitError::ResourceView(&srv.name, Some(()))
),
None => (),
}
)*
return Err(InitError::ResourceView(&srv.name, None));
}
for uav in &info.unordereds {
$(
match meta.$field.link_unordered_view(uav, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.unordered_views[uav.slot as usize] = Some(d);
continue;
},
Some(Err(_)) => return Err(
InitError::UnorderedView(&uav.name, Some(()))
),
None => (),
}
)*
return Err(InitError::UnorderedView(&uav.name, None));
}
for sm in &info.samplers {
$(
match meta.$field.link_sampler(sm, &self.$field) {
Some(d) => {
assert!(meta.$field.is_active());
desc.samplers[sm.slot as usize] = Some(d);
continue;
},
None => (),
}
)*
return Err(InitError::Sampler(&sm.name, None));
}
for out in &info.outputs {
$(
match meta.$field.link_output(out, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.color_targets[out.slot as usize] = Some(d);
continue;
},
Some(Err(fm)) => return Err(
InitError::PixelExport(&out.name, Some(fm))
),
None => (),
}
)*
return Err(InitError::PixelExport(&out.name, None));
}
if !info.knows_outputs {
use $crate::gfx::shade::core as s;
let mut out = s::OutputVar {
name: String::new(),
slot: 0,
base_type: s::BaseType::F32,
container: s::ContainerType::Vector(4),
};
$(
match meta.$field.link_output(&out, &self.$field) {
Some(Ok(d)) => {
assert!(meta.$field.is_active());
desc.color_targets[out.slot as usize] = Some(d);
out.slot += 1;
},
Some(Err(fm)) => return Err(
InitError::PixelExport(&"!known", Some(fm))
),
None => (),
}
)*
}
for _ in 0..1 {
$(
if let Some(d) = meta.$field.link_depth_stencil(&self.$field) {
assert!(meta.$field.is_active());
desc.depth_stencil = Some(d);
}
if meta.$field.link_scissor() {
assert!(meta.$field.is_active());
desc.scissor = true;
}
)*
}
Ok(meta)
}
}
impl<'a> PipelineData<$crate::R> for Data<'a> {
type Meta = Meta;
fn bake_to(&self,
out: &mut RawDataSet<$crate::R>,
meta: &Self::Meta,
man: &mut $crate::gfx::handle::Manager<$crate::R>,
access: &mut AccessInfo<$crate::R>) {
$(
meta.$field.bind_to(out, self.$field, man, access);
)*
}
}
impl Default for Init<'static> {
fn default() -> Self {
Init {
$( $field: stringify!($field), )*
}
}
}
pub fn new() -> Init<'static> {
Default::default()
}
}
}}