• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2017 The vulkano developers
2 // Licensed under the Apache License, Version 2.0
3 // <LICENSE-APACHE or
4 // https://www.apache.org/licenses/LICENSE-2.0> or the MIT
5 // license <LICENSE-MIT or https://opensource.org/licenses/MIT>,
6 // at your option. All files in the project carrying such
7 // notice may not be copied, modified, or distributed except
8 // according to those terms.
9 
10 //! Contains the `check_desc_against_limits` function and the `PipelineLayoutLimitsError` error.
11 
12 use crate::descriptor_set::layout::DescriptorSetLayout;
13 use crate::descriptor_set::layout::DescriptorType;
14 use crate::device::Properties;
15 use crate::pipeline::layout::PipelineLayoutPcRange;
16 use crate::pipeline::shader::ShaderStages;
17 use std::error;
18 use std::fmt;
19 use std::sync::Arc;
20 
21 /// Checks whether the pipeline layout description fulfills the device limits requirements.
check_desc_against_limits( properties: &Properties, descriptor_set_layouts: &[Arc<DescriptorSetLayout>], push_constants_ranges: &[PipelineLayoutPcRange], ) -> Result<(), PipelineLayoutLimitsError>22 pub fn check_desc_against_limits(
23     properties: &Properties,
24     descriptor_set_layouts: &[Arc<DescriptorSetLayout>],
25     push_constants_ranges: &[PipelineLayoutPcRange],
26 ) -> Result<(), PipelineLayoutLimitsError> {
27     let mut num_resources = Counter::default();
28     let mut num_samplers = Counter::default();
29     let mut num_uniform_buffers = Counter::default();
30     let mut num_uniform_buffers_dynamic = 0;
31     let mut num_storage_buffers = Counter::default();
32     let mut num_storage_buffers_dynamic = 0;
33     let mut num_sampled_images = Counter::default();
34     let mut num_storage_images = Counter::default();
35     let mut num_input_attachments = Counter::default();
36 
37     for set in descriptor_set_layouts {
38         for descriptor in (0..set.num_bindings()).filter_map(|i| set.descriptor(i).map(|d| d)) {
39             num_resources.increment(descriptor.array_count, &descriptor.stages);
40 
41             match descriptor.ty.ty() {
42                 // TODO:
43                 DescriptorType::Sampler => {
44                     num_samplers.increment(descriptor.array_count, &descriptor.stages);
45                 }
46                 DescriptorType::CombinedImageSampler => {
47                     num_samplers.increment(descriptor.array_count, &descriptor.stages);
48                     num_sampled_images.increment(descriptor.array_count, &descriptor.stages);
49                 }
50                 DescriptorType::SampledImage | DescriptorType::UniformTexelBuffer => {
51                     num_sampled_images.increment(descriptor.array_count, &descriptor.stages);
52                 }
53                 DescriptorType::StorageImage | DescriptorType::StorageTexelBuffer => {
54                     num_storage_images.increment(descriptor.array_count, &descriptor.stages);
55                 }
56                 DescriptorType::UniformBuffer => {
57                     num_uniform_buffers.increment(descriptor.array_count, &descriptor.stages);
58                 }
59                 DescriptorType::UniformBufferDynamic => {
60                     num_uniform_buffers.increment(descriptor.array_count, &descriptor.stages);
61                     num_uniform_buffers_dynamic += 1;
62                 }
63                 DescriptorType::StorageBuffer => {
64                     num_storage_buffers.increment(descriptor.array_count, &descriptor.stages);
65                 }
66                 DescriptorType::StorageBufferDynamic => {
67                     num_storage_buffers.increment(descriptor.array_count, &descriptor.stages);
68                     num_storage_buffers_dynamic += 1;
69                 }
70                 DescriptorType::InputAttachment => {
71                     num_input_attachments.increment(descriptor.array_count, &descriptor.stages);
72                 }
73             }
74         }
75     }
76 
77     if descriptor_set_layouts.len() > properties.max_bound_descriptor_sets as usize {
78         return Err(PipelineLayoutLimitsError::MaxDescriptorSetsLimitExceeded {
79             limit: properties.max_bound_descriptor_sets as usize,
80             requested: descriptor_set_layouts.len(),
81         });
82     }
83 
84     if num_resources.max_per_stage() > properties.max_per_stage_resources {
85         return Err(
86             PipelineLayoutLimitsError::MaxPerStageResourcesLimitExceeded {
87                 limit: properties.max_per_stage_resources,
88                 requested: num_resources.max_per_stage(),
89             },
90         );
91     }
92 
93     if num_samplers.max_per_stage() > properties.max_per_stage_descriptor_samplers {
94         return Err(
95             PipelineLayoutLimitsError::MaxPerStageDescriptorSamplersLimitExceeded {
96                 limit: properties.max_per_stage_descriptor_samplers,
97                 requested: num_samplers.max_per_stage(),
98             },
99         );
100     }
101     if num_uniform_buffers.max_per_stage()
102         > properties.max_per_stage_descriptor_uniform_buffers
103     {
104         return Err(
105             PipelineLayoutLimitsError::MaxPerStageDescriptorUniformBuffersLimitExceeded {
106                 limit: properties.max_per_stage_descriptor_uniform_buffers,
107                 requested: num_uniform_buffers.max_per_stage(),
108             },
109         );
110     }
111     if num_storage_buffers.max_per_stage()
112         > properties.max_per_stage_descriptor_storage_buffers
113     {
114         return Err(
115             PipelineLayoutLimitsError::MaxPerStageDescriptorStorageBuffersLimitExceeded {
116                 limit: properties.max_per_stage_descriptor_storage_buffers,
117                 requested: num_storage_buffers.max_per_stage(),
118             },
119         );
120     }
121     if num_sampled_images.max_per_stage()
122         > properties.max_per_stage_descriptor_sampled_images
123     {
124         return Err(
125             PipelineLayoutLimitsError::MaxPerStageDescriptorSampledImagesLimitExceeded {
126                 limit: properties.max_per_stage_descriptor_sampled_images,
127                 requested: num_sampled_images.max_per_stage(),
128             },
129         );
130     }
131     if num_storage_images.max_per_stage()
132         > properties.max_per_stage_descriptor_storage_images
133     {
134         return Err(
135             PipelineLayoutLimitsError::MaxPerStageDescriptorStorageImagesLimitExceeded {
136                 limit: properties.max_per_stage_descriptor_storage_images,
137                 requested: num_storage_images.max_per_stage(),
138             },
139         );
140     }
141     if num_input_attachments.max_per_stage()
142         > properties
143             .max_per_stage_descriptor_input_attachments
144     {
145         return Err(
146             PipelineLayoutLimitsError::MaxPerStageDescriptorInputAttachmentsLimitExceeded {
147                 limit: properties
148                     .max_per_stage_descriptor_input_attachments,
149                 requested: num_input_attachments.max_per_stage(),
150             },
151         );
152     }
153 
154     if num_samplers.total > properties.max_descriptor_set_samplers {
155         return Err(
156             PipelineLayoutLimitsError::MaxDescriptorSetSamplersLimitExceeded {
157                 limit: properties.max_descriptor_set_samplers,
158                 requested: num_samplers.total,
159             },
160         );
161     }
162     if num_uniform_buffers.total > properties.max_descriptor_set_uniform_buffers {
163         return Err(
164             PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersLimitExceeded {
165                 limit: properties.max_descriptor_set_uniform_buffers,
166                 requested: num_uniform_buffers.total,
167             },
168         );
169     }
170     if num_uniform_buffers_dynamic
171         > properties
172             .max_descriptor_set_uniform_buffers_dynamic
173     {
174         return Err(
175             PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersDynamicLimitExceeded {
176                 limit: properties
177                     .max_descriptor_set_uniform_buffers_dynamic,
178                 requested: num_uniform_buffers_dynamic,
179             },
180         );
181     }
182     if num_storage_buffers.total > properties.max_descriptor_set_storage_buffers {
183         return Err(
184             PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersLimitExceeded {
185                 limit: properties.max_descriptor_set_storage_buffers,
186                 requested: num_storage_buffers.total,
187             },
188         );
189     }
190     if num_storage_buffers_dynamic
191         > properties
192             .max_descriptor_set_storage_buffers_dynamic
193     {
194         return Err(
195             PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersDynamicLimitExceeded {
196                 limit: properties
197                     .max_descriptor_set_storage_buffers_dynamic,
198                 requested: num_storage_buffers_dynamic,
199             },
200         );
201     }
202     if num_sampled_images.total > properties.max_descriptor_set_sampled_images {
203         return Err(
204             PipelineLayoutLimitsError::MaxDescriptorSetSampledImagesLimitExceeded {
205                 limit: properties.max_descriptor_set_sampled_images,
206                 requested: num_sampled_images.total,
207             },
208         );
209     }
210     if num_storage_images.total > properties.max_descriptor_set_storage_images {
211         return Err(
212             PipelineLayoutLimitsError::MaxDescriptorSetStorageImagesLimitExceeded {
213                 limit: properties.max_descriptor_set_storage_images,
214                 requested: num_storage_images.total,
215             },
216         );
217     }
218     if num_input_attachments.total > properties.max_descriptor_set_input_attachments {
219         return Err(
220             PipelineLayoutLimitsError::MaxDescriptorSetInputAttachmentsLimitExceeded {
221                 limit: properties.max_descriptor_set_input_attachments,
222                 requested: num_input_attachments.total,
223             },
224         );
225     }
226 
227     for &PipelineLayoutPcRange { offset, size, .. } in push_constants_ranges {
228         if offset + size > properties.max_push_constants_size as usize {
229             return Err(PipelineLayoutLimitsError::MaxPushConstantsSizeExceeded {
230                 limit: properties.max_push_constants_size as usize,
231                 requested: offset + size,
232             });
233         }
234     }
235 
236     Ok(())
237 }
238 
239 /// The pipeline layout description isn't compatible with the hardware limits.
240 #[derive(Clone, Debug, PartialEq, Eq)]
241 pub enum PipelineLayoutLimitsError {
242     /// The maximum number of descriptor sets has been exceeded.
243     MaxDescriptorSetsLimitExceeded {
244         /// The limit that must be fulfilled.
245         limit: usize,
246         /// What was requested.
247         requested: usize,
248     },
249 
250     /// The maximum size of push constants has been exceeded.
251     MaxPushConstantsSizeExceeded {
252         /// The limit that must be fulfilled.
253         limit: usize,
254         /// What was requested.
255         requested: usize,
256     },
257 
258     /// The `max_per_stage_resources()` limit has been exceeded.
259     MaxPerStageResourcesLimitExceeded {
260         /// The limit that must be fulfilled.
261         limit: u32,
262         /// What was requested.
263         requested: u32,
264     },
265 
266     /// The `max_per_stage_descriptor_samplers()` limit has been exceeded.
267     MaxPerStageDescriptorSamplersLimitExceeded {
268         /// The limit that must be fulfilled.
269         limit: u32,
270         /// What was requested.
271         requested: u32,
272     },
273 
274     /// The `max_per_stage_descriptor_uniform_buffers()` limit has been exceeded.
275     MaxPerStageDescriptorUniformBuffersLimitExceeded {
276         /// The limit that must be fulfilled.
277         limit: u32,
278         /// What was requested.
279         requested: u32,
280     },
281 
282     /// The `max_per_stage_descriptor_storage_buffers()` limit has been exceeded.
283     MaxPerStageDescriptorStorageBuffersLimitExceeded {
284         /// The limit that must be fulfilled.
285         limit: u32,
286         /// What was requested.
287         requested: u32,
288     },
289 
290     /// The `max_per_stage_descriptor_sampled_images()` limit has been exceeded.
291     MaxPerStageDescriptorSampledImagesLimitExceeded {
292         /// The limit that must be fulfilled.
293         limit: u32,
294         /// What was requested.
295         requested: u32,
296     },
297 
298     /// The `max_per_stage_descriptor_storage_images()` limit has been exceeded.
299     MaxPerStageDescriptorStorageImagesLimitExceeded {
300         /// The limit that must be fulfilled.
301         limit: u32,
302         /// What was requested.
303         requested: u32,
304     },
305 
306     /// The `max_per_stage_descriptor_input_attachments()` limit has been exceeded.
307     MaxPerStageDescriptorInputAttachmentsLimitExceeded {
308         /// The limit that must be fulfilled.
309         limit: u32,
310         /// What was requested.
311         requested: u32,
312     },
313 
314     /// The `max_descriptor_set_samplers()` limit has been exceeded.
315     MaxDescriptorSetSamplersLimitExceeded {
316         /// The limit that must be fulfilled.
317         limit: u32,
318         /// What was requested.
319         requested: u32,
320     },
321 
322     /// The `max_descriptor_set_uniform_buffers()` limit has been exceeded.
323     MaxDescriptorSetUniformBuffersLimitExceeded {
324         /// The limit that must be fulfilled.
325         limit: u32,
326         /// What was requested.
327         requested: u32,
328     },
329 
330     /// The `max_descriptor_set_uniform_buffers_dynamic()` limit has been exceeded.
331     MaxDescriptorSetUniformBuffersDynamicLimitExceeded {
332         /// The limit that must be fulfilled.
333         limit: u32,
334         /// What was requested.
335         requested: u32,
336     },
337 
338     /// The `max_descriptor_set_storage_buffers()` limit has been exceeded.
339     MaxDescriptorSetStorageBuffersLimitExceeded {
340         /// The limit that must be fulfilled.
341         limit: u32,
342         /// What was requested.
343         requested: u32,
344     },
345 
346     /// The `max_descriptor_set_storage_buffers_dynamic()` limit has been exceeded.
347     MaxDescriptorSetStorageBuffersDynamicLimitExceeded {
348         /// The limit that must be fulfilled.
349         limit: u32,
350         /// What was requested.
351         requested: u32,
352     },
353 
354     /// The `max_descriptor_set_sampled_images()` limit has been exceeded.
355     MaxDescriptorSetSampledImagesLimitExceeded {
356         /// The limit that must be fulfilled.
357         limit: u32,
358         /// What was requested.
359         requested: u32,
360     },
361 
362     /// The `max_descriptor_set_storage_images()` limit has been exceeded.
363     MaxDescriptorSetStorageImagesLimitExceeded {
364         /// The limit that must be fulfilled.
365         limit: u32,
366         /// What was requested.
367         requested: u32,
368     },
369 
370     /// The `max_descriptor_set_input_attachments()` limit has been exceeded.
371     MaxDescriptorSetInputAttachmentsLimitExceeded {
372         /// The limit that must be fulfilled.
373         limit: u32,
374         /// What was requested.
375         requested: u32,
376     },
377 }
378 
379 impl error::Error for PipelineLayoutLimitsError {}
380 
381 impl fmt::Display for PipelineLayoutLimitsError {
382     #[inline]
fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error>383     fn fmt(&self, fmt: &mut fmt::Formatter) -> Result<(), fmt::Error> {
384         write!(
385             fmt,
386             "{}",
387             match *self {
388                 PipelineLayoutLimitsError::MaxDescriptorSetsLimitExceeded { .. } => {
389                     "the maximum number of descriptor sets has been exceeded"
390                 }
391                 PipelineLayoutLimitsError::MaxPushConstantsSizeExceeded { .. } => {
392                     "the maximum size of push constants has been exceeded"
393                 }
394                 PipelineLayoutLimitsError::MaxPerStageResourcesLimitExceeded { .. } => {
395                     "the `max_per_stage_resources()` limit has been exceeded"
396                 }
397                 PipelineLayoutLimitsError::MaxPerStageDescriptorSamplersLimitExceeded {
398                     ..
399                 } => {
400                     "the `max_per_stage_descriptor_samplers()` limit has been exceeded"
401                 }
402                 PipelineLayoutLimitsError::MaxPerStageDescriptorUniformBuffersLimitExceeded {
403                     ..
404                 } => "the `max_per_stage_descriptor_uniform_buffers()` limit has been exceeded",
405                 PipelineLayoutLimitsError::MaxPerStageDescriptorStorageBuffersLimitExceeded {
406                     ..
407                 } => "the `max_per_stage_descriptor_storage_buffers()` limit has been exceeded",
408                 PipelineLayoutLimitsError::MaxPerStageDescriptorSampledImagesLimitExceeded {
409                     ..
410                 } => "the `max_per_stage_descriptor_sampled_images()` limit has been exceeded",
411                 PipelineLayoutLimitsError::MaxPerStageDescriptorStorageImagesLimitExceeded {
412                     ..
413                 } => "the `max_per_stage_descriptor_storage_images()` limit has been exceeded",
414                 PipelineLayoutLimitsError::MaxPerStageDescriptorInputAttachmentsLimitExceeded {
415                     ..
416                 } => "the `max_per_stage_descriptor_input_attachments()` limit has been exceeded",
417                 PipelineLayoutLimitsError::MaxDescriptorSetSamplersLimitExceeded { .. } => {
418                     "the `max_descriptor_set_samplers()` limit has been exceeded"
419                 }
420                 PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersLimitExceeded {
421                     ..
422                 } => {
423                     "the `max_descriptor_set_uniform_buffers()` limit has been exceeded"
424                 }
425                 PipelineLayoutLimitsError::MaxDescriptorSetUniformBuffersDynamicLimitExceeded {
426                     ..
427                 } => "the `max_descriptor_set_uniform_buffers_dynamic()` limit has been exceeded",
428                 PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersLimitExceeded {
429                     ..
430                 } => {
431                     "the `max_descriptor_set_storage_buffers()` limit has been exceeded"
432                 }
433                 PipelineLayoutLimitsError::MaxDescriptorSetStorageBuffersDynamicLimitExceeded {
434                     ..
435                 } => "the `max_descriptor_set_storage_buffers_dynamic()` limit has been exceeded",
436                 PipelineLayoutLimitsError::MaxDescriptorSetSampledImagesLimitExceeded {
437                     ..
438                 } => {
439                     "the `max_descriptor_set_sampled_images()` limit has been exceeded"
440                 }
441                 PipelineLayoutLimitsError::MaxDescriptorSetStorageImagesLimitExceeded {
442                     ..
443                 } => {
444                     "the `max_descriptor_set_storage_images()` limit has been exceeded"
445                 }
446                 PipelineLayoutLimitsError::MaxDescriptorSetInputAttachmentsLimitExceeded {
447                     ..
448                 } => {
449                     "the `max_descriptor_set_input_attachments()` limit has been exceeded"
450                 }
451             }
452         )
453     }
454 }
455 
456 // Helper struct for the main function.
457 #[derive(Default)]
458 struct Counter {
459     total: u32,
460     compute: u32,
461     vertex: u32,
462     geometry: u32,
463     tess_ctl: u32,
464     tess_eval: u32,
465     frag: u32,
466 }
467 
468 impl Counter {
increment(&mut self, num: u32, stages: &ShaderStages)469     fn increment(&mut self, num: u32, stages: &ShaderStages) {
470         self.total += num;
471         if stages.compute {
472             self.compute += num;
473         }
474         if stages.vertex {
475             self.vertex += num;
476         }
477         if stages.tessellation_control {
478             self.tess_ctl += num;
479         }
480         if stages.tessellation_evaluation {
481             self.tess_eval += num;
482         }
483         if stages.geometry {
484             self.geometry += num;
485         }
486         if stages.fragment {
487             self.frag += num;
488         }
489     }
490 
max_per_stage(&self) -> u32491     fn max_per_stage(&self) -> u32 {
492         let mut max = 0;
493         if self.compute > max {
494             max = self.compute;
495         }
496         if self.vertex > max {
497             max = self.vertex;
498         }
499         if self.geometry > max {
500             max = self.geometry;
501         }
502         if self.tess_ctl > max {
503             max = self.tess_ctl;
504         }
505         if self.tess_eval > max {
506             max = self.tess_eval;
507         }
508         if self.frag > max {
509             max = self.frag;
510         }
511         max
512     }
513 }
514