mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2025-02-16 09:02:25 +00:00
Fix handling of runtime sized arrays in shaders (#1992)
* Fix handling of runtime sized arrays in shaders * Small fix
This commit is contained in:
parent
137fb9f24b
commit
9a50d6ca56
@ -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));
|
||||||
|
@ -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,
|
||||||
|
@ -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
|
||||||
|
@ -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(),
|
||||||
|
@ -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.
|
||||||
|
@ -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)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
Loading…
Reference in New Issue
Block a user