Rework attachments list

This commit is contained in:
Pierre Krieger 2017-01-04 16:55:19 +01:00
parent 0b5d494288
commit 19beb1eb06
6 changed files with 147 additions and 190 deletions

View File

@ -322,7 +322,7 @@ fn main() {
// each image.
let framebuffers = images.iter().map(|image| {
let dimensions = [image.dimensions()[0], image.dimensions()[1], 1];
Framebuffer::new(render_pass.clone(), dimensions, (image.clone(),)).unwrap()
Framebuffer::new(render_pass.clone(), dimensions, render_pass.desc().start_attachments().color(image.clone())).unwrap()
}).collect::<Vec<_>>();
// Initialization is finally finished!

View File

@ -0,0 +1,121 @@
// Copyright (c) 2016 The vulkano developers
// Licensed under the Apache License, Version 2.0
// <LICENSE-APACHE or
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
// at your option. All files in the project carrying such
// notice may not be copied, modified, or distributed except
// according to those terms.
use command_buffer::cmd::CommandsListSink;
use image::traits::ImageView;
//use sync::AccessFlagBits;
//use sync::PipelineStages;
use VulkanObject;
use vk;
/// A list of attachments.
// TODO: rework this trait
pub unsafe trait AttachmentsList {
/// Returns the raw handles of the image views of this list.
// TODO: better return type
fn raw_image_view_handles(&self) -> Vec<vk::ImageView>;
/// Returns the minimal dimensions of the views. Returns `None` if the list is empty.
///
/// Must be done for each component individually.
///
/// For example if one view is 256x256x1 and another one is 128x512x2, then this function
/// should return 128x256x1.
fn min_dimensions(&self) -> Option<[u32; 3]>;
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
}
unsafe impl AttachmentsList for () {
#[inline]
fn raw_image_view_handles(&self) -> Vec<vk::ImageView> {
vec![]
}
#[inline]
fn min_dimensions(&self) -> Option<[u32; 3]> {
None
}
#[inline]
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
}
}
macro_rules! impl_into_atch_list {
($first:ident $(, $rest:ident)*) => (
unsafe impl<$first $(, $rest)*> AttachmentsList for ($first, $($rest),*)
where $first: ImageView,
$($rest: ImageView,)*
{
#[inline]
#[allow(non_snake_case)]
fn raw_image_view_handles(&self) -> Vec<vk::ImageView> {
let &(ref $first, $(ref $rest,)*) = self;
vec![
$first.inner().internal_object(),
$(
$rest.inner().internal_object(),
)*
]
}
#[inline]
fn min_dimensions(&self) -> Option<[u32; 3]> {
unimplemented!()
/*let my_view_dims = self.first.parent().dimensions();
debug_assert_eq!(my_view_dims.depth(), 1);
let my_view_dims = [my_view_dims.width(), my_view_dims.height(),
my_view_dims.array_layers()]; // FIXME: should be the view's layers, not the image's
match self.rest.min_dimensions() {
Some(r_dims) => {
Some([
cmp::min(r_dims[0], my_view_dims[0]),
cmp::min(r_dims[1], my_view_dims[1]),
cmp::min(r_dims[2], my_view_dims[2])
])
},
None => Some(my_view_dims),
}*/
}
#[inline]
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
unimplemented!()
/*// TODO: "wrong" values
let stages = PipelineStages {
color_attachment_output: true,
late_fragment_tests: true,
.. PipelineStages::none()
};
let access = AccessFlagBits {
color_attachment_read: true,
color_attachment_write: true,
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
.. AccessFlagBits::none()
};
// FIXME: adjust layers & mipmaps with the view's parameters
sink.add_image_transition(self.first.parent(), 0, 1, 0, 1, true, Layout::General /* FIXME: wrong */,
stages, access);
self.rest.add_transition(sink);*/
}
}
impl_into_atch_list!($($rest),*);
);
() => ();
}
impl_into_atch_list!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);

View File

@ -7,7 +7,6 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use std::cmp;
use std::error;
use std::fmt;
use std::mem;
@ -16,15 +15,12 @@ use std::sync::Arc;
use command_buffer::cmd::CommandsListSink;
use device::Device;
use framebuffer::AttachmentsList;
use framebuffer::FramebufferRef;
use framebuffer::RenderPass;
use framebuffer::RenderPassRef;
use framebuffer::RenderPassDescAttachmentsList;
use framebuffer::RenderPassCompatible;
use image::sys::Layout;
use image::traits::ImageView;
use sync::AccessFlagBits;
use sync::PipelineStages;
use Error;
use OomError;
@ -53,20 +49,17 @@ impl<Rp, A> Framebuffer<Rp, A> {
/// Builds a new framebuffer.
///
/// The `attachments` parameter depends on which `RenderPassRef` implementation is used.
pub fn new<Ia>(render_pass: Rp, dimensions: [u32; 3],
attachments: Ia) -> Result<Arc<Framebuffer<Rp, A>>, FramebufferCreationError>
pub fn new<Ia>(render_pass: Rp, dimensions: [u32; 3], attachments: Ia)
-> Result<Arc<Framebuffer<Rp, A>>, FramebufferCreationError>
where Rp: RenderPassRef,
Rp::Desc: RenderPassDescAttachmentsList<Ia>,
Ia: IntoAttachmentsList<List = A>,
A: AttachmentsList
Rp::Desc: RenderPassDescAttachmentsList<Ia, List = A>,
A: AttachmentsList,
{
let device = render_pass.inner().device().clone();
// This function call is supposed to check whether the attachments are valid.
// For more safety, we do some additional `debug_assert`s below.
try!(render_pass.inner().desc().check_attachments_list(&attachments));
let attachments = attachments.into_attachments_list();
let attachments = try!(render_pass.inner().desc().check_attachments_list(attachments));
// Checking the dimensions against the limits.
{
@ -216,173 +209,6 @@ impl<Rp, A> Drop for Framebuffer<Rp, A> {
}
}
pub unsafe trait AttachmentsList {
/// Returns the raw handles of the image views of this list.
// TODO: better return type
fn raw_image_view_handles(&self) -> Vec<vk::ImageView>;
/// Returns the minimal dimensions of the views. Returns `None` if the list is empty.
///
/// Must be done for each component individually.
///
/// For example if one view is 256x256x1 and another one is 128x512x2, then this function
/// should return 128x256x1.
fn min_dimensions(&self) -> Option<[u32; 3]>;
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
}
#[derive(Debug, Copy, Clone)]
pub struct EmptyAttachmentsList;
unsafe impl AttachmentsList for EmptyAttachmentsList {
#[inline]
fn raw_image_view_handles(&self) -> Vec<vk::ImageView> {
vec![]
}
#[inline]
fn min_dimensions(&self) -> Option<[u32; 3]> {
None
}
#[inline]
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
}
}
unsafe impl AttachmentsList for () {
#[inline]
fn raw_image_view_handles(&self) -> Vec<vk::ImageView> {
vec![]
}
#[inline]
fn min_dimensions(&self) -> Option<[u32; 3]> {
None
}
#[inline]
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
}
}
pub struct List<A, R> { pub first: A, pub rest: R }
unsafe impl<A, R> AttachmentsList for List<A, R>
where A: ImageView,
R: AttachmentsList
{
#[inline]
fn raw_image_view_handles(&self) -> Vec<vk::ImageView> {
let mut list = self.rest.raw_image_view_handles();
list.insert(0, self.first.inner().internal_object());
list
}
#[inline]
fn min_dimensions(&self) -> Option<[u32; 3]> {
let my_view_dims = self.first.parent().dimensions();
debug_assert_eq!(my_view_dims.depth(), 1);
let my_view_dims = [my_view_dims.width(), my_view_dims.height(),
my_view_dims.array_layers()]; // FIXME: should be the view's layers, not the image's
match self.rest.min_dimensions() {
Some(r_dims) => {
Some([
cmp::min(r_dims[0], my_view_dims[0]),
cmp::min(r_dims[1], my_view_dims[1]),
cmp::min(r_dims[2], my_view_dims[2])
])
},
None => Some(my_view_dims),
}
}
#[inline]
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
// TODO: "wrong" values
let stages = PipelineStages {
color_attachment_output: true,
late_fragment_tests: true,
.. PipelineStages::none()
};
let access = AccessFlagBits {
color_attachment_read: true,
color_attachment_write: true,
depth_stencil_attachment_read: true,
depth_stencil_attachment_write: true,
.. AccessFlagBits::none()
};
// FIXME: adjust layers & mipmaps with the view's parameters
sink.add_image_transition(self.first.parent(), 0, 1, 0, 1, true, Layout::General /* FIXME: wrong */,
stages, access);
self.rest.add_transition(sink);
}
}
/// Trait for types that can be turned into a list of attachments.
pub trait IntoAttachmentsList {
/// The list of attachments.
type List;
/// Performs the conversion.
fn into_attachments_list(self) -> Self::List;
}
/*impl<S, T> IntoAttachmentsList for T where T: AttachmentsList<S> {
type List = T;
#[inline]
fn into_attachments_list(self) -> T {
self
}
}*/
impl IntoAttachmentsList for () {
type List = EmptyAttachmentsList;
#[inline]
fn into_attachments_list(self) -> EmptyAttachmentsList {
EmptyAttachmentsList
}
}
macro_rules! impl_into_atch_list {
($first:ident, $($rest:ident),+) => (
impl<$first, $($rest),+> IntoAttachmentsList for ($first, $($rest),+) {
type List = List<$first, <($($rest,)+) as IntoAttachmentsList>::List>;
#[inline]
#[allow(non_snake_case)]
fn into_attachments_list(self) -> Self::List {
let ($first, $($rest),+) = self;
List {
first: $first,
rest: IntoAttachmentsList::into_attachments_list(($($rest,)+))
}
}
}
impl_into_atch_list!($($rest),+);
);
($alone:ident) => (
impl<A> IntoAttachmentsList for (A,) {
type List = List<A, EmptyAttachmentsList>;
#[inline]
fn into_attachments_list(self) -> Self::List {
List { first: self.0, rest: EmptyAttachmentsList }
}
}
);
}
impl_into_atch_list!(A, B, C, D, E, F, G, H, I, J, K, L, M, N, O, P, Q, R, S, T, U, V, W, X, Y, Z);
/// Error that can happen when creating a framebuffer object.
#[derive(Copy, Clone, Debug, PartialEq, Eq)]
#[repr(u32)]

View File

@ -73,7 +73,6 @@ macro_rules! ordered_passes_renderpass {
use $crate::framebuffer::LayoutPassDependencyDescription;
use $crate::framebuffer::FramebufferCreationError;
use $crate::framebuffer::RenderPassCreationError;
use $crate::framebuffer::IntoAttachmentsList;
use $crate::image::Layout;
use $crate::image::traits::ImageView;
use $crate::sync::AccessFlagBits;
@ -347,7 +346,9 @@ macro_rules! ordered_passes_renderpass {
([] __impl_attachments__ [] [] [] [$($params:ident),*]) => {
unsafe impl RenderPassDescAttachmentsList<AttachmentsStart> for CustomRenderPassDesc {
fn check_attachments_list(&self, attachments: &AttachmentsStart) -> Result<(), FramebufferCreationError> {
type List = ();
fn check_attachments_list(&self, attachments: AttachmentsStart) -> Result<(), FramebufferCreationError> {
Ok(()) // FIXME:
}
}
@ -370,9 +371,13 @@ macro_rules! ordered_passes_renderpass {
};
([] __impl_attachments__ [$prev:ident] [$($prev_params:ident),*] [] [$($params:ident),*]) => {
unsafe impl<$($prev_params,)*> RenderPassDescAttachmentsList<$prev<$($prev_params,)*>> for CustomRenderPassDesc {
fn check_attachments_list(&self, attachments: &$prev<$($prev_params,)*>) -> Result<(), FramebufferCreationError> {
Ok(()) // FIXME:
unsafe impl<$($prev_params,)*> RenderPassDescAttachmentsList<$prev<$($prev_params,)*>> for CustomRenderPassDesc
where $($prev_params: ImageView,)*
{
type List = ($($prev_params,)*); // TODO: wrong
fn check_attachments_list(&self, attachments: $prev<$($prev_params,)*>) -> Result<Self::List, FramebufferCreationError> {
unimplemented!() // FIXME:
}
}
};

View File

@ -77,9 +77,8 @@
//!
//! TODO
pub use self::attachments_list::AttachmentsList;
pub use self::empty::EmptySinglePassRenderPassDesc;
pub use self::framebuffer::AttachmentsList; // TODO: rework and remove
pub use self::framebuffer::IntoAttachmentsList; // TODO: rework and remove
pub use self::framebuffer::Framebuffer;
pub use self::framebuffer::FramebufferCreationError;
pub use self::sys::RenderPass;
@ -100,6 +99,7 @@ pub use self::traits::Subpass;
#[macro_use]
mod macros;
mod attachments_list;
mod empty;
mod framebuffer;
mod sys;

View File

@ -13,6 +13,7 @@ use device::Device;
use format::ClearValue;
use format::Format;
use format::FormatTy;
use framebuffer::AttachmentsList;
use framebuffer::Framebuffer;
use framebuffer::FramebufferCreationError;
use framebuffer::RenderPass;
@ -436,10 +437,14 @@ impl<'a, R: ?Sized + 'a> Iterator for RenderPassDescDependencies<'a, R> where R:
/// TODO: more stuff with aliasing
///
pub unsafe trait RenderPassDescAttachmentsList<A>: RenderPassDesc {
/// The "compiled" list of attachments.
type List: AttachmentsList;
/// Decodes a `A` into a list of attachments.
///
/// Returns an error if one of the attachments is wrong.
fn check_attachments_list(&self, &A) -> Result<(), FramebufferCreationError>;
/// Checks that the attachments match the render pass, and returns a list. Returns an error if
/// one of the attachments is wrong.
fn check_attachments_list(&self, A) -> Result<Self::List, FramebufferCreationError>;
}
/*unsafe impl<A, R> RenderPassDescAttachmentsList<A> for R where R: RenderPassDesc {