diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 98a0943bcb253142c836cdfd13623a13f18c2871..f8e35ccbfa6eda1143c1293eb3a0ae947b6760d7 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -32,11 +32,15 @@ namespace vkcv {
 
 		[[nodiscard]]
 		vkcv::ImageHandle getHandle() const;
-		
+
+		[[nodiscard]]
+		uint32_t getMipCount();
+
 		void switchLayout(vk::ImageLayout newLayout);
 		
 		void fill(void* data, size_t size = SIZE_MAX);
 		void generateMipChainImmediate();
+		void recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream);
 	private:
 		ImageManager* const m_manager;
 		const ImageHandle   m_handle;
diff --git a/projects/voxelization/src/Voxelization.cpp b/projects/voxelization/src/Voxelization.cpp
index e471eea637093e746181e1895ec90df3876edae2..a101a03aae245701fcc097b677cd486fa4445561 100644
--- a/projects/voxelization/src/Voxelization.cpp
+++ b/projects/voxelization/src/Voxelization.cpp
@@ -70,7 +70,7 @@ Voxelization::Voxelization(
 	vkcv::SamplerHandle shadowSampler)
 	:
 	m_corePtr(corePtr), 
-	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, false, true)),
+	m_voxelImage(m_corePtr->createImage(vk::Format::eR16G16B16A16Sfloat, voxelResolution, voxelResolution, voxelResolution, true, true)),
 	m_dummyRenderTarget(m_corePtr->createImage(voxelizationDummyFormat, voxelResolution, voxelResolution, 1, false, false, true)),
 	m_voxelInfoBuffer(m_corePtr->createBuffer<VoxelizationInfo>(vkcv::BufferType::UNIFORM, 1)),
 	m_voxelBuffer(m_corePtr->createBuffer<VoxelBufferContent>(vkcv::BufferType::STORAGE, voxelCount)){
@@ -272,6 +272,8 @@ void Voxelization::voxelizeMeshes(
 		vkcv::PushConstantData(nullptr, 0));
 
 	m_corePtr->recordImageMemoryBarrier(cmdStream, m_voxelImage.getHandle());
+
+	m_voxelImage.recordMipChainGeneration(cmdStream);
 }
 
 void Voxelization::renderVoxelVisualisation(
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index dca6358b84aa7bcd0f38e78d3fa7aa49fd11395d..0a3353f7248fc417c9f49701be7d5f81455ad667 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -64,6 +64,10 @@ namespace vkcv{
 	void Image::generateMipChainImmediate() {
 		m_manager->generateImageMipChainImmediate(m_handle);
 	}
+
+	void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle& cmdStream) {
+		m_manager->recordImageMipChainGenerationToCmdStream(cmdStream, m_handle);
+	}
 	
 	Image::Image(ImageManager* manager, const ImageHandle& handle) :
 		m_manager(manager),
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index dd54da39cfe1d832e006e4f673e6aa8e1eb7ee18..14d7c506a526634a894163e387a8504b0d48241b 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -438,6 +438,60 @@ namespace vkcv {
 		);
 	}
 
+	void ImageManager::recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, const ImageHandle& handle) {
+
+		const auto id = handle.getId();
+		if (id >= m_images.size()) {
+			vkcv_log(vkcv::LogLevel::ERROR, "Invalid image handle");
+			return;
+		}
+
+		auto& image = m_images[id];
+		recordImageLayoutTransition(handle, vk::ImageLayout::eGeneral, cmdBuffer);
+
+		vk::ImageAspectFlags aspectMask = isDepthImageFormat(image.m_format) ?
+			vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor;
+
+		uint32_t srcWidth = image.m_width;
+		uint32_t srcHeight = image.m_height;
+		uint32_t srcDepth = image.m_depth;
+
+		auto half = [](uint32_t in) {
+			return std::max<uint32_t>(in / 2, 1);
+		};
+
+		uint32_t dstWidth = half(srcWidth);
+		uint32_t dstHeight = half(srcHeight);
+		uint32_t dstDepth = half(srcDepth);
+
+		for (uint32_t srcMip = 0; srcMip < image.m_viewPerMip.size() - 1; srcMip++) {
+			uint32_t dstMip = srcMip + 1;
+			vk::ImageBlit region(
+				vk::ImageSubresourceLayers(aspectMask, srcMip, 0, 1),
+				{ vk::Offset3D(0, 0, 0), vk::Offset3D(srcWidth, srcHeight, srcDepth) },
+				vk::ImageSubresourceLayers(aspectMask, dstMip, 0, 1),
+				{ vk::Offset3D(0, 0, 0), vk::Offset3D(dstWidth, dstHeight, dstDepth) });
+
+			cmdBuffer.blitImage(
+				image.m_handle,
+				vk::ImageLayout::eGeneral,
+				image.m_handle,
+				vk::ImageLayout::eGeneral,
+				region,
+				vk::Filter::eLinear);
+
+			srcWidth = dstWidth;
+			srcHeight = dstHeight;
+			srcDepth = dstDepth;
+
+			dstWidth = half(dstWidth);
+			dstHeight = half(dstHeight);
+			dstDepth = half(dstDepth);
+
+			recordImageMemoryBarrier(handle, cmdBuffer);
+		}
+	}
+
 	void ImageManager::generateImageMipChainImmediate(const ImageHandle& handle) {
 
 		const auto& device = m_core->getContext().getDevice();
@@ -450,62 +504,23 @@ namespace vkcv {
 			return;
 		}
 
-		const auto id = handle.getId();
-		if (id >= m_images.size()) {
-			vkcv_log(vkcv::LogLevel::ERROR, "Invalid image handle");
-			return;
-		}
-		auto& image = m_images[id];
-		switchImageLayoutImmediate(handle, vk::ImageLayout::eGeneral);
-
-		const auto record = [&image, this, handle](const vk::CommandBuffer cmdBuffer) {
-
-			vk::ImageAspectFlags aspectMask = isDepthImageFormat(image.m_format) ?
-				vk::ImageAspectFlagBits::eDepth : vk::ImageAspectFlagBits::eColor;
-
-			uint32_t srcWidth   = image.m_width;
-			uint32_t srcHeight  = image.m_height;
-			uint32_t srcDepth   = image.m_depth;
-
-			auto half = [](uint32_t in) {
-				return std::max<uint32_t>(in / 2, 1);
-			};
-
-			uint32_t dstWidth   = half(image.m_width);
-			uint32_t dstHeight  = half(image.m_height);
-			uint32_t dstDepth   = half(image.m_depth);
-
-			for (uint32_t srcMip = 0; srcMip < image.m_viewPerMip.size() - 1; srcMip++) {
-				uint32_t dstMip = srcMip + 1;
-				vk::ImageBlit region(
-					vk::ImageSubresourceLayers(aspectMask, srcMip, 0, 1),
-					{ vk::Offset3D(0, 0, 0), vk::Offset3D(srcWidth, srcHeight, srcDepth) },
-					vk::ImageSubresourceLayers(aspectMask, dstMip, 0, 1),
-					{ vk::Offset3D(0, 0, 0), vk::Offset3D(dstWidth, dstHeight, dstDepth) });
-
-				cmdBuffer.blitImage(
-					image.m_handle,
-					vk::ImageLayout::eGeneral,
-					image.m_handle,
-					vk::ImageLayout::eGeneral,
-					region,
-					vk::Filter::eLinear);
-
-				srcWidth    = dstWidth;
-				srcHeight   = dstHeight;
-				srcDepth    = dstDepth;
-
-				dstWidth    = half(dstWidth);
-				dstHeight   = half(dstHeight);
-				dstDepth    = half(dstDepth);
-				
-				recordImageMemoryBarrier(handle, cmdBuffer);
-			}
+		const auto record = [this, handle](const vk::CommandBuffer cmdBuffer) {
+			recordImageMipGenerationToCmdBuffer(cmdBuffer, handle);
 		};
 
 		m_core->recordAndSubmitCommandsImmediate(submitInfo, record, nullptr);
 	}
 
+	void ImageManager::recordImageMipChainGenerationToCmdStream(
+		const vkcv::CommandStreamHandle& cmdStream,
+		const ImageHandle& handle) {
+
+		const auto record = [this, handle](const vk::CommandBuffer cmdBuffer) {
+			recordImageMipGenerationToCmdBuffer(cmdBuffer, handle);
+		};
+		m_core->recordCommandsToStream(cmdStream, record, nullptr);
+	}
+
 	uint32_t ImageManager::getImageWidth(const ImageHandle &handle) const {
 		const uint64_t id = handle.getId();
 		const bool isSwapchainImage = handle.isSwapchainImage();
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 69ab7943f34bcf3579a4384cbd59e78e5b7aacdf..9cd1a8dec6d37af7e01273993cc6a38c06b68ce6 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -60,7 +60,9 @@ namespace vkcv {
 		 * @param id Image handle id
 		 */
 		void destroyImageById(uint64_t id);
-		
+
+		void recordImageMipGenerationToCmdBuffer(vk::CommandBuffer cmdBuffer, const ImageHandle& handle);
+
 	public:
 		~ImageManager() noexcept;
 		ImageManager(ImageManager&& other) = delete;
@@ -101,6 +103,7 @@ namespace vkcv {
 
 		void fillImage(const ImageHandle& handle, void* data, size_t size);
 		void generateImageMipChainImmediate(const ImageHandle& handle);
+		void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle& cmdStream, const ImageHandle& handle);
 		
 		[[nodiscard]]
 		uint32_t getImageWidth(const ImageHandle& handle) const;