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)); let ident = format_ident!("{}", format!("{:?}", ty));
quote! { ::vulkano::descriptor_set::layout::DescriptorType::#ident } 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 { let image_format = match image_format {
Some(image_format) => { Some(image_format) => {
let ident = format_ident!("{}", format!("{:?}", image_format)); let ident = format_ident!("{}", format!("{:?}", image_format));

View File

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

View File

@ -573,10 +573,25 @@ impl<L, P> AutoCommandBufferBuilder<L, P> {
elements: &[Option<T>], elements: &[Option<T>],
mut extra_check: impl FnMut(u32, &T) -> Result<(), DescriptorResourceInvalidError>, mut extra_check: impl FnMut(u32, &T) -> Result<(), DescriptorResourceInvalidError>,
) -> Result<(), PipelineExecutionError> { ) -> Result<(), PipelineExecutionError> {
for (index, element) in elements[0..reqs.descriptor_count as usize] let elements_to_check = if let Some(descriptor_count) = reqs.descriptor_count {
.iter() // The shader has a fixed-sized array, so it will never access more than
.enumerate() // 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; let index = index as u32;
// VUID-vkCmdDispatch-None-02699 // VUID-vkCmdDispatch-None-02699

View File

@ -722,8 +722,8 @@ impl DescriptorSetLayoutBinding {
&self, &self,
descriptor_requirements: &DescriptorRequirements, descriptor_requirements: &DescriptorRequirements,
) -> Result<(), DescriptorRequirementsNotMet> { ) -> Result<(), DescriptorRequirementsNotMet> {
let DescriptorRequirements { let &DescriptorRequirements {
descriptor_types, ref descriptor_types,
descriptor_count, descriptor_count,
image_format: _, image_format: _,
image_multisampled: _, image_multisampled: _,
@ -746,16 +746,18 @@ impl DescriptorSetLayoutBinding {
}); });
} }
if self.descriptor_count < *descriptor_count { if let Some(required) = descriptor_count {
return Err(DescriptorRequirementsNotMet::DescriptorCount { if self.descriptor_count < required {
required: *descriptor_count, return Err(DescriptorRequirementsNotMet::DescriptorCount {
obtained: self.descriptor_count, required,
}); obtained: self.descriptor_count,
});
}
} }
if !self.stages.contains(stages) { if !self.stages.contains(&stages) {
return Err(DescriptorRequirementsNotMet::ShaderStages { return Err(DescriptorRequirementsNotMet::ShaderStages {
required: *stages, required: stages,
obtained: self.stages, obtained: self.stages,
}); });
} }
@ -768,7 +770,7 @@ impl From<&DescriptorRequirements> for DescriptorSetLayoutBinding {
fn from(reqs: &DescriptorRequirements) -> Self { fn from(reqs: &DescriptorRequirements) -> Self {
Self { Self {
descriptor_type: reqs.descriptor_types[0], descriptor_type: reqs.descriptor_types[0],
descriptor_count: reqs.descriptor_count, descriptor_count: reqs.descriptor_count.unwrap_or(0),
variable_descriptor_count: false, variable_descriptor_count: false,
stages: reqs.stages, stages: reqs.stages,
immutable_samplers: Vec::new(), 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 /// The number of descriptors (array elements) that the shader requires. The descriptor set
/// layout can declare more than this, but never less. /// 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 /// The image format that is required for image views bound to this descriptor. If this is
/// `None`, then any image format is allowed. /// `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 variable_id_info = spirv.id(variable_id);
let mut reqs = DescriptorRequirements { let mut reqs = DescriptorRequirements {
descriptor_count: 1, descriptor_count: Some(1),
..Default::default() ..Default::default()
}; };
@ -878,12 +878,15 @@ fn descriptor_requirements_of(spirv: &Spirv, variable_id: Id) -> DescriptorVaria
_ => panic!("failed to find array length"), _ => 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) Some(element_type)
} }
&Instruction::TypeRuntimeArray { element_type, .. } => { &Instruction::TypeRuntimeArray { element_type, .. } => {
reqs.descriptor_count = 0; reqs.descriptor_count = None;
Some(element_type) Some(element_type)
} }