• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 // Copyright (c) 2022 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 use crate::{
11     command_buffer::{
12         allocator::CommandBufferAllocator,
13         synced::{Command, SyncCommandBufferBuilder},
14         sys::UnsafeCommandBufferBuilder,
15         AutoCommandBufferBuilder,
16     },
17     device::{DeviceOwned, QueueFlags},
18     pipeline::{
19         graphics::{
20             color_blend::LogicOp,
21             depth_stencil::{CompareOp, StencilFaces, StencilOp, StencilOps},
22             input_assembly::PrimitiveTopology,
23             rasterization::{CullMode, DepthBias, FrontFace, LineStipple},
24             viewport::{Scissor, Viewport},
25         },
26         DynamicState,
27     },
28     RequirementNotMet, RequiresOneOf, Version,
29 };
30 use parking_lot::Mutex;
31 use smallvec::SmallVec;
32 use std::{
33     error::Error,
34     fmt::{Display, Error as FmtError, Formatter},
35     ops::RangeInclusive,
36 };
37 
38 /// # Commands to set dynamic state for pipelines.
39 ///
40 /// These commands require a queue with a pipeline type that uses the given state.
41 impl<L, A> AutoCommandBufferBuilder<L, A>
42 where
43     A: CommandBufferAllocator,
44 {
45     // Helper function for dynamic state setting.
validate_pipeline_fixed_state( &self, state: DynamicState, ) -> Result<(), SetDynamicStateError>46     fn validate_pipeline_fixed_state(
47         &self,
48         state: DynamicState,
49     ) -> Result<(), SetDynamicStateError> {
50         // VUID-vkCmdDispatch-None-02859
51         if self.state().pipeline_graphics().map_or(false, |pipeline| {
52             matches!(pipeline.dynamic_state(state), Some(false))
53         }) {
54             return Err(SetDynamicStateError::PipelineHasFixedState);
55         }
56 
57         Ok(())
58     }
59 
60     /// Sets the dynamic blend constants for future draw calls.
61     ///
62     /// # Panics
63     ///
64     /// - Panics if the queue family of the command buffer does not support graphics operations.
65     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_blend_constants(&mut self, constants: [f32; 4]) -> &mut Self66     pub fn set_blend_constants(&mut self, constants: [f32; 4]) -> &mut Self {
67         self.validate_set_blend_constants(constants).unwrap();
68 
69         unsafe {
70             self.inner.set_blend_constants(constants);
71         }
72 
73         self
74     }
75 
validate_set_blend_constants( &self, _constants: [f32; 4], ) -> Result<(), SetDynamicStateError>76     fn validate_set_blend_constants(
77         &self,
78         _constants: [f32; 4],
79     ) -> Result<(), SetDynamicStateError> {
80         self.validate_pipeline_fixed_state(DynamicState::BlendConstants)?;
81 
82         let queue_family_properties = self.queue_family_properties();
83 
84         // VUID-vkCmdSetBlendConstants-commandBuffer-cmdpool
85         if !queue_family_properties
86             .queue_flags
87             .intersects(QueueFlags::GRAPHICS)
88         {
89             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
90         }
91 
92         Ok(())
93     }
94 
95     /// Sets whether dynamic color writes should be enabled for each attachment in the
96     /// framebuffer.
97     ///
98     /// # Panics
99     ///
100     /// - Panics if the queue family of the command buffer does not support graphics operations.
101     /// - Panics if the [`color_write_enable`](crate::device::Features::color_write_enable)
102     ///   feature is not enabled on the device.
103     /// - Panics if the currently bound graphics pipeline already contains this state internally.
104     /// - If there is a graphics pipeline with color blend state bound, `enables.len()` must equal
105     /// - [`attachments.len()`](crate::pipeline::graphics::color_blend::ColorBlendState::attachments).
set_color_write_enable<I>(&mut self, enables: I) -> &mut Self where I: IntoIterator<Item = bool>, I::IntoIter: ExactSizeIterator,106     pub fn set_color_write_enable<I>(&mut self, enables: I) -> &mut Self
107     where
108         I: IntoIterator<Item = bool>,
109         I::IntoIter: ExactSizeIterator,
110     {
111         let enables = enables.into_iter();
112 
113         self.validate_set_color_write_enable(&enables).unwrap();
114 
115         unsafe {
116             self.inner.set_color_write_enable(enables);
117         }
118 
119         self
120     }
121 
validate_set_color_write_enable( &self, enables: &impl ExactSizeIterator, ) -> Result<(), SetDynamicStateError>122     fn validate_set_color_write_enable(
123         &self,
124         enables: &impl ExactSizeIterator,
125     ) -> Result<(), SetDynamicStateError> {
126         self.validate_pipeline_fixed_state(DynamicState::ColorWriteEnable)?;
127 
128         let queue_family_properties = self.queue_family_properties();
129 
130         // VUID-vkCmdSetColorWriteEnableEXT-commandBuffer-cmdpool
131         if !queue_family_properties
132             .queue_flags
133             .intersects(QueueFlags::GRAPHICS)
134         {
135             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
136         }
137 
138         // VUID-vkCmdSetColorWriteEnableEXT-None-04803
139         if !self.device().enabled_features().color_write_enable {
140             return Err(SetDynamicStateError::RequirementNotMet {
141                 required_for: "`AutoCommandBufferBuilder::set_color_write_enable`",
142                 requires_one_of: RequiresOneOf {
143                     device_extensions: &["ext_color_write_enable"],
144                     ..Default::default()
145                 },
146             });
147         }
148 
149         if let Some(color_blend_state) = self
150             .state()
151             .pipeline_graphics()
152             .and_then(|pipeline| pipeline.color_blend_state())
153         {
154             // VUID-vkCmdSetColorWriteEnableEXT-attachmentCount-06656
155             // Indirectly checked
156             if enables.len() != color_blend_state.attachments.len() {
157                 return Err(
158                     SetDynamicStateError::PipelineColorBlendAttachmentCountMismatch {
159                         provided_count: enables.len() as u32,
160                         required_count: color_blend_state.attachments.len() as u32,
161                     },
162                 );
163             }
164         }
165 
166         Ok(())
167     }
168 
169     /// Sets the dynamic cull mode for future draw calls.
170     ///
171     /// # Panics
172     ///
173     /// - Panics if the queue family of the command buffer does not support graphics operations.
174     /// - Panics if the device API version is less than 1.3 and the
175     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
176     ///   not enabled on the device.
177     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_cull_mode(&mut self, cull_mode: CullMode) -> &mut Self178     pub fn set_cull_mode(&mut self, cull_mode: CullMode) -> &mut Self {
179         self.validate_set_cull_mode(cull_mode).unwrap();
180 
181         unsafe {
182             self.inner.set_cull_mode(cull_mode);
183         }
184 
185         self
186     }
187 
validate_set_cull_mode(&self, cull_mode: CullMode) -> Result<(), SetDynamicStateError>188     fn validate_set_cull_mode(&self, cull_mode: CullMode) -> Result<(), SetDynamicStateError> {
189         self.validate_pipeline_fixed_state(DynamicState::CullMode)?;
190 
191         // VUID-vkCmdSetCullMode-cullMode-parameter
192         cull_mode.validate_device(self.device())?;
193 
194         let queue_family_properties = self.queue_family_properties();
195 
196         // VUID-vkCmdSetCullMode-commandBuffer-cmdpool
197         if !queue_family_properties
198             .queue_flags
199             .intersects(QueueFlags::GRAPHICS)
200         {
201             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
202         }
203 
204         // VUID-vkCmdSetCullMode-None-03384
205         if !(self.device().api_version() >= Version::V1_3
206             || self.device().enabled_features().extended_dynamic_state)
207         {
208             return Err(SetDynamicStateError::RequirementNotMet {
209                 required_for: "`AutoCommandBufferBuilder::set_cull_mode`",
210                 requires_one_of: RequiresOneOf {
211                     api_version: Some(Version::V1_3),
212                     features: &["extended_dynamic_state"],
213                     ..Default::default()
214                 },
215             });
216         }
217 
218         Ok(())
219     }
220 
221     /// Sets the dynamic depth bias values for future draw calls.
222     ///
223     /// # Panics
224     ///
225     /// - Panics if the queue family of the command buffer does not support graphics operations.
226     /// - Panics if the currently bound graphics pipeline already contains this state internally.
227     /// - If the [`depth_bias_clamp`](crate::device::Features::depth_bias_clamp)
228     ///   feature is not enabled on the device, panics if `clamp` is not 0.0.
set_depth_bias( &mut self, constant_factor: f32, clamp: f32, slope_factor: f32, ) -> &mut Self229     pub fn set_depth_bias(
230         &mut self,
231         constant_factor: f32,
232         clamp: f32,
233         slope_factor: f32,
234     ) -> &mut Self {
235         self.validate_set_depth_bias(constant_factor, clamp, slope_factor)
236             .unwrap();
237 
238         unsafe {
239             self.inner
240                 .set_depth_bias(constant_factor, clamp, slope_factor);
241         }
242 
243         self
244     }
245 
validate_set_depth_bias( &self, _constant_factor: f32, clamp: f32, _slope_factor: f32, ) -> Result<(), SetDynamicStateError>246     fn validate_set_depth_bias(
247         &self,
248         _constant_factor: f32,
249         clamp: f32,
250         _slope_factor: f32,
251     ) -> Result<(), SetDynamicStateError> {
252         self.validate_pipeline_fixed_state(DynamicState::DepthBias)?;
253 
254         let queue_family_properties = self.queue_family_properties();
255 
256         // VUID-vkCmdSetDepthBias-commandBuffer-cmdpool
257         if !queue_family_properties
258             .queue_flags
259             .intersects(QueueFlags::GRAPHICS)
260         {
261             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
262         }
263 
264         // VUID-vkCmdSetDepthBias-depthBiasClamp-00790
265         if clamp != 0.0 && !self.device().enabled_features().depth_bias_clamp {
266             return Err(SetDynamicStateError::RequirementNotMet {
267                 required_for: "`clamp` is not `0.0`",
268                 requires_one_of: RequiresOneOf {
269                     features: &["depth_bias_clamp"],
270                     ..Default::default()
271                 },
272             });
273         }
274 
275         Ok(())
276     }
277 
278     /// Sets whether dynamic depth bias is enabled for future draw calls.
279     ///
280     /// # Panics
281     ///
282     /// - Panics if the queue family of the command buffer does not support graphics operations.
283     /// - Panics if the device API version is less than 1.3 and the
284     ///   [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
285     ///   not enabled on the device.
286     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_depth_bias_enable(&mut self, enable: bool) -> &mut Self287     pub fn set_depth_bias_enable(&mut self, enable: bool) -> &mut Self {
288         self.validate_set_depth_bias_enable(enable).unwrap();
289 
290         unsafe {
291             self.inner.set_depth_bias_enable(enable);
292         }
293 
294         self
295     }
296 
validate_set_depth_bias_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError>297     fn validate_set_depth_bias_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError> {
298         self.validate_pipeline_fixed_state(DynamicState::DepthBiasEnable)?;
299 
300         let queue_family_properties = self.queue_family_properties();
301 
302         // VUID-vkCmdSetDepthBiasEnable-commandBuffer-cmdpool
303         if !queue_family_properties
304             .queue_flags
305             .intersects(QueueFlags::GRAPHICS)
306         {
307             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
308         }
309 
310         // VUID-vkCmdSetDepthBiasEnable-None-04872
311         if !(self.device().api_version() >= Version::V1_3
312             || self.device().enabled_features().extended_dynamic_state2)
313         {
314             return Err(SetDynamicStateError::RequirementNotMet {
315                 required_for: "`AutoCommandBufferBuilder::set_depth_bias_enable`",
316                 requires_one_of: RequiresOneOf {
317                     api_version: Some(Version::V1_3),
318                     features: &["extended_dynamic_state2"],
319                     ..Default::default()
320                 },
321             });
322         }
323 
324         Ok(())
325     }
326 
327     /// Sets the dynamic depth bounds for future draw calls.
328     ///
329     /// # Panics
330     ///
331     /// - Panics if the queue family of the command buffer does not support graphics operations.
332     /// - Panics if the currently bound graphics pipeline already contains this state internally.
333     /// - If the
334     ///   [`ext_depth_range_unrestricted`](crate::device::DeviceExtensions::ext_depth_range_unrestricted)
335     ///   device extension is not enabled, panics if the start and end of `bounds` are not between
336     ///   0.0 and 1.0 inclusive.
set_depth_bounds(&mut self, bounds: RangeInclusive<f32>) -> &mut Self337     pub fn set_depth_bounds(&mut self, bounds: RangeInclusive<f32>) -> &mut Self {
338         self.validate_set_depth_bounds(bounds.clone()).unwrap();
339 
340         unsafe {
341             self.inner.set_depth_bounds(bounds);
342         }
343 
344         self
345     }
346 
validate_set_depth_bounds( &self, bounds: RangeInclusive<f32>, ) -> Result<(), SetDynamicStateError>347     fn validate_set_depth_bounds(
348         &self,
349         bounds: RangeInclusive<f32>,
350     ) -> Result<(), SetDynamicStateError> {
351         self.validate_pipeline_fixed_state(DynamicState::DepthBounds)?;
352 
353         let queue_family_properties = self.queue_family_properties();
354 
355         // VUID-vkCmdSetDepthBounds-commandBuffer-cmdpool
356         if !queue_family_properties
357             .queue_flags
358             .intersects(QueueFlags::GRAPHICS)
359         {
360             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
361         }
362 
363         // VUID-vkCmdSetDepthBounds-minDepthBounds-00600
364         // VUID-vkCmdSetDepthBounds-maxDepthBounds-00601
365         if !self
366             .device()
367             .enabled_extensions()
368             .ext_depth_range_unrestricted
369             && !((0.0..=1.0).contains(bounds.start()) && (0.0..=1.0).contains(bounds.end()))
370         {
371             return Err(SetDynamicStateError::RequirementNotMet {
372                 required_for: "`bounds` is not between `0.0` and `1.0` inclusive",
373                 requires_one_of: RequiresOneOf {
374                     device_extensions: &["ext_depth_range_unrestricted"],
375                     ..Default::default()
376                 },
377             });
378         }
379 
380         Ok(())
381     }
382 
383     /// Sets whether dynamic depth bounds testing is enabled for future draw calls.
384     ///
385     /// # Panics
386     ///
387     /// - Panics if the queue family of the command buffer does not support graphics operations.
388     /// - Panics if the device API version is less than 1.3 and the
389     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
390     ///   not enabled on the device.
391     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_depth_bounds_test_enable(&mut self, enable: bool) -> &mut Self392     pub fn set_depth_bounds_test_enable(&mut self, enable: bool) -> &mut Self {
393         self.validate_set_depth_bounds_test_enable(enable).unwrap();
394 
395         unsafe {
396             self.inner.set_depth_bounds_test_enable(enable);
397         }
398 
399         self
400     }
401 
validate_set_depth_bounds_test_enable( &self, _enable: bool, ) -> Result<(), SetDynamicStateError>402     fn validate_set_depth_bounds_test_enable(
403         &self,
404         _enable: bool,
405     ) -> Result<(), SetDynamicStateError> {
406         self.validate_pipeline_fixed_state(DynamicState::DepthBoundsTestEnable)?;
407 
408         let queue_family_properties = self.queue_family_properties();
409 
410         // VUID-vkCmdSetDepthBoundsTestEnable-commandBuffer-cmdpool
411         if !queue_family_properties
412             .queue_flags
413             .intersects(QueueFlags::GRAPHICS)
414         {
415             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
416         }
417 
418         // VUID-vkCmdSetDepthBoundsTestEnable-None-03349
419         if !(self.device().api_version() >= Version::V1_3
420             || self.device().enabled_features().extended_dynamic_state)
421         {
422             return Err(SetDynamicStateError::RequirementNotMet {
423                 required_for: "`AutoCommandBufferBuilder::set_depth_bounds_test_enable`",
424                 requires_one_of: RequiresOneOf {
425                     api_version: Some(Version::V1_3),
426                     features: &["extended_dynamic_state"],
427                     ..Default::default()
428                 },
429             });
430         }
431 
432         Ok(())
433     }
434 
435     /// Sets the dynamic depth compare op for future draw calls.
436     ///
437     /// # Panics
438     ///
439     /// - Panics if the queue family of the command buffer does not support graphics operations.
440     /// - Panics if the device API version is less than 1.3 and the
441     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
442     ///   not enabled on the device.
443     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_depth_compare_op(&mut self, compare_op: CompareOp) -> &mut Self444     pub fn set_depth_compare_op(&mut self, compare_op: CompareOp) -> &mut Self {
445         self.validate_set_depth_compare_op(compare_op).unwrap();
446 
447         unsafe {
448             self.inner.set_depth_compare_op(compare_op);
449         }
450 
451         self
452     }
453 
validate_set_depth_compare_op( &self, compare_op: CompareOp, ) -> Result<(), SetDynamicStateError>454     fn validate_set_depth_compare_op(
455         &self,
456         compare_op: CompareOp,
457     ) -> Result<(), SetDynamicStateError> {
458         self.validate_pipeline_fixed_state(DynamicState::DepthCompareOp)?;
459 
460         // VUID-vkCmdSetDepthCompareOp-depthCompareOp-parameter
461         compare_op.validate_device(self.device())?;
462 
463         let queue_family_properties = self.queue_family_properties();
464 
465         // VUID-vkCmdSetDepthCompareOp-commandBuffer-cmdpool
466         if !queue_family_properties
467             .queue_flags
468             .intersects(QueueFlags::GRAPHICS)
469         {
470             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
471         }
472 
473         // VUID-vkCmdSetDepthCompareOp-None-03353
474         if !(self.device().api_version() >= Version::V1_3
475             || self.device().enabled_features().extended_dynamic_state)
476         {
477             return Err(SetDynamicStateError::RequirementNotMet {
478                 required_for: "`AutoCommandBufferBuilder::set_depth_compare_op`",
479                 requires_one_of: RequiresOneOf {
480                     api_version: Some(Version::V1_3),
481                     features: &["extended_dynamic_state"],
482                     ..Default::default()
483                 },
484             });
485         }
486 
487         Ok(())
488     }
489 
490     /// Sets whether dynamic depth testing is enabled for future draw calls.
491     ///
492     /// # Panics
493     ///
494     /// - Panics if the queue family of the command buffer does not support graphics operations.
495     /// - Panics if the device API version is less than 1.3 and the
496     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
497     ///   not enabled on the device.
498     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_depth_test_enable(&mut self, enable: bool) -> &mut Self499     pub fn set_depth_test_enable(&mut self, enable: bool) -> &mut Self {
500         self.validate_set_depth_test_enable(enable).unwrap();
501 
502         unsafe {
503             self.inner.set_depth_test_enable(enable);
504         }
505 
506         self
507     }
508 
validate_set_depth_test_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError>509     fn validate_set_depth_test_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError> {
510         self.validate_pipeline_fixed_state(DynamicState::DepthTestEnable)?;
511 
512         let queue_family_properties = self.queue_family_properties();
513 
514         // VUID-vkCmdSetDepthTestEnable-commandBuffer-cmdpool
515         if !queue_family_properties
516             .queue_flags
517             .intersects(QueueFlags::GRAPHICS)
518         {
519             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
520         }
521 
522         // VUID-vkCmdSetDepthTestEnable-None-03352
523         if !(self.device().api_version() >= Version::V1_3
524             || self.device().enabled_features().extended_dynamic_state)
525         {
526             return Err(SetDynamicStateError::RequirementNotMet {
527                 required_for: "`AutoCommandBufferBuilder::set_depth_test_enable`",
528                 requires_one_of: RequiresOneOf {
529                     api_version: Some(Version::V1_3),
530                     features: &["extended_dynamic_state"],
531                     ..Default::default()
532                 },
533             });
534         }
535 
536         Ok(())
537     }
538 
539     /// Sets whether dynamic depth write is enabled for future draw calls.
540     ///
541     /// # Panics
542     ///
543     /// - Panics if the queue family of the command buffer does not support graphics operations.
544     /// - Panics if the device API version is less than 1.3 and the
545     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
546     ///   not enabled on the device.
547     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_depth_write_enable(&mut self, enable: bool) -> &mut Self548     pub fn set_depth_write_enable(&mut self, enable: bool) -> &mut Self {
549         self.validate_set_depth_write_enable(enable).unwrap();
550 
551         unsafe {
552             self.inner.set_depth_write_enable(enable);
553         }
554 
555         self
556     }
557 
validate_set_depth_write_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError>558     fn validate_set_depth_write_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError> {
559         self.validate_pipeline_fixed_state(DynamicState::DepthWriteEnable)?;
560 
561         let queue_family_properties = self.queue_family_properties();
562 
563         // VUID-vkCmdSetDepthWriteEnable-commandBuffer-cmdpool
564         if !queue_family_properties
565             .queue_flags
566             .intersects(QueueFlags::GRAPHICS)
567         {
568             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
569         }
570 
571         // VUID-vkCmdSetDepthWriteEnable-None-03354
572         if !(self.device().api_version() >= Version::V1_3
573             || self.device().enabled_features().extended_dynamic_state)
574         {
575             return Err(SetDynamicStateError::RequirementNotMet {
576                 required_for: "`AutoCommandBufferBuilder::set_depth_write_enable`",
577                 requires_one_of: RequiresOneOf {
578                     api_version: Some(Version::V1_3),
579                     features: &["extended_dynamic_state"],
580                     ..Default::default()
581                 },
582             });
583         }
584 
585         Ok(())
586     }
587 
588     /// Sets the dynamic discard rectangles for future draw calls.
589     ///
590     /// # Panics
591     ///
592     /// - Panics if the queue family of the command buffer does not support graphics operations.
593     /// - Panics if the
594     ///   [`ext_discard_rectangles`](crate::device::DeviceExtensions::ext_discard_rectangles)
595     ///   extension is not enabled on the device.
596     /// - Panics if the currently bound graphics pipeline already contains this state internally.
597     /// - Panics if the highest discard rectangle slot being set is greater than the
598     ///   [`max_discard_rectangles`](crate::device::Properties::max_discard_rectangles) device
599     ///   property.
set_discard_rectangle( &mut self, first_rectangle: u32, rectangles: impl IntoIterator<Item = Scissor>, ) -> &mut Self600     pub fn set_discard_rectangle(
601         &mut self,
602         first_rectangle: u32,
603         rectangles: impl IntoIterator<Item = Scissor>,
604     ) -> &mut Self {
605         let rectangles: SmallVec<[Scissor; 2]> = rectangles.into_iter().collect();
606         self.validate_set_discard_rectangle(first_rectangle, &rectangles)
607             .unwrap();
608 
609         unsafe {
610             self.inner
611                 .set_discard_rectangle(first_rectangle, rectangles);
612         }
613 
614         self
615     }
616 
validate_set_discard_rectangle( &self, first_rectangle: u32, rectangles: &[Scissor], ) -> Result<(), SetDynamicStateError>617     fn validate_set_discard_rectangle(
618         &self,
619         first_rectangle: u32,
620         rectangles: &[Scissor],
621     ) -> Result<(), SetDynamicStateError> {
622         self.validate_pipeline_fixed_state(DynamicState::DiscardRectangle)?;
623 
624         let queue_family_properties = self.queue_family_properties();
625 
626         // VUID-vkCmdSetDiscardRectangle-commandBuffer-cmdpool
627         if !queue_family_properties
628             .queue_flags
629             .intersects(QueueFlags::GRAPHICS)
630         {
631             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
632         }
633 
634         if self.device().enabled_extensions().ext_discard_rectangles {
635             return Err(SetDynamicStateError::RequirementNotMet {
636                 required_for: "`AutoCommandBufferBuilder::set_discard_rectangle`",
637                 requires_one_of: RequiresOneOf {
638                     device_extensions: &["ext_discard_rectangles"],
639                     ..Default::default()
640                 },
641             });
642         }
643 
644         // VUID-vkCmdSetDiscardRectangleEXT-firstDiscardRectangle-00585
645         if first_rectangle + rectangles.len() as u32
646             > self
647                 .device()
648                 .physical_device()
649                 .properties()
650                 .max_discard_rectangles
651                 .unwrap()
652         {
653             return Err(SetDynamicStateError::MaxDiscardRectanglesExceeded {
654                 provided: first_rectangle + rectangles.len() as u32,
655                 max: self
656                     .device()
657                     .physical_device()
658                     .properties()
659                     .max_discard_rectangles
660                     .unwrap(),
661             });
662         }
663 
664         Ok(())
665     }
666 
667     /// Sets the dynamic front face for future draw calls.
668     ///
669     /// # Panics
670     ///
671     /// - Panics if the queue family of the command buffer does not support graphics operations.
672     /// - Panics if the device API version is less than 1.3 and the
673     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
674     ///   not enabled on the device.
675     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_front_face(&mut self, face: FrontFace) -> &mut Self676     pub fn set_front_face(&mut self, face: FrontFace) -> &mut Self {
677         self.validate_set_front_face(face).unwrap();
678 
679         unsafe {
680             self.inner.set_front_face(face);
681         }
682 
683         self
684     }
685 
validate_set_front_face(&self, face: FrontFace) -> Result<(), SetDynamicStateError>686     fn validate_set_front_face(&self, face: FrontFace) -> Result<(), SetDynamicStateError> {
687         self.validate_pipeline_fixed_state(DynamicState::FrontFace)?;
688 
689         // VUID-vkCmdSetFrontFace-frontFace-parameter
690         face.validate_device(self.device())?;
691 
692         let queue_family_properties = self.queue_family_properties();
693 
694         // VUID-vkCmdSetFrontFace-commandBuffer-cmdpool
695         if !queue_family_properties
696             .queue_flags
697             .intersects(QueueFlags::GRAPHICS)
698         {
699             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
700         }
701 
702         // VUID-vkCmdSetFrontFace-None-03383
703         if !(self.device().api_version() >= Version::V1_3
704             || self.device().enabled_features().extended_dynamic_state)
705         {
706             return Err(SetDynamicStateError::RequirementNotMet {
707                 required_for: "`AutoCommandBufferBuilder::set_front_face`",
708                 requires_one_of: RequiresOneOf {
709                     api_version: Some(Version::V1_3),
710                     features: &["extended_dynamic_state"],
711                     ..Default::default()
712                 },
713             });
714         }
715 
716         Ok(())
717     }
718 
719     /// Sets the dynamic line stipple values for future draw calls.
720     ///
721     /// # Panics
722     ///
723     /// - Panics if the queue family of the command buffer does not support graphics operations.
724     /// - Panics if the [`ext_line_rasterization`](crate::device::DeviceExtensions::ext_line_rasterization)
725     ///   extension is not enabled on the device.
726     /// - Panics if the currently bound graphics pipeline already contains this state internally.
727     /// - Panics if `factor` is not between 1 and 256 inclusive.
set_line_stipple(&mut self, factor: u32, pattern: u16) -> &mut Self728     pub fn set_line_stipple(&mut self, factor: u32, pattern: u16) -> &mut Self {
729         self.validate_set_line_stipple(factor, pattern).unwrap();
730 
731         unsafe {
732             self.inner.set_line_stipple(factor, pattern);
733         }
734 
735         self
736     }
737 
validate_set_line_stipple( &self, factor: u32, _pattern: u16, ) -> Result<(), SetDynamicStateError>738     fn validate_set_line_stipple(
739         &self,
740         factor: u32,
741         _pattern: u16,
742     ) -> Result<(), SetDynamicStateError> {
743         self.validate_pipeline_fixed_state(DynamicState::LineStipple)?;
744 
745         let queue_family_properties = self.queue_family_properties();
746 
747         // VUID-vkCmdSetLineStippleEXT-commandBuffer-cmdpool
748         if !queue_family_properties
749             .queue_flags
750             .intersects(QueueFlags::GRAPHICS)
751         {
752             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
753         }
754 
755         if !self.device().enabled_extensions().ext_line_rasterization {
756             return Err(SetDynamicStateError::RequirementNotMet {
757                 required_for: "`AutoCommandBufferBuilder::set_line_stipple`",
758                 requires_one_of: RequiresOneOf {
759                     device_extensions: &["ext_line_rasterization"],
760                     ..Default::default()
761                 },
762             });
763         }
764 
765         // VUID-vkCmdSetLineStippleEXT-lineStippleFactor-02776
766         if !(1..=256).contains(&factor) {
767             return Err(SetDynamicStateError::FactorOutOfRange);
768         }
769 
770         Ok(())
771     }
772 
773     /// Sets the dynamic line width for future draw calls.
774     ///
775     /// # Panics
776     ///
777     /// - Panics if the queue family of the command buffer does not support graphics operations.
778     /// - Panics if the currently bound graphics pipeline already contains this state internally.
779     /// - If the [`wide_lines`](crate::device::Features::wide_lines) feature is not enabled, panics
780     ///   if `line_width` is not 1.0.
set_line_width(&mut self, line_width: f32) -> &mut Self781     pub fn set_line_width(&mut self, line_width: f32) -> &mut Self {
782         self.validate_set_line_width(line_width).unwrap();
783 
784         unsafe {
785             self.inner.set_line_width(line_width);
786         }
787 
788         self
789     }
790 
validate_set_line_width(&self, line_width: f32) -> Result<(), SetDynamicStateError>791     fn validate_set_line_width(&self, line_width: f32) -> Result<(), SetDynamicStateError> {
792         self.validate_pipeline_fixed_state(DynamicState::LineWidth)?;
793 
794         let queue_family_properties = self.queue_family_properties();
795 
796         // VUID-vkCmdSetLineWidth-commandBuffer-cmdpool
797         if !queue_family_properties
798             .queue_flags
799             .intersects(QueueFlags::GRAPHICS)
800         {
801             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
802         }
803 
804         // VUID-vkCmdSetLineWidth-lineWidth-00788
805         if !self.device().enabled_features().wide_lines && line_width != 1.0 {
806             return Err(SetDynamicStateError::RequirementNotMet {
807                 required_for: "`line_width` is not `1.0`",
808                 requires_one_of: RequiresOneOf {
809                     features: &["wide_lines"],
810                     ..Default::default()
811                 },
812             });
813         }
814 
815         Ok(())
816     }
817 
818     /// Sets the dynamic logic op for future draw calls.
819     ///
820     /// # Panics
821     ///
822     /// - Panics if the queue family of the command buffer does not support graphics operations.
823     /// - Panics if the
824     ///   [`extended_dynamic_state2_logic_op`](crate::device::Features::extended_dynamic_state2_logic_op)
825     ///   feature is not enabled on the device.
826     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_logic_op(&mut self, logic_op: LogicOp) -> &mut Self827     pub fn set_logic_op(&mut self, logic_op: LogicOp) -> &mut Self {
828         self.validate_set_logic_op(logic_op).unwrap();
829 
830         unsafe {
831             self.inner.set_logic_op(logic_op);
832         }
833 
834         self
835     }
836 
validate_set_logic_op(&self, logic_op: LogicOp) -> Result<(), SetDynamicStateError>837     fn validate_set_logic_op(&self, logic_op: LogicOp) -> Result<(), SetDynamicStateError> {
838         self.validate_pipeline_fixed_state(DynamicState::LogicOp)?;
839 
840         // VUID-vkCmdSetLogicOpEXT-logicOp-parameter
841         logic_op.validate_device(self.device())?;
842 
843         let queue_family_properties = self.queue_family_properties();
844 
845         // VUID-vkCmdSetLogicOpEXT-commandBuffer-cmdpool
846         if !queue_family_properties
847             .queue_flags
848             .intersects(QueueFlags::GRAPHICS)
849         {
850             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
851         }
852 
853         // VUID-vkCmdSetLogicOpEXT-None-04867
854         if !self
855             .device()
856             .enabled_features()
857             .extended_dynamic_state2_logic_op
858         {
859             return Err(SetDynamicStateError::RequirementNotMet {
860                 required_for: "`AutoCommandBufferBuilder::set_logic_op`",
861                 requires_one_of: RequiresOneOf {
862                     features: &["extended_dynamic_state2_logic_op"],
863                     ..Default::default()
864                 },
865             });
866         }
867 
868         Ok(())
869     }
870 
871     /// Sets the dynamic number of patch control points for future draw calls.
872     ///
873     /// # Panics
874     ///
875     /// - Panics if the queue family of the command buffer does not support graphics operations.
876     /// - Panics if the
877     ///   [`extended_dynamic_state2_patch_control_points`](crate::device::Features::extended_dynamic_state2_patch_control_points)
878     ///   feature is not enabled on the device.
879     /// - Panics if the currently bound graphics pipeline already contains this state internally.
880     /// - Panics if `num` is 0.
881     /// - Panics if `num` is greater than the
882     ///   [`max_tessellation_patch_size`](crate::device::Properties::max_tessellation_patch_size)
883     ///   property of the device.
set_patch_control_points(&mut self, num: u32) -> &mut Self884     pub fn set_patch_control_points(&mut self, num: u32) -> &mut Self {
885         self.validate_set_patch_control_points(num).unwrap();
886 
887         unsafe {
888             self.inner.set_patch_control_points(num);
889         }
890 
891         self
892     }
893 
validate_set_patch_control_points(&self, num: u32) -> Result<(), SetDynamicStateError>894     fn validate_set_patch_control_points(&self, num: u32) -> Result<(), SetDynamicStateError> {
895         self.validate_pipeline_fixed_state(DynamicState::PatchControlPoints)?;
896 
897         let queue_family_properties = self.queue_family_properties();
898 
899         // VUID-vkCmdSetPatchControlPointsEXT-commandBuffer-cmdpool
900         if !queue_family_properties
901             .queue_flags
902             .intersects(QueueFlags::GRAPHICS)
903         {
904             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
905         }
906 
907         // VUID-vkCmdSetPatchControlPointsEXT-None-04873
908         if !self
909             .device()
910             .enabled_features()
911             .extended_dynamic_state2_patch_control_points
912         {
913             return Err(SetDynamicStateError::RequirementNotMet {
914                 required_for: "`AutoCommandBufferBuilder::set_patch_control_points`",
915                 requires_one_of: RequiresOneOf {
916                     features: &["extended_dynamic_state2_patch_control_points"],
917                     ..Default::default()
918                 },
919             });
920         }
921 
922         // VUID-vkCmdSetPatchControlPointsEXT-patchControlPoints-04874
923         assert!(num > 0, "num must be greater than 0");
924 
925         // VUID-vkCmdSetPatchControlPointsEXT-patchControlPoints-04874
926         if num
927             > self
928                 .device()
929                 .physical_device()
930                 .properties()
931                 .max_tessellation_patch_size
932         {
933             return Err(SetDynamicStateError::MaxTessellationPatchSizeExceeded {
934                 provided: num,
935                 max: self
936                     .device()
937                     .physical_device()
938                     .properties()
939                     .max_tessellation_patch_size,
940             });
941         }
942 
943         Ok(())
944     }
945 
946     /// Sets whether dynamic primitive restart is enabled for future draw calls.
947     ///
948     /// # Panics
949     ///
950     /// - Panics if the queue family of the command buffer does not support graphics operations.
951     /// - Panics if the device API version is less than 1.3 and the
952     ///   [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
953     ///   not enabled on the device.
954     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_primitive_restart_enable(&mut self, enable: bool) -> &mut Self955     pub fn set_primitive_restart_enable(&mut self, enable: bool) -> &mut Self {
956         self.validate_set_primitive_restart_enable(enable).unwrap();
957 
958         unsafe {
959             self.inner.set_primitive_restart_enable(enable);
960         }
961 
962         self
963     }
964 
validate_set_primitive_restart_enable( &self, _enable: bool, ) -> Result<(), SetDynamicStateError>965     fn validate_set_primitive_restart_enable(
966         &self,
967         _enable: bool,
968     ) -> Result<(), SetDynamicStateError> {
969         self.validate_pipeline_fixed_state(DynamicState::PrimitiveRestartEnable)?;
970 
971         let queue_family_properties = self.queue_family_properties();
972 
973         // VUID-vkCmdSetPrimitiveRestartEnable-commandBuffer-cmdpool
974         if !queue_family_properties
975             .queue_flags
976             .intersects(QueueFlags::GRAPHICS)
977         {
978             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
979         }
980 
981         // VUID-vkCmdSetPrimitiveRestartEnable-None-04866
982         if !(self.device().api_version() >= Version::V1_3
983             || self.device().enabled_features().extended_dynamic_state2)
984         {
985             return Err(SetDynamicStateError::RequirementNotMet {
986                 required_for: "`AutoCommandBufferBuilder::set_primitive_restart_enable`",
987                 requires_one_of: RequiresOneOf {
988                     api_version: Some(Version::V1_3),
989                     features: &["extended_dynamic_state2"],
990                     ..Default::default()
991                 },
992             });
993         }
994 
995         Ok(())
996     }
997 
998     /// Sets the dynamic primitive topology for future draw calls.
999     ///
1000     /// # Panics
1001     ///
1002     /// - Panics if the queue family of the command buffer does not support graphics operations.
1003     /// - Panics if the device API version is less than 1.3 and the
1004     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
1005     ///   not enabled on the device.
1006     /// - Panics if the currently bound graphics pipeline already contains this state internally.
1007     /// - If the [`geometry_shader`](crate::device::Features::geometry_shader) feature is not
1008     ///   enabled, panics if `topology` is a `WithAdjacency` topology.
1009     /// - If the [`tessellation_shader`](crate::device::Features::tessellation_shader) feature is
1010     ///   not enabled, panics if `topology` is `PatchList`.
set_primitive_topology(&mut self, topology: PrimitiveTopology) -> &mut Self1011     pub fn set_primitive_topology(&mut self, topology: PrimitiveTopology) -> &mut Self {
1012         self.validate_set_primitive_topology(topology).unwrap();
1013 
1014         unsafe {
1015             self.inner.set_primitive_topology(topology);
1016         }
1017 
1018         self
1019     }
1020 
validate_set_primitive_topology( &self, topology: PrimitiveTopology, ) -> Result<(), SetDynamicStateError>1021     fn validate_set_primitive_topology(
1022         &self,
1023         topology: PrimitiveTopology,
1024     ) -> Result<(), SetDynamicStateError> {
1025         self.validate_pipeline_fixed_state(DynamicState::PrimitiveTopology)?;
1026 
1027         // VUID-vkCmdSetPrimitiveTopology-primitiveTopology-parameter
1028         topology.validate_device(self.device())?;
1029 
1030         let queue_family_properties = self.queue_family_properties();
1031 
1032         // VUID-vkCmdSetPrimitiveTopology-commandBuffer-cmdpool
1033         if !queue_family_properties
1034             .queue_flags
1035             .intersects(QueueFlags::GRAPHICS)
1036         {
1037             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1038         }
1039 
1040         // VUID-vkCmdSetPrimitiveTopology-None-03347
1041         if !(self.device().api_version() >= Version::V1_3
1042             || self.device().enabled_features().extended_dynamic_state)
1043         {
1044             return Err(SetDynamicStateError::RequirementNotMet {
1045                 required_for: "`AutoCommandBufferBuilder::set_primitive_topology`",
1046                 requires_one_of: RequiresOneOf {
1047                     api_version: Some(Version::V1_3),
1048                     features: &["extended_dynamic_state"],
1049                     ..Default::default()
1050                 },
1051             });
1052         }
1053 
1054         // VUID?
1055         // Since these requirements exist for fixed state when creating the pipeline,
1056         // I assume they exist for dynamic state as well.
1057         match topology {
1058             PrimitiveTopology::TriangleFan => {
1059                 if self.device().enabled_extensions().khr_portability_subset
1060                     && !self.device().enabled_features().triangle_fans
1061                 {
1062                     return Err(SetDynamicStateError::RequirementNotMet {
1063                         required_for: "this device is a portability subset device, and `topology` \
1064                             is `PrimitiveTopology::TriangleFan`",
1065                         requires_one_of: RequiresOneOf {
1066                             features: &["triangle_fans"],
1067                             ..Default::default()
1068                         },
1069                     });
1070                 }
1071             }
1072             PrimitiveTopology::LineListWithAdjacency
1073             | PrimitiveTopology::LineStripWithAdjacency
1074             | PrimitiveTopology::TriangleListWithAdjacency
1075             | PrimitiveTopology::TriangleStripWithAdjacency => {
1076                 if !self.device().enabled_features().geometry_shader {
1077                     return Err(SetDynamicStateError::RequirementNotMet {
1078                         required_for: "`topology` is `PrimitiveTopology::*WithAdjacency`",
1079                         requires_one_of: RequiresOneOf {
1080                             features: &["geometry_shader"],
1081                             ..Default::default()
1082                         },
1083                     });
1084                 }
1085             }
1086             PrimitiveTopology::PatchList => {
1087                 if !self.device().enabled_features().tessellation_shader {
1088                     return Err(SetDynamicStateError::RequirementNotMet {
1089                         required_for: "`topology` is `PrimitiveTopology::PatchList`",
1090                         requires_one_of: RequiresOneOf {
1091                             features: &["tessellation_shader"],
1092                             ..Default::default()
1093                         },
1094                     });
1095                 }
1096             }
1097             _ => (),
1098         }
1099 
1100         Ok(())
1101     }
1102 
1103     /// Sets whether dynamic rasterizer discard is enabled for future draw calls.
1104     ///
1105     /// # Panics
1106     ///
1107     /// - Panics if the queue family of the command buffer does not support graphics operations.
1108     /// - Panics if the device API version is less than 1.3 and the
1109     ///   [`extended_dynamic_state2`](crate::device::Features::extended_dynamic_state2) feature is
1110     ///   not enabled on the device.
1111     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_rasterizer_discard_enable(&mut self, enable: bool) -> &mut Self1112     pub fn set_rasterizer_discard_enable(&mut self, enable: bool) -> &mut Self {
1113         self.validate_set_rasterizer_discard_enable(enable).unwrap();
1114 
1115         unsafe {
1116             self.inner.set_rasterizer_discard_enable(enable);
1117         }
1118 
1119         self
1120     }
1121 
validate_set_rasterizer_discard_enable( &self, _enable: bool, ) -> Result<(), SetDynamicStateError>1122     fn validate_set_rasterizer_discard_enable(
1123         &self,
1124         _enable: bool,
1125     ) -> Result<(), SetDynamicStateError> {
1126         self.validate_pipeline_fixed_state(DynamicState::RasterizerDiscardEnable)?;
1127 
1128         let queue_family_properties = self.queue_family_properties();
1129 
1130         // VUID-vkCmdSetRasterizerDiscardEnable-commandBuffer-cmdpool
1131         if !queue_family_properties
1132             .queue_flags
1133             .intersects(QueueFlags::GRAPHICS)
1134         {
1135             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1136         }
1137 
1138         // VUID-vkCmdSetRasterizerDiscardEnable-None-04871
1139         if !(self.device().api_version() >= Version::V1_3
1140             || self.device().enabled_features().extended_dynamic_state2)
1141         {
1142             return Err(SetDynamicStateError::RequirementNotMet {
1143                 required_for: "`AutoCommandBufferBuilder::set_rasterizer_discard_enable`",
1144                 requires_one_of: RequiresOneOf {
1145                     api_version: Some(Version::V1_3),
1146                     features: &["extended_dynamic_state2"],
1147                     ..Default::default()
1148                 },
1149             });
1150         }
1151 
1152         Ok(())
1153     }
1154 
1155     /// Sets the dynamic scissors for future draw calls.
1156     ///
1157     /// # Panics
1158     ///
1159     /// - Panics if the queue family of the command buffer does not support graphics operations.
1160     /// - Panics if the currently bound graphics pipeline already contains this state internally.
1161     /// - Panics if the highest scissor slot being set is greater than the
1162     ///   [`max_viewports`](crate::device::Properties::max_viewports) device property.
1163     /// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
1164     ///   panics if `first_scissor` is not 0, or if more than 1 scissor is provided.
set_scissor( &mut self, first_scissor: u32, scissors: impl IntoIterator<Item = Scissor>, ) -> &mut Self1165     pub fn set_scissor(
1166         &mut self,
1167         first_scissor: u32,
1168         scissors: impl IntoIterator<Item = Scissor>,
1169     ) -> &mut Self {
1170         let scissors: SmallVec<[Scissor; 2]> = scissors.into_iter().collect();
1171         self.validate_set_scissor(first_scissor, &scissors).unwrap();
1172 
1173         unsafe {
1174             self.inner.set_scissor(first_scissor, scissors);
1175         }
1176 
1177         self
1178     }
1179 
validate_set_scissor( &self, first_scissor: u32, scissors: &[Scissor], ) -> Result<(), SetDynamicStateError>1180     fn validate_set_scissor(
1181         &self,
1182         first_scissor: u32,
1183         scissors: &[Scissor],
1184     ) -> Result<(), SetDynamicStateError> {
1185         self.validate_pipeline_fixed_state(DynamicState::Scissor)?;
1186 
1187         let queue_family_properties = self.queue_family_properties();
1188 
1189         // VUID-vkCmdSetScissor-commandBuffer-cmdpool
1190         if !queue_family_properties
1191             .queue_flags
1192             .intersects(QueueFlags::GRAPHICS)
1193         {
1194             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1195         }
1196 
1197         // VUID-vkCmdSetScissor-firstScissor-00592
1198         if first_scissor + scissors.len() as u32
1199             > self.device().physical_device().properties().max_viewports
1200         {
1201             return Err(SetDynamicStateError::MaxViewportsExceeded {
1202                 provided: first_scissor + scissors.len() as u32,
1203                 max: self.device().physical_device().properties().max_viewports,
1204             });
1205         }
1206 
1207         if !self.device().enabled_features().multi_viewport {
1208             // VUID-vkCmdSetScissor-firstScissor-00593
1209             if first_scissor != 0 {
1210                 return Err(SetDynamicStateError::RequirementNotMet {
1211                     required_for: "`first_scissor` is not `0`",
1212                     requires_one_of: RequiresOneOf {
1213                         features: &["multi_viewport"],
1214                         ..Default::default()
1215                     },
1216                 });
1217             }
1218 
1219             // VUID-vkCmdSetScissor-scissorCount-00594
1220             if scissors.len() > 1 {
1221                 return Err(SetDynamicStateError::RequirementNotMet {
1222                     required_for: "`scissors.len()` is greater than `1`",
1223                     requires_one_of: RequiresOneOf {
1224                         features: &["multi_viewport"],
1225                         ..Default::default()
1226                     },
1227                 });
1228             }
1229         }
1230 
1231         Ok(())
1232     }
1233 
1234     /// Sets the dynamic scissors with count for future draw calls.
1235     ///
1236     /// # Panics
1237     ///
1238     /// - Panics if the queue family of the command buffer does not support graphics operations.
1239     /// - Panics if the device API version is less than 1.3 and the
1240     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
1241     ///   not enabled on the device.
1242     /// - Panics if the currently bound graphics pipeline already contains this state internally.
1243     /// - Panics if the highest scissor slot being set is greater than the
1244     ///   [`max_viewports`](crate::device::Properties::max_viewports) device property.
1245     /// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
1246     ///   panics if more than 1 scissor is provided.
set_scissor_with_count( &mut self, scissors: impl IntoIterator<Item = Scissor>, ) -> &mut Self1247     pub fn set_scissor_with_count(
1248         &mut self,
1249         scissors: impl IntoIterator<Item = Scissor>,
1250     ) -> &mut Self {
1251         let scissors: SmallVec<[Scissor; 2]> = scissors.into_iter().collect();
1252         self.validate_set_scissor_with_count(&scissors).unwrap();
1253 
1254         unsafe {
1255             self.inner.set_scissor_with_count(scissors);
1256         }
1257 
1258         self
1259     }
1260 
validate_set_scissor_with_count( &self, scissors: &[Scissor], ) -> Result<(), SetDynamicStateError>1261     fn validate_set_scissor_with_count(
1262         &self,
1263         scissors: &[Scissor],
1264     ) -> Result<(), SetDynamicStateError> {
1265         self.validate_pipeline_fixed_state(DynamicState::ScissorWithCount)?;
1266 
1267         let queue_family_properties = self.queue_family_properties();
1268 
1269         // VUID-vkCmdSetScissorWithCount-commandBuffer-cmdpool
1270         if !queue_family_properties
1271             .queue_flags
1272             .intersects(QueueFlags::GRAPHICS)
1273         {
1274             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1275         }
1276 
1277         // VUID-vkCmdSetScissorWithCount-None-03396
1278         if !(self.device().api_version() >= Version::V1_3
1279             || self.device().enabled_features().extended_dynamic_state)
1280         {
1281             return Err(SetDynamicStateError::RequirementNotMet {
1282                 required_for: "`AutoCommandBufferBuilder::set_scissor_with_count`",
1283                 requires_one_of: RequiresOneOf {
1284                     api_version: Some(Version::V1_3),
1285                     features: &["extended_dynamic_state"],
1286                     ..Default::default()
1287                 },
1288             });
1289         }
1290 
1291         // VUID-vkCmdSetScissorWithCount-scissorCount-03397
1292         if scissors.len() as u32 > self.device().physical_device().properties().max_viewports {
1293             return Err(SetDynamicStateError::MaxViewportsExceeded {
1294                 provided: scissors.len() as u32,
1295                 max: self.device().physical_device().properties().max_viewports,
1296             });
1297         }
1298 
1299         // VUID-vkCmdSetScissorWithCount-scissorCount-03398
1300         if !self.device().enabled_features().multi_viewport && scissors.len() > 1 {
1301             return Err(SetDynamicStateError::RequirementNotMet {
1302                 required_for: "`scissors.len()` is greater than `1`",
1303                 requires_one_of: RequiresOneOf {
1304                     features: &["multi_viewport"],
1305                     ..Default::default()
1306                 },
1307             });
1308         }
1309 
1310         Ok(())
1311     }
1312 
1313     /// Sets the dynamic stencil compare mask on one or both faces for future draw calls.
1314     ///
1315     /// # Panics
1316     ///
1317     /// - Panics if the queue family of the command buffer does not support graphics operations.
1318     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_stencil_compare_mask( &mut self, faces: StencilFaces, compare_mask: u32, ) -> &mut Self1319     pub fn set_stencil_compare_mask(
1320         &mut self,
1321         faces: StencilFaces,
1322         compare_mask: u32,
1323     ) -> &mut Self {
1324         self.validate_set_stencil_compare_mask(faces, compare_mask)
1325             .unwrap();
1326 
1327         unsafe {
1328             self.inner.set_stencil_compare_mask(faces, compare_mask);
1329         }
1330 
1331         self
1332     }
1333 
validate_set_stencil_compare_mask( &self, faces: StencilFaces, _compare_mask: u32, ) -> Result<(), SetDynamicStateError>1334     fn validate_set_stencil_compare_mask(
1335         &self,
1336         faces: StencilFaces,
1337         _compare_mask: u32,
1338     ) -> Result<(), SetDynamicStateError> {
1339         self.validate_pipeline_fixed_state(DynamicState::StencilCompareMask)?;
1340 
1341         // VUID-vkCmdSetStencilCompareMask-faceMask-parameter
1342         faces.validate_device(self.device())?;
1343 
1344         let queue_family_properties = self.queue_family_properties();
1345 
1346         // VUID-vkCmdSetStencilCompareMask-commandBuffer-cmdpool
1347         if !queue_family_properties
1348             .queue_flags
1349             .intersects(QueueFlags::GRAPHICS)
1350         {
1351             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1352         }
1353 
1354         Ok(())
1355     }
1356 
1357     /// Sets the dynamic stencil ops on one or both faces for future draw calls.
1358     ///
1359     /// # Panics
1360     ///
1361     /// - Panics if the queue family of the command buffer does not support graphics operations.
1362     /// - Panics if the device API version is less than 1.3 and the
1363     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
1364     ///   not enabled on the device.
1365     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_stencil_op( &mut self, faces: StencilFaces, fail_op: StencilOp, pass_op: StencilOp, depth_fail_op: StencilOp, compare_op: CompareOp, ) -> &mut Self1366     pub fn set_stencil_op(
1367         &mut self,
1368         faces: StencilFaces,
1369         fail_op: StencilOp,
1370         pass_op: StencilOp,
1371         depth_fail_op: StencilOp,
1372         compare_op: CompareOp,
1373     ) -> &mut Self {
1374         self.validate_set_stencil_op(faces, fail_op, pass_op, depth_fail_op, compare_op)
1375             .unwrap();
1376 
1377         unsafe {
1378             self.inner
1379                 .set_stencil_op(faces, fail_op, pass_op, depth_fail_op, compare_op);
1380         }
1381 
1382         self
1383     }
1384 
validate_set_stencil_op( &self, faces: StencilFaces, fail_op: StencilOp, pass_op: StencilOp, depth_fail_op: StencilOp, compare_op: CompareOp, ) -> Result<(), SetDynamicStateError>1385     fn validate_set_stencil_op(
1386         &self,
1387         faces: StencilFaces,
1388         fail_op: StencilOp,
1389         pass_op: StencilOp,
1390         depth_fail_op: StencilOp,
1391         compare_op: CompareOp,
1392     ) -> Result<(), SetDynamicStateError> {
1393         self.validate_pipeline_fixed_state(DynamicState::StencilOp)?;
1394 
1395         // VUID-vkCmdSetStencilOp-faceMask-parameter
1396         faces.validate_device(self.device())?;
1397 
1398         // VUID-vkCmdSetStencilOp-failOp-parameter
1399         fail_op.validate_device(self.device())?;
1400 
1401         // VUID-vkCmdSetStencilOp-passOp-parameter
1402         pass_op.validate_device(self.device())?;
1403 
1404         // VUID-vkCmdSetStencilOp-depthFailOp-parameter
1405         depth_fail_op.validate_device(self.device())?;
1406 
1407         // VUID-vkCmdSetStencilOp-compareOp-parameter
1408         compare_op.validate_device(self.device())?;
1409 
1410         let queue_family_properties = self.queue_family_properties();
1411 
1412         // VUID-vkCmdSetStencilOp-commandBuffer-cmdpool
1413         if !queue_family_properties
1414             .queue_flags
1415             .intersects(QueueFlags::GRAPHICS)
1416         {
1417             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1418         }
1419 
1420         // VUID-vkCmdSetStencilOp-None-03351
1421         if !(self.device().api_version() >= Version::V1_3
1422             || self.device().enabled_features().extended_dynamic_state)
1423         {
1424             return Err(SetDynamicStateError::RequirementNotMet {
1425                 required_for: "`AutoCommandBufferBuilder::set_stencil_op`",
1426                 requires_one_of: RequiresOneOf {
1427                     api_version: Some(Version::V1_3),
1428                     features: &["extended_dynamic_state"],
1429                     ..Default::default()
1430                 },
1431             });
1432         }
1433 
1434         Ok(())
1435     }
1436 
1437     /// Sets the dynamic stencil reference on one or both faces for future draw calls.
1438     ///
1439     /// # Panics
1440     ///
1441     /// - Panics if the queue family of the command buffer does not support graphics operations.
1442     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_stencil_reference(&mut self, faces: StencilFaces, reference: u32) -> &mut Self1443     pub fn set_stencil_reference(&mut self, faces: StencilFaces, reference: u32) -> &mut Self {
1444         self.validate_set_stencil_reference(faces, reference)
1445             .unwrap();
1446 
1447         unsafe {
1448             self.inner.set_stencil_reference(faces, reference);
1449         }
1450 
1451         self
1452     }
1453 
validate_set_stencil_reference( &self, faces: StencilFaces, _reference: u32, ) -> Result<(), SetDynamicStateError>1454     fn validate_set_stencil_reference(
1455         &self,
1456         faces: StencilFaces,
1457         _reference: u32,
1458     ) -> Result<(), SetDynamicStateError> {
1459         self.validate_pipeline_fixed_state(DynamicState::StencilReference)?;
1460 
1461         // VUID-vkCmdSetStencilReference-faceMask-parameter
1462         faces.validate_device(self.device())?;
1463 
1464         let queue_family_properties = self.queue_family_properties();
1465 
1466         // VUID-vkCmdSetStencilReference-commandBuffer-cmdpool
1467         if !queue_family_properties
1468             .queue_flags
1469             .intersects(QueueFlags::GRAPHICS)
1470         {
1471             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1472         }
1473 
1474         Ok(())
1475     }
1476 
1477     /// Sets whether dynamic stencil testing is enabled for future draw calls.
1478     ///
1479     /// # Panics
1480     ///
1481     /// - Panics if the queue family of the command buffer does not support graphics operations.
1482     /// - Panics if the device API version is less than 1.3 and the
1483     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
1484     ///   not enabled on the device.
1485     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_stencil_test_enable(&mut self, enable: bool) -> &mut Self1486     pub fn set_stencil_test_enable(&mut self, enable: bool) -> &mut Self {
1487         self.validate_set_stencil_test_enable(enable).unwrap();
1488 
1489         unsafe {
1490             self.inner.set_stencil_test_enable(enable);
1491         }
1492 
1493         self
1494     }
1495 
validate_set_stencil_test_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError>1496     fn validate_set_stencil_test_enable(&self, _enable: bool) -> Result<(), SetDynamicStateError> {
1497         self.validate_pipeline_fixed_state(DynamicState::StencilTestEnable)?;
1498 
1499         let queue_family_properties = self.queue_family_properties();
1500 
1501         // VUID-vkCmdSetStencilTestEnable-commandBuffer-cmdpool
1502         if !queue_family_properties
1503             .queue_flags
1504             .intersects(QueueFlags::GRAPHICS)
1505         {
1506             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1507         }
1508 
1509         // VUID-vkCmdSetStencilTestEnable-None-03350
1510         if !(self.device().api_version() >= Version::V1_3
1511             || self.device().enabled_features().extended_dynamic_state)
1512         {
1513             return Err(SetDynamicStateError::RequirementNotMet {
1514                 required_for: "`AutoCommandBufferBuilder::set_stencil_test_enable`",
1515                 requires_one_of: RequiresOneOf {
1516                     api_version: Some(Version::V1_3),
1517                     features: &["extended_dynamic_state"],
1518                     ..Default::default()
1519                 },
1520             });
1521         }
1522 
1523         Ok(())
1524     }
1525 
1526     /// Sets the dynamic stencil write mask on one or both faces for future draw calls.
1527     ///
1528     /// # Panics
1529     ///
1530     /// - Panics if the queue family of the command buffer does not support graphics operations.
1531     /// - Panics if the currently bound graphics pipeline already contains this state internally.
set_stencil_write_mask(&mut self, faces: StencilFaces, write_mask: u32) -> &mut Self1532     pub fn set_stencil_write_mask(&mut self, faces: StencilFaces, write_mask: u32) -> &mut Self {
1533         self.validate_set_stencil_write_mask(faces, write_mask)
1534             .unwrap();
1535 
1536         unsafe {
1537             self.inner.set_stencil_write_mask(faces, write_mask);
1538         }
1539 
1540         self
1541     }
1542 
validate_set_stencil_write_mask( &self, faces: StencilFaces, _write_mask: u32, ) -> Result<(), SetDynamicStateError>1543     fn validate_set_stencil_write_mask(
1544         &self,
1545         faces: StencilFaces,
1546         _write_mask: u32,
1547     ) -> Result<(), SetDynamicStateError> {
1548         self.validate_pipeline_fixed_state(DynamicState::StencilWriteMask)?;
1549 
1550         // VUID-vkCmdSetStencilWriteMask-faceMask-parameter
1551         faces.validate_device(self.device())?;
1552 
1553         let queue_family_properties = self.queue_family_properties();
1554 
1555         // VUID-vkCmdSetStencilWriteMask-commandBuffer-cmdpool
1556         if !queue_family_properties
1557             .queue_flags
1558             .intersects(QueueFlags::GRAPHICS)
1559         {
1560             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1561         }
1562 
1563         Ok(())
1564     }
1565 
1566     /// Sets the dynamic viewports for future draw calls.
1567     ///
1568     /// # Panics
1569     ///
1570     /// - Panics if the queue family of the command buffer does not support graphics operations.
1571     /// - Panics if the currently bound graphics pipeline already contains this state internally.
1572     /// - Panics if the highest viewport slot being set is greater than the
1573     ///   [`max_viewports`](crate::device::Properties::max_viewports) device property.
1574     /// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
1575     ///   panics if `first_viewport` is not 0, or if more than 1 viewport is provided.
set_viewport( &mut self, first_viewport: u32, viewports: impl IntoIterator<Item = Viewport>, ) -> &mut Self1576     pub fn set_viewport(
1577         &mut self,
1578         first_viewport: u32,
1579         viewports: impl IntoIterator<Item = Viewport>,
1580     ) -> &mut Self {
1581         let viewports: SmallVec<[Viewport; 2]> = viewports.into_iter().collect();
1582         self.validate_set_viewport(first_viewport, &viewports)
1583             .unwrap();
1584 
1585         unsafe {
1586             self.inner.set_viewport(first_viewport, viewports);
1587         }
1588 
1589         self
1590     }
1591 
validate_set_viewport( &self, first_viewport: u32, viewports: &[Viewport], ) -> Result<(), SetDynamicStateError>1592     fn validate_set_viewport(
1593         &self,
1594         first_viewport: u32,
1595         viewports: &[Viewport],
1596     ) -> Result<(), SetDynamicStateError> {
1597         self.validate_pipeline_fixed_state(DynamicState::Viewport)?;
1598 
1599         let queue_family_properties = self.queue_family_properties();
1600 
1601         // VUID-vkCmdSetViewport-commandBuffer-cmdpool
1602         if !queue_family_properties
1603             .queue_flags
1604             .intersects(QueueFlags::GRAPHICS)
1605         {
1606             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1607         }
1608 
1609         // VUID-vkCmdSetViewport-firstViewport-01223
1610         if first_viewport + viewports.len() as u32
1611             > self.device().physical_device().properties().max_viewports
1612         {
1613             return Err(SetDynamicStateError::MaxViewportsExceeded {
1614                 provided: first_viewport + viewports.len() as u32,
1615                 max: self.device().physical_device().properties().max_viewports,
1616             });
1617         }
1618 
1619         if !self.device().enabled_features().multi_viewport {
1620             // VUID-vkCmdSetViewport-firstViewport-01224
1621             if first_viewport != 0 {
1622                 return Err(SetDynamicStateError::RequirementNotMet {
1623                     required_for: "`first_scissors` is not `0`",
1624                     requires_one_of: RequiresOneOf {
1625                         features: &["multi_viewport"],
1626                         ..Default::default()
1627                     },
1628                 });
1629             }
1630 
1631             // VUID-vkCmdSetViewport-viewportCount-01225
1632             if viewports.len() > 1 {
1633                 return Err(SetDynamicStateError::RequirementNotMet {
1634                     required_for: "`viewports.len()` is greater than `1`",
1635                     requires_one_of: RequiresOneOf {
1636                         features: &["multi_viewport"],
1637                         ..Default::default()
1638                     },
1639                 });
1640             }
1641         }
1642 
1643         Ok(())
1644     }
1645 
1646     /// Sets the dynamic viewports with count for future draw calls.
1647     ///
1648     /// # Panics
1649     ///
1650     /// - Panics if the queue family of the command buffer does not support graphics operations.
1651     /// - Panics if the device API version is less than 1.3 and the
1652     ///   [`extended_dynamic_state`](crate::device::Features::extended_dynamic_state) feature is
1653     ///   not enabled on the device.
1654     /// - Panics if the currently bound graphics pipeline already contains this state internally.
1655     /// - Panics if the highest viewport slot being set is greater than the
1656     ///   [`max_viewports`](crate::device::Properties::max_viewports) device property.
1657     /// - If the [`multi_viewport`](crate::device::Features::multi_viewport) feature is not enabled,
1658     ///   panics if more than 1 viewport is provided.
set_viewport_with_count( &mut self, viewports: impl IntoIterator<Item = Viewport>, ) -> &mut Self1659     pub fn set_viewport_with_count(
1660         &mut self,
1661         viewports: impl IntoIterator<Item = Viewport>,
1662     ) -> &mut Self {
1663         let viewports: SmallVec<[Viewport; 2]> = viewports.into_iter().collect();
1664         self.validate_set_viewport_with_count(&viewports).unwrap();
1665 
1666         unsafe {
1667             self.inner.set_viewport_with_count(viewports);
1668         }
1669 
1670         self
1671     }
1672 
validate_set_viewport_with_count( &self, viewports: &[Viewport], ) -> Result<(), SetDynamicStateError>1673     fn validate_set_viewport_with_count(
1674         &self,
1675         viewports: &[Viewport],
1676     ) -> Result<(), SetDynamicStateError> {
1677         self.validate_pipeline_fixed_state(DynamicState::ViewportWithCount)?;
1678 
1679         let queue_family_properties = self.queue_family_properties();
1680 
1681         // VUID-vkCmdSetViewportWithCount-commandBuffer-cmdpool
1682         if !queue_family_properties
1683             .queue_flags
1684             .intersects(QueueFlags::GRAPHICS)
1685         {
1686             return Err(SetDynamicStateError::NotSupportedByQueueFamily);
1687         }
1688 
1689         // VUID-vkCmdSetViewportWithCount-None-03393
1690         if !(self.device().api_version() >= Version::V1_3
1691             || self.device().enabled_features().extended_dynamic_state)
1692         {
1693             return Err(SetDynamicStateError::RequirementNotMet {
1694                 required_for: "`AutoCommandBufferBuilder::set_viewport_with_count`",
1695                 requires_one_of: RequiresOneOf {
1696                     api_version: Some(Version::V1_3),
1697                     features: &["extended_dynamic_state"],
1698                     ..Default::default()
1699                 },
1700             });
1701         }
1702 
1703         // VUID-vkCmdSetViewportWithCount-viewportCount-03394
1704         if viewports.len() as u32 > self.device().physical_device().properties().max_viewports {
1705             return Err(SetDynamicStateError::MaxViewportsExceeded {
1706                 provided: viewports.len() as u32,
1707                 max: self.device().physical_device().properties().max_viewports,
1708             });
1709         }
1710 
1711         // VUID-vkCmdSetViewportWithCount-viewportCount-03395
1712         if !self.device().enabled_features().multi_viewport && viewports.len() > 1 {
1713             return Err(SetDynamicStateError::RequirementNotMet {
1714                 required_for: "`viewports.len()` is greater than `1`",
1715                 requires_one_of: RequiresOneOf {
1716                     features: &["multi_viewport"],
1717                     ..Default::default()
1718                 },
1719             });
1720         }
1721 
1722         Ok(())
1723     }
1724 }
1725 
1726 impl SyncCommandBufferBuilder {
1727     /// Calls `vkCmdSetBlendConstants` on the builder.
1728     #[inline]
set_blend_constants(&mut self, constants: [f32; 4])1729     pub unsafe fn set_blend_constants(&mut self, constants: [f32; 4]) {
1730         struct Cmd {
1731             constants: [f32; 4],
1732         }
1733 
1734         impl Command for Cmd {
name(&self) -> &'static str1735             fn name(&self) -> &'static str {
1736                 "set_blend_constants"
1737             }
1738 
send(&self, out: &mut UnsafeCommandBufferBuilder)1739             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1740                 out.set_blend_constants(self.constants);
1741             }
1742         }
1743 
1744         self.commands.push(Box::new(Cmd { constants }));
1745         self.current_state.blend_constants = Some(constants);
1746     }
1747 
1748     /// Calls `vkCmdSetColorWriteEnableEXT` on the builder.
1749     ///
1750     /// If the list is empty then the command is automatically ignored.
set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>)1751     pub unsafe fn set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>) {
1752         struct Cmd<I> {
1753             enables: Mutex<Option<I>>,
1754         }
1755 
1756         impl<I> Command for Cmd<I>
1757         where
1758             I: IntoIterator<Item = bool> + Send + Sync,
1759         {
1760             fn name(&self) -> &'static str {
1761                 "set_color_write_enable"
1762             }
1763 
1764             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1765                 out.set_color_write_enable(self.enables.lock().take().unwrap());
1766             }
1767         }
1768 
1769         let enables: SmallVec<[bool; 4]> = enables.into_iter().collect();
1770         self.current_state.color_write_enable = Some(enables.clone());
1771         self.commands.push(Box::new(Cmd {
1772             enables: Mutex::new(Some(enables)),
1773         }));
1774     }
1775 
1776     /// Calls `vkCmdSetCullModeEXT` on the builder.
1777     #[inline]
set_cull_mode(&mut self, cull_mode: CullMode)1778     pub unsafe fn set_cull_mode(&mut self, cull_mode: CullMode) {
1779         struct Cmd {
1780             cull_mode: CullMode,
1781         }
1782 
1783         impl Command for Cmd {
1784             fn name(&self) -> &'static str {
1785                 "set_cull_mode"
1786             }
1787 
1788             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1789                 out.set_cull_mode(self.cull_mode);
1790             }
1791         }
1792 
1793         self.commands.push(Box::new(Cmd { cull_mode }));
1794         self.current_state.cull_mode = Some(cull_mode);
1795     }
1796 
1797     /// Calls `vkCmdSetDepthBias` on the builder.
1798     #[inline]
set_depth_bias(&mut self, constant_factor: f32, clamp: f32, slope_factor: f32)1799     pub unsafe fn set_depth_bias(&mut self, constant_factor: f32, clamp: f32, slope_factor: f32) {
1800         struct Cmd {
1801             constant_factor: f32,
1802             clamp: f32,
1803             slope_factor: f32,
1804         }
1805 
1806         impl Command for Cmd {
1807             fn name(&self) -> &'static str {
1808                 "set_depth_bias"
1809             }
1810 
1811             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1812                 out.set_depth_bias(self.constant_factor, self.clamp, self.slope_factor);
1813             }
1814         }
1815 
1816         self.commands.push(Box::new(Cmd {
1817             constant_factor,
1818             clamp,
1819             slope_factor,
1820         }));
1821         self.current_state.depth_bias = Some(DepthBias {
1822             constant_factor,
1823             clamp,
1824             slope_factor,
1825         });
1826     }
1827 
1828     /// Calls `vkCmdSetDepthBiasEnableEXT` on the builder.
1829     #[inline]
set_depth_bias_enable(&mut self, enable: bool)1830     pub unsafe fn set_depth_bias_enable(&mut self, enable: bool) {
1831         struct Cmd {
1832             enable: bool,
1833         }
1834 
1835         impl Command for Cmd {
1836             fn name(&self) -> &'static str {
1837                 "set_depth_bias_enable"
1838             }
1839 
1840             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1841                 out.set_depth_bias_enable(self.enable);
1842             }
1843         }
1844 
1845         self.commands.push(Box::new(Cmd { enable }));
1846         self.current_state.depth_bias_enable = Some(enable);
1847     }
1848 
1849     /// Calls `vkCmdSetDepthBounds` on the builder.
1850     #[inline]
set_depth_bounds(&mut self, bounds: RangeInclusive<f32>)1851     pub unsafe fn set_depth_bounds(&mut self, bounds: RangeInclusive<f32>) {
1852         struct Cmd {
1853             bounds: RangeInclusive<f32>,
1854         }
1855 
1856         impl Command for Cmd {
1857             fn name(&self) -> &'static str {
1858                 "set_depth_bounds"
1859             }
1860 
1861             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1862                 out.set_depth_bounds(self.bounds.clone());
1863             }
1864         }
1865 
1866         self.commands.push(Box::new(Cmd {
1867             bounds: bounds.clone(),
1868         }));
1869         self.current_state.depth_bounds = Some(bounds);
1870     }
1871 
1872     /// Calls `vkCmdSetDepthBoundsTestEnableEXT` on the builder.
1873     #[inline]
set_depth_bounds_test_enable(&mut self, enable: bool)1874     pub unsafe fn set_depth_bounds_test_enable(&mut self, enable: bool) {
1875         struct Cmd {
1876             enable: bool,
1877         }
1878 
1879         impl Command for Cmd {
1880             fn name(&self) -> &'static str {
1881                 "set_depth_bounds_test_enable"
1882             }
1883 
1884             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1885                 out.set_depth_bounds_test_enable(self.enable);
1886             }
1887         }
1888 
1889         self.commands.push(Box::new(Cmd { enable }));
1890         self.current_state.depth_bounds_test_enable = Some(enable);
1891     }
1892 
1893     /// Calls `vkCmdSetDepthCompareOpEXT` on the builder.
1894     #[inline]
set_depth_compare_op(&mut self, compare_op: CompareOp)1895     pub unsafe fn set_depth_compare_op(&mut self, compare_op: CompareOp) {
1896         struct Cmd {
1897             compare_op: CompareOp,
1898         }
1899 
1900         impl Command for Cmd {
1901             fn name(&self) -> &'static str {
1902                 "set_depth_compare_op"
1903             }
1904 
1905             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1906                 out.set_depth_compare_op(self.compare_op);
1907             }
1908         }
1909 
1910         self.commands.push(Box::new(Cmd { compare_op }));
1911         self.current_state.depth_compare_op = Some(compare_op);
1912     }
1913 
1914     /// Calls `vkCmdSetDepthTestEnableEXT` on the builder.
1915     #[inline]
set_depth_test_enable(&mut self, enable: bool)1916     pub unsafe fn set_depth_test_enable(&mut self, enable: bool) {
1917         struct Cmd {
1918             enable: bool,
1919         }
1920 
1921         impl Command for Cmd {
1922             fn name(&self) -> &'static str {
1923                 "set_depth_test_enable"
1924             }
1925 
1926             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1927                 out.set_depth_test_enable(self.enable);
1928             }
1929         }
1930 
1931         self.commands.push(Box::new(Cmd { enable }));
1932         self.current_state.depth_test_enable = Some(enable);
1933     }
1934 
1935     /// Calls `vkCmdSetDepthWriteEnableEXT` on the builder.
1936     #[inline]
set_depth_write_enable(&mut self, enable: bool)1937     pub unsafe fn set_depth_write_enable(&mut self, enable: bool) {
1938         struct Cmd {
1939             enable: bool,
1940         }
1941 
1942         impl Command for Cmd {
1943             fn name(&self) -> &'static str {
1944                 "set_depth_write_enable"
1945             }
1946 
1947             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1948                 out.set_depth_write_enable(self.enable);
1949             }
1950         }
1951 
1952         self.commands.push(Box::new(Cmd { enable }));
1953         self.current_state.depth_write_enable = Some(enable);
1954     }
1955 
1956     /// Calls `vkCmdSetDiscardRectangle` on the builder.
1957     ///
1958     /// If the list is empty then the command is automatically ignored.
set_discard_rectangle( &mut self, first_rectangle: u32, rectangles: impl IntoIterator<Item = Scissor>, )1959     pub unsafe fn set_discard_rectangle(
1960         &mut self,
1961         first_rectangle: u32,
1962         rectangles: impl IntoIterator<Item = Scissor>,
1963     ) {
1964         struct Cmd {
1965             first_rectangle: u32,
1966             rectangles: Mutex<SmallVec<[Scissor; 2]>>,
1967         }
1968 
1969         impl Command for Cmd {
1970             fn name(&self) -> &'static str {
1971                 "set_discard_rectangle"
1972             }
1973 
1974             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
1975                 out.set_discard_rectangle(self.first_rectangle, self.rectangles.lock().drain(..));
1976             }
1977         }
1978 
1979         let rectangles: SmallVec<[Scissor; 2]> = rectangles.into_iter().collect();
1980 
1981         for (num, rectangle) in rectangles.iter().enumerate() {
1982             let num = num as u32 + first_rectangle;
1983             self.current_state.discard_rectangle.insert(num, *rectangle);
1984         }
1985 
1986         self.commands.push(Box::new(Cmd {
1987             first_rectangle,
1988             rectangles: Mutex::new(rectangles),
1989         }));
1990     }
1991 
1992     /// Calls `vkCmdSetFrontFaceEXT` on the builder.
1993     #[inline]
set_front_face(&mut self, face: FrontFace)1994     pub unsafe fn set_front_face(&mut self, face: FrontFace) {
1995         struct Cmd {
1996             face: FrontFace,
1997         }
1998 
1999         impl Command for Cmd {
2000             fn name(&self) -> &'static str {
2001                 "set_front_face"
2002             }
2003 
2004             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2005                 out.set_front_face(self.face);
2006             }
2007         }
2008 
2009         self.commands.push(Box::new(Cmd { face }));
2010         self.current_state.front_face = Some(face);
2011     }
2012 
2013     /// Calls `vkCmdSetLineStippleEXT` on the builder.
2014     #[inline]
set_line_stipple(&mut self, factor: u32, pattern: u16)2015     pub unsafe fn set_line_stipple(&mut self, factor: u32, pattern: u16) {
2016         struct Cmd {
2017             factor: u32,
2018             pattern: u16,
2019         }
2020 
2021         impl Command for Cmd {
2022             fn name(&self) -> &'static str {
2023                 "set_line_stipple"
2024             }
2025 
2026             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2027                 out.set_line_stipple(self.factor, self.pattern);
2028             }
2029         }
2030 
2031         self.commands.push(Box::new(Cmd { factor, pattern }));
2032         self.current_state.line_stipple = Some(LineStipple { factor, pattern });
2033     }
2034 
2035     /// Calls `vkCmdSetLineWidth` on the builder.
2036     #[inline]
set_line_width(&mut self, line_width: f32)2037     pub unsafe fn set_line_width(&mut self, line_width: f32) {
2038         struct Cmd {
2039             line_width: f32,
2040         }
2041 
2042         impl Command for Cmd {
2043             fn name(&self) -> &'static str {
2044                 "set_line_width"
2045             }
2046 
2047             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2048                 out.set_line_width(self.line_width);
2049             }
2050         }
2051 
2052         self.commands.push(Box::new(Cmd { line_width }));
2053         self.current_state.line_width = Some(line_width);
2054     }
2055 
2056     /// Calls `vkCmdSetLogicOpEXT` on the builder.
2057     #[inline]
set_logic_op(&mut self, logic_op: LogicOp)2058     pub unsafe fn set_logic_op(&mut self, logic_op: LogicOp) {
2059         struct Cmd {
2060             logic_op: LogicOp,
2061         }
2062 
2063         impl Command for Cmd {
2064             fn name(&self) -> &'static str {
2065                 "set_logic_op"
2066             }
2067 
2068             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2069                 out.set_logic_op(self.logic_op);
2070             }
2071         }
2072 
2073         self.commands.push(Box::new(Cmd { logic_op }));
2074         self.current_state.logic_op = Some(logic_op);
2075     }
2076 
2077     /// Calls `vkCmdSetPatchControlPointsEXT` on the builder.
2078     #[inline]
set_patch_control_points(&mut self, num: u32)2079     pub unsafe fn set_patch_control_points(&mut self, num: u32) {
2080         struct Cmd {
2081             num: u32,
2082         }
2083 
2084         impl Command for Cmd {
2085             fn name(&self) -> &'static str {
2086                 "set_patch_control_points"
2087             }
2088 
2089             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2090                 out.set_patch_control_points(self.num);
2091             }
2092         }
2093 
2094         self.commands.push(Box::new(Cmd { num }));
2095         self.current_state.patch_control_points = Some(num);
2096     }
2097 
2098     /// Calls `vkCmdSetPrimitiveRestartEnableEXT` on the builder.
2099     #[inline]
set_primitive_restart_enable(&mut self, enable: bool)2100     pub unsafe fn set_primitive_restart_enable(&mut self, enable: bool) {
2101         struct Cmd {
2102             enable: bool,
2103         }
2104 
2105         impl Command for Cmd {
2106             fn name(&self) -> &'static str {
2107                 "set_primitive_restart_enable"
2108             }
2109 
2110             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2111                 out.set_primitive_restart_enable(self.enable);
2112             }
2113         }
2114 
2115         self.commands.push(Box::new(Cmd { enable }));
2116         self.current_state.primitive_restart_enable = Some(enable);
2117     }
2118 
2119     /// Calls `vkCmdSetPrimitiveTopologyEXT` on the builder.
2120     #[inline]
set_primitive_topology(&mut self, topology: PrimitiveTopology)2121     pub unsafe fn set_primitive_topology(&mut self, topology: PrimitiveTopology) {
2122         struct Cmd {
2123             topology: PrimitiveTopology,
2124         }
2125 
2126         impl Command for Cmd {
2127             fn name(&self) -> &'static str {
2128                 "set_primitive_topology"
2129             }
2130 
2131             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2132                 out.set_primitive_topology(self.topology);
2133             }
2134         }
2135 
2136         self.commands.push(Box::new(Cmd { topology }));
2137         self.current_state.primitive_topology = Some(topology);
2138     }
2139 
2140     /// Calls `vkCmdSetRasterizerDiscardEnableEXT` on the builder.
2141     #[inline]
set_rasterizer_discard_enable(&mut self, enable: bool)2142     pub unsafe fn set_rasterizer_discard_enable(&mut self, enable: bool) {
2143         struct Cmd {
2144             enable: bool,
2145         }
2146 
2147         impl Command for Cmd {
2148             fn name(&self) -> &'static str {
2149                 "set_rasterizer_discard_enable"
2150             }
2151 
2152             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2153                 out.set_rasterizer_discard_enable(self.enable);
2154             }
2155         }
2156 
2157         self.commands.push(Box::new(Cmd { enable }));
2158         self.current_state.rasterizer_discard_enable = Some(enable);
2159     }
2160 
2161     /// Calls `vkCmdSetStencilCompareMask` on the builder.
2162     #[inline]
set_stencil_compare_mask(&mut self, faces: StencilFaces, compare_mask: u32)2163     pub unsafe fn set_stencil_compare_mask(&mut self, faces: StencilFaces, compare_mask: u32) {
2164         struct Cmd {
2165             faces: StencilFaces,
2166             compare_mask: u32,
2167         }
2168 
2169         impl Command for Cmd {
2170             fn name(&self) -> &'static str {
2171                 "set_stencil_compare_mask"
2172             }
2173 
2174             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2175                 out.set_stencil_compare_mask(self.faces, self.compare_mask);
2176             }
2177         }
2178 
2179         self.commands.push(Box::new(Cmd {
2180             faces,
2181             compare_mask,
2182         }));
2183 
2184         let faces = ash::vk::StencilFaceFlags::from(faces);
2185 
2186         if faces.intersects(ash::vk::StencilFaceFlags::FRONT) {
2187             self.current_state.stencil_compare_mask.front = Some(compare_mask);
2188         }
2189 
2190         if faces.intersects(ash::vk::StencilFaceFlags::BACK) {
2191             self.current_state.stencil_compare_mask.back = Some(compare_mask);
2192         }
2193     }
2194 
2195     /// Calls `vkCmdSetStencilOpEXT` on the builder.
2196     #[inline]
set_stencil_op( &mut self, faces: StencilFaces, fail_op: StencilOp, pass_op: StencilOp, depth_fail_op: StencilOp, compare_op: CompareOp, )2197     pub unsafe fn set_stencil_op(
2198         &mut self,
2199         faces: StencilFaces,
2200         fail_op: StencilOp,
2201         pass_op: StencilOp,
2202         depth_fail_op: StencilOp,
2203         compare_op: CompareOp,
2204     ) {
2205         struct Cmd {
2206             faces: StencilFaces,
2207             fail_op: StencilOp,
2208             pass_op: StencilOp,
2209             depth_fail_op: StencilOp,
2210             compare_op: CompareOp,
2211         }
2212 
2213         impl Command for Cmd {
2214             fn name(&self) -> &'static str {
2215                 "set_stencil_op"
2216             }
2217 
2218             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2219                 out.set_stencil_op(
2220                     self.faces,
2221                     self.fail_op,
2222                     self.pass_op,
2223                     self.depth_fail_op,
2224                     self.compare_op,
2225                 );
2226             }
2227         }
2228 
2229         self.commands.push(Box::new(Cmd {
2230             faces,
2231             fail_op,
2232             pass_op,
2233             depth_fail_op,
2234             compare_op,
2235         }));
2236 
2237         let faces = ash::vk::StencilFaceFlags::from(faces);
2238 
2239         if faces.intersects(ash::vk::StencilFaceFlags::FRONT) {
2240             self.current_state.stencil_op.front = Some(StencilOps {
2241                 fail_op,
2242                 pass_op,
2243                 depth_fail_op,
2244                 compare_op,
2245             });
2246         }
2247 
2248         if faces.intersects(ash::vk::StencilFaceFlags::BACK) {
2249             self.current_state.stencil_op.back = Some(StencilOps {
2250                 fail_op,
2251                 pass_op,
2252                 depth_fail_op,
2253                 compare_op,
2254             });
2255         }
2256     }
2257 
2258     /// Calls `vkCmdSetStencilReference` on the builder.
2259     #[inline]
set_stencil_reference(&mut self, faces: StencilFaces, reference: u32)2260     pub unsafe fn set_stencil_reference(&mut self, faces: StencilFaces, reference: u32) {
2261         struct Cmd {
2262             faces: StencilFaces,
2263             reference: u32,
2264         }
2265 
2266         impl Command for Cmd {
2267             fn name(&self) -> &'static str {
2268                 "set_stencil_reference"
2269             }
2270 
2271             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2272                 out.set_stencil_reference(self.faces, self.reference);
2273             }
2274         }
2275 
2276         self.commands.push(Box::new(Cmd { faces, reference }));
2277 
2278         let faces = ash::vk::StencilFaceFlags::from(faces);
2279 
2280         if faces.intersects(ash::vk::StencilFaceFlags::FRONT) {
2281             self.current_state.stencil_reference.front = Some(reference);
2282         }
2283 
2284         if faces.intersects(ash::vk::StencilFaceFlags::BACK) {
2285             self.current_state.stencil_reference.back = Some(reference);
2286         }
2287     }
2288 
2289     /// Calls `vkCmdSetStencilTestEnableEXT` on the builder.
2290     #[inline]
set_stencil_test_enable(&mut self, enable: bool)2291     pub unsafe fn set_stencil_test_enable(&mut self, enable: bool) {
2292         struct Cmd {
2293             enable: bool,
2294         }
2295 
2296         impl Command for Cmd {
2297             fn name(&self) -> &'static str {
2298                 "set_stencil_test_enable"
2299             }
2300 
2301             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2302                 out.set_stencil_test_enable(self.enable);
2303             }
2304         }
2305 
2306         self.commands.push(Box::new(Cmd { enable }));
2307         self.current_state.stencil_test_enable = Some(enable);
2308     }
2309 
2310     /// Calls `vkCmdSetStencilWriteMask` on the builder.
2311     #[inline]
set_stencil_write_mask(&mut self, faces: StencilFaces, write_mask: u32)2312     pub unsafe fn set_stencil_write_mask(&mut self, faces: StencilFaces, write_mask: u32) {
2313         struct Cmd {
2314             faces: StencilFaces,
2315             write_mask: u32,
2316         }
2317 
2318         impl Command for Cmd {
2319             fn name(&self) -> &'static str {
2320                 "set_stencil_write_mask"
2321             }
2322 
2323             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2324                 out.set_stencil_write_mask(self.faces, self.write_mask);
2325             }
2326         }
2327 
2328         self.commands.push(Box::new(Cmd { faces, write_mask }));
2329 
2330         let faces = ash::vk::StencilFaceFlags::from(faces);
2331 
2332         if faces.intersects(ash::vk::StencilFaceFlags::FRONT) {
2333             self.current_state.stencil_write_mask.front = Some(write_mask);
2334         }
2335 
2336         if faces.intersects(ash::vk::StencilFaceFlags::BACK) {
2337             self.current_state.stencil_write_mask.back = Some(write_mask);
2338         }
2339     }
2340 
2341     /// Calls `vkCmdSetScissor` on the builder.
2342     ///
2343     /// If the list is empty then the command is automatically ignored.
set_scissor( &mut self, first_scissor: u32, scissors: impl IntoIterator<Item = Scissor>, )2344     pub unsafe fn set_scissor(
2345         &mut self,
2346         first_scissor: u32,
2347         scissors: impl IntoIterator<Item = Scissor>,
2348     ) {
2349         struct Cmd {
2350             first_scissor: u32,
2351             scissors: Mutex<SmallVec<[Scissor; 2]>>,
2352         }
2353 
2354         impl Command for Cmd {
2355             fn name(&self) -> &'static str {
2356                 "set_scissor"
2357             }
2358 
2359             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2360                 out.set_scissor(self.first_scissor, self.scissors.lock().drain(..));
2361             }
2362         }
2363 
2364         let scissors: SmallVec<[Scissor; 2]> = scissors.into_iter().collect();
2365 
2366         for (num, scissor) in scissors.iter().enumerate() {
2367             let num = num as u32 + first_scissor;
2368             self.current_state.scissor.insert(num, *scissor);
2369         }
2370 
2371         self.commands.push(Box::new(Cmd {
2372             first_scissor,
2373             scissors: Mutex::new(scissors),
2374         }));
2375     }
2376 
2377     /// Calls `vkCmdSetScissorWithCountEXT` on the builder.
2378     ///
2379     /// If the list is empty then the command is automatically ignored.
set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>)2380     pub unsafe fn set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>) {
2381         struct Cmd {
2382             scissors: Mutex<SmallVec<[Scissor; 2]>>,
2383         }
2384 
2385         impl Command for Cmd {
2386             fn name(&self) -> &'static str {
2387                 "set_scissor_with_count"
2388             }
2389 
2390             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2391                 out.set_scissor_with_count(self.scissors.lock().drain(..));
2392             }
2393         }
2394 
2395         let scissors: SmallVec<[Scissor; 2]> = scissors.into_iter().collect();
2396         self.current_state.scissor_with_count = Some(scissors.clone());
2397         self.commands.push(Box::new(Cmd {
2398             scissors: Mutex::new(scissors),
2399         }));
2400     }
2401 
2402     /// Calls `vkCmdSetViewport` on the builder.
2403     ///
2404     /// If the list is empty then the command is automatically ignored.
set_viewport( &mut self, first_viewport: u32, viewports: impl IntoIterator<Item = Viewport>, )2405     pub unsafe fn set_viewport(
2406         &mut self,
2407         first_viewport: u32,
2408         viewports: impl IntoIterator<Item = Viewport>,
2409     ) {
2410         struct Cmd {
2411             first_viewport: u32,
2412             viewports: Mutex<SmallVec<[Viewport; 2]>>,
2413         }
2414 
2415         impl Command for Cmd {
2416             fn name(&self) -> &'static str {
2417                 "set_viewport"
2418             }
2419 
2420             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2421                 out.set_viewport(self.first_viewport, self.viewports.lock().drain(..));
2422             }
2423         }
2424 
2425         let viewports: SmallVec<[Viewport; 2]> = viewports.into_iter().collect();
2426 
2427         for (num, viewport) in viewports.iter().enumerate() {
2428             let num = num as u32 + first_viewport;
2429             self.current_state.viewport.insert(num, viewport.clone());
2430         }
2431 
2432         self.commands.push(Box::new(Cmd {
2433             first_viewport,
2434             viewports: Mutex::new(viewports),
2435         }));
2436     }
2437 
2438     /// Calls `vkCmdSetViewportWithCountEXT` on the builder.
2439     ///
2440     /// If the list is empty then the command is automatically ignored.
set_viewport_with_count( &mut self, viewports: impl IntoIterator<Item = Viewport>, )2441     pub unsafe fn set_viewport_with_count(
2442         &mut self,
2443         viewports: impl IntoIterator<Item = Viewport>,
2444     ) {
2445         struct Cmd {
2446             viewports: Mutex<SmallVec<[Viewport; 2]>>,
2447         }
2448 
2449         impl Command for Cmd {
2450             fn name(&self) -> &'static str {
2451                 "set_viewport_with_count"
2452             }
2453 
2454             unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) {
2455                 out.set_viewport_with_count(self.viewports.lock().drain(..));
2456             }
2457         }
2458 
2459         let viewports: SmallVec<[Viewport; 2]> = viewports.into_iter().collect();
2460         self.current_state.viewport_with_count = Some(viewports.clone());
2461         self.commands.push(Box::new(Cmd {
2462             viewports: Mutex::new(viewports),
2463         }));
2464     }
2465 }
2466 
2467 impl UnsafeCommandBufferBuilder {
2468     /// Calls `vkCmdSetBlendConstants` on the builder.
2469     #[inline]
set_blend_constants(&mut self, constants: [f32; 4])2470     pub unsafe fn set_blend_constants(&mut self, constants: [f32; 4]) {
2471         let fns = self.device.fns();
2472         (fns.v1_0.cmd_set_blend_constants)(self.handle, &constants);
2473     }
2474 
2475     /// Calls `vkCmdSetColorWriteEnableEXT` on the builder.
2476     ///
2477     /// If the list is empty then the command is automatically ignored.
set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>)2478     pub unsafe fn set_color_write_enable(&mut self, enables: impl IntoIterator<Item = bool>) {
2479         debug_assert!(self.device.enabled_extensions().ext_color_write_enable);
2480 
2481         let enables = enables
2482             .into_iter()
2483             .map(|v| v as ash::vk::Bool32)
2484             .collect::<SmallVec<[_; 4]>>();
2485         if enables.is_empty() {
2486             return;
2487         }
2488 
2489         let fns = self.device.fns();
2490         (fns.ext_color_write_enable.cmd_set_color_write_enable_ext)(
2491             self.handle,
2492             enables.len() as u32,
2493             enables.as_ptr(),
2494         );
2495     }
2496 
2497     /// Calls `vkCmdSetCullModeEXT` on the builder.
2498     #[inline]
set_cull_mode(&mut self, cull_mode: CullMode)2499     pub unsafe fn set_cull_mode(&mut self, cull_mode: CullMode) {
2500         let fns = self.device.fns();
2501 
2502         if self.device.api_version() >= Version::V1_3 {
2503             (fns.v1_3.cmd_set_cull_mode)(self.handle, cull_mode.into());
2504         } else {
2505             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2506             (fns.ext_extended_dynamic_state.cmd_set_cull_mode_ext)(self.handle, cull_mode.into());
2507         }
2508     }
2509 
2510     /// Calls `vkCmdSetDepthBias` on the builder.
2511     #[inline]
set_depth_bias(&mut self, constant_factor: f32, clamp: f32, slope_factor: f32)2512     pub unsafe fn set_depth_bias(&mut self, constant_factor: f32, clamp: f32, slope_factor: f32) {
2513         let fns = self.device.fns();
2514         (fns.v1_0.cmd_set_depth_bias)(self.handle, constant_factor, clamp, slope_factor);
2515     }
2516 
2517     /// Calls `vkCmdSetDepthBiasEnableEXT` on the builder.
2518     #[inline]
set_depth_bias_enable(&mut self, enable: bool)2519     pub unsafe fn set_depth_bias_enable(&mut self, enable: bool) {
2520         let fns = self.device.fns();
2521 
2522         if self.device.api_version() >= Version::V1_3 {
2523             (fns.v1_3.cmd_set_depth_bias_enable)(self.handle, enable.into());
2524         } else {
2525             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state2);
2526             (fns.ext_extended_dynamic_state2
2527                 .cmd_set_depth_bias_enable_ext)(self.handle, enable.into());
2528         }
2529     }
2530 
2531     /// Calls `vkCmdSetDepthBounds` on the builder.
2532     #[inline]
set_depth_bounds(&mut self, bounds: RangeInclusive<f32>)2533     pub unsafe fn set_depth_bounds(&mut self, bounds: RangeInclusive<f32>) {
2534         let fns = self.device.fns();
2535         (fns.v1_0.cmd_set_depth_bounds)(self.handle, *bounds.start(), *bounds.end());
2536     }
2537 
2538     /// Calls `vkCmdSetDepthBoundsTestEnableEXT` on the builder.
2539     #[inline]
set_depth_bounds_test_enable(&mut self, enable: bool)2540     pub unsafe fn set_depth_bounds_test_enable(&mut self, enable: bool) {
2541         let fns = self.device.fns();
2542 
2543         if self.device.api_version() >= Version::V1_3 {
2544             (fns.v1_3.cmd_set_depth_bounds_test_enable)(self.handle, enable.into());
2545         } else {
2546             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2547             (fns.ext_extended_dynamic_state
2548                 .cmd_set_depth_bounds_test_enable_ext)(self.handle, enable.into());
2549         }
2550     }
2551 
2552     /// Calls `vkCmdSetDepthCompareOpEXT` on the builder.
2553     #[inline]
set_depth_compare_op(&mut self, compare_op: CompareOp)2554     pub unsafe fn set_depth_compare_op(&mut self, compare_op: CompareOp) {
2555         let fns = self.device.fns();
2556 
2557         if self.device.api_version() >= Version::V1_3 {
2558             (fns.v1_3.cmd_set_depth_compare_op)(self.handle, compare_op.into());
2559         } else {
2560             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2561             (fns.ext_extended_dynamic_state.cmd_set_depth_compare_op_ext)(
2562                 self.handle,
2563                 compare_op.into(),
2564             );
2565         }
2566     }
2567 
2568     /// Calls `vkCmdSetDepthTestEnableEXT` on the builder.
2569     #[inline]
set_depth_test_enable(&mut self, enable: bool)2570     pub unsafe fn set_depth_test_enable(&mut self, enable: bool) {
2571         let fns = self.device.fns();
2572 
2573         if self.device.api_version() >= Version::V1_3 {
2574             (fns.v1_3.cmd_set_depth_test_enable)(self.handle, enable.into());
2575         } else {
2576             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2577             (fns.ext_extended_dynamic_state.cmd_set_depth_test_enable_ext)(
2578                 self.handle,
2579                 enable.into(),
2580             );
2581         }
2582     }
2583 
2584     /// Calls `vkCmdSetDepthWriteEnableEXT` on the builder.
2585     #[inline]
set_depth_write_enable(&mut self, enable: bool)2586     pub unsafe fn set_depth_write_enable(&mut self, enable: bool) {
2587         let fns = self.device.fns();
2588 
2589         if self.device.api_version() >= Version::V1_3 {
2590             (fns.v1_3.cmd_set_depth_write_enable)(self.handle, enable.into());
2591         } else {
2592             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2593             (fns.ext_extended_dynamic_state
2594                 .cmd_set_depth_write_enable_ext)(self.handle, enable.into());
2595         }
2596     }
2597 
2598     /// Calls `vkCmdSetDiscardRectangleEXT` on the builder.
2599     ///
2600     /// If the list is empty then the command is automatically ignored.
set_discard_rectangle( &mut self, first_rectangle: u32, rectangles: impl IntoIterator<Item = Scissor>, )2601     pub unsafe fn set_discard_rectangle(
2602         &mut self,
2603         first_rectangle: u32,
2604         rectangles: impl IntoIterator<Item = Scissor>,
2605     ) {
2606         debug_assert!(self.device.enabled_extensions().ext_discard_rectangles);
2607 
2608         let rectangles = rectangles
2609             .into_iter()
2610             .map(|v| v.into())
2611             .collect::<SmallVec<[_; 2]>>();
2612         if rectangles.is_empty() {
2613             return;
2614         }
2615 
2616         debug_assert!(
2617             first_rectangle + rectangles.len() as u32
2618                 <= self
2619                     .device
2620                     .physical_device()
2621                     .properties()
2622                     .max_discard_rectangles
2623                     .unwrap()
2624         );
2625 
2626         let fns = self.device.fns();
2627         (fns.ext_discard_rectangles.cmd_set_discard_rectangle_ext)(
2628             self.handle,
2629             first_rectangle,
2630             rectangles.len() as u32,
2631             rectangles.as_ptr(),
2632         );
2633     }
2634 
2635     /// Calls `vkCmdSetFrontFaceEXT` on the builder.
2636     #[inline]
set_front_face(&mut self, face: FrontFace)2637     pub unsafe fn set_front_face(&mut self, face: FrontFace) {
2638         let fns = self.device.fns();
2639 
2640         if self.device.api_version() >= Version::V1_3 {
2641             (fns.v1_3.cmd_set_front_face)(self.handle, face.into());
2642         } else {
2643             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2644             (fns.ext_extended_dynamic_state.cmd_set_front_face_ext)(self.handle, face.into());
2645         }
2646     }
2647 
2648     /// Calls `vkCmdSetLineStippleEXT` on the builder.
2649     #[inline]
set_line_stipple(&mut self, factor: u32, pattern: u16)2650     pub unsafe fn set_line_stipple(&mut self, factor: u32, pattern: u16) {
2651         debug_assert!(self.device.enabled_extensions().ext_line_rasterization);
2652         let fns = self.device.fns();
2653         (fns.ext_line_rasterization.cmd_set_line_stipple_ext)(self.handle, factor, pattern);
2654     }
2655 
2656     /// Calls `vkCmdSetLineWidth` on the builder.
2657     #[inline]
set_line_width(&mut self, line_width: f32)2658     pub unsafe fn set_line_width(&mut self, line_width: f32) {
2659         let fns = self.device.fns();
2660         (fns.v1_0.cmd_set_line_width)(self.handle, line_width);
2661     }
2662 
2663     /// Calls `vkCmdSetLogicOpEXT` on the builder.
2664     #[inline]
set_logic_op(&mut self, logic_op: LogicOp)2665     pub unsafe fn set_logic_op(&mut self, logic_op: LogicOp) {
2666         debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state2);
2667         debug_assert!(
2668             self.device
2669                 .enabled_features()
2670                 .extended_dynamic_state2_logic_op
2671         );
2672         let fns = self.device.fns();
2673 
2674         (fns.ext_extended_dynamic_state2.cmd_set_logic_op_ext)(self.handle, logic_op.into());
2675     }
2676 
2677     /// Calls `vkCmdSetPatchControlPointsEXT` on the builder.
2678     #[inline]
set_patch_control_points(&mut self, num: u32)2679     pub unsafe fn set_patch_control_points(&mut self, num: u32) {
2680         debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state2);
2681         let fns = self.device.fns();
2682         (fns.ext_extended_dynamic_state2
2683             .cmd_set_patch_control_points_ext)(self.handle, num);
2684     }
2685 
2686     /// Calls `vkCmdSetPrimitiveRestartEnableEXT` on the builder.
2687     #[inline]
set_primitive_restart_enable(&mut self, enable: bool)2688     pub unsafe fn set_primitive_restart_enable(&mut self, enable: bool) {
2689         let fns = self.device.fns();
2690 
2691         if self.device.api_version() >= Version::V1_3 {
2692             (fns.v1_3.cmd_set_primitive_restart_enable)(self.handle, enable.into());
2693         } else {
2694             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state2);
2695             (fns.ext_extended_dynamic_state2
2696                 .cmd_set_primitive_restart_enable_ext)(self.handle, enable.into());
2697         }
2698     }
2699 
2700     /// Calls `vkCmdSetPrimitiveTopologyEXT` on the builder.
2701     #[inline]
set_primitive_topology(&mut self, topology: PrimitiveTopology)2702     pub unsafe fn set_primitive_topology(&mut self, topology: PrimitiveTopology) {
2703         let fns = self.device.fns();
2704 
2705         if self.device.api_version() >= Version::V1_3 {
2706             (fns.v1_3.cmd_set_primitive_topology)(self.handle, topology.into());
2707         } else {
2708             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2709             (fns.ext_extended_dynamic_state
2710                 .cmd_set_primitive_topology_ext)(self.handle, topology.into());
2711         }
2712     }
2713 
2714     /// Calls `vkCmdSetRasterizerDiscardEnableEXT` on the builder.
2715     #[inline]
set_rasterizer_discard_enable(&mut self, enable: bool)2716     pub unsafe fn set_rasterizer_discard_enable(&mut self, enable: bool) {
2717         let fns = self.device.fns();
2718 
2719         if self.device.api_version() >= Version::V1_3 {
2720             (fns.v1_3.cmd_set_rasterizer_discard_enable)(self.handle, enable.into());
2721         } else {
2722             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state2);
2723             (fns.ext_extended_dynamic_state2
2724                 .cmd_set_rasterizer_discard_enable_ext)(self.handle, enable.into());
2725         }
2726     }
2727 
2728     /// Calls `vkCmdSetStencilCompareMask` on the builder.
2729     #[inline]
set_stencil_compare_mask(&mut self, face_mask: StencilFaces, compare_mask: u32)2730     pub unsafe fn set_stencil_compare_mask(&mut self, face_mask: StencilFaces, compare_mask: u32) {
2731         let fns = self.device.fns();
2732         (fns.v1_0.cmd_set_stencil_compare_mask)(self.handle, face_mask.into(), compare_mask);
2733     }
2734 
2735     /// Calls `vkCmdSetStencilOpEXT` on the builder.
2736     #[inline]
set_stencil_op( &mut self, face_mask: StencilFaces, fail_op: StencilOp, pass_op: StencilOp, depth_fail_op: StencilOp, compare_op: CompareOp, )2737     pub unsafe fn set_stencil_op(
2738         &mut self,
2739         face_mask: StencilFaces,
2740         fail_op: StencilOp,
2741         pass_op: StencilOp,
2742         depth_fail_op: StencilOp,
2743         compare_op: CompareOp,
2744     ) {
2745         let fns = self.device.fns();
2746 
2747         if self.device.api_version() >= Version::V1_3 {
2748             (fns.v1_3.cmd_set_stencil_op)(
2749                 self.handle,
2750                 face_mask.into(),
2751                 fail_op.into(),
2752                 pass_op.into(),
2753                 depth_fail_op.into(),
2754                 compare_op.into(),
2755             );
2756         } else {
2757             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2758             (fns.ext_extended_dynamic_state.cmd_set_stencil_op_ext)(
2759                 self.handle,
2760                 face_mask.into(),
2761                 fail_op.into(),
2762                 pass_op.into(),
2763                 depth_fail_op.into(),
2764                 compare_op.into(),
2765             );
2766         }
2767     }
2768 
2769     /// Calls `vkCmdSetStencilReference` on the builder.
2770     #[inline]
set_stencil_reference(&mut self, face_mask: StencilFaces, reference: u32)2771     pub unsafe fn set_stencil_reference(&mut self, face_mask: StencilFaces, reference: u32) {
2772         let fns = self.device.fns();
2773         (fns.v1_0.cmd_set_stencil_reference)(self.handle, face_mask.into(), reference);
2774     }
2775 
2776     /// Calls `vkCmdSetStencilTestEnableEXT` on the builder.
2777     #[inline]
set_stencil_test_enable(&mut self, enable: bool)2778     pub unsafe fn set_stencil_test_enable(&mut self, enable: bool) {
2779         let fns = self.device.fns();
2780 
2781         if self.device.api_version() >= Version::V1_3 {
2782             (fns.v1_3.cmd_set_stencil_test_enable)(self.handle, enable.into());
2783         } else {
2784             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2785             (fns.ext_extended_dynamic_state
2786                 .cmd_set_stencil_test_enable_ext)(self.handle, enable.into());
2787         }
2788     }
2789 
2790     /// Calls `vkCmdSetStencilWriteMask` on the builder.
2791     #[inline]
set_stencil_write_mask(&mut self, face_mask: StencilFaces, write_mask: u32)2792     pub unsafe fn set_stencil_write_mask(&mut self, face_mask: StencilFaces, write_mask: u32) {
2793         let fns = self.device.fns();
2794         (fns.v1_0.cmd_set_stencil_write_mask)(self.handle, face_mask.into(), write_mask);
2795     }
2796 
2797     /// Calls `vkCmdSetScissor` on the builder.
2798     ///
2799     /// If the list is empty then the command is automatically ignored.
set_scissor( &mut self, first_scissor: u32, scissors: impl IntoIterator<Item = Scissor>, )2800     pub unsafe fn set_scissor(
2801         &mut self,
2802         first_scissor: u32,
2803         scissors: impl IntoIterator<Item = Scissor>,
2804     ) {
2805         let scissors = scissors
2806             .into_iter()
2807             .map(ash::vk::Rect2D::from)
2808             .collect::<SmallVec<[_; 2]>>();
2809         if scissors.is_empty() {
2810             return;
2811         }
2812 
2813         let fns = self.device.fns();
2814         (fns.v1_0.cmd_set_scissor)(
2815             self.handle,
2816             first_scissor,
2817             scissors.len() as u32,
2818             scissors.as_ptr(),
2819         );
2820     }
2821 
2822     /// Calls `vkCmdSetScissorWithCountEXT` on the builder.
2823     ///
2824     /// If the list is empty then the command is automatically ignored.
set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>)2825     pub unsafe fn set_scissor_with_count(&mut self, scissors: impl IntoIterator<Item = Scissor>) {
2826         let scissors = scissors
2827             .into_iter()
2828             .map(ash::vk::Rect2D::from)
2829             .collect::<SmallVec<[_; 2]>>();
2830         if scissors.is_empty() {
2831             return;
2832         }
2833 
2834         let fns = self.device.fns();
2835 
2836         if self.device.api_version() >= Version::V1_3 {
2837             (fns.v1_3.cmd_set_scissor_with_count)(
2838                 self.handle,
2839                 scissors.len() as u32,
2840                 scissors.as_ptr(),
2841             );
2842         } else {
2843             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2844             (fns.ext_extended_dynamic_state
2845                 .cmd_set_scissor_with_count_ext)(
2846                 self.handle,
2847                 scissors.len() as u32,
2848                 scissors.as_ptr(),
2849             );
2850         }
2851     }
2852 
2853     /// Calls `vkCmdSetViewport` on the builder.
2854     ///
2855     /// If the list is empty then the command is automatically ignored.
set_viewport( &mut self, first_viewport: u32, viewports: impl IntoIterator<Item = Viewport>, )2856     pub unsafe fn set_viewport(
2857         &mut self,
2858         first_viewport: u32,
2859         viewports: impl IntoIterator<Item = Viewport>,
2860     ) {
2861         let viewports = viewports
2862             .into_iter()
2863             .map(|v| v.into())
2864             .collect::<SmallVec<[_; 2]>>();
2865         if viewports.is_empty() {
2866             return;
2867         }
2868 
2869         let fns = self.device.fns();
2870         (fns.v1_0.cmd_set_viewport)(
2871             self.handle,
2872             first_viewport,
2873             viewports.len() as u32,
2874             viewports.as_ptr(),
2875         );
2876     }
2877 
2878     /// Calls `vkCmdSetViewportWithCountEXT` on the builder.
2879     ///
2880     /// If the list is empty then the command is automatically ignored.
set_viewport_with_count( &mut self, viewports: impl IntoIterator<Item = Viewport>, )2881     pub unsafe fn set_viewport_with_count(
2882         &mut self,
2883         viewports: impl IntoIterator<Item = Viewport>,
2884     ) {
2885         let viewports = viewports
2886             .into_iter()
2887             .map(|v| v.into())
2888             .collect::<SmallVec<[_; 2]>>();
2889         if viewports.is_empty() {
2890             return;
2891         }
2892 
2893         let fns = self.device.fns();
2894 
2895         if self.device.api_version() >= Version::V1_3 {
2896             (fns.v1_3.cmd_set_viewport_with_count)(
2897                 self.handle,
2898                 viewports.len() as u32,
2899                 viewports.as_ptr(),
2900             );
2901         } else {
2902             debug_assert!(self.device.enabled_extensions().ext_extended_dynamic_state);
2903             (fns.ext_extended_dynamic_state
2904                 .cmd_set_viewport_with_count_ext)(
2905                 self.handle,
2906                 viewports.len() as u32,
2907                 viewports.as_ptr(),
2908             );
2909         }
2910     }
2911 }
2912 
2913 #[derive(Clone, Debug)]
2914 #[allow(dead_code)]
2915 pub(in super::super) enum SetDynamicStateError {
2916     RequirementNotMet {
2917         required_for: &'static str,
2918         requires_one_of: RequiresOneOf,
2919     },
2920 
2921     /// The provided `factor` is not between 1 and 256 inclusive.
2922     FactorOutOfRange,
2923 
2924     /// The [`max_discard_rectangles`](crate::device::Properties::max_discard_rectangles)
2925     /// limit has been exceeded.
2926     MaxDiscardRectanglesExceeded { provided: u32, max: u32 },
2927 
2928     /// The [`max_tessellation_patch_size`](crate::device::Properties::max_tessellation_patch_size)
2929     /// limit has been exceeded.
2930     MaxTessellationPatchSizeExceeded { provided: u32, max: u32 },
2931 
2932     /// The [`max_viewports`](crate::device::Properties::max_viewports)
2933     /// limit has been exceeded.
2934     MaxViewportsExceeded { provided: u32, max: u32 },
2935 
2936     /// The queue family doesn't allow this operation.
2937     NotSupportedByQueueFamily,
2938 
2939     /// The provided item count is different from the number of attachments in the color blend
2940     /// state of the currently bound pipeline.
2941     PipelineColorBlendAttachmentCountMismatch {
2942         provided_count: u32,
2943         required_count: u32,
2944     },
2945 
2946     /// The currently bound pipeline contains this state as internally fixed state, which cannot be
2947     /// overridden with dynamic state.
2948     PipelineHasFixedState,
2949 }
2950 
2951 impl Error for SetDynamicStateError {}
2952 
2953 impl Display for SetDynamicStateError {
fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>2954     fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> {
2955         match self {
2956             Self::RequirementNotMet {
2957                 required_for,
2958                 requires_one_of,
2959             } => write!(
2960                 f,
2961                 "a requirement was not met for: {}; requires one of: {}",
2962                 required_for, requires_one_of,
2963             ),
2964             Self::FactorOutOfRange => write!(
2965                 f,
2966                 "the provided `factor` is not between 1 and 256 inclusive",
2967             ),
2968             Self::MaxDiscardRectanglesExceeded { .. } => {
2969                 write!(f, "the `max_discard_rectangles` limit has been exceeded")
2970             }
2971             Self::MaxTessellationPatchSizeExceeded { .. } => write!(
2972                 f,
2973                 "the `max_tessellation_patch_size` limit has been exceeded",
2974             ),
2975             Self::MaxViewportsExceeded { .. } => {
2976                 write!(f, "the `max_viewports` limit has been exceeded")
2977             }
2978             Self::NotSupportedByQueueFamily => {
2979                 write!(f, "the queue family doesn't allow this operation")
2980             }
2981             Self::PipelineColorBlendAttachmentCountMismatch {
2982                 provided_count,
2983                 required_count,
2984             } => write!(
2985                 f,
2986                 "the provided item count ({}) is different from the number of attachments in the \
2987                 color blend state of the currently bound pipeline ({})",
2988                 provided_count, required_count,
2989             ),
2990             Self::PipelineHasFixedState => write!(
2991                 f,
2992                 "the currently bound pipeline contains this state as internally fixed state, which \
2993                 cannot be overridden with dynamic state",
2994             ),
2995         }
2996     }
2997 }
2998 
2999 impl From<RequirementNotMet> for SetDynamicStateError {
from(err: RequirementNotMet) -> Self3000     fn from(err: RequirementNotMet) -> Self {
3001         Self::RequirementNotMet {
3002             required_for: err.required_for,
3003             requires_one_of: err.requires_one_of,
3004         }
3005     }
3006 }
3007