Fix decompression of cube-compatible layered 2D images

Previously, 6 layers were removed from the dirty subresources set if
any layer of a cube-compatible images was dirty. This happened even for
image views with fewer than 6 layers. For compressed images this means
layers were marked 'clean' even though they hadn't been decompressed
yet.

This change removes the logic for marking cube layers as clean after
updating borders. We now avoid processing the same cube multiple times
by skipping ahead the layer index. Note also that the previous logic
assumed that the dirty layer was the first layer of a cube. We now round
down to a multiple of 6.

Bug: b/198674734
Change-Id: I888c8018b11734ae5f7317b2d7fef2df3c6a06dd
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/56968
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index c237504..aaae8a8 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -1192,21 +1192,19 @@
 			    subresource.arrayLayer <= lastLayer;
 			    subresource.arrayLayer++)
 			{
-				updateCube(subresource);
-
-				// updateCube() updates all layers of all cubemaps at once, so remove entries to avoid duplicating effort
-				VkImageSubresource cleanSubresource = subresource;
-				for(cleanSubresource.arrayLayer = 0; cleanSubresource.arrayLayer < arrayLayers - 5;)
+				auto it = dirtySubresources.find(subresource);
+				if(it != dirtySubresources.end())
 				{
-					// Delete one cube's worth of dirty subregions
-					for(uint32_t i = 0; i < 6; i++, cleanSubresource.arrayLayer++)
+					// Since cube faces affect each other's borders, we update all 6 layers.
+
+					subresource.arrayLayer -= subresource.arrayLayer % 6;  // Round down to a multiple of 6.
+
+					if(subresource.arrayLayer + 5 <= lastLayer)
 					{
-						auto it = dirtySubresources.find(cleanSubresource);
-						if(it != dirtySubresources.end())
-						{
-							dirtySubresources.erase(it);
-						}
+						device->getBlitter()->updateBorders(decompressedImage ? decompressedImage : this, subresource);
 					}
+
+					subresource.arrayLayer += 5;  // Together with the loop increment, advances to the next cube.
 				}
 			}
 		}
@@ -1300,18 +1298,6 @@
 	}
 }
 
-void Image::updateCube(const VkImageSubresource &subres)
-{
-	VkImageSubresource subresource = subres;
-
-	// Update the borders of all the groups of 6 layers that can be part of a cubemaps but don't
-	// touch leftover layers that cannot be part of cubemaps.
-	for(subresource.arrayLayer = 0; subresource.arrayLayer < arrayLayers - 5; subresource.arrayLayer += 6)
-	{
-		device->getBlitter()->updateBorders(decompressedImage ? decompressedImage : this, subresource);
-	}
-}
-
 void Image::decodeETC2(const VkImageSubresource &subresource)
 {
 	ASSERT(decompressedImage);
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index 38ac5fc..97676ac 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -133,9 +133,9 @@
 	VkFormat getClearFormat() const;
 	void clear(void *pixelData, VkFormat pixelFormat, const vk::Format &viewFormat, const VkImageSubresourceRange &subresourceRange, const VkRect2D &renderArea);
 	int borderSize() const;
+
 	bool requiresPreprocessing() const;
 	void decompress(const VkImageSubresource &subresource);
-	void updateCube(const VkImageSubresource &subresource);
 	void decodeETC2(const VkImageSubresource &subresource);
 	void decodeBC(const VkImageSubresource &subresource);
 	void decodeASTC(const VkImageSubresource &subresource);