Commit 1c004416 by Nicolas Capens Committed by Nicolas Capens

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: 's avatarNicolas Capens <nicolascapens@google.com> Reviewed-by: 's avatarAlexis Hétu <sugoi@google.com>
parent 7c84c9e5
......@@ -1888,9 +1888,10 @@ Vector4f SamplerCore::sampleTexel(Int4 &uuuu, Int4 &vvvv, Int4 &wwww, Float4 &z,
{
// 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 SamplerCore::replaceBorderTexel(const Vector4f &c, Int4 valid)
}
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 @@ void SamplerCore::address(const Float4 &uvw, Int4 &xyz0, Int4 &xyz1, Float4 &f,
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
{
......
......@@ -78,6 +78,14 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t inst, vk::Sampl
samplerState.minLod = sampler->minLod;
samplerState.maxLod = sampler->maxLod;
}
else
{
// OpImageFetch does not take a sampler descriptor, but for VK_EXT_image_robustness
// requires replacing invalid texels with zero.
// TODO(b/159329067): Claim VK_EXT_image_robustness
// TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
samplerState.border = VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK;
}
return emitSamplerRoutine(instruction, samplerState);
};
......@@ -349,14 +357,18 @@ sw::AddressingMode SpirvShader::convertAddressingMode(int coordinateIndex, const
if(!sampler)
{
// OpImageFetch does not take a sampler descriptor, but still needs a valid,
// arbitrary addressing mode that prevents out-of-bounds accesses:
// OpImageFetch does not take a sampler descriptor, but still needs a valid
// addressing mode that prevents out-of-bounds accesses:
// "The value returned by a read of an invalid texel is undefined, unless that
// read operation is from a buffer resource and the robustBufferAccess feature
// is enabled. In that case, an invalid texel is replaced as described by the
// robustBufferAccess feature." - Vulkan 1.1
return ADDRESSING_WRAP;
// VK_EXT_image_robustness requires nullifying out-of-bounds accesses.
// ADDRESSING_BORDER causes texel replacement to be performed.
// TODO(b/159329067): Claim VK_EXT_image_robustness
// TODO(b/162327166): Only perform bounds checks when VK_EXT_image_robustness is enabled.
return ADDRESSING_BORDER;
}
VkSamplerAddressMode addressMode = VK_SAMPLER_ADDRESS_MODE_REPEAT;
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment