Framebuffer clear assert fix

Respect loadOp when clearing attachments in beginRenderPass().

Bug b/119621736

Change-Id: Id9ad0f1ad9dc6116264782be3370c37c078d6846
Reviewed-on: https://swiftshader-review.googlesource.com/c/24050
Tested-by: Alexis Hétu <sugoi@google.com>
Reviewed-by: Chris Forbes <chrisforbes@google.com>
diff --git a/src/Vulkan/VkFramebuffer.cpp b/src/Vulkan/VkFramebuffer.cpp
index c7fd078..1adadce 100644
--- a/src/Vulkan/VkFramebuffer.cpp
+++ b/src/Vulkan/VkFramebuffer.cpp
@@ -15,6 +15,8 @@
 #include "VkFramebuffer.hpp"
 #include "VkImageView.hpp"
 #include "VkRenderPass.hpp"
+#include "Device/Surface.hpp"
+#include <algorithm>
 #include <memory.h>
 
 namespace vk
@@ -38,11 +40,32 @@
 
 void Framebuffer::clear(uint32_t clearValueCount, const VkClearValue* pClearValues, const VkRect2D& renderArea)
 {
-	ASSERT(clearValueCount >= attachmentCount);
+	ASSERT(attachmentCount == renderPass->getAttachmentCount());
 
-	for(uint32_t i = 0; i < attachmentCount; i++)
+	const uint32_t count = std::min(clearValueCount, attachmentCount);
+	for(uint32_t i = 0; i < count; i++)
 	{
-		attachments[i]->clear(pClearValues[i], renderArea);
+		const VkAttachmentDescription attachment = renderPass->getAttachment(i);
+		bool isDepth = sw::Surface::isDepth(attachment.format);
+		bool isStencil = sw::Surface::isStencil(attachment.format);
+
+		if(isDepth || isStencil)
+		{
+			bool clearDepth = (isDepth && (attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR));
+			bool clearStencil = (isStencil && (attachment.stencilLoadOp == VK_ATTACHMENT_LOAD_OP_CLEAR));
+
+			if(clearDepth || clearStencil)
+			{
+				attachments[i]->clear(pClearValues[i],
+				                      (clearDepth ? VK_IMAGE_ASPECT_DEPTH_BIT : 0) |
+				                      (clearStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : 0),
+				                      renderArea);
+			}
+		}
+		else if(attachment.loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR)
+		{
+			attachments[i]->clear(pClearValues[i], VK_IMAGE_ASPECT_COLOR_BIT, renderArea);
+		}
 	}
 }
 
diff --git a/src/Vulkan/VkImageView.cpp b/src/Vulkan/VkImageView.cpp
index 293c8d7..9dd1680 100644
--- a/src/Vulkan/VkImageView.cpp
+++ b/src/Vulkan/VkImageView.cpp
@@ -72,7 +72,7 @@
 	return false;
 }
 
-void ImageView::clear(const VkClearValue& clearValue, const VkRect2D& renderArea)
+void ImageView::clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkRect2D& renderArea)
 {
 	// Note: clearing ignores swizzling, so components is ignored.
 
@@ -86,6 +86,8 @@
 		UNIMPLEMENTED();
 	}
 
+	VkImageSubresourceRange sr = subresourceRange;
+	sr.aspectMask = aspectMask;
 	image->clear(clearValue, renderArea, subresourceRange);
 }
 
diff --git a/src/Vulkan/VkImageView.hpp b/src/Vulkan/VkImageView.hpp
index d2a0124..26be628 100644
--- a/src/Vulkan/VkImageView.hpp
+++ b/src/Vulkan/VkImageView.hpp
@@ -31,7 +31,7 @@
 
 	static size_t ComputeRequiredAllocationSize(const VkImageViewCreateInfo* pCreateInfo);
 
-	void clear(const VkClearValue& clearValues, const VkRect2D& renderArea);
+	void clear(const VkClearValue& clearValues, const VkImageAspectFlags aspectMask, const VkRect2D& renderArea);
 	void clear(const VkClearValue& clearValue, const VkImageAspectFlags aspectMask, const VkClearRect& renderArea);
 
 private: