Perform independent blend state optimization

Previously we were checking whether all attachments have a format which
requires clamping. We now support the independentBlend feature, and
independent clamping, so we can optimize the blend state more granularly
and not miss opportunities.

Bug: b/140193782
Change-Id: I7e663fd8ebc6a7a6e35133c0c4c5cad84278eeb3
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/47828
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Alexis Hétu <sugoi@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp
index b5f36bf..8e35ff2 100644
--- a/src/Device/Context.cpp
+++ b/src/Device/Context.cpp
@@ -119,6 +119,16 @@
 	return activeBlendState;
 }
 
+bool Context::isColorClamped(int index) const
+{
+	if(renderTarget[index] && renderTarget[index]->getFormat().isFloatFormat())
+	{
+		return false;
+	}
+
+	return true;
+}
+
 bool Context::alphaBlendActive(int index) const
 {
 	ASSERT((index >= 0) && (index < RENDERTARGETS));
@@ -185,20 +195,6 @@
 	return blendState[index].destBlendFactor;
 }
 
-bool Context::allTargetsColorClamp() const
-{
-	// TODO: remove all of this and support VkPhysicalDeviceFeatures::independentBlend instead
-	for(int i = 0; i < RENDERTARGETS; i++)
-	{
-		if(renderTarget[i] && renderTarget[i]->getFormat().isFloatFormat())
-		{
-			return false;
-		}
-	}
-
-	return true;
-}
-
 VkBlendOp Context::blendOperation(int index) const
 {
 	ASSERT((index >= 0) && (index < RENDERTARGETS));
@@ -242,7 +238,7 @@
 				}
 			}
 		case VK_BLEND_OP_SUBTRACT:
-			if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+			if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 			{
 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 			}
@@ -282,7 +278,7 @@
 			}
 			else if(sourceBlendFactor(index) == VK_BLEND_FACTOR_ONE)
 			{
-				if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+				if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 				{
 					return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 				}
@@ -293,7 +289,7 @@
 			}
 			else
 			{
-				if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+				if(destBlendFactor(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 				{
 					return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 				}
@@ -396,7 +392,7 @@
 				}
 			}
 		case VK_BLEND_OP_SUBTRACT:
-			if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+			if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 			{
 				return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 			}
@@ -436,7 +432,7 @@
 			}
 			else if(sourceBlendFactorAlpha(index) == VK_BLEND_FACTOR_ONE)
 			{
-				if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+				if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 				{
 					return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 				}
@@ -447,7 +443,7 @@
 			}
 			else
 			{
-				if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp())
+				if(destBlendFactorAlpha(index) == VK_BLEND_FACTOR_ZERO && isColorClamped(index))
 				{
 					return VK_BLEND_OP_ZERO_EXT;  // Negative, clamped to zero
 				}
diff --git a/src/Device/Context.hpp b/src/Device/Context.hpp
index 8b32b29..e4648dc 100644
--- a/src/Device/Context.hpp
+++ b/src/Device/Context.hpp
@@ -83,10 +83,9 @@
 	bool depthBufferActive() const;
 	bool stencilActive() const;
 
-	bool allTargetsColorClamp() const;
-
 	void setBlendState(int index, BlendState state);
 	BlendState getBlendState(int index) const;
+	bool isColorClamped(int index) const;
 
 	VkPrimitiveTopology topology;
 	VkProvokingVertexModeEXT provokingVertexMode;