pub mod present;
pub mod render;
use {
crate::{
command::{Capability, Family, FamilyId, Fence, Queue, Submission, Submittable, Supports},
factory::Factory,
frame::Frames,
graph::GraphContext,
util::{rendy_with_metal_backend, rendy_without_metal_backend},
BufferId, ImageId, NodeId,
},
gfx_hal::{queue::QueueFamilyId, Backend},
};
#[derive(Clone, Copy, Debug)]
pub struct BufferAccess {
pub access: gfx_hal::buffer::Access,
pub usage: gfx_hal::buffer::Usage,
pub stages: gfx_hal::pso::PipelineStage,
}
#[derive(Clone, Debug)]
pub struct BufferBarrier {
pub states: std::ops::Range<gfx_hal::buffer::State>,
pub stages: std::ops::Range<gfx_hal::pso::PipelineStage>,
pub families: Option<std::ops::Range<QueueFamilyId>>,
}
#[derive(Clone, Debug)]
pub struct NodeBuffer {
pub id: BufferId,
pub range: std::ops::Range<u64>,
pub acquire: Option<BufferBarrier>,
pub release: Option<BufferBarrier>,
}
#[derive(Clone, Copy, Debug)]
pub struct ImageAccess {
pub access: gfx_hal::image::Access,
pub usage: gfx_hal::image::Usage,
pub layout: gfx_hal::image::Layout,
pub stages: gfx_hal::pso::PipelineStage,
}
#[derive(Clone, Debug)]
pub struct ImageBarrier {
pub states: std::ops::Range<gfx_hal::image::State>,
pub stages: std::ops::Range<gfx_hal::pso::PipelineStage>,
pub families: Option<std::ops::Range<QueueFamilyId>>,
}
#[derive(Clone, Debug)]
pub struct NodeImage {
pub id: ImageId,
pub range: gfx_hal::image::SubresourceRange,
pub layout: gfx_hal::image::Layout,
pub clear: Option<gfx_hal::command::ClearValue>,
pub acquire: Option<ImageBarrier>,
pub release: Option<ImageBarrier>,
}
pub trait NodeSubmittable<'a, B: Backend> {
type Submittable: Submittable<B> + 'a;
type Submittables: IntoIterator<Item = Self::Submittable>;
}
pub trait Node<B: Backend, T: ?Sized>:
for<'a> NodeSubmittable<'a, B> + std::fmt::Debug + Sized + Sync + Send + 'static
{
type Capability: Capability;
type Desc: NodeDesc<B, T, Node = Self>;
fn desc() -> Self::Desc
where
Self::Desc: Default,
{
Default::default()
}
fn builder() -> DescBuilder<B, T, Self::Desc>
where
Self::Desc: Default,
{
Self::desc().builder()
}
fn run<'a>(
&'a mut self,
ctx: &GraphContext<B>,
factory: &Factory<B>,
aux: &T,
frames: &'a Frames<B>,
) -> <Self as NodeSubmittable<'a, B>>::Submittables;
unsafe fn dispose(self, factory: &mut Factory<B>, aux: &T);
}
pub trait NodeDesc<B: Backend, T: ?Sized>: std::fmt::Debug + Sized + 'static {
type Node: Node<B, T>;
fn builder(self) -> DescBuilder<B, T, Self> {
DescBuilder {
desc: self,
buffers: Vec::new(),
images: Vec::new(),
dependencies: Vec::new(),
marker: std::marker::PhantomData,
}
}
fn buffers(&self) -> Vec<BufferAccess> {
Vec::new()
}
fn images(&self) -> Vec<ImageAccess> {
Vec::new()
}
fn build<'a>(
self,
ctx: &GraphContext<B>,
factory: &mut Factory<B>,
family: &mut Family<B>,
queue: usize,
aux: &T,
buffers: Vec<NodeBuffer>,
images: Vec<NodeImage>,
) -> Result<Self::Node, failure::Error>;
}
pub trait DynNode<B: Backend, T: ?Sized>: std::fmt::Debug + Sync + Send {
unsafe fn run<'a>(
&mut self,
ctx: &GraphContext<B>,
factory: &Factory<B>,
queue: &mut Queue<B>,
aux: &T,
frames: &Frames<B>,
waits: &[(&'a B::Semaphore, gfx_hal::pso::PipelineStage)],
signals: &[&'a B::Semaphore],
fence: Option<&mut Fence<B>>,
);
unsafe fn dispose(self: Box<Self>, factory: &mut Factory<B>, aux: &T);
}
impl<B, T, N> DynNode<B, T> for (N,)
where
B: Backend,
T: ?Sized,
N: Node<B, T>,
{
unsafe fn run<'a>(
&mut self,
ctx: &GraphContext<B>,
factory: &Factory<B>,
queue: &mut Queue<B>,
aux: &T,
frames: &Frames<B>,
waits: &[(&'a B::Semaphore, gfx_hal::pso::PipelineStage)],
signals: &[&'a B::Semaphore],
fence: Option<&mut Fence<B>>,
) {
let submittables = Node::run(&mut self.0, ctx, factory, aux, frames);
queue.submit(
Some(
Submission::new()
.submits(submittables)
.wait(waits.iter().cloned())
.signal(signals.iter().cloned()),
),
fence,
)
}
unsafe fn dispose(self: Box<Self>, factory: &mut Factory<B>, aux: &T) {
N::dispose(self.0, factory, aux);
}
}
pub trait NodeBuilder<B: Backend, T: ?Sized>: std::fmt::Debug {
fn family(&self, factory: &mut Factory<B>, families: &[Family<B>]) -> Option<FamilyId>;
fn buffers(&self) -> Vec<(BufferId, BufferAccess)>;
fn images(&self) -> Vec<(ImageId, ImageAccess)>;
fn dependencies(&self) -> Vec<NodeId>;
fn build<'a>(
self: Box<Self>,
ctx: &GraphContext<B>,
factory: &mut Factory<B>,
family: &mut Family<B>,
queue: usize,
aux: &T,
buffers: Vec<NodeBuffer>,
images: Vec<NodeImage>,
) -> Result<Box<dyn DynNode<B, T>>, failure::Error>;
}
#[derive(derivative::Derivative)]
#[derivative(Debug(bound = "N: std::fmt::Debug"))]
pub struct DescBuilder<B: Backend, T: ?Sized, N> {
desc: N,
buffers: Vec<BufferId>,
images: Vec<ImageId>,
dependencies: Vec<NodeId>,
marker: std::marker::PhantomData<fn(B, &T)>,
}
impl<B, T, N> DescBuilder<B, T, N>
where
B: Backend,
T: ?Sized,
{
pub fn add_buffer(&mut self, buffer: BufferId) -> &mut Self {
self.buffers.push(buffer);
self
}
pub fn with_buffer(mut self, buffer: BufferId) -> Self {
self.add_buffer(buffer);
self
}
pub fn add_image(&mut self, image: ImageId) -> &mut Self {
self.images.push(image);
self
}
pub fn with_image(mut self, image: ImageId) -> Self {
self.add_image(image);
self
}
pub fn add_dependency(&mut self, dependency: NodeId) -> &mut Self {
self.dependencies.push(dependency);
self
}
pub fn with_dependency(mut self, dependency: NodeId) -> Self {
self.add_dependency(dependency);
self
}
}
impl<B, T, N> NodeBuilder<B, T> for DescBuilder<B, T, N>
where
B: Backend,
T: ?Sized,
N: NodeDesc<B, T>,
{
fn family(&self, _factory: &mut Factory<B>, families: &[Family<B>]) -> Option<FamilyId> {
families
.iter()
.find(|family| {
Supports::<<N::Node as Node<B, T>>::Capability>::supports(&family.capability())
.is_some()
})
.map(|family| family.id())
}
fn buffers(&self) -> Vec<(BufferId, BufferAccess)> {
let desc_buffers = self.desc.buffers();
assert_eq!(self.buffers.len(), desc_buffers.len());
self.buffers.iter().cloned().zip(desc_buffers).collect()
}
fn images(&self) -> Vec<(ImageId, ImageAccess)> {
let desc_images = self.desc.images();
assert_eq!(self.images.len(), desc_images.len());
self.images.iter().cloned().zip(desc_images).collect()
}
fn dependencies(&self) -> Vec<NodeId> {
self.dependencies.clone()
}
fn build<'a>(
self: Box<Self>,
ctx: &GraphContext<B>,
factory: &mut Factory<B>,
family: &mut Family<B>,
queue: usize,
aux: &T,
buffers: Vec<NodeBuffer>,
images: Vec<NodeImage>,
) -> Result<Box<dyn DynNode<B, T>>, failure::Error> {
Ok(Box::new((self.desc.build(
ctx, factory, family, queue, aux, buffers, images,
)?,)))
}
}
pub fn gfx_acquire_barriers<'a, 'b, B: Backend>(
ctx: &'a GraphContext<B>,
buffers: impl IntoIterator<Item = &'b NodeBuffer>,
images: impl IntoIterator<Item = &'b NodeImage>,
) -> (
std::ops::Range<gfx_hal::pso::PipelineStage>,
Vec<gfx_hal::memory::Barrier<'a, B>>,
) {
let mut bstart = gfx_hal::pso::PipelineStage::empty();
let mut bend = gfx_hal::pso::PipelineStage::empty();
let mut istart = gfx_hal::pso::PipelineStage::empty();
let mut iend = gfx_hal::pso::PipelineStage::empty();
let barriers: Vec<gfx_hal::memory::Barrier<'_, B>> = buffers
.into_iter()
.filter_map(|buffer| {
buffer.acquire.as_ref().map(|acquire| {
bstart |= acquire.stages.start;
bend |= acquire.stages.end;
gfx_hal::memory::Barrier::Buffer {
states: acquire.states.clone(),
families: acquire.families.clone(),
target: ctx
.get_buffer(buffer.id)
.expect("Buffer does not exist")
.raw(),
range: Some(buffer.range.start)..Some(buffer.range.end),
}
})
})
.chain(images.into_iter().filter_map(|image| {
image.acquire.as_ref().map(|acquire| {
istart |= acquire.stages.start;
iend |= acquire.stages.end;
gfx_hal::memory::Barrier::Image {
states: acquire.states.clone(),
families: acquire.families.clone(),
target: ctx.get_image(image.id).expect("Image does not exist").raw(),
range: image.range.clone(),
}
})
}))
.collect();
(bstart | istart..bend | iend, barriers)
}
pub fn gfx_release_barriers<'a, B: Backend>(
ctx: &'a GraphContext<B>,
buffers: impl IntoIterator<Item = &'a NodeBuffer>,
images: impl IntoIterator<Item = &'a NodeImage>,
) -> (
std::ops::Range<gfx_hal::pso::PipelineStage>,
Vec<gfx_hal::memory::Barrier<'a, B>>,
) {
let mut bstart = gfx_hal::pso::PipelineStage::empty();
let mut bend = gfx_hal::pso::PipelineStage::empty();
let mut istart = gfx_hal::pso::PipelineStage::empty();
let mut iend = gfx_hal::pso::PipelineStage::empty();
let barriers: Vec<gfx_hal::memory::Barrier<'_, B>> = buffers
.into_iter()
.filter_map(|buffer| {
buffer.release.as_ref().map(|release| {
bstart |= release.stages.start;
bend |= release.stages.end;
gfx_hal::memory::Barrier::Buffer {
states: release.states.clone(),
families: release.families.clone(),
target: ctx
.get_buffer(buffer.id)
.expect("Buffer does not exist")
.raw(),
range: Some(buffer.range.start)..Some(buffer.range.end),
}
})
})
.chain(images.into_iter().filter_map(|image| {
image.release.as_ref().map(|release| {
istart |= release.stages.start;
iend |= release.stages.end;
gfx_hal::memory::Barrier::Image {
states: release.states.clone(),
families: release.families.clone(),
target: ctx.get_image(image.id).expect("Image does not exist").raw(),
range: image.range.clone(),
}
})
}))
.collect();
(bstart | istart..bend | iend, barriers)
}
rendy_with_metal_backend! {
pub fn is_metal<B: Backend>() -> bool {
std::any::TypeId::of::<B>() == std::any::TypeId::of::<rendy_util::metal::Backend>()
}
}
rendy_without_metal_backend! {
pub fn is_metal<B: Backend>() -> bool {
false
}
}