/// Transition the texture usage. A `subresource_range` of `None` indicates the whole texture.
Transition the texture usage. A `subresource_range` of `None` indicates the whole texture.
Transition the texture usage . A ` subresource_range ` of ` None ` indicates the whole texture .
pub fn transition_usage_now(
        &self,
        command_buffer: vk::CommandBuffer,
        usage: TextureUsage,
        subresource: Option<Subresource>,
    ) -> Result<(), Error> {
        let format = self.descriptor.format;
        // log2(32768) + 1 = 16; enough barriers on the stack for a non-array image with mipmaps, up to 32768 x 32768
        let mut image_memory_barriers = SmallVec::<[vk::ImageMemoryBarrier; 16]>::new();
        let mut src_stage_mask = vk::PipelineStageFlags::empty();
        let dst_stage_mask = pipeline_stage(usage, format);
        let mut add_image_memory_barrier = |range: vk::ImageSubresourceRange, range_last_usage: &mut TextureUsage| {
            // TODO: Add a version of this optimization back at the "whole texture" level.
            //       Example: If we're only repeatedly requesting that the image is SAMPLED,
            //       there's no need to iterate all of the subresources every time.
            let last_read_only = (*range_last_usage & read_only_texture_usage()) == *range_last_usage;
            if last_read_only && *range_last_usage == usage {
                return;
            }
            src_stage_mask |= pipeline_stage(*range_last_usage, format);
            let src_access_mask = access_flags(*range_last_usage, format);
            let dst_access_mask = access_flags(usage, format);
            let old_layout = image_layout(*range_last_usage, format);
            let new_layout = image_layout(usage, format);
            // TODO: We should probably set old_layout to UNDEFINED as an optimization when
            //       new_layout is TRANSFER_DST_OPTIMAL
            let image_memory_barrier = vk::ImageMemoryBarrier {
                src_access_mask,
                dst_access_mask,
                old_layout,
                new_layout,
                image: self.handle,
                subresource_range: range,
                src_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
                dst_queue_family_index: vk::QUEUE_FAMILY_IGNORED,
                ..Default::default()
            };
            log::trace!(
                concat!(
                    "mip_level: {}, array_layer: {}, ",
                    "old_usage: {:?}, old_layout: {:?}, src_stage_mask: {:?}, src_access_mask: {:?}, ",
                    "new_usage: {:?}, new_layout: {:?}, dst_stage_mask: {:?}, dst_access_mask: {:?}"
                ),
                image_memory_barrier.subresource_range.base_mip_level,
                image_memory_barrier.subresource_range.base_array_layer,
                *range_last_usage,
                image_memory_barrier.old_layout,
                src_stage_mask,
                image_memory_barrier.src_access_mask,
                usage,
                image_memory_barrier.new_layout,
                dst_stage_mask,
                image_memory_barrier.dst_access_mask,
            );
            *range_last_usage = usage;
            image_memory_barriers.push(image_memory_barrier);
        };
        match subresource {
            Some(subresource) => {
                let mut subresource_usage = self.subresource_usage.lock();
                let (range, range_last_usage) = subresource_usage.usage_mut(subresource);
                add_image_memory_barrier(range, range_last_usage);
            }
            None => {
                for (range, range_last_usage) in self.subresource_usage.lock().iter_mut() {
                    add_image_memory_barrier(range, range_last_usage);
                }
            }
        }
        if !image_memory_barriers.is_empty() {
            let dependency_flags = vk::DependencyFlags::empty();
            let memory_barriers = &[];
            let buffer_memory_barriers = &[];
            let image_memory_barriers: &[vk::ImageMemoryBarrier] = &*image_memory_barriers;
            unsafe {
                self.device.raw.cmd_pipeline_barrier(
                    command_buffer,
                    src_stage_mask,
                    dst_stage_mask,
                    dependency_flags,
                    memory_barriers,
                    buffer_memory_barriers,
                    image_memory_barriers,
                );
            }
        }
        Ok(())
    }
pub fn transition_usage_now ( & self , command_buffer : vk :: CommandBuffer , usage : TextureUsage , subresource : Option < Subresource > , ) -> Result < ( ) , Error > { let format = self . descriptor . format ; // log2(32768) + 1 = 16; enough barriers on the stack for a non-array image with mipmaps, up to 32768 x 32768 let mut image_memory_barriers = SmallVec :: < [ vk :: ImageMemoryBarrier ; 16 ] > :: new ( ) ; let mut src_stage_mask = vk :: PipelineStageFlags :: empty ( ) ; let dst_stage_mask = pipeline_stage ( usage , format ) ; let mut add_image_memory_barrier = | range : vk :: ImageSubresourceRange , range_last_usage : & mut TextureUsage | { // TODO: Add a version of this optimization back at the "whole texture" level. //       Example: If we're only repeatedly requesting that the image is SAMPLED, //       there's no need to iterate all of the subresources every time. let last_read_only = ( * range_last_usage & read_only_texture_usage ( ) ) == * range_last_usage ; if last_read_only && * range_last_usage == usage { return ; } src_stage_mask |= pipeline_stage ( * range_last_usage , format ) ; let src_access_mask = access_flags ( * range_last_usage , format ) ; let dst_access_mask = access_flags ( usage , format ) ; let old_layout = image_layout ( * range_last_usage , format ) ; let new_layout = image_layout ( usage , format ) ; // TODO: We should probably set old_layout to UNDEFINED as an optimization when //       new_layout is TRANSFER_DST_OPTIMAL let image_memory_barrier = vk :: ImageMemoryBarrier { src_access_mask , dst_access_mask , old_layout , new_layout , image : self . handle , subresource_range : range , src_queue_family_index : vk :: QUEUE_FAMILY_IGNORED , dst_queue_family_index : vk :: QUEUE_FAMILY_IGNORED , .. Default :: default ( ) } ; log :: trace ! ( concat ( " " " " " " ) image_memory_barrier subresource_range base_mip_level image_memory_barrier subresource_range base_array_layer range_last_usage image_memory_barrier old_layout src_stage_mask image_memory_barrier src_access_mask usage image_memory_barrier new_layout dst_stage_mask image_memory_barrier dst_access_mask ) ; * range_last_usage = usage ; image_memory_barriers . push ( image_memory_barrier ) ; } ; match subresource { Some ( subresource ) => { let mut subresource_usage = self . subresource_usage . lock ( ) ; let ( range , range_last_usage ) = subresource_usage . usage_mut ( subresource ) ; add_image_memory_barrier ( range , range_last_usage ) ; } None => { for ( range , range_last_usage ) in self . subresource_usage . lock ( ) . iter_mut ( ) { add_image_memory_barrier ( range , range_last_usage ) ; } } } if ! image_memory_barriers . is_empty ( ) { let dependency_flags = vk :: DependencyFlags :: empty ( ) ; let memory_barriers = & [ ] ; let buffer_memory_barriers = & [ ] ; let image_memory_barriers : & [ vk :: ImageMemoryBarrier ] = & * image_memory_barriers ; unsafe { self . device . raw . cmd_pipeline_barrier ( command_buffer , src_stage_mask , dst_stage_mask , dependency_flags , memory_barriers , buffer_memory_barriers , image_memory_barriers , ) ; } } Ok ( ( ) ) }
Transition the texture usage.
Transition the texture usage .
&self
command_buffer
vk::CommandBuffer
usage
TextureUsage
subresource
Option<Subresource>