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 buffer::{BufferContents, BufferUsage, Subbuffer}, 12 command_buffer::{ 13 allocator::CommandBufferAllocator, 14 synced::{Command, Resource, SyncCommandBufferBuilder, SyncCommandBufferBuilderError}, 15 sys::UnsafeCommandBufferBuilder, 16 AutoCommandBufferBuilder, ResourceInCommand, ResourceUseRef, 17 }, 18 device::{DeviceOwned, QueueFlags}, 19 format::{ClearColorValue, ClearDepthStencilValue, Format, FormatFeatures}, 20 image::{ImageAccess, ImageAspects, ImageLayout, ImageSubresourceRange, ImageUsage}, 21 sync::{AccessFlags, PipelineMemoryAccess, PipelineStages}, 22 DeviceSize, RequirementNotMet, RequiresOneOf, SafeDeref, Version, VulkanObject, 23 }; 24 use smallvec::{smallvec, SmallVec}; 25 use std::{ 26 error::Error, 27 fmt::{Display, Error as FmtError, Formatter}, 28 mem::size_of_val, 29 sync::Arc, 30 }; 31 32 /// # Commands to fill resources with new data. 33 impl<L, A> AutoCommandBufferBuilder<L, A> 34 where 35 A: CommandBufferAllocator, 36 { 37 /// Clears a color image with a specific value. clear_color_image( &mut self, clear_info: ClearColorImageInfo, ) -> Result<&mut Self, ClearError>38 pub fn clear_color_image( 39 &mut self, 40 clear_info: ClearColorImageInfo, 41 ) -> Result<&mut Self, ClearError> { 42 self.validate_clear_color_image(&clear_info)?; 43 44 unsafe { 45 self.inner.clear_color_image(clear_info)?; 46 } 47 48 Ok(self) 49 } 50 validate_clear_color_image( &self, clear_info: &ClearColorImageInfo, ) -> Result<(), ClearError>51 fn validate_clear_color_image( 52 &self, 53 clear_info: &ClearColorImageInfo, 54 ) -> Result<(), ClearError> { 55 let device = self.device(); 56 57 // VUID-vkCmdClearColorImage-renderpass 58 if self.render_pass_state.is_some() { 59 return Err(ClearError::ForbiddenInsideRenderPass); 60 } 61 62 let queue_family_properties = self.queue_family_properties(); 63 64 // VUID-vkCmdClearColorImage-commandBuffer-cmdpool 65 if !queue_family_properties 66 .queue_flags 67 .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) 68 { 69 return Err(ClearError::NotSupportedByQueueFamily); 70 } 71 72 let &ClearColorImageInfo { 73 ref image, 74 image_layout, 75 clear_value: _, 76 ref regions, 77 _ne: _, 78 } = clear_info; 79 80 // VUID-vkCmdClearColorImage-imageLayout-parameter 81 image_layout.validate_device(device)?; 82 83 // VUID-vkCmdClearColorImage-commonparent 84 assert_eq!(device, image.device()); 85 86 // VUID-vkCmdClearColorImage-image-00002 87 if !image.usage().intersects(ImageUsage::TRANSFER_DST) { 88 return Err(ClearError::MissingUsage { 89 usage: "transfer_dst", 90 }); 91 } 92 93 if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { 94 // VUID-vkCmdClearColorImage-image-01993 95 if !image 96 .format_features() 97 .intersects(FormatFeatures::TRANSFER_DST) 98 { 99 return Err(ClearError::MissingFormatFeature { 100 format_feature: "transfer_dst", 101 }); 102 } 103 } 104 105 let image_aspects = image.format().aspects(); 106 107 // VUID-vkCmdClearColorImage-image-00007 108 if image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 109 return Err(ClearError::FormatNotSupported { 110 format: image.format(), 111 }); 112 } 113 114 // VUID-vkCmdClearColorImage-image-00007 115 if image.format().compression().is_some() { 116 return Err(ClearError::FormatNotSupported { 117 format: image.format(), 118 }); 119 } 120 121 // VUID-vkCmdClearColorImage-image-01545 122 if image.format().ycbcr_chroma_sampling().is_some() { 123 return Err(ClearError::FormatNotSupported { 124 format: image.format(), 125 }); 126 } 127 128 // VUID-vkCmdClearColorImage-imageLayout-01394 129 if !matches!( 130 image_layout, 131 ImageLayout::TransferDstOptimal | ImageLayout::General 132 ) { 133 return Err(ClearError::ImageLayoutInvalid { image_layout }); 134 } 135 136 for (region_index, subresource_range) in regions.iter().enumerate() { 137 // VUID-VkImageSubresourceRange-aspectMask-parameter 138 subresource_range.aspects.validate_device(device)?; 139 140 // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask 141 assert!(!subresource_range.aspects.is_empty()); 142 143 // VUID-vkCmdClearColorImage-aspectMask-02498 144 if !image_aspects.contains(subresource_range.aspects) { 145 return Err(ClearError::AspectsNotAllowed { 146 region_index, 147 aspects: subresource_range.aspects, 148 allowed_aspects: image_aspects, 149 }); 150 } 151 152 // VUID-VkImageSubresourceRange-levelCount-01720 153 assert!(!subresource_range.mip_levels.is_empty()); 154 155 // VUID-vkCmdClearColorImage-baseMipLevel-01470 156 // VUID-vkCmdClearColorImage-pRanges-01692 157 if subresource_range.mip_levels.end > image.mip_levels() { 158 return Err(ClearError::MipLevelsOutOfRange { 159 region_index, 160 mip_levels_range_end: subresource_range.mip_levels.end, 161 image_mip_levels: image.dimensions().array_layers(), 162 }); 163 } 164 165 // VUID-VkImageSubresourceRange-layerCount-01721 166 assert!(!subresource_range.array_layers.is_empty()); 167 168 // VUID-vkCmdClearDepthStencilImage-baseArrayLayer-01476 169 // VUID-vkCmdClearDepthStencilImage-pRanges-01695 170 if subresource_range.array_layers.end > image.dimensions().array_layers() { 171 return Err(ClearError::ArrayLayersOutOfRange { 172 region_index, 173 array_layers_range_end: subresource_range.array_layers.end, 174 image_array_layers: image.dimensions().array_layers(), 175 }); 176 } 177 } 178 179 Ok(()) 180 } 181 182 /// Clears a depth/stencil image with a specific value. clear_depth_stencil_image( &mut self, clear_info: ClearDepthStencilImageInfo, ) -> Result<&mut Self, ClearError>183 pub fn clear_depth_stencil_image( 184 &mut self, 185 clear_info: ClearDepthStencilImageInfo, 186 ) -> Result<&mut Self, ClearError> { 187 self.validate_clear_depth_stencil_image(&clear_info)?; 188 189 unsafe { 190 self.inner.clear_depth_stencil_image(clear_info)?; 191 } 192 193 Ok(self) 194 } 195 validate_clear_depth_stencil_image( &self, clear_info: &ClearDepthStencilImageInfo, ) -> Result<(), ClearError>196 fn validate_clear_depth_stencil_image( 197 &self, 198 clear_info: &ClearDepthStencilImageInfo, 199 ) -> Result<(), ClearError> { 200 let device = self.device(); 201 202 // VUID-vkCmdClearDepthStencilImage-renderpass 203 if self.render_pass_state.is_some() { 204 return Err(ClearError::ForbiddenInsideRenderPass); 205 } 206 207 let queue_family_properties = self.queue_family_properties(); 208 209 // VUID-vkCmdClearDepthStencilImage-commandBuffer-cmdpool 210 if !queue_family_properties 211 .queue_flags 212 .intersects(QueueFlags::GRAPHICS) 213 { 214 return Err(ClearError::NotSupportedByQueueFamily); 215 } 216 217 let &ClearDepthStencilImageInfo { 218 ref image, 219 image_layout, 220 clear_value, 221 ref regions, 222 _ne: _, 223 } = clear_info; 224 225 // VUID-vkCmdClearDepthStencilImage-imageLayout-parameter 226 image_layout.validate_device(device)?; 227 228 // VUID-vkCmdClearDepthStencilImage-commonparent 229 assert_eq!(device, image.device()); 230 231 if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { 232 // VUID-vkCmdClearDepthStencilImage-image-01994 233 if !image 234 .format_features() 235 .intersects(FormatFeatures::TRANSFER_DST) 236 { 237 return Err(ClearError::MissingFormatFeature { 238 format_feature: "transfer_dst", 239 }); 240 } 241 } 242 243 let image_aspects = image.format().aspects(); 244 245 // VUID-vkCmdClearDepthStencilImage-image-00014 246 if !image_aspects.intersects(ImageAspects::DEPTH | ImageAspects::STENCIL) { 247 return Err(ClearError::FormatNotSupported { 248 format: image.format(), 249 }); 250 } 251 252 // VUID-vkCmdClearDepthStencilImage-imageLayout-00012 253 if !matches!( 254 image_layout, 255 ImageLayout::TransferDstOptimal | ImageLayout::General 256 ) { 257 return Err(ClearError::ImageLayoutInvalid { image_layout }); 258 } 259 260 // VUID-VkClearDepthStencilValue-depth-00022 261 if !device.enabled_extensions().ext_depth_range_unrestricted 262 && !(0.0..=1.0).contains(&clear_value.depth) 263 { 264 return Err(ClearError::RequirementNotMet { 265 required_for: "`clear_info.clear_value.depth` is not between `0.0` and `1.0` \ 266 inclusive", 267 requires_one_of: RequiresOneOf { 268 device_extensions: &["ext_depth_range_unrestricted"], 269 ..Default::default() 270 }, 271 }); 272 } 273 274 let mut image_aspects_used = ImageAspects::empty(); 275 276 for (region_index, subresource_range) in regions.iter().enumerate() { 277 // VUID-VkImageSubresourceRange-aspectMask-parameter 278 subresource_range.aspects.validate_device(device)?; 279 280 // VUID-VkImageSubresourceRange-aspectMask-requiredbitmask 281 assert!(!subresource_range.aspects.is_empty()); 282 283 // VUID-vkCmdClearDepthStencilImage-aspectMask-02824 284 // VUID-vkCmdClearDepthStencilImage-image-02825 285 // VUID-vkCmdClearDepthStencilImage-image-02826 286 if !image_aspects.contains(subresource_range.aspects) { 287 return Err(ClearError::AspectsNotAllowed { 288 region_index, 289 aspects: subresource_range.aspects, 290 allowed_aspects: image_aspects, 291 }); 292 } 293 294 image_aspects_used |= subresource_range.aspects; 295 296 // VUID-VkImageSubresourceRange-levelCount-01720 297 assert!(!subresource_range.mip_levels.is_empty()); 298 299 // VUID-vkCmdClearDepthStencilImage-baseMipLevel-01474 300 // VUID-vkCmdClearDepthStencilImage-pRanges-01694 301 if subresource_range.mip_levels.end > image.mip_levels() { 302 return Err(ClearError::MipLevelsOutOfRange { 303 region_index, 304 mip_levels_range_end: subresource_range.mip_levels.end, 305 image_mip_levels: image.dimensions().array_layers(), 306 }); 307 } 308 309 // VUID-VkImageSubresourceRange-layerCount-01721 310 assert!(!subresource_range.array_layers.is_empty()); 311 312 // VUID-vkCmdClearDepthStencilImage-baseArrayLayer-01476 313 // VUID-vkCmdClearDepthStencilImage-pRanges-01695 314 if subresource_range.array_layers.end > image.dimensions().array_layers() { 315 return Err(ClearError::ArrayLayersOutOfRange { 316 region_index, 317 array_layers_range_end: subresource_range.array_layers.end, 318 image_array_layers: image.dimensions().array_layers(), 319 }); 320 } 321 } 322 323 // VUID-vkCmdClearDepthStencilImage-pRanges-02658 324 // VUID-vkCmdClearDepthStencilImage-pRanges-02659 325 if image_aspects_used.intersects(ImageAspects::STENCIL) 326 && !image.stencil_usage().intersects(ImageUsage::TRANSFER_DST) 327 { 328 return Err(ClearError::MissingUsage { 329 usage: "transfer_dst", 330 }); 331 } 332 333 // VUID-vkCmdClearDepthStencilImage-pRanges-02660 334 if !(image_aspects_used - ImageAspects::STENCIL).is_empty() 335 && !image.usage().intersects(ImageUsage::TRANSFER_DST) 336 { 337 return Err(ClearError::MissingUsage { 338 usage: "transfer_dst", 339 }); 340 } 341 342 Ok(()) 343 } 344 345 /// Fills a region of a buffer with repeated copies of a value. 346 /// 347 /// This function is similar to the `memset` function in C. The `data` parameter is a number 348 /// that will be repeatedly written through the entire buffer. 349 /// 350 /// # Panics 351 /// 352 /// - Panics if `dst_buffer` was not created from the same device as `self`. fill_buffer( &mut self, dst_buffer: Subbuffer<[u32]>, data: u32, ) -> Result<&mut Self, ClearError>353 pub fn fill_buffer( 354 &mut self, 355 dst_buffer: Subbuffer<[u32]>, 356 data: u32, 357 ) -> Result<&mut Self, ClearError> { 358 self.validate_fill_buffer(&dst_buffer, data)?; 359 360 unsafe { 361 self.inner.fill_buffer(dst_buffer, data)?; 362 } 363 364 Ok(self) 365 } 366 validate_fill_buffer( &self, dst_buffer: &Subbuffer<[u32]>, _data: u32, ) -> Result<(), ClearError>367 fn validate_fill_buffer( 368 &self, 369 dst_buffer: &Subbuffer<[u32]>, 370 _data: u32, 371 ) -> Result<(), ClearError> { 372 let device = self.device(); 373 374 // VUID-vkCmdFillBuffer-renderpass 375 if self.render_pass_state.is_some() { 376 return Err(ClearError::ForbiddenInsideRenderPass); 377 } 378 379 let queue_family_properties = self.queue_family_properties(); 380 381 if device.api_version() >= Version::V1_1 || device.enabled_extensions().khr_maintenance1 { 382 // VUID-vkCmdFillBuffer-commandBuffer-cmdpool 383 if !queue_family_properties 384 .queue_flags 385 .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) 386 { 387 return Err(ClearError::NotSupportedByQueueFamily); 388 } 389 } else { 390 // VUID-vkCmdFillBuffer-commandBuffer-00030 391 if !queue_family_properties 392 .queue_flags 393 .intersects(QueueFlags::GRAPHICS | QueueFlags::COMPUTE) 394 { 395 return Err(ClearError::NotSupportedByQueueFamily); 396 } 397 } 398 399 // VUID-vkCmdFillBuffer-commonparent 400 assert_eq!(device, dst_buffer.device()); 401 402 // VUID-vkCmdFillBuffer-size-00026 403 // Guaranteed by `Subbuffer` 404 405 // VUID-vkCmdFillBuffer-dstBuffer-00029 406 if !dst_buffer 407 .buffer() 408 .usage() 409 .intersects(BufferUsage::TRANSFER_DST) 410 { 411 return Err(ClearError::MissingUsage { 412 usage: "transfer_dst", 413 }); 414 } 415 416 // VUID-vkCmdFillBuffer-dstOffset-00024 417 // VUID-vkCmdFillBuffer-size-00027 418 // Guaranteed by `Subbuffer` 419 420 // VUID-vkCmdFillBuffer-dstOffset-00025 421 // VUID-vkCmdFillBuffer-size-00028 422 // Guaranteed because we take `Subbuffer<[u32]>` 423 424 Ok(()) 425 } 426 427 /// Writes data to a region of a buffer. 428 /// 429 /// # Panics 430 /// 431 /// - Panics if `dst_buffer` was not created from the same device as `self`. update_buffer<D, Dd>( &mut self, dst_buffer: Subbuffer<D>, data: Dd, ) -> Result<&mut Self, ClearError> where D: BufferContents + ?Sized, Dd: SafeDeref<Target = D> + Send + Sync + 'static,432 pub fn update_buffer<D, Dd>( 433 &mut self, 434 dst_buffer: Subbuffer<D>, 435 data: Dd, 436 ) -> Result<&mut Self, ClearError> 437 where 438 D: BufferContents + ?Sized, 439 Dd: SafeDeref<Target = D> + Send + Sync + 'static, 440 { 441 self.validate_update_buffer( 442 dst_buffer.as_bytes(), 443 size_of_val(data.deref()) as DeviceSize, 444 )?; 445 446 unsafe { 447 self.inner.update_buffer(dst_buffer, data)?; 448 } 449 450 Ok(self) 451 } 452 validate_update_buffer( &self, dst_buffer: &Subbuffer<[u8]>, data_size: DeviceSize, ) -> Result<(), ClearError>453 fn validate_update_buffer( 454 &self, 455 dst_buffer: &Subbuffer<[u8]>, 456 data_size: DeviceSize, 457 ) -> Result<(), ClearError> { 458 let device = self.device(); 459 460 // VUID-vkCmdUpdateBuffer-renderpass 461 if self.render_pass_state.is_some() { 462 return Err(ClearError::ForbiddenInsideRenderPass); 463 } 464 465 let queue_family_properties = self.queue_family_properties(); 466 467 // VUID-vkCmdUpdateBuffer-commandBuffer-cmdpool 468 if !queue_family_properties 469 .queue_flags 470 .intersects(QueueFlags::TRANSFER | QueueFlags::GRAPHICS | QueueFlags::COMPUTE) 471 { 472 return Err(ClearError::NotSupportedByQueueFamily); 473 } 474 475 // VUID-vkCmdUpdateBuffer-commonparent 476 assert_eq!(device, dst_buffer.device()); 477 478 // VUID-vkCmdUpdateBuffer-dataSize-arraylength 479 assert!(data_size != 0); 480 481 // VUID-vkCmdUpdateBuffer-dstBuffer-00034 482 if !dst_buffer 483 .buffer() 484 .usage() 485 .intersects(BufferUsage::TRANSFER_DST) 486 { 487 return Err(ClearError::MissingUsage { 488 usage: "transfer_dst", 489 }); 490 } 491 492 // VUID-vkCmdUpdateBuffer-dstOffset-00032 493 // VUID-vkCmdUpdateBuffer-dataSize-00033 494 if data_size > dst_buffer.size() { 495 return Err(ClearError::RegionOutOfBufferBounds { 496 region_index: 0, 497 offset_range_end: data_size, 498 buffer_size: dst_buffer.size(), 499 }); 500 } 501 502 // VUID-vkCmdUpdateBuffer-dstOffset-00036 503 if dst_buffer.offset() % 4 != 0 { 504 return Err(ClearError::OffsetNotAlignedForBuffer { 505 region_index: 0, 506 offset: dst_buffer.offset(), 507 required_alignment: 4, 508 }); 509 } 510 511 // VUID-vkCmdUpdateBuffer-dataSize-00037 512 if data_size > 65536 { 513 return Err(ClearError::DataTooLarge { 514 size: data_size, 515 max: 65536, 516 }); 517 } 518 519 // VUID-vkCmdUpdateBuffer-dataSize-00038 520 if data_size % 4 != 0 { 521 return Err(ClearError::SizeNotAlignedForBuffer { 522 region_index: 0, 523 size: data_size, 524 required_alignment: 4, 525 }); 526 } 527 528 Ok(()) 529 } 530 } 531 532 impl SyncCommandBufferBuilder { 533 /// Calls `vkCmdClearColorImage` on the builder. 534 /// 535 /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid 536 /// usage of the command anyway. 537 #[inline] clear_color_image( &mut self, clear_info: ClearColorImageInfo, ) -> Result<(), SyncCommandBufferBuilderError>538 pub unsafe fn clear_color_image( 539 &mut self, 540 clear_info: ClearColorImageInfo, 541 ) -> Result<(), SyncCommandBufferBuilderError> { 542 struct Cmd { 543 clear_info: ClearColorImageInfo, 544 } 545 546 impl Command for Cmd { 547 fn name(&self) -> &'static str { 548 "clear_color_image" 549 } 550 551 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 552 out.clear_color_image(&self.clear_info); 553 } 554 } 555 556 let &ClearColorImageInfo { 557 ref image, 558 image_layout, 559 clear_value: _, 560 ref regions, 561 _ne: _, 562 } = &clear_info; 563 564 let command_index = self.commands.len(); 565 let command_name = "clear_color_image"; 566 let resources: SmallVec<[_; 8]> = regions 567 .iter() 568 .cloned() 569 .flat_map(|subresource_range| { 570 [( 571 ResourceUseRef { 572 command_index, 573 command_name, 574 resource_in_command: ResourceInCommand::Destination, 575 secondary_use_ref: None, 576 }, 577 Resource::Image { 578 image: image.clone(), 579 subresource_range, 580 memory: PipelineMemoryAccess { 581 stages: PipelineStages::ALL_TRANSFER, 582 access: AccessFlags::TRANSFER_WRITE, 583 exclusive: true, 584 }, 585 start_layout: image_layout, 586 end_layout: image_layout, 587 }, 588 )] 589 }) 590 .collect(); 591 592 for resource in &resources { 593 self.check_resource_conflicts(resource)?; 594 } 595 596 self.commands.push(Box::new(Cmd { clear_info })); 597 598 for resource in resources { 599 self.add_resource(resource); 600 } 601 602 Ok(()) 603 } 604 605 /// Calls `vkCmdClearDepthStencilImage` on the builder. 606 /// 607 /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid 608 /// usage of the command anyway. 609 #[inline] clear_depth_stencil_image( &mut self, clear_info: ClearDepthStencilImageInfo, ) -> Result<(), SyncCommandBufferBuilderError>610 pub unsafe fn clear_depth_stencil_image( 611 &mut self, 612 clear_info: ClearDepthStencilImageInfo, 613 ) -> Result<(), SyncCommandBufferBuilderError> { 614 struct Cmd { 615 clear_info: ClearDepthStencilImageInfo, 616 } 617 618 impl Command for Cmd { 619 fn name(&self) -> &'static str { 620 "clear_depth_stencil_image" 621 } 622 623 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 624 out.clear_depth_stencil_image(&self.clear_info); 625 } 626 } 627 628 let &ClearDepthStencilImageInfo { 629 ref image, 630 image_layout, 631 clear_value: _, 632 ref regions, 633 _ne: _, 634 } = &clear_info; 635 636 let command_index = self.commands.len(); 637 let command_name = "clear_depth_stencil_image"; 638 let resources: SmallVec<[_; 8]> = regions 639 .iter() 640 .cloned() 641 .flat_map(|subresource_range| { 642 [( 643 ResourceUseRef { 644 command_index, 645 command_name, 646 resource_in_command: ResourceInCommand::Destination, 647 secondary_use_ref: None, 648 }, 649 Resource::Image { 650 image: image.clone(), 651 subresource_range, 652 memory: PipelineMemoryAccess { 653 stages: PipelineStages::ALL_TRANSFER, 654 access: AccessFlags::TRANSFER_WRITE, 655 exclusive: true, 656 }, 657 start_layout: image_layout, 658 end_layout: image_layout, 659 }, 660 )] 661 }) 662 .collect(); 663 664 for resource in &resources { 665 self.check_resource_conflicts(resource)?; 666 } 667 668 self.commands.push(Box::new(Cmd { clear_info })); 669 670 for resource in resources { 671 self.add_resource(resource); 672 } 673 674 Ok(()) 675 } 676 677 /// Calls `vkCmdFillBuffer` on the builder. 678 #[inline] fill_buffer( &mut self, dst_buffer: Subbuffer<[u32]>, data: u32, ) -> Result<(), SyncCommandBufferBuilderError>679 pub unsafe fn fill_buffer( 680 &mut self, 681 dst_buffer: Subbuffer<[u32]>, 682 data: u32, 683 ) -> Result<(), SyncCommandBufferBuilderError> { 684 struct Cmd { 685 dst_buffer: Subbuffer<[u32]>, 686 data: u32, 687 } 688 689 impl Command for Cmd { 690 fn name(&self) -> &'static str { 691 "fill_buffer" 692 } 693 694 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 695 out.fill_buffer(&self.dst_buffer, self.data); 696 } 697 } 698 699 let command_index = self.commands.len(); 700 let command_name = "fill_buffer"; 701 let resources = [( 702 ResourceUseRef { 703 command_index, 704 command_name, 705 resource_in_command: ResourceInCommand::Destination, 706 secondary_use_ref: None, 707 }, 708 Resource::Buffer { 709 buffer: dst_buffer.as_bytes().clone(), 710 range: 0..dst_buffer.size(), 711 memory: PipelineMemoryAccess { 712 stages: PipelineStages::ALL_TRANSFER, 713 access: AccessFlags::TRANSFER_WRITE, 714 exclusive: true, 715 }, 716 }, 717 )]; 718 719 for resource in &resources { 720 self.check_resource_conflicts(resource)?; 721 } 722 723 self.commands.push(Box::new(Cmd { dst_buffer, data })); 724 725 for resource in resources { 726 self.add_resource(resource); 727 } 728 729 Ok(()) 730 } 731 732 /// Calls `vkCmdUpdateBuffer` on the builder. update_buffer<D, Dd>( &mut self, dst_buffer: Subbuffer<D>, data: Dd, ) -> Result<(), SyncCommandBufferBuilderError> where D: BufferContents + ?Sized, Dd: SafeDeref<Target = D> + Send + Sync + 'static,733 pub unsafe fn update_buffer<D, Dd>( 734 &mut self, 735 dst_buffer: Subbuffer<D>, 736 data: Dd, 737 ) -> Result<(), SyncCommandBufferBuilderError> 738 where 739 D: BufferContents + ?Sized, 740 Dd: SafeDeref<Target = D> + Send + Sync + 'static, 741 { 742 struct Cmd<D: ?Sized, Dd> { 743 dst_buffer: Subbuffer<D>, 744 data: Dd, 745 } 746 747 impl<D, Dd> Command for Cmd<D, Dd> 748 where 749 D: BufferContents + ?Sized, 750 Dd: SafeDeref<Target = D> + Send + Sync + 'static, 751 { 752 fn name(&self) -> &'static str { 753 "update_buffer" 754 } 755 756 unsafe fn send(&self, out: &mut UnsafeCommandBufferBuilder) { 757 out.update_buffer(&self.dst_buffer, self.data.deref()); 758 } 759 } 760 761 let command_index = self.commands.len(); 762 let command_name = "update_buffer"; 763 let resources = [( 764 ResourceUseRef { 765 command_index, 766 command_name, 767 resource_in_command: ResourceInCommand::Destination, 768 secondary_use_ref: None, 769 }, 770 Resource::Buffer { 771 buffer: dst_buffer.as_bytes().clone(), 772 range: 0..size_of_val(data.deref()) as DeviceSize, 773 memory: PipelineMemoryAccess { 774 stages: PipelineStages::ALL_TRANSFER, 775 access: AccessFlags::TRANSFER_WRITE, 776 exclusive: true, 777 }, 778 }, 779 )]; 780 781 for resource in &resources { 782 self.check_resource_conflicts(resource)?; 783 } 784 785 self.commands.push(Box::new(Cmd { dst_buffer, data })); 786 787 for resource in resources { 788 self.add_resource(resource); 789 } 790 791 Ok(()) 792 } 793 } 794 795 impl UnsafeCommandBufferBuilder { 796 /// Calls `vkCmdClearColorImage` on the builder. 797 /// 798 /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid 799 /// usage of the command anyway. 800 #[inline] clear_color_image(&mut self, clear_info: &ClearColorImageInfo)801 pub unsafe fn clear_color_image(&mut self, clear_info: &ClearColorImageInfo) { 802 let &ClearColorImageInfo { 803 ref image, 804 image_layout, 805 clear_value, 806 ref regions, 807 _ne: _, 808 } = clear_info; 809 810 if regions.is_empty() { 811 return; 812 } 813 814 let clear_value = clear_value.into(); 815 let ranges: SmallVec<[_; 8]> = regions 816 .iter() 817 .cloned() 818 .map(ash::vk::ImageSubresourceRange::from) 819 .collect(); 820 821 let fns = self.device.fns(); 822 (fns.v1_0.cmd_clear_color_image)( 823 self.handle, 824 image.inner().image.handle(), 825 image_layout.into(), 826 &clear_value, 827 ranges.len() as u32, 828 ranges.as_ptr(), 829 ); 830 } 831 832 /// Calls `vkCmdClearDepthStencilImage` on the builder. 833 /// 834 /// Does nothing if the list of regions is empty, as it would be a no-op and isn't a valid 835 /// usage of the command anyway. 836 #[inline] clear_depth_stencil_image(&mut self, clear_info: &ClearDepthStencilImageInfo)837 pub unsafe fn clear_depth_stencil_image(&mut self, clear_info: &ClearDepthStencilImageInfo) { 838 let &ClearDepthStencilImageInfo { 839 ref image, 840 image_layout, 841 clear_value, 842 ref regions, 843 _ne: _, 844 } = clear_info; 845 846 if regions.is_empty() { 847 return; 848 } 849 850 let clear_value = clear_value.into(); 851 let ranges: SmallVec<[_; 8]> = regions 852 .iter() 853 .cloned() 854 .map(ash::vk::ImageSubresourceRange::from) 855 .collect(); 856 857 let fns = self.device.fns(); 858 (fns.v1_0.cmd_clear_depth_stencil_image)( 859 self.handle, 860 image.inner().image.handle(), 861 image_layout.into(), 862 &clear_value, 863 ranges.len() as u32, 864 ranges.as_ptr(), 865 ); 866 } 867 868 /// Calls `vkCmdFillBuffer` on the builder. 869 #[inline] fill_buffer(&mut self, dst_buffer: &Subbuffer<[u32]>, data: u32)870 pub unsafe fn fill_buffer(&mut self, dst_buffer: &Subbuffer<[u32]>, data: u32) { 871 let fns = self.device.fns(); 872 (fns.v1_0.cmd_fill_buffer)( 873 self.handle, 874 dst_buffer.buffer().handle(), 875 dst_buffer.offset(), 876 dst_buffer.size(), 877 data, 878 ); 879 } 880 881 /// Calls `vkCmdUpdateBuffer` on the builder. update_buffer<D>(&mut self, dst_buffer: &Subbuffer<D>, data: &D) where D: BufferContents + ?Sized,882 pub unsafe fn update_buffer<D>(&mut self, dst_buffer: &Subbuffer<D>, data: &D) 883 where 884 D: BufferContents + ?Sized, 885 { 886 let fns = self.device.fns(); 887 (fns.v1_0.cmd_update_buffer)( 888 self.handle, 889 dst_buffer.buffer().handle(), 890 dst_buffer.offset(), 891 size_of_val(data) as DeviceSize, 892 data as *const _ as *const _, 893 ); 894 } 895 } 896 897 /// Parameters to clear a color image. 898 #[derive(Clone, Debug)] 899 pub struct ClearColorImageInfo { 900 /// The image to clear. 901 /// 902 /// There is no default value. 903 pub image: Arc<dyn ImageAccess>, 904 905 /// The layout used for `image` during the clear operation. 906 /// 907 /// The following layouts are allowed: 908 /// - [`ImageLayout::TransferDstOptimal`] 909 /// - [`ImageLayout::General`] 910 /// 911 /// The default value is [`ImageLayout::TransferDstOptimal`]. 912 pub image_layout: ImageLayout, 913 914 /// The color value to clear the image to. 915 /// 916 /// The default value is `ClearColorValue::Float([0.0; 4])`. 917 pub clear_value: ClearColorValue, 918 919 /// The subresource ranges of `image` to clear. 920 /// 921 /// The default value is a single region, covering the whole image. 922 pub regions: SmallVec<[ImageSubresourceRange; 1]>, 923 924 pub _ne: crate::NonExhaustive, 925 } 926 927 impl ClearColorImageInfo { 928 /// Returns a `ClearColorImageInfo` with the specified `image`. 929 #[inline] image(image: Arc<dyn ImageAccess>) -> Self930 pub fn image(image: Arc<dyn ImageAccess>) -> Self { 931 let range = image.subresource_range(); 932 933 Self { 934 image, 935 image_layout: ImageLayout::TransferDstOptimal, 936 clear_value: ClearColorValue::Float([0.0; 4]), 937 regions: smallvec![range], 938 _ne: crate::NonExhaustive(()), 939 } 940 } 941 } 942 943 /// Parameters to clear a depth/stencil image. 944 #[derive(Clone, Debug)] 945 pub struct ClearDepthStencilImageInfo { 946 /// The image to clear. 947 /// 948 /// There is no default value. 949 pub image: Arc<dyn ImageAccess>, 950 951 /// The layout used for `image` during the clear operation. 952 /// 953 /// The following layouts are allowed: 954 /// - [`ImageLayout::TransferDstOptimal`] 955 /// - [`ImageLayout::General`] 956 /// 957 /// The default value is [`ImageLayout::TransferDstOptimal`]. 958 pub image_layout: ImageLayout, 959 960 /// The depth/stencil values to clear the image to. 961 /// 962 /// The default value is zero for both. 963 pub clear_value: ClearDepthStencilValue, 964 965 /// The subresource ranges of `image` to clear. 966 /// 967 /// The default value is a single region, covering the whole image. 968 pub regions: SmallVec<[ImageSubresourceRange; 1]>, 969 970 pub _ne: crate::NonExhaustive, 971 } 972 973 impl ClearDepthStencilImageInfo { 974 /// Returns a `ClearDepthStencilImageInfo` with the specified `image`. 975 #[inline] image(image: Arc<dyn ImageAccess>) -> Self976 pub fn image(image: Arc<dyn ImageAccess>) -> Self { 977 let range = image.subresource_range(); 978 979 Self { 980 image, 981 image_layout: ImageLayout::TransferDstOptimal, 982 clear_value: ClearDepthStencilValue::default(), 983 regions: smallvec![range], 984 _ne: crate::NonExhaustive(()), 985 } 986 } 987 } 988 989 /// Error that can happen when recording a clear command. 990 #[derive(Clone, Debug)] 991 pub enum ClearError { 992 SyncCommandBufferBuilderError(SyncCommandBufferBuilderError), 993 994 RequirementNotMet { 995 required_for: &'static str, 996 requires_one_of: RequiresOneOf, 997 }, 998 999 /// Operation forbidden inside of a render pass. 1000 ForbiddenInsideRenderPass, 1001 1002 /// The queue family doesn't allow this operation. 1003 NotSupportedByQueueFamily, 1004 1005 /// The end of the range of accessed array layers of the subresource range of a region is 1006 /// greater than the number of array layers in the image. 1007 ArrayLayersOutOfRange { 1008 region_index: usize, 1009 array_layers_range_end: u32, 1010 image_array_layers: u32, 1011 }, 1012 1013 /// The aspects of the subresource range of a region contain aspects that are not present 1014 /// in the image, or that are not allowed. 1015 AspectsNotAllowed { 1016 region_index: usize, 1017 aspects: ImageAspects, 1018 allowed_aspects: ImageAspects, 1019 }, 1020 1021 /// The provided data has a size larger than the maximum allowed. 1022 DataTooLarge { 1023 size: DeviceSize, 1024 max: DeviceSize, 1025 }, 1026 1027 /// The format of an image is not supported for this operation. 1028 FormatNotSupported { 1029 format: Format, 1030 }, 1031 1032 /// A specified image layout is not valid for this operation. 1033 ImageLayoutInvalid { 1034 image_layout: ImageLayout, 1035 }, 1036 1037 /// The end of the range of accessed mip levels of the subresource range of a region is greater 1038 /// than the number of mip levels in the image. 1039 MipLevelsOutOfRange { 1040 region_index: usize, 1041 mip_levels_range_end: u32, 1042 image_mip_levels: u32, 1043 }, 1044 1045 /// An image does not have a required format feature. 1046 MissingFormatFeature { 1047 format_feature: &'static str, 1048 }, 1049 1050 /// A resource did not have a required usage enabled. 1051 MissingUsage { 1052 usage: &'static str, 1053 }, 1054 1055 /// The buffer offset of a region is not a multiple of the required buffer alignment. 1056 OffsetNotAlignedForBuffer { 1057 region_index: usize, 1058 offset: DeviceSize, 1059 required_alignment: DeviceSize, 1060 }, 1061 1062 /// The end of the range of accessed byte offsets of a region is greater than the size of the 1063 /// buffer. 1064 RegionOutOfBufferBounds { 1065 region_index: usize, 1066 offset_range_end: DeviceSize, 1067 buffer_size: DeviceSize, 1068 }, 1069 1070 /// The buffer size of a region is not a multiple of the required buffer alignment. 1071 SizeNotAlignedForBuffer { 1072 region_index: usize, 1073 size: DeviceSize, 1074 required_alignment: DeviceSize, 1075 }, 1076 } 1077 1078 impl Error for ClearError { source(&self) -> Option<&(dyn Error + 'static)>1079 fn source(&self) -> Option<&(dyn Error + 'static)> { 1080 match self { 1081 Self::SyncCommandBufferBuilderError(err) => Some(err), 1082 _ => None, 1083 } 1084 } 1085 } 1086 1087 impl Display for ClearError { fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError>1088 fn fmt(&self, f: &mut Formatter<'_>) -> Result<(), FmtError> { 1089 match self { 1090 Self::SyncCommandBufferBuilderError(_) => write!(f, "a SyncCommandBufferBuilderError"), 1091 Self::RequirementNotMet { 1092 required_for, 1093 requires_one_of, 1094 } => write!( 1095 f, 1096 "a requirement was not met for: {}; requires one of: {}", 1097 required_for, requires_one_of, 1098 ), 1099 Self::ForbiddenInsideRenderPass => { 1100 write!(f, "operation forbidden inside of a render pass") 1101 } 1102 Self::NotSupportedByQueueFamily => { 1103 write!(f, "the queue family doesn't allow this operation") 1104 } 1105 Self::ArrayLayersOutOfRange { 1106 region_index, 1107 array_layers_range_end, 1108 image_array_layers, 1109 } => write!( 1110 f, 1111 "the end of the range of accessed array layers ({}) of the subresource range of \ 1112 region {} is greater than the number of array layers in the image ({})", 1113 array_layers_range_end, region_index, image_array_layers, 1114 ), 1115 Self::AspectsNotAllowed { 1116 region_index, 1117 aspects, 1118 allowed_aspects, 1119 } => write!( 1120 f, 1121 "the aspects ({:?}) of the subresource range of region {} contain aspects that \ 1122 are not present in the image, or that are not allowed ({:?})", 1123 aspects, region_index, allowed_aspects, 1124 ), 1125 Self::DataTooLarge { size, max } => write!( 1126 f, 1127 "the provided data has a size ({}) greater than the maximum allowed ({})", 1128 size, max, 1129 ), 1130 Self::FormatNotSupported { format } => write!( 1131 f, 1132 "the format of the image ({:?}) is not supported for this operation", 1133 format, 1134 ), 1135 Self::ImageLayoutInvalid { image_layout } => write!( 1136 f, 1137 "the specified image layout {:?} is not valid for this operation", 1138 image_layout, 1139 ), 1140 Self::MipLevelsOutOfRange { 1141 region_index, 1142 mip_levels_range_end, 1143 image_mip_levels, 1144 } => write!( 1145 f, 1146 "the end of the range of accessed mip levels ({}) of the subresource range of \ 1147 region {} is not less than the number of mip levels in the image ({})", 1148 mip_levels_range_end, region_index, image_mip_levels, 1149 ), 1150 Self::MissingFormatFeature { format_feature } => write!( 1151 f, 1152 "the image does not have the required format feature {}", 1153 format_feature, 1154 ), 1155 Self::MissingUsage { usage } => write!( 1156 f, 1157 "the resource did not have the required usage {} enabled", 1158 usage, 1159 ), 1160 Self::OffsetNotAlignedForBuffer { 1161 region_index, 1162 offset, 1163 required_alignment, 1164 } => write!( 1165 f, 1166 "the buffer offset ({}) of region {} is not a multiple of the required \ 1167 buffer alignment ({})", 1168 offset, region_index, required_alignment, 1169 ), 1170 Self::RegionOutOfBufferBounds { 1171 region_index, 1172 offset_range_end, 1173 buffer_size, 1174 } => write!( 1175 f, 1176 "the end of the range of accessed byte offsets ({}) of region {} is greater \ 1177 than the size of the buffer ({})", 1178 offset_range_end, region_index, buffer_size, 1179 ), 1180 Self::SizeNotAlignedForBuffer { 1181 region_index, 1182 size, 1183 required_alignment, 1184 } => write!( 1185 f, 1186 "the buffer size ({}) of region {} is not a multiple of the required buffer \ 1187 alignment ({})", 1188 size, region_index, required_alignment, 1189 ), 1190 } 1191 } 1192 } 1193 1194 impl From<SyncCommandBufferBuilderError> for ClearError { from(err: SyncCommandBufferBuilderError) -> Self1195 fn from(err: SyncCommandBufferBuilderError) -> Self { 1196 Self::SyncCommandBufferBuilderError(err) 1197 } 1198 } 1199 1200 impl From<RequirementNotMet> for ClearError { from(err: RequirementNotMet) -> Self1201 fn from(err: RequirementNotMet) -> Self { 1202 Self::RequirementNotMet { 1203 required_for: err.required_for, 1204 requires_one_of: err.requires_one_of, 1205 } 1206 } 1207 } 1208