use device::DeviceOwned;
use format::ClearValue;
use framebuffer::FramebufferSys;
use framebuffer::RenderPassDesc;
use framebuffer::RenderPassSys;
use image::ImageViewAccess;
use pipeline::shader::ShaderInterfaceDef;
use SafeDeref;
pub unsafe trait FramebufferAbstract: RenderPassAbstract {
fn inner(&self) -> FramebufferSys;
fn dimensions(&self) -> [u32; 3];
fn attached_image_view(&self, index: usize) -> Option<&dyn ImageViewAccess>;
#[inline]
fn width(&self) -> u32 {
self.dimensions()[0]
}
#[inline]
fn height(&self) -> u32 {
self.dimensions()[1]
}
#[inline]
fn layers(&self) -> u32 {
self.dimensions()[2]
}
}
unsafe impl<T> FramebufferAbstract for T
where T: SafeDeref,
T::Target: FramebufferAbstract
{
#[inline]
fn inner(&self) -> FramebufferSys {
FramebufferAbstract::inner(&**self)
}
#[inline]
fn dimensions(&self) -> [u32; 3] {
(**self).dimensions()
}
#[inline]
fn attached_image_view(&self, index: usize) -> Option<&dyn ImageViewAccess> {
(**self).attached_image_view(index)
}
}
pub unsafe trait RenderPassAbstract: DeviceOwned + RenderPassDesc {
fn inner(&self) -> RenderPassSys;
}
unsafe impl<T> RenderPassAbstract for T
where T: SafeDeref,
T::Target: RenderPassAbstract
{
#[inline]
fn inner(&self) -> RenderPassSys {
(**self).inner()
}
}
pub unsafe trait RenderPassDescClearValues<C> {
fn convert_clear_values(&self, C) -> Box<dyn Iterator<Item = ClearValue>>;
}
unsafe impl<T, C> RenderPassDescClearValues<C> for T
where T: SafeDeref,
T::Target: RenderPassDescClearValues<C>
{
#[inline]
fn convert_clear_values(&self, vals: C) -> Box<dyn Iterator<Item = ClearValue>> {
(**self).convert_clear_values(vals)
}
}
pub unsafe trait RenderPassSubpassInterface<Other: ?Sized>: RenderPassDesc
where Other: ShaderInterfaceDef
{
fn is_compatible_with(&self, subpass: u32, other: &Other) -> bool;
}
unsafe impl<A, B: ?Sized> RenderPassSubpassInterface<B> for A
where A: RenderPassDesc,
B: ShaderInterfaceDef
{
fn is_compatible_with(&self, subpass: u32, other: &B) -> bool {
let pass_descr = match RenderPassDesc::subpass_descs(self)
.skip(subpass as usize)
.next() {
Some(s) => s,
None => return false,
};
for element in other.elements() {
for location in element.location.clone() {
let attachment_id = match pass_descr.color_attachments.get(location as usize) {
Some(a) => a.0,
None => return false,
};
let attachment_desc = (&self)
.attachment_descs()
.skip(attachment_id)
.next()
.unwrap();
}
}
true
}
}
pub unsafe trait RenderPassCompatible<Other: ?Sized>: RenderPassDesc
where Other: RenderPassDesc
{
fn is_compatible_with(&self, other: &Other) -> bool;
}
unsafe impl<A: ?Sized, B: ?Sized> RenderPassCompatible<B> for A
where A: RenderPassDesc,
B: RenderPassDesc
{
fn is_compatible_with(&self, other: &B) -> bool {
if self.num_attachments() != other.num_attachments() {
return false;
}
for atch_num in 0 .. self.num_attachments() {
let my_atch = self.attachment_desc(atch_num).unwrap();
let other_atch = other.attachment_desc(atch_num).unwrap();
if !my_atch.is_compatible_with(&other_atch) {
return false;
}
}
return true;
}
}
#[derive(Debug, Copy, Clone)]
pub struct Subpass<L> {
render_pass: L,
subpass_id: u32,
}
impl<L> Subpass<L>
where L: RenderPassDesc
{
#[inline]
pub fn from(render_pass: L, id: u32) -> Option<Subpass<L>> {
if (id as usize) < render_pass.num_subpasses() {
Some(Subpass {
render_pass: render_pass,
subpass_id: id,
})
} else {
None
}
}
#[inline]
pub fn num_color_attachments(&self) -> u32 {
self.render_pass
.num_color_attachments(self.subpass_id)
.unwrap()
}
#[inline]
pub fn has_depth(&self) -> bool {
self.render_pass.has_depth(self.subpass_id).unwrap()
}
#[inline]
pub fn has_writable_depth(&self) -> bool {
self.render_pass
.has_writable_depth(self.subpass_id)
.unwrap()
}
#[inline]
pub fn has_stencil(&self) -> bool {
self.render_pass.has_stencil(self.subpass_id).unwrap()
}
#[inline]
pub fn has_writable_stencil(&self) -> bool {
self.render_pass
.has_writable_stencil(self.subpass_id)
.unwrap()
}
#[inline]
pub fn has_color_or_depth_stencil_attachment(&self) -> bool {
self.num_color_attachments() >= 1 ||
self.render_pass
.has_depth_stencil_attachment(self.subpass_id)
.unwrap() != (false, false)
}
#[inline]
pub fn num_samples(&self) -> Option<u32> {
self.render_pass.num_samples(self.subpass_id)
}
}
impl<L> Subpass<L> {
#[inline]
pub fn render_pass(&self) -> &L {
&self.render_pass
}
#[inline]
pub fn index(&self) -> u32 {
self.subpass_id
}
}
impl<L> Into<(L, u32)> for Subpass<L> {
#[inline]
fn into(self) -> (L, u32) {
(self.render_pass, self.subpass_id)
}
}