/* CommandBuffer, ImageArray and Image are structs to wrap vulkan functions in a rustic way. */ fn copy_images_to_imagearray( command_buffer: &Arc, image_array: &Arc, images: &Vec>, ) -> Result<(), String> { let device = global_context().device(); // start recording of command buffer if let Err(msg) = command_buffer.begin(VkCommandBufferBeginInfo::new( VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT, )) { return Err(msg); } // subresource range of target (ImageArray) let array_subresource_range = VkImageSubresourceRange { aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel: 0, levelCount: 1, baseArrayLayer: 0, layerCount: images.len() as u32, }; // subresource range of source (Image) let subresource_range = VkImageSubresourceRange { aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel: 0, levelCount: 1, baseArrayLayer: 0, layerCount: 1, }; // pipeline barrier for target (ImageArray) command_buffer.set_image_array_layout( image_array, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, array_subresource_range.clone(), ); // iterate over every source image for (i, image) in images.iter().enumerate() { // create copy info let image_copy = VkImageCopy { srcSubresource: VkImageSubresourceLayers { aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, mipLevel: 0, baseArrayLayer: 0, layerCount: 1, }, srcOffset: VkOffset3D { x: 0, y: 0, z: 0 }, dstSubresource: VkImageSubresourceLayers { aspectMask: VK_IMAGE_ASPECT_COLOR_BIT, mipLevel: 0, baseArrayLayer: i as u32, layerCount: 1, }, dstOffset: VkOffset3D { x: 0, y: 0, z: 0 }, extent: VkExtent3D { width: image.width(), height: image.height(), depth: 1, }, }; // pipeline barrier for source (Image) command_buffer.set_image_layout( image, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, subresource_range.clone(), ); // copy the data to the specified layer command_buffer.copy_image( image.vk_image(), image_array.vk_image(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &vec![image_copy], ); // pipeline barrier for source (Image) command_buffer.set_image_layout( image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, subresource_range.clone(), ); } // pipeline barrier for target (ImageArray) command_buffer.set_image_array_layout( image_array, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, array_subresource_range, ); // end recording of command buffer if let Err(msg) = command_buffer.end() { return Err(msg); } // submit current queue if let Err(msg) = device.queue_submit( None, Vec::new(), Vec::new(), vec![command_buffer.clone()], Vec::new(), ) { return Err(msg); } if let Err(msg) = device.queue_wait_idle() { return Err(msg); } Ok(()) } // sub set of command buffer functions impl CommandBuffer { pub fn set_image_layout( &self, image: &Arc, old_image_layout: VkImageLayout, new_image_layout: VkImageLayout, subresource_range: VkImageSubresourceRange, ) { self.set_vk_image_layout( image.vk_image(), old_image_layout, new_image_layout, subresource_range, ); } fn set_image_array_layout( &self, image_array: &Arc, old_image_layout: VkImageLayout, new_image_layout: VkImageLayout, subresource_range: VkImageSubresourceRange, ) { self.set_vk_image_layout( image_array.vk_image(), old_image_layout, new_image_layout, subresource_range, ); } fn set_vk_image_layout( &self, image: VkImage, old_image_layout: VkImageLayout, new_image_layout: VkImageLayout, subresource_range: VkImageSubresourceRange, ) { self.pipeline_barrier( match old_image_layout { VK_IMAGE_LAYOUT_UNDEFINED => VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_IMAGE_LAYOUT_PREINITIALIZED => VK_PIPELINE_STAGE_HOST_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL => VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL => VK_PIPELINE_STAGE_TRANSFER_BIT, _ => panic!( "old image layout not supported {}", stringify!(old_image_layout) ), }, match new_image_layout { VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL => VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL => VK_PIPELINE_STAGE_TRANSFER_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL => VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, _ => panic!( "new image layout not supported {}", stringify!(new_image_layout) ), }, 0, vec![VkImageMemoryBarrier::new( match old_image_layout { VK_IMAGE_LAYOUT_UNDEFINED => 0, VK_IMAGE_LAYOUT_PREINITIALIZED => VK_ACCESS_HOST_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL => VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL => VK_ACCESS_TRANSFER_READ_BIT, _ => panic!( "old image layout not supported {}", stringify!(old_image_layout) ), }, match new_image_layout { VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL => VK_ACCESS_TRANSFER_READ_BIT, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL => VK_ACCESS_TRANSFER_WRITE_BIT, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL => VK_ACCESS_SHADER_READ_BIT, _ => panic!( "new image layout not supported {}", stringify!(new_image_layout) ), }, VK_QUEUE_FAMILY_IGNORED, VK_QUEUE_FAMILY_IGNORED, old_image_layout, new_image_layout, image, subresource_range, )], Vec::new(), Vec::new(), ) } pub fn pipeline_barrier( &self, src_stage_mask: VkPipelineStageFlags, dst_stage_mask: VkPipelineStageFlags, dependency_flags: VkDependencyFlags, image_memory_barriers: Vec, buffer_memory_barriers: Vec, memory_barriers: Vec, ) { unsafe { vkCmdPipelineBarrier( self.buffer, src_stage_mask, dst_stage_mask, dependency_flags, memory_barriers.len() as u32, memory_barriers.as_ptr(), buffer_memory_barriers.len() as u32, buffer_memory_barriers.as_ptr(), image_memory_barriers.len() as u32, image_memory_barriers.as_ptr(), ); } } pub fn copy_image( &self, src_image: VkImage, dst_image: VkImage, src_layout: VkImageLayout, dst_layout: VkImageLayout, regions: &Vec, ) { unsafe { vkCmdCopyImage( self.buffer, src_image, src_layout, dst_image, dst_layout, regions.len() as u32, regions.as_ptr(), ) } } }