1pub mod present;
5pub mod render;
6
7use {
8 crate::{
9 command::{Capability, Families, Family, FamilyId, Fence, Queue, Submission, Submittable},
10 factory::{Factory, UploadError},
11 frame::Frames,
12 graph::GraphContext,
13 wsi::SwapchainError,
14 BufferId, ImageId, NodeId,
15 },
16 rendy_core::hal::{queue::QueueFamilyId, Backend},
17};
18
19#[derive(Clone, Copy, Debug)]
23pub struct BufferAccess {
24 pub access: rendy_core::hal::buffer::Access,
26
27 pub usage: rendy_core::hal::buffer::Usage,
30
31 pub stages: rendy_core::hal::pso::PipelineStage,
33}
34
35#[derive(Clone, Debug)]
37pub struct BufferBarrier {
38 pub states: std::ops::Range<rendy_core::hal::buffer::State>,
40
41 pub stages: std::ops::Range<rendy_core::hal::pso::PipelineStage>,
43
44 pub families: Option<std::ops::Range<QueueFamilyId>>,
46}
47
48#[derive(Clone, Debug)]
53pub struct NodeBuffer {
54 pub id: BufferId,
56
57 pub range: std::ops::Range<u64>,
59
60 pub acquire: Option<BufferBarrier>,
64
65 pub release: Option<BufferBarrier>,
69}
70
71#[derive(Clone, Copy, Debug)]
73pub struct ImageAccess {
74 pub access: rendy_core::hal::image::Access,
76
77 pub usage: rendy_core::hal::image::Usage,
80
81 pub layout: rendy_core::hal::image::Layout,
86
87 pub stages: rendy_core::hal::pso::PipelineStage,
89}
90
91#[derive(Clone, Debug)]
95pub struct ImageBarrier {
96 pub states: std::ops::Range<rendy_core::hal::image::State>,
98
99 pub stages: std::ops::Range<rendy_core::hal::pso::PipelineStage>,
101
102 pub families: Option<std::ops::Range<QueueFamilyId>>,
104}
105
106#[derive(Clone, Debug)]
108pub struct NodeImage {
109 pub id: ImageId,
111
112 pub range: rendy_core::hal::image::SubresourceRange,
114
115 pub layout: rendy_core::hal::image::Layout,
117
118 pub clear: Option<rendy_core::hal::command::ClearValue>,
120
121 pub acquire: Option<ImageBarrier>,
125
126 pub release: Option<ImageBarrier>,
130}
131
132pub trait NodeSubmittable<'a, B: Backend> {
134 type Submittable: Submittable<B> + 'a;
136
137 type Submittables: IntoIterator<Item = Self::Submittable>;
139}
140
141pub trait Node<B: Backend, T: ?Sized>:
151 for<'a> NodeSubmittable<'a, B> + std::fmt::Debug + Sized + Sync + Send + 'static
152{
153 type Capability: Capability;
156
157 fn run<'a>(
160 &'a mut self,
161 ctx: &GraphContext<B>,
162 factory: &Factory<B>,
163 aux: &T,
164 frames: &'a Frames<B>,
165 ) -> <Self as NodeSubmittable<'a, B>>::Submittables;
166
167 unsafe fn dispose(self, factory: &mut Factory<B>, aux: &T);
173}
174
175pub trait NodeDesc<B: Backend, T: ?Sized>: std::fmt::Debug + Sized + 'static {
179 type Node: Node<B, T>;
181
182 fn builder(self) -> DescBuilder<B, T, Self> {
184 DescBuilder::new(self)
185 }
186
187 fn buffers(&self) -> Vec<BufferAccess> {
189 Vec::new()
190 }
191
192 fn images(&self) -> Vec<ImageAccess> {
194 Vec::new()
195 }
196
197 fn build<'a>(
208 self,
209 ctx: &GraphContext<B>,
210 factory: &mut Factory<B>,
211 family: &mut Family<B>,
212 queue: usize,
213 aux: &T,
214 buffers: Vec<NodeBuffer>,
215 images: Vec<NodeImage>,
216 ) -> Result<Self::Node, NodeBuildError>;
217}
218
219pub trait DynNode<B: Backend, T: ?Sized>: std::fmt::Debug + Sync + Send {
221 unsafe fn run<'a>(
224 &mut self,
225 ctx: &GraphContext<B>,
226 factory: &Factory<B>,
227 queue: &mut Queue<B>,
228 aux: &T,
229 frames: &Frames<B>,
230 waits: &[(&'a B::Semaphore, rendy_core::hal::pso::PipelineStage)],
231 signals: &[&'a B::Semaphore],
232 fence: Option<&mut Fence<B>>,
233 );
234
235 unsafe fn dispose(self: Box<Self>, factory: &mut Factory<B>, aux: &T);
241}
242
243impl<B, T, N> DynNode<B, T> for (N,)
244where
245 B: Backend,
246 T: ?Sized,
247 N: Node<B, T>,
248{
249 unsafe fn run<'a>(
250 &mut self,
251 ctx: &GraphContext<B>,
252 factory: &Factory<B>,
253 queue: &mut Queue<B>,
254 aux: &T,
255 frames: &Frames<B>,
256 waits: &[(&'a B::Semaphore, rendy_core::hal::pso::PipelineStage)],
257 signals: &[&'a B::Semaphore],
258 fence: Option<&mut Fence<B>>,
259 ) {
260 let submittables = Node::run(&mut self.0, ctx, factory, aux, frames);
261 queue.submit(
262 Some(
263 Submission::new()
264 .submits(submittables)
265 .wait(waits.iter().cloned())
266 .signal(signals.iter().cloned()),
267 ),
268 fence,
269 )
270 }
271
272 unsafe fn dispose(self: Box<Self>, factory: &mut Factory<B>, aux: &T) {
273 N::dispose(self.0, factory, aux);
274 }
275}
276
277#[derive(Debug)]
279pub enum NodeBuildError {
280 Upload(UploadError),
282 QueueFamily(FamilyId),
284 View(rendy_core::hal::image::ViewError),
286 Pipeline(rendy_core::hal::pso::CreationError),
288 Swapchain(SwapchainError),
290 OutOfMemory(rendy_core::hal::device::OutOfMemory),
292}
293
294pub trait NodeBuilder<B: Backend, T: ?Sized>: std::fmt::Debug {
296 fn family(&self, factory: &mut Factory<B>, families: &Families<B>) -> Option<FamilyId>;
298
299 fn buffers(&self) -> Vec<(BufferId, BufferAccess)>;
301
302 fn images(&self) -> Vec<(ImageId, ImageAccess)>;
304
305 fn dependencies(&self) -> Vec<NodeId>;
307
308 fn build<'a>(
310 self: Box<Self>,
311 ctx: &GraphContext<B>,
312 factory: &mut Factory<B>,
313 family: &mut Family<B>,
314 queue: usize,
315 aux: &T,
316 buffers: Vec<NodeBuffer>,
317 images: Vec<NodeImage>,
318 ) -> Result<Box<dyn DynNode<B, T>>, NodeBuildError>;
319}
320
321pub struct DescBuilder<B: Backend, T: ?Sized, N> {
323 desc: N,
324 buffers: Vec<BufferId>,
325 images: Vec<ImageId>,
326 dependencies: Vec<NodeId>,
327 marker: std::marker::PhantomData<fn(B, &T)>,
328}
329
330impl<B, T, N> std::fmt::Debug for DescBuilder<B, T, N>
331where
332 B: Backend,
333 T: ?Sized,
334 N: std::fmt::Debug,
335{
336 fn fmt(&self, fmt: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
337 fmt.debug_struct("DescBuilder")
338 .field("desc", &self.desc)
339 .field("buffers", &self.buffers)
340 .field("images", &self.images)
341 .field("dependencies", &self.dependencies)
342 .finish()
343 }
344}
345
346impl<B, T, N> DescBuilder<B, T, N>
347where
348 B: Backend,
349 T: ?Sized,
350{
351 pub fn new(desc: N) -> Self {
353 DescBuilder {
354 desc,
355 buffers: Vec::new(),
356 images: Vec::new(),
357 dependencies: Vec::new(),
358 marker: std::marker::PhantomData,
359 }
360 }
361 pub fn add_buffer(&mut self, buffer: BufferId) -> &mut Self {
364 self.buffers.push(buffer);
365 self
366 }
367
368 pub fn with_buffer(mut self, buffer: BufferId) -> Self {
371 self.add_buffer(buffer);
372 self
373 }
374
375 pub fn add_image(&mut self, image: ImageId) -> &mut Self {
378 self.images.push(image);
379 self
380 }
381
382 pub fn with_image(mut self, image: ImageId) -> Self {
385 self.add_image(image);
386 self
387 }
388
389 pub fn add_dependency(&mut self, dependency: NodeId) -> &mut Self {
392 self.dependencies.push(dependency);
393 self
394 }
395
396 pub fn with_dependency(mut self, dependency: NodeId) -> Self {
399 self.add_dependency(dependency);
400 self
401 }
402}
403
404impl<B, T, N> NodeBuilder<B, T> for DescBuilder<B, T, N>
405where
406 B: Backend,
407 T: ?Sized,
408 N: NodeDesc<B, T>,
409{
410 fn family(&self, _factory: &mut Factory<B>, families: &Families<B>) -> Option<FamilyId> {
411 families.with_capability::<<N::Node as Node<B, T>>::Capability>()
412 }
413
414 fn buffers(&self) -> Vec<(BufferId, BufferAccess)> {
415 let desc_buffers = self.desc.buffers();
416 assert_eq!(self.buffers.len(), desc_buffers.len());
417
418 self.buffers.iter().cloned().zip(desc_buffers).collect()
419 }
420
421 fn images(&self) -> Vec<(ImageId, ImageAccess)> {
422 let desc_images = self.desc.images();
423 assert_eq!(self.images.len(), desc_images.len());
424
425 self.images.iter().cloned().zip(desc_images).collect()
426 }
427
428 fn dependencies(&self) -> Vec<NodeId> {
429 self.dependencies.clone()
430 }
431
432 fn build<'a>(
433 self: Box<Self>,
434 ctx: &GraphContext<B>,
435 factory: &mut Factory<B>,
436 family: &mut Family<B>,
437 queue: usize,
438 aux: &T,
439 buffers: Vec<NodeBuffer>,
440 images: Vec<NodeImage>,
441 ) -> Result<Box<dyn DynNode<B, T>>, NodeBuildError> {
442 Ok(Box::new((self.desc.build(
443 ctx, factory, family, queue, aux, buffers, images,
444 )?,)))
445 }
446}
447
448pub fn gfx_acquire_barriers<'a, 'b, B: Backend>(
450 ctx: &'a GraphContext<B>,
451 buffers: impl IntoIterator<Item = &'b NodeBuffer>,
452 images: impl IntoIterator<Item = &'b NodeImage>,
453) -> (
454 std::ops::Range<rendy_core::hal::pso::PipelineStage>,
455 Vec<rendy_core::hal::memory::Barrier<'a, B>>,
456) {
457 let mut bstart = rendy_core::hal::pso::PipelineStage::empty();
458 let mut bend = rendy_core::hal::pso::PipelineStage::empty();
459
460 let mut istart = rendy_core::hal::pso::PipelineStage::empty();
461 let mut iend = rendy_core::hal::pso::PipelineStage::empty();
462
463 let barriers: Vec<rendy_core::hal::memory::Barrier<'_, B>> = buffers
464 .into_iter()
465 .filter_map(|buffer| {
466 buffer.acquire.as_ref().map(|acquire| {
467 bstart |= acquire.stages.start;
468 bend |= acquire.stages.end;
469
470 rendy_core::hal::memory::Barrier::Buffer {
471 states: acquire.states.clone(),
472 families: acquire.families.clone(),
473 target: ctx
474 .get_buffer(buffer.id)
475 .expect("Buffer does not exist")
476 .raw(),
477 range: Some(buffer.range.start)..Some(buffer.range.end),
478 }
479 })
480 })
481 .chain(images.into_iter().filter_map(|image| {
482 image.acquire.as_ref().map(|acquire| {
483 istart |= acquire.stages.start;
484 iend |= acquire.stages.end;
485
486 rendy_core::hal::memory::Barrier::Image {
487 states: acquire.states.clone(),
488 families: acquire.families.clone(),
489 target: ctx.get_image(image.id).expect("Image does not exist").raw(),
490 range: image.range.clone(),
491 }
492 })
493 }))
494 .collect();
495
496 (bstart | istart..bend | iend, barriers)
497}
498
499pub fn gfx_release_barriers<'a, B: Backend>(
501 ctx: &'a GraphContext<B>,
502 buffers: impl IntoIterator<Item = &'a NodeBuffer>,
503 images: impl IntoIterator<Item = &'a NodeImage>,
504) -> (
505 std::ops::Range<rendy_core::hal::pso::PipelineStage>,
506 Vec<rendy_core::hal::memory::Barrier<'a, B>>,
507) {
508 let mut bstart = rendy_core::hal::pso::PipelineStage::empty();
509 let mut bend = rendy_core::hal::pso::PipelineStage::empty();
510
511 let mut istart = rendy_core::hal::pso::PipelineStage::empty();
512 let mut iend = rendy_core::hal::pso::PipelineStage::empty();
513
514 let barriers: Vec<rendy_core::hal::memory::Barrier<'_, B>> = buffers
515 .into_iter()
516 .filter_map(|buffer| {
517 buffer.release.as_ref().map(|release| {
518 bstart |= release.stages.start;
519 bend |= release.stages.end;
520
521 rendy_core::hal::memory::Barrier::Buffer {
522 states: release.states.clone(),
523 families: release.families.clone(),
524 target: ctx
525 .get_buffer(buffer.id)
526 .expect("Buffer does not exist")
527 .raw(),
528 range: Some(buffer.range.start)..Some(buffer.range.end),
529 }
530 })
531 })
532 .chain(images.into_iter().filter_map(|image| {
533 image.release.as_ref().map(|release| {
534 istart |= release.stages.start;
535 iend |= release.stages.end;
536
537 rendy_core::hal::memory::Barrier::Image {
538 states: release.states.clone(),
539 families: release.families.clone(),
540 target: ctx.get_image(image.id).expect("Image does not exist").raw(),
541 range: image.range.clone(),
542 }
543 })
544 }))
545 .collect();
546
547 (bstart | istart..bend | iend, barriers)
548}