Fix FP blending path to not make clamping assumptions We had assumed in Context in various places that negative pixel values would be clamped to zero, which is incorrect for floating-point color attachments. TODO: on the assumption that there is value in these blend optimizations themselves, we should split the context blend state to be per-attachment. This would give us the `independentBlend` optional feature, and also allow us to keep the optimization for those attachments which do have clamping in a mixed MRT scenario. Bug: b/132433217 Test: dEQP-VK.pipeline.blend.format.r16* Change-Id: I5434475aba5d21a8c8342b42cccc575b517f0900 Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/31050 Tested-by: Chris Forbes <chrisforbes@google.com> Presubmit-Ready: Chris Forbes <chrisforbes@google.com> Kokoro-Presubmit: kokoro <noreply+kokoro@google.com> Reviewed-by: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Device/Context.cpp b/src/Device/Context.cpp index b2d6734..b6d811e 100644 --- a/src/Device/Context.cpp +++ b/src/Device/Context.cpp
@@ -324,6 +324,20 @@ return destBlendFactorState; } + 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() const { if(!alphaBlendEnable) return VK_BLEND_OP_SRC_EXT; @@ -365,7 +379,7 @@ } } case VK_BLEND_OP_SUBTRACT: - if(sourceBlendFactor() == VK_BLEND_FACTOR_ZERO) + if(sourceBlendFactor() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero } @@ -405,7 +419,7 @@ } else if(sourceBlendFactor() == VK_BLEND_FACTOR_ONE) { - if(destBlendFactor() == VK_BLEND_FACTOR_ZERO) + if(destBlendFactor() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero } @@ -416,7 +430,7 @@ } else { - if(destBlendFactor() == VK_BLEND_FACTOR_ZERO) + if(destBlendFactor() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero } @@ -533,7 +547,7 @@ } } case VK_BLEND_OP_SUBTRACT: - if(sourceBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO) + if(sourceBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero } @@ -573,7 +587,7 @@ } else if(sourceBlendFactorAlpha() == VK_BLEND_FACTOR_ONE) { - if(destBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO) + if(destBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero } @@ -584,7 +598,7 @@ } else { - if(destBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO) + if(destBlendFactorAlpha() == VK_BLEND_FACTOR_ZERO && allTargetsColorClamp()) { return VK_BLEND_OP_ZERO_EXT; // Negative, clamped to zero }