use std::sync::Arc;
use device::Device;
use format::ClearValue;
use format::Format;
use format::FormatTy;
use framebuffer::RenderPass;
use framebuffer::RenderPassCompatible;
use framebuffer::RenderPassCreationError;
use framebuffer::RenderPassDescClearValues;
use image::ImageLayout;
use sync::AccessFlagBits;
use sync::PipelineStages;
use SafeDeref;
use vk;
pub unsafe trait RenderPassDesc: RenderPassDescClearValues<Vec<ClearValue>> {
fn num_attachments(&self) -> usize;
fn attachment_desc(&self, num: usize) -> Option<AttachmentDescription>;
#[inline]
fn attachment_descs(&self) -> RenderPassDescAttachments<Self>
where Self: Sized
{
RenderPassDescAttachments {
render_pass: self,
num: 0,
}
}
fn num_subpasses(&self) -> usize;
fn subpass_desc(&self, num: usize) -> Option<PassDescription>;
#[inline]
fn subpass_descs(&self) -> RenderPassDescSubpasses<Self>
where Self: Sized
{
RenderPassDescSubpasses {
render_pass: self,
num: 0,
}
}
fn num_dependencies(&self) -> usize;
fn dependency_desc(&self, num: usize) -> Option<PassDependencyDescription>;
#[inline]
fn dependency_descs(&self) -> RenderPassDescDependencies<Self>
where Self: Sized
{
RenderPassDescDependencies {
render_pass: self,
num: 0,
}
}
#[inline]
fn is_compatible_with<T>(&self, other: &T) -> bool
where Self: Sized,
T: ?Sized + RenderPassDesc
{
RenderPassCompatible::is_compatible_with(self, other)
}
#[inline]
fn build_render_pass(self, device: Arc<Device>)
-> Result<RenderPass<Self>, RenderPassCreationError>
where Self: Sized
{
RenderPass::new(device, self)
}
#[inline]
fn num_color_attachments(&self, subpass: u32) -> Option<u32> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| p.color_attachments.len() as u32)
}
#[inline]
fn num_samples(&self, subpass: u32) -> Option<u32> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.and_then(|p| {
p.color_attachments
.iter()
.cloned()
.chain(p.depth_stencil.clone().into_iter())
.filter_map(|a| (&self).attachment_descs().skip(a.0).next())
.next()
.map(|a| a.samples)
})
}
#[inline]
fn has_depth_stencil_attachment(&self, subpass: u32) -> Option<(bool, bool)> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| {
let atch_num = match p.depth_stencil {
Some((d, _)) => d,
None => return (false, false),
};
match (&self)
.attachment_descs()
.skip(atch_num)
.next()
.unwrap()
.format
.ty() {
FormatTy::Depth => (true, false),
FormatTy::Stencil => (false, true),
FormatTy::DepthStencil => (true, true),
_ => unreachable!(),
}
})
}
#[inline]
fn has_depth(&self, subpass: u32) -> Option<bool> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| {
let atch_num = match p.depth_stencil {
Some((d, _)) => d,
None => return false,
};
match (&self)
.attachment_descs()
.skip(atch_num)
.next()
.unwrap()
.format
.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
})
}
#[inline]
fn has_writable_depth(&self, subpass: u32) -> Option<bool> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| {
let atch_num = match p.depth_stencil {
Some((d, l)) => {
if l == ImageLayout::DepthStencilReadOnlyOptimal {
return false;
}
d
},
None => return false,
};
match (&self)
.attachment_descs()
.skip(atch_num)
.next()
.unwrap()
.format
.ty() {
FormatTy::Depth => true,
FormatTy::Stencil => false,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
})
}
#[inline]
fn has_stencil(&self, subpass: u32) -> Option<bool> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| {
let atch_num = match p.depth_stencil {
Some((d, _)) => d,
None => return false,
};
match (&self)
.attachment_descs()
.skip(atch_num)
.next()
.unwrap()
.format
.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
})
}
#[inline]
fn has_writable_stencil(&self, subpass: u32) -> Option<bool> {
(&self)
.subpass_descs()
.skip(subpass as usize)
.next()
.map(|p| {
let atch_num = match p.depth_stencil {
Some((d, l)) => {
if l == ImageLayout::DepthStencilReadOnlyOptimal {
return false;
}
d
},
None => return false,
};
match (&self)
.attachment_descs()
.skip(atch_num)
.next()
.unwrap()
.format
.ty() {
FormatTy::Depth => false,
FormatTy::Stencil => true,
FormatTy::DepthStencil => true,
_ => unreachable!(),
}
})
}
}
unsafe impl<T> RenderPassDesc for T
where T: SafeDeref,
T::Target: RenderPassDesc
{
#[inline]
fn num_attachments(&self) -> usize {
(**self).num_attachments()
}
#[inline]
fn attachment_desc(&self, num: usize) -> Option<AttachmentDescription> {
(**self).attachment_desc(num)
}
#[inline]
fn num_subpasses(&self) -> usize {
(**self).num_subpasses()
}
#[inline]
fn subpass_desc(&self, num: usize) -> Option<PassDescription> {
(**self).subpass_desc(num)
}
#[inline]
fn num_dependencies(&self) -> usize {
(**self).num_dependencies()
}
#[inline]
fn dependency_desc(&self, num: usize) -> Option<PassDependencyDescription> {
(**self).dependency_desc(num)
}
}
#[derive(Debug, Copy, Clone)]
pub struct RenderPassDescAttachments<'a, R: ?Sized + 'a> {
render_pass: &'a R,
num: usize,
}
impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescAttachments<'a, R>
where R: RenderPassDesc
{
type Item = AttachmentDescription;
fn next(&mut self) -> Option<AttachmentDescription> {
if self.num < self.render_pass.num_attachments() {
let n = self.num;
self.num += 1;
Some(self.render_pass
.attachment_desc(n)
.expect("Wrong RenderPassDesc implementation"))
} else {
None
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct RenderPassDescSubpasses<'a, R: ?Sized + 'a> {
render_pass: &'a R,
num: usize,
}
impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescSubpasses<'a, R>
where R: RenderPassDesc
{
type Item = PassDescription;
fn next(&mut self) -> Option<PassDescription> {
if self.num < self.render_pass.num_subpasses() {
let n = self.num;
self.num += 1;
Some(self.render_pass
.subpass_desc(n)
.expect("Wrong RenderPassDesc implementation"))
} else {
None
}
}
}
#[derive(Debug, Copy, Clone)]
pub struct RenderPassDescDependencies<'a, R: ?Sized + 'a> {
render_pass: &'a R,
num: usize,
}
impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescDependencies<'a, R>
where R: RenderPassDesc
{
type Item = PassDependencyDescription;
fn next(&mut self) -> Option<PassDependencyDescription> {
if self.num < self.render_pass.num_dependencies() {
let n = self.num;
self.num += 1;
Some(self.render_pass
.dependency_desc(n)
.expect("Wrong RenderPassDesc implementation"))
} else {
None
}
}
}
#[derive(Debug, Clone)]
pub struct AttachmentDescription {
pub format: Format,
pub samples: u32,
pub load: LoadOp,
pub store: StoreOp,
pub stencil_load: LoadOp,
pub stencil_store: StoreOp,
pub initial_layout: ImageLayout,
pub final_layout: ImageLayout,
}
impl AttachmentDescription {
#[inline]
pub fn is_compatible_with(&self, other: &AttachmentDescription) -> bool {
self.format == other.format && self.samples == other.samples
}
}
#[derive(Debug, Clone)]
pub struct PassDescription {
pub color_attachments: Vec<(usize, ImageLayout)>,
pub depth_stencil: Option<(usize, ImageLayout)>,
pub input_attachments: Vec<(usize, ImageLayout)>,
pub resolve_attachments: Vec<(usize, ImageLayout)>,
pub preserve_attachments: Vec<usize>, }
#[derive(Debug, Clone)]
pub struct PassDependencyDescription {
pub source_subpass: usize,
pub destination_subpass: usize,
pub source_stages: PipelineStages,
pub destination_stages: PipelineStages,
pub source_access: AccessFlagBits,
pub destination_access: AccessFlagBits,
pub by_region: bool,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum StoreOp {
Store = vk::ATTACHMENT_STORE_OP_STORE,
DontCare = vk::ATTACHMENT_STORE_OP_DONT_CARE,
}
#[derive(Debug, Copy, Clone, PartialEq, Eq, Hash)]
#[repr(u32)]
pub enum LoadOp {
Load = vk::ATTACHMENT_LOAD_OP_LOAD,
Clear = vk::ATTACHMENT_LOAD_OP_CLEAR,
DontCare = vk::ATTACHMENT_LOAD_OP_DONT_CARE,
}