Ensure compressed image copy is height compliant

Image copy operations on compressed formats must have dimensions that
are multiples of the block dimensions, unless the extent dimension + its
corresponding offset is equal to the image subresource dimension.

Bug: b/168025369
Change-Id: I3e77bfefe78347d4635128ece10f9d48aef40daa
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/48188
Reviewed-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Sean Risser <srisser@google.com>
Commit-Queue: Alexis Hétu <sugoi@google.com>
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index a0287cc..596741c 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -703,6 +703,7 @@
 	VkExtent2D adjustedExtent = extent;
 	VkImageAspectFlagBits aspect = static_cast<VkImageAspectFlagBits>(region.imageSubresource.aspectMask);
 	Format usedFormat = getFormat(aspect);
+
 	if(region.bufferRowLength != 0)
 	{
 		adjustedExtent.width = region.bufferRowLength;
@@ -710,10 +711,11 @@
 		if(usedFormat.isCompressed())
 		{
 			int blockWidth = usedFormat.blockWidth();
-			ASSERT((adjustedExtent.width % blockWidth) == 0);
-			adjustedExtent.width /= blockWidth;
+			ASSERT((adjustedExtent.width % blockWidth == 0) || (adjustedExtent.width + region.imageOffset.x == extent.width));
+			adjustedExtent.width = (region.bufferRowLength + blockWidth - 1) / blockWidth;
 		}
 	}
+
 	if(region.bufferImageHeight != 0)
 	{
 		adjustedExtent.height = region.bufferImageHeight;
@@ -721,10 +723,11 @@
 		if(usedFormat.isCompressed())
 		{
 			int blockHeight = usedFormat.blockHeight();
-			ASSERT((adjustedExtent.height % blockHeight) == 0);
-			adjustedExtent.height /= blockHeight;
+			ASSERT((adjustedExtent.height % blockHeight == 0) || (adjustedExtent.height + region.imageOffset.y == extent.height));
+			adjustedExtent.height = (region.bufferImageHeight + blockHeight - 1) / blockHeight;
 		}
 	}
+
 	return adjustedExtent;
 }