vkCmdResolveImage implementation

Implemented the resolve command using the regular blit function,
since it already supports resolve operations. Removed baseArrayLayer
related checks in Image::copyTo(), since resolving array images
exercises that path.

Bug b/118619338

Change-Id: I6a70ef5f396e51be7fde34ebe72fcf991396a45f
Tests: dEQP-VK.api.copy_and_blit.core.resolve_image.*
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/28888
Presubmit-Ready: Alexis Hétu <sugoi@google.com>
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Tested-by: Alexis Hétu <sugoi@google.com>
Kokoro-Presubmit: kokoro <noreply+kokoro@google.com>
diff --git a/src/Vulkan/VkCommandBuffer.cpp b/src/Vulkan/VkCommandBuffer.cpp
index 0af06da..fa6f3d8 100644
--- a/src/Vulkan/VkCommandBuffer.cpp
+++ b/src/Vulkan/VkCommandBuffer.cpp
@@ -792,6 +792,24 @@
 	VkFilter filter;
 };
 
+struct ResolveImage : public CommandBuffer::Command
+{
+	ResolveImage(VkImage srcImage, VkImage dstImage, const VkImageResolve& region) :
+		srcImage(srcImage), dstImage(dstImage), region(region)
+	{
+	}
+
+	void play(CommandBuffer::ExecutionState& executionState) override
+	{
+		Cast(srcImage)->resolve(dstImage, region);
+	}
+
+private:
+	VkImage srcImage;
+	VkImage dstImage;
+	VkImageResolve region;
+};
+
 struct PipelineBarrier : public CommandBuffer::Command
 {
 	PipelineBarrier()
@@ -1420,7 +1438,16 @@
 void CommandBuffer::resolveImage(VkImage srcImage, VkImageLayout srcImageLayout, VkImage dstImage, VkImageLayout dstImageLayout,
 	uint32_t regionCount, const VkImageResolve* pRegions)
 {
-	UNIMPLEMENTED("resolveImage");
+	ASSERT(state == RECORDING);
+	ASSERT(srcImageLayout == VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL ||
+	       srcImageLayout == VK_IMAGE_LAYOUT_GENERAL);
+	ASSERT(dstImageLayout == VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL ||
+	       dstImageLayout == VK_IMAGE_LAYOUT_GENERAL);
+
+	for(uint32_t i = 0; i < regionCount; i++)
+	{
+		addCommand<ResolveImage>(srcImage, dstImage, pRegions[i]);
+	}
 }
 
 void CommandBuffer::setEvent(VkEvent event, VkPipelineStageFlags stageMask)
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index cce91d7..a5d8679 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -105,7 +105,6 @@
 	if(!((pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
 		 (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
 		 (pRegion.srcSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
-		 (pRegion.srcSubresource.baseArrayLayer != 0) ||
 		 (pRegion.srcSubresource.layerCount != 1))
 	{
 		UNIMPLEMENTED("srcSubresource");
@@ -114,7 +113,6 @@
 	if(!((pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT) ||
 		 (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_DEPTH_BIT) ||
 		 (pRegion.dstSubresource.aspectMask == VK_IMAGE_ASPECT_STENCIL_BIT)) ||
-		 (pRegion.dstSubresource.baseArrayLayer != 0) ||
 		 (pRegion.dstSubresource.layerCount != 1))
 	{
 		UNIMPLEMENTED("dstSubresource");
@@ -621,6 +619,26 @@
 	device->getBlitter()->blit(this, Cast(dstImage), region, filter);
 }
 
+void Image::resolve(VkImage dstImage, const VkImageResolve& region)
+{
+	VkImageBlit blitRegion;
+
+	blitRegion.srcOffsets[0] = blitRegion.srcOffsets[1] = region.srcOffset;
+	blitRegion.srcOffsets[1].x += region.extent.width;
+	blitRegion.srcOffsets[1].y += region.extent.height;
+	blitRegion.srcOffsets[1].z += region.extent.depth;
+
+	blitRegion.dstOffsets[0] = blitRegion.dstOffsets[1] = region.dstOffset;
+	blitRegion.dstOffsets[1].x += region.extent.width;
+	blitRegion.dstOffsets[1].y += region.extent.height;
+	blitRegion.dstOffsets[1].z += region.extent.depth;
+
+	blitRegion.srcSubresource = region.srcSubresource;
+	blitRegion.dstSubresource = region.dstSubresource;
+
+	device->getBlitter()->blit(this, Cast(dstImage), blitRegion, VK_FILTER_NEAREST);
+}
+
 VkFormat Image::getClearFormat() const
 {
 	// Set the proper format for the clear value, as described here:
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index dffccbb..0ad40a5 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -47,6 +47,7 @@
 	void copyFrom(VkBuffer srcBuffer, const VkBufferImageCopy& region);
 
 	void blit(VkImage dstImage, const VkImageBlit& region, VkFilter filter);
+	void resolve(VkImage dstImage, const VkImageResolve& region);
 	void clear(const VkClearValue& clearValue, const vk::Format& viewFormat, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange);
 	void clear(const VkClearDepthStencilValue& color, const VkImageSubresourceRange& subresourceRange);