Fix handling of runtime sized arrays in shaders (#1992)

* Fix handling of runtime sized arrays in shaders

* Small fix
This commit is contained in:
Rua 2022-09-22 09:11:30 +02:00 committed by GitHub
parent 137fb9f24b
commit 9a50d6ca56
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 46 additions and 19 deletions

View File

@ -110,6 +110,10 @@ fn write_descriptor_requirements(
let ident = format_ident!("{}", format!("{:?}", ty));
quote! { ::vulkano::descriptor_set::layout::DescriptorType::#ident }
});
let descriptor_count = match descriptor_count {
Some(descriptor_count) => quote! { Some(#descriptor_count) },
None => quote! { None },
};
let image_format = match image_format {
Some(image_format) => {
let ident = format_ident!("{}", format!("{:?}", image_format));

View File

@ -196,7 +196,7 @@ where
#[inline]
pub fn new(device: Arc<Device>, usage: BufferUsage) -> CpuBufferPool<T> {
assert!(size_of::<T>() > 0);
let pool = device.standard_memory_pool().clone();
let pool = device.standard_memory_pool();
CpuBufferPool {
device,

View File

@ -573,10 +573,25 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
elements: &[Option<T>],
mut extra_check: impl FnMut(u32, &T) -> Result<(), DescriptorResourceInvalidError>,
) -> Result<(), PipelineExecutionError> {
for (index, element) in elements[0..reqs.descriptor_count as usize]
.iter()
.enumerate()
{
let elements_to_check = if let Some(descriptor_count) = reqs.descriptor_count {
// The shader has a fixed-sized array, so it will never access more than
// the first `descriptor_count` elements.
elements.get(..descriptor_count as usize).ok_or({
// There are less than `descriptor_count` elements in `elements`
PipelineExecutionError::DescriptorResourceInvalid {
set_num,
binding_num,
index: elements.len() as u32,
error: DescriptorResourceInvalidError::Missing,
}
})?
} else {
// The shader has a runtime-sized array, so any element could potentially
// be accessed. We must check them all.
elements
};
for (index, element) in elements_to_check.iter().enumerate() {
let index = index as u32;
// VUID-vkCmdDispatch-None-02699

View File

@ -722,8 +722,8 @@ impl DescriptorSetLayoutBinding {
&self,
descriptor_requirements: &DescriptorRequirements,
) -> Result<(), DescriptorRequirementsNotMet> {
let DescriptorRequirements {
descriptor_types,
let &DescriptorRequirements {
ref descriptor_types,
descriptor_count,
image_format: _,
image_multisampled: _,
@ -746,16 +746,18 @@ impl DescriptorSetLayoutBinding {
});
}
if self.descriptor_count < *descriptor_count {
if let Some(required) = descriptor_count {
if self.descriptor_count < required {
return Err(DescriptorRequirementsNotMet::DescriptorCount {
required: *descriptor_count,
required,
obtained: self.descriptor_count,
});
}
}
if !self.stages.contains(stages) {
if !self.stages.contains(&stages) {
return Err(DescriptorRequirementsNotMet::ShaderStages {
required: *stages,
required: stages,
obtained: self.stages,
});
}
@ -768,7 +770,7 @@ impl From<&DescriptorRequirements> for DescriptorSetLayoutBinding {
fn from(reqs: &DescriptorRequirements) -> Self {
Self {
descriptor_type: reqs.descriptor_types[0],
descriptor_count: reqs.descriptor_count,
descriptor_count: reqs.descriptor_count.unwrap_or(0),
variable_descriptor_count: false,
stages: reqs.stages,
immutable_samplers: Vec::new(),

View File

@ -542,7 +542,10 @@ pub struct DescriptorRequirements {
/// The number of descriptors (array elements) that the shader requires. The descriptor set
/// layout can declare more than this, but never less.
pub descriptor_count: u32,
///
/// `None` means that the shader declares this as a runtime-sized array, and could potentially
/// access every array element provided in the descriptor set.
pub descriptor_count: Option<u32>,
/// The image format that is required for image views bound to this descriptor. If this is
/// `None`, then any image format is allowed.

View File

@ -711,7 +711,7 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
let variable_id_info = spirv.id(variable_id);
let mut reqs = DescriptorRequirements {
descriptor_count: 1,
descriptor_count: Some(1),
..Default::default()
};
@ -878,12 +878,15 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
_ => panic!("failed to find array length"),
};
reqs.descriptor_count *= len as u32;
if let Some(count) = reqs.descriptor_count.as_mut() {
*count *= len as u32
}
Some(element_type)
}
&Instruction::TypeRuntimeArray { element_type, .. } => {
reqs.descriptor_count = 0;
reqs.descriptor_count = None;
Some(element_type)
}