Replace ImageAccess::descriptor_layouts() (#2197)

* Replace `ImageAccess::descriptor_layouts()`

* Add `WriteDescriptorSet` constructors for image views with layout

* Replace `descriptor_layouts` for real

* Small changes

* More improvements
This commit is contained in:
Rua 2023-05-03 17:19:28 +02:00 committed by GitHub
parent 7741e00348
commit 93babbebae
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
14 changed files with 591 additions and 282 deletions

View File

@ -20,8 +20,8 @@ use vulkano::{
allocator::StandardCommandBufferAllocator, AutoCommandBufferBuilder, CommandBufferUsage,
},
descriptor_set::{
allocator::StandardDescriptorSetAllocator, layout::DescriptorType, DescriptorSet,
PersistentDescriptorSet, WriteDescriptorSet,
allocator::StandardDescriptorSetAllocator, layout::DescriptorType, DescriptorBufferInfo,
DescriptorSet, PersistentDescriptorSet, WriteDescriptorSet,
},
device::{
physical::PhysicalDeviceType, Device, DeviceCreateInfo, DeviceExtensions, QueueCreateInfo,
@ -226,8 +226,10 @@ fn main() {
// this range.
WriteDescriptorSet::buffer_with_range(
0,
input_buffer,
0..size_of::<cs::InData>() as DeviceSize,
DescriptorBufferInfo {
buffer: input_buffer,
range: 0..size_of::<cs::InData>() as DeviceSize,
},
),
WriteDescriptorSet::buffer(1, output_buffer.clone()),
],

View File

@ -17,10 +17,10 @@ use crate::{
AutoCommandBufferBuilder,
},
descriptor_set::{
check_descriptor_write, layout::DescriptorType, sys::UnsafeDescriptorSet,
DescriptorBindingResources, DescriptorSetResources, DescriptorSetUpdateError,
DescriptorSetWithOffsets, DescriptorSetsCollection, DescriptorWriteInfo,
WriteDescriptorSet,
layout::DescriptorType, set_descriptor_write_image_layouts, sys::UnsafeDescriptorSet,
validate_descriptor_write, DescriptorBindingResources, DescriptorBufferInfo,
DescriptorSetResources, DescriptorSetUpdateError, DescriptorSetWithOffsets,
DescriptorSetsCollection, DescriptorWriteInfo, WriteDescriptorSet,
},
device::{DeviceOwned, QueueFlags},
memory::{is_aligned, DeviceAlignment},
@ -194,7 +194,9 @@ where
});
}
if let Some((buffer, range)) = element {
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
// VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979
if offset as DeviceSize + range.end > buffer.size() {
return Err(BindPushError::DynamicOffsetOutOfBufferBounds {
@ -623,7 +625,15 @@ where
set_num: u32,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
) -> &mut Self {
let descriptor_writes: SmallVec<[_; 8]> = descriptor_writes.into_iter().collect();
let mut descriptor_writes: SmallVec<[_; 8]> = descriptor_writes.into_iter().collect();
// Set the image layouts
if let Some(set_layout) = pipeline_layout.set_layouts().get(set_num as usize) {
for write in &mut descriptor_writes {
set_descriptor_write_image_layouts(write, set_layout);
}
}
self.validate_push_descriptor_set(
pipeline_bind_point,
&pipeline_layout,
@ -706,7 +716,7 @@ where
}
for write in descriptor_writes {
check_descriptor_write(write, descriptor_set_layout, 0)?;
validate_descriptor_write(write, descriptor_set_layout, 0)?;
}
Ok(())
@ -901,9 +911,16 @@ impl SyncCommandBufferBuilder {
}
}
let descriptor_writes: SmallVec<[WriteDescriptorSet; 8]> =
let mut descriptor_writes: SmallVec<[WriteDescriptorSet; 8]> =
descriptor_writes.into_iter().collect();
// Set the image layouts
if let Some(set_layout) = pipeline_layout.set_layouts().get(set_num as usize) {
for write in &mut descriptor_writes {
set_descriptor_write_image_layouts(write, set_layout);
}
}
let state = self.current_state.invalidate_descriptor_sets(
pipeline_bind_point,
pipeline_layout.clone(),
@ -1213,12 +1230,15 @@ impl UnsafeCommandBufferBuilder {
descriptor_writes: impl IntoIterator<Item = &'a WriteDescriptorSet>,
) {
debug_assert!(self.device.enabled_extensions().khr_push_descriptor);
let set_layout = &pipeline_layout.set_layouts()[set_num as usize];
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
let (infos_vk, mut writes_vk): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
.into_iter()
.map(|write| {
let binding =
&pipeline_layout.set_layouts()[set_num as usize].bindings()[&write.binding()];
let mut write = write.clone(); // Ew!
set_descriptor_write_image_layouts(&mut write, set_layout);
let binding = &set_layout.bindings()[&write.binding()];
(
write.to_vulkan_info(binding.descriptor_type),
@ -1227,28 +1247,28 @@ impl UnsafeCommandBufferBuilder {
})
.unzip();
if writes.is_empty() {
if writes_vk.is_empty() {
return;
}
// Set the info pointers separately.
for (info, write) in infos.iter().zip(writes.iter_mut()) {
match info {
for (info_vk, write_vk) in infos_vk.iter().zip(writes_vk.iter_mut()) {
match info_vk {
DescriptorWriteInfo::Image(info) => {
write.descriptor_count = info.len() as u32;
write.p_image_info = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_image_info = info.as_ptr();
}
DescriptorWriteInfo::Buffer(info) => {
write.descriptor_count = info.len() as u32;
write.p_buffer_info = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_buffer_info = info.as_ptr();
}
DescriptorWriteInfo::BufferView(info) => {
write.descriptor_count = info.len() as u32;
write.p_texel_buffer_view = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_texel_buffer_view = info.as_ptr();
}
}
debug_assert!(write.descriptor_count != 0);
debug_assert!(write_vk.descriptor_count != 0);
}
let fns = self.device.fns();
@ -1258,8 +1278,8 @@ impl UnsafeCommandBufferBuilder {
pipeline_bind_point.into(),
pipeline_layout.handle(),
set_num,
writes.len() as u32,
writes.as_ptr(),
writes_vk.len() as u32,
writes_vk.as_ptr(),
);
}
}

View File

@ -17,12 +17,15 @@ use crate::{
AutoCommandBufferBuilder, DispatchIndirectCommand, DrawIndexedIndirectCommand,
DrawIndirectCommand, ResourceInCommand, ResourceUseRef, SubpassContents,
},
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
descriptor_set::{
layout::DescriptorType, DescriptorBindingResources, DescriptorBufferInfo,
DescriptorImageViewInfo,
},
device::{DeviceOwned, QueueFlags},
format::{Format, FormatFeatures},
image::{
view::ImageViewType, ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract,
SampleCount,
view::ImageViewType, ImageAccess, ImageAspects, ImageLayout, ImageSubresourceRange,
ImageViewAbstract, SampleCount,
},
pipeline::{
graphics::{
@ -642,8 +645,7 @@ where
let layout_binding =
&pipeline.layout().set_layouts()[set_num as usize].bindings()[&binding_num];
let check_buffer =
|_index: u32, (_buffer, _range): &(Subbuffer<[u8]>, Range<DeviceSize>)| Ok(());
let check_buffer = |_index: u32, _buffer_info: &DescriptorBufferInfo| Ok(());
let check_buffer_view = |index: u32, buffer_view: &Arc<BufferView>| {
for desc_reqs in (binding_reqs.descriptors.get(&Some(index)).into_iter())
@ -840,7 +842,12 @@ where
Ok(())
};
let check_image_view = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| {
let check_image_view = |index: u32, image_view_info: &DescriptorImageViewInfo| {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
check_image_view_common(index, image_view)?;
if let Some(sampler) = layout_binding.immutable_samplers.get(index as usize) {
@ -850,13 +857,21 @@ where
Ok(())
};
let check_image_view_sampler =
|index: u32, (image_view, sampler): &(Arc<dyn ImageViewAbstract>, Arc<Sampler>)| {
check_image_view_common(index, image_view)?;
check_sampler_common(index, sampler)?;
let check_image_view_sampler = |index: u32,
(image_view_info, sampler): &(
DescriptorImageViewInfo,
Arc<Sampler>,
)| {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
Ok(())
};
check_image_view_common(index, image_view)?;
check_sampler_common(index, sampler)?;
Ok(())
};
let check_sampler = |index: u32, sampler: &Arc<Sampler>| {
check_sampler_common(index, sampler)?;
@ -881,7 +896,12 @@ where
})
});
for (id, image_view) in iter {
for (id, image_view_info) in iter {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
return Err(
DescriptorResourceInvalidError::SamplerImageViewIncompatible {
@ -2101,16 +2121,12 @@ impl SyncCommandBufferBuilder {
)
})
};
let image_resource = |(index, image, subresource_range): (
let image_resource = |(index, image, layout, subresource_range): (
u32,
Arc<dyn ImageAccess>,
ImageLayout,
ImageSubresourceRange,
)| {
let layout = image
.descriptor_layouts()
.expect("descriptor_layouts must return Some when used in an image view")
.layout_for(descriptor_type);
memory_iter(index).map(move |memory| {
(
ResourceUseRef {
@ -2147,7 +2163,9 @@ impl SyncCommandBufferBuilder {
resources.extend(
(elements.iter().enumerate())
.filter_map(|(index, element)| {
element.as_ref().map(|(buffer, range)| {
element.as_ref().map(|buffer_info| {
let DescriptorBufferInfo { buffer, range } = buffer_info;
let dynamic_offset = dynamic_offsets[index] as DeviceSize;
(
@ -2164,7 +2182,8 @@ impl SyncCommandBufferBuilder {
resources.extend(
(elements.iter().enumerate())
.filter_map(|(index, element)| {
element.as_ref().map(|(buffer, range)| {
element.as_ref().map(|buffer_info| {
let DescriptorBufferInfo { buffer, range } = buffer_info;
(index as u32, buffer.clone(), range.clone())
})
})
@ -2191,10 +2210,16 @@ impl SyncCommandBufferBuilder {
resources.extend(
(elements.iter().enumerate())
.filter_map(|(index, element)| {
element.as_ref().map(|image_view| {
element.as_ref().map(|image_view_info| {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
(
index as u32,
image_view.image(),
image_layout,
image_view.subresource_range().clone(),
)
})
@ -2206,10 +2231,16 @@ impl SyncCommandBufferBuilder {
resources.extend(
(elements.iter().enumerate())
.filter_map(|(index, element)| {
element.as_ref().map(|(image_view, _)| {
element.as_ref().map(|(image_view_info, _sampler)| {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
(
index as u32,
image_view.image(),
image_layout,
image_view.subresource_range().clone(),
)
})

View File

@ -12,9 +12,10 @@ use crate::{
buffer::{BufferContents, BufferUsage, Subbuffer},
command_buffer::{allocator::CommandBufferAllocator, commands::bind_push::BindPushError},
descriptor_set::{
check_descriptor_write, layout::DescriptorType, DescriptorBindingResources,
DescriptorSetResources, DescriptorSetWithOffsets, DescriptorSetsCollection,
DescriptorWriteInfo, WriteDescriptorSet,
layout::DescriptorType, set_descriptor_write_image_layouts, validate_descriptor_write,
DescriptorBindingResources, DescriptorBufferInfo, DescriptorSetResources,
DescriptorSetWithOffsets, DescriptorSetsCollection, DescriptorWriteInfo,
WriteDescriptorSet,
},
device::{DeviceOwned, QueueFlags},
memory::is_aligned,
@ -172,7 +173,9 @@ where
});
}
if let Some((buffer, range)) = element {
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
// VUID-vkCmdBindDescriptorSets-pDescriptorSets-01979
if offset as DeviceSize + range.end > buffer.size() {
return Err(BindPushError::DynamicOffsetOutOfBufferBounds {
@ -761,7 +764,15 @@ where
set_num: u32,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
) -> &mut Self {
let descriptor_writes: SmallVec<[_; 8]> = descriptor_writes.into_iter().collect();
let mut descriptor_writes: SmallVec<[_; 8]> = descriptor_writes.into_iter().collect();
// Set the image layouts
if let Some(set_layout) = pipeline_layout.set_layouts().get(set_num as usize) {
for write in &mut descriptor_writes {
set_descriptor_write_image_layouts(write, set_layout);
}
}
self.validate_push_descriptor_set(
pipeline_bind_point,
&pipeline_layout,
@ -842,7 +853,7 @@ where
}
for write in descriptor_writes {
check_descriptor_write(write, descriptor_set_layout, 0)?;
validate_descriptor_write(write, descriptor_set_layout, 0)?;
}
Ok(())
@ -856,16 +867,17 @@ where
set_num: u32,
descriptor_writes: impl IntoIterator<Item = WriteDescriptorSet>,
) -> &mut Self {
let descriptor_writes: SmallVec<[WriteDescriptorSet; 8]> =
let mut descriptor_writes: SmallVec<[WriteDescriptorSet; 8]> =
descriptor_writes.into_iter().collect();
debug_assert!(self.device().enabled_extensions().khr_push_descriptor);
let set_layout = &pipeline_layout.set_layouts()[set_num as usize];
let (infos, mut writes): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
.iter()
let (infos_vk, mut writes_vk): (SmallVec<[_; 8]>, SmallVec<[_; 8]>) = descriptor_writes
.iter_mut()
.map(|write| {
let binding =
&pipeline_layout.set_layouts()[set_num as usize].bindings()[&write.binding()];
set_descriptor_write_image_layouts(write, set_layout);
let binding = &set_layout.bindings()[&write.binding()];
(
write.to_vulkan_info(binding.descriptor_type),
@ -874,28 +886,28 @@ where
})
.unzip();
if writes.is_empty() {
if writes_vk.is_empty() {
return self;
}
// Set the info pointers separately.
for (info, write) in infos.iter().zip(writes.iter_mut()) {
match info {
for (info_vk, write_vk) in infos_vk.iter().zip(writes_vk.iter_mut()) {
match info_vk {
DescriptorWriteInfo::Image(info) => {
write.descriptor_count = info.len() as u32;
write.p_image_info = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_image_info = info.as_ptr();
}
DescriptorWriteInfo::Buffer(info) => {
write.descriptor_count = info.len() as u32;
write.p_buffer_info = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_buffer_info = info.as_ptr();
}
DescriptorWriteInfo::BufferView(info) => {
write.descriptor_count = info.len() as u32;
write.p_texel_buffer_view = info.as_ptr();
write_vk.descriptor_count = info.len() as u32;
write_vk.p_texel_buffer_view = info.as_ptr();
}
}
debug_assert!(write.descriptor_count != 0);
debug_assert!(write_vk.descriptor_count != 0);
}
let fns = self.device().fns();
@ -904,8 +916,8 @@ where
pipeline_bind_point.into(),
pipeline_layout.handle(),
set_num,
writes.len() as u32,
writes.as_ptr(),
writes_vk.len() as u32,
writes_vk.as_ptr(),
);
let state = self.builder_state.invalidate_descriptor_sets(

View File

@ -18,7 +18,10 @@ use crate::{
DispatchIndirectCommand, DrawIndexedIndirectCommand, DrawIndirectCommand,
ResourceInCommand, ResourceUseRef, SubpassContents,
},
descriptor_set::{layout::DescriptorType, DescriptorBindingResources},
descriptor_set::{
layout::DescriptorType, DescriptorBindingResources, DescriptorBufferInfo,
DescriptorImageViewInfo,
},
device::{DeviceOwned, QueueFlags},
format::FormatFeatures,
image::{ImageAccess, ImageAspects, ImageSubresourceRange, ImageViewAbstract, SampleCount},
@ -40,7 +43,7 @@ use crate::{
DeviceSize, RequiresOneOf, VulkanObject,
};
use ahash::HashMap;
use std::{cmp::min, mem::size_of, ops::Range, sync::Arc};
use std::{cmp::min, mem::size_of, sync::Arc};
impl<L, A> CommandBufferBuilder<L, A>
where
@ -991,8 +994,7 @@ where
let layout_binding =
&pipeline.layout().set_layouts()[set_num as usize].bindings()[&binding_num];
let check_buffer =
|_index: u32, (_buffer, _range): &(Subbuffer<[u8]>, Range<DeviceSize>)| Ok(());
let check_buffer = |_index: u32, _info: &DescriptorBufferInfo| Ok(());
let check_buffer_view = |index: u32, buffer_view: &Arc<BufferView>| {
for desc_reqs in (binding_reqs.descriptors.get(&Some(index)).into_iter())
@ -1189,7 +1191,12 @@ where
Ok(())
};
let check_image_view = |index: u32, image_view: &Arc<dyn ImageViewAbstract>| {
let check_image_view = |index: u32, image_view_info: &DescriptorImageViewInfo| {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
check_image_view_common(index, image_view)?;
if let Some(sampler) = layout_binding.immutable_samplers.get(index as usize) {
@ -1199,13 +1206,21 @@ where
Ok(())
};
let check_image_view_sampler =
|index: u32, (image_view, sampler): &(Arc<dyn ImageViewAbstract>, Arc<Sampler>)| {
check_image_view_common(index, image_view)?;
check_sampler_common(index, sampler)?;
let check_image_view_sampler = |index: u32,
(image_view_info, sampler): &(
DescriptorImageViewInfo,
Arc<Sampler>,
)| {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
Ok(())
};
check_image_view_common(index, image_view)?;
check_sampler_common(index, sampler)?;
Ok(())
};
let check_sampler = |index: u32, sampler: &Arc<Sampler>| {
check_sampler_common(index, sampler)?;
@ -1231,7 +1246,12 @@ where
})
});
for (id, image_view) in iter {
for (id, image_view_info) in iter {
let DescriptorImageViewInfo {
image_view,
image_layout: _,
} = image_view_info;
if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
return Err(
DescriptorResourceInvalidError::SamplerImageViewIncompatible {
@ -2065,7 +2085,9 @@ fn record_descriptor_sets_access(
let dynamic_offsets = descriptor_set_state.dynamic_offsets();
for (index, element) in elements.iter().enumerate() {
if let Some((buffer, range)) = element {
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
let dynamic_offset = dynamic_offsets[index] as DeviceSize;
let (use_ref, stage_access_iter) = use_iter(index as u32);
@ -2085,7 +2107,9 @@ fn record_descriptor_sets_access(
}
} else {
for (index, element) in elements.iter().enumerate() {
if let Some((buffer, range)) = element {
if let Some(buffer_info) = element {
let DescriptorBufferInfo { buffer, range } = buffer_info;
let (use_ref, stage_access_iter) = use_iter(index as u32);
let mut range = range.clone();
@ -2127,15 +2151,14 @@ fn record_descriptor_sets_access(
}
DescriptorBindingResources::ImageView(elements) => {
for (index, element) in elements.iter().enumerate() {
if let Some(image_view) = element {
if let Some(image_view_info) = element {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
let image = image_view.image();
let image_inner = image.inner();
let layout = image
.descriptor_layouts()
.expect(
"descriptor_layouts must return Some when used in an image view",
)
.layout_for(descriptor_type);
let (use_ref, stage_access_iter) = use_iter(index as u32);
for stage_access in stage_access_iter {
@ -2144,7 +2167,7 @@ fn record_descriptor_sets_access(
image_inner,
image_view.subresource_range().clone(),
stage_access,
layout,
image_layout,
);
}
}
@ -2152,15 +2175,14 @@ fn record_descriptor_sets_access(
}
DescriptorBindingResources::ImageViewSampler(elements) => {
for (index, element) in elements.iter().enumerate() {
if let Some((image_view, _)) = element {
if let Some((image_view_info, _sampler)) = element {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
let image = image_view.image();
let image_inner = image.inner();
let layout = image
.descriptor_layouts()
.expect(
"descriptor_layouts must return Some when used in an image view",
)
.layout_for(descriptor_type);
let (use_ref, stage_access_iter) = use_iter(index as u32);
for stage_access in stage_access_iter {
@ -2169,7 +2191,7 @@ fn record_descriptor_sets_access(
image_inner,
image_view.subresource_range().clone(),
stage_access,
layout,
image_layout,
);
}
}

View File

@ -78,20 +78,21 @@
//! [`DescriptorSetAllocator`]: allocator::DescriptorSetAllocator
//! [`StandardDescriptorSetAllocator`]: allocator::StandardDescriptorSetAllocator
pub(crate) use self::update::{check_descriptor_write, DescriptorWriteInfo};
pub(crate) use self::update::{
set_descriptor_write_image_layouts, validate_descriptor_write, DescriptorWriteInfo,
};
pub use self::{
collection::DescriptorSetsCollection,
persistent::PersistentDescriptorSet,
update::{DescriptorSetUpdateError, WriteDescriptorSet, WriteDescriptorSetElements},
update::{
DescriptorBufferInfo, DescriptorImageViewInfo, DescriptorSetUpdateError,
WriteDescriptorSet, WriteDescriptorSetElements,
},
};
use self::{layout::DescriptorSetLayout, sys::UnsafeDescriptorSet};
use crate::{
buffer::{view::BufferView, Subbuffer},
descriptor_set::layout::DescriptorType,
device::DeviceOwned,
image::view::ImageViewAbstract,
sampler::Sampler,
DeviceSize, OomError, VulkanObject,
buffer::view::BufferView, descriptor_set::layout::DescriptorType, device::DeviceOwned,
sampler::Sampler, OomError, VulkanObject,
};
use ahash::HashMap;
use smallvec::{smallvec, SmallVec};
@ -99,7 +100,6 @@ use std::{
error::Error,
fmt::{Display, Error as FmtError, Formatter},
hash::{Hash, Hasher},
ops::Range,
ptr,
sync::Arc,
};
@ -188,22 +188,24 @@ impl DescriptorSetInner {
let descriptor_writes = descriptor_writes.into_iter();
let (lower_size_bound, _) = descriptor_writes.size_hint();
let mut descriptor_write_info: SmallVec<[_; 8]> = SmallVec::with_capacity(lower_size_bound);
let mut write_descriptor_set: SmallVec<[_; 8]> = SmallVec::with_capacity(lower_size_bound);
let mut descriptor_write_infos_vk: SmallVec<[_; 8]> =
SmallVec::with_capacity(lower_size_bound);
let mut descriptor_writes_vk: SmallVec<[_; 8]> = SmallVec::with_capacity(lower_size_bound);
for write in descriptor_writes {
for mut write in descriptor_writes {
set_descriptor_write_image_layouts(&mut write, &layout);
let layout_binding =
check_descriptor_write(&write, &layout, variable_descriptor_count)?;
validate_descriptor_write(&write, &layout, variable_descriptor_count)?;
resources.update(&write);
descriptor_write_info.push(write.to_vulkan_info(layout_binding.descriptor_type));
write_descriptor_set.push(write.to_vulkan(handle, layout_binding.descriptor_type));
descriptor_write_infos_vk.push(write.to_vulkan_info(layout_binding.descriptor_type));
descriptor_writes_vk.push(write.to_vulkan(handle, layout_binding.descriptor_type));
}
if !write_descriptor_set.is_empty() {
for (info, write) in descriptor_write_info
if !descriptor_writes_vk.is_empty() {
for (info, write) in descriptor_write_infos_vk
.iter()
.zip(write_descriptor_set.iter_mut())
.zip(descriptor_writes_vk.iter_mut())
{
match info {
DescriptorWriteInfo::Image(info) => {
@ -227,8 +229,8 @@ impl DescriptorSetInner {
(fns.v1_0.update_descriptor_sets)(
layout.device().handle(),
write_descriptor_set.len() as u32,
write_descriptor_set.as_ptr(),
descriptor_writes_vk.len() as u32,
descriptor_writes_vk.as_ptr(),
0,
ptr::null(),
);
@ -342,10 +344,10 @@ impl DescriptorSetResources {
#[derive(Clone)]
pub enum DescriptorBindingResources {
None(Elements<()>),
Buffer(Elements<(Subbuffer<[u8]>, Range<DeviceSize>)>),
Buffer(Elements<DescriptorBufferInfo>),
BufferView(Elements<Arc<BufferView>>),
ImageView(Elements<Arc<dyn ImageViewAbstract>>),
ImageViewSampler(Elements<(Arc<dyn ImageViewAbstract>, Arc<Sampler>)>),
ImageView(Elements<DescriptorImageViewInfo>),
ImageViewSampler(Elements<(DescriptorImageViewInfo, Arc<Sampler>)>),
Sampler(Elements<Arc<Sampler>>),
}

View File

@ -11,7 +11,9 @@ use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorT
use crate::{
buffer::{view::BufferView, BufferUsage, Subbuffer},
device::DeviceOwned,
image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract},
image::{
view::ImageViewType, ImageAspects, ImageLayout, ImageType, ImageUsage, ImageViewAbstract,
},
sampler::{Sampler, SamplerImageViewIncompatibleError},
DeviceSize, RequiresOneOf, VulkanObject,
};
@ -33,10 +35,11 @@ use std::{
/// non-arrayed bindings, where `descriptor_count` in the descriptor set layout is 1.
/// - The `_array` variant writes several elements and allows specifying the target array index.
/// At least one element must be provided; a panic results if the provided iterator is empty.
#[derive(Clone, Debug)]
pub struct WriteDescriptorSet {
binding: u32,
first_array_element: u32,
elements: WriteDescriptorSetElements,
pub(crate) elements: WriteDescriptorSetElements, // public so that the image layouts can be changed
}
impl WriteDescriptorSet {
@ -74,7 +77,14 @@ impl WriteDescriptorSet {
#[inline]
pub fn buffer(binding: u32, buffer: Subbuffer<impl ?Sized>) -> Self {
let range = 0..buffer.size();
Self::buffer_with_range_array(binding, 0, [(buffer, range)])
Self::buffer_with_range_array(
binding,
0,
[DescriptorBufferInfo {
buffer: buffer.into_bytes(),
range,
}],
)
}
/// Write a number of consecutive buffer elements.
@ -91,28 +101,18 @@ impl WriteDescriptorSet {
first_array_element,
elements.into_iter().map(|buffer| {
let range = 0..buffer.size();
(buffer, range)
DescriptorBufferInfo {
buffer: buffer.into_bytes(),
range,
}
}),
)
}
/// Write a single buffer to array element 0, specifying the range of the buffer to be bound.
///
/// `range` is the slice of bytes in `buffer` that will be made available to the shader.
/// `range` must not be outside the range `buffer`.
///
/// For dynamic buffer bindings, `range` specifies the slice that is to be bound if the
/// dynamic offset were zero. When binding the descriptor set, the effective value of `range`
/// shifts forward by the offset that was provided. For example, if `range` is specified as
/// `0..8` when writing the descriptor set, and then when binding the descriptor set the
/// offset `16` is used, then the range of `buffer` that will actually be bound is `16..24`.
#[inline]
pub fn buffer_with_range(
binding: u32,
buffer: Subbuffer<impl ?Sized>,
range: Range<DeviceSize>,
) -> Self {
Self::buffer_with_range_array(binding, 0, [(buffer, range)])
pub fn buffer_with_range(binding: u32, buffer_info: DescriptorBufferInfo) -> Self {
Self::buffer_with_range_array(binding, 0, [buffer_info])
}
/// Write a number of consecutive buffer elements, specifying the ranges of the buffers to be
@ -122,12 +122,9 @@ impl WriteDescriptorSet {
pub fn buffer_with_range_array(
binding: u32,
first_array_element: u32,
elements: impl IntoIterator<Item = (Subbuffer<impl ?Sized>, Range<DeviceSize>)>,
elements: impl IntoIterator<Item = DescriptorBufferInfo>,
) -> Self {
let elements: SmallVec<_> = elements
.into_iter()
.map(|(buffer, range)| (buffer.into_bytes(), range))
.collect();
let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty());
Self {
@ -151,6 +148,7 @@ impl WriteDescriptorSet {
) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty());
Self {
binding,
first_array_element,
@ -158,17 +156,53 @@ impl WriteDescriptorSet {
}
}
/// Write a single image view to array element 0.
/// Write a single image view to array element 0, using the `Undefined` image layout,
/// which will be automatically replaced with an appropriate default layout.
#[inline]
pub fn image_view(binding: u32, image_view: Arc<dyn ImageViewAbstract>) -> Self {
Self::image_view_array(binding, 0, [image_view])
Self::image_view_with_layout_array(
binding,
0,
[DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::Undefined,
}],
)
}
/// Write a number of consecutive image view elements.
/// Write a number of consecutive image view elements, using the `Undefined` image layout,
/// which will be automatically replaced with an appropriate default layout.
#[inline]
pub fn image_view_array(
binding: u32,
first_array_element: u32,
elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>,
) -> Self {
Self::image_view_with_layout_array(
binding,
first_array_element,
elements
.into_iter()
.map(|image_view| DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::Undefined,
}),
)
}
/// Write a single image view to array element 0, specifying the layout of the image to be
/// bound.
#[inline]
pub fn image_view_with_layout(binding: u32, image_view_info: DescriptorImageViewInfo) -> Self {
Self::image_view_with_layout_array(binding, 0, [image_view_info])
}
/// Write a number of consecutive image view elements, specifying the layouts of the images to
/// be bound.
pub fn image_view_with_layout_array(
binding: u32,
first_array_element: u32,
elements: impl IntoIterator<Item = DescriptorImageViewInfo>,
) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty());
@ -179,24 +213,73 @@ impl WriteDescriptorSet {
}
}
/// Write a single image view and sampler to array element 0.
/// Write a single image view and sampler to array element 0,
/// using the `Undefined` image layout, which will be automatically replaced with
/// an appropriate default layout.
#[inline]
pub fn image_view_sampler(
binding: u32,
image_view: Arc<dyn ImageViewAbstract>,
sampler: Arc<Sampler>,
) -> Self {
Self::image_view_sampler_array(binding, 0, [(image_view, sampler)])
Self::image_view_with_layout_sampler_array(
binding,
0,
[(
DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::Undefined,
},
sampler,
)],
)
}
/// Write a number of consecutive image view and sampler elements.
/// Write a number of consecutive image view and sampler elements,
/// using the `Undefined` image layout, which will be automatically replaced with
/// an appropriate default layout.
#[inline]
pub fn image_view_sampler_array(
binding: u32,
first_array_element: u32,
elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>,
) -> Self {
Self::image_view_with_layout_sampler_array(
binding,
first_array_element,
elements.into_iter().map(|(image_view, sampler)| {
(
DescriptorImageViewInfo {
image_view,
image_layout: ImageLayout::Undefined,
},
sampler,
)
}),
)
}
/// Write a single image view and sampler to array element 0, specifying the layout of the
/// image to be bound.
#[inline]
pub fn image_view_with_layout_sampler(
binding: u32,
image_view_info: DescriptorImageViewInfo,
sampler: Arc<Sampler>,
) -> Self {
Self::image_view_with_layout_sampler_array(binding, 0, [(image_view_info, sampler)])
}
/// Write a number of consecutive image view and sampler elements, specifying the layout of the
/// image to be bound.
pub fn image_view_with_layout_sampler_array(
binding: u32,
first_array_element: u32,
elements: impl IntoIterator<Item = (DescriptorImageViewInfo, Arc<Sampler>)>,
) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty());
Self {
binding,
first_array_element,
@ -218,6 +301,7 @@ impl WriteDescriptorSet {
) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty());
Self {
binding,
first_array_element,
@ -268,7 +352,9 @@ impl WriteDescriptorSet {
DescriptorWriteInfo::Buffer(
elements
.iter()
.map(|(buffer, range)| {
.map(|buffer_info| {
let DescriptorBufferInfo { buffer, range } = buffer_info;
debug_assert!(!range.is_empty());
debug_assert!(range.end <= buffer.buffer().size());
@ -305,14 +391,16 @@ impl WriteDescriptorSet {
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",
);
.map(|image_view_info| {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
ash::vk::DescriptorImageInfo {
sampler: ash::vk::Sampler::null(),
image_view: image_view.handle(),
image_layout: layouts.layout_for(descriptor_type).into(),
image_layout: image_layout.into(),
}
})
.collect(),
@ -326,14 +414,16 @@ impl WriteDescriptorSet {
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",
);
.map(|(image_view_info, sampler)| {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
ash::vk::DescriptorImageInfo {
sampler: sampler.handle(),
image_view: image_view.handle(),
image_layout: layouts.layout_for(descriptor_type).into(),
image_layout: image_layout.into(),
}
})
.collect(),
@ -375,12 +465,13 @@ impl WriteDescriptorSet {
}
/// The elements held by a `WriteDescriptorSet`.
#[derive(Clone, Debug)]
pub enum WriteDescriptorSetElements {
None(u32),
Buffer(SmallVec<[(Subbuffer<[u8]>, Range<DeviceSize>); 1]>),
Buffer(SmallVec<[DescriptorBufferInfo; 1]>),
BufferView(SmallVec<[Arc<BufferView>; 1]>),
ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>),
ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>),
ImageView(SmallVec<[DescriptorImageViewInfo; 1]>),
ImageViewSampler(SmallVec<[(DescriptorImageViewInfo, Arc<Sampler>); 1]>),
Sampler(SmallVec<[Arc<Sampler>; 1]>),
}
@ -399,6 +490,49 @@ impl WriteDescriptorSetElements {
}
}
/// Parameters to write a buffer reference to a descriptor.
#[derive(Clone, Debug)]
pub struct DescriptorBufferInfo {
/// The buffer to write to the descriptor.
pub buffer: Subbuffer<[u8]>,
/// The slice of bytes in `buffer` that will be made available to the shader.
/// `range` must not be outside the range `buffer`.
///
/// For dynamic buffer bindings, `range` specifies the slice that is to be bound if the
/// dynamic offset were zero. When binding the descriptor set, the effective value of `range`
/// shifts forward by the offset that was provided. For example, if `range` is specified as
/// `0..8` when writing the descriptor set, and then when binding the descriptor set the
/// offset `16` is used, then the range of `buffer` that will actually be bound is `16..24`.
pub range: Range<DeviceSize>,
}
/// Parameters to write an image view reference to a descriptor.
#[derive(Clone, Debug)]
pub struct DescriptorImageViewInfo {
/// The image view to write to the descriptor.
pub image_view: Arc<dyn ImageViewAbstract>,
/// The layout that the image is expected to be in when it's accessed in the shader.
///
/// Only certain layouts are allowed, depending on the type of descriptor.
///
/// For `SampledImage`, `CombinedImageSampler` and `InputAttachment`:
/// - `General`
/// - `ShaderReadOnlyOptimal`
/// - `DepthStencilReadOnlyOptimal`
/// - `DepthReadOnlyStencilAttachmentOptimal`
/// - `DepthAttachmentStencilReadOnlyOptimal`
///
/// For `StorageImage`:
/// - `General`
///
/// If the `Undefined` layout is provided, then it will be automatically replaced with
/// `General` for `StorageImage` descriptors, and with `ShaderReadOnlyOptimal` for any other
/// descriptor type.
pub image_layout: ImageLayout,
}
#[derive(Clone, Debug)]
pub(crate) enum DescriptorWriteInfo {
Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
@ -406,7 +540,52 @@ pub(crate) enum DescriptorWriteInfo {
BufferView(SmallVec<[ash::vk::BufferView; 1]>),
}
pub(crate) fn check_descriptor_write<'a>(
pub(crate) fn set_descriptor_write_image_layouts(
write: &mut WriteDescriptorSet,
layout: &DescriptorSetLayout,
) {
let default_layout = if let Some(layout_binding) = layout.bindings().get(&write.binding()) {
match layout_binding.descriptor_type {
DescriptorType::CombinedImageSampler
| DescriptorType::SampledImage
| DescriptorType::InputAttachment => ImageLayout::ShaderReadOnlyOptimal,
DescriptorType::StorageImage => ImageLayout::General,
_ => return,
}
} else {
return;
};
match &mut write.elements {
WriteDescriptorSetElements::ImageView(elements) => {
for image_view_info in elements {
let DescriptorImageViewInfo {
image_view: _,
image_layout,
} = image_view_info;
if *image_layout == ImageLayout::Undefined {
*image_layout = default_layout;
}
}
}
WriteDescriptorSetElements::ImageViewSampler(elements) => {
for (image_view_info, _sampler) in elements {
let DescriptorImageViewInfo {
image_view: _,
image_layout,
} = image_view_info;
if *image_layout == ImageLayout::Undefined {
*image_layout = default_layout;
}
}
}
_ => (),
}
}
pub(crate) fn validate_descriptor_write<'a>(
write: &WriteDescriptorSet,
layout: &'a DescriptorSetLayout,
variable_descriptor_count: u32,
@ -512,7 +691,12 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, (image_view, sampler)) in elements.iter().enumerate() {
for (index, (image_view_info, sampler)) in elements.iter().enumerate() {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device());
assert_eq!(device, sampler.device());
@ -549,6 +733,21 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
// VUID-VkWriteDescriptorSet-descriptorType-04150
if !matches!(
image_layout,
ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::ShaderReadOnlyOptimal
| ImageLayout::General
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal,
) {
return Err(DescriptorSetUpdateError::ImageLayoutInvalid {
binding: write.binding(),
index: descriptor_range_start + index as u32,
});
}
// VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450
if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().mutable_comparison_samplers
@ -604,9 +803,14 @@ pub(crate) fn check_descriptor_write<'a>(
let immutable_samplers = &layout_binding.immutable_samplers
[descriptor_range_start as usize..descriptor_range_end as usize];
for (index, (image_view, sampler)) in
for (index, (image_view_info, sampler)) in
elements.iter().zip(immutable_samplers).enumerate()
{
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337
@ -642,6 +846,21 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
// VUID-VkWriteDescriptorSet-descriptorType-04150
if !matches!(
image_layout,
ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::ShaderReadOnlyOptimal
| ImageLayout::General
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal,
) {
return Err(DescriptorSetUpdateError::ImageLayoutInvalid {
binding: write.binding(),
index: descriptor_range_start + index as u32,
});
}
if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
binding: write.binding(),
@ -664,7 +883,12 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, image_view) in elements.iter().enumerate() {
for (index, image_view_info) in elements.iter().enumerate() {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337
@ -700,6 +924,21 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
// VUID-VkWriteDescriptorSet-descriptorType-04149
if !matches!(
image_layout,
ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::ShaderReadOnlyOptimal
| ImageLayout::General
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal,
) {
return Err(DescriptorSetUpdateError::ImageLayoutInvalid {
binding: write.binding(),
index: descriptor_range_start + index as u32,
});
}
// VUID-VkWriteDescriptorSet-descriptorType-01946
if image_view.sampler_ycbcr_conversion().is_some() {
return Err(
@ -723,7 +962,12 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, image_view) in elements.iter().enumerate() {
for (index, image_view_info) in elements.iter().enumerate() {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00339
@ -759,6 +1003,14 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
// VUID-VkWriteDescriptorSet-descriptorType-04152
if !matches!(image_layout, ImageLayout::General) {
return Err(DescriptorSetUpdateError::ImageLayoutInvalid {
binding: write.binding(),
index: descriptor_range_start + index as u32,
});
}
// VUID-VkWriteDescriptorSet-descriptorType-00336
if !image_view.component_mapping().is_identity() {
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
@ -849,7 +1101,9 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, (buffer, range)) in elements.iter().enumerate() {
for (index, buffer_info) in elements.iter().enumerate() {
let DescriptorBufferInfo { buffer, range } = buffer_info;
assert_eq!(device, buffer.device());
if !buffer
@ -888,7 +1142,9 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, (buffer, range)) in elements.iter().enumerate() {
for (index, buffer_info) in elements.iter().enumerate() {
let DescriptorBufferInfo { buffer, range } = buffer_info;
assert_eq!(device, buffer.device());
if !buffer
@ -927,7 +1183,12 @@ pub(crate) fn check_descriptor_write<'a>(
});
};
for (index, image_view) in elements.iter().enumerate() {
for (index, image_view_info) in elements.iter().enumerate() {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00338
@ -963,6 +1224,21 @@ pub(crate) fn check_descriptor_write<'a>(
});
}
// VUID-VkWriteDescriptorSet-descriptorType-04151
if !matches!(
image_layout,
ImageLayout::DepthStencilReadOnlyOptimal
| ImageLayout::ShaderReadOnlyOptimal
| ImageLayout::General
| ImageLayout::DepthReadOnlyStencilAttachmentOptimal
| ImageLayout::DepthAttachmentStencilReadOnlyOptimal,
) {
return Err(DescriptorSetUpdateError::ImageLayoutInvalid {
binding: write.binding(),
index: descriptor_range_start + index as u32,
});
}
// VUID-VkWriteDescriptorSet-descriptorType-00336
if !image_view.component_mapping().is_identity() {
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
@ -1014,19 +1290,36 @@ pub enum DescriptorSetUpdateError {
written_count: u32,
},
ImageLayoutInvalid {
binding: u32,
index: u32,
},
/// Tried to write an image view with a 2D type and a 3D underlying image.
ImageView2dFrom3d { binding: u32, index: u32 },
ImageView2dFrom3d {
binding: u32,
index: u32,
},
/// Tried to write an image view that has both the `depth` and `stencil` aspects.
ImageViewDepthAndStencil { binding: u32, index: u32 },
ImageViewDepthAndStencil {
binding: u32,
index: u32,
},
/// Tried to write an image view with an attached sampler YCbCr conversion to a binding that
/// does not support it.
ImageViewHasSamplerYcbcrConversion { binding: u32, index: u32 },
ImageViewHasSamplerYcbcrConversion {
binding: u32,
index: u32,
},
/// Tried to write an image view of an arrayed type to a descriptor type that does not support
/// it.
ImageViewIsArrayed { binding: u32, index: u32 },
ImageViewIsArrayed {
binding: u32,
index: u32,
},
/// Tried to write an image view that was not compatible with the sampler that was provided as
/// part of the update or immutably in the layout.
@ -1038,7 +1331,10 @@ pub enum DescriptorSetUpdateError {
/// Tried to write an image view to a descriptor type that requires it to be identity swizzled,
/// but it was not.
ImageViewNotIdentitySwizzled { binding: u32, index: u32 },
ImageViewNotIdentitySwizzled {
binding: u32,
index: u32,
},
/// Tried to write an element type that was not compatible with the descriptor type in the
/// layout.
@ -1049,7 +1345,9 @@ pub enum DescriptorSetUpdateError {
},
/// Tried to write to a nonexistent binding.
InvalidBinding { binding: u32 },
InvalidBinding {
binding: u32,
},
/// A resource was missing a usage flag that was required.
MissingUsage {
@ -1067,7 +1365,10 @@ pub enum DescriptorSetUpdateError {
},
/// Tried to write a sampler that has an attached sampler YCbCr conversion.
SamplerHasSamplerYcbcrConversion { binding: u32, index: u32 },
SamplerHasSamplerYcbcrConversion {
binding: u32,
index: u32,
},
}
impl Error for DescriptorSetUpdateError {
@ -1103,6 +1404,12 @@ impl Display for DescriptorSetUpdateError {
available",
written_count, binding, available_count,
),
Self::ImageLayoutInvalid { binding, index } => write!(
f,
"tried to write an image view to binding {} index {} with an image layout that is \
not valid for that descriptor type",
binding, index,
),
Self::ImageView2dFrom3d { binding, index } => write!(
f,
"tried to write an image view to binding {} index {} with a 2D type and a 3D \

View File

@ -10,8 +10,7 @@
use super::{
sys::{Image, ImageMemory, RawImage},
traits::ImageContent,
ImageAccess, ImageAspects, ImageDescriptorLayouts, ImageError, ImageLayout, ImageUsage,
SampleCount,
ImageAccess, ImageAspects, ImageError, ImageLayout, ImageUsage, SampleCount,
};
use crate::{
device::{Device, DeviceOwned},
@ -603,16 +602,6 @@ unsafe impl ImageAccess for AttachmentImage {
self.attachment_layout
}
#[inline]
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
Some(ImageDescriptorLayouts {
storage_image: ImageLayout::General,
combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
sampled_image: ImageLayout::ShaderReadOnlyOptimal,
input_attachment: ImageLayout::ShaderReadOnlyOptimal,
})
}
#[inline]
unsafe fn layout_initialized(&self) {
self.layout_initialized.store(true, Ordering::SeqCst);

View File

@ -10,8 +10,8 @@
use super::{
sys::{Image, RawImage},
traits::ImageContent,
ImageAccess, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageError,
ImageLayout, ImageSubresourceLayers, ImageUsage, MipmapsCount,
ImageAccess, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
ImageSubresourceLayers, ImageUsage, MipmapsCount,
};
use crate::{
buffer::{Buffer, BufferContents, BufferCreateInfo, BufferError, BufferUsage, Subbuffer},
@ -331,16 +331,6 @@ unsafe impl ImageAccess for ImmutableImage {
fn final_layout_requirement(&self) -> ImageLayout {
self.layout
}
#[inline]
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
Some(ImageDescriptorLayouts {
storage_image: ImageLayout::General,
combined_image_sampler: self.layout,
sampled_image: self.layout,
input_attachment: self.layout,
})
}
}
unsafe impl<P> ImageContent<P> for ImmutableImage {
@ -391,11 +381,6 @@ unsafe impl ImageAccess for ImmutableImageInitialization {
fn final_layout_requirement(&self) -> ImageLayout {
self.image.layout
}
#[inline]
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
None
}
}
impl PartialEq for ImmutableImageInitialization {

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except
// according to those terms.
use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum};
use crate::macros::vulkan_enum;
vulkan_enum! {
#[non_exhaustive]
@ -205,31 +205,3 @@ impl Default for ImageLayout {
ImageLayout::Undefined
}
}
/// The set of layouts to use for an image when used in descriptor of various kinds.
#[derive(Clone, Copy, Debug, PartialEq, Eq)]
pub struct ImageDescriptorLayouts {
/// The image layout to use in a descriptor as a storage image.
pub storage_image: ImageLayout,
/// The image layout to use in a descriptor as a combined image sampler.
pub combined_image_sampler: ImageLayout,
/// The image layout to use in a descriptor as a sampled image.
pub sampled_image: ImageLayout,
/// 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),
}
}
}

View File

@ -50,7 +50,7 @@ pub use self::{
aspect::{ImageAspect, ImageAspects},
attachment::AttachmentImage,
immutable::ImmutableImage,
layout::{ImageDescriptorLayouts, ImageLayout},
layout::ImageLayout,
storage::StorageImage,
swapchain::SwapchainImage,
sys::ImageError,

View File

@ -10,8 +10,8 @@
use super::{
sys::{Image, ImageMemory, RawImage},
traits::ImageContent,
ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions,
ImageError, ImageLayout, ImageUsage,
ImageAccess, ImageAspects, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
ImageUsage,
};
use crate::{
device::{Device, DeviceOwned, Queue},
@ -491,16 +491,6 @@ unsafe impl ImageAccess for StorageImage {
fn is_layout_initialized(&self) -> bool {
self.layout_initialized.load(Ordering::Relaxed)
}
#[inline]
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
Some(ImageDescriptorLayouts {
storage_image: ImageLayout::General,
combined_image_sampler: ImageLayout::General,
sampled_image: ImageLayout::General,
input_attachment: ImageLayout::General,
})
}
}
unsafe impl<P> ImageContent<P> for StorageImage {

View File

@ -10,7 +10,7 @@
use super::{
sys::{Image, ImageMemory},
traits::ImageContent,
ImageAccess, ImageDescriptorLayouts, ImageLayout,
ImageAccess, ImageLayout,
};
use crate::{
device::{Device, DeviceOwned},
@ -82,15 +82,6 @@ unsafe impl ImageAccess for SwapchainImage {
ImageLayout::PresentSrc
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
Some(ImageDescriptorLayouts {
storage_image: ImageLayout::General,
combined_image_sampler: ImageLayout::ShaderReadOnlyOptimal,
sampled_image: ImageLayout::ShaderReadOnlyOptimal,
input_attachment: ImageLayout::ShaderReadOnlyOptimal,
})
}
unsafe fn layout_initialized(&self) {
match self.inner.memory() {
&ImageMemory::Swapchain {

View File

@ -8,8 +8,8 @@
// according to those terms.
use super::{
sys::Image, ImageAspects, ImageDescriptorLayouts, ImageDimensions, ImageLayout,
ImageSubresourceLayers, ImageSubresourceRange, ImageUsage, SampleCount,
sys::Image, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers,
ImageSubresourceRange, ImageUsage, SampleCount,
};
use crate::{
device::{Device, DeviceOwned},
@ -149,12 +149,6 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
preinitialized,
})
}
/// Returns an [`ImageDescriptorLayouts`] structure specifying the image layout to use
/// in descriptors of various kinds.
///
/// This must return `Some` if the image is to be used to create an image view.
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts>;
}
impl Debug for dyn ImageAccess {
@ -216,10 +210,6 @@ where
fn final_layout_requirement(&self) -> ImageLayout {
self.image.final_layout_requirement()
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
self.image.descriptor_layouts()
}
}
impl<I> PartialEq for ImageAccessFromUndefinedLayout<I>
@ -264,10 +254,6 @@ where
(**self).final_layout_requirement()
}
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
(**self).descriptor_layouts()
}
unsafe fn layout_initialized(&self) {
(**self).layout_initialized();
}