ranim_render/graph/
mod.rs

1use std::ops::{Deref, DerefMut};
2
3pub mod view;
4
5pub mod clear;
6pub use clear::*;
7
8pub mod oit_resolve;
9pub use oit_resolve::*;
10
11use variadics_please::all_tuples;
12
13use crate::{
14    RenderContext,
15    primitives::viewport::ViewportGpuPacket,
16    resource::Handle,
17    utils::collections::{Graph, TypeBinnedVec},
18};
19
20slotmap::new_key_type! { pub struct GlobalRenderNodeKey; }
21/// Global render graph is something executed globally, which is, NOT per-view.
22///
23/// For per-view's render graph see [`view::ViewRenderGraph`].
24#[derive(Default)]
25pub struct GlobalRenderGraph {
26    inner: Graph<GlobalRenderNodeKey, Box<dyn AnyGlobalRenderNodeTrait + Send + Sync>>,
27}
28
29impl Deref for GlobalRenderGraph {
30    type Target = Graph<GlobalRenderNodeKey, Box<dyn AnyGlobalRenderNodeTrait + Send + Sync>>;
31    fn deref(&self) -> &Self::Target {
32        &self.inner
33    }
34}
35
36impl DerefMut for GlobalRenderGraph {
37    fn deref_mut(&mut self) -> &mut Self::Target {
38        &mut self.inner
39    }
40}
41
42impl GlobalRenderGraph {
43    pub fn new() -> Self {
44        Self::default()
45    }
46    pub fn insert_node(
47        &mut self,
48        node: impl AnyGlobalRenderNodeTrait + Send + Sync + 'static,
49    ) -> GlobalRenderNodeKey {
50        self.inner.insert_node(Box::new(node))
51    }
52}
53
54impl AnyGlobalRenderNodeTrait for GlobalRenderGraph {
55    fn exec(
56        &self,
57        #[cfg(not(feature = "profiling"))] encoder: &mut wgpu::CommandEncoder,
58        #[cfg(feature = "profiling")] encoder: &mut wgpu_profiler::Scope<'_, wgpu::CommandEncoder>,
59        render_ctx: RenderContext,
60    ) {
61        self.iter().for_each(|n| {
62            n.exec(encoder, render_ctx);
63        });
64    }
65}
66
67pub trait AnyGlobalRenderNodeTrait {
68    fn exec(
69        &self,
70        #[cfg(not(feature = "profiling"))] encoder: &mut wgpu::CommandEncoder,
71        #[cfg(feature = "profiling")] scope: &mut wgpu_profiler::Scope<'_, wgpu::CommandEncoder>,
72        render_ctx: RenderContext,
73    );
74}
75impl<T: GlobalRenderNodeTrait> AnyGlobalRenderNodeTrait for T {
76    fn exec(
77        &self,
78        #[cfg(not(feature = "profiling"))] encoder: &mut wgpu::CommandEncoder,
79        #[cfg(feature = "profiling")] encoder: &mut wgpu_profiler::Scope<'_, wgpu::CommandEncoder>,
80        render_ctx: RenderContext,
81    ) {
82        self.run(
83            encoder,
84            <Self as GlobalRenderNodeTrait>::Query::query(render_ctx.render_packets),
85            render_ctx,
86        );
87    }
88}
89
90pub trait GlobalRenderNodeTrait {
91    type Query: RenderPacketsQuery;
92    fn run(
93        &self,
94        #[cfg(not(feature = "profiling"))] encoder: &mut wgpu::CommandEncoder,
95        #[cfg(feature = "profiling")] encoder: &mut wgpu_profiler::Scope<'_, wgpu::CommandEncoder>,
96        render_packets: <Self::Query as RenderPacketsQuery>::Output<'_>,
97        render_ctx: RenderContext,
98    );
99}
100
101pub trait RenderPacketsQuery {
102    type Output<'s>;
103    fn query(store: &RenderPackets) -> Self::Output<'_>;
104}
105
106/// A marker trait to make compiler happy.
107pub trait RenderPacketMark {}
108impl RenderPacketMark for ViewportGpuPacket {}
109
110impl<T: RenderPacketMark + Send + Sync + 'static> RenderPacketsQuery for T {
111    type Output<'s> = &'s [Handle<T>];
112    fn query(store: &RenderPackets) -> Self::Output<'_> {
113        store.get()
114    }
115}
116
117impl RenderPacketsQuery for () {
118    type Output<'s> = ();
119    fn query(_store: &RenderPackets) -> Self::Output<'_> {}
120}
121
122macro_rules! impl_tuple_render_packet_query {
123    ($($T:ident),*) => {
124        impl<$($T: RenderPacketMark + Send + Sync + 'static,)*> RenderPacketsQuery for ($($T,)*) {
125            type Output<'s> = ($(&'s [Handle<$T>],)*);
126            fn query(store: &RenderPackets) -> Self::Output<'_> {
127                ($(store.get::<$T>(),)*)
128            }
129        }
130    };
131}
132
133all_tuples!(impl_tuple_render_packet_query, 1, 16, T);
134
135/// A type-erased container of [`Handle`]s for render packets.
136///
137/// Its inner is a [`TypeBinnedVec`].
138#[derive(Default)]
139pub struct RenderPackets {
140    inner: TypeBinnedVec,
141}
142
143impl RenderPackets {
144    #[inline]
145    pub fn get<T: RenderPacketMark + Send + Sync + 'static>(&self) -> &[Handle<T>] {
146        self.inner.get_row::<Handle<T>>()
147    }
148    #[inline]
149    pub fn extend<T: RenderPacketMark + Send + Sync + 'static>(
150        &mut self,
151        packets: impl IntoIterator<Item = Handle<T>>,
152    ) {
153        self.inner.extend(packets);
154    }
155    #[inline]
156    pub fn push<T: RenderPacketMark + Send + Sync + 'static>(&mut self, packet: Handle<T>) {
157        self.inner.push(packet);
158    }
159    #[inline]
160    pub fn clear(&mut self) {
161        self.inner.clear();
162    }
163}