mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-26 08:45:59 +00:00
Merge pull request #603 from tomaka/persistent-ds
Add PersistentDescriptorSet
This commit is contained in:
commit
8da238817f
@ -140,9 +140,10 @@ fn main() {
|
|||||||
.build(device.clone())
|
.build(device.clone())
|
||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
let set = Arc::new(simple_descriptor_set!(pipeline.clone(), 0, {
|
let set = Arc::new(vulkano::descriptor::descriptor_set::PersistentDescriptorSet::start(pipeline.clone(), 0)
|
||||||
tex: (texture.clone(), sampler.clone())
|
.add_sampled_image(texture.clone(), sampler.clone()).unwrap()
|
||||||
}));
|
.build().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
let framebuffers = images.iter().map(|image| {
|
let framebuffers = images.iter().map(|image| {
|
||||||
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
|
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
|
||||||
|
@ -138,9 +138,10 @@ fn main() {
|
|||||||
.build(device.clone())
|
.build(device.clone())
|
||||||
.unwrap());
|
.unwrap());
|
||||||
|
|
||||||
let set = Arc::new(simple_descriptor_set!(pipeline.clone(), 0, {
|
let set = Arc::new(vulkano::descriptor::descriptor_set::PersistentDescriptorSet::start(pipeline.clone(), 0)
|
||||||
uniforms: uniform_buffer.clone()
|
.add_buffer(uniform_buffer.clone()).unwrap()
|
||||||
}));
|
.build().unwrap()
|
||||||
|
);
|
||||||
|
|
||||||
let framebuffers = images.iter().map(|image| {
|
let framebuffers = images.iter().map(|image| {
|
||||||
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
|
Arc::new(vulkano::framebuffer::Framebuffer::start(renderpass.clone())
|
||||||
|
@ -42,6 +42,7 @@
|
|||||||
//!
|
//!
|
||||||
|
|
||||||
use format::Format;
|
use format::Format;
|
||||||
|
use image::Dimensions;
|
||||||
use std::cmp;
|
use std::cmp;
|
||||||
use std::ops::BitOr;
|
use std::ops::BitOr;
|
||||||
use vk;
|
use vk;
|
||||||
@ -118,7 +119,7 @@ pub enum DescriptorDescTy {
|
|||||||
},
|
},
|
||||||
InputAttachment {
|
InputAttachment {
|
||||||
/// If `true`, the input attachment is multisampled. Only multisampled images can be
|
/// If `true`, the input attachment is multisampled. Only multisampled images can be
|
||||||
/// attached to this descriptor.
|
/// attached to this descriptor. If `false`, only single-sampled images can be attached.
|
||||||
multisampled: bool,
|
multisampled: bool,
|
||||||
array_layers: DescriptorImageDescArray,
|
array_layers: DescriptorImageDescArray,
|
||||||
},
|
},
|
||||||
@ -302,6 +303,22 @@ pub enum DescriptorImageDescDimensions {
|
|||||||
Cube,
|
Cube,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl DescriptorImageDescDimensions {
|
||||||
|
/// Builds the `DescriptorImageDescDimensions` that corresponds to actual dimensions.
|
||||||
|
#[inline]
|
||||||
|
pub fn from_dimensions(dims: Dimensions) -> DescriptorImageDescDimensions {
|
||||||
|
match dims {
|
||||||
|
Dimensions::Dim1d { .. } => DescriptorImageDescDimensions::OneDimensional,
|
||||||
|
Dimensions::Dim1dArray { .. } => DescriptorImageDescDimensions::OneDimensional,
|
||||||
|
Dimensions::Dim2d { .. } => DescriptorImageDescDimensions::TwoDimensional,
|
||||||
|
Dimensions::Dim2dArray { .. } => DescriptorImageDescDimensions::TwoDimensional,
|
||||||
|
Dimensions::Dim3d { .. } => DescriptorImageDescDimensions::ThreeDimensional,
|
||||||
|
Dimensions::Cubemap { .. } => DescriptorImageDescDimensions::Cube,
|
||||||
|
Dimensions::CubemapArray { .. } => DescriptorImageDescDimensions::Cube,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
// TODO: documentation
|
// TODO: documentation
|
||||||
#[derive(Debug, Clone, PartialEq, Eq)]
|
#[derive(Debug, Clone, PartialEq, Eq)]
|
||||||
pub struct DescriptorBufferDesc {
|
pub struct DescriptorBufferDesc {
|
||||||
|
@ -41,6 +41,15 @@ use descriptor::descriptor::DescriptorDesc;
|
|||||||
use image::ImageAccess;
|
use image::ImageAccess;
|
||||||
|
|
||||||
pub use self::collection::DescriptorSetsCollection;
|
pub use self::collection::DescriptorSetsCollection;
|
||||||
|
pub use self::persistent::PersistentDescriptorSet;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetBuildError;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetBuilder;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetBuilderArray;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetBuf;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetBufView;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetError;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetImg;
|
||||||
|
pub use self::persistent::PersistentDescriptorSetSampler;
|
||||||
pub use self::simple::*;
|
pub use self::simple::*;
|
||||||
pub use self::std_pool::StdDescriptorPool;
|
pub use self::std_pool::StdDescriptorPool;
|
||||||
pub use self::std_pool::StdDescriptorPoolAlloc;
|
pub use self::std_pool::StdDescriptorPoolAlloc;
|
||||||
@ -56,6 +65,7 @@ pub use self::unsafe_layout::UnsafeDescriptorSetLayout;
|
|||||||
|
|
||||||
pub mod collection;
|
pub mod collection;
|
||||||
|
|
||||||
|
mod persistent;
|
||||||
mod simple;
|
mod simple;
|
||||||
mod std_pool;
|
mod std_pool;
|
||||||
mod sys;
|
mod sys;
|
||||||
|
960
vulkano/src/descriptor/descriptor_set/persistent.rs
Normal file
960
vulkano/src/descriptor/descriptor_set/persistent.rs
Normal file
@ -0,0 +1,960 @@
|
|||||||
|
// Copyright (c) 2017 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 std::error;
|
||||||
|
use std::fmt;
|
||||||
|
use std::sync::Arc;
|
||||||
|
|
||||||
|
use buffer::BufferAccess;
|
||||||
|
use buffer::BufferViewRef;
|
||||||
|
use descriptor::descriptor::DescriptorDesc;
|
||||||
|
use descriptor::descriptor::DescriptorDescTy;
|
||||||
|
use descriptor::descriptor::DescriptorImageDesc;
|
||||||
|
use descriptor::descriptor::DescriptorImageDescArray;
|
||||||
|
use descriptor::descriptor::DescriptorImageDescDimensions;
|
||||||
|
use descriptor::descriptor::DescriptorType;
|
||||||
|
use descriptor::descriptor_set::DescriptorSet;
|
||||||
|
use descriptor::descriptor_set::DescriptorSetDesc;
|
||||||
|
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||||
|
use descriptor::descriptor_set::DescriptorPool;
|
||||||
|
use descriptor::descriptor_set::DescriptorPoolAlloc;
|
||||||
|
use descriptor::descriptor_set::UnsafeDescriptorSet;
|
||||||
|
use descriptor::descriptor_set::DescriptorWrite;
|
||||||
|
use descriptor::descriptor_set::StdDescriptorPoolAlloc;
|
||||||
|
use descriptor::pipeline_layout::PipelineLayoutAbstract;
|
||||||
|
use device::Device;
|
||||||
|
use device::DeviceOwned;
|
||||||
|
use format::Format;
|
||||||
|
use image::ImageAccess;
|
||||||
|
use image::ImageLayout;
|
||||||
|
use image::ImageViewAccess;
|
||||||
|
use sampler::Sampler;
|
||||||
|
use sync::AccessFlagBits;
|
||||||
|
use sync::PipelineStages;
|
||||||
|
use OomError;
|
||||||
|
use VulkanObject;
|
||||||
|
|
||||||
|
/// An immutable descriptor set that is expected to be long-lived.
|
||||||
|
///
|
||||||
|
/// Creating a persistent descriptor set allocates from a pool, and can't be modified once created.
|
||||||
|
/// You are therefore encouraged to create them at initialization and not the during
|
||||||
|
/// performance-critical paths.
|
||||||
|
///
|
||||||
|
/// > **Note**: You can control of the pool that is used to create the descriptor set, if you wish
|
||||||
|
/// > so. By creating a implementation of the `DescriptorPool` trait that doesn't perform any
|
||||||
|
/// > actual allocation, you can skip this allocation and make it acceptable to use a persistent
|
||||||
|
/// > descriptor set in performance-critical paths..
|
||||||
|
///
|
||||||
|
/// The template parameter of the `PersistentDescriptorSet` is complex, and you shouldn't try to
|
||||||
|
/// express it explicitely. If you want to store your descriptor set in a struct or in a `Vec` for
|
||||||
|
/// example, you are encouraged to turn the `PersistentDescriptorSet` into a `Box<DescriptorSet>`
|
||||||
|
/// or a `Arc<DescriptorSet>`.
|
||||||
|
///
|
||||||
|
/// # Example
|
||||||
|
// TODO:
|
||||||
|
pub struct PersistentDescriptorSet<R, P = StdDescriptorPoolAlloc> {
|
||||||
|
inner: P,
|
||||||
|
resources: R,
|
||||||
|
layout: Arc<UnsafeDescriptorSetLayout>
|
||||||
|
}
|
||||||
|
|
||||||
|
impl PersistentDescriptorSet<()> {
|
||||||
|
/// Starts the process of building a `PersistentDescriptorSet`. Returns a builder.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// - Panics if the set id is out of range.
|
||||||
|
///
|
||||||
|
pub fn start<Pl>(layout: Pl, set_id: usize) -> PersistentDescriptorSetBuilder<Pl, ()>
|
||||||
|
where Pl: PipelineLayoutAbstract
|
||||||
|
{
|
||||||
|
assert!(layout.num_sets() > set_id);
|
||||||
|
|
||||||
|
let cap = layout.num_bindings_in_set(set_id).unwrap_or(0);
|
||||||
|
|
||||||
|
PersistentDescriptorSetBuilder {
|
||||||
|
layout: layout,
|
||||||
|
set_id: set_id,
|
||||||
|
binding_id: 0,
|
||||||
|
writes: Vec::with_capacity(cap),
|
||||||
|
resources: (),
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<R, P> DescriptorSet for PersistentDescriptorSet<R, P> where P: DescriptorPoolAlloc {
|
||||||
|
#[inline]
|
||||||
|
fn inner(&self) -> &UnsafeDescriptorSet {
|
||||||
|
self.inner.inner()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn buffers_list<'a>(&'a self) -> Box<Iterator<Item = &'a BufferAccess> + 'a> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn images_list<'a>(&'a self) -> Box<Iterator<Item = &'a ImageAccess> + 'a> {
|
||||||
|
unimplemented!()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: is DescriptorSetDesc really necessary?
|
||||||
|
unsafe impl<R, P> DescriptorSetDesc for PersistentDescriptorSet<R, P> {
|
||||||
|
#[inline]
|
||||||
|
fn num_bindings(&self) -> usize {
|
||||||
|
unimplemented!() // FIXME:
|
||||||
|
}
|
||||||
|
|
||||||
|
#[inline]
|
||||||
|
fn descriptor(&self, binding: usize) -> Option<DescriptorDesc> {
|
||||||
|
unimplemented!() // FIXME:
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe impl<R, P> DeviceOwned for PersistentDescriptorSet<R, P>
|
||||||
|
where P: DeviceOwned
|
||||||
|
{
|
||||||
|
#[inline]
|
||||||
|
fn device(&self) -> &Arc<Device> {
|
||||||
|
self.layout.device()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Prototype of a `PersistentDescriptorSet`.
|
||||||
|
///
|
||||||
|
/// The template parameter `L` is the pipeline layout to use, and the template parameter `R` is
|
||||||
|
/// an unspecified type that represents the list of resources.
|
||||||
|
///
|
||||||
|
/// See the docs of `PersistentDescriptorSet` for an example.
|
||||||
|
pub struct PersistentDescriptorSetBuilder<L, R> {
|
||||||
|
// The pipeline layout.
|
||||||
|
layout: L,
|
||||||
|
// Id of the set within the pipeline layout.
|
||||||
|
set_id: usize,
|
||||||
|
// Binding currently being filled.
|
||||||
|
binding_id: usize,
|
||||||
|
// The writes to perform on a descriptor set in order to put the resources in it.
|
||||||
|
writes: Vec<DescriptorWrite>,
|
||||||
|
// Holds the resources alive.
|
||||||
|
resources: R,
|
||||||
|
}
|
||||||
|
|
||||||
|
// TODO: lots of checks are still missing, see the docs of
|
||||||
|
// VkDescriptorImageInfo and VkWriteDescriptorSet
|
||||||
|
|
||||||
|
impl<L, R> PersistentDescriptorSetBuilder<L, R>
|
||||||
|
where L: PipelineLayoutAbstract
|
||||||
|
{
|
||||||
|
/// Builds a `PersistentDescriptorSet` from the builder.
|
||||||
|
#[inline]
|
||||||
|
pub fn build(self) -> Result<PersistentDescriptorSet<R, StdDescriptorPoolAlloc>, PersistentDescriptorSetBuildError> {
|
||||||
|
let pool = Device::standard_descriptor_pool(self.layout.device());
|
||||||
|
self.build_with_pool(pool)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Builds a `PersistentDescriptorSet` from the builder.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the pool doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn build_with_pool<P>(self, pool: P)
|
||||||
|
-> Result<PersistentDescriptorSet<R, P::Alloc>, PersistentDescriptorSetBuildError>
|
||||||
|
where P: DescriptorPool
|
||||||
|
{
|
||||||
|
assert_eq!(self.layout.device().internal_object(),
|
||||||
|
pool.device().internal_object());
|
||||||
|
|
||||||
|
let expected_desc = self.layout.num_bindings_in_set(self.set_id).unwrap();
|
||||||
|
|
||||||
|
if expected_desc > self.binding_id {
|
||||||
|
return Err(PersistentDescriptorSetBuildError::MissingDescriptors {
|
||||||
|
expected: expected_desc as u32,
|
||||||
|
obtained: self.binding_id as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert_eq!(expected_desc, self.binding_id);
|
||||||
|
|
||||||
|
let set_layout = self.layout.descriptor_set_layout(self.set_id)
|
||||||
|
.expect("Unable to get the descriptor set layout")
|
||||||
|
.clone();
|
||||||
|
|
||||||
|
let set = unsafe {
|
||||||
|
let mut set = pool.alloc(&set_layout)?;
|
||||||
|
set.inner_mut().write(pool.device(), self.writes.into_iter());
|
||||||
|
set
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSet {
|
||||||
|
inner: set,
|
||||||
|
resources: self.resources,
|
||||||
|
layout: set_layout,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Call this function if the next element of the set is an array in order to set the value of
|
||||||
|
/// each element.
|
||||||
|
///
|
||||||
|
/// Returns an error if the descriptor is empty.
|
||||||
|
///
|
||||||
|
/// This function can be called even if the descriptor isn't an array, and it is valid to enter
|
||||||
|
/// the "array", add one element, then leave.
|
||||||
|
#[inline]
|
||||||
|
pub fn enter_array(self) -> Result<PersistentDescriptorSetBuilderArray<L, R>, PersistentDescriptorSetError> {
|
||||||
|
let desc = match self.layout.descriptor(self.set_id, self.binding_id) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => return Err(PersistentDescriptorSetError::EmptyExpected),
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: self,
|
||||||
|
desc,
|
||||||
|
array_element: 0,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Skips the current descriptor if it is empty.
|
||||||
|
#[inline]
|
||||||
|
pub fn add_empty(mut self) -> Result<PersistentDescriptorSetBuilder<L, R>, PersistentDescriptorSetError> {
|
||||||
|
match self.layout.descriptor(self.set_id, self.binding_id) {
|
||||||
|
None => (),
|
||||||
|
Some(desc) => return Err(PersistentDescriptorSetError::WrongDescriptorTy {
|
||||||
|
expected: desc.ty.ty().unwrap()
|
||||||
|
}),
|
||||||
|
}
|
||||||
|
|
||||||
|
self.binding_id += 1;
|
||||||
|
Ok(self)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a buffer as the next descriptor.
|
||||||
|
///
|
||||||
|
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the buffer doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
#[inline]
|
||||||
|
pub fn add_buffer<T>(self, buffer: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilder<L, (R, PersistentDescriptorSetBuf<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: BufferAccess
|
||||||
|
{
|
||||||
|
self.enter_array()?
|
||||||
|
.add_buffer(buffer)?
|
||||||
|
.leave_array()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a buffer view as the next descriptor.
|
||||||
|
///
|
||||||
|
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the buffer view doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_buffer_view<T>(self, view: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilder<L, (R, PersistentDescriptorSetBufView<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: BufferViewRef
|
||||||
|
{
|
||||||
|
self.enter_array()?
|
||||||
|
.add_buffer_view(view)?
|
||||||
|
.leave_array()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds an image view as the next descriptor.
|
||||||
|
///
|
||||||
|
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the image view doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
#[inline]
|
||||||
|
pub fn add_image<T>(self, image_view: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilder<L, (R, PersistentDescriptorSetImg<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: ImageViewAccess
|
||||||
|
{
|
||||||
|
self.enter_array()?
|
||||||
|
.add_image(image_view)?
|
||||||
|
.leave_array()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds an image view with a sampler as the next descriptor.
|
||||||
|
///
|
||||||
|
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the image view or the sampler doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
#[inline]
|
||||||
|
pub fn add_sampled_image<T>(self, image_view: T, sampler: Arc<Sampler>)
|
||||||
|
-> Result<PersistentDescriptorSetBuilder<L, ((R, PersistentDescriptorSetImg<T>), PersistentDescriptorSetSampler)>, PersistentDescriptorSetError>
|
||||||
|
where T: ImageViewAccess
|
||||||
|
{
|
||||||
|
self.enter_array()?
|
||||||
|
.add_sampled_image(image_view, sampler)?
|
||||||
|
.leave_array()
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a sampler as the next descriptor.
|
||||||
|
///
|
||||||
|
/// An error is returned if the sampler isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the sampler doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
#[inline]
|
||||||
|
pub fn add_sampler(self, sampler: Arc<Sampler>)
|
||||||
|
-> Result<PersistentDescriptorSetBuilder<L, (R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError>
|
||||||
|
{
|
||||||
|
self.enter_array()?
|
||||||
|
.add_sampler(sampler)?
|
||||||
|
.leave_array()
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Same as `PersistentDescriptorSetBuilder`, but we're in an array.
|
||||||
|
pub struct PersistentDescriptorSetBuilderArray<L, R> {
|
||||||
|
// The original builder.
|
||||||
|
builder: PersistentDescriptorSetBuilder<L, R>,
|
||||||
|
// Current array elements.
|
||||||
|
array_element: usize,
|
||||||
|
// Description of the descriptor.
|
||||||
|
desc: DescriptorDesc,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl<L, R> PersistentDescriptorSetBuilderArray<L, R> where L: PipelineLayoutAbstract {
|
||||||
|
/// Leaves the array. Call this once you added all the elements of the array.
|
||||||
|
pub fn leave_array(mut self) -> Result<PersistentDescriptorSetBuilder<L, R>, PersistentDescriptorSetError> {
|
||||||
|
if self.desc.array_count > self.array_element as u32 {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingArrayElements {
|
||||||
|
expected: self.desc.array_count,
|
||||||
|
obtained: self.array_element as u32,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
debug_assert_eq!(self.desc.array_count, self.array_element as u32);
|
||||||
|
|
||||||
|
self.builder.binding_id += 1;
|
||||||
|
Ok(self.builder)
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a buffer as the next element in the array.
|
||||||
|
///
|
||||||
|
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the buffer doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_buffer<T>(mut self, buffer: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilderArray<L, (R, PersistentDescriptorSetBuf<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: BufferAccess
|
||||||
|
{
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
buffer.inner().buffer.device().internal_object());
|
||||||
|
|
||||||
|
if self.array_element as u32 >= self.desc.array_count {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.builder.writes.push(match self.desc.ty {
|
||||||
|
DescriptorDescTy::Buffer(ref buffer_desc) => {
|
||||||
|
// Note that the buffer content is not checked. This is technically not unsafe as
|
||||||
|
// long as the data in the buffer has no invalid memory representation (ie. no
|
||||||
|
// bool, no enum, no pointer, no str) and as long as the robust buffer access
|
||||||
|
// feature is enabled.
|
||||||
|
// TODO: this is not checked ^
|
||||||
|
|
||||||
|
// TODO: eventually shouldn't be an assert ; for now robust_buffer_access is always
|
||||||
|
// enabled so this assert should never fail in practice, but we put it anyway
|
||||||
|
// in case we forget to adjust this code
|
||||||
|
assert!(self.builder.layout.device().enabled_features().robust_buffer_access);
|
||||||
|
|
||||||
|
if buffer_desc.storage {
|
||||||
|
if !buffer.inner().buffer.usage_storage_buffer() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
DescriptorWrite::storage_buffer(self.builder.binding_id as u32,
|
||||||
|
self.array_element as u32, &buffer)
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
if !buffer.inner().buffer.usage_uniform_buffer() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
unsafe {
|
||||||
|
DescriptorWrite::uniform_buffer(self.builder.binding_id as u32,
|
||||||
|
self.array_element as u32, &buffer)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ref d => {
|
||||||
|
return Err(PersistentDescriptorSetError::WrongDescriptorTy {
|
||||||
|
expected: d.ty().unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let readonly = self.desc.readonly;
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: PersistentDescriptorSetBuilder {
|
||||||
|
layout: self.builder.layout,
|
||||||
|
set_id: self.builder.set_id,
|
||||||
|
binding_id: self.builder.binding_id,
|
||||||
|
writes: self.builder.writes,
|
||||||
|
resources: (self.builder.resources, PersistentDescriptorSetBuf {
|
||||||
|
buffer: buffer,
|
||||||
|
write: !readonly,
|
||||||
|
stage: PipelineStages::none(), // FIXME:
|
||||||
|
access: AccessFlagBits::none(), // FIXME:
|
||||||
|
})
|
||||||
|
},
|
||||||
|
desc: self.desc,
|
||||||
|
array_element: self.array_element + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a buffer view as the next element in the array.
|
||||||
|
///
|
||||||
|
/// An error is returned if the buffer isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the buffer view doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_buffer_view<T>(mut self, view: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilderArray<L, (R, PersistentDescriptorSetBufView<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: BufferViewRef
|
||||||
|
{
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
view.view().device().internal_object());
|
||||||
|
|
||||||
|
if self.array_element as u32 >= self.desc.array_count {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.builder.writes.push(match self.desc.ty {
|
||||||
|
DescriptorDescTy::TexelBuffer { storage, format } => {
|
||||||
|
if storage {
|
||||||
|
// TODO: storage_texel_buffer_atomic
|
||||||
|
|
||||||
|
if !view.view().storage_texel_buffer() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorWrite::storage_texel_buffer(self.builder.binding_id as u32,
|
||||||
|
self.array_element as u32,
|
||||||
|
view.view())
|
||||||
|
} else {
|
||||||
|
if !view.view().uniform_texel_buffer() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
DescriptorWrite::uniform_texel_buffer(self.builder.binding_id as u32,
|
||||||
|
self.array_element as u32,
|
||||||
|
view.view())
|
||||||
|
}
|
||||||
|
},
|
||||||
|
ref d => {
|
||||||
|
return Err(PersistentDescriptorSetError::WrongDescriptorTy {
|
||||||
|
expected: d.ty().unwrap()
|
||||||
|
});
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let readonly = self.desc.readonly;
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: PersistentDescriptorSetBuilder {
|
||||||
|
layout: self.builder.layout,
|
||||||
|
set_id: self.builder.set_id,
|
||||||
|
binding_id: self.builder.binding_id,
|
||||||
|
writes: self.builder.writes,
|
||||||
|
resources: (self.builder.resources, PersistentDescriptorSetBufView {
|
||||||
|
view: view,
|
||||||
|
write: !readonly,
|
||||||
|
stage: PipelineStages::none(), // FIXME:
|
||||||
|
access: AccessFlagBits::none(), // FIXME:
|
||||||
|
})
|
||||||
|
},
|
||||||
|
desc: self.desc,
|
||||||
|
array_element: self.array_element + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds an image view as the next element in the array.
|
||||||
|
///
|
||||||
|
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the image view doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_image<T>(mut self, image_view: T)
|
||||||
|
-> Result<PersistentDescriptorSetBuilderArray<L, (R, PersistentDescriptorSetImg<T>)>, PersistentDescriptorSetError>
|
||||||
|
where T: ImageViewAccess
|
||||||
|
{
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
image_view.parent().inner().image.device().internal_object());
|
||||||
|
|
||||||
|
if self.array_element as u32 >= self.desc.array_count {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
let desc = match self.builder.layout.descriptor(self.builder.set_id, self.builder.binding_id) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => return Err(PersistentDescriptorSetError::EmptyExpected),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.builder.writes.push(match desc.ty {
|
||||||
|
DescriptorDescTy::Image(ref desc) => {
|
||||||
|
image_match_desc(&image_view, &desc)?;
|
||||||
|
|
||||||
|
if desc.sampled {
|
||||||
|
DescriptorWrite::sampled_image(self.builder.binding_id as u32, self.array_element as u32, &image_view)
|
||||||
|
} else {
|
||||||
|
DescriptorWrite::storage_image(self.builder.binding_id as u32, self.array_element as u32, &image_view)
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DescriptorDescTy::InputAttachment { multisampled, array_layers } => {
|
||||||
|
if !image_view.parent().inner().image.usage_input_attachment() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
if multisampled && image_view.samples() == 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::ExpectedMultisampled);
|
||||||
|
} else if !multisampled && image_view.samples() != 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::UnexpectedMultisampled);
|
||||||
|
}
|
||||||
|
|
||||||
|
let image_layers = image_view.dimensions().array_layers();
|
||||||
|
|
||||||
|
match array_layers {
|
||||||
|
DescriptorImageDescArray::NonArrayed => {
|
||||||
|
if image_layers != 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
|
||||||
|
expected: 1,
|
||||||
|
obtained: image_layers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DescriptorImageDescArray::Arrayed { max_layers: Some(max_layers) } => {
|
||||||
|
if image_layers > max_layers { // TODO: is this correct? "max" layers? or is it in fact min layers?
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
|
||||||
|
expected: max_layers,
|
||||||
|
obtained: image_layers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DescriptorImageDescArray::Arrayed { max_layers: None } => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
DescriptorWrite::input_attachment(self.builder.binding_id as u32, self.array_element as u32, &image_view)
|
||||||
|
},
|
||||||
|
ty => {
|
||||||
|
return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty().unwrap() });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let readonly = self.desc.readonly;
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: PersistentDescriptorSetBuilder {
|
||||||
|
layout: self.builder.layout,
|
||||||
|
set_id: self.builder.set_id,
|
||||||
|
binding_id: self.builder.binding_id,
|
||||||
|
writes: self.builder.writes,
|
||||||
|
resources: (self.builder.resources, PersistentDescriptorSetImg {
|
||||||
|
image: image_view,
|
||||||
|
write: !readonly,
|
||||||
|
first_mipmap: 0, // FIXME:
|
||||||
|
num_mipmaps: 1, // FIXME:
|
||||||
|
first_layer: 0, // FIXME:
|
||||||
|
num_layers: 1, // FIXME:
|
||||||
|
layout: ImageLayout::General, // FIXME:
|
||||||
|
stage: PipelineStages::none(), // FIXME:
|
||||||
|
access: AccessFlagBits::none(), // FIXME:
|
||||||
|
})
|
||||||
|
},
|
||||||
|
desc: self.desc,
|
||||||
|
array_element: self.array_element + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds an image view with a sampler as the next element in the array.
|
||||||
|
///
|
||||||
|
/// An error is returned if the image view isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the image or the sampler doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_sampled_image<T>(mut self, image_view: T, sampler: Arc<Sampler>)
|
||||||
|
-> Result<PersistentDescriptorSetBuilderArray<L, ((R, PersistentDescriptorSetImg<T>), PersistentDescriptorSetSampler)>, PersistentDescriptorSetError>
|
||||||
|
where T: ImageViewAccess
|
||||||
|
{
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
image_view.parent().inner().image.device().internal_object());
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
sampler.device().internal_object());
|
||||||
|
|
||||||
|
if self.array_element as u32 >= self.desc.array_count {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
let desc = match self.builder.layout.descriptor(self.builder.set_id, self.builder.binding_id) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => return Err(PersistentDescriptorSetError::EmptyExpected),
|
||||||
|
};
|
||||||
|
|
||||||
|
if !image_view.can_be_sampled(&sampler) {
|
||||||
|
return Err(PersistentDescriptorSetError::IncompatibleImageViewSampler);
|
||||||
|
}
|
||||||
|
|
||||||
|
self.builder.writes.push(match desc.ty {
|
||||||
|
DescriptorDescTy::CombinedImageSampler(ref desc) => {
|
||||||
|
image_match_desc(&image_view, &desc)?;
|
||||||
|
DescriptorWrite::combined_image_sampler(self.builder.binding_id as u32, self.array_element as u32, &sampler, &image_view)
|
||||||
|
},
|
||||||
|
ty => {
|
||||||
|
return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty().unwrap() });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
let readonly = self.desc.readonly;
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: PersistentDescriptorSetBuilder {
|
||||||
|
layout: self.builder.layout,
|
||||||
|
set_id: self.builder.set_id,
|
||||||
|
binding_id: self.builder.binding_id,
|
||||||
|
writes: self.builder.writes,
|
||||||
|
resources: ((self.builder.resources, PersistentDescriptorSetImg {
|
||||||
|
image: image_view,
|
||||||
|
write: !readonly,
|
||||||
|
first_mipmap: 0, // FIXME:
|
||||||
|
num_mipmaps: 1, // FIXME:
|
||||||
|
first_layer: 0, // FIXME:
|
||||||
|
num_layers: 1, // FIXME:
|
||||||
|
layout: ImageLayout::General, // FIXME:
|
||||||
|
stage: PipelineStages::none(), // FIXME:
|
||||||
|
access: AccessFlagBits::none(), // FIXME:
|
||||||
|
}), PersistentDescriptorSetSampler {
|
||||||
|
sampler: sampler,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
desc: self.desc,
|
||||||
|
array_element: self.array_element + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Binds a sampler as the next element in the array.
|
||||||
|
///
|
||||||
|
/// An error is returned if the sampler isn't compatible with the descriptor.
|
||||||
|
///
|
||||||
|
/// # Panic
|
||||||
|
///
|
||||||
|
/// Panics if the sampler doesn't have the same device as the pipeline layout.
|
||||||
|
///
|
||||||
|
pub fn add_sampler(mut self, sampler: Arc<Sampler>)
|
||||||
|
-> Result<PersistentDescriptorSetBuilderArray<L, (R, PersistentDescriptorSetSampler)>, PersistentDescriptorSetError>
|
||||||
|
{
|
||||||
|
assert_eq!(self.builder.layout.device().internal_object(),
|
||||||
|
sampler.device().internal_object());
|
||||||
|
|
||||||
|
if self.array_element as u32 >= self.desc.array_count {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayOutOfBounds);
|
||||||
|
}
|
||||||
|
|
||||||
|
let desc = match self.builder.layout.descriptor(self.builder.set_id, self.builder.binding_id) {
|
||||||
|
Some(d) => d,
|
||||||
|
None => return Err(PersistentDescriptorSetError::EmptyExpected),
|
||||||
|
};
|
||||||
|
|
||||||
|
self.builder.writes.push(match desc.ty {
|
||||||
|
DescriptorDescTy::Sampler => {
|
||||||
|
DescriptorWrite::sampler(self.builder.binding_id as u32, self.array_element as u32, &sampler)
|
||||||
|
},
|
||||||
|
ty => {
|
||||||
|
return Err(PersistentDescriptorSetError::WrongDescriptorTy { expected: ty.ty().unwrap() });
|
||||||
|
},
|
||||||
|
});
|
||||||
|
|
||||||
|
Ok(PersistentDescriptorSetBuilderArray {
|
||||||
|
builder: PersistentDescriptorSetBuilder {
|
||||||
|
layout: self.builder.layout,
|
||||||
|
set_id: self.builder.set_id,
|
||||||
|
binding_id: self.builder.binding_id,
|
||||||
|
writes: self.builder.writes,
|
||||||
|
resources: (self.builder.resources, PersistentDescriptorSetSampler {
|
||||||
|
sampler: sampler,
|
||||||
|
}),
|
||||||
|
},
|
||||||
|
desc: self.desc,
|
||||||
|
array_element: self.array_element + 1,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Checks whether an image view matches the descriptor.
|
||||||
|
fn image_match_desc<I>(image_view: &I, desc: &DescriptorImageDesc)
|
||||||
|
-> Result<(), PersistentDescriptorSetError>
|
||||||
|
where I: ?Sized + ImageViewAccess
|
||||||
|
{
|
||||||
|
if desc.sampled && !image_view.parent().inner().image.usage_sampled() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
} else if !desc.sampled && !image_view.parent().inner().image.usage_storage() {
|
||||||
|
return Err(PersistentDescriptorSetError::MissingUsage);
|
||||||
|
}
|
||||||
|
|
||||||
|
let image_view_ty = DescriptorImageDescDimensions::from_dimensions(image_view.dimensions());
|
||||||
|
if image_view_ty != desc.dimensions {
|
||||||
|
return Err(PersistentDescriptorSetError::ImageViewTypeMismatch {
|
||||||
|
expected: desc.dimensions,
|
||||||
|
obtained: image_view_ty,
|
||||||
|
});
|
||||||
|
}
|
||||||
|
|
||||||
|
if let Some(format) = desc.format {
|
||||||
|
if image_view.format() != format {
|
||||||
|
return Err(PersistentDescriptorSetError::ImageViewFormatMismatch {
|
||||||
|
expected: format,
|
||||||
|
obtained: image_view.format(),
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if desc.multisampled && image_view.samples() == 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::ExpectedMultisampled);
|
||||||
|
} else if !desc.multisampled && image_view.samples() != 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::UnexpectedMultisampled);
|
||||||
|
}
|
||||||
|
|
||||||
|
let image_layers = image_view.dimensions().array_layers();
|
||||||
|
|
||||||
|
match desc.array_layers {
|
||||||
|
DescriptorImageDescArray::NonArrayed => {
|
||||||
|
// TODO: when a non-array is expected, can we pass an image view that is in fact an
|
||||||
|
// array with one layer? need to check
|
||||||
|
if image_layers != 1 {
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
|
||||||
|
expected: 1,
|
||||||
|
obtained: image_layers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DescriptorImageDescArray::Arrayed { max_layers: Some(max_layers) } => {
|
||||||
|
if image_layers > max_layers { // TODO: is this correct? "max" layers? or is it in fact min layers?
|
||||||
|
return Err(PersistentDescriptorSetError::ArrayLayersMismatch {
|
||||||
|
expected: max_layers,
|
||||||
|
obtained: image_layers,
|
||||||
|
})
|
||||||
|
}
|
||||||
|
},
|
||||||
|
DescriptorImageDescArray::Arrayed { max_layers: None } => {},
|
||||||
|
};
|
||||||
|
|
||||||
|
Ok(())
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal object related to the `PersistentDescriptorSet` system.
|
||||||
|
pub struct PersistentDescriptorSetBuf<B> {
|
||||||
|
buffer: B,
|
||||||
|
write: bool,
|
||||||
|
stage: PipelineStages,
|
||||||
|
access: AccessFlagBits,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal object related to the `PersistentDescriptorSet` system.
|
||||||
|
pub struct PersistentDescriptorSetBufView<V>
|
||||||
|
where V: BufferViewRef
|
||||||
|
{
|
||||||
|
view: V,
|
||||||
|
write: bool,
|
||||||
|
stage: PipelineStages,
|
||||||
|
access: AccessFlagBits,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal object related to the `PersistentDescriptorSet` system.
|
||||||
|
pub struct PersistentDescriptorSetImg<I> {
|
||||||
|
image: I,
|
||||||
|
write: bool,
|
||||||
|
first_mipmap: u32,
|
||||||
|
num_mipmaps: u32,
|
||||||
|
first_layer: u32,
|
||||||
|
num_layers: u32,
|
||||||
|
layout: ImageLayout,
|
||||||
|
stage: PipelineStages,
|
||||||
|
access: AccessFlagBits,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Internal object related to the `PersistentDescriptorSet` system.
|
||||||
|
pub struct PersistentDescriptorSetSampler {
|
||||||
|
sampler: Arc<Sampler>,
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error related to the persistent descriptor set.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PersistentDescriptorSetError {
|
||||||
|
/// Expected one type of resource but got another.
|
||||||
|
WrongDescriptorTy {
|
||||||
|
/// The expected descriptor type.
|
||||||
|
expected: DescriptorType,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// Expected nothing.
|
||||||
|
EmptyExpected,
|
||||||
|
|
||||||
|
/// Tried to add too many elements to an array.
|
||||||
|
ArrayOutOfBounds,
|
||||||
|
|
||||||
|
/// Didn't fill all the elements of an array before leaving.
|
||||||
|
MissingArrayElements {
|
||||||
|
/// Number of expected elements.
|
||||||
|
expected: u32,
|
||||||
|
/// Number of elements that were added.
|
||||||
|
obtained: u32,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// The image view isn't compatible with the sampler.
|
||||||
|
IncompatibleImageViewSampler,
|
||||||
|
|
||||||
|
/// The buffer or image is missing the correct usage.
|
||||||
|
MissingUsage,
|
||||||
|
|
||||||
|
/// Expected a multisampled image, but got a single-sampled image.
|
||||||
|
ExpectedMultisampled,
|
||||||
|
|
||||||
|
/// Expected a single-sampled image, but got a multisampled image.
|
||||||
|
UnexpectedMultisampled,
|
||||||
|
|
||||||
|
/// The number of array layers of an image doesn't match what was expected.
|
||||||
|
ArrayLayersMismatch {
|
||||||
|
/// Number of expected array layers for the image.
|
||||||
|
expected: u32,
|
||||||
|
/// Number of array layers of the image that was added.
|
||||||
|
obtained: u32,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// The format of an image view doesn't match what was expected.
|
||||||
|
ImageViewFormatMismatch {
|
||||||
|
/// Expected format.
|
||||||
|
expected: Format,
|
||||||
|
/// Format of the image view that was passed.
|
||||||
|
obtained: Format,
|
||||||
|
},
|
||||||
|
|
||||||
|
/// The type of an image view doesn't match what was expected.
|
||||||
|
ImageViewTypeMismatch {
|
||||||
|
/// Expected type.
|
||||||
|
expected: DescriptorImageDescDimensions,
|
||||||
|
/// Type of the image view that was passed.
|
||||||
|
obtained: DescriptorImageDescDimensions,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for PersistentDescriptorSetError {
|
||||||
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
PersistentDescriptorSetError::WrongDescriptorTy { .. } => {
|
||||||
|
"expected one type of resource but got another"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::EmptyExpected => {
|
||||||
|
"expected an empty descriptor but got something"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::ArrayOutOfBounds => {
|
||||||
|
"tried to add too many elements to an array"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::MissingArrayElements { .. } => {
|
||||||
|
"didn't fill all the elements of an array before leaving"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::IncompatibleImageViewSampler => {
|
||||||
|
"the image view isn't compatible with the sampler"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::MissingUsage => {
|
||||||
|
"the buffer or image is missing the correct usage"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::ExpectedMultisampled => {
|
||||||
|
"expected a multisampled image, but got a single-sampled image"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::UnexpectedMultisampled => {
|
||||||
|
"expected a single-sampled image, but got a multisampled image"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::ArrayLayersMismatch { .. } => {
|
||||||
|
"the number of array layers of an image doesn't match what was expected"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::ImageViewFormatMismatch { .. } => {
|
||||||
|
"the format of an image view doesn't match what was expected"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetError::ImageViewTypeMismatch { .. } => {
|
||||||
|
"the type of an image view doesn't match what was expected"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PersistentDescriptorSetError {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(fmt, "{}", error::Error::description(self))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
/// Error when building a persistent descriptor set.
|
||||||
|
#[derive(Debug, Clone)]
|
||||||
|
pub enum PersistentDescriptorSetBuildError {
|
||||||
|
/// Out of memory.
|
||||||
|
OomError(OomError),
|
||||||
|
|
||||||
|
/// Didn't fill all the descriptors before building.
|
||||||
|
MissingDescriptors {
|
||||||
|
/// Number of expected descriptors.
|
||||||
|
expected: u32,
|
||||||
|
/// Number of descriptors that were added.
|
||||||
|
obtained: u32,
|
||||||
|
},
|
||||||
|
}
|
||||||
|
|
||||||
|
impl error::Error for PersistentDescriptorSetBuildError {
|
||||||
|
#[inline]
|
||||||
|
fn description(&self) -> &str {
|
||||||
|
match *self {
|
||||||
|
PersistentDescriptorSetBuildError::MissingDescriptors { .. } => {
|
||||||
|
"didn't fill all the descriptors before building"
|
||||||
|
},
|
||||||
|
PersistentDescriptorSetBuildError::OomError(_) => {
|
||||||
|
"not enough memory available"
|
||||||
|
},
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<OomError> for PersistentDescriptorSetBuildError {
|
||||||
|
#[inline]
|
||||||
|
fn from(err: OomError) -> PersistentDescriptorSetBuildError {
|
||||||
|
PersistentDescriptorSetBuildError::OomError(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
impl fmt::Display for PersistentDescriptorSetBuildError {
|
||||||
|
#[inline]
|
||||||
|
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||||
|
write!(fmt, "{}", error::Error::description(self))
|
||||||
|
}
|
||||||
|
}
|
@ -6,9 +6,13 @@
|
|||||||
// at your option. All files in the project carrying such
|
// at your option. All files in the project carrying such
|
||||||
// notice may not be copied, modified, or distributed except
|
// notice may not be copied, modified, or distributed except
|
||||||
// according to those terms.
|
// according to those terms.
|
||||||
|
|
||||||
|
// Since some elements of this module are deprecated, we allow using deprecated things in
|
||||||
|
// this module in order to not get warnings.
|
||||||
|
#![allow(deprecated)]
|
||||||
|
|
||||||
use std::sync::Arc;
|
use std::sync::Arc;
|
||||||
|
|
||||||
use buffer::BufferAccess;
|
use buffer::BufferAccess;
|
||||||
use buffer::BufferViewRef;
|
use buffer::BufferViewRef;
|
||||||
use descriptor::descriptor::DescriptorDesc;
|
use descriptor::descriptor::DescriptorDesc;
|
||||||
@ -101,35 +105,36 @@ unsafe impl<R, P> DescriptorSetDesc for SimpleDescriptorSet<R, P>
|
|||||||
/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object.
|
/// Builds a descriptor set in the form of a `SimpleDescriptorSet` object.
|
||||||
// TODO: more doc
|
// TODO: more doc
|
||||||
#[macro_export]
|
#[macro_export]
|
||||||
macro_rules! simple_descriptor_set {
|
#[deprecated(note = "Use `PersistentDescriptorSet` instead")]
|
||||||
($layout:expr, $set_num:expr, {$($name:ident: $val:expr),*$(,)*}) => ({
|
macro_rules! simple_descriptor_set {
|
||||||
#[allow(unused_imports)]
|
($layout:expr, $set_num:expr, {$($name:ident: $val:expr),*$(,)*}) => ({
|
||||||
use $crate::descriptor::descriptor_set::SimpleDescriptorSetBuilder;
|
#[allow(unused_imports)]
|
||||||
#[allow(unused_imports)]
|
use $crate::descriptor::descriptor_set::SimpleDescriptorSetBuilder;
|
||||||
use $crate::descriptor::descriptor_set::SimpleDescriptorSetBufferExt;
|
#[allow(unused_imports)]
|
||||||
#[allow(unused_imports)]
|
use $crate::descriptor::descriptor_set::SimpleDescriptorSetBufferExt;
|
||||||
use $crate::descriptor::descriptor_set::SimpleDescriptorSetImageExt;
|
#[allow(unused_imports)]
|
||||||
|
use $crate::descriptor::descriptor_set::SimpleDescriptorSetImageExt;
|
||||||
// We build an empty `SimpleDescriptorSetBuilder` struct, then adds each element one by
|
|
||||||
// one. When done, we call `build()` on the builder.
|
// We build an empty `SimpleDescriptorSetBuilder` struct, then adds each element one by
|
||||||
|
// one. When done, we call `build()` on the builder.
|
||||||
let builder = SimpleDescriptorSetBuilder::new($layout, $set_num);
|
|
||||||
|
let builder = SimpleDescriptorSetBuilder::new($layout, $set_num);
|
||||||
$(
|
|
||||||
// Here `$val` can be either a buffer or an image. However we can't create an extension
|
$(
|
||||||
// trait for both buffers and image, because `impl<T: ImageAccess> ExtTrait for T {}` would
|
// Here `$val` can be either a buffer or an image. However we can't create an extension
|
||||||
// conflict with `impl<T: BufferAccess> ExtTrait for T {}`.
|
// trait for both buffers and image, because `impl<T: ImageAccess> ExtTrait for T {}` would
|
||||||
//
|
// conflict with `impl<T: BufferAccess> ExtTrait for T {}`.
|
||||||
// Therefore we use a trick: we create two traits, one for buffers
|
//
|
||||||
// (`SimpleDescriptorSetBufferExt`) and one for images (`SimpleDescriptorSetImageExt`),
|
// Therefore we use a trick: we create two traits, one for buffers
|
||||||
// that both have a method named `add_me`. We import these two traits in scope and
|
// (`SimpleDescriptorSetBufferExt`) and one for images (`SimpleDescriptorSetImageExt`),
|
||||||
// call `add_me` on the value, letting Rust dispatch to the right trait. A compilation
|
// that both have a method named `add_me`. We import these two traits in scope and
|
||||||
// error will happen if `$val` is both a buffer and an image.
|
// call `add_me` on the value, letting Rust dispatch to the right trait. A compilation
|
||||||
let builder = $val.add_me(builder, stringify!($name));
|
// error will happen if `$val` is both a buffer and an image.
|
||||||
)*
|
let builder = $val.add_me(builder, stringify!($name));
|
||||||
|
)*
|
||||||
builder.build()
|
|
||||||
});
|
builder.build()
|
||||||
|
});
|
||||||
}
|
}
|
||||||
|
|
||||||
/// Prototype of a `SimpleDescriptorSet`.
|
/// Prototype of a `SimpleDescriptorSet`.
|
||||||
@ -142,6 +147,7 @@ macro_rules! simple_descriptor_set {
|
|||||||
///
|
///
|
||||||
/// # Example
|
/// # Example
|
||||||
// TODO: example here
|
// TODO: example here
|
||||||
|
#[deprecated(note = "Use `PersistentDescriptorSet` instead of `simple_descriptor_set!`")]
|
||||||
pub struct SimpleDescriptorSetBuilder<L, R> {
|
pub struct SimpleDescriptorSetBuilder<L, R> {
|
||||||
// The pipeline layout.
|
// The pipeline layout.
|
||||||
layout: L,
|
layout: L,
|
||||||
@ -228,14 +234,14 @@ unsafe impl<L, R, T> SimpleDescriptorSetBufferExt<L, R> for T
|
|||||||
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
||||||
|
|
||||||
assert!(desc.array_count == 1); // not implemented
|
assert!(desc.array_count == 1); // not implemented
|
||||||
i.writes.push(match desc.ty.ty().unwrap() {
|
i.writes.push(match desc.ty.ty().unwrap() {
|
||||||
DescriptorType::UniformBuffer => unsafe {
|
DescriptorType::UniformBuffer => unsafe {
|
||||||
DescriptorWrite::uniform_buffer(binding_id as u32, 0, &self)
|
DescriptorWrite::uniform_buffer(binding_id as u32, 0, &self)
|
||||||
},
|
},
|
||||||
DescriptorType::StorageBuffer => unsafe {
|
DescriptorType::StorageBuffer => unsafe {
|
||||||
DescriptorWrite::storage_buffer(binding_id as u32, 0, &self)
|
DescriptorWrite::storage_buffer(binding_id as u32, 0, &self)
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
SimpleDescriptorSetBuilder {
|
SimpleDescriptorSetBuilder {
|
||||||
@ -277,17 +283,17 @@ unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for T
|
|||||||
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
||||||
|
|
||||||
assert!(desc.array_count == 1); // not implemented
|
assert!(desc.array_count == 1); // not implemented
|
||||||
i.writes.push(match desc.ty.ty().unwrap() {
|
i.writes.push(match desc.ty.ty().unwrap() {
|
||||||
DescriptorType::SampledImage => {
|
DescriptorType::SampledImage => {
|
||||||
DescriptorWrite::sampled_image(binding_id as u32, 0, &self)
|
DescriptorWrite::sampled_image(binding_id as u32, 0, &self)
|
||||||
},
|
},
|
||||||
DescriptorType::StorageImage => {
|
DescriptorType::StorageImage => {
|
||||||
DescriptorWrite::storage_image(binding_id as u32, 0, &self)
|
DescriptorWrite::storage_image(binding_id as u32, 0, &self)
|
||||||
},
|
},
|
||||||
DescriptorType::InputAttachment => {
|
DescriptorType::InputAttachment => {
|
||||||
DescriptorWrite::input_attachment(binding_id as u32, 0, &self)
|
DescriptorWrite::input_attachment(binding_id as u32, 0, &self)
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
SimpleDescriptorSetBuilder {
|
SimpleDescriptorSetBuilder {
|
||||||
@ -326,14 +332,14 @@ unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for (T, Arc<Sampler>)
|
|||||||
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
let desc = i.layout.descriptor(set_id, binding_id).unwrap(); // TODO: Result instead
|
||||||
|
|
||||||
assert!(desc.array_count == 1); // not implemented
|
assert!(desc.array_count == 1); // not implemented
|
||||||
i.writes.push(match desc.ty.ty().unwrap() {
|
i.writes.push(match desc.ty.ty().unwrap() {
|
||||||
DescriptorType::CombinedImageSampler => {
|
DescriptorType::CombinedImageSampler => {
|
||||||
DescriptorWrite::combined_image_sampler(binding_id as u32,
|
DescriptorWrite::combined_image_sampler(binding_id as u32,
|
||||||
0,
|
0,
|
||||||
&self.1,
|
&self.1,
|
||||||
&image_view)
|
&image_view)
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
SimpleDescriptorSetBuilder {
|
SimpleDescriptorSetBuilder {
|
||||||
@ -374,14 +380,14 @@ unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for Vec<(T, Arc<Sampler>)
|
|||||||
|
|
||||||
let mut imgs = Vec::new();
|
let mut imgs = Vec::new();
|
||||||
for (num, (img, sampler)) in self.into_iter().enumerate() {
|
for (num, (img, sampler)) in self.into_iter().enumerate() {
|
||||||
i.writes.push(match desc.ty.ty().unwrap() {
|
i.writes.push(match desc.ty.ty().unwrap() {
|
||||||
DescriptorType::CombinedImageSampler => {
|
DescriptorType::CombinedImageSampler => {
|
||||||
DescriptorWrite::combined_image_sampler(binding_id as u32,
|
DescriptorWrite::combined_image_sampler(binding_id as u32,
|
||||||
num as u32,
|
num as u32,
|
||||||
&sampler,
|
&sampler,
|
||||||
&img)
|
&img)
|
||||||
},
|
},
|
||||||
_ => panic!(),
|
_ => panic!(),
|
||||||
});
|
});
|
||||||
|
|
||||||
imgs.push(SimpleDescriptorSetImg {
|
imgs.push(SimpleDescriptorSetImg {
|
||||||
@ -407,17 +413,17 @@ unsafe impl<L, R, T> SimpleDescriptorSetImageExt<L, R> for Vec<(T, Arc<Sampler>)
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
/*
|
/*
|
||||||
/// Internal trait related to the `SimpleDescriptorSet` system.
|
/// Internal trait related to the `SimpleDescriptorSet` system.
|
||||||
pub unsafe trait SimpleDescriptorSetResourcesCollection {
|
pub unsafe trait SimpleDescriptorSetResourcesCollection {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
|
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>);
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl SimpleDescriptorSetResourcesCollection for () {
|
unsafe impl SimpleDescriptorSetResourcesCollection for () {
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, _: &mut CommandsListSink<'a>) {
|
fn add_transition<'a>(&'a self, _: &mut CommandsListSink<'a>) {
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/// Internal object related to the `SimpleDescriptorSet` system.
|
/// Internal object related to the `SimpleDescriptorSet` system.
|
||||||
@ -428,27 +434,27 @@ pub struct SimpleDescriptorSetBuf<B> {
|
|||||||
access: AccessFlagBits,
|
access: AccessFlagBits,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*unsafe impl<B> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBuf<B>
|
/*unsafe impl<B> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBuf<B>
|
||||||
where B: BufferAccess
|
where B: BufferAccess
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
||||||
// TODO: wrong values
|
// TODO: wrong values
|
||||||
let stages = PipelineStages {
|
let stages = PipelineStages {
|
||||||
compute_shader: true,
|
compute_shader: true,
|
||||||
all_graphics: true,
|
all_graphics: true,
|
||||||
.. PipelineStages::none()
|
.. PipelineStages::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
let access = AccessFlagBits {
|
let access = AccessFlagBits {
|
||||||
uniform_read: true,
|
uniform_read: true,
|
||||||
shader_read: true,
|
shader_read: true,
|
||||||
shader_write: true,
|
shader_write: true,
|
||||||
.. AccessFlagBits::none()
|
.. AccessFlagBits::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
sink.add_buffer_transition(&self.buffer, 0, self.buffer.size(), self.write, stages, access);
|
sink.add_buffer_transition(&self.buffer, 0, self.buffer.size(), self.write, stages, access);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/// Internal object related to the `SimpleDescriptorSet` system.
|
/// Internal object related to the `SimpleDescriptorSet` system.
|
||||||
@ -461,28 +467,28 @@ pub struct SimpleDescriptorSetBufView<V>
|
|||||||
access: AccessFlagBits,
|
access: AccessFlagBits,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*unsafe impl<V> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBufView<V>
|
/*unsafe impl<V> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetBufView<V>
|
||||||
where V: BufferViewRef, V::BufferAccess: BufferAccess
|
where V: BufferViewRef, V::BufferAccess: BufferAccess
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
||||||
// TODO: wrong values
|
// TODO: wrong values
|
||||||
let stages = PipelineStages {
|
let stages = PipelineStages {
|
||||||
compute_shader: true,
|
compute_shader: true,
|
||||||
all_graphics: true,
|
all_graphics: true,
|
||||||
.. PipelineStages::none()
|
.. PipelineStages::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
let access = AccessFlagBits {
|
let access = AccessFlagBits {
|
||||||
uniform_read: true,
|
uniform_read: true,
|
||||||
shader_read: true,
|
shader_read: true,
|
||||||
shader_write: true,
|
shader_write: true,
|
||||||
.. AccessFlagBits::none()
|
.. AccessFlagBits::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
sink.add_buffer_transition(self.view.view().buffer(), 0, self.view.view().buffer().size(),
|
sink.add_buffer_transition(self.view.view().buffer(), 0, self.view.view().buffer().size(),
|
||||||
self.write, stages, access);
|
self.write, stages, access);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
|
||||||
/// Internal object related to the `SimpleDescriptorSet` system.
|
/// Internal object related to the `SimpleDescriptorSet` system.
|
||||||
@ -499,40 +505,40 @@ pub struct SimpleDescriptorSetImg<I> {
|
|||||||
access: AccessFlagBits,
|
access: AccessFlagBits,
|
||||||
}
|
}
|
||||||
|
|
||||||
/*unsafe impl<I> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetImg<I>
|
/*unsafe impl<I> SimpleDescriptorSetResourcesCollection for SimpleDescriptorSetImg<I>
|
||||||
where I: ImageViewAccess
|
where I: ImageViewAccess
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
||||||
// TODO: wrong values
|
// TODO: wrong values
|
||||||
let stages = PipelineStages {
|
let stages = PipelineStages {
|
||||||
compute_shader: true,
|
compute_shader: true,
|
||||||
all_graphics: true,
|
all_graphics: true,
|
||||||
.. PipelineStages::none()
|
.. PipelineStages::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
let access = AccessFlagBits {
|
let access = AccessFlagBits {
|
||||||
uniform_read: true,
|
uniform_read: true,
|
||||||
input_attachment_read: true,
|
input_attachment_read: true,
|
||||||
shader_read: true,
|
shader_read: true,
|
||||||
shader_write: true,
|
shader_write: true,
|
||||||
.. AccessFlagBits::none()
|
.. AccessFlagBits::none()
|
||||||
};
|
};
|
||||||
|
|
||||||
// FIXME: adjust layers & mipmaps with the view's parameters
|
// FIXME: adjust layers & mipmaps with the view's parameters
|
||||||
sink.add_image_transition(self.image.parent(), self.first_layer, self.num_layers,
|
sink.add_image_transition(self.image.parent(), self.first_layer, self.num_layers,
|
||||||
self.first_mipmap, self.num_mipmaps, self.write,
|
self.first_mipmap, self.num_mipmaps, self.write,
|
||||||
self.layout, stages, access);
|
self.layout, stages, access);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
unsafe impl<A, B> SimpleDescriptorSetResourcesCollection for (A, B)
|
unsafe impl<A, B> SimpleDescriptorSetResourcesCollection for (A, B)
|
||||||
where A: SimpleDescriptorSetResourcesCollection,
|
where A: SimpleDescriptorSetResourcesCollection,
|
||||||
B: SimpleDescriptorSetResourcesCollection
|
B: SimpleDescriptorSetResourcesCollection
|
||||||
{
|
{
|
||||||
#[inline]
|
#[inline]
|
||||||
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
fn add_transition<'a>(&'a self, sink: &mut CommandsListSink<'a>) {
|
||||||
self.0.add_transition(sink);
|
self.0.add_transition(sink);
|
||||||
self.1.add_transition(sink);
|
self.1.add_transition(sink);
|
||||||
}
|
}
|
||||||
}*/
|
}*/
|
||||||
|
@ -740,6 +740,7 @@ impl fmt::Debug for UnsafeDescriptorSet {
|
|||||||
///
|
///
|
||||||
/// Use the various constructors to build a `DescriptorWrite`. While it is safe to build a
|
/// Use the various constructors to build a `DescriptorWrite`. While it is safe to build a
|
||||||
/// `DescriptorWrite`, it is unsafe to actually use it to write to a descriptor set.
|
/// `DescriptorWrite`, it is unsafe to actually use it to write to a descriptor set.
|
||||||
|
// TODO: allow binding whole arrays at once
|
||||||
pub struct DescriptorWrite {
|
pub struct DescriptorWrite {
|
||||||
binding: u32,
|
binding: u32,
|
||||||
first_array_element: u32,
|
first_array_element: u32,
|
||||||
@ -829,10 +830,9 @@ impl DescriptorWrite {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn uniform_texel_buffer<'a, F, B>(binding: u32, array_element: u32,
|
pub fn uniform_texel_buffer<'a, F, B>(binding: u32, array_element: u32,
|
||||||
view: &Arc<BufferView<F, B>>)
|
view: &BufferView<F, B>)
|
||||||
-> DescriptorWrite
|
-> DescriptorWrite
|
||||||
where B: BufferAccess,
|
where B: BufferAccess
|
||||||
F: 'static + Send + Sync
|
|
||||||
{
|
{
|
||||||
assert!(view.uniform_texel_buffer());
|
assert!(view.uniform_texel_buffer());
|
||||||
|
|
||||||
@ -845,10 +845,9 @@ impl DescriptorWrite {
|
|||||||
|
|
||||||
#[inline]
|
#[inline]
|
||||||
pub fn storage_texel_buffer<'a, F, B>(binding: u32, array_element: u32,
|
pub fn storage_texel_buffer<'a, F, B>(binding: u32, array_element: u32,
|
||||||
view: &Arc<BufferView<F, B>>)
|
view: &BufferView<F, B>)
|
||||||
-> DescriptorWrite
|
-> DescriptorWrite
|
||||||
where B: BufferAccess + 'static,
|
where B: BufferAccess
|
||||||
F: 'static + Send + Sync
|
|
||||||
{
|
{
|
||||||
assert!(view.storage_texel_buffer());
|
assert!(view.storage_texel_buffer());
|
||||||
|
|
||||||
|
@ -69,7 +69,7 @@ pub unsafe trait PipelineLayoutDesc {
|
|||||||
|
|
||||||
/// Returns the descriptor for the given binding of the given set.
|
/// Returns the descriptor for the given binding of the given set.
|
||||||
///
|
///
|
||||||
/// Returns `None` if out of range.
|
/// Returns `None` if out of range or if the descriptor is empty.
|
||||||
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;
|
fn descriptor(&self, set: usize, binding: usize) -> Option<DescriptorDesc>;
|
||||||
|
|
||||||
/// If the `PipelineLayoutDesc` implementation is able to provide an existing
|
/// If the `PipelineLayoutDesc` implementation is able to provide an existing
|
||||||
|
@ -363,6 +363,7 @@ pub unsafe trait ImageViewAccess {
|
|||||||
/// Returns the format of this view. This can be different from the parent's format.
|
/// Returns the format of this view. This can be different from the parent's format.
|
||||||
#[inline]
|
#[inline]
|
||||||
fn format(&self) -> Format {
|
fn format(&self) -> Format {
|
||||||
|
// TODO: remove this default impl
|
||||||
self.inner().format()
|
self.inner().format()
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -390,7 +391,7 @@ pub unsafe trait ImageViewAccess {
|
|||||||
///
|
///
|
||||||
/// This method should check whether the sampler's configuration can be used with the format
|
/// This method should check whether the sampler's configuration can be used with the format
|
||||||
/// of the view.
|
/// of the view.
|
||||||
// TODO: return a Result
|
// TODO: return a Result and propagate it when binding to a descriptor set
|
||||||
fn can_be_sampled(&self, sampler: &Sampler) -> bool {
|
fn can_be_sampled(&self, sampler: &Sampler) -> bool {
|
||||||
true /* FIXME */
|
true /* FIXME */
|
||||||
}
|
}
|
||||||
|
@ -73,6 +73,7 @@ use OomError;
|
|||||||
use VulkanObject;
|
use VulkanObject;
|
||||||
use check_errors;
|
use check_errors;
|
||||||
use device::Device;
|
use device::Device;
|
||||||
|
use device::DeviceOwned;
|
||||||
use vk;
|
use vk;
|
||||||
|
|
||||||
pub use pipeline::depth_stencil::Compare;
|
pub use pipeline::depth_stencil::Compare;
|
||||||
@ -471,6 +472,13 @@ impl Sampler {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
unsafe impl DeviceOwned for Sampler {
|
||||||
|
#[inline]
|
||||||
|
fn device(&self) -> &Arc<Device> {
|
||||||
|
&self.device
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
unsafe impl VulkanObject for Sampler {
|
unsafe impl VulkanObject for Sampler {
|
||||||
type Object = vk::Sampler;
|
type Object = vk::Sampler;
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user