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

View File

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

View File

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

View File

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

View File

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

View File

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

View File

@ -11,7 +11,9 @@ use super::layout::{DescriptorSetLayout, DescriptorSetLayoutBinding, DescriptorT
use crate::{ use crate::{
buffer::{view::BufferView, BufferUsage, Subbuffer}, buffer::{view::BufferView, BufferUsage, Subbuffer},
device::DeviceOwned, device::DeviceOwned,
image::{view::ImageViewType, ImageAspects, ImageType, ImageUsage, ImageViewAbstract}, image::{
view::ImageViewType, ImageAspects, ImageLayout, ImageType, ImageUsage, ImageViewAbstract,
},
sampler::{Sampler, SamplerImageViewIncompatibleError}, sampler::{Sampler, SamplerImageViewIncompatibleError},
DeviceSize, RequiresOneOf, VulkanObject, DeviceSize, RequiresOneOf, VulkanObject,
}; };
@ -33,10 +35,11 @@ use std::{
/// non-arrayed bindings, where `descriptor_count` in the descriptor set layout is 1. /// 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. /// - 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. /// At least one element must be provided; a panic results if the provided iterator is empty.
#[derive(Clone, Debug)]
pub struct WriteDescriptorSet { pub struct WriteDescriptorSet {
binding: u32, binding: u32,
first_array_element: u32, first_array_element: u32,
elements: WriteDescriptorSetElements, pub(crate) elements: WriteDescriptorSetElements, // public so that the image layouts can be changed
} }
impl WriteDescriptorSet { impl WriteDescriptorSet {
@ -74,7 +77,14 @@ impl WriteDescriptorSet {
#[inline] #[inline]
pub fn buffer(binding: u32, buffer: Subbuffer<impl ?Sized>) -> Self { pub fn buffer(binding: u32, buffer: Subbuffer<impl ?Sized>) -> Self {
let range = 0..buffer.size(); 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. /// Write a number of consecutive buffer elements.
@ -91,28 +101,18 @@ impl WriteDescriptorSet {
first_array_element, first_array_element,
elements.into_iter().map(|buffer| { elements.into_iter().map(|buffer| {
let range = 0..buffer.size(); 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. /// 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] #[inline]
pub fn buffer_with_range( pub fn buffer_with_range(binding: u32, buffer_info: DescriptorBufferInfo) -> Self {
binding: u32, Self::buffer_with_range_array(binding, 0, [buffer_info])
buffer: Subbuffer<impl ?Sized>,
range: Range<DeviceSize>,
) -> Self {
Self::buffer_with_range_array(binding, 0, [(buffer, range)])
} }
/// Write a number of consecutive buffer elements, specifying the ranges of the buffers to be /// 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( pub fn buffer_with_range_array(
binding: u32, binding: u32,
first_array_element: u32, first_array_element: u32,
elements: impl IntoIterator<Item = (Subbuffer<impl ?Sized>, Range<DeviceSize>)>, elements: impl IntoIterator<Item = DescriptorBufferInfo>,
) -> Self { ) -> Self {
let elements: SmallVec<_> = elements let elements: SmallVec<_> = elements.into_iter().collect();
.into_iter()
.map(|(buffer, range)| (buffer.into_bytes(), range))
.collect();
assert!(!elements.is_empty()); assert!(!elements.is_empty());
Self { Self {
@ -151,6 +148,7 @@ impl WriteDescriptorSet {
) -> Self { ) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect(); let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty()); assert!(!elements.is_empty());
Self { Self {
binding, binding,
first_array_element, 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] #[inline]
pub fn image_view(binding: u32, image_view: Arc<dyn ImageViewAbstract>) -> Self { 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( pub fn image_view_array(
binding: u32, binding: u32,
first_array_element: u32, first_array_element: u32,
elements: impl IntoIterator<Item = Arc<dyn ImageViewAbstract>>, 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 { ) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect(); let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty()); 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] #[inline]
pub fn image_view_sampler( pub fn image_view_sampler(
binding: u32, binding: u32,
image_view: Arc<dyn ImageViewAbstract>, image_view: Arc<dyn ImageViewAbstract>,
sampler: Arc<Sampler>, sampler: Arc<Sampler>,
) -> Self { ) -> 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( pub fn image_view_sampler_array(
binding: u32, binding: u32,
first_array_element: u32, first_array_element: u32,
elements: impl IntoIterator<Item = (Arc<dyn ImageViewAbstract>, Arc<Sampler>)>, 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 { ) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect(); let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty()); assert!(!elements.is_empty());
Self { Self {
binding, binding,
first_array_element, first_array_element,
@ -218,6 +301,7 @@ impl WriteDescriptorSet {
) -> Self { ) -> Self {
let elements: SmallVec<_> = elements.into_iter().collect(); let elements: SmallVec<_> = elements.into_iter().collect();
assert!(!elements.is_empty()); assert!(!elements.is_empty());
Self { Self {
binding, binding,
first_array_element, first_array_element,
@ -268,7 +352,9 @@ impl WriteDescriptorSet {
DescriptorWriteInfo::Buffer( DescriptorWriteInfo::Buffer(
elements elements
.iter() .iter()
.map(|(buffer, range)| { .map(|buffer_info| {
let DescriptorBufferInfo { buffer, range } = buffer_info;
debug_assert!(!range.is_empty()); debug_assert!(!range.is_empty());
debug_assert!(range.end <= buffer.buffer().size()); debug_assert!(range.end <= buffer.buffer().size());
@ -305,14 +391,16 @@ impl WriteDescriptorSet {
DescriptorWriteInfo::Image( DescriptorWriteInfo::Image(
elements elements
.iter() .iter()
.map(|image_view| { .map(|image_view_info| {
let layouts = image_view.image().descriptor_layouts().expect( let &DescriptorImageViewInfo {
"descriptor_layouts must return Some when used in an image view", ref image_view,
); image_layout,
} = image_view_info;
ash::vk::DescriptorImageInfo { ash::vk::DescriptorImageInfo {
sampler: ash::vk::Sampler::null(), sampler: ash::vk::Sampler::null(),
image_view: image_view.handle(), image_view: image_view.handle(),
image_layout: layouts.layout_for(descriptor_type).into(), image_layout: image_layout.into(),
} }
}) })
.collect(), .collect(),
@ -326,14 +414,16 @@ impl WriteDescriptorSet {
DescriptorWriteInfo::Image( DescriptorWriteInfo::Image(
elements elements
.iter() .iter()
.map(|(image_view, sampler)| { .map(|(image_view_info, sampler)| {
let layouts = image_view.image().descriptor_layouts().expect( let &DescriptorImageViewInfo {
"descriptor_layouts must return Some when used in an image view", ref image_view,
); image_layout,
} = image_view_info;
ash::vk::DescriptorImageInfo { ash::vk::DescriptorImageInfo {
sampler: sampler.handle(), sampler: sampler.handle(),
image_view: image_view.handle(), image_view: image_view.handle(),
image_layout: layouts.layout_for(descriptor_type).into(), image_layout: image_layout.into(),
} }
}) })
.collect(), .collect(),
@ -375,12 +465,13 @@ impl WriteDescriptorSet {
} }
/// The elements held by a `WriteDescriptorSet`. /// The elements held by a `WriteDescriptorSet`.
#[derive(Clone, Debug)]
pub enum WriteDescriptorSetElements { pub enum WriteDescriptorSetElements {
None(u32), None(u32),
Buffer(SmallVec<[(Subbuffer<[u8]>, Range<DeviceSize>); 1]>), Buffer(SmallVec<[DescriptorBufferInfo; 1]>),
BufferView(SmallVec<[Arc<BufferView>; 1]>), BufferView(SmallVec<[Arc<BufferView>; 1]>),
ImageView(SmallVec<[Arc<dyn ImageViewAbstract>; 1]>), ImageView(SmallVec<[DescriptorImageViewInfo; 1]>),
ImageViewSampler(SmallVec<[(Arc<dyn ImageViewAbstract>, Arc<Sampler>); 1]>), ImageViewSampler(SmallVec<[(DescriptorImageViewInfo, Arc<Sampler>); 1]>),
Sampler(SmallVec<[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)] #[derive(Clone, Debug)]
pub(crate) enum DescriptorWriteInfo { pub(crate) enum DescriptorWriteInfo {
Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>), Image(SmallVec<[ash::vk::DescriptorImageInfo; 1]>),
@ -406,7 +540,52 @@ pub(crate) enum DescriptorWriteInfo {
BufferView(SmallVec<[ash::vk::BufferView; 1]>), 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, write: &WriteDescriptorSet,
layout: &'a DescriptorSetLayout, layout: &'a DescriptorSetLayout,
variable_descriptor_count: u32, 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, image_view.device());
assert_eq!(device, sampler.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 // VUID-VkDescriptorImageInfo-mutableComparisonSamplers-04450
if device.enabled_extensions().khr_portability_subset if device.enabled_extensions().khr_portability_subset
&& !device.enabled_features().mutable_comparison_samplers && !device.enabled_features().mutable_comparison_samplers
@ -604,9 +803,14 @@ pub(crate) fn check_descriptor_write<'a>(
let immutable_samplers = &layout_binding.immutable_samplers let immutable_samplers = &layout_binding.immutable_samplers
[descriptor_range_start as usize..descriptor_range_end as usize]; [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() elements.iter().zip(immutable_samplers).enumerate()
{ {
let &DescriptorImageViewInfo {
ref image_view,
image_layout,
} = image_view_info;
assert_eq!(device, image_view.device()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337 // 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()) { if let Err(error) = sampler.check_can_sample(image_view.as_ref()) {
return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler { return Err(DescriptorSetUpdateError::ImageViewIncompatibleSampler {
binding: write.binding(), 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()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00337 // 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 // VUID-VkWriteDescriptorSet-descriptorType-01946
if image_view.sampler_ycbcr_conversion().is_some() { if image_view.sampler_ycbcr_conversion().is_some() {
return Err( 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()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00339 // 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 // VUID-VkWriteDescriptorSet-descriptorType-00336
if !image_view.component_mapping().is_identity() { if !image_view.component_mapping().is_identity() {
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled { 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()); assert_eq!(device, buffer.device());
if !buffer 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()); assert_eq!(device, buffer.device());
if !buffer 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()); assert_eq!(device, image_view.device());
// VUID-VkWriteDescriptorSet-descriptorType-00338 // 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 // VUID-VkWriteDescriptorSet-descriptorType-00336
if !image_view.component_mapping().is_identity() { if !image_view.component_mapping().is_identity() {
return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled { return Err(DescriptorSetUpdateError::ImageViewNotIdentitySwizzled {
@ -1014,19 +1290,36 @@ pub enum DescriptorSetUpdateError {
written_count: u32, written_count: u32,
}, },
ImageLayoutInvalid {
binding: u32,
index: u32,
},
/// Tried to write an image view with a 2D type and a 3D underlying image. /// 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. /// 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 /// Tried to write an image view with an attached sampler YCbCr conversion to a binding that
/// does not support it. /// 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 /// Tried to write an image view of an arrayed type to a descriptor type that does not support
/// it. /// 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 /// 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. /// 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, /// Tried to write an image view to a descriptor type that requires it to be identity swizzled,
/// but it was not. /// 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 /// Tried to write an element type that was not compatible with the descriptor type in the
/// layout. /// layout.
@ -1049,7 +1345,9 @@ pub enum DescriptorSetUpdateError {
}, },
/// Tried to write to a nonexistent binding. /// Tried to write to a nonexistent binding.
InvalidBinding { binding: u32 }, InvalidBinding {
binding: u32,
},
/// A resource was missing a usage flag that was required. /// A resource was missing a usage flag that was required.
MissingUsage { MissingUsage {
@ -1067,7 +1365,10 @@ pub enum DescriptorSetUpdateError {
}, },
/// Tried to write a sampler that has an attached sampler YCbCr conversion. /// 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 { impl Error for DescriptorSetUpdateError {
@ -1103,6 +1404,12 @@ impl Display for DescriptorSetUpdateError {
available", available",
written_count, binding, available_count, 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!( Self::ImageView2dFrom3d { binding, index } => write!(
f, f,
"tried to write an image view to binding {} index {} with a 2D type and a 3D \ "tried to write an image view to binding {} index {} with a 2D type and a 3D \

View File

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

View File

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

View File

@ -7,7 +7,7 @@
// notice may not be copied, modified, or distributed except // notice may not be copied, modified, or distributed except
// according to those terms. // according to those terms.
use crate::{descriptor_set::layout::DescriptorType, macros::vulkan_enum}; use crate::macros::vulkan_enum;
vulkan_enum! { vulkan_enum! {
#[non_exhaustive] #[non_exhaustive]
@ -205,31 +205,3 @@ impl Default for ImageLayout {
ImageLayout::Undefined 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}, aspect::{ImageAspect, ImageAspects},
attachment::AttachmentImage, attachment::AttachmentImage,
immutable::ImmutableImage, immutable::ImmutableImage,
layout::{ImageDescriptorLayouts, ImageLayout}, layout::ImageLayout,
storage::StorageImage, storage::StorageImage,
swapchain::SwapchainImage, swapchain::SwapchainImage,
sys::ImageError, sys::ImageError,

View File

@ -10,8 +10,8 @@
use super::{ use super::{
sys::{Image, ImageMemory, RawImage}, sys::{Image, ImageMemory, RawImage},
traits::ImageContent, traits::ImageContent,
ImageAccess, ImageAspects, ImageCreateFlags, ImageDescriptorLayouts, ImageDimensions, ImageAccess, ImageAspects, ImageCreateFlags, ImageDimensions, ImageError, ImageLayout,
ImageError, ImageLayout, ImageUsage, ImageUsage,
}; };
use crate::{ use crate::{
device::{Device, DeviceOwned, Queue}, device::{Device, DeviceOwned, Queue},
@ -491,16 +491,6 @@ unsafe impl ImageAccess for StorageImage {
fn is_layout_initialized(&self) -> bool { fn is_layout_initialized(&self) -> bool {
self.layout_initialized.load(Ordering::Relaxed) 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 { unsafe impl<P> ImageContent<P> for StorageImage {

View File

@ -10,7 +10,7 @@
use super::{ use super::{
sys::{Image, ImageMemory}, sys::{Image, ImageMemory},
traits::ImageContent, traits::ImageContent,
ImageAccess, ImageDescriptorLayouts, ImageLayout, ImageAccess, ImageLayout,
}; };
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
@ -82,15 +82,6 @@ unsafe impl ImageAccess for SwapchainImage {
ImageLayout::PresentSrc 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) { unsafe fn layout_initialized(&self) {
match self.inner.memory() { match self.inner.memory() {
&ImageMemory::Swapchain { &ImageMemory::Swapchain {

View File

@ -8,8 +8,8 @@
// according to those terms. // according to those terms.
use super::{ use super::{
sys::Image, ImageAspects, ImageDescriptorLayouts, ImageDimensions, ImageLayout, sys::Image, ImageAspects, ImageDimensions, ImageLayout, ImageSubresourceLayers,
ImageSubresourceLayers, ImageSubresourceRange, ImageUsage, SampleCount, ImageSubresourceRange, ImageUsage, SampleCount,
}; };
use crate::{ use crate::{
device::{Device, DeviceOwned}, device::{Device, DeviceOwned},
@ -149,12 +149,6 @@ pub unsafe trait ImageAccess: DeviceOwned + Send + Sync {
preinitialized, 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 { impl Debug for dyn ImageAccess {
@ -216,10 +210,6 @@ where
fn final_layout_requirement(&self) -> ImageLayout { fn final_layout_requirement(&self) -> ImageLayout {
self.image.final_layout_requirement() self.image.final_layout_requirement()
} }
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
self.image.descriptor_layouts()
}
} }
impl<I> PartialEq for ImageAccessFromUndefinedLayout<I> impl<I> PartialEq for ImageAccessFromUndefinedLayout<I>
@ -264,10 +254,6 @@ where
(**self).final_layout_requirement() (**self).final_layout_requirement()
} }
fn descriptor_layouts(&self) -> Option<ImageDescriptorLayouts> {
(**self).descriptor_layouts()
}
unsafe fn layout_initialized(&self) { unsafe fn layout_initialized(&self) {
(**self).layout_initialized(); (**self).layout_initialized();
} }