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