mirror of
https://github.com/vulkano-rs/vulkano.git
synced 2024-11-25 08:14:20 +00:00
Check pipeline layout limits (#757)
* Check pipeline layout limits * Fix copyright year * Fix unimplemented!() for PipelineLayoutLimitsError * Fix style * Fix minor mistake
This commit is contained in:
parent
06a0b3715f
commit
94c376c268
440
vulkano/src/descriptor/pipeline_layout/limits_check.rs
Normal file
440
vulkano/src/descriptor/pipeline_layout/limits_check.rs
Normal file
@ -0,0 +1,440 @@
|
||||
// Copyright (c) 2017 The vulkano developers
|
||||
// Licensed under the Apache License, Version 2.0
|
||||
// <LICENSE-APACHE or
|
||||
// http://www.apache.org/licenses/LICENSE-2.0> or the MIT
|
||||
// license <LICENSE-MIT or http://opensource.org/licenses/MIT>,
|
||||
// at your option. All files in the project carrying such
|
||||
// notice may not be copied, modified, or distributed except
|
||||
// according to those terms.
|
||||
|
||||
//! Contains the `check_desc_against_limits` function and the `PipelineLayoutLimitsError` error.
|
||||
|
||||
use std::error;
|
||||
use std::fmt;
|
||||
|
||||
use device::Device;
|
||||
use descriptor::descriptor::DescriptorType;
|
||||
use descriptor::descriptor::ShaderStages;
|
||||
use descriptor::pipeline_layout::PipelineLayoutDesc;
|
||||
use descriptor::pipeline_layout::PipelineLayoutDescPcRange;
|
||||
|
||||
/// Checks whether the pipeline layout description fulfills the device limits requirements.
|
||||
pub fn check_desc_against_limits<D>(device: &Device, desc: &D)
|
||||
-> Result<(), PipelineLayoutLimitsError>
|
||||
where D: ?Sized + PipelineLayoutDesc
|
||||
{
|
||||
let mut num_resources = Counter::default();
|
||||
let mut num_samplers = Counter::default();
|
||||
let mut num_uniform_buffers = Counter::default();
|
||||
let mut num_uniform_buffers_dynamic = 0;
|
||||
let mut num_storage_buffers = Counter::default();
|
||||
let mut num_storage_buffers_dynamic = 0;
|
||||
let mut num_sampled_images = Counter::default();
|
||||
let mut num_storage_images = Counter::default();
|
||||
let mut num_input_attachments = Counter::default();
|
||||
|
||||
for set in 0 .. desc.num_sets() {
|
||||
for binding in 0 .. desc.num_bindings_in_set(set).unwrap() {
|
||||
let descriptor = desc.descriptor(set, binding).unwrap();
|
||||
num_resources.increment(descriptor.array_count, &descriptor.stages);
|
||||
|
||||
match descriptor.ty.ty().expect("Not implemented yet") { // TODO:
|
||||
DescriptorType::Sampler => {
|
||||
num_samplers.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::CombinedImageSampler => {
|
||||
num_samplers.increment(descriptor.array_count, &descriptor.stages);
|
||||
num_sampled_images.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::SampledImage | DescriptorType::UniformTexelBuffer => {
|
||||
num_sampled_images.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::StorageImage | DescriptorType::StorageTexelBuffer => {
|
||||
num_storage_images.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::UniformBuffer => {
|
||||
num_uniform_buffers.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::UniformBufferDynamic => {
|
||||
num_uniform_buffers.increment(descriptor.array_count, &descriptor.stages);
|
||||
num_uniform_buffers_dynamic += 1;
|
||||
},
|
||||
DescriptorType::StorageBuffer => {
|
||||
num_storage_buffers.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
DescriptorType::StorageBufferDynamic => {
|
||||
num_storage_buffers.increment(descriptor.array_count, &descriptor.stages);
|
||||
num_storage_buffers_dynamic += 1;
|
||||
},
|
||||
DescriptorType::InputAttachment => {
|
||||
num_input_attachments.increment(descriptor.array_count, &descriptor.stages);
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
let limits = device.physical_device().limits();
|
||||
|
||||
if desc.num_sets() > limits.max_bound_descriptor_sets() as usize {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetsLimitExceeded {
|
||||
limit: limits.max_bound_descriptor_sets() as usize,
|
||||
requested: desc.num_sets(),
|
||||
});
|
||||
}
|
||||
|
||||
if num_resources.max_per_stage() > limits.max_per_stage_resources() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageResourcesLimitExceeded {
|
||||
limit: limits.max_per_stage_resources(),
|
||||
requested: num_resources.max_per_stage(),
|
||||
});
|
||||
}
|
||||
|
||||
if num_samplers.max_per_stage() > limits.max_per_stage_descriptor_samplers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorSamplersLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_samplers(),
|
||||
requested: num_samplers.max_per_stage(),
|
||||
});
|
||||
}
|
||||
if num_uniform_buffers.max_per_stage() > limits.max_per_stage_descriptor_uniform_buffers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorUniformBuffersLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_uniform_buffers(),
|
||||
requested: num_uniform_buffers.max_per_stage(),
|
||||
});
|
||||
}
|
||||
if num_storage_buffers.max_per_stage() > limits.max_per_stage_descriptor_storage_buffers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorStorageBuffersLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_storage_buffers(),
|
||||
requested: num_storage_buffers.max_per_stage(),
|
||||
});
|
||||
}
|
||||
if num_sampled_images.max_per_stage() > limits.max_per_stage_descriptor_sampled_images() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorSampledImagesLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_sampled_images(),
|
||||
requested: num_sampled_images.max_per_stage(),
|
||||
});
|
||||
}
|
||||
if num_storage_images.max_per_stage() > limits.max_per_stage_descriptor_storage_images() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorStorageImagesLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_storage_images(),
|
||||
requested: num_storage_images.max_per_stage(),
|
||||
});
|
||||
}
|
||||
if num_input_attachments.max_per_stage() > limits.max_per_stage_descriptor_input_attachments() {
|
||||
return Err(PipelineLayoutLimitsError::MaxPerStageDescriptorInputAttachmentsLimitExceeded {
|
||||
limit: limits.max_per_stage_descriptor_input_attachments(),
|
||||
requested: num_input_attachments.max_per_stage(),
|
||||
});
|
||||
}
|
||||
|
||||
if num_samplers.total > limits.max_descriptor_set_samplers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetSamplersLimitExceeded {
|
||||
limit: limits.max_descriptor_set_samplers(),
|
||||
requested: num_samplers.total,
|
||||
});
|
||||
}
|
||||
if num_uniform_buffers.total > limits.max_descriptor_set_uniform_buffers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersLimitExceeded {
|
||||
limit: limits.max_descriptor_set_uniform_buffers(),
|
||||
requested: num_uniform_buffers.total,
|
||||
});
|
||||
}
|
||||
if num_uniform_buffers_dynamic > limits.max_descriptor_set_uniform_buffers_dynamic() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersDynamicLimitExceeded {
|
||||
limit: limits.max_descriptor_set_uniform_buffers_dynamic(),
|
||||
requested: num_uniform_buffers_dynamic,
|
||||
});
|
||||
}
|
||||
if num_storage_buffers.total > limits.max_descriptor_set_storage_buffers() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersLimitExceeded {
|
||||
limit: limits.max_descriptor_set_storage_buffers(),
|
||||
requested: num_storage_buffers.total,
|
||||
});
|
||||
}
|
||||
if num_storage_buffers_dynamic > limits.max_descriptor_set_storage_buffers_dynamic() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersDynamicLimitExceeded {
|
||||
limit: limits.max_descriptor_set_storage_buffers_dynamic(),
|
||||
requested: num_storage_buffers_dynamic,
|
||||
});
|
||||
}
|
||||
if num_sampled_images.total > limits.max_descriptor_set_sampled_images() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetSampledImagesLimitExceeded {
|
||||
limit: limits.max_descriptor_set_sampled_images(),
|
||||
requested: num_sampled_images.total,
|
||||
});
|
||||
}
|
||||
if num_storage_images.total > limits.max_descriptor_set_storage_images() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetStorageImagesLimitExceeded {
|
||||
limit: limits.max_descriptor_set_storage_images(),
|
||||
requested: num_storage_images.total,
|
||||
});
|
||||
}
|
||||
if num_input_attachments.total > limits.max_descriptor_set_input_attachments() {
|
||||
return Err(PipelineLayoutLimitsError::MaxDescriptorSetInputAttachmentsLimitExceeded {
|
||||
limit: limits.max_descriptor_set_input_attachments(),
|
||||
requested: num_input_attachments.total,
|
||||
});
|
||||
}
|
||||
|
||||
for pc_id in 0 .. desc.num_push_constants_ranges() {
|
||||
let PipelineLayoutDescPcRange {
|
||||
offset,
|
||||
size,
|
||||
stages,
|
||||
} = {
|
||||
match desc.push_constants_range(pc_id) {
|
||||
Some(o) => o,
|
||||
None => continue,
|
||||
}
|
||||
};
|
||||
|
||||
if offset + size > limits.max_push_constants_size() as usize {
|
||||
return Err(PipelineLayoutLimitsError::MaxPushConstantsSizeExceeded {
|
||||
limit: limits.max_push_constants_size() as usize,
|
||||
requested: offset + size,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// The pipeline layout description isn't compatible with the hardware limits.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum PipelineLayoutLimitsError {
|
||||
/// The maximum number of descriptor sets has been exceeded.
|
||||
MaxDescriptorSetsLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: usize,
|
||||
/// What was requested.
|
||||
requested: usize,
|
||||
},
|
||||
|
||||
/// The maximum size of push constants has been exceeded.
|
||||
MaxPushConstantsSizeExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: usize,
|
||||
/// What was requested.
|
||||
requested: usize,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_resources()` limit has been exceeded.
|
||||
MaxPerStageResourcesLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_samplers()` limit has been exceeded.
|
||||
MaxPerStageDescriptorSamplersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_uniform_buffers()` limit has been exceeded.
|
||||
MaxPerStageDescriptorUniformBuffersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_storage_buffers()` limit has been exceeded.
|
||||
MaxPerStageDescriptorStorageBuffersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_sampled_images()` limit has been exceeded.
|
||||
MaxPerStageDescriptorSampledImagesLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_storage_images()` limit has been exceeded.
|
||||
MaxPerStageDescriptorStorageImagesLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_per_stage_descriptor_input_attachments()` limit has been exceeded.
|
||||
MaxPerStageDescriptorInputAttachmentsLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_samplers()` limit has been exceeded.
|
||||
MaxDescriptorSetSamplersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_uniform_buffers()` limit has been exceeded.
|
||||
MaxDescriptorSetUniformBuffersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_uniform_buffers_dynamic()` limit has been exceeded.
|
||||
MaxDescriptorSetUniformBuffersDynamicLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_storage_buffers()` limit has been exceeded.
|
||||
MaxDescriptorSetStorageBuffersLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_storage_buffers_dynamic()` limit has been exceeded.
|
||||
MaxDescriptorSetStorageBuffersDynamicLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_sampled_images()` limit has been exceeded.
|
||||
MaxDescriptorSetSampledImagesLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_storage_images()` limit has been exceeded.
|
||||
MaxDescriptorSetStorageImagesLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
|
||||
/// The `max_descriptor_set_input_attachments()` limit has been exceeded.
|
||||
MaxDescriptorSetInputAttachmentsLimitExceeded {
|
||||
/// The limit that must be fulfilled.
|
||||
limit: u32,
|
||||
/// What was requested.
|
||||
requested: u32,
|
||||
},
|
||||
}
|
||||
|
||||
impl error::Error for PipelineLayoutLimitsError {
|
||||
#[inline]
|
||||
fn description(&self) -> &str {
|
||||
match *self {
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetsLimitExceeded { .. } => {
|
||||
"the maximum number of descriptor sets has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPushConstantsSizeExceeded { .. } => {
|
||||
"the maximum size of push constants has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageResourcesLimitExceeded { .. } => {
|
||||
"the `max_per_stage_resources()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorSamplersLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_samplers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorUniformBuffersLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_uniform_buffers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorStorageBuffersLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_storage_buffers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorSampledImagesLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_sampled_images()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorStorageImagesLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_storage_images()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxPerStageDescriptorInputAttachmentsLimitExceeded { .. } => {
|
||||
"the `max_per_stage_descriptor_input_attachments()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetSamplersLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_samplers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_uniform_buffers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersDynamicLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_uniform_buffers_dynamic()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_storage_buffers()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersDynamicLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_storage_buffers_dynamic()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetSampledImagesLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_sampled_images()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetStorageImagesLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_storage_images()` limit has been exceeded"
|
||||
},
|
||||
PipelineLayoutLimitsError::MaxDescriptorSetInputAttachmentsLimitExceeded { .. } => {
|
||||
"the `max_descriptor_set_input_attachments()` limit has been exceeded"
|
||||
},
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
impl fmt::Display for PipelineLayoutLimitsError {
|
||||
#[inline]
|
||||
fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
|
||||
write!(fmt, "{}", error::Error::description(self))
|
||||
}
|
||||
}
|
||||
|
||||
// Helper struct for the main function.
|
||||
#[derive(Default)]
|
||||
struct Counter {
|
||||
total: u32,
|
||||
compute: u32,
|
||||
vertex: u32,
|
||||
geometry: u32,
|
||||
tess_ctl: u32,
|
||||
tess_eval: u32,
|
||||
frag: u32,
|
||||
}
|
||||
|
||||
impl Counter {
|
||||
fn increment(&mut self, num: u32, stages: &ShaderStages) {
|
||||
self.total += num;
|
||||
if stages.compute { self.compute += num; }
|
||||
if stages.vertex { self.vertex += num; }
|
||||
if stages.tessellation_control { self.tess_ctl += num; }
|
||||
if stages.tessellation_evaluation { self.tess_eval += num; }
|
||||
if stages.geometry { self.geometry += num; }
|
||||
if stages.fragment { self.frag += num; }
|
||||
}
|
||||
|
||||
fn max_per_stage(&self) -> u32 {
|
||||
let mut max = 0;
|
||||
if self.compute > max { max = self.compute; }
|
||||
if self.vertex > max { max = self.vertex; }
|
||||
if self.geometry > max { max = self.geometry; }
|
||||
if self.tess_ctl > max { max = self.tess_ctl; }
|
||||
if self.tess_eval > max { max = self.tess_eval; }
|
||||
if self.frag > max { max = self.frag; }
|
||||
max
|
||||
}
|
||||
}
|
@ -50,6 +50,7 @@
|
||||
//! TODO: write this section
|
||||
|
||||
pub use self::empty::EmptyPipelineDesc;
|
||||
pub use self::limits_check::PipelineLayoutLimitsError;
|
||||
pub use self::sys::PipelineLayout;
|
||||
pub use self::sys::PipelineLayoutCreationError;
|
||||
pub use self::sys::PipelineLayoutSys;
|
||||
@ -63,6 +64,7 @@ pub use self::traits::PipelineLayoutSuperset;
|
||||
pub use self::union::PipelineLayoutDescUnion;
|
||||
|
||||
mod empty;
|
||||
mod limits_check;
|
||||
mod sys;
|
||||
mod traits;
|
||||
mod union;
|
||||
|
@ -26,6 +26,7 @@ use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||
use descriptor::pipeline_layout::PipelineLayoutAbstract;
|
||||
use descriptor::pipeline_layout::PipelineLayoutDesc;
|
||||
use descriptor::pipeline_layout::PipelineLayoutDescPcRange;
|
||||
use descriptor::pipeline_layout::PipelineLayoutLimitsError;
|
||||
use device::Device;
|
||||
use device::DeviceOwned;
|
||||
|
||||
@ -51,7 +52,8 @@ impl<L> PipelineLayout<L>
|
||||
pub fn new(device: Arc<Device>, desc: L)
|
||||
-> Result<PipelineLayout<L>, PipelineLayoutCreationError> {
|
||||
let vk = device.pointers();
|
||||
let limits = device.physical_device().limits();
|
||||
|
||||
desc.check_against_limits(&device)?;
|
||||
|
||||
// Building the list of `UnsafeDescriptorSetLayout` objects.
|
||||
let layouts = {
|
||||
@ -81,12 +83,6 @@ impl<L> PipelineLayout<L>
|
||||
.map(|l| l.internal_object())
|
||||
.collect::<SmallVec<[_; 16]>>();
|
||||
|
||||
// FIXME: must also check per-descriptor-type limits (eg. max uniform buffer descriptors)
|
||||
|
||||
if layouts_ids.len() > limits.max_bound_descriptor_sets() as usize {
|
||||
return Err(PipelineLayoutCreationError::MaxDescriptorSetsLimitExceeded);
|
||||
}
|
||||
|
||||
// Builds a list of `vkPushConstantRange` that describe the push constants.
|
||||
let push_constants = {
|
||||
let mut out: SmallVec<[_; 8]> = SmallVec::new();
|
||||
@ -107,10 +103,6 @@ impl<L> PipelineLayout<L>
|
||||
return Err(PipelineLayoutCreationError::InvalidPushConstant);
|
||||
}
|
||||
|
||||
if offset + size > limits.max_push_constants_size() as usize {
|
||||
return Err(PipelineLayoutCreationError::MaxPushConstantsSizeExceeded);
|
||||
}
|
||||
|
||||
out.push(vk::PushConstantRange {
|
||||
stageFlags: stages.into_vulkan_bits(),
|
||||
offset: offset as u32,
|
||||
@ -267,15 +259,13 @@ unsafe impl<'a> VulkanObject for PipelineLayoutSys<'a> {
|
||||
}
|
||||
}
|
||||
|
||||
/// Error that can happen when creating an instance.
|
||||
/// Error that can happen when creating a pipeline layout.
|
||||
#[derive(Clone, Debug, PartialEq, Eq)]
|
||||
pub enum PipelineLayoutCreationError {
|
||||
/// Not enough memory.
|
||||
OomError(OomError),
|
||||
/// The maximum number of descriptor sets has been exceeded.
|
||||
MaxDescriptorSetsLimitExceeded,
|
||||
/// The maximum size of push constants has been exceeded.
|
||||
MaxPushConstantsSizeExceeded,
|
||||
/// The pipeline layout description doesn't fulfill the limit requirements.
|
||||
LimitsError(PipelineLayoutLimitsError),
|
||||
/// One of the push constants range didn't obey the rules. The list of stages must not be
|
||||
/// empty, the size must not be 0, and the size must be a multiple or 4.
|
||||
InvalidPushConstant,
|
||||
@ -288,11 +278,8 @@ impl error::Error for PipelineLayoutCreationError {
|
||||
PipelineLayoutCreationError::OomError(_) => {
|
||||
"not enough memory available"
|
||||
},
|
||||
PipelineLayoutCreationError::MaxDescriptorSetsLimitExceeded => {
|
||||
"the maximum number of descriptor sets has been exceeded"
|
||||
},
|
||||
PipelineLayoutCreationError::MaxPushConstantsSizeExceeded => {
|
||||
"the maximum size of push constants has been exceeded"
|
||||
PipelineLayoutCreationError::LimitsError(_) => {
|
||||
"the pipeline layout description doesn't fulfill the limit requirements"
|
||||
},
|
||||
PipelineLayoutCreationError::InvalidPushConstant => {
|
||||
"one of the push constants range didn't obey the rules"
|
||||
@ -304,6 +291,7 @@ impl error::Error for PipelineLayoutCreationError {
|
||||
fn cause(&self) -> Option<&error::Error> {
|
||||
match *self {
|
||||
PipelineLayoutCreationError::OomError(ref err) => Some(err),
|
||||
PipelineLayoutCreationError::LimitsError(ref err) => Some(err),
|
||||
_ => None,
|
||||
}
|
||||
}
|
||||
@ -323,6 +311,13 @@ impl From<OomError> for PipelineLayoutCreationError {
|
||||
}
|
||||
}
|
||||
|
||||
impl From<PipelineLayoutLimitsError> for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: PipelineLayoutLimitsError) -> PipelineLayoutCreationError {
|
||||
PipelineLayoutCreationError::LimitsError(err)
|
||||
}
|
||||
}
|
||||
|
||||
impl From<Error> for PipelineLayoutCreationError {
|
||||
#[inline]
|
||||
fn from(err: Error) -> PipelineLayoutCreationError {
|
||||
|
@ -17,6 +17,7 @@ use descriptor::descriptor::DescriptorDesc;
|
||||
use descriptor::descriptor::ShaderStages;
|
||||
use descriptor::descriptor_set::DescriptorSetsCollection;
|
||||
use descriptor::descriptor_set::UnsafeDescriptorSetLayout;
|
||||
use descriptor::pipeline_layout::limits_check;
|
||||
use descriptor::pipeline_layout::PipelineLayout;
|
||||
use descriptor::pipeline_layout::PipelineLayoutCreationError;
|
||||
use descriptor::pipeline_layout::PipelineLayoutDescUnion;
|
||||
@ -99,6 +100,14 @@ pub unsafe trait PipelineLayoutDesc {
|
||||
PipelineLayoutDescUnion::new(self, other)
|
||||
}
|
||||
|
||||
/// Checks whether this description fulfills the device limits requirements.
|
||||
#[inline]
|
||||
fn check_against_limits(&self, device: &Device)
|
||||
-> Result<(), limits_check::PipelineLayoutLimitsError>
|
||||
{
|
||||
limits_check::check_desc_against_limits(device, self)
|
||||
}
|
||||
|
||||
/// Turns the layout description into a `PipelineLayout` object that can be used by Vulkan.
|
||||
///
|
||||
/// > **Note**: This is just a shortcut for `PipelineLayout::new`.
|
||||
|
Loading…
Reference in New Issue
Block a user