Implement VK_EXT_custom_border_color
This implementation uses the custom border color as "baked" state,
instead of data stored in the descriptor. This is justified by the
assumption that only few custom border colors will be used in practice.
maxSamplerAllocationCount and maxCustomBorderColorSamplers are both
set to 4000, like many other implementations currently:
https://vulkan.gpuinfo.org/displayextensionproperty.php?name=maxCustomBorderColorSamplers
Note that infinity is deemed a valid border component value, and Reactor
intentionally asserts when trying to initialize a Float constant with
infinity, so we bit-cast to int in C++.
Bug: b/151215666
Bug: angleproject:6200
Tests: dEQP-VK.*clamp_to_border_custom*
Change-Id: I22608a80f50194bbac66cf515b0a9249b67b5f00
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/54469
Presubmit-Ready: Nicolas Capens <nicolascapens@google.com>
Kokoro-Result: kokoro <noreply+kokoro@google.com>
Tested-by: Nicolas Capens <nicolascapens@google.com>
Reviewed-by: Sean Risser <srisser@google.com>
Commit-Queue: Nicolas Capens <nicolascapens@google.com>
diff --git a/src/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index 655ec3f..d821e46 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -2120,45 +2120,69 @@
Vector4f SamplerCore::replaceBorderTexel(const Vector4f &c, Int4 valid)
{
- Int4 borderRGB;
- Int4 borderA;
+ Vector4i border;
bool scaled = !hasFloatTexture() && !hasUnnormalizedIntegerTexture() && !state.compareEnable;
bool sign = !hasUnsignedTextureComponent(0);
- Int4 float_one = scaled ? As<Int4>(Float4(static_cast<float>(sign ? 0x7FFF : 0xFFFF))) : As<Int4>(Float4(1.0f));
+ float scale = scaled ? static_cast<float>(sign ? 0x7FFF : 0xFFFF) : 1.0f;
+ Int4 float_one = As<Int4>(Float4(scale));
switch(state.border)
{
case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK:
case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK:
- borderRGB = Int4(0);
- borderA = Int4(0);
+ border.x = Int4(0);
+ border.y = Int4(0);
+ border.z = Int4(0);
+ border.w = Int4(0);
break;
case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK:
- borderRGB = Int4(0);
- borderA = float_one;
+ border.x = Int4(0);
+ border.y = Int4(0);
+ border.z = Int4(0);
+ border.w = float_one;
break;
case VK_BORDER_COLOR_INT_OPAQUE_BLACK:
- borderRGB = Int4(0);
- borderA = Int4(1);
+ border.x = Int4(0);
+ border.y = Int4(0);
+ border.z = Int4(0);
+ border.w = Int4(1);
break;
case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE:
- borderRGB = float_one;
- borderA = float_one;
+ border.x = float_one;
+ border.y = float_one;
+ border.z = float_one;
+ border.w = float_one;
break;
case VK_BORDER_COLOR_INT_OPAQUE_WHITE:
- borderRGB = Int4(1);
- borderA = Int4(1);
+ border.x = Int4(1);
+ border.y = Int4(1);
+ border.z = Int4(1);
+ border.w = Int4(1);
+ break;
+ case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT:
+ // This bit-casts from float to int in C++ code instead of Reactor code
+ // because Reactor does not guarantee preserving infinity (b/140302841).
+ border.x = Int4(bit_cast<int>(scale * state.customBorder.float32[0]));
+ border.y = Int4(bit_cast<int>(scale * state.customBorder.float32[1]));
+ border.z = Int4(bit_cast<int>(scale * state.customBorder.float32[2]));
+ border.w = Int4(bit_cast<int>(scale * state.customBorder.float32[3]));
+ break;
+ case VK_BORDER_COLOR_INT_CUSTOM_EXT:
+ border.x = Int4(state.customBorder.int32[0]);
+ border.y = Int4(state.customBorder.int32[1]);
+ border.z = Int4(state.customBorder.int32[2]);
+ border.w = Int4(state.customBorder.int32[3]);
break;
default:
UNSUPPORTED("sint/uint/sfloat border: %u", state.border);
}
Vector4f out;
- out.x = As<Float4>((valid & As<Int4>(c.x)) | (~valid & borderRGB)); // TODO: IfThenElse()
- out.y = As<Float4>((valid & As<Int4>(c.y)) | (~valid & borderRGB));
- out.z = As<Float4>((valid & As<Int4>(c.z)) | (~valid & borderRGB));
- out.w = As<Float4>((valid & As<Int4>(c.w)) | (~valid & borderA));
+ out.x = As<Float4>((valid & As<Int4>(c.x)) | (~valid & border.x)); // TODO: IfThenElse()
+ out.y = As<Float4>((valid & As<Int4>(c.y)) | (~valid & border.y));
+ out.z = As<Float4>((valid & As<Int4>(c.z)) | (~valid & border.z));
+ out.w = As<Float4>((valid & As<Int4>(c.w)) | (~valid & border.w));
return out;
}