Perform texel replacement on out-of-bounds OpImageFetch accesses
VK_EXT_image_robustness requires returning zero on out-of-bounds image
accesses. OpImageFetch was previously merely clamping the coordinates to
be in-bounds.
This change reuses some of the functionality for
VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER to perform texel replacement.
Bug: b/159329067
Tests: dEQP-VK.robustness.image_robustness.*
Change-Id: I8c00b8de2793b0b7028230cb180d308a4b9b60ec
Reviewed-on: https://swiftshader-review.googlesource.com/c/SwiftShader/+/47095
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/Pipeline/SamplerCore.cpp b/src/Pipeline/SamplerCore.cpp
index ba17235..1a84042 100644
--- a/src/Pipeline/SamplerCore.cpp
+++ b/src/Pipeline/SamplerCore.cpp
@@ -1888,9 +1888,10 @@
{
// Valid texels have positive coordinates.
Int4 negative = Int4(0);
- if(state.addressingModeU == ADDRESSING_BORDER) negative |= uuuu;
- if(state.addressingModeV == ADDRESSING_BORDER) negative |= vvvv;
- if(state.addressingModeW == ADDRESSING_BORDER) negative |= wwww;
+ if(state.addressingModeU != ADDRESSING_UNUSED) negative |= uuuu;
+ if(state.addressingModeV != ADDRESSING_UNUSED) negative |= vvvv;
+ if(state.addressingModeW != ADDRESSING_UNUSED) negative |= wwww;
+ if(state.addressingModeY != ADDRESSING_UNUSED) negative |= cubeArrayId;
valid = CmpNLT(negative, Int4(0));
}
@@ -2123,7 +2124,7 @@
}
Vector4f out;
- out.x = As<Float4>((valid & As<Int4>(c.x)) | (~valid & borderRGB));
+ 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));
@@ -2252,7 +2253,16 @@
if(function == Fetch)
{
- xyz0 = Min(Max(((function.offset != 0) && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw), Int4(0)), maxXYZ);
+ Int4 xyz = (function.offset && (addressingMode != ADDRESSING_LAYER)) ? As<Int4>(uvw) + As<Int4>(texOffset) : As<Int4>(uvw);
+ xyz0 = Min(Max(xyz, Int4(0)), maxXYZ);
+
+ // VK_EXT_image_robustness requires checking for out-of-bounds accesses.
+ // TODO(b/159329067): Claim VK_EXT_image_robustness
+ // TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
+ // If the above clamping altered the result, the access is out-of-bounds.
+ // In that case set the coordinate to -1 to perform texel replacement later.
+ Int4 outOfBounds = CmpNEQ(xyz, xyz0);
+ xyz0 |= outOfBounds;
}
else if(addressingMode == ADDRESSING_LAYER) // Note: Offset does not apply to array layers
{