mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-18 10:02:29 +00:00
Rework DescriptorSetResources
and DescriptorWrite
(#1732)
* Rework `DescriptorSetResources` and `DescriptorWrite` * Small fix * Simplification in DescriptorWrite
This commit is contained in:
parent
f7f5e42190
commit
520d15532b
@ -88,7 +88,7 @@ pub use self::traits::BufferInner;
|
||||
pub use self::traits::TypedBufferAccess;
|
||||
pub use self::usage::BufferUsage;
|
||||
pub use self::view::BufferView;
|
||||
pub use self::view::BufferViewRef;
|
||||
pub use self::view::BufferViewAbstract;
|
||||
|
||||
pub mod cpu_access;
|
||||
pub mod cpu_pool;
|
||||
|
@ -236,34 +236,42 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub unsafe trait BufferViewRef {
|
||||
type BufferAccess: BufferAccess;
|
||||
pub unsafe trait BufferViewAbstract: Send + Sync {
|
||||
/// Returns the inner handle used by this buffer view.
|
||||
fn inner(&self) -> ash::vk::BufferView;
|
||||
|
||||
fn view(&self) -> &BufferView<Self::BufferAccess>;
|
||||
/// Returns the wrapped buffer that this buffer view was created from.
|
||||
fn buffer(&self) -> &dyn BufferAccess;
|
||||
}
|
||||
|
||||
unsafe impl<B> BufferViewRef for BufferView<B>
|
||||
unsafe impl<B> BufferViewAbstract for BufferView<B>
|
||||
where
|
||||
B: BufferAccess,
|
||||
{
|
||||
type BufferAccess = B;
|
||||
#[inline]
|
||||
fn inner(&self) -> ash::vk::BufferView {
|
||||
self.handle
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn view(&self) -> &BufferView<B> {
|
||||
self
|
||||
fn buffer(&self) -> &dyn BufferAccess {
|
||||
&self.buffer
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<T, B> BufferViewRef for T
|
||||
unsafe impl<T> BufferViewAbstract for T
|
||||
where
|
||||
T: SafeDeref<Target = BufferView<B>>,
|
||||
B: BufferAccess,
|
||||
T: SafeDeref + Send + Sync,
|
||||
T::Target: BufferViewAbstract,
|
||||
{
|
||||
type BufferAccess = B;
|
||||
#[inline]
|
||||
fn inner(&self) -> ash::vk::BufferView {
|
||||
(**self).inner()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn view(&self) -> &BufferView<B> {
|
||||
&**self
|
||||
fn buffer(&self) -> &dyn BufferAccess {
|
||||
(**self).buffer()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1172,32 +1172,32 @@ impl<'a> SetOrPush<'a> {
|
||||
#[inline]
|
||||
pub fn num_buffers(&self) -> usize {
|
||||
match self {
|
||||
Self::Set(set, offsets) => set.num_buffers(),
|
||||
Self::Push(writes) => writes.resources().num_buffers(),
|
||||
Self::Set(set, offsets) => set.resources().num_buffers(),
|
||||
Self::Push(writes) => writes.num_buffers(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn buffer(&self, num: usize) -> Option<(&'a dyn BufferAccess, u32)> {
|
||||
match *self {
|
||||
Self::Set(set, offsets) => set.buffer(num),
|
||||
Self::Push(writes) => writes.resources().buffer(num),
|
||||
Self::Set(set, offsets) => set.resources().buffer(num),
|
||||
Self::Push(writes) => writes.buffer(num),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn num_images(&self) -> usize {
|
||||
match self {
|
||||
Self::Set(set, offsets) => set.num_images(),
|
||||
Self::Push(writes) => writes.resources().num_images(),
|
||||
Self::Set(set, offsets) => set.resources().num_images(),
|
||||
Self::Push(writes) => writes.num_images(),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn image(&self, num: usize) -> Option<(&'a dyn ImageViewAbstract, u32)> {
|
||||
match *self {
|
||||
Self::Set(set, offsets) => set.image(num),
|
||||
Self::Push(writes) => writes.resources().image(num),
|
||||
Self::Set(set, offsets) => set.resources().image(num),
|
||||
Self::Push(writes) => writes.image(num),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -18,6 +18,7 @@ use crate::command_buffer::CommandBufferUsage;
|
||||
use crate::command_buffer::SecondaryCommandBuffer;
|
||||
use crate::command_buffer::SubpassContents;
|
||||
use crate::descriptor_set::sys::DescriptorWrite;
|
||||
use crate::descriptor_set::sys::DescriptorWriteInfo;
|
||||
use crate::descriptor_set::sys::UnsafeDescriptorSet;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
@ -1372,21 +1373,51 @@ impl UnsafeCommandBufferBuilder {
|
||||
return;
|
||||
}
|
||||
|
||||
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
|
||||
.into_iter()
|
||||
.map(|write| {
|
||||
let descriptor = pipeline_layout.descriptor_set_layouts()[set_num as usize]
|
||||
.descriptor(write.binding_num)
|
||||
.unwrap();
|
||||
let descriptor_type = descriptor.ty.ty();
|
||||
|
||||
(
|
||||
write.to_vulkan_info(descriptor_type),
|
||||
write.to_vulkan(ash::vk::DescriptorSet::null(), descriptor_type),
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
|
||||
// Set the info pointers separately.
|
||||
for (info, write) in infos.iter().zip(writes.iter_mut()) {
|
||||
match info {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(write.descriptor_count != 0);
|
||||
}
|
||||
|
||||
let fns = self.device().fns();
|
||||
let cmd = self.internal_object();
|
||||
|
||||
let raw_writes: SmallVec<[_; 8]> = descriptor_writes
|
||||
.iter()
|
||||
.map(|write| write.to_vulkan(ash::vk::DescriptorSet::null()))
|
||||
.collect();
|
||||
|
||||
fns.khr_push_descriptor.cmd_push_descriptor_set_khr(
|
||||
cmd,
|
||||
pipeline_bind_point.into(),
|
||||
pipeline_layout.internal_object(),
|
||||
set_num,
|
||||
raw_writes.len() as u32,
|
||||
raw_writes.as_ptr(),
|
||||
writes.len() as u32,
|
||||
writes.as_ptr(),
|
||||
);
|
||||
}
|
||||
|
||||
|
@ -7,14 +7,12 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::resources::DescriptorSetResources;
|
||||
use super::DescriptorSetError;
|
||||
use super::MissingBufferUsage;
|
||||
use super::MissingImageUsage;
|
||||
use crate::buffer::{BufferAccess, BufferView};
|
||||
use crate::descriptor_set::layout::{DescriptorDesc, DescriptorDescImage, DescriptorDescTy};
|
||||
use crate::descriptor_set::sys::DescriptorWrite;
|
||||
use crate::descriptor_set::DescriptorSetLayout;
|
||||
use crate::descriptor_set::sys::{DescriptorWrite, DescriptorWriteElements};
|
||||
use crate::descriptor_set::{
|
||||
DescriptorSetError, DescriptorSetLayout, MissingBufferUsage, MissingImageUsage,
|
||||
};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::view::ImageViewType;
|
||||
use crate::image::{ImageViewAbstract, SampleCount};
|
||||
@ -33,8 +31,7 @@ pub struct DescriptorSetBuilder {
|
||||
in_array: bool,
|
||||
descriptors: Vec<BuilderDescriptor>,
|
||||
cur_binding: u32,
|
||||
resources: DescriptorSetResources,
|
||||
desc_writes: Vec<DescriptorWrite>,
|
||||
writes: Vec<DescriptorWrite>,
|
||||
poisoned: bool,
|
||||
}
|
||||
|
||||
@ -47,32 +44,10 @@ impl DescriptorSetBuilder {
|
||||
pub fn start(layout: Arc<DescriptorSetLayout>) -> Self {
|
||||
let mut descriptors = Vec::with_capacity(layout.num_bindings() as usize);
|
||||
let mut desc_writes_capacity = 0;
|
||||
let mut t_num_bufs = 0;
|
||||
let mut t_num_imgs = 0;
|
||||
let mut t_num_samplers = 0;
|
||||
|
||||
for binding_i in 0..layout.num_bindings() {
|
||||
if let Some(desc) = layout.descriptor(binding_i) {
|
||||
let descriptor_count = desc.descriptor_count as usize;
|
||||
let (num_bufs, num_imgs, num_samplers) = match desc.ty {
|
||||
DescriptorDescTy::Sampler { .. } => (0, 0, 1),
|
||||
DescriptorDescTy::CombinedImageSampler { .. } => (0, 1, 1),
|
||||
DescriptorDescTy::SampledImage { .. } => (0, 1, 0),
|
||||
DescriptorDescTy::InputAttachment { .. } => (0, 1, 0),
|
||||
DescriptorDescTy::StorageImage { .. } => (0, 1, 0),
|
||||
DescriptorDescTy::UniformTexelBuffer { .. } => (1, 0, 0),
|
||||
DescriptorDescTy::StorageTexelBuffer { .. } => (1, 0, 0),
|
||||
DescriptorDescTy::UniformBuffer => (1, 0, 0),
|
||||
DescriptorDescTy::StorageBuffer => (1, 0, 0),
|
||||
DescriptorDescTy::UniformBufferDynamic => (1, 0, 0),
|
||||
DescriptorDescTy::StorageBufferDynamic => (1, 0, 0),
|
||||
};
|
||||
|
||||
t_num_bufs += num_bufs * descriptor_count;
|
||||
t_num_imgs += num_imgs * descriptor_count;
|
||||
t_num_samplers += num_samplers * descriptor_count;
|
||||
desc_writes_capacity += descriptor_count;
|
||||
|
||||
desc_writes_capacity += desc.descriptor_count as usize;
|
||||
descriptors.push(BuilderDescriptor {
|
||||
desc: Some(desc),
|
||||
array_element: 0,
|
||||
@ -90,8 +65,7 @@ impl DescriptorSetBuilder {
|
||||
in_array: false,
|
||||
cur_binding: 0,
|
||||
descriptors,
|
||||
resources: DescriptorSetResources::new(t_num_bufs, t_num_imgs, t_num_samplers),
|
||||
desc_writes: Vec::with_capacity(desc_writes_capacity),
|
||||
writes: Vec::with_capacity(desc_writes_capacity),
|
||||
poisoned: false,
|
||||
}
|
||||
}
|
||||
@ -108,10 +82,38 @@ impl DescriptorSetBuilder {
|
||||
obtained: self.cur_binding,
|
||||
})
|
||||
} else {
|
||||
let mut buffers = Vec::new();
|
||||
let mut images = Vec::new();
|
||||
|
||||
for (write_index, write) in self.writes.iter().enumerate() {
|
||||
let first_array_element = write.first_array_element() as usize;
|
||||
|
||||
match write.elements() {
|
||||
DescriptorWriteElements::Buffer(elements) => buffers.extend(
|
||||
(first_array_element..first_array_element + elements.len())
|
||||
.map(|element_index| (write_index, element_index)),
|
||||
),
|
||||
DescriptorWriteElements::BufferView(elements) => buffers.extend(
|
||||
(first_array_element..first_array_element + elements.len())
|
||||
.map(|element_index| (write_index, element_index)),
|
||||
),
|
||||
DescriptorWriteElements::ImageView(elements) => images.extend(
|
||||
(first_array_element..first_array_element + elements.len())
|
||||
.map(|element_index| (write_index, element_index)),
|
||||
),
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => images.extend(
|
||||
(first_array_element..first_array_element + elements.len())
|
||||
.map(|element_index| (write_index, element_index)),
|
||||
),
|
||||
DescriptorWriteElements::Sampler(elements) => (),
|
||||
}
|
||||
}
|
||||
|
||||
Ok(DescriptorSetBuilderOutput {
|
||||
layout: self.layout,
|
||||
writes: self.desc_writes,
|
||||
resources: self.resources,
|
||||
writes: self.writes,
|
||||
buffers,
|
||||
images,
|
||||
})
|
||||
}
|
||||
}
|
||||
@ -242,7 +244,7 @@ impl DescriptorSetBuilder {
|
||||
// enabled so this assert should never fail in practice, but we put it anyway
|
||||
// in case we forget to adjust this code
|
||||
|
||||
builder.desc_writes.push(match inner_desc.ty {
|
||||
match inner_desc.ty {
|
||||
DescriptorDescTy::StorageBuffer | DescriptorDescTy::StorageBufferDynamic => {
|
||||
assert!(
|
||||
builder
|
||||
@ -257,14 +259,6 @@ impl DescriptorSetBuilder {
|
||||
MissingBufferUsage::StorageBuffer,
|
||||
));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
DescriptorWrite::storage_buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&buffer],
|
||||
)
|
||||
}
|
||||
}
|
||||
DescriptorDescTy::UniformBuffer => {
|
||||
assert!(
|
||||
@ -280,14 +274,6 @@ impl DescriptorSetBuilder {
|
||||
MissingBufferUsage::UniformBuffer,
|
||||
));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
DescriptorWrite::uniform_buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&buffer],
|
||||
)
|
||||
}
|
||||
}
|
||||
DescriptorDescTy::UniformBufferDynamic => {
|
||||
assert!(
|
||||
@ -303,19 +289,18 @@ impl DescriptorSetBuilder {
|
||||
MissingBufferUsage::UniformBuffer,
|
||||
));
|
||||
}
|
||||
|
||||
unsafe {
|
||||
DescriptorWrite::dynamic_uniform_buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&buffer],
|
||||
)
|
||||
}
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[buffer],
|
||||
));
|
||||
}
|
||||
|
||||
builder.resources.add_buffer(builder.cur_binding, buffer);
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
@ -352,7 +337,7 @@ impl DescriptorSetBuilder {
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
builder.desc_writes.push(match inner_desc.ty {
|
||||
match inner_desc.ty {
|
||||
DescriptorDescTy::StorageTexelBuffer { .. } => {
|
||||
// TODO: storage_texel_buffer_atomic
|
||||
|
||||
@ -361,12 +346,6 @@ impl DescriptorSetBuilder {
|
||||
MissingBufferUsage::StorageTexelBuffer,
|
||||
));
|
||||
}
|
||||
|
||||
DescriptorWrite::storage_texel_buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&*view],
|
||||
)
|
||||
}
|
||||
DescriptorDescTy::UniformTexelBuffer { .. } => {
|
||||
if !view.uniform_texel_buffer() {
|
||||
@ -374,17 +353,18 @@ impl DescriptorSetBuilder {
|
||||
MissingBufferUsage::UniformTexelBuffer,
|
||||
));
|
||||
}
|
||||
|
||||
DescriptorWrite::uniform_texel_buffer(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&*view],
|
||||
)
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::buffer_view(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[view as Arc<_>],
|
||||
));
|
||||
}
|
||||
|
||||
builder.resources.add_buffer_view(builder.cur_binding, view);
|
||||
descriptor.array_element += 1;
|
||||
|
||||
if leave_array {
|
||||
@ -420,7 +400,7 @@ impl DescriptorSetBuilder {
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
builder.desc_writes.push(match &inner_desc.ty {
|
||||
match &inner_desc.ty {
|
||||
DescriptorDescTy::CombinedImageSampler {
|
||||
image_desc,
|
||||
immutable_samplers,
|
||||
@ -438,12 +418,6 @@ impl DescriptorSetBuilder {
|
||||
}
|
||||
|
||||
image_match_desc(&image_view, image_desc)?;
|
||||
|
||||
DescriptorWrite::combined_image_sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[(None, &image_view)],
|
||||
)
|
||||
}
|
||||
DescriptorDescTy::SampledImage { ref image_desc, .. } => {
|
||||
if !image_view.image().inner().image.usage().sampled {
|
||||
@ -453,12 +427,6 @@ impl DescriptorSetBuilder {
|
||||
}
|
||||
|
||||
image_match_desc(&image_view, image_desc)?;
|
||||
|
||||
DescriptorWrite::sampled_image(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&image_view],
|
||||
)
|
||||
}
|
||||
DescriptorDescTy::StorageImage { ref image_desc, .. } => {
|
||||
if !image_view.image().inner().image.usage().storage {
|
||||
@ -472,12 +440,6 @@ impl DescriptorSetBuilder {
|
||||
if !image_view.component_mapping().is_identity() {
|
||||
return Err(DescriptorSetError::NotIdentitySwizzled);
|
||||
}
|
||||
|
||||
DescriptorWrite::storage_image(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&image_view],
|
||||
)
|
||||
}
|
||||
DescriptorDescTy::InputAttachment { multisampled } => {
|
||||
if !image_view.image().inner().image.usage().input_attachment {
|
||||
@ -503,18 +465,19 @@ impl DescriptorSetBuilder {
|
||||
if image_view.ty().is_arrayed() {
|
||||
return Err(DescriptorSetError::UnexpectedArrayed);
|
||||
}
|
||||
|
||||
DescriptorWrite::input_attachment(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&image_view],
|
||||
)
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::image_view(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[image_view],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
builder.resources.add_image(builder.cur_binding, image_view);
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
@ -567,7 +530,7 @@ impl DescriptorSetBuilder {
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
builder.desc_writes.push(match &inner_desc.ty {
|
||||
match &inner_desc.ty {
|
||||
DescriptorDescTy::CombinedImageSampler {
|
||||
image_desc,
|
||||
immutable_samplers,
|
||||
@ -577,19 +540,19 @@ impl DescriptorSetBuilder {
|
||||
}
|
||||
|
||||
image_match_desc(&image_view, image_desc)?;
|
||||
|
||||
DescriptorWrite::combined_image_sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[(Some(&sampler), &image_view)],
|
||||
)
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::image_view_sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[(image_view, sampler)],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
builder.resources.add_image(builder.cur_binding, image_view);
|
||||
builder.resources.add_sampler(builder.cur_binding, sampler);
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
@ -619,23 +582,24 @@ impl DescriptorSetBuilder {
|
||||
None => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
};
|
||||
|
||||
builder.desc_writes.push(match &inner_desc.ty {
|
||||
match &inner_desc.ty {
|
||||
DescriptorDescTy::Sampler { immutable_samplers } => {
|
||||
if !immutable_samplers.is_empty() {
|
||||
return Err(DescriptorSetError::SamplerIsImmutable);
|
||||
}
|
||||
|
||||
DescriptorWrite::sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[&sampler],
|
||||
)
|
||||
}
|
||||
_ => return Err(DescriptorSetError::WrongDescriptorType),
|
||||
});
|
||||
}
|
||||
|
||||
unsafe {
|
||||
builder.writes.push(DescriptorWrite::sampler(
|
||||
builder.cur_binding,
|
||||
descriptor.array_element,
|
||||
[sampler],
|
||||
));
|
||||
}
|
||||
|
||||
descriptor.array_element += 1;
|
||||
builder.resources.add_sampler(builder.cur_binding, sampler);
|
||||
|
||||
if leave_array {
|
||||
builder.leave_array()?;
|
||||
@ -658,7 +622,8 @@ unsafe impl DeviceOwned for DescriptorSetBuilder {
|
||||
pub struct DescriptorSetBuilderOutput {
|
||||
layout: Arc<DescriptorSetLayout>,
|
||||
writes: Vec<DescriptorWrite>,
|
||||
resources: DescriptorSetResources,
|
||||
buffers: Vec<(usize, usize)>,
|
||||
images: Vec<(usize, usize)>,
|
||||
}
|
||||
|
||||
impl DescriptorSetBuilderOutput {
|
||||
@ -668,29 +633,50 @@ impl DescriptorSetBuilderOutput {
|
||||
&self.layout
|
||||
}
|
||||
|
||||
/// Returns the resources used by the output.
|
||||
#[inline]
|
||||
pub fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
}
|
||||
|
||||
/// Returns the descriptor writes.
|
||||
#[inline]
|
||||
pub fn writes(&self) -> &[DescriptorWrite] {
|
||||
&self.writes
|
||||
}
|
||||
}
|
||||
|
||||
impl From<DescriptorSetBuilderOutput>
|
||||
for (
|
||||
Arc<DescriptorSetLayout>,
|
||||
Vec<DescriptorWrite>,
|
||||
DescriptorSetResources,
|
||||
)
|
||||
{
|
||||
#[inline]
|
||||
fn from(output: DescriptorSetBuilderOutput) -> Self {
|
||||
(output.layout, output.writes, output.resources)
|
||||
pub(crate) fn num_buffers(&self) -> usize {
|
||||
self.buffers.len()
|
||||
}
|
||||
|
||||
pub(crate) fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
self.buffers
|
||||
.get(index)
|
||||
.map(|&(write_index, element_index)| {
|
||||
let write = &self.writes[write_index];
|
||||
let buffer = match write.elements() {
|
||||
DescriptorWriteElements::Buffer(elements) => elements[element_index].as_ref(),
|
||||
DescriptorWriteElements::BufferView(elements) => {
|
||||
elements[element_index].buffer()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let binding_num = write.binding_num;
|
||||
(buffer, binding_num)
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn num_images(&self) -> usize {
|
||||
self.images.len()
|
||||
}
|
||||
|
||||
pub(crate) fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
self.images.get(index).map(|&(write_index, element_index)| {
|
||||
let write = &self.writes[write_index];
|
||||
let image = match write.elements() {
|
||||
DescriptorWriteElements::ImageView(elements) => elements[element_index].as_ref(),
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => {
|
||||
elements[element_index].0.as_ref()
|
||||
}
|
||||
_ => unreachable!(),
|
||||
};
|
||||
let binding_num = write.binding_num;
|
||||
(image, binding_num)
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -781,7 +781,7 @@ impl DescriptorDescTy {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub(super) fn immutable_samplers(&self) -> &[Arc<Sampler>] {
|
||||
pub(crate) fn immutable_samplers(&self) -> &[Arc<Sampler>] {
|
||||
match self {
|
||||
Self::Sampler {
|
||||
immutable_samplers, ..
|
||||
|
@ -77,13 +77,13 @@ pub use self::builder::DescriptorSetBuilder;
|
||||
pub use self::collection::DescriptorSetsCollection;
|
||||
use self::layout::DescriptorSetLayout;
|
||||
pub use self::persistent::PersistentDescriptorSet;
|
||||
pub use self::resources::{DescriptorBindingResources, DescriptorSetResources};
|
||||
pub use self::single_layout_pool::SingleLayoutDescSetPool;
|
||||
use self::sys::UnsafeDescriptorSet;
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::descriptor_set::layout::DescriptorDescTy;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::format::Format;
|
||||
use crate::image::view::ImageViewAbstract;
|
||||
use crate::image::view::ImageViewType;
|
||||
use crate::OomError;
|
||||
use crate::SafeDeref;
|
||||
@ -123,23 +123,8 @@ pub unsafe trait DescriptorSet: DeviceOwned + Send + Sync {
|
||||
DescriptorSetWithOffsets::new(self, dynamic_offsets)
|
||||
}
|
||||
|
||||
/// Returns the number of buffers within this descriptor set.
|
||||
fn num_buffers(&self) -> usize;
|
||||
|
||||
/// Returns the `index`th buffer of this descriptor set, or `None` if out of range. Also
|
||||
/// returns the index of the descriptor that uses this buffer.
|
||||
///
|
||||
/// The valid range is between 0 and `num_buffers()`.
|
||||
fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)>;
|
||||
|
||||
/// Returns the number of images within this descriptor set.
|
||||
fn num_images(&self) -> usize;
|
||||
|
||||
/// Returns the `index`th image of this descriptor set, or `None` if out of range. Also returns
|
||||
/// the index of the descriptor that uses this image.
|
||||
///
|
||||
/// The valid range is between 0 and `num_images()`.
|
||||
fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)>;
|
||||
/// Returns the resources bound to this descriptor set.
|
||||
fn resources(&self) -> &DescriptorSetResources;
|
||||
}
|
||||
|
||||
unsafe impl<T> DescriptorSet for T
|
||||
@ -158,23 +143,8 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_buffers(&self) -> usize {
|
||||
(**self).num_buffers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
(**self).buffer(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_images(&self) -> usize {
|
||||
(**self).num_images()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
(**self).image(index)
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
(**self).resources()
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -21,24 +21,19 @@
|
||||
//! # Example
|
||||
//! TODO:
|
||||
|
||||
use super::builder::DescriptorSetBuilder;
|
||||
use super::resources::DescriptorSetResources;
|
||||
use super::DescriptorSetError;
|
||||
use crate::buffer::BufferView;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilder;
|
||||
use crate::descriptor_set::pool::standard::StdDescriptorPoolAlloc;
|
||||
use crate::descriptor_set::pool::DescriptorPool;
|
||||
use crate::descriptor_set::pool::DescriptorPoolAlloc;
|
||||
use crate::descriptor_set::BufferAccess;
|
||||
use crate::descriptor_set::DescriptorSet;
|
||||
use crate::descriptor_set::DescriptorSetLayout;
|
||||
use crate::descriptor_set::UnsafeDescriptorSet;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::descriptor_set::pool::{DescriptorPool, DescriptorPoolAlloc};
|
||||
use crate::descriptor_set::resources::DescriptorSetResources;
|
||||
use crate::descriptor_set::{
|
||||
BufferAccess, DescriptorSet, DescriptorSetError, DescriptorSetLayout, UnsafeDescriptorSet,
|
||||
};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::VulkanObject;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// A simple, immutable descriptor set that is expected to be long-lived.
|
||||
@ -77,27 +72,15 @@ where
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_buffers(&self) -> usize {
|
||||
self.resources.num_buffers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
self.resources.buffer(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_images(&self) -> usize {
|
||||
self.resources.num_images()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
self.resources.image(index)
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<P> DeviceOwned for PersistentDescriptorSet<P> {
|
||||
unsafe impl<P> DeviceOwned for PersistentDescriptorSet<P>
|
||||
where
|
||||
P: DescriptorPoolAlloc,
|
||||
{
|
||||
#[inline]
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.layout.device()
|
||||
@ -245,17 +228,19 @@ impl PersistentDescriptorSetBuilder {
|
||||
where
|
||||
P: ?Sized + DescriptorPool,
|
||||
{
|
||||
let (layout, writes, resources) = self.inner.build()?.into();
|
||||
let writes = self.inner.build()?;
|
||||
let set = unsafe {
|
||||
let mut set = pool.alloc(&layout)?;
|
||||
set.inner_mut().write(pool.device(), &writes);
|
||||
let mut set = pool.alloc(writes.layout())?;
|
||||
set.inner_mut().write(writes.layout(), writes.writes());
|
||||
set
|
||||
};
|
||||
let mut resources = DescriptorSetResources::new(writes.layout());
|
||||
resources.update(writes.writes());
|
||||
|
||||
Ok(PersistentDescriptorSet {
|
||||
inner: set,
|
||||
resources,
|
||||
layout,
|
||||
layout: writes.layout().clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -148,7 +148,6 @@ impl UnsafeDescriptorPool {
|
||||
/// - You must ensure that the allocated descriptor sets are no longer in use when the pool
|
||||
/// is destroyed, as destroying the pool is equivalent to freeing all the sets.
|
||||
///
|
||||
#[inline]
|
||||
pub unsafe fn alloc<'l, I>(
|
||||
&mut self,
|
||||
layouts: I,
|
||||
@ -172,16 +171,6 @@ impl UnsafeDescriptorPool {
|
||||
layout.internal_object()
|
||||
})
|
||||
.collect();
|
||||
|
||||
self.alloc_impl(&layouts, &variable_descriptor_counts)
|
||||
}
|
||||
|
||||
// Actual implementation of `alloc`. Separated so that it is not inlined.
|
||||
unsafe fn alloc_impl(
|
||||
&mut self,
|
||||
layouts: &SmallVec<[ash::vk::DescriptorSetLayout; 8]>,
|
||||
variable_descriptor_counts: &SmallVec<[u32; 8]>,
|
||||
) -> Result<impl ExactSizeIterator<Item = UnsafeDescriptorSet>, DescriptorPoolAllocError> {
|
||||
let num = layouts.len();
|
||||
|
||||
let output = if num == 0 {
|
||||
@ -242,7 +231,9 @@ impl UnsafeDescriptorPool {
|
||||
output
|
||||
};
|
||||
|
||||
Ok(output.into_iter().map(|s| UnsafeDescriptorSet { set: s }))
|
||||
Ok(output
|
||||
.into_iter()
|
||||
.map(|handle| UnsafeDescriptorSet::new(handle)))
|
||||
}
|
||||
|
||||
/// Frees some descriptor sets.
|
||||
@ -435,7 +426,7 @@ mod tests {
|
||||
|
||||
let mut pool = UnsafeDescriptorPool::new(device, &desc, 10, false).unwrap();
|
||||
unsafe {
|
||||
let sets = pool.alloc(iter::once(&set_layout)).unwrap();
|
||||
let sets = pool.alloc([&set_layout]).unwrap();
|
||||
assert_eq!(sets.count(), 1);
|
||||
}
|
||||
}
|
||||
@ -469,7 +460,7 @@ mod tests {
|
||||
let mut pool = UnsafeDescriptorPool::new(device2, &desc, 10, false).unwrap();
|
||||
|
||||
unsafe {
|
||||
let _ = pool.alloc(iter::once(&set_layout));
|
||||
let _ = pool.alloc([&set_layout]);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
@ -7,116 +7,225 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::buffer::BufferInner;
|
||||
use crate::buffer::BufferView;
|
||||
use crate::buffer::BufferViewAbstract;
|
||||
use crate::descriptor_set::layout::{DescriptorSetLayout, DescriptorType};
|
||||
use crate::descriptor_set::sys::{DescriptorWrite, DescriptorWriteElements};
|
||||
use crate::descriptor_set::BufferAccess;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::device::Queue;
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::sync::AccessError;
|
||||
use crate::DeviceSize;
|
||||
use fnv::FnvHashMap;
|
||||
use smallvec::{smallvec, SmallVec};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// The resources that are bound to a descriptor set.
|
||||
#[derive(Clone)]
|
||||
pub struct DescriptorSetResources {
|
||||
buffers: Vec<(Arc<dyn BufferAccess + 'static>, u32)>,
|
||||
images: Vec<(Arc<dyn ImageViewAbstract + 'static>, u32)>,
|
||||
samplers: Vec<(Arc<Sampler>, u32)>,
|
||||
}
|
||||
|
||||
struct BufferViewResource<B>(Arc<BufferView<B>>)
|
||||
where
|
||||
B: BufferAccess;
|
||||
|
||||
unsafe impl<B> DeviceOwned for BufferViewResource<B>
|
||||
where
|
||||
B: BufferAccess,
|
||||
{
|
||||
fn device(&self) -> &Arc<Device> {
|
||||
self.0.device()
|
||||
}
|
||||
}
|
||||
|
||||
unsafe impl<B> BufferAccess for BufferViewResource<B>
|
||||
where
|
||||
B: BufferAccess,
|
||||
{
|
||||
fn inner(&self) -> BufferInner<'_> {
|
||||
self.0.buffer().inner()
|
||||
}
|
||||
|
||||
fn size(&self) -> DeviceSize {
|
||||
self.0.buffer().size()
|
||||
}
|
||||
|
||||
fn conflict_key(&self) -> (u64, u64) {
|
||||
self.0.buffer().conflict_key()
|
||||
}
|
||||
|
||||
fn try_gpu_lock(&self, exclusive_access: bool, queue: &Queue) -> Result<(), AccessError> {
|
||||
self.0.buffer().try_gpu_lock(exclusive_access, queue)
|
||||
}
|
||||
|
||||
unsafe fn increase_gpu_lock(&self) {
|
||||
self.0.buffer().increase_gpu_lock()
|
||||
}
|
||||
|
||||
unsafe fn unlock(&self) {
|
||||
self.0.buffer().unlock()
|
||||
}
|
||||
descriptors: FnvHashMap<u32, DescriptorBindingResources>,
|
||||
buffers: Vec<(u32, usize)>,
|
||||
images: Vec<(u32, usize)>,
|
||||
}
|
||||
|
||||
impl DescriptorSetResources {
|
||||
pub fn new(buffer_capacity: usize, image_capacity: usize, sampler_capacity: usize) -> Self {
|
||||
/// Creates a new `DescriptorSetResources` matching the provided descriptor set layout, and
|
||||
/// all descriptors set to `None`.
|
||||
pub fn new(layout: &DescriptorSetLayout) -> Self {
|
||||
let descriptors = layout
|
||||
.desc()
|
||||
.bindings()
|
||||
.iter()
|
||||
.enumerate()
|
||||
.filter_map(|(b, d)| d.as_ref().map(|d| (b as u32, d)))
|
||||
.map(|(binding_num, binding_desc)| {
|
||||
let count = binding_desc.descriptor_count as usize;
|
||||
let binding_resources = match binding_desc.ty.ty() {
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic => {
|
||||
DescriptorBindingResources::Buffer(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer => {
|
||||
DescriptorBindingResources::BufferView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment => {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
if binding_desc.ty.immutable_samplers().is_empty() {
|
||||
DescriptorBindingResources::ImageViewSampler(smallvec![None; count])
|
||||
} else {
|
||||
DescriptorBindingResources::ImageView(smallvec![None; count])
|
||||
}
|
||||
}
|
||||
DescriptorType::Sampler => {
|
||||
if binding_desc.ty.immutable_samplers().is_empty() {
|
||||
DescriptorBindingResources::Sampler(smallvec![None; count])
|
||||
} else {
|
||||
DescriptorBindingResources::None
|
||||
}
|
||||
}
|
||||
};
|
||||
(binding_num, binding_resources)
|
||||
})
|
||||
.collect();
|
||||
|
||||
Self {
|
||||
buffers: Vec::with_capacity(buffer_capacity),
|
||||
images: Vec::with_capacity(image_capacity),
|
||||
samplers: Vec::with_capacity(sampler_capacity),
|
||||
descriptors,
|
||||
buffers: Vec::new(),
|
||||
images: Vec::new(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn num_buffers(&self) -> usize {
|
||||
/// Applies descriptor writes to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the binding number of a write does not exist in the resources.
|
||||
/// - See also [`DescriptorBindingResources::update`].
|
||||
pub fn update<'a>(&mut self, writes: impl IntoIterator<Item = &'a DescriptorWrite>) {
|
||||
for write in writes {
|
||||
self.descriptors
|
||||
.get_mut(&write.binding_num)
|
||||
.expect("descriptor write has invalid binding number")
|
||||
.update(write)
|
||||
}
|
||||
|
||||
self.buffers.clear();
|
||||
self.images.clear();
|
||||
|
||||
for (&binding, resources) in self.descriptors.iter() {
|
||||
match resources {
|
||||
DescriptorBindingResources::None => (),
|
||||
DescriptorBindingResources::Buffer(resources) => {
|
||||
self.buffers.extend(resources.iter().enumerate().filter_map(
|
||||
|(index, resource)| resource.as_ref().map(|_| (binding, index)),
|
||||
))
|
||||
}
|
||||
DescriptorBindingResources::BufferView(resources) => {
|
||||
self.buffers.extend(resources.iter().enumerate().filter_map(
|
||||
|(index, resource)| resource.as_ref().map(|_| (binding, index)),
|
||||
))
|
||||
}
|
||||
DescriptorBindingResources::ImageView(resources) => {
|
||||
self.images.extend(resources.iter().enumerate().filter_map(
|
||||
|(index, resource)| resource.as_ref().map(|_| (binding, index)),
|
||||
))
|
||||
}
|
||||
DescriptorBindingResources::ImageViewSampler(resources) => {
|
||||
self.images.extend(resources.iter().enumerate().filter_map(
|
||||
|(index, resource)| resource.as_ref().map(|_| (binding, index)),
|
||||
))
|
||||
}
|
||||
DescriptorBindingResources::Sampler(_) => (),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns a reference to the bound resources for `binding`. Returns `None` if the binding
|
||||
/// doesn't exist.
|
||||
#[inline]
|
||||
pub fn binding(&self, binding: u32) -> Option<&DescriptorBindingResources> {
|
||||
self.descriptors.get(&binding)
|
||||
}
|
||||
|
||||
pub(crate) fn num_buffers(&self) -> usize {
|
||||
self.buffers.len()
|
||||
}
|
||||
|
||||
pub fn num_images(&self) -> usize {
|
||||
pub(crate) fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
self.buffers
|
||||
.get(index)
|
||||
.and_then(|&(binding, index)| match &self.descriptors[&binding] {
|
||||
DescriptorBindingResources::Buffer(resources) => {
|
||||
resources[index].as_ref().map(|r| (r.as_ref(), binding))
|
||||
}
|
||||
DescriptorBindingResources::BufferView(resources) => {
|
||||
resources[index].as_ref().map(|r| (r.buffer(), binding))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
|
||||
pub(crate) fn num_images(&self) -> usize {
|
||||
self.images.len()
|
||||
}
|
||||
|
||||
pub fn num_samplers(&self) -> usize {
|
||||
self.samplers.len()
|
||||
}
|
||||
|
||||
pub fn add_buffer(&mut self, desc_index: u32, buffer: Arc<dyn BufferAccess + 'static>) {
|
||||
self.buffers.push((buffer, desc_index));
|
||||
}
|
||||
|
||||
pub fn add_buffer_view<B>(&mut self, desc_index: u32, view: Arc<BufferView<B>>)
|
||||
where
|
||||
B: BufferAccess + 'static,
|
||||
{
|
||||
self.buffers
|
||||
.push((Arc::new(BufferViewResource(view)), desc_index));
|
||||
}
|
||||
|
||||
pub fn add_image(&mut self, desc_index: u32, image: Arc<dyn ImageViewAbstract + 'static>) {
|
||||
self.images.push((image, desc_index));
|
||||
}
|
||||
|
||||
pub fn add_sampler(&mut self, desc_index: u32, sampler: Arc<Sampler>) {
|
||||
self.samplers.push((sampler, desc_index))
|
||||
}
|
||||
|
||||
pub fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
self.buffers
|
||||
.get(index)
|
||||
.map(|(buf, bind)| (&**buf as _, *bind))
|
||||
}
|
||||
|
||||
pub fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
pub(crate) fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
self.images
|
||||
.get(index)
|
||||
.map(|(img, bind)| (&**img as _, *bind))
|
||||
.and_then(|&(binding, index)| match &self.descriptors[&binding] {
|
||||
DescriptorBindingResources::ImageView(resources) => {
|
||||
resources[index].as_ref().map(|r| (r.as_ref(), binding))
|
||||
}
|
||||
DescriptorBindingResources::ImageViewSampler(resources) => {
|
||||
resources[index].as_ref().map(|r| (r.0.as_ref(), binding))
|
||||
}
|
||||
_ => unreachable!(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
/// The resources that are bound to a single descriptor set binding.
|
||||
#[derive(Clone)]
|
||||
pub enum DescriptorBindingResources {
|
||||
None,
|
||||
Buffer(Elements<Arc<dyn BufferAccess>>),
|
||||
BufferView(Elements<Arc<dyn BufferViewAbstract>>),
|
||||
ImageView(Elements<Arc<dyn ImageViewAbstract>>),
|
||||
ImageViewSampler(Elements<(Arc<dyn ImageViewAbstract>, Arc<Sampler>)>),
|
||||
Sampler(Elements<Arc<Sampler>>),
|
||||
}
|
||||
|
||||
type Elements<T> = SmallVec<[Option<T>; 1]>;
|
||||
|
||||
impl DescriptorBindingResources {
|
||||
/// Applies a descriptor write to the resources.
|
||||
///
|
||||
/// # Panics
|
||||
///
|
||||
/// - Panics if the resource types do not match.
|
||||
/// - Panics if the write goes out of bounds.
|
||||
pub fn update(&mut self, write: &DescriptorWrite) {
|
||||
fn write_resources<T: Clone>(first: usize, resources: &mut [Option<T>], elements: &[T]) {
|
||||
resources
|
||||
.get_mut(first..first + elements.len())
|
||||
.expect("descriptor write for binding out of bounds")
|
||||
.iter_mut()
|
||||
.zip(elements)
|
||||
.for_each(|(resource, element)| {
|
||||
*resource = Some(element.clone());
|
||||
});
|
||||
}
|
||||
|
||||
let first = write.first_array_element() as usize;
|
||||
|
||||
match (self, write.elements()) {
|
||||
(
|
||||
DescriptorBindingResources::Buffer(resources),
|
||||
DescriptorWriteElements::Buffer(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::BufferView(resources),
|
||||
DescriptorWriteElements::BufferView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageView(resources),
|
||||
DescriptorWriteElements::ImageView(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::ImageViewSampler(resources),
|
||||
DescriptorWriteElements::ImageViewSampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
(
|
||||
DescriptorBindingResources::Sampler(resources),
|
||||
DescriptorWriteElements::Sampler(elements),
|
||||
) => write_resources(first, resources, elements),
|
||||
_ => panic!(
|
||||
"descriptor write for binding {} has wrong resource type",
|
||||
write.binding_num,
|
||||
),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
@ -7,26 +7,21 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use super::builder::DescriptorSetBuilder;
|
||||
use super::resources::DescriptorSetResources;
|
||||
use super::DescriptorSetError;
|
||||
use crate::buffer::BufferView;
|
||||
use crate::descriptor_set::builder::DescriptorSetBuilder;
|
||||
use crate::descriptor_set::layout::DescriptorSetLayout;
|
||||
use crate::descriptor_set::pool::DescriptorPoolAlloc;
|
||||
use crate::descriptor_set::pool::DescriptorPoolAllocError;
|
||||
use crate::descriptor_set::pool::UnsafeDescriptorPool;
|
||||
use crate::descriptor_set::BufferAccess;
|
||||
use crate::descriptor_set::DescriptorSet;
|
||||
use crate::descriptor_set::UnsafeDescriptorSet;
|
||||
use crate::device::Device;
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::descriptor_set::pool::{
|
||||
DescriptorPoolAlloc, DescriptorPoolAllocError, UnsafeDescriptorPool,
|
||||
};
|
||||
use crate::descriptor_set::{BufferAccess, DescriptorSet, DescriptorSetError, UnsafeDescriptorSet};
|
||||
use crate::device::{Device, DeviceOwned};
|
||||
use crate::image::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
use crate::OomError;
|
||||
use crate::VulkanObject;
|
||||
use crossbeam_queue::SegQueue;
|
||||
use std::hash::Hash;
|
||||
use std::hash::Hasher;
|
||||
use std::hash::{Hash, Hasher};
|
||||
use std::sync::Arc;
|
||||
|
||||
/// `SingleLayoutDescSetPool` is a convenience wrapper provided by Vulkano not to be confused with
|
||||
@ -191,23 +186,8 @@ unsafe impl DescriptorSet for SingleLayoutDescSet {
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_buffers(&self) -> usize {
|
||||
self.resources.num_buffers()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn buffer(&self, index: usize) -> Option<(&dyn BufferAccess, u32)> {
|
||||
self.resources.buffer(index)
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn num_images(&self) -> usize {
|
||||
self.resources.num_images()
|
||||
}
|
||||
|
||||
#[inline]
|
||||
fn image(&self, index: usize) -> Option<(&dyn ImageViewAbstract, u32)> {
|
||||
self.resources.image(index)
|
||||
fn resources(&self) -> &DescriptorSetResources {
|
||||
&self.resources
|
||||
}
|
||||
}
|
||||
|
||||
@ -339,16 +319,18 @@ impl<'a> SingleLayoutDescSetBuilder<'a> {
|
||||
|
||||
/// Builds a `SingleLayoutDescSet` from the builder.
|
||||
pub fn build(self) -> Result<SingleLayoutDescSet, DescriptorSetError> {
|
||||
let (layout, writes, resources) = self.inner.build()?.into();
|
||||
let writes = self.inner.build()?;
|
||||
let mut alloc = self.pool.next_alloc()?;
|
||||
unsafe {
|
||||
alloc.inner_mut().write(&self.pool.device, &writes);
|
||||
alloc.inner_mut().write(writes.layout(), writes.writes());
|
||||
}
|
||||
let mut resources = DescriptorSetResources::new(writes.layout());
|
||||
resources.update(writes.writes());
|
||||
|
||||
Ok(SingleLayoutDescSet {
|
||||
inner: alloc,
|
||||
resources,
|
||||
layout,
|
||||
layout: writes.layout().clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
@ -9,11 +9,8 @@
|
||||
|
||||
//! Low-level descriptor set.
|
||||
|
||||
use crate::buffer::BufferAccess;
|
||||
use crate::buffer::BufferInner;
|
||||
use crate::buffer::BufferView;
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
use crate::device::Device;
|
||||
use crate::buffer::{BufferAccess, BufferInner, BufferViewAbstract};
|
||||
use crate::descriptor_set::layout::{DescriptorSetLayout, DescriptorType};
|
||||
use crate::device::DeviceOwned;
|
||||
use crate::image::view::ImageViewAbstract;
|
||||
use crate::sampler::Sampler;
|
||||
@ -30,52 +27,83 @@ use std::sync::Arc;
|
||||
/// doesn't hold the pool or the device it is associated to.
|
||||
/// Instead it is an object meant to be used with the `UnsafeDescriptorPool`.
|
||||
pub struct UnsafeDescriptorSet {
|
||||
pub(super) set: ash::vk::DescriptorSet,
|
||||
handle: ash::vk::DescriptorSet,
|
||||
}
|
||||
|
||||
impl UnsafeDescriptorSet {
|
||||
// TODO: add copying from other descriptor sets
|
||||
// add a `copy` method that just takes a copy, and an `update` method that takes both
|
||||
// writes and copies and that actually performs the operation
|
||||
pub(crate) fn new(handle: ash::vk::DescriptorSet) -> Self {
|
||||
Self { handle }
|
||||
}
|
||||
|
||||
/// Modifies a descriptor set. Doesn't check that the writes or copies are correct, and
|
||||
/// doesn't check whether the descriptor set is in use.
|
||||
///
|
||||
/// **Important**: You must ensure that the `DescriptorSetLayout` object is alive before
|
||||
/// updating a descriptor set.
|
||||
///
|
||||
/// # Safety
|
||||
///
|
||||
/// - The `Device` must be the device the pool of this set was created with.
|
||||
/// - The `DescriptorSetLayout` object this set was created with must be alive.
|
||||
/// - Doesn't verify that the things you write in the descriptor set match its layout.
|
||||
/// - Doesn't keep the resources alive. You have to do that yourself.
|
||||
/// - Updating a descriptor set obeys synchronization rules that aren't checked here. Once a
|
||||
/// command buffer contains a pointer/reference to a descriptor set, it is illegal to write
|
||||
/// to it.
|
||||
///
|
||||
pub unsafe fn write(&mut self, device: &Device, writes: &[DescriptorWrite]) {
|
||||
let fns = device.fns();
|
||||
pub unsafe fn write<'a>(
|
||||
&mut self,
|
||||
layout: &DescriptorSetLayout,
|
||||
writes: impl IntoIterator<Item = &'a DescriptorWrite>,
|
||||
) {
|
||||
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = writes
|
||||
.into_iter()
|
||||
.map(|write| {
|
||||
let descriptor_type = layout.descriptor(write.binding_num).unwrap().ty.ty();
|
||||
|
||||
let raw_writes: SmallVec<[_; 8]> = writes
|
||||
.iter()
|
||||
.map(|write| write.to_vulkan(self.set))
|
||||
.collect();
|
||||
(
|
||||
write.to_vulkan_info(descriptor_type),
|
||||
write.to_vulkan(self.handle, descriptor_type),
|
||||
)
|
||||
})
|
||||
.unzip();
|
||||
|
||||
// It is forbidden to call `vkUpdateDescriptorSets` with 0 writes, so we need to perform
|
||||
// this emptiness check.
|
||||
if raw_writes.is_empty() {
|
||||
if writes.is_empty() {
|
||||
return;
|
||||
}
|
||||
|
||||
// Set the info pointers separately.
|
||||
for (info, write) in infos.iter().zip(writes.iter_mut()) {
|
||||
match info {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
debug_assert!(write.descriptor_count != 0);
|
||||
}
|
||||
|
||||
let fns = layout.device().fns();
|
||||
|
||||
fns.v1_0.update_descriptor_sets(
|
||||
device.internal_object(),
|
||||
raw_writes.len() as u32,
|
||||
raw_writes.as_ptr(),
|
||||
layout.device().internal_object(),
|
||||
writes.len() as u32,
|
||||
writes.as_ptr(),
|
||||
0,
|
||||
ptr::null(),
|
||||
);
|
||||
}
|
||||
|
||||
// TODO: add copying from other descriptor sets
|
||||
// add a `copy` method that just takes a copy, and an `update` method that takes both
|
||||
// writes and copies and that actually performs the operation
|
||||
}
|
||||
|
||||
unsafe impl VulkanObject for UnsafeDescriptorSet {
|
||||
@ -83,13 +111,13 @@ unsafe impl VulkanObject for UnsafeDescriptorSet {
|
||||
|
||||
#[inline]
|
||||
fn internal_object(&self) -> ash::vk::DescriptorSet {
|
||||
self.set
|
||||
self.handle
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Debug for UnsafeDescriptorSet {
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "<Vulkan descriptor set {:?}>", self.set)
|
||||
write!(fmt, "<Vulkan descriptor set {:?}>", self.handle)
|
||||
}
|
||||
}
|
||||
|
||||
@ -98,442 +126,288 @@ impl fmt::Debug for UnsafeDescriptorSet {
|
||||
/// 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.
|
||||
pub struct DescriptorWrite {
|
||||
binding: u32,
|
||||
pub(crate) binding_num: u32,
|
||||
first_array_element: u32,
|
||||
descriptor_type: DescriptorType,
|
||||
info: DescriptorWriteInfo,
|
||||
elements: DescriptorWriteElements,
|
||||
}
|
||||
|
||||
impl DescriptorWrite {
|
||||
#[inline]
|
||||
pub unsafe fn buffer(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferAccess>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::Buffer(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn buffer_view(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn BufferViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::BufferView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn image_view(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::ImageView(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn image_view_sampler(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::ImageViewSampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn sampler(
|
||||
binding_num: u32,
|
||||
first_array_element: u32,
|
||||
elements: impl IntoIterator<Item = Arc<Sampler>>,
|
||||
) -> Self {
|
||||
let elements: SmallVec<_> = elements.into_iter().collect();
|
||||
assert!(!elements.is_empty());
|
||||
Self {
|
||||
binding_num,
|
||||
first_array_element,
|
||||
elements: DescriptorWriteElements::Sampler(elements),
|
||||
}
|
||||
}
|
||||
|
||||
/// Returns the binding number that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn binding_num(&self) -> u32 {
|
||||
self.binding_num
|
||||
}
|
||||
|
||||
/// Returns the first array element in the binding that is updated by this descriptor write.
|
||||
#[inline]
|
||||
pub fn first_array_element(&self) -> u32 {
|
||||
self.first_array_element
|
||||
}
|
||||
|
||||
/// Returns a reference to the elements held by this descriptor write.
|
||||
#[inline]
|
||||
pub fn elements(&self) -> &DescriptorWriteElements {
|
||||
&self.elements
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan_info(&self, descriptor_type: DescriptorType) -> DescriptorWriteInfo {
|
||||
match &self.elements {
|
||||
DescriptorWriteElements::Buffer(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformBuffer
|
||||
| DescriptorType::StorageBuffer
|
||||
| DescriptorType::UniformBufferDynamic
|
||||
| DescriptorType::StorageBufferDynamic
|
||||
));
|
||||
DescriptorWriteInfo::Buffer(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_storage_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_storage_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::BufferView(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::UniformTexelBuffer | DescriptorType::StorageTexelBuffer
|
||||
));
|
||||
DescriptorWriteInfo::BufferView(
|
||||
elements
|
||||
.iter()
|
||||
.map(|buffer_view| buffer_view.inner())
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::ImageView(elements) => {
|
||||
// Note: combined image sampler can occur with immutable samplers
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
| DescriptorType::SampledImage
|
||||
| DescriptorType::StorageImage
|
||||
| DescriptorType::InputAttachment
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => {
|
||||
debug_assert!(matches!(
|
||||
descriptor_type,
|
||||
DescriptorType::CombinedImageSampler
|
||||
));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|(image_view, sampler)| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.layout_for(descriptor_type).into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
DescriptorWriteElements::Sampler(elements) => {
|
||||
debug_assert!(matches!(descriptor_type, DescriptorType::Sampler));
|
||||
DescriptorWriteInfo::Image(
|
||||
elements
|
||||
.iter()
|
||||
.map(|sampler| ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: ash::vk::ImageView::null(),
|
||||
image_layout: ash::vk::ImageLayout::UNDEFINED,
|
||||
})
|
||||
.collect(),
|
||||
)
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan(
|
||||
&self,
|
||||
dst_set: ash::vk::DescriptorSet,
|
||||
descriptor_type: DescriptorType,
|
||||
) -> ash::vk::WriteDescriptorSet {
|
||||
ash::vk::WriteDescriptorSet {
|
||||
dst_set,
|
||||
dst_binding: self.binding_num,
|
||||
dst_array_element: self.first_array_element,
|
||||
descriptor_count: 0,
|
||||
descriptor_type: descriptor_type.into(),
|
||||
p_image_info: ptr::null(),
|
||||
p_buffer_info: ptr::null(),
|
||||
p_texel_buffer_view: ptr::null(),
|
||||
..Default::default()
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// The elements held by a descriptor write.
|
||||
pub enum DescriptorWriteElements {
|
||||
Buffer(SmallVec<[Arc<dyn BufferAccess>; 1]>),
|
||||
BufferView(SmallVec<[Arc<dyn BufferViewAbstract>; 1]>),
|
||||
ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>),
|
||||
ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>),
|
||||
Sampler(SmallVec<[Arc<Sampler>; 1]>),
|
||||
}
|
||||
|
||||
impl DescriptorWriteElements {
|
||||
/// Returns the number of elements.
|
||||
#[inline]
|
||||
pub fn len(&self) -> u32 {
|
||||
match self {
|
||||
DescriptorWriteElements::Buffer(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::BufferView(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::ImageView(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::ImageViewSampler(elements) => elements.len() as u32,
|
||||
DescriptorWriteElements::Sampler(elements) => elements.len() as u32,
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
#[derive(Clone, Debug)]
|
||||
enum DescriptorWriteInfo {
|
||||
pub(crate) enum DescriptorWriteInfo {
|
||||
Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
|
||||
Buffer(SmallVec<[ash::vk::DescriptorBufferInfo; 1]>),
|
||||
BufferView(SmallVec<[ash::vk::BufferView; 1]>),
|
||||
}
|
||||
|
||||
impl DescriptorWrite {
|
||||
#[inline]
|
||||
pub fn storage_image<'a, I>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
image_views: impl IntoIterator<Item = &'a I>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
I: ImageViewAbstract + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::StorageImage,
|
||||
info: DescriptorWriteInfo::Image(
|
||||
image_views
|
||||
.into_iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.storage_image.into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sampler<'a>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
samplers: impl IntoIterator<Item = &'a Arc<Sampler>>,
|
||||
) -> DescriptorWrite {
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::Sampler,
|
||||
info: DescriptorWriteInfo::Image(
|
||||
samplers
|
||||
.into_iter()
|
||||
.map(|sampler| ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.internal_object(),
|
||||
image_view: ash::vk::ImageView::null(),
|
||||
image_layout: ash::vk::ImageLayout::UNDEFINED,
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn sampled_image<'a, I>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
image_views: impl IntoIterator<Item = &'a I>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
I: ImageViewAbstract + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::SampledImage,
|
||||
info: DescriptorWriteInfo::Image(
|
||||
image_views
|
||||
.into_iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.sampled_image.into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn combined_image_sampler<'a, I>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
image_views_samplers: impl IntoIterator<Item = (Option<&'a Arc<Sampler>>, &'a I)>, // Some for dynamic sampler, None for immutable
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
I: ImageViewAbstract + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::CombinedImageSampler,
|
||||
info: DescriptorWriteInfo::Image(
|
||||
image_views_samplers
|
||||
.into_iter()
|
||||
.map(|(sampler, image_view)| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: sampler.map(|s| s.internal_object()).unwrap_or_default(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.combined_image_sampler.into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn uniform_texel_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffer_views: impl IntoIterator<Item = &'a BufferView<B>>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::UniformTexelBuffer,
|
||||
info: DescriptorWriteInfo::BufferView(
|
||||
buffer_views
|
||||
.into_iter()
|
||||
.map(|buffer_view| {
|
||||
assert!(buffer_view.uniform_texel_buffer());
|
||||
buffer_view.internal_object()
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn storage_texel_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffer_view: impl IntoIterator<Item = &'a BufferView<B>>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::StorageTexelBuffer,
|
||||
info: DescriptorWriteInfo::BufferView(
|
||||
buffer_view
|
||||
.into_iter()
|
||||
.map(|buffer_view| {
|
||||
assert!(buffer_view.storage_texel_buffer());
|
||||
buffer_view.internal_object()
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn uniform_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffers: impl IntoIterator<Item = &'a B>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::UniformBuffer,
|
||||
info: DescriptorWriteInfo::Buffer(
|
||||
buffers
|
||||
.into_iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_uniform_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_uniform_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn storage_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffers: impl IntoIterator<Item = &'a B>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::StorageBuffer,
|
||||
info: DescriptorWriteInfo::Buffer(
|
||||
buffers
|
||||
.into_iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_storage_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_storage_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn dynamic_uniform_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffers: impl IntoIterator<Item = &'a B>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::UniformBufferDynamic,
|
||||
info: DescriptorWriteInfo::Buffer(
|
||||
buffers
|
||||
.into_iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_uniform_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_uniform_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub unsafe fn dynamic_storage_buffer<'a, B>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
buffers: impl IntoIterator<Item = &'a B>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
B: BufferAccess + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::StorageBufferDynamic,
|
||||
info: DescriptorWriteInfo::Buffer(
|
||||
buffers
|
||||
.into_iter()
|
||||
.map(|buffer| {
|
||||
let size = buffer.size();
|
||||
let BufferInner { buffer, offset } = buffer.inner();
|
||||
|
||||
debug_assert_eq!(
|
||||
offset
|
||||
% buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.min_storage_buffer_offset_alignment,
|
||||
0
|
||||
);
|
||||
debug_assert!(
|
||||
size <= buffer
|
||||
.device()
|
||||
.physical_device()
|
||||
.properties()
|
||||
.max_storage_buffer_range
|
||||
as DeviceSize
|
||||
);
|
||||
ash::vk::DescriptorBufferInfo {
|
||||
buffer: buffer.internal_object(),
|
||||
offset,
|
||||
range: size,
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
#[inline]
|
||||
pub fn input_attachment<'a, I>(
|
||||
binding: u32,
|
||||
first_array_element: u32,
|
||||
image_views: impl IntoIterator<Item = &'a I>,
|
||||
) -> DescriptorWrite
|
||||
where
|
||||
I: ImageViewAbstract + 'a,
|
||||
{
|
||||
DescriptorWrite {
|
||||
binding,
|
||||
first_array_element,
|
||||
descriptor_type: DescriptorType::InputAttachment,
|
||||
info: DescriptorWriteInfo::Image(
|
||||
image_views
|
||||
.into_iter()
|
||||
.map(|image_view| {
|
||||
let layouts = image_view.image().descriptor_layouts().expect(
|
||||
"descriptor_layouts must return Some when used in an image view",
|
||||
);
|
||||
ash::vk::DescriptorImageInfo {
|
||||
sampler: ash::vk::Sampler::null(),
|
||||
image_view: image_view.inner().internal_object(),
|
||||
image_layout: layouts.input_attachment.into(),
|
||||
}
|
||||
})
|
||||
.collect(),
|
||||
),
|
||||
}
|
||||
}
|
||||
|
||||
pub(crate) fn to_vulkan(&self, dst_set: ash::vk::DescriptorSet) -> ash::vk::WriteDescriptorSet {
|
||||
let mut result = ash::vk::WriteDescriptorSet {
|
||||
dst_set,
|
||||
dst_binding: self.binding,
|
||||
dst_array_element: self.first_array_element,
|
||||
descriptor_count: 0,
|
||||
descriptor_type: self.descriptor_type.into(),
|
||||
p_image_info: ptr::null(),
|
||||
p_buffer_info: ptr::null(),
|
||||
p_texel_buffer_view: ptr::null(),
|
||||
..Default::default()
|
||||
};
|
||||
|
||||
// Set the pointers separately.
|
||||
// You must keep `*self` alive and unmoved until the function call is done.
|
||||
match &self.info {
|
||||
impl DescriptorWriteInfo {
|
||||
fn set_info(&self, write: &mut ash::vk::WriteDescriptorSet) {
|
||||
match self {
|
||||
DescriptorWriteInfo::Image(info) => {
|
||||
result.descriptor_count = info.len() as u32;
|
||||
result.p_image_info = info.as_ptr();
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_image_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::Buffer(info) => {
|
||||
result.descriptor_count = info.len() as u32;
|
||||
result.p_buffer_info = info.as_ptr();
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_buffer_info = info.as_ptr();
|
||||
}
|
||||
DescriptorWriteInfo::BufferView(info) => {
|
||||
result.descriptor_count = info.len() as u32;
|
||||
result.p_texel_buffer_view = info.as_ptr();
|
||||
write.descriptor_count = info.len() as u32;
|
||||
write.p_texel_buffer_view = info.as_ptr();
|
||||
}
|
||||
}
|
||||
|
||||
// Since the `DescriptorWrite` objects are built only through functions, we know for
|
||||
// sure that it's impossible to have an empty descriptor write.
|
||||
debug_assert!(result.descriptor_count != 0);
|
||||
result
|
||||
debug_assert!(write.descriptor_count != 0);
|
||||
}
|
||||
}
|
||||
|
@ -7,6 +7,8 @@
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
use crate::descriptor_set::layout::DescriptorType;
|
||||
|
||||
/// Layout of an image.
|
||||
///
|
||||
/// > **Note**: In vulkano, image layouts are mostly a low-level detail. You can ignore them,
|
||||
@ -58,3 +60,18 @@ pub struct ImageDescriptorLayouts {
|
||||
/// The image layout to use in a descriptor as an input attachment.
|
||||
pub input_attachment: ImageLayout,
|
||||
}
|
||||
|
||||
impl ImageDescriptorLayouts {
|
||||
/// Returns the layout for the given descriptor type. Panics if `descriptor_type` is not an
|
||||
/// image descriptor type.
|
||||
#[inline]
|
||||
pub fn layout_for(&self, descriptor_type: DescriptorType) -> ImageLayout {
|
||||
match descriptor_type {
|
||||
DescriptorType::CombinedImageSampler => self.combined_image_sampler,
|
||||
DescriptorType::SampledImage => self.sampled_image,
|
||||
DescriptorType::StorageImage => self.storage_image,
|
||||
DescriptorType::InputAttachment => self.input_attachment,
|
||||
_ => panic!("{:?} is not an image descriptor type", descriptor_type),
|
||||
}
|
||||
}
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user