mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-22 14:56:42 +00:00
Merge pull request #486 from tomaka/fb-cleanup
Lots of cleanups in the framebuffer modules
This commit is contained in:
commit
77797d0eec
@ -7,43 +7,20 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::cmp;
|
||||
use std::sync::Arc;
|
||||
use SafeDeref;
|
||||
use image::ImageViewAccess;
|
||||
use image::sys::UnsafeImageView;
|
||||
//use sync::AccessFlagBits;
|
||||
//use sync::PipelineStages;
|
||||
|
||||
/// A list of attachments.
|
||||
// TODO: rework this trait
|
||||
pub unsafe trait AttachmentsList {
|
||||
/// Returns the image views of this list.
|
||||
// TODO: better return type
|
||||
fn raw_image_view_handles(&self) -> Vec<&UnsafeImageView>;
|
||||
|
||||
/// Returns the dimensions of the intersection of the views. Returns `None` if the list is
|
||||
/// empty.
|
||||
///
|
||||
/// For example if one view is 256x256x2 and another one is 128x512x3, then this function
|
||||
/// should return 128x256x2.
|
||||
fn intersection_dimensions(&self) -> Option<[u32; 3]>;
|
||||
|
||||
// TODO: meh for API
|
||||
fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess>;
|
||||
}
|
||||
|
||||
unsafe impl<T> AttachmentsList for T where T: SafeDeref, T::Target: AttachmentsList {
|
||||
#[inline]
|
||||
fn raw_image_view_handles(&self) -> Vec<&UnsafeImageView> {
|
||||
(**self).raw_image_view_handles()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intersection_dimensions(&self) -> Option<[u32; 3]> {
|
||||
(**self).intersection_dimensions()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> {
|
||||
(**self).as_image_view_accesses()
|
||||
@ -51,16 +28,6 @@ unsafe impl<T> AttachmentsList for T where T: SafeDeref, T::Target: AttachmentsL
|
||||
}
|
||||
|
||||
unsafe impl AttachmentsList for () {
|
||||
#[inline]
|
||||
fn raw_image_view_handles(&self) -> Vec<&UnsafeImageView> {
|
||||
vec![]
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intersection_dimensions(&self) -> Option<[u32; 3]> {
|
||||
None
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> {
|
||||
vec![]
|
||||
@ -68,37 +35,6 @@ unsafe impl AttachmentsList for () {
|
||||
}
|
||||
|
||||
unsafe impl AttachmentsList for Vec<Arc<ImageViewAccess + Send + Sync>> {
|
||||
#[inline]
|
||||
fn raw_image_view_handles(&self) -> Vec<&UnsafeImageView> {
|
||||
self.iter().map(|img| img.inner()).collect()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intersection_dimensions(&self) -> Option<[u32; 3]> {
|
||||
let mut dims = None;
|
||||
|
||||
for view in self.iter() {
|
||||
debug_assert_eq!(view.dimensions().depth(), 1);
|
||||
|
||||
match dims {
|
||||
None => {
|
||||
dims = Some([
|
||||
view.dimensions().width(),
|
||||
view.dimensions().height(),
|
||||
view.dimensions().array_layers()
|
||||
]);
|
||||
},
|
||||
Some(ref mut d) => {
|
||||
d[0] = cmp::min(view.dimensions().width(), d[0]);
|
||||
d[1] = cmp::min(view.dimensions().height(), d[1]);
|
||||
d[2] = cmp::min(view.dimensions().array_layers(), d[2]);
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
dims
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> {
|
||||
self.iter().map(|p| &**p as &ImageViewAccess).collect()
|
||||
@ -108,33 +44,6 @@ unsafe impl AttachmentsList for Vec<Arc<ImageViewAccess + Send + Sync>> {
|
||||
unsafe impl<A, B> AttachmentsList for (A, B)
|
||||
where A: AttachmentsList, B: ImageViewAccess
|
||||
{
|
||||
#[inline]
|
||||
fn raw_image_view_handles(&self) -> Vec<&UnsafeImageView> {
|
||||
let mut list = self.0.raw_image_view_handles();
|
||||
list.push(self.1.inner());
|
||||
list
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn intersection_dimensions(&self) -> Option<[u32; 3]> {
|
||||
let dims = {
|
||||
let d = self.1.dimensions();
|
||||
debug_assert_eq!(d.depth(), 1);
|
||||
[d.width(), d.height(), d.array_layers()]
|
||||
};
|
||||
|
||||
let dims = match self.0.intersection_dimensions() {
|
||||
Some(d) => [
|
||||
cmp::min(d[0], dims[0]),
|
||||
cmp::min(d[1], dims[1]),
|
||||
cmp::min(d[2], dims[2])
|
||||
],
|
||||
None => dims,
|
||||
};
|
||||
|
||||
Some(dims)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn as_image_view_accesses(&self) -> Vec<&ImageViewAccess> {
|
||||
let mut list = self.0.as_image_view_accesses();
|
||||
|
@ -14,12 +14,10 @@ use format::ClearValue;
|
||||
use format::Format;
|
||||
use format::FormatTy;
|
||||
use framebuffer::RenderPass;
|
||||
use framebuffer::RenderPassDescAttachmentsList;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
use framebuffer::RenderPassCompatible;
|
||||
use framebuffer::RenderPassCreationError;
|
||||
use image::ImageLayout as ImageLayout;
|
||||
use image::ImageViewAccess;
|
||||
use sync::AccessFlagBits;
|
||||
use sync::PipelineStages;
|
||||
|
||||
@ -44,9 +42,7 @@ use vk;
|
||||
/// - The provided methods shouldn't be overriden with fancy implementations. For example
|
||||
/// `build_render_pass` must build a render pass from the description and not a different one.
|
||||
///
|
||||
pub unsafe trait RenderPassDesc: RenderPassDescClearValues<Vec<ClearValue>> +
|
||||
RenderPassDescAttachmentsList<Vec<Arc<ImageViewAccess + Send + Sync>>>
|
||||
{
|
||||
pub unsafe trait RenderPassDesc: RenderPassDescClearValues<Vec<ClearValue>> {
|
||||
/// Returns the number of attachments of the render pass.
|
||||
fn num_attachments(&self) -> usize;
|
||||
|
||||
|
@ -8,17 +8,12 @@
|
||||
// according to those terms.
|
||||
|
||||
use std::iter;
|
||||
use std::sync::Arc;
|
||||
use format::ClearValue;
|
||||
use framebuffer::AttachmentsList;
|
||||
use framebuffer::FramebufferCreationError;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use framebuffer::RenderPassDescAttachmentsList;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
use framebuffer::LayoutAttachmentDescription;
|
||||
use framebuffer::LayoutPassDescription;
|
||||
use framebuffer::LayoutPassDependencyDescription;
|
||||
use image::ImageViewAccess;
|
||||
|
||||
/// Description of an empty render pass.
|
||||
///
|
||||
@ -143,29 +138,6 @@ unsafe impl RenderPassDesc for EmptySinglePassRenderPassDesc {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl RenderPassDescAttachmentsList<Vec<Arc<ImageViewAccess + Send + Sync>>> for EmptySinglePassRenderPassDesc {
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, list: Vec<Arc<ImageViewAccess + Send + Sync>>)
|
||||
-> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError>
|
||||
{
|
||||
if list.is_empty() {
|
||||
Ok(Box::new(()) as Box<_>)
|
||||
} else {
|
||||
Err(FramebufferCreationError::AttachmentsCountMismatch {
|
||||
expected: 0,
|
||||
obtained: list.len(),
|
||||
})
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl RenderPassDescAttachmentsList<()> for EmptySinglePassRenderPassDesc {
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, list: ()) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
Ok(Box::new(()) as Box<_>)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl RenderPassDescClearValues<Vec<ClearValue>> for EmptySinglePassRenderPassDesc {
|
||||
#[inline]
|
||||
fn convert_clear_values(&self, values: Vec<ClearValue>) -> Box<Iterator<Item = ClearValue>> {
|
||||
|
@ -7,6 +7,7 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use std::cmp;
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
use std::marker::PhantomData;
|
||||
@ -26,9 +27,9 @@ use framebuffer::LayoutPassDependencyDescription;
|
||||
use framebuffer::LayoutPassDescription;
|
||||
use framebuffer::RenderPassAbstract;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
use framebuffer::RenderPassDescAttachmentsList;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use framebuffer::RenderPassSys;
|
||||
use framebuffer::ensure_image_view_compatible;
|
||||
use image::ImageView;
|
||||
use image::ImageViewAccess;
|
||||
|
||||
@ -39,91 +40,49 @@ use VulkanPointers;
|
||||
use check_errors;
|
||||
use vk;
|
||||
|
||||
/// Contains the list of images attached to a render pass.
|
||||
/// Contains a render pass and the image views that are attached to it.
|
||||
///
|
||||
/// Creating a framebuffer is done by passing the render pass object, the dimensions of the
|
||||
/// framebuffer, and the list of attachments to `Framebuffer::new()`.
|
||||
/// Creating a framebuffer is done by calling `Framebuffer::start`, which returns a
|
||||
/// `FramebufferBuilder` object. You can then add the framebuffer attachments one by one by
|
||||
/// calling `add(image)`. When you are done, call `build()`.
|
||||
///
|
||||
/// Just like all render pass objects implement the `RenderPassAbstract` trait, all framebuffer
|
||||
/// objects implement the `FramebufferAbstract` trait. This means that you can cast any
|
||||
/// `Arc<Framebuffer<..>>` into an `Arc<FramebufferAbstract + Send + Sync>` for easier storage.
|
||||
/// Both the `add` and the `build` functions perform various checks to make sure that the number
|
||||
/// of images is correct and that each image is compatible with the attachment definition in the
|
||||
/// render pass.
|
||||
///
|
||||
/// ## With a generic list of attachments
|
||||
///
|
||||
/// The list of attachments passed to `Framebuffer::new()` can be of various types, but one of the
|
||||
/// possibilities is to pass an object of type `Vec<Arc<ImageView + Send + Sync>>`.
|
||||
///
|
||||
/// > **Note**: If you access a render pass object through the `RenderPassAbstract` trait, passing
|
||||
/// > a `Vec<Arc<ImageView + Send + Sync>>` is the only possible method.
|
||||
///
|
||||
/// The framebuffer constructor will perform various checks to make sure that the number of images
|
||||
/// is correct and that each image can be used with this render pass.
|
||||
///
|
||||
/// ```ignore // FIXME: unignore
|
||||
/// ```
|
||||
/// # use std::sync::Arc;
|
||||
/// # use vulkano::framebuffer::RenderPassAbstract;
|
||||
/// use vulkano::framebuffer::Framebuffer;
|
||||
///
|
||||
/// # let render_pass: Arc<RenderPassAbstract + Send + Sync> = return;
|
||||
/// # let my_image: Arc<vulkano::image::ImageViewAccess> = return;
|
||||
/// // let render_pass: Arc<RenderPassAbstract + Send + Sync> = ...;
|
||||
/// let framebuffer = Framebuffer::new(render_pass.clone(), [1024, 768, 1],
|
||||
/// vec![my_image.clone() as Arc<_>]).unwrap();
|
||||
/// # let my_image: Arc<vulkano::image::AttachmentImage<vulkano::format::Format>> = return;
|
||||
/// // let render_pass: Arc<_> = ...;
|
||||
/// let framebuffer = Framebuffer::start(render_pass.clone())
|
||||
/// .add(my_image).unwrap()
|
||||
/// .build().unwrap();
|
||||
/// ```
|
||||
///
|
||||
/// ## With a specialized list of attachments
|
||||
/// Just like render pass objects implement the `RenderPassAbstract` trait, all framebuffer
|
||||
/// objects implement the `FramebufferAbstract` trait. This means that you can cast any
|
||||
/// `Arc<Framebuffer<..>>` into an `Arc<FramebufferAbstract + Send + Sync>` for easier storage.
|
||||
///
|
||||
/// The list of attachments can also be of any type `T`, as long as the render pass description
|
||||
/// implements the trait `RenderPassDescAttachmentsList<T>`.
|
||||
/// ## Framebuffer dimensions
|
||||
///
|
||||
/// For example if you pass a render pass object that implements
|
||||
/// `RenderPassDescAttachmentsList<Foo>`, then you can pass a `Foo` as the list of attachments.
|
||||
/// If you use `Framebuffer::start()` to create a framebuffer then vulkano will automatically
|
||||
/// make sure that all the attachments have the same dimensions, as this is the most common
|
||||
/// situation.
|
||||
///
|
||||
/// > **Note**: The reason why `Vec<Arc<ImageView + Send + Sync>>` always works (see previous section) is that
|
||||
/// > render pass descriptions are required to always implement
|
||||
/// > `RenderPassDescAttachmentsList<Vec<Arc<ImageViewAccess + Send + Sync>>>`.
|
||||
/// Alternatively you can also use `with_intersecting_dimensions`, in which case the dimensions of
|
||||
/// the framebuffer will be the intersection of the dimensions of all attachments, or
|
||||
/// `with_dimensions` if you want to specify exact dimensions. If you use `with_dimensions`, you
|
||||
/// are allowed to attach images that are larger than these dimensions.
|
||||
///
|
||||
/// When it comes to the `single_pass_renderpass!` and `ordered_passes_renderpass!` macros, you can
|
||||
/// build a list of attachments by calling `start_attachments()` on the render pass description,
|
||||
/// which will return an object that has a method whose name is the name of the first attachment
|
||||
/// and that can be used to specify it. This method will return another object that has a method
|
||||
/// whose name is the name of the second attachment, and so on. See the documentation of the macros
|
||||
/// for more details. TODO: put link here
|
||||
/// If the dimensions of the framebuffer don't match the dimensions of one of its attachment, then
|
||||
/// only the top-left hand corner of the image will be drawn to.
|
||||
///
|
||||
/// ```ignore // FIXME: unignore
|
||||
/// # #[macro_use] extern crate vulkano;
|
||||
/// # fn main() {
|
||||
/// # let device: std::sync::Arc<vulkano::device::Device> = return;
|
||||
/// use std::sync::Arc;
|
||||
/// use vulkano::format::Format;
|
||||
/// use vulkano::framebuffer::Framebuffer;
|
||||
///
|
||||
/// let render_pass = single_pass_renderpass!(device.clone(),
|
||||
/// attachments: {
|
||||
/// // `foo` is a custom name we give to the first and only attachment.
|
||||
/// foo: {
|
||||
/// load: Clear,
|
||||
/// store: Store,
|
||||
/// format: Format::R8G8B8A8Unorm,
|
||||
/// samples: 1,
|
||||
/// }
|
||||
/// },
|
||||
/// pass: {
|
||||
/// color: [foo], // Repeat the attachment name here.
|
||||
/// depth_stencil: {}
|
||||
/// }
|
||||
/// ).unwrap();
|
||||
///
|
||||
/// # let my_image: Arc<vulkano::image::ImageViewAccess> = return;
|
||||
/// let framebuffer = {
|
||||
/// let atch = render_pass.desc().start_attachments().foo(my_image.clone() as Arc<_>);
|
||||
/// Framebuffer::new(render_pass, [1024, 768, 1], atch).unwrap()
|
||||
/// };
|
||||
/// # }
|
||||
/// ```
|
||||
#[derive(Debug)]
|
||||
pub struct Framebuffer<Rp, A> {
|
||||
// TODO: is this field really needed?
|
||||
device: Arc<Device>,
|
||||
render_pass: Rp,
|
||||
framebuffer: vk::Framebuffer,
|
||||
@ -136,7 +95,29 @@ impl<Rp> Framebuffer<Rp, ()> {
|
||||
pub fn start(render_pass: Rp) -> FramebufferBuilder<Rp, ()> {
|
||||
FramebufferBuilder {
|
||||
render_pass: render_pass,
|
||||
dimensions: FramebufferBuilderDimensions::AutoIdentical,
|
||||
raw_ids: SmallVec::new(),
|
||||
dimensions: FramebufferBuilderDimensions::AutoIdentical(None),
|
||||
attachments: (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts building a framebuffer. The dimensions of the framebuffer will automatically be
|
||||
/// the intersection of the dimensions of all the attachments.
|
||||
pub fn with_intersecting_dimensions(render_pass: Rp) -> FramebufferBuilder<Rp, ()> {
|
||||
FramebufferBuilder {
|
||||
render_pass: render_pass,
|
||||
raw_ids: SmallVec::new(),
|
||||
dimensions: FramebufferBuilderDimensions::AutoSmaller(None),
|
||||
attachments: (),
|
||||
}
|
||||
}
|
||||
|
||||
/// Starts building a framebuffer.
|
||||
pub fn with_dimensions(render_pass: Rp, dimensions: [u32; 3]) -> FramebufferBuilder<Rp, ()> {
|
||||
FramebufferBuilder {
|
||||
render_pass: render_pass,
|
||||
raw_ids: SmallVec::new(),
|
||||
dimensions: FramebufferBuilderDimensions::Specific(dimensions),
|
||||
attachments: (),
|
||||
}
|
||||
}
|
||||
@ -145,13 +126,26 @@ impl<Rp> Framebuffer<Rp, ()> {
|
||||
/// Prototype of a framebuffer.
|
||||
pub struct FramebufferBuilder<Rp, A> {
|
||||
render_pass: Rp,
|
||||
raw_ids: SmallVec<[vk::ImageView; 8]>,
|
||||
dimensions: FramebufferBuilderDimensions,
|
||||
attachments: A,
|
||||
}
|
||||
|
||||
impl<Rp, A> fmt::Debug for FramebufferBuilder<Rp, A> where Rp: fmt::Debug, A: fmt::Debug {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
fmt.debug_struct("FramebufferBuilder")
|
||||
.field("render_pass", &self.render_pass)
|
||||
.field("dimensions", &self.dimensions)
|
||||
.field("attachments", &self.attachments)
|
||||
.finish()
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Debug)]
|
||||
enum FramebufferBuilderDimensions {
|
||||
AutoIdentical,
|
||||
AutoSmaller,
|
||||
AutoIdentical(Option<[u32; 3]>),
|
||||
AutoSmaller(Option<[u32; 3]>),
|
||||
Specific([u32; 3]),
|
||||
}
|
||||
|
||||
@ -168,36 +162,75 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
{
|
||||
let access = attachment.access();
|
||||
|
||||
// TODO: check number of attachments
|
||||
if self.raw_ids.len() >= self.render_pass.num_attachments() {
|
||||
return Err(FramebufferCreationError::AttachmentsCountMismatch {
|
||||
expected: self.render_pass.num_attachments(),
|
||||
obtained: self.raw_ids.len() + 1,
|
||||
});
|
||||
}
|
||||
|
||||
match ensure_image_view_compatible(&self.render_pass, self.raw_ids.len(), &access) {
|
||||
Ok(()) => (),
|
||||
Err(err) => return Err(FramebufferCreationError::IncompatibleAttachment(err))
|
||||
};
|
||||
|
||||
let img_dims = access.dimensions();
|
||||
debug_assert_eq!(img_dims.depth(), 1);
|
||||
|
||||
let dimensions = match self.dimensions {
|
||||
FramebufferBuilderDimensions::AutoIdentical => {
|
||||
let dims = access.dimensions();
|
||||
debug_assert_eq!(dims.depth(), 1);
|
||||
let dims = [dims.width(), dims.height(), dims.array_layers()];
|
||||
FramebufferBuilderDimensions::Specific(dims)
|
||||
FramebufferBuilderDimensions::AutoIdentical(None) => {
|
||||
let dims = [img_dims.width(), img_dims.height(), img_dims.array_layers()];
|
||||
FramebufferBuilderDimensions::AutoIdentical(Some(dims))
|
||||
},
|
||||
FramebufferBuilderDimensions::AutoSmaller => {
|
||||
FramebufferBuilderDimensions::AutoSmaller
|
||||
FramebufferBuilderDimensions::AutoIdentical(Some(current)) => {
|
||||
if img_dims.width() != current[0] || img_dims.height() != current[1] ||
|
||||
img_dims.array_layers() != current[2]
|
||||
{
|
||||
return Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
|
||||
expected: current,
|
||||
obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()]
|
||||
});
|
||||
}
|
||||
|
||||
FramebufferBuilderDimensions::AutoIdentical(Some(current))
|
||||
}
|
||||
FramebufferBuilderDimensions::AutoSmaller(None) => {
|
||||
let dims = [img_dims.width(), img_dims.height(), img_dims.array_layers()];
|
||||
FramebufferBuilderDimensions::AutoSmaller(Some(dims))
|
||||
},
|
||||
FramebufferBuilderDimensions::AutoSmaller(Some(current)) => {
|
||||
let new_dims = [
|
||||
cmp::min(current[0], img_dims.width()),
|
||||
cmp::min(current[1], img_dims.height()),
|
||||
cmp::min(current[2], img_dims.array_layers())
|
||||
];
|
||||
|
||||
FramebufferBuilderDimensions::AutoSmaller(Some(new_dims))
|
||||
},
|
||||
FramebufferBuilderDimensions::Specific(current) => {
|
||||
let dims = access.dimensions();
|
||||
if dims.width() != current[0] || dims.height() != current[1] ||
|
||||
dims.array_layers() != current[2]
|
||||
if img_dims.width() < current[0] || img_dims.height() < current[1] ||
|
||||
img_dims.array_layers() < current[2]
|
||||
{
|
||||
return Err(FramebufferCreationError::AttachmentTooSmall); // TODO: more precise?
|
||||
return Err(FramebufferCreationError::AttachmentDimensionsIncompatible {
|
||||
expected: current,
|
||||
obtained: [img_dims.width(), img_dims.height(), img_dims.array_layers()]
|
||||
});
|
||||
}
|
||||
|
||||
FramebufferBuilderDimensions::Specific([
|
||||
dims.width(),
|
||||
dims.height(),
|
||||
dims.array_layers()
|
||||
img_dims.width(),
|
||||
img_dims.height(),
|
||||
img_dims.array_layers()
|
||||
])
|
||||
}
|
||||
};
|
||||
|
||||
let mut raw_ids = self.raw_ids;
|
||||
raw_ids.push(access.inner().internal_object());
|
||||
|
||||
Ok(FramebufferBuilder {
|
||||
render_pass: self.render_pass,
|
||||
raw_ids: raw_ids,
|
||||
dimensions: dimensions,
|
||||
attachments: (self.attachments, access),
|
||||
})
|
||||
@ -216,6 +249,7 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
{
|
||||
FramebufferBuilder {
|
||||
render_pass: self.render_pass,
|
||||
raw_ids: self.raw_ids,
|
||||
dimensions: self.dimensions,
|
||||
attachments: Box::new(self.attachments) as Box<_>,
|
||||
}
|
||||
@ -225,22 +259,25 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
pub fn build(self) -> Result<Framebuffer<Rp, A>, FramebufferCreationError> {
|
||||
let device = self.render_pass.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.
|
||||
// FIXME: check attachments when they are added to the builder instead of at the end
|
||||
let attachments = self.attachments;
|
||||
//let attachments = try!(self.render_pass.check_attachments_list(self.attachments));
|
||||
|
||||
// TODO: add a debug assertion that checks whether the attachments are compatible
|
||||
// with the RP ; this should be checked by the RenderPassDescAttachmentsList trait
|
||||
// impl, but we can double-check in debug mode
|
||||
// also check the number of attachments
|
||||
// Check the number of attachments.
|
||||
if self.raw_ids.len() != self.render_pass.num_attachments() {
|
||||
return Err(FramebufferCreationError::AttachmentsCountMismatch {
|
||||
expected: self.render_pass.num_attachments(),
|
||||
obtained: self.raw_ids.len(),
|
||||
});
|
||||
}
|
||||
|
||||
// Compute the dimensions.
|
||||
let dimensions = match self.dimensions {
|
||||
FramebufferBuilderDimensions::AutoIdentical => panic!(), // TODO: what if 0 attachment?
|
||||
FramebufferBuilderDimensions::AutoSmaller => attachments.intersection_dimensions().unwrap(), // TODO: what if 0 attachment?
|
||||
FramebufferBuilderDimensions::Specific(dims) => dims,
|
||||
FramebufferBuilderDimensions::Specific(dims) |
|
||||
FramebufferBuilderDimensions::AutoIdentical(Some(dims)) |
|
||||
FramebufferBuilderDimensions::AutoSmaller(Some(dims)) => {
|
||||
dims
|
||||
},
|
||||
FramebufferBuilderDimensions::AutoIdentical(None) |
|
||||
FramebufferBuilderDimensions::AutoSmaller(None) => {
|
||||
return Err(FramebufferCreationError::CantDetermineDimensions);
|
||||
},
|
||||
};
|
||||
|
||||
// Checking the dimensions against the limits.
|
||||
@ -255,9 +292,6 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
}
|
||||
}
|
||||
|
||||
let ids: SmallVec<[vk::ImageView; 8]> =
|
||||
attachments.raw_image_view_handles().into_iter().map(|v| v.internal_object()).collect();
|
||||
|
||||
let framebuffer = unsafe {
|
||||
let vk = device.pointers();
|
||||
|
||||
@ -266,8 +300,8 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
pNext: ptr::null(),
|
||||
flags: 0, // reserved
|
||||
renderPass: self.render_pass.inner().internal_object(),
|
||||
attachmentCount: ids.len() as u32,
|
||||
pAttachments: ids.as_ptr(),
|
||||
attachmentCount: self.raw_ids.len() as u32,
|
||||
pAttachments: self.raw_ids.as_ptr(),
|
||||
width: dimensions[0],
|
||||
height: dimensions[1],
|
||||
layers: dimensions[2],
|
||||
@ -284,7 +318,7 @@ impl<Rp, A> FramebufferBuilder<Rp, A>
|
||||
render_pass: self.render_pass,
|
||||
framebuffer: framebuffer,
|
||||
dimensions: dimensions,
|
||||
resources: attachments,
|
||||
resources: self.attachments,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -379,15 +413,6 @@ unsafe impl<Rp, A> RenderPassDesc for Framebuffer<Rp, A> where Rp: RenderPassDes
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<At, Rp, A> RenderPassDescAttachmentsList<At> for Framebuffer<Rp, A>
|
||||
where Rp: RenderPassDescAttachmentsList<At>
|
||||
{
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, atch: At) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
self.render_pass.check_attachments_list(atch)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<C, Rp, A> RenderPassDescClearValues<C> for Framebuffer<Rp, A>
|
||||
where Rp: RenderPassDescClearValues<C>
|
||||
{
|
||||
@ -441,8 +466,13 @@ pub enum FramebufferCreationError {
|
||||
OomError(OomError),
|
||||
/// The requested dimensions exceed the device's limits.
|
||||
DimensionsTooLarge,
|
||||
/// One of the attachments is too small compared to the requested framebuffer dimensions.
|
||||
AttachmentTooSmall,
|
||||
/// The attachment has a size that isn't compatible with the requested framebuffer dimensions.
|
||||
AttachmentDimensionsIncompatible {
|
||||
/// Expected dimensions.
|
||||
expected: [u32; 3],
|
||||
/// Attachment dimensions.
|
||||
obtained: [u32; 3],
|
||||
},
|
||||
/// The number of attachments doesn't match the number expected by the render pass.
|
||||
AttachmentsCountMismatch {
|
||||
/// Expected number of attachments.
|
||||
@ -451,12 +481,9 @@ pub enum FramebufferCreationError {
|
||||
obtained: usize,
|
||||
},
|
||||
/// One of the images cannot be used as the requested attachment.
|
||||
IncompatibleAttachment {
|
||||
/// Zero-based id of the attachment.
|
||||
attachment_num: usize,
|
||||
/// The problem.
|
||||
error: IncompatibleRenderPassAttachmentError,
|
||||
},
|
||||
IncompatibleAttachment(IncompatibleRenderPassAttachmentError),
|
||||
/// The framebuffer has no attachment and no dimension was specified.
|
||||
CantDetermineDimensions,
|
||||
}
|
||||
|
||||
impl From<OomError> for FramebufferCreationError {
|
||||
@ -473,16 +500,18 @@ impl error::Error for FramebufferCreationError {
|
||||
FramebufferCreationError::OomError(_) => "no memory available",
|
||||
FramebufferCreationError::DimensionsTooLarge => "the dimensions of the framebuffer \
|
||||
are too large",
|
||||
FramebufferCreationError::AttachmentTooSmall => {
|
||||
"one of the attachments is too small compared to the requested framebuffer \
|
||||
dimensions"
|
||||
FramebufferCreationError::AttachmentDimensionsIncompatible { .. } => {
|
||||
"the attachment has a size that isn't compatible with the framebuffer dimensions"
|
||||
},
|
||||
FramebufferCreationError::AttachmentsCountMismatch { .. } => {
|
||||
"the number of attachments doesn't match the number expected by the render pass"
|
||||
},
|
||||
FramebufferCreationError::IncompatibleAttachment { .. } => {
|
||||
FramebufferCreationError::IncompatibleAttachment(_) => {
|
||||
"one of the images cannot be used as the requested attachment"
|
||||
},
|
||||
FramebufferCreationError::CantDetermineDimensions => {
|
||||
"the framebuffer has no attachment and no dimension was specified"
|
||||
},
|
||||
}
|
||||
}
|
||||
|
||||
@ -490,7 +519,7 @@ impl error::Error for FramebufferCreationError {
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
match *self {
|
||||
FramebufferCreationError::OomError(ref err) => Some(err),
|
||||
FramebufferCreationError::IncompatibleAttachment { ref error, .. } => Some(error),
|
||||
FramebufferCreationError::IncompatibleAttachment(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -510,70 +539,314 @@ impl From<Error> for FramebufferCreationError {
|
||||
}
|
||||
}
|
||||
|
||||
/* FIXME: restore
|
||||
#[cfg(test)]
|
||||
mod tests {
|
||||
use format::R8G8B8A8Unorm;
|
||||
use std::sync::Arc;
|
||||
use format::Format;
|
||||
use framebuffer::EmptySinglePassRenderPassDesc;
|
||||
use framebuffer::Framebuffer;
|
||||
use framebuffer::FramebufferCreationError;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use image::attachment::AttachmentImage;
|
||||
|
||||
#[test]
|
||||
fn simple_create() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = single_pass_renderpass! {
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: R8G8B8A8Unorm,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [color],
|
||||
depth_stencil: {}
|
||||
}
|
||||
}.unwrap();
|
||||
).unwrap());
|
||||
|
||||
let image = AttachmentImage::new(&device, [1024, 768], R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let _ = Framebuffer::new(render_pass, [1024, 768, 1], example::AList {
|
||||
color: image.clone()
|
||||
}).unwrap();
|
||||
let image = AttachmentImage::new(device.clone(), [1024, 768],
|
||||
Format::R8G8B8A8Unorm).unwrap();
|
||||
let _ = Framebuffer::start(render_pass).add(image.clone()).unwrap().build().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn framebuffer_too_large() {
|
||||
fn check_device_limits() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = example::CustomRenderPass::new(&device, &example::Formats {
|
||||
color: (R8G8B8A8Unorm, 1)
|
||||
}).unwrap();
|
||||
|
||||
let image = AttachmentImage::new(&device, [1024, 768], R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let alist = example::AList { color: image.clone() };
|
||||
match Framebuffer::new(render_pass, [0xffffffff, 0xffffffff, 0xffffffff], alist) {
|
||||
let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap();
|
||||
let res = Framebuffer::with_dimensions(rp, [0xffffffff, 0xffffffff, 0xffffffff]).build();
|
||||
match res {
|
||||
Err(FramebufferCreationError::DimensionsTooLarge) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_too_small() {
|
||||
fn attachment_format_mismatch() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = example::CustomRenderPass::new(&device, &example::Formats {
|
||||
color: (R8G8B8A8Unorm, 1)
|
||||
}).unwrap();
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [color],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let image = AttachmentImage::new(&device, [512, 512], R8G8B8A8Unorm).unwrap();
|
||||
let image = AttachmentImage::new(device.clone(), [1024, 768],
|
||||
Format::R8Unorm).unwrap();
|
||||
|
||||
let alist = example::AList { color: image.clone() };
|
||||
match Framebuffer::new(render_pass, [600, 600, 1], alist) {
|
||||
Err(FramebufferCreationError::AttachmentTooSmall) => (),
|
||||
match Framebuffer::start(render_pass).add(image.clone()) {
|
||||
Err(FramebufferCreationError::IncompatibleAttachment(_)) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
}*/
|
||||
|
||||
// TODO: check samples mismatch
|
||||
|
||||
#[test]
|
||||
fn attachment_dims_larger_than_specified_valid() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [color],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let img = AttachmentImage::new(device.clone(), [600, 600], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let _ = Framebuffer::with_dimensions(render_pass, [512, 512, 1])
|
||||
.add(img).unwrap()
|
||||
.build().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn attachment_dims_smaller_than_specified() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
color: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [color],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let img = AttachmentImage::new(device.clone(), [512, 700], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
match Framebuffer::with_dimensions(render_pass, [600, 600, 1]).add(img) {
|
||||
Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected, obtained }) => {
|
||||
assert_eq!(expected, [600, 600, 1]);
|
||||
assert_eq!(obtained, [512, 700, 1]);
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_attachments_dims_not_identical() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
a: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
},
|
||||
b: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [a, b],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let a = AttachmentImage::new(device.clone(), [512, 512], Format::R8G8B8A8Unorm).unwrap();
|
||||
let b = AttachmentImage::new(device.clone(), [512, 513], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
match Framebuffer::start(render_pass).add(a).unwrap().add(b) {
|
||||
Err(FramebufferCreationError::AttachmentDimensionsIncompatible { expected, obtained }) => {
|
||||
assert_eq!(expected, [512, 512, 1]);
|
||||
assert_eq!(obtained, [512, 513, 1]);
|
||||
},
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn multi_attachments_auto_smaller() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
a: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
},
|
||||
b: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [a, b],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let a = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap();
|
||||
let b = AttachmentImage::new(device.clone(), [512, 128], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let fb = Framebuffer::with_intersecting_dimensions(render_pass)
|
||||
.add(a).unwrap()
|
||||
.add(b).unwrap()
|
||||
.build().unwrap();
|
||||
|
||||
match (fb.width(), fb.height(), fb.layers()) {
|
||||
(256, 128, 1) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn not_enough_attachments() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
a: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
},
|
||||
b: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [a, b],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let img = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let res = Framebuffer::with_intersecting_dimensions(render_pass)
|
||||
.add(img).unwrap()
|
||||
.build();
|
||||
|
||||
match res {
|
||||
Err(FramebufferCreationError::AttachmentsCountMismatch { expected: 2,
|
||||
obtained: 1 }) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn too_many_attachments() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let render_pass = Arc::new(single_pass_renderpass!(device.clone(),
|
||||
attachments: {
|
||||
a: {
|
||||
load: Clear,
|
||||
store: DontCare,
|
||||
format: Format::R8G8B8A8Unorm,
|
||||
samples: 1,
|
||||
}
|
||||
},
|
||||
pass: {
|
||||
color: [a],
|
||||
depth_stencil: {}
|
||||
}
|
||||
).unwrap());
|
||||
|
||||
let a = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap();
|
||||
let b = AttachmentImage::new(device.clone(), [256, 512], Format::R8G8B8A8Unorm).unwrap();
|
||||
|
||||
let res = Framebuffer::with_intersecting_dimensions(render_pass)
|
||||
.add(a).unwrap()
|
||||
.add(b);
|
||||
|
||||
match res {
|
||||
Err(FramebufferCreationError::AttachmentsCountMismatch { expected: 1,
|
||||
obtained: 2 }) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn empty_working() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap();
|
||||
let _ = Framebuffer::with_dimensions(rp, [512, 512, 1]).build().unwrap();
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cant_determine_dimensions_auto() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap();
|
||||
let res = Framebuffer::start(rp).build();
|
||||
match res {
|
||||
Err(FramebufferCreationError::CantDetermineDimensions) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
|
||||
#[test]
|
||||
fn cant_determine_dimensions_intersect() {
|
||||
let (device, _) = gfx_dev_and_queue!();
|
||||
|
||||
let rp = EmptySinglePassRenderPassDesc.build_render_pass(device).unwrap();
|
||||
let res = Framebuffer::with_intersecting_dimensions(rp).build();
|
||||
match res {
|
||||
Err(FramebufferCreationError::CantDetermineDimensions) => (),
|
||||
_ => panic!()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -65,20 +65,14 @@ macro_rules! ordered_passes_renderpass {
|
||||
#![allow(non_camel_case_types)]
|
||||
#![allow(non_snake_case)]
|
||||
|
||||
use std::sync::Arc;
|
||||
use $crate::format::ClearValue;
|
||||
use $crate::format::Format;
|
||||
use $crate::framebuffer::AttachmentsList;
|
||||
use $crate::framebuffer::FramebufferCreationError;
|
||||
use $crate::framebuffer::RenderPassDesc;
|
||||
use $crate::framebuffer::RenderPassDescAttachmentsList;
|
||||
use $crate::framebuffer::RenderPassDescClearValues;
|
||||
use $crate::framebuffer::LayoutAttachmentDescription;
|
||||
use $crate::framebuffer::LayoutPassDescription;
|
||||
use $crate::framebuffer::LayoutPassDependencyDescription;
|
||||
use $crate::framebuffer::ensure_image_view_compatible;
|
||||
use $crate::image::ImageLayout;
|
||||
use $crate::image::ImageViewAccess;
|
||||
use $crate::sync::AccessFlagBits;
|
||||
use $crate::sync::PipelineStages;
|
||||
|
||||
@ -128,29 +122,6 @@ macro_rules! ordered_passes_renderpass {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl RenderPassDescAttachmentsList<Vec<Arc<ImageViewAccess + Send + Sync>>> for CustomRenderPassDesc {
|
||||
fn check_attachments_list(&self, list: Vec<Arc<ImageViewAccess + Send + Sync>>) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
if list.len() != self.num_attachments() {
|
||||
return Err(FramebufferCreationError::AttachmentsCountMismatch {
|
||||
expected: self.num_attachments(),
|
||||
obtained: list.len(),
|
||||
});
|
||||
}
|
||||
|
||||
for n in 0 .. self.num_attachments() {
|
||||
match ensure_image_view_compatible(self, n, &*list[n]) {
|
||||
Ok(()) => (),
|
||||
Err(err) => return Err(FramebufferCreationError::IncompatibleAttachment {
|
||||
attachment_num: n,
|
||||
error: err,
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
Ok(Box::new(list) as Box<_>)
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_attachments() -> usize {
|
||||
#![allow(unused_assignments)]
|
||||
|
@ -104,6 +104,7 @@ pub use self::desc::StoreOp;
|
||||
pub use self::desc::LoadOp;
|
||||
pub use self::empty::EmptySinglePassRenderPassDesc;
|
||||
pub use self::framebuffer::Framebuffer;
|
||||
pub use self::framebuffer::FramebufferBuilder;
|
||||
pub use self::framebuffer::FramebufferCreationError;
|
||||
pub use self::framebuffer::FramebufferSys;
|
||||
pub use self::sys::RenderPass;
|
||||
@ -112,7 +113,6 @@ pub use self::sys::RenderPassSys;
|
||||
pub use self::traits::FramebufferAbstract;
|
||||
pub use self::traits::RenderPassDescClearValues;
|
||||
pub use self::traits::RenderPassCompatible;
|
||||
pub use self::traits::RenderPassDescAttachmentsList;
|
||||
pub use self::traits::RenderPassAbstract;
|
||||
pub use self::traits::RenderPassSubpassInterface;
|
||||
pub use self::traits::Subpass;
|
||||
|
@ -19,15 +19,12 @@ use smallvec::SmallVec;
|
||||
use device::Device;
|
||||
use device::DeviceOwned;
|
||||
use format::ClearValue;
|
||||
use framebuffer::AttachmentsList;
|
||||
use framebuffer::EmptySinglePassRenderPassDesc;
|
||||
use framebuffer::FramebufferCreationError;
|
||||
use framebuffer::LayoutAttachmentDescription;
|
||||
use framebuffer::LayoutPassDependencyDescription;
|
||||
use framebuffer::LayoutPassDescription;
|
||||
use framebuffer::LoadOp;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
use framebuffer::RenderPassDescAttachmentsList;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use framebuffer::RenderPassAbstract;
|
||||
|
||||
@ -361,15 +358,6 @@ unsafe impl<D> RenderPassDesc for RenderPass<D> where D: RenderPassDesc {
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A, D> RenderPassDescAttachmentsList<A> for RenderPass<D>
|
||||
where D: RenderPassDescAttachmentsList<A>
|
||||
{
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, atch: A) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
self.desc.check_attachments_list(atch)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<C, D> RenderPassDescClearValues<C> for RenderPass<D>
|
||||
where D: RenderPassDescClearValues<C>
|
||||
{
|
||||
|
@ -9,8 +9,6 @@
|
||||
|
||||
use device::DeviceOwned;
|
||||
use format::ClearValue;
|
||||
use framebuffer::AttachmentsList;
|
||||
use framebuffer::FramebufferCreationError;
|
||||
use framebuffer::FramebufferSys;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use framebuffer::RenderPassSys;
|
||||
@ -108,40 +106,6 @@ unsafe impl<T> RenderPassAbstract for T where T: SafeDeref, T::Target: RenderPas
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for `RenderPassDesc`. Defines which types are allowed as an attachments list.
|
||||
///
|
||||
/// When the user creates a framebuffer, they need to pass a render pass object and a list of
|
||||
/// attachments. In order for it to work, the render pass object must implement
|
||||
/// `RenderPassDescAttachmentsList<A>` where `A` is the type of the list of attachments.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// This trait is unsafe because it's the job of the implementation to check whether the
|
||||
/// attachments list is correct. What needs to be checked:
|
||||
///
|
||||
/// - That the attachments' format and samples count match the render pass layout.
|
||||
/// - That the attachments have been created with the proper usage flags.
|
||||
/// - That the attachments only expose one mipmap.
|
||||
/// - That the attachments use identity components swizzling.
|
||||
/// TODO: more stuff with aliasing
|
||||
///
|
||||
pub unsafe trait RenderPassDescAttachmentsList<A> {
|
||||
/// Decodes a `A` into a list of attachments.
|
||||
///
|
||||
/// 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<Box<AttachmentsList + Send + Sync>, FramebufferCreationError>;
|
||||
}
|
||||
|
||||
unsafe impl<A, T> RenderPassDescAttachmentsList<A> for T
|
||||
where T: SafeDeref, T::Target: RenderPassDescAttachmentsList<A>
|
||||
{
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, atch: A) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
(**self).check_attachments_list(atch)
|
||||
}
|
||||
}
|
||||
|
||||
/// Extension trait for `RenderPassDesc`. Defines which types are allowed as a list of clear values.
|
||||
///
|
||||
/// When the user enters a render pass, they need to pass a list of clear values to apply to
|
||||
|
@ -33,14 +33,11 @@ use descriptor::pipeline_layout::PipelineLayoutNotSupersetError;
|
||||
use descriptor::pipeline_layout::PipelineLayoutSys;
|
||||
use descriptor::pipeline_layout::EmptyPipelineDesc;
|
||||
use format::ClearValue;
|
||||
use framebuffer::AttachmentsList;
|
||||
use framebuffer::LayoutAttachmentDescription;
|
||||
use framebuffer::LayoutPassDescription;
|
||||
use framebuffer::LayoutPassDependencyDescription;
|
||||
use framebuffer::FramebufferCreationError;
|
||||
use framebuffer::RenderPassAbstract;
|
||||
use framebuffer::RenderPassDesc;
|
||||
use framebuffer::RenderPassDescAttachmentsList;
|
||||
use framebuffer::RenderPassDescClearValues;
|
||||
use framebuffer::RenderPassSubpassInterface;
|
||||
use framebuffer::RenderPassSys;
|
||||
@ -1178,15 +1175,6 @@ unsafe impl<Mv, L, Rp> RenderPassDesc for GraphicsPipeline<Mv, L, Rp>
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<A, Mv, L, Rp> RenderPassDescAttachmentsList<A> for GraphicsPipeline<Mv, L, Rp>
|
||||
where Rp: RenderPassDescAttachmentsList<A>
|
||||
{
|
||||
#[inline]
|
||||
fn check_attachments_list(&self, atch: A) -> Result<Box<AttachmentsList + Send + Sync>, FramebufferCreationError> {
|
||||
self.render_pass.check_attachments_list(atch)
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<C, Mv, L, Rp> RenderPassDescClearValues<C> for GraphicsPipeline<Mv, L, Rp>
|
||||
where Rp: RenderPassDescClearValues<C>
|
||||
{
|
||||
|
Loading…
Reference in New Issue
Block a user