Implementation of partial clear

Implemented subregion clears.
The quad layout had to be disabled to depth/stencil textures,
as it was not expected by dEQP.

Passes all tests in api.image_clearing.dedicated_allocation.
- partial_clear_color_attachment.*
- partial_clear_depth_stencil_attachment.*

Bug b/119621736

Change-Id: I9e854eceeef4a72b2ae507d62dbdbfa0b56c96f3
Reviewed-on: https://swiftshader-review.googlesource.com/c/23829
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
Reviewed-by: Corentin Wallez <cwallez@google.com>
diff --git a/src/Device/Surface.cpp b/src/Device/Surface.cpp
index 0da1282..b367ec5 100644
--- a/src/Device/Surface.cpp
+++ b/src/Device/Surface.cpp
@@ -1995,20 +1995,6 @@
 
 	bool Surface::hasQuadLayout(VkFormat format)
 	{
-		switch(format)
-		{
-		case VK_FORMAT_D16_UNORM:
-		case VK_FORMAT_X8_D24_UNORM_PACK32:
-		case VK_FORMAT_D32_SFLOAT:
-		case VK_FORMAT_S8_UINT:
-		case VK_FORMAT_D16_UNORM_S8_UINT:
-		case VK_FORMAT_D24_UNORM_S8_UINT:
-		case VK_FORMAT_D32_SFLOAT_S8_UINT:
-			return true;
-		default:
-			break;
-		}
-
 		return false;
 	}
 
diff --git a/src/Vulkan/VkImage.cpp b/src/Vulkan/VkImage.cpp
index 89887a4..9278161 100644
--- a/src/Vulkan/VkImage.cpp
+++ b/src/Vulkan/VkImage.cpp
@@ -532,6 +532,32 @@
 	}
 }
 
+void Image::clear(void* pixelData, VkFormat format, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange, VkImageAspectFlags aspectMask)
+{
+	if((subresourceRange.baseMipLevel != 0) ||
+	   (subresourceRange.levelCount != 1))
+	{
+		UNIMPLEMENTED();
+	}
+
+	sw::SliceRect dRect(renderArea.offset.x, renderArea.offset.y,
+			            renderArea.offset.x + renderArea.extent.width,
+			            renderArea.offset.y + renderArea.extent.height, 0);
+
+	uint32_t firstLayer = subresourceRange.baseArrayLayer;
+	uint32_t lastLayer = getLastLayerIndex(subresourceRange);
+	for(uint32_t layer = firstLayer; layer <= lastLayer; ++layer)
+	{
+		for(uint32_t s = 0; s < extent.depth; ++s)
+		{
+			dRect.slice = s;
+			sw::Surface* surface = asSurface(aspectMask, 0, layer);
+			blitter->clear(pixelData, format, surface, dRect, 0xF);
+			delete surface;
+		}
+	}
+}
+
 void Image::clear(const VkClearColorValue& color, const VkImageSubresourceRange& subresourceRange)
 {
 	if(!(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT))
@@ -567,22 +593,26 @@
 	     (subresourceRange.aspectMask & (VK_IMAGE_ASPECT_DEPTH_BIT |
 	                                     VK_IMAGE_ASPECT_STENCIL_BIT))) ||
 	   (subresourceRange.baseMipLevel != 0) ||
-	   (subresourceRange.levelCount != 1) ||
-	   (renderArea.offset.x != 0) ||
-	   (renderArea.offset.y != 0) ||
-	   (renderArea.extent.width != extent.width) ||
-	   (renderArea.extent.height != extent.height))
+	   (subresourceRange.levelCount != 1))
 	{
 		UNIMPLEMENTED();
 	}
 
 	if(subresourceRange.aspectMask == VK_IMAGE_ASPECT_COLOR_BIT)
 	{
-		clear(clearValue.color, subresourceRange);
+		clear((void*)(clearValue.color.float32), getClearFormat(), renderArea, subresourceRange, VK_IMAGE_ASPECT_COLOR_BIT);
 	}
 	else
 	{
-		clear(clearValue.depthStencil, subresourceRange);
+		if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_DEPTH_BIT)
+		{
+			clear((void*)(&clearValue.depthStencil.depth), VK_FORMAT_D32_SFLOAT, renderArea, subresourceRange, VK_IMAGE_ASPECT_DEPTH_BIT);
+		}
+
+		if(subresourceRange.aspectMask & VK_IMAGE_ASPECT_STENCIL_BIT)
+		{
+			clear((void*)(&clearValue.depthStencil.stencil), VK_FORMAT_S8_UINT, renderArea, subresourceRange, VK_IMAGE_ASPECT_STENCIL_BIT);
+		}
 	}
 }
 
diff --git a/src/Vulkan/VkImage.hpp b/src/Vulkan/VkImage.hpp
index badca58..eb8cc94 100644
--- a/src/Vulkan/VkImage.hpp
+++ b/src/Vulkan/VkImage.hpp
@@ -73,6 +73,7 @@
 	uint32_t getLastMipLevel(const VkImageSubresourceRange& subresourceRange) const;
 	VkFormat getClearFormat() const;
 	void clear(void* pixelData, VkFormat format, const VkImageSubresourceRange& subresourceRange, VkImageAspectFlags aspectMask);
+	void clear(void* pixelData, VkFormat format, const VkRect2D& renderArea, const VkImageSubresourceRange& subresourceRange, VkImageAspectFlags aspectMask);
 	sw::Surface* asSurface(const VkImageAspectFlags& flags, uint32_t mipLevel, uint32_t layer) const;
 
 	DeviceMemory*            deviceMemory = nullptr;