use {
super::{
AccessType, Binding, Command, Graph, Node, Resource, Subresource, SubresourceRange,
ViewInfo,
},
crate::{
ExecutionPipeline, TimestampQuery,
driver::{
compute::ComputePipeline, graphics::GraphicsPipeline, ray_tracing::RayTracingPipeline,
},
},
std::marker::PhantomData,
};
pub trait Pipeline<'a> {
type Command;
fn bind_cmd(self, _: Command<'a>) -> Self::Command;
}
macro_rules! pipeline {
($variant:ident, $pipeline:ident, $is_fn:ident, $unwrap_fn:ident) => {
paste::paste! {
impl<'a> Pipeline<'a> for $pipeline {
type Command = PipelineCommand<'a, $pipeline>;
fn bind_cmd(self, mut cmd: Command<'a>) -> Self::Command {
{
let cmd = cmd.cmd_mut();
if cmd.expect_last_exec().pipeline.is_some() {
cmd.execs.push(Default::default());
}
cmd.expect_last_exec_mut().pipeline = Some(ExecutionPipeline::$variant(self));
}
Self::Command {
__: PhantomData,
cmd,
}
}
}
impl<'a> Pipeline<'a> for &'a $pipeline {
type Command = PipelineCommand<'a, $pipeline>;
fn bind_cmd(self, mut cmd: Command<'a>) -> Self::Command {
{
let cmd = cmd.cmd_mut();
if cmd.expect_last_exec().pipeline.is_some() {
cmd.execs.push(Default::default());
}
cmd.expect_last_exec_mut().pipeline
= Some(ExecutionPipeline::$variant(self.clone()));
}
Self::Command {
__: PhantomData,
cmd,
}
}
}
impl ExecutionPipeline {
#[allow(unused)]
pub(crate) fn $is_fn(&self) -> bool {
matches!(self, Self::$variant(_))
}
#[allow(unused)]
pub(crate) fn $unwrap_fn(&self) -> &$pipeline {
if let Self::$variant(binding) = self {
&binding
} else {
panic!();
}
}
}
}
};
}
pipeline!(Compute, ComputePipeline, is_compute, unwrap_compute);
pipeline!(Graphics, GraphicsPipeline, is_graphics, unwrap_graphics);
pipeline!(
RayTracing,
RayTracingPipeline,
is_ray_tracing,
unwrap_ray_tracing
);
pub struct PipelineCommand<'c, T> {
pub(super) __: PhantomData<T>,
pub(super) cmd: Command<'c>,
}
#[allow(private_bounds)]
impl<'c, T> PipelineCommand<'c, T> {
pub fn bind_pipeline<P>(self, pipeline: P) -> P::Command
where
P: Pipeline<'c>,
{
pipeline.bind_cmd(self.cmd)
}
pub fn bind_resource<R>(&mut self, resource: R) -> R::Node
where
R: Resource,
{
self.cmd.bind_resource(resource)
}
pub fn write_timestamp(&mut self) -> TimestampQuery {
self.cmd.write_timestamp()
}
pub fn end_cmd(self) -> &'c mut Graph {
self.cmd.end_cmd()
}
pub fn resource<N>(&self, resource_node: N) -> &N::Resource
where
N: Node,
{
self.cmd.resource(resource_node)
}
pub fn resource_access<N>(mut self, resource_node: N, access: AccessType) -> Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.cmd.set_resource_access(resource_node, access);
self
}
pub fn set_resource_access<N>(&mut self, resource_node: N, access: AccessType) -> &mut Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.cmd.set_resource_access(resource_node, access);
self
}
pub fn set_shader_resource_access<N>(
&mut self,
binding: impl Into<Binding>,
resource_node: N,
access: AccessType,
) -> &mut Self
where
N: Node + Subresource,
N::Info: Copy,
SubresourceRange: From<N::Info>,
ViewInfo: From<N::Info>,
{
let subresource = resource_node.info(&self.cmd.graph.resources);
self.set_shader_subresource_access(binding, resource_node, subresource, access)
}
pub fn set_shader_subresource_access<N>(
&mut self,
binding: impl Into<Binding>,
resource_node: N,
subresource: impl Into<N::Info>,
access: AccessType,
) -> &mut Self
where
N: Node + Subresource,
N::Info: Copy,
SubresourceRange: From<N::Info>,
ViewInfo: From<N::Info>,
{
let binding = binding.into();
let subresource = subresource.into();
let node_idx = resource_node.index();
let view_info = subresource.into();
self.cmd.push_subresource_access(
resource_node,
SubresourceRange::from(subresource),
access,
);
#[cfg(feature = "checked")]
{
if let Some(prev) = self.cmd.cmd().expect_last_exec().bindings.get(&binding) {
assert!(
*prev == (node_idx, view_info),
"shader binding {binding:?} already bound to a different resource or view"
);
}
}
self.cmd
.cmd_mut()
.expect_last_exec_mut()
.bindings
.insert(binding, (node_idx, view_info));
self
}
pub fn set_subresource_access<N>(
&mut self,
resource_node: N,
subresource: impl Into<N::Range>,
access: AccessType,
) -> &mut Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.cmd
.set_subresource_access(resource_node, subresource, access);
self
}
pub fn shader_resource_access<N>(
mut self,
binding: impl Into<Binding>,
resource_node: N,
access: AccessType,
) -> Self
where
N: Node + Subresource,
N::Info: Copy,
SubresourceRange: From<N::Info>,
ViewInfo: From<N::Info>,
{
self.set_shader_resource_access(binding, resource_node, access);
self
}
pub fn shader_subresource_access<N>(
mut self,
binding: impl Into<Binding>,
resource_node: N,
subresource: impl Into<N::Info>,
access: AccessType,
) -> Self
where
N: Node + Subresource,
N::Info: Copy,
SubresourceRange: From<N::Info>,
ViewInfo: From<N::Info>,
{
self.set_shader_subresource_access(binding, resource_node, subresource, access);
self
}
pub fn subresource_access<N>(
mut self,
resource_node: N,
subresource: impl Into<N::Range>,
access: AccessType,
) -> Self
where
N: Node + Subresource,
SubresourceRange: From<N::Range>,
{
self.cmd
.set_subresource_access(resource_node, subresource, access);
self
}
}