#[doc(hidden)]
#[macro_export]
macro_rules! gfx_pipeline_inner {
{
$( $field:ident: $ty:ty, )*
} => {
use $crate::pso::{DataLink, DataBind, Descriptor, InitError, RawDataSet, AccessInfo};
#[derive(Clone, Debug, PartialEq)]
pub struct Data<R: $crate::Resources> {
$( pub $field: <$ty as DataBind<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> $crate::pso::PipelineInit for Init<'a> {
type Meta = Meta;
fn link_to<'s>(&self, desc: &mut Descriptor, info: &'s $crate::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::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<R: $crate::Resources> $crate::pso::PipelineData<R> for Data<R> {
type Meta = Meta;
fn bake_to(&self,
out: &mut RawDataSet<R>,
meta: &Self::Meta,
man: &mut $crate::handle::Manager<R>,
access: &mut AccessInfo<R>) {
$(
meta.$field.bind_to(out, &self.$field, man, access);
)*
}
}
}
}
#[macro_export]
macro_rules! gfx_pipeline_base {
($module:ident {
$( $field:ident: $ty:ty, )*
}) => {
#[allow(missing_docs)]
pub mod $module {
#[allow(unused_imports)]
use super::*;
#[allow(unused_imports)]
use super::gfx;
gfx_pipeline_inner!{ $(
$field: $ty,
)*}
}
}
}
#[macro_export]
macro_rules! gfx_pipeline {
($module:ident {
$( $field:ident: $ty:ty = $value:expr, )*
}) => {
#[allow(missing_docs)]
pub mod $module {
#[allow(unused_imports)]
use super::*;
#[allow(unused_imports)]
use super::gfx;
gfx_pipeline_inner!{ $(
$field: $ty,
)*}
pub fn new() -> Init<'static> {
Init {
$( $field: $value, )*
}
}
}
}
}