Merge pull request #9 from tomaka/fb-rework

Fb rework
This commit is contained in:
tomaka 2016-03-14 11:25:44 +01:00
commit b2713c745c
7 changed files with 340 additions and 310 deletions

View File

@ -109,7 +109,7 @@ fn main() {
}
}
let renderpass = vulkano::framebuffer::RenderPass::new(&device, renderpass::Layout).unwrap();
let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();
let texture = vulkano::image::Image::<vulkano::image::Type2d, _, _>::new(&device, &vulkano::image::Usage::all(),
vulkano::memory::DeviceLocal, &queue,

View File

@ -161,7 +161,7 @@ fn main() {
}
}
let renderpass = vulkano::framebuffer::RenderPass::new(&device, renderpass::Layout).unwrap();
let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();
let descriptor_pool = vulkano::descriptor_set::DescriptorPool::new(&device).unwrap();
let descriptor_set_layout = vulkano::descriptor_set::DescriptorSetLayout::new(&device, vs::Set0).unwrap();

View File

@ -176,7 +176,7 @@ fn main() {
}
}
let renderpass = vulkano::framebuffer::RenderPass::new(&device, renderpass::Layout).unwrap();
let renderpass = renderpass::CustomRenderPass::new(&device).unwrap();
let pipeline = {
let ia = vulkano::pipeline::input_assembly::InputAssembly::triangle_list();

View File

@ -18,11 +18,9 @@ use format::PossibleFloatOrCompressedFormatDesc;
use format::PossibleFloatFormatDesc;
use format::StrongStorage;
use framebuffer::AbstractFramebuffer;
use framebuffer::AbstractRenderPass;
use framebuffer::Framebuffer;
use framebuffer::RenderPass;
use framebuffer::Framebuffer;
use framebuffer::Subpass;
use framebuffer::Layout as RenderPassLayout;
use image::AbstractImage;
use image::AbstractImageView;
use image::Image;
@ -63,7 +61,7 @@ pub struct InnerCommandBufferBuilder {
framebuffers: Vec<Arc<AbstractFramebuffer>>,
// List of renderpasses used in this CB.
renderpasses: Vec<Arc<AbstractRenderPass>>,
renderpasses: Vec<Arc<RenderPass>>,
// List of all resources that are used by this command buffer.
buffer_resources: Vec<Arc<AbstractBuffer>>,
@ -94,7 +92,7 @@ impl InnerCommandBufferBuilder {
pub fn new<R>(pool: &Arc<CommandBufferPool>, secondary: bool, secondary_cont: Option<Subpass<R>>,
secondary_cont_fb: Option<&Arc<Framebuffer<R>>>)
-> Result<InnerCommandBufferBuilder, OomError>
where R: 'static
where R: RenderPass + 'static
{
let device = pool.device();
let vk = device.pointers();
@ -132,7 +130,7 @@ impl InnerCommandBufferBuilder {
let (rp, sp) = if let Some(ref sp) = secondary_cont {
renderpasses.push(sp.render_pass().clone() as Arc<_>);
(sp.render_pass().internal_object(), sp.index())
(sp.render_pass().render_pass().internal_object(), sp.index())
} else {
(0, 0)
};
@ -585,16 +583,16 @@ impl InnerCommandBufferBuilder {
/// - Care must be taken to respect the rules about secondary command buffers.
///
#[inline]
pub unsafe fn begin_renderpass<R, F>(mut self, renderpass: &Arc<RenderPass<R>>,
pub unsafe fn begin_renderpass<R, F>(mut self, render_pass: &Arc<R>,
framebuffer: &Arc<Framebuffer<F>>,
secondary_cmd_buffers: bool,
clear_values: &[ClearValue]) -> InnerCommandBufferBuilder
where R: RenderPassLayout + 'static, F: RenderPassLayout + 'static
where R: RenderPass + 'static, F: RenderPass + 'static
{
assert!(framebuffer.is_compatible_with(renderpass));
assert!(framebuffer.is_compatible_with(render_pass));
self.framebuffers.push(framebuffer.clone() as Arc<_>);
self.renderpasses.push(renderpass.clone() as Arc<_>);
self.renderpasses.push(render_pass.clone() as Arc<_>);
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let clear_values = clear_values.iter().map(|value| {
@ -629,7 +627,7 @@ impl InnerCommandBufferBuilder {
let infos = vk::RenderPassBeginInfo {
sType: vk::STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,
pNext: ptr::null(),
renderPass: renderpass.internal_object(),
renderPass: render_pass.render_pass().internal_object(),
framebuffer: framebuffer.internal_object(),
renderArea: vk::Rect2D { // TODO: let user customize
offset: vk::Offset2D { x: 0, y: 0 },
@ -772,7 +770,7 @@ pub struct InnerCommandBuffer {
secondary_command_buffers: Vec<Arc<AbstractCommandBuffer>>,
descriptor_sets: Vec<Arc<AbstractDescriptorSet>>,
framebuffers: Vec<Arc<AbstractFramebuffer>>,
renderpasses: Vec<Arc<AbstractRenderPass>>,
renderpasses: Vec<Arc<RenderPass>>,
buffer_resources: Vec<Arc<AbstractBuffer>>,
image_resources: Vec<Arc<AbstractImage>>,
image_views_resources: Vec<Arc<AbstractImageView>>,

View File

@ -15,10 +15,10 @@ use format::PossibleFloatOrCompressedFormatDesc;
use format::PossibleFloatFormatDesc;
use format::StrongStorage;
use framebuffer::Framebuffer;
use framebuffer::UnsafeRenderPass;
use framebuffer::RenderPassCompatible;
use framebuffer::RenderPass;
use framebuffer::LayoutCompatible as RenderPassLayoutCompatible;
use framebuffer::Layout as RenderPassLayout;
use framebuffer::LayoutClearValues as RenderPassLayoutClearValues;
use framebuffer::RenderPassClearValues;
use framebuffer::Subpass;
use image::Image;
use image::ImageTypeMarker;
@ -55,7 +55,7 @@ impl PrimaryCommandBufferBuilder {
pub fn new(pool: &Arc<CommandBufferPool>)
-> Result<PrimaryCommandBufferBuilder, OomError>
{
let inner = try!(InnerCommandBufferBuilder::new::<()>(pool, false, None, None));
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, false, None, None));
Ok(PrimaryCommandBufferBuilder { inner: inner })
}
@ -171,15 +171,15 @@ impl PrimaryCommandBufferBuilder {
///
// FIXME: rest of the parameters (render area and clear attachment values)
#[inline]
pub fn draw_inline<R, F, C>(self, renderpass: &Arc<RenderPass<R>>,
pub fn draw_inline<R, F, C>(self, renderpass: &Arc<R>,
framebuffer: &Arc<Framebuffer<F>>, clear_values: C)
-> PrimaryCommandBufferBuilderInlineDraw
where F: RenderPassLayout + RenderPassLayoutClearValues<C> + 'static, R: RenderPassLayout + 'static
where F: RenderPass + RenderPassClearValues<C> + 'static, R: RenderPass + 'static
{
// FIXME: check for compatibility
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let clear_values = framebuffer.renderpass().layout().convert_clear_values(clear_values)
let clear_values = framebuffer.render_pass().convert_clear_values(clear_values)
.collect::<Vec<_>>();
unsafe {
@ -188,7 +188,7 @@ impl PrimaryCommandBufferBuilder {
PrimaryCommandBufferBuilderInlineDraw {
inner: inner,
current_subpass: 0,
num_subpasses: framebuffer.renderpass().num_subpasses(),
num_subpasses: framebuffer.render_pass().num_subpasses(),
}
}
}
@ -204,16 +204,16 @@ impl PrimaryCommandBufferBuilder {
///
// FIXME: rest of the parameters (render area and clear attachment values)
#[inline]
pub fn draw_secondary<R, F, C>(self, renderpass: &Arc<RenderPass<R>>,
pub fn draw_secondary<R, F, C>(self, renderpass: &Arc<R>,
framebuffer: &Arc<Framebuffer<F>>, clear_values: C)
-> PrimaryCommandBufferBuilderSecondaryDraw
where F: RenderPassLayout + RenderPassLayoutClearValues<C> + 'static,
R: RenderPassLayout + 'static
where F: RenderPass + RenderPassClearValues<C> + 'static,
R: RenderPass + 'static
{
// FIXME: check for compatibility
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let clear_values = framebuffer.renderpass().layout().convert_clear_values(clear_values)
let clear_values = framebuffer.render_pass().convert_clear_values(clear_values)
.collect::<Vec<_>>();
unsafe {
@ -222,7 +222,7 @@ impl PrimaryCommandBufferBuilder {
PrimaryCommandBufferBuilderSecondaryDraw {
inner: inner,
current_subpass: 0,
num_subpasses: framebuffer.renderpass().num_subpasses(),
num_subpasses: framebuffer.render_pass().num_subpasses(),
}
}
}
@ -464,13 +464,13 @@ impl AbstractCommandBuffer for PrimaryCommandBuffer {}
/// A prototype of a secondary compute command buffer.
pub struct SecondaryGraphicsCommandBufferBuilder<R> {
inner: InnerCommandBufferBuilder,
renderpass_layout: R,
renderpass_subpass: u32,
render_pass: Arc<R>,
render_pass_subpass: u32,
framebuffer: Option<Arc<Framebuffer<R>>>,
}
impl<R> SecondaryGraphicsCommandBufferBuilder<R>
where R: RenderPassLayout
where R: RenderPass + 'static
{
/// Builds a new secondary command buffer and start recording commands in it.
///
@ -479,13 +479,12 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
pub fn new(pool: &Arc<CommandBufferPool>, subpass: Subpass<R>,
framebuffer: Option<&Arc<Framebuffer<R>>>)
-> Result<SecondaryGraphicsCommandBufferBuilder<R>, OomError>
where R: Clone + 'static
{
let inner = try!(InnerCommandBufferBuilder::new(pool, true, Some(subpass), framebuffer.clone()));
Ok(SecondaryGraphicsCommandBufferBuilder {
inner: inner,
renderpass_layout: subpass.render_pass().layout().clone(),
renderpass_subpass: subpass.index(),
render_pass: subpass.render_pass().clone(),
render_pass_subpass: subpass.index(),
framebuffer: framebuffer.map(|fb| fb.clone()),
})
}
@ -496,17 +495,17 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
vertices: V, dynamic: &DynamicState, sets: L)
-> SecondaryGraphicsCommandBufferBuilder<R>
where Pv: VertexDefinition + VertexSource<V> + 'static, Pl: PipelineLayoutDesc + 'static,
Rp: RenderPassLayout + 'static, L: DescriptorSetsCollection + 'static,
R: RenderPassLayoutCompatible<Rp>
Rp: RenderPass + 'static, L: DescriptorSetsCollection + 'static,
R: RenderPassCompatible<Rp>
{
assert!(self.renderpass_layout.is_compatible_with(pipeline.subpass().render_pass().layout()));
assert_eq!(self.renderpass_subpass, pipeline.subpass().index());
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
unsafe {
SecondaryGraphicsCommandBufferBuilder {
inner: self.inner.draw(pipeline, vertices, dynamic, sets),
renderpass_layout: self.renderpass_layout,
renderpass_subpass: self.renderpass_subpass,
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
framebuffer: self.framebuffer,
}
}
@ -517,19 +516,19 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
vertices: V, indices: Ib, dynamic: &DynamicState,
sets: L) -> SecondaryGraphicsCommandBufferBuilder<R>
where Pv: 'static + VertexDefinition + VertexSource<V>, Pl: 'static + PipelineLayoutDesc,
Rp: RenderPassLayout + 'static,
Rp: RenderPass + 'static,
Ib: Into<BufferSlice<'a, [I], Ibo, Ibm>>, I: 'static + Index,
L: DescriptorSetsCollection + 'static,
Ibm: MemorySourceChunk
{
assert!(self.renderpass_layout.is_compatible_with(pipeline.subpass().render_pass().layout()));
assert_eq!(self.renderpass_subpass, pipeline.subpass().index());
assert!(self.render_pass.is_compatible_with(pipeline.subpass().render_pass()));
assert_eq!(self.render_pass_subpass, pipeline.subpass().index());
unsafe {
SecondaryGraphicsCommandBufferBuilder {
inner: self.inner.draw_indexed(pipeline, vertices, indices, dynamic, sets),
renderpass_layout: self.renderpass_layout,
renderpass_subpass: self.renderpass_subpass,
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
framebuffer: self.framebuffer,
}
}
@ -542,8 +541,8 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
Ok(Arc::new(SecondaryGraphicsCommandBuffer {
inner: inner,
renderpass_layout: self.renderpass_layout,
renderpass_subpass: self.renderpass_subpass,
render_pass: self.render_pass,
render_pass_subpass: self.render_pass_subpass,
}))
}
}
@ -557,8 +556,8 @@ impl<R> SecondaryGraphicsCommandBufferBuilder<R>
/// A secondary graphics command buffer can't be called outside of a renderpass.
pub struct SecondaryGraphicsCommandBuffer<R> {
inner: InnerCommandBuffer,
renderpass_layout: R,
renderpass_subpass: u32,
render_pass: Arc<R>,
render_pass_subpass: u32,
}
impl<R> AbstractCommandBuffer for SecondaryGraphicsCommandBuffer<R> {}
@ -574,7 +573,7 @@ impl SecondaryComputeCommandBufferBuilder {
pub fn new(pool: &Arc<CommandBufferPool>)
-> Result<SecondaryComputeCommandBufferBuilder, OomError>
{
let inner = try!(InnerCommandBufferBuilder::new::<()>(pool, true, None, None));
let inner = try!(InnerCommandBufferBuilder::new::<UnsafeRenderPass>(pool, true, None, None));
Ok(SecondaryComputeCommandBufferBuilder { inner: inner })
}

View File

@ -8,9 +8,9 @@
//! the format and dimensions of the attachments that are part of the subpass. The render
//! pass only defines the layout of the rendering process.
//! - A `Framebuffer` contains the list of actual images that are attached. It is created from a
//! `RenderPass` and has to match its characteristics.
//! `UnsafeRenderPass` and has to match its characteristics.
//!
//! This split means that you can create graphics pipelines from a `RenderPass` alone.
//! This split means that you can create graphics pipelines from a `UnsafeRenderPass` alone.
//! A `Framebuffer` is only needed when you add draw commands to a command buffer.
//!
//! # Render passes
@ -24,27 +24,27 @@
//! subpasses, which means that you need to declare dependencies if the output of a subpass
//! needs to be read in a following subpass.
//!
//! Before you can create a `RenderPass` object with the vulkano library, you have to create an
//! object that can describe these three lists through `Layout` trait. This trait is
//! unsafe because the information that its methods return is trusted blindly by vulkano.
//! In vulkano, a render pass is any object that implements the `RenderPass` trait.
//!
//! You can create a render pass by creating a `UnsafeRenderPass` object. But as its name tells,
//! it is unsafe because it doesn't perform some checks.
//!
//! Instead you are encouraged to use a safe wrapper around an `UnsafeRenderPass`.
//! There are two ways to do this: TODO add more ways
//!
//! - Creating an instance of an `EmptySinglePassLayout`, which describes a renderpass with no
//! - Creating an instance of an `EmptySinglePassRenderPass`, which describes a renderpass with no
//! attachment and with one subpass.
//! - Using the `single_pass_renderpass!` macro. See the documentation of this macro.
//!
//! ## Example
//!
//! With `EmptySinglePassLayout`:
//! With `EmptySinglePassRenderPass`:
//!
//! ```no_run
//! use vulkano::framebuffer::RenderPass;
//! use vulkano::framebuffer::EmptySinglePassLayout;
//! use vulkano::framebuffer::EmptySinglePassRenderPass;
//!
//! # let device: std::sync::Arc<vulkano::device::Device> = unsafe { ::std::mem::uninitialized() };
//! let renderpass = RenderPass::new(&device, EmptySinglePassLayout).unwrap();
//! // the type of `renderpass` is `RenderPass<EmptySinglePassLayout>`
//! let renderpass = EmptySinglePassRenderPass::new(&device).unwrap();
//! ```
//!
//! # Framebuffers
@ -53,10 +53,10 @@
//! framebuffer, and the list of attachments to `Framebuffer::new()`.
//!
//! The slightly tricky part is that the list of attachments depends on the trait implementation
//! of `Layout`. For example if you use an `EmptySinglePassLayout`, you have to pass
//! of `RenderPass`. For example if you use an `EmptySinglePassRenderPass`, you have to pass
//! `()` for the list of attachments.
//!
//! Some implementations of `Layout` can use strong typing for the attachments list, in
//! Some implementations of `RenderPass` can use strong typing for the attachments list, in
//! order to produce a compilation error if you pass the wrong kind of attachment. Other
//! implementations may have more relaxed rules and check the format of the attachments at runtime
//! instead.
@ -66,7 +66,6 @@ use std::fmt;
use std::iter;
use std::iter::Empty as EmptyIter;
use std::mem;
use std::option::IntoIter as OptionIntoIter;
use std::ptr;
use std::sync::Arc;
@ -84,29 +83,25 @@ use VulkanPointers;
use check_errors;
use vk;
/// Types that describes the characteristics of a renderpass.
pub unsafe trait Layout {
/// Iterator that produces attachments.
type AttachmentsDescIter: ExactSizeIterator<Item = LayoutAttachmentDescription>;
/// Trait for objects that describe a render pass.
///
/// # Safety
///
/// This trait is unsafe because:
///
/// - `render_pass` has to return the same `UnsafeRenderPass` every time.
/// - `num_subpasses` has to return a correct value.
///
pub unsafe trait RenderPass {
/// Returns the underlying `UnsafeRenderPass`. Used by vulkano's internals.
fn render_pass(&self) -> &UnsafeRenderPass;
/// Returns the descriptions of the attachments.
fn attachments(&self) -> Self::AttachmentsDescIter;
/// Iterator that produces passes.
type PassesIter: ExactSizeIterator<Item = LayoutPassDescription>;
/// Returns the descriptions of the passes.
fn passes(&self) -> Self::PassesIter;
/// Iterator that produces pass dependencies.
type PassDependenciesIter: ExactSizeIterator<Item = LayoutPassDependencyDescription>;
/// Returns the descriptions of the dependencies between passes.
fn pass_dependencies(&self) -> Self::PassDependenciesIter;
/// Returns the number of subpasses within the render pass.
fn num_subpasses(&self) -> u32;
}
/// Extension trait for `Layout`. Defines which types are allowed as an attachments list.
pub unsafe trait LayoutAttachmentsList<A>: Layout {
/// Extension trait for `RenderPass`. Defines which types are allowed as an attachments list.
pub unsafe trait RenderPassAttachmentsList<A>: RenderPass {
/// A decoded `A`.
type AttachmentsIter: ExactSizeIterator<Item = Arc<AbstractImageView>>;
@ -114,8 +109,8 @@ pub unsafe trait LayoutAttachmentsList<A>: Layout {
fn convert_attachments_list(&self, A) -> Self::AttachmentsIter;
}
/// Extension trait for `Layout`. Defines which types are allowed as a list of clear values.
pub unsafe trait LayoutClearValues<C>: Layout {
/// Extension trait for `RenderPass`. Defines which types are allowed as a list of clear values.
pub unsafe trait RenderPassClearValues<C>: RenderPass {
/// Iterator that produces one clear value per attachment.
type ClearValuesIter: Iterator<Item = ClearValue>;
@ -128,28 +123,29 @@ pub unsafe trait LayoutClearValues<C>: Layout {
fn convert_clear_values(&self, C) -> Self::ClearValuesIter;
}
/// Trait implemented on renderpass layouts to check whether they are compatible
/// with another layout.
/// Trait implemented on render pass objects to check whether they are compatible
/// with another render pass.
///
/// The trait is automatically implemented for all type that implement `Layout`.
/// The trait is automatically implemented for all type that implement `RenderPass`.
// TODO: once specialization lands, this trait can be specialized for pairs that are known to
// always be compatible
// TODO: maybe this can be unimplemented on some pairs, to provide compile-time checks?
pub unsafe trait LayoutCompatible<Other>: Layout where Other: Layout {
pub unsafe trait RenderPassCompatible<Other>: RenderPass where Other: RenderPass {
/// Returns `true` if this layout is compatible with the other layout, as defined in the
/// `Render Pass Compatibility` section of the Vulkan specs.
fn is_compatible_with(&self, other: &Other) -> bool;
fn is_compatible_with(&self, other: &Arc<Other>) -> bool;
}
unsafe impl<A, B> LayoutCompatible<B> for A
where A: Layout, B: Layout
unsafe impl<A, B> RenderPassCompatible<B> for A
where A: RenderPass, B: RenderPass
{
fn is_compatible_with(&self, other: &B) -> bool {
for (atch1, atch2) in self.attachments().zip(other.attachments()) {
fn is_compatible_with(&self, other: &Arc<B>) -> bool {
// FIXME:
/*for (atch1, atch2) in self.attachments().zip(other.attachments()) {
if !atch1.is_compatible_with(&atch2) {
return false;
}
}
}*/
return true;
@ -157,7 +153,8 @@ unsafe impl<A, B> LayoutCompatible<B> for A
}
}
/// Describes an attachment that will be used in a renderpass.
/// Describes an attachment that will be used in a render pass.
#[derive(Debug, Clone)]
pub struct LayoutAttachmentDescription {
/// Format of the image that is going to be binded.
pub format: Format,
@ -188,11 +185,12 @@ impl LayoutAttachmentDescription {
}
}
/// Describes one of the passes of a renderpass.
/// Describes one of the passes of a render pass.
///
/// # Restrictions
///
/// All these restrictions are checked when the `RenderPass` object is created.
/// All these restrictions are checked when the `UnsafeRenderPass` object is created.
/// TODO: that's not the case ^
///
/// - The number of color attachments must be less than the limit of the physical device.
/// - All the attachments in `color_attachments` and `depth_stencil` must have the same
@ -210,6 +208,7 @@ impl LayoutAttachmentDescription {
///
// TODO: add tests for all these restrictions
// TODO: allow unused attachments (for example attachment 0 and 2 are used, 1 is unused)
#[derive(Debug, Clone)]
pub struct LayoutPassDescription {
/// Indices and layouts of attachments to use as color attachments.
pub color_attachments: Vec<(usize, ImageLayout)>, // TODO: Vec is slow
@ -230,12 +229,13 @@ pub struct LayoutPassDescription {
pub preserve_attachments: Vec<usize>, // TODO: Vec is slow
}
/// Describes a dependency between two passes of a renderpass.
/// Describes a dependency between two passes of a render pass.
///
/// The implementation is allowed to change the order of the passes within a renderpass, unless
/// The implementation is allowed to change the order of the passes within a render pass, unless
/// you specify that there exists a dependency between two passes (ie. the result of one will be
/// used as the input of another one).
// FIXME: finish
#[derive(Debug, Clone)]
pub struct LayoutPassDependencyDescription {
/// Index of the subpass that writes the data that `destination_subpass` is going to use.
pub source_subpass: usize,
@ -251,40 +251,48 @@ pub struct LayoutPassDependencyDescription {
pub by_region: bool,
}
/// Implementation of `Layout` with no attachment at all and a single pass.
#[derive(Debug, Copy, Clone)]
pub struct EmptySinglePassLayout;
/// Implementation of `RenderPass` with no attachment at all and a single pass.
///
/// When you use a `EmptySinglePassRenderPass`, the list of attachments and clear values must
/// be `()`.
pub struct EmptySinglePassRenderPass {
render_pass: UnsafeRenderPass,
}
unsafe impl Layout for EmptySinglePassLayout {
type AttachmentsDescIter = EmptyIter<LayoutAttachmentDescription>;
impl EmptySinglePassRenderPass {
/// Builds the render pass.
pub fn new(device: &Arc<Device>) -> Result<Arc<EmptySinglePassRenderPass>, OomError> {
let rp = try!(unsafe {
let pass = LayoutPassDescription {
color_attachments: vec![],
depth_stencil: None,
input_attachments: vec![],
resolve_attachments: vec![],
preserve_attachments: vec![],
};
#[inline]
fn attachments(&self) -> Self::AttachmentsDescIter {
iter::empty()
}
UnsafeRenderPass::new(device, iter::empty(), Some(pass).into_iter(), iter::empty())
});
type PassesIter = OptionIntoIter<LayoutPassDescription>;
#[inline]
fn passes(&self) -> Self::PassesIter {
Some(LayoutPassDescription {
color_attachments: vec![],
depth_stencil: None,
input_attachments: vec![],
resolve_attachments: vec![],
preserve_attachments: vec![],
}).into_iter()
}
type PassDependenciesIter = EmptyIter<LayoutPassDependencyDescription>;
#[inline]
fn pass_dependencies(&self) -> Self::PassDependenciesIter {
iter::empty()
Ok(Arc::new(EmptySinglePassRenderPass {
render_pass: rp
}))
}
}
unsafe impl LayoutAttachmentsList<()> for EmptySinglePassLayout {
unsafe impl RenderPass for EmptySinglePassRenderPass {
#[inline]
fn render_pass(&self) -> &UnsafeRenderPass {
&self.render_pass
}
#[inline]
fn num_subpasses(&self) -> u32 {
1
}
}
unsafe impl RenderPassAttachmentsList<()> for EmptySinglePassRenderPass {
type AttachmentsIter = EmptyIter<Arc<AbstractImageView>>;
#[inline]
@ -293,7 +301,7 @@ unsafe impl LayoutAttachmentsList<()> for EmptySinglePassLayout {
}
}
unsafe impl LayoutClearValues<()> for EmptySinglePassLayout {
unsafe impl RenderPassClearValues<()> for EmptySinglePassRenderPass {
type ClearValuesIter = EmptyIter<ClearValue>;
#[inline]
@ -302,7 +310,7 @@ unsafe impl LayoutClearValues<()> for EmptySinglePassLayout {
}
}
/// Builds a `RenderPass` object.
/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! single_pass_renderpass {
(
@ -325,7 +333,7 @@ macro_rules! single_pass_renderpass {
}
}
/// Builds a `RenderPass` object.
/// Builds a `CustomRenderPass` object that provides a safe wrapper around `UnsafeRenderPass`.
#[macro_export]
macro_rules! ordered_passes_renderpass {
(
@ -350,19 +358,20 @@ macro_rules! ordered_passes_renderpass {
) => {
use std; // TODO: import everything instead
use std::sync::Arc;
use $crate::OomError;
use $crate::device::Device;
use $crate::format::ClearValue;
use $crate::framebuffer::UnsafeRenderPass;
#[derive(Copy, Clone, Debug, PartialEq, Eq, Hash)]
pub struct Layout;
pub struct CustomRenderPass {
render_pass: UnsafeRenderPass
}
unsafe impl $crate::framebuffer::Layout for Layout {
type AttachmentsDescIter = std::vec::IntoIter<$crate::framebuffer::LayoutAttachmentDescription>;
type PassesIter = std::vec::IntoIter<$crate::framebuffer::LayoutPassDescription>;
type PassDependenciesIter = std::vec::IntoIter<$crate::framebuffer::LayoutPassDependencyDescription>;
impl CustomRenderPass {
pub fn new(device: &Arc<Device>) -> Result<Arc<CustomRenderPass>, OomError> {
#![allow(unused_assignments)]
#[inline]
fn attachments(&self) -> Self::AttachmentsDescIter {
vec![
let attachments = vec![
$(
$crate::framebuffer::LayoutAttachmentDescription {
format: $crate::format::FormatDesc::format(&$crate::format::$format), // FIXME: only works with markers
@ -373,54 +382,48 @@ macro_rules! ordered_passes_renderpass {
final_layout: $crate::image::Layout::PresentSrc, // FIXME:
},
)*
].into_iter()
}
];
#[inline]
#[allow(unused_mut)]
#[allow(unused_assignments)]
fn passes(&self) -> Self::PassesIter {
let mut attachment_num = 0;
$(
let $atch_name = attachment_num;
attachment_num += 1;
)*
let passes = {
let mut attachment_num = 0;
$(
let $atch_name = attachment_num;
attachment_num += 1;
)*
vec![
$({
let mut depth = None;
$(
depth = Some(($depth_atch, $crate::image::Layout::DepthStencilAttachmentOptimal));
)*
vec![
$({
let mut depth = None;
$(
depth = Some(($depth_atch, $crate::image::Layout::DepthStencilAttachmentOptimal));
)*
$crate::framebuffer::LayoutPassDescription {
color_attachments: vec![
$(
($color_atch, $crate::image::Layout::ColorAttachmentOptimal)
),*
],
depth_stencil: depth,
input_attachments: vec![
$(
($input_atch, $crate::image::Layout::ShaderReadOnlyOptimal)
),*
],
resolve_attachments: vec![],
preserve_attachments: (0 .. attachment_num).filter(|&a| {
$(if a == $color_atch { return false; })*
$(if a == $depth_atch { return false; })*
$(if a == $input_atch { return false; })*
true
}).collect()
}
}),*
].into_iter()
}
$crate::framebuffer::LayoutPassDescription {
color_attachments: vec![
$(
($color_atch, $crate::image::Layout::ColorAttachmentOptimal)
),*
],
depth_stencil: depth,
input_attachments: vec![
$(
($input_atch, $crate::image::Layout::ShaderReadOnlyOptimal)
),*
],
resolve_attachments: vec![],
preserve_attachments: (0 .. attachment_num).filter(|&a| {
$(if a == $color_atch { return false; })*
$(if a == $depth_atch { return false; })*
$(if a == $input_atch { return false; })*
true
}).collect()
}
}),*
]
};
#[inline]
fn pass_dependencies(&self) -> Self::PassDependenciesIter {
// TODO: could use a custom iterator
(1 .. self.passes().len()).flat_map(|p2| {
let pass_dependencies = (1 .. passes.len()).flat_map(|p2| {
(0 .. p2.clone()).map(move |p1| {
$crate::framebuffer::LayoutPassDependencyDescription {
source_subpass: p1,
@ -428,7 +431,34 @@ macro_rules! ordered_passes_renderpass {
by_region: false,
}
})
}).collect::<Vec<_>>().into_iter()
}).collect::<Vec<_>>();
let rp = try!(unsafe {
UnsafeRenderPass::new(device, attachments.into_iter(), passes.into_iter(),
pass_dependencies.into_iter())
});
Ok(Arc::new(CustomRenderPass {
render_pass: rp
}))
}
}
unsafe impl $crate::framebuffer::RenderPass for CustomRenderPass {
#[inline]
fn render_pass(&self) -> &UnsafeRenderPass {
&self.render_pass
}
#[inline]
fn num_subpasses(&self) -> u32 {
#![allow(unused_variables)]
let mut attachment_num = 0;
$(
$(let $depth_atch = attachment_num;)* // necessary to make the macro compile
attachment_num += 1;
)*
attachment_num
}
}
@ -436,7 +466,7 @@ macro_rules! ordered_passes_renderpass {
Arc<$crate::image::AbstractTypedImageView<$crate::image::Type2d, $crate::format::$format>>,
)*);
unsafe impl $crate::framebuffer::LayoutAttachmentsList<AList> for Layout {
unsafe impl $crate::framebuffer::RenderPassAttachmentsList<AList> for CustomRenderPass {
// TODO: shouldn't build a Vec
type AttachmentsIter = std::vec::IntoIter<std::sync::Arc<$crate::image::AbstractImageView>>;
@ -448,7 +478,7 @@ macro_rules! ordered_passes_renderpass {
ordered_passes_renderpass!{__impl_clear_values__ [0] [] [$($atch_name $format $load,)*] }
unsafe impl $crate::framebuffer::LayoutClearValues<ClearValues> for Layout {
unsafe impl $crate::framebuffer::RenderPassClearValues<ClearValues> for CustomRenderPass {
type ClearValuesIter = ClearValuesIter;
#[inline]
@ -547,33 +577,44 @@ pub enum LoadOp {
}
/// Defines the layout of multiple subpasses.
pub struct RenderPass<L> {
device: Arc<Device>,
pub struct UnsafeRenderPass {
renderpass: vk::RenderPass,
device: Arc<Device>,
num_passes: u32,
layout: L,
}
impl<L> RenderPass<L> where L: Layout {
impl UnsafeRenderPass {
/// Builds a new renderpass.
///
/// This function calls the methods of the `Layout` implementation and builds the
/// corresponding Vulkan object.
///
/// # Safety
///
/// This function doesn't check whether all the restrictions in the attachments, passes and
/// passes dependencies were enforced.
///
/// See the documentation of the structs of this module for more info about these restrictions.
///
/// # Panic
///
/// - Panicks if this functions detects that the `Layout` trait was not implemented
/// correctly and contains an error.
/// See the documentation of the various methods and structs related to `Layout`
/// for more details.
/// Can panick if it detects some violations in the restrictions. Only unexpensive checks are
/// performed. `debug_assert!` is used, so some restrictions are only checked in debug
/// mode.
///
pub fn new(device: &Arc<Device>, layout: L) -> Result<Arc<RenderPass<L>>, OomError> {
pub unsafe fn new<Ia, Ip, Id>(device: &Arc<Device>, attachments: Ia, passes: Ip,
pass_dependencies: Id)
-> Result<UnsafeRenderPass, OomError>
where Ia: ExactSizeIterator<Item = LayoutAttachmentDescription> + Clone, // with specialization we can handle the "Clone" restriction internally
Ip: ExactSizeIterator<Item = LayoutPassDescription> + Clone, // with specialization we can handle the "Clone" restriction internally
Id: ExactSizeIterator<Item = LayoutPassDependencyDescription>
{
let vk = device.pointers();
// TODO: check the validity of the renderpass layout with debug_assert!
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let attachments = layout.attachments().map(|attachment| {
let attachments = attachments.clone().map(|attachment| {
vk::AttachmentDescription {
flags: 0, // FIXME: may alias flag
format: attachment.format as u32,
@ -594,21 +635,21 @@ impl<L> RenderPass<L> where L: Layout {
// input attachment references, then all resolve attachment references, then the depth
// stencil attachment reference.
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let attachment_references = layout.passes().flat_map(|pass| {
let attachment_references = passes.clone().flat_map(|pass| {
debug_assert!(pass.resolve_attachments.is_empty() ||
pass.resolve_attachments.len() == pass.color_attachments.len());
let resolve = pass.resolve_attachments.into_iter().map(|(offset, img_la)| {
debug_assert!(offset < layout.attachments().len());
debug_assert!(offset < attachments.len());
vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
});
let color = pass.color_attachments.into_iter().map(|(offset, img_la)| {
debug_assert!(offset < layout.attachments().len());
debug_assert!(offset < attachments.len());
vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
});
let input = pass.input_attachments.into_iter().map(|(offset, img_la)| {
debug_assert!(offset < layout.attachments().len());
debug_assert!(offset < attachments.len());
vk::AttachmentReference { attachment: offset as u32, layout: img_la as u32, }
});
@ -625,7 +666,7 @@ impl<L> RenderPass<L> where L: Layout {
// This is separate because attachment references are u32s and not `vkAttachmentReference`
// structs.
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let preserve_attachments_references = layout.passes().flat_map(|pass| {
let preserve_attachments_references = passes.clone().flat_map(|pass| {
pass.preserve_attachments.into_iter().map(|offset| offset as u32)
}).collect::<Vec<_>>();
@ -636,40 +677,38 @@ impl<L> RenderPass<L> where L: Layout {
let mut ref_index = 0usize;
let mut preserve_ref_index = 0usize;
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let passes = layout.passes().map(|pass| {
unsafe {
assert!(pass.color_attachments.len() as u32 <=
device.physical_device().limits().max_color_attachments());
let passes = passes.clone().map(|pass| {
assert!(pass.color_attachments.len() as u32 <=
device.physical_device().limits().max_color_attachments());
let color_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.color_attachments.len();
let input_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.input_attachments.len();
let resolve_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.resolve_attachments.len();
let depth_stencil = if pass.depth_stencil.is_some() {
let a = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += 1;
a
} else {
ptr::null()
};
let color_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.color_attachments.len();
let input_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.input_attachments.len();
let resolve_attachments = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += pass.resolve_attachments.len();
let depth_stencil = if pass.depth_stencil.is_some() {
let a = attachment_references.as_ptr().offset(ref_index as isize);
ref_index += 1;
a
} else {
ptr::null()
};
let preserve_attachments = preserve_attachments_references.as_ptr().offset(preserve_ref_index as isize);
preserve_ref_index += pass.preserve_attachments.len();
let preserve_attachments = preserve_attachments_references.as_ptr().offset(preserve_ref_index as isize);
preserve_ref_index += pass.preserve_attachments.len();
vk::SubpassDescription {
flags: 0, // reserved
pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS,
inputAttachmentCount: pass.input_attachments.len() as u32,
pInputAttachments: input_attachments,
colorAttachmentCount: pass.color_attachments.len() as u32,
pColorAttachments: color_attachments,
pResolveAttachments: if pass.resolve_attachments.len() == 0 { ptr::null() } else { resolve_attachments },
pDepthStencilAttachment: depth_stencil,
preserveAttachmentCount: pass.preserve_attachments.len() as u32,
pPreserveAttachments: preserve_attachments,
}
vk::SubpassDescription {
flags: 0, // reserved
pipelineBindPoint: vk::PIPELINE_BIND_POINT_GRAPHICS,
inputAttachmentCount: pass.input_attachments.len() as u32,
pInputAttachments: input_attachments,
colorAttachmentCount: pass.color_attachments.len() as u32,
pColorAttachments: color_attachments,
pResolveAttachments: if pass.resolve_attachments.len() == 0 { ptr::null() } else { resolve_attachments },
pDepthStencilAttachment: depth_stencil,
preserveAttachmentCount: pass.preserve_attachments.len() as u32,
pPreserveAttachments: preserve_attachments,
}
}).collect::<Vec<_>>();
@ -679,9 +718,9 @@ impl<L> RenderPass<L> where L: Layout {
debug_assert!(preserve_ref_index == preserve_attachments_references.len());
// TODO: allocate on stack instead (https://github.com/rust-lang/rfcs/issues/618)
let dependencies = layout.pass_dependencies().map(|dependency| {
debug_assert!(dependency.source_subpass < layout.passes().len());
debug_assert!(dependency.destination_subpass < layout.passes().len());
let dependencies = pass_dependencies.map(|dependency| {
debug_assert!(dependency.source_subpass < passes.len());
debug_assert!(dependency.destination_subpass < passes.len());
vk::SubpassDependency {
srcSubpass: dependency.source_subpass as u32,
@ -694,7 +733,7 @@ impl<L> RenderPass<L> where L: Layout {
}
}).collect::<Vec<_>>();
let renderpass = unsafe {
let renderpass = {
let infos = vk::RenderPassCreateInfo {
sType: vk::STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
pNext: ptr::null(),
@ -713,27 +752,14 @@ impl<L> RenderPass<L> where L: Layout {
output
};
Ok(Arc::new(RenderPass {
Ok(UnsafeRenderPass {
device: device.clone(),
renderpass: renderpass,
num_passes: passes.len() as u32,
layout: layout,
}))
})
}
}
impl RenderPass<EmptySinglePassLayout> {
/// Builds a `RenderPass` with no attachment and a single pass.
#[inline]
pub fn empty_single_pass(device: &Arc<Device>)
-> Result<Arc<RenderPass<EmptySinglePassLayout>>, OomError>
{
RenderPass::new(device, EmptySinglePassLayout)
}
}
impl<L> RenderPass<L> where L: Layout {
/// Returns the device that was used to create this renderpass.
/// Returns the device that was used to create this render pass.
#[inline]
pub fn device(&self) -> &Arc<Device> {
&self.device
@ -746,26 +772,9 @@ impl<L> RenderPass<L> where L: Layout {
}
// TODO: add a `subpass` method that takes `Arc<Self>` as parameter
/// Returns true if this renderpass is compatible with another one.
///
/// This means that framebuffers created with this renderpass can also be used alongside with
/// the other renderpass.
#[inline]
pub fn is_compatible_with<R2>(&self, other: &RenderPass<R2>) -> bool
where R2: Layout
{
self.layout.is_compatible_with(&other.layout)
}
/// Returns the layout used to create this renderpass.
#[inline]
pub fn layout(&self) -> &L {
&self.layout
}
}
unsafe impl<L> VulkanObject for RenderPass<L> {
unsafe impl VulkanObject for UnsafeRenderPass {
type Object = vk::RenderPass;
#[inline]
@ -774,7 +783,19 @@ unsafe impl<L> VulkanObject for RenderPass<L> {
}
}
impl<L> Drop for RenderPass<L> {
unsafe impl RenderPass for UnsafeRenderPass {
#[inline]
fn render_pass(&self) -> &UnsafeRenderPass {
self
}
#[inline]
fn num_subpasses(&self) -> u32 {
self.num_subpasses()
}
}
impl Drop for UnsafeRenderPass {
#[inline]
fn drop(&mut self) {
unsafe {
@ -784,24 +805,25 @@ impl<L> Drop for RenderPass<L> {
}
}
/// Trait implemented on all render pass objects.
pub trait AbstractRenderPass {}
impl<L> AbstractRenderPass for RenderPass<L> {}
/// Represents a subpass within a `RenderPass`.
/// Represents a subpass within a `RenderPass` object.
///
/// This struct doesn't correspond to anything in Vulkan. It is simply an equivalent to a
/// combination of a render pass and subpass ID.
/// tuple of a render pass and subpass index. Contrary to a tuple, however, the existence of the
/// subpass is checked when the object is created. When you have a `Subpass` you are guaranteed
/// that the given subpass does exist.
///
pub struct Subpass<'a, L: 'a> {
render_pass: &'a Arc<RenderPass<L>>,
render_pass: &'a Arc<L>,
subpass_id: u32,
}
impl<'a, L: 'a> Subpass<'a, L> {
/// Returns a handle that represents a subpass of a render pass.
#[inline]
pub fn from(render_pass: &Arc<RenderPass<L>>, id: u32) -> Option<Subpass<L>> {
if id < render_pass.num_passes {
pub fn from(render_pass: &Arc<L>, id: u32) -> Option<Subpass<L>>
where L: RenderPass
{
if id < render_pass.render_pass().num_passes {
Some(Subpass {
render_pass: render_pass,
subpass_id: id,
@ -814,7 +836,7 @@ impl<'a, L: 'a> Subpass<'a, L> {
/// Returns the render pass of this subpass.
#[inline]
pub fn render_pass(&self) -> &'a Arc<RenderPass<L>> {
pub fn render_pass(&self) -> &'a Arc<L> {
self.render_pass
}
@ -838,6 +860,8 @@ impl<'a, L: 'a> Subpass<'a, L> {
}
}
// we need manual verifications, otherwise Copy/Clone are only implemented if `L`
// implements Copy/Clone
impl<'a, L: 'a> Copy for Subpass<'a, L> {}
impl<'a, L: 'a> Clone for Subpass<'a, L> {
#[inline]
@ -846,7 +870,7 @@ impl<'a, L: 'a> Clone for Subpass<'a, L> {
}
}
/// Contains the list of images attached to a renderpass.
/// Contains the list of images attached to a render pass.
///
/// This is a structure that you must pass when you start recording draw commands in a
/// command buffer.
@ -856,7 +880,7 @@ impl<'a, L: 'a> Clone for Subpass<'a, L> {
/// whether two renderpass objects are compatible by calling `is_compatible_with`.
pub struct Framebuffer<L> {
device: Arc<Device>,
renderpass: Arc<RenderPass<L>>,
render_pass: Arc<L>,
framebuffer: vk::Framebuffer,
dimensions: (u32, u32, u32),
resources: Vec<Arc<AbstractImageView>>,
@ -865,28 +889,27 @@ pub struct Framebuffer<L> {
impl<L> Framebuffer<L> {
/// Builds a new framebuffer.
///
/// The `attachments` parameter depends on which struct is used as a template parameter
/// for the render pass.
/// The `attachments` parameter depends on which `RenderPass` implementation is used.
///
/// # Panic
///
/// - Panicks if one of the attachments has a different sample count than what the render pass
/// describes.
/// - Additionally, some methods in the `Layout` implementation may panic if you
/// pass invalid attachments.
/// - Additionally, some methods in the `RenderPassAttachmentsList` implementation may panic
/// if you pass invalid attachments. // TODO: should be error instead
///
pub fn new<'a, A>(renderpass: &Arc<RenderPass<L>>, dimensions: (u32, u32, u32), // TODO: what about [u32; 3] instead?
pub fn new<'a, A>(render_pass: &Arc<L>, dimensions: (u32, u32, u32), // TODO: what about [u32; 3] instead?
attachments: A) -> Result<Arc<Framebuffer<L>>, FramebufferCreationError>
where L: Layout + LayoutAttachmentsList<A>
where L: RenderPass + RenderPassAttachmentsList<A>
{
let vk = renderpass.device.pointers();
let device = renderpass.device.clone();
let vk = render_pass.render_pass().device().pointers();
let device = render_pass.render_pass().device().clone();
let attachments = renderpass.layout.convert_attachments_list(attachments).collect::<Vec<_>>();
let attachments = render_pass.convert_attachments_list(attachments).collect::<Vec<_>>();
// checking the dimensions against the limits
{
let limits = renderpass.device().physical_device().limits();
let limits = render_pass.render_pass().device().physical_device().limits();
let limits = [limits.max_framebuffer_width(), limits.max_framebuffer_height(),
limits.max_framebuffer_layers()];
if dimensions.0 > limits[0] || dimensions.1 > limits[1] || dimensions.2 > limits[2] {
@ -905,7 +928,7 @@ impl<L> Framebuffer<L> {
sType: vk::STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
pNext: ptr::null(),
flags: 0, // reserved
renderPass: renderpass.internal_object(),
renderPass: render_pass.render_pass().internal_object(),
attachmentCount: ids.len() as u32,
pAttachments: ids.as_ptr(),
width: dimensions.0,
@ -921,7 +944,7 @@ impl<L> Framebuffer<L> {
Ok(Arc::new(Framebuffer {
device: device,
renderpass: renderpass.clone(),
render_pass: render_pass.clone(),
framebuffer: framebuffer,
dimensions: dimensions,
resources: attachments,
@ -930,12 +953,14 @@ impl<L> Framebuffer<L> {
/// Returns true if this framebuffer can be used with the specified renderpass.
#[inline]
pub fn is_compatible_with<R>(&self, renderpass: &Arc<RenderPass<R>>) -> bool
where R: Layout, L: Layout
pub fn is_compatible_with<R>(&self, render_pass: &Arc<R>) -> bool
where R: RenderPass, L: RenderPass
{
(&*self.renderpass as *const RenderPass<L> as usize ==
&**renderpass as *const RenderPass<R> as usize) ||
self.renderpass.is_compatible_with(renderpass)
// FIXME:
true
/*(&*self.renderpass as *const UnsafeRenderPass<L> as usize ==
&**renderpass as *const UnsafeRenderPass<R> as usize) ||
self.renderpass.is_compatible_with(renderpass)*/
}
/// Returns the width, height and layers of this framebuffer.
@ -964,8 +989,8 @@ impl<L> Framebuffer<L> {
/// Returns the renderpass that was used to create this framebuffer.
#[inline]
pub fn renderpass(&self) -> &Arc<RenderPass<L>> {
&self.renderpass
pub fn render_pass(&self) -> &Arc<L> {
&self.render_pass
}
/// Returns all the resources attached to that framebuffer.
@ -1051,21 +1076,21 @@ impl From<Error> for FramebufferCreationError {
#[cfg(test)]
mod tests {
use framebuffer::Framebuffer;
use framebuffer::RenderPass;
use framebuffer::UnsafeRenderPass;
use framebuffer::FramebufferCreationError;
#[test]
#[ignore] // TODO: crashes on AMD+Windows
fn empty_renderpass_create() {
let (device, _) = gfx_dev_and_queue!();
let _ = RenderPass::empty_single_pass(&device).unwrap();
let _ = UnsafeRenderPass::empty_single_pass(&device).unwrap();
}
#[test]
#[ignore] // TODO: crashes on AMD+Windows
fn framebuffer_too_large() {
let (device, _) = gfx_dev_and_queue!();
let renderpass = RenderPass::empty_single_pass(&device).unwrap();
let renderpass = UnsafeRenderPass::empty_single_pass(&device).unwrap();
match Framebuffer::new(&renderpass, (0xffffffff, 0xffffffff, 0xffffffff), ()) {
Err(FramebufferCreationError::DimensionsTooLarge) => (),

View File

@ -35,7 +35,7 @@ pub struct GraphicsPipeline<VertexDefinition, Layout, RenderP> {
pipeline: vk::Pipeline,
layout: Arc<PipelineLayout<Layout>>,
render_pass: Arc<RenderPass<RenderP>>,
render_pass: Arc<RenderP>,
render_pass_subpass: u32,
vertex_definition: VertexDefinition,
@ -49,7 +49,7 @@ pub struct GraphicsPipeline<VertexDefinition, Layout, RenderP> {
}
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
where Mv: VertexDefinition, L: PipelineLayoutDesc
where Mv: VertexDefinition, L: PipelineLayoutDesc, Rp: RenderPass
{
/// Builds a new graphics pipeline object.
///
@ -309,7 +309,7 @@ impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
pColorBlendState: &blend,
pDynamicState: &dynamic_states,
layout: layout.internal_object(),
renderPass: render_pass.render_pass().internal_object(),
renderPass: render_pass.render_pass().render_pass().internal_object(),
subpass: render_pass.index(),
basePipelineHandle: 0, // TODO:
basePipelineIndex: -1, // TODO:
@ -342,20 +342,28 @@ impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
}
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
where Mv: VertexDefinition, L: PipelineLayoutDesc
where Mv: VertexDefinition
{
/// Returns the vertex definition used in the constructor.
#[inline]
pub fn vertex_definition(&self) -> &Mv {
&self.vertex_definition
}
}
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
where L: PipelineLayoutDesc
{
/// Returns the pipeline layout used in the constructor.
#[inline]
pub fn layout(&self) -> &Arc<PipelineLayout<L>> {
&self.layout
}
}
impl<Mv, L, Rp> GraphicsPipeline<Mv, L, Rp>
where Rp: RenderPass
{
/// Returns the pass used in the constructor.
#[inline]
pub fn subpass(&self) -> Subpass<Rp> {