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