diff --git a/include/vkcv/Core.hpp b/include/vkcv/Core.hpp
index fc80436ec85967619dab6aa5a518f0986e2b4f62..1cec2a7149ab17de76f390944e27941c317cd6e6 100644
--- a/include/vkcv/Core.hpp
+++ b/include/vkcv/Core.hpp
@@ -338,8 +338,14 @@ namespace vkcv {
 		 * @param[in] image Image handle
 		 * @param[in] data Image data pointer
 		 * @param[in] size Size of data
-		 */
-		void fillImage(const ImageHandle &image, const void* data, size_t size);
+		 * @param[in] firstLayer First image layer
+		 * @param[in] layerCount Image layer count
+		 */
+		void fillImage(const ImageHandle &image,
+					   const void* data,
+					   size_t size,
+					   uint32_t firstLayer,
+					   uint32_t layerCount);
 
 		/**
 		 * @brief Switches the images layout synchronously if possible.
diff --git a/include/vkcv/Image.hpp b/include/vkcv/Image.hpp
index 511ac67102ec26e9bd92c1b9e62b42d34c784e4d..c9c91db25fb4398439d609247d71ba6be3524464 100644
--- a/include/vkcv/Image.hpp
+++ b/include/vkcv/Image.hpp
@@ -112,6 +112,17 @@ namespace vkcv {
 		 * the actual number of copied bytes is min(size, imageDataSize)
 		 */
 		void fill(const void* data, size_t size = SIZE_MAX);
+		
+		/**
+		 * @brief Fills a specific image layer with data of a given
+		 * size in bytes.
+		 *
+		 * @param[in] layer Image layer destination
+		 * @param[in] data Pointer to the source data
+		 * @param[in] size Lower limit of the data size to copy in bytes,
+		 * the actual number of copied bytes is min(size, imageDataSize)
+		 */
+		void fillLayer(uint32_t layer, const void* data, size_t size = SIZE_MAX);
 
 		/**
 		 * @brief Records mip chain generation to command stream,
diff --git a/src/vkcv/Core.cpp b/src/vkcv/Core.cpp
index 99a516ad96e6feaf90990f1be8747ff967ada9ab..7fde9196d3187f3aafa7134325ee7d166d6cd23c 100644
--- a/src/vkcv/Core.cpp
+++ b/src/vkcv/Core.cpp
@@ -879,8 +879,12 @@ namespace vkcv {
 		);
 	}
 
-	void Core::fillImage(const ImageHandle &image, const void* data, size_t size) {
-		m_ImageManager->fillImage(image, data, size);
+	void Core::fillImage(const ImageHandle &image,
+						 const void* data,
+						 size_t size,
+						 uint32_t firstLayer,
+						 uint32_t layerCount) {
+		m_ImageManager->fillImage(image, data, size, firstLayer, layerCount);
 	}
 
 	void Core::switchImageLayout(const ImageHandle &image, vk::ImageLayout layout) {
diff --git a/src/vkcv/Image.cpp b/src/vkcv/Image.cpp
index 63a395e7f8f0e590d6b2dbdde3f8d527c4d8c87b..fc6140fe4664096145aa08551422d919bcb4dc25 100644
--- a/src/vkcv/Image.cpp
+++ b/src/vkcv/Image.cpp
@@ -64,7 +64,11 @@ namespace vkcv {
 	}
 
 	void Image::fill(const void* data, size_t size) {
-		m_core->fillImage(m_handle, data, size);
+		m_core->fillImage(m_handle, data, size, 0, 0);
+	}
+	
+	void Image::fillLayer(uint32_t layer, const void* data, size_t size) {
+		m_core->fillImage(m_handle, data, size, layer, 1);
 	}
 
 	void Image::recordMipChainGeneration(const vkcv::CommandStreamHandle &cmdStream,
diff --git a/src/vkcv/ImageManager.cpp b/src/vkcv/ImageManager.cpp
index 93d78f43a0a8f0aedbb38331bff5fccdf96c7687..44022297f6a046d1efaf2b4ea80aafeded381a83 100644
--- a/src/vkcv/ImageManager.cpp
+++ b/src/vkcv/ImageManager.cpp
@@ -488,22 +488,48 @@ namespace vkcv {
 		}
 	}
 
-	void ImageManager::fillImage(const ImageHandle &handle, const void* data, size_t size) {
+	void ImageManager::fillImage(const ImageHandle &handle,
+								 const void* data,
+								 size_t size,
+								 uint32_t firstLayer,
+								 uint32_t layerCount) {
 		if (handle.isSwapchainImage()) {
 			vkcv_log(LogLevel::ERROR, "Swapchain image cannot be filled");
 			return;
 		}
 
 		auto &image = (*this) [handle];
+		
+		const uint32_t baseArrayLayer = std::min<uint32_t>(firstLayer, image.m_layers);
+		
+		if (baseArrayLayer >= image.m_layers) {
+			return;
+		}
+		
+		uint32_t arrayLayerCount;
+		
+		if (layerCount > 0) {
+			arrayLayerCount = std::min<uint32_t>(layerCount, image.m_layers);
+		} else {
+			arrayLayerCount = image.m_layers;
+		}
+		
+		if (arrayLayerCount < baseArrayLayer) {
+			return;
+		}
+		
+		arrayLayerCount -= baseArrayLayer;
 		switchImageLayoutImmediate(handle, vk::ImageLayout::eTransferDstOptimal);
 
-		const size_t image_size =
-			(image.m_width * image.m_height * image.m_depth * getBytesPerPixel(image.m_format));
+		const size_t image_size = (
+				image.m_width * image.m_height * image.m_depth * getBytesPerPixel(image.m_format)
+		);
 
 		const size_t max_size = std::min(size, image_size);
 
 		BufferHandle bufferHandle = getBufferManager().createBuffer(
-			TypeGuard(1), BufferType::STAGING, BufferMemoryType::DEVICE_LOCAL, max_size, false);
+			TypeGuard(1), BufferType::STAGING, BufferMemoryType::DEVICE_LOCAL, max_size, false
+		);
 
 		getBufferManager().fillBuffer(bufferHandle, data, max_size, 0);
 
@@ -514,7 +540,8 @@ namespace vkcv {
 
 		core.recordCommandsToStream(
 			stream,
-			[&image, &stagingBuffer](const vk::CommandBuffer &commandBuffer) {
+			[&image, &stagingBuffer, &baseArrayLayer, &arrayLayerCount]
+			(const vk::CommandBuffer &commandBuffer) {
 				vk::ImageAspectFlags aspectFlags;
 
 				if (isDepthImageFormat(image.m_format)) {
@@ -524,16 +551,26 @@ namespace vkcv {
 				}
 
 				const vk::BufferImageCopy region(
-					0, 0, 0, vk::ImageSubresourceLayers(aspectFlags, 0, 0, image.m_layers),
+					0,
+					0,
+					0,
+					vk::ImageSubresourceLayers(aspectFlags, 0, baseArrayLayer, arrayLayerCount),
 					vk::Offset3D(0, 0, 0),
-					vk::Extent3D(image.m_width, image.m_height, image.m_depth));
+					vk::Extent3D(image.m_width, image.m_height, image.m_depth)
+				);
 
-				commandBuffer.copyBufferToImage(stagingBuffer, image.m_handle,
-												vk::ImageLayout::eTransferDstOptimal, 1, &region);
+				commandBuffer.copyBufferToImage(
+						stagingBuffer,
+						image.m_handle,
+						vk::ImageLayout::eTransferDstOptimal,
+						1,
+						&region
+				);
 			},
 			[&]() {
 				switchImageLayoutImmediate(handle, vk::ImageLayout::eShaderReadOnlyOptimal);
-			});
+			}
+		);
 
 		core.submitCommandStream(stream, false);
 	}
@@ -553,17 +590,23 @@ namespace vkcv {
 		auto &dstImage = (*this) [dst];
 
 		vk::ImageResolve region(
-			vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1),
+			vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, srcImage.m_layers),
 			vk::Offset3D(0, 0, 0),
-			vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, 1),
+			vk::ImageSubresourceLayers(vk::ImageAspectFlagBits::eColor, 0, 0, dstImage.m_layers),
 			vk::Offset3D(0, 0, 0),
-			vk::Extent3D(dstImage.m_width, dstImage.m_height, dstImage.m_depth));
+			vk::Extent3D(dstImage.m_width, dstImage.m_height, dstImage.m_depth)
+		);
 
 		recordImageLayoutTransition(src, 0, 0, vk::ImageLayout::eTransferSrcOptimal, cmdBuffer);
 		recordImageLayoutTransition(dst, 0, 0, vk::ImageLayout::eTransferDstOptimal, cmdBuffer);
 
-		cmdBuffer.resolveImage(srcImage.m_handle, srcImage.m_layout, dstImage.m_handle,
-							   dstImage.m_layout, region);
+		cmdBuffer.resolveImage(
+				srcImage.m_handle,
+				srcImage.m_layout,
+				dstImage.m_handle,
+				dstImage.m_layout,
+				region
+		);
 	}
 
 	uint32_t ImageManager::getImageWidth(const ImageHandle &handle) const {
diff --git a/src/vkcv/ImageManager.hpp b/src/vkcv/ImageManager.hpp
index 5a91d962370071ac9c557ad877fd26268e1e2b2a..cbb6961f915dfee1c90409af38c61738f260a525 100644
--- a/src/vkcv/ImageManager.hpp
+++ b/src/vkcv/ImageManager.hpp
@@ -106,7 +106,11 @@ namespace vkcv {
 
 		void recordImageMemoryBarrier(const ImageHandle &handle, vk::CommandBuffer cmdBuffer);
 
-		void fillImage(const ImageHandle &handle, const void* data, size_t size);
+		void fillImage(const ImageHandle &handle,
+					   const void* data,
+					   size_t size,
+					   uint32_t firstLayer,
+					   uint32_t layerCount);
 
 		void recordImageMipChainGenerationToCmdStream(const vkcv::CommandStreamHandle &cmdStream,
 													  const ImageHandle &handle);