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, ...@@ -1888,9 +1888,10 @@ Vector4f SamplerCore::sampleTexel(Int4 &uuuu, Int4 &vvvv, Int4 &wwww, Float4 &z,
{ {
// Valid texels have positive coordinates. // Valid texels have positive coordinates.
Int4 negative = Int4(0); Int4 negative = Int4(0);
if(state.addressingModeU == ADDRESSING_BORDER) negative |= uuuu; if(state.addressingModeU != ADDRESSING_UNUSED) negative |= uuuu;
if(state.addressingModeV == ADDRESSING_BORDER) negative |= vvvv; if(state.addressingModeV != ADDRESSING_UNUSED) negative |= vvvv;
if(state.addressingModeW == ADDRESSING_BORDER) negative |= wwww; if(state.addressingModeW != ADDRESSING_UNUSED) negative |= wwww;
if(state.addressingModeY != ADDRESSING_UNUSED) negative |= cubeArrayId;
valid = CmpNLT(negative, Int4(0)); valid = CmpNLT(negative, Int4(0));
} }
...@@ -2123,7 +2124,7 @@ Vector4f SamplerCore::replaceBorderTexel(const Vector4f &c, Int4 valid) ...@@ -2123,7 +2124,7 @@ Vector4f SamplerCore::replaceBorderTexel(const Vector4f &c, Int4 valid)
} }
Vector4f out; 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.y = As<Float4>((valid & As<Int4>(c.y)) | (~valid & borderRGB));
out.z = As<Float4>((valid & As<Int4>(c.z)) | (~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.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, ...@@ -2252,7 +2253,16 @@ void SamplerCore::address(const Float4 &uvw, Int4 &xyz0, Int4 &xyz1, Float4 &f,
if(function == Fetch) 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 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 ...@@ -78,6 +78,14 @@ SpirvShader::ImageSampler *SpirvShader::getImageSampler(uint32_t inst, vk::Sampl
samplerState.minLod = sampler->minLod; samplerState.minLod = sampler->minLod;
samplerState.maxLod = sampler->maxLod; 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); return emitSamplerRoutine(instruction, samplerState);
}; };
...@@ -349,14 +357,18 @@ sw::AddressingMode SpirvShader::convertAddressingMode(int coordinateIndex, const ...@@ -349,14 +357,18 @@ sw::AddressingMode SpirvShader::convertAddressingMode(int coordinateIndex, const
if(!sampler) if(!sampler)
{ {
// OpImageFetch does not take a sampler descriptor, but still needs a valid, // OpImageFetch does not take a sampler descriptor, but still needs a valid
// arbitrary addressing mode that prevents out-of-bounds accesses: // addressing mode that prevents out-of-bounds accesses:
// "The value returned by a read of an invalid texel is undefined, unless that // "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 // 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 // is enabled. In that case, an invalid texel is replaced as described by the
// robustBufferAccess feature." - Vulkan 1.1 // 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; 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