From 10ec13fe4fc04efccde1a959478b0bd54bcfaf8c Mon Sep 17 00:00:00 2001 From: liruoyu Date: Tue, 3 Nov 2020 16:31:17 +0800 Subject: [PATCH] Adjust texture data and threshold Affects: dEQP-GLES3.functional.texture.wrap.* dEQP-GLES2.functional.texture.wrap.* Components: OpenGL VK-GL-CTS issue: 2589 Root cause: We treat all variable which have relaxed precision decoration as half precision value. 1. When run in repeat&linear mode, sampling texture edge will get an unexpect result. 2. When run in nearest mode, threshold is 2/256, but texture gradient is 2/255. so, if target texel's deviation more then 1, will get a fail result. Solution: 1. Adjust texture data, make the difference between two adjacent texel under 2/256 in per-channel. 2. Adjust threshold to 2/255 in RGBA_8888 mode, adjust threshold to (1 + 256/16) in RGBA_4444 mode. 3. Adjust texture data, make the texture gradient like a pyramid in repeat mode. Change-Id: I2382d36bdeb227e81d0d0b8f76f61d26a00f0fcd --- framework/common/tcuTexLookupVerifier.cpp | 5 ++ framework/common/tcuTexLookupVerifier.hpp | 1 + framework/common/tcuTexVerifierUtil.cpp | 9 ++++ framework/common/tcuTexVerifierUtil.hpp | 10 ++++ framework/common/tcuTextureUtil.cpp | 66 +++++++++++++++++++---- framework/common/tcuTextureUtil.hpp | 1 + modules/gles2/functional/es2fTextureWrapTests.cpp | 25 +++++++-- modules/gles3/functional/es3fTextureWrapTests.cpp | 13 ++++- 8 files changed, 114 insertions(+), 16 deletions(-) diff --git a/framework/common/tcuTexLookupVerifier.cpp b/framework/common/tcuTexLookupVerifier.cpp index a5be969..1dfd3d8 100644 --- a/framework/common/tcuTexLookupVerifier.cpp +++ b/framework/common/tcuTexLookupVerifier.cpp @@ -2203,6 +2203,11 @@ Vec4 computeFloatingPointThreshold (const IVec4& bits, const Vec4& value) return computeFloatingPointError(value, bits); } +Vec4 computeColorBitsThreshold(const IVec4& bits, const IVec4& numAccurateBits) +{ + return computeColorBitsError(bits, numAccurateBits); +} + Vec2 computeLodBoundsFromDerivates (const float dudx, const float dvdx, const float dwdx, const float dudy, const float dvdy, const float dwdy, const LodPrecision& prec) { const float mux = deFloatAbs(dudx); diff --git a/framework/common/tcuTexLookupVerifier.hpp b/framework/common/tcuTexLookupVerifier.hpp index d69efca..60dc472 100644 --- a/framework/common/tcuTexLookupVerifier.hpp +++ b/framework/common/tcuTexLookupVerifier.hpp @@ -102,6 +102,7 @@ enum TexLookupScaleMode Vec4 computeFixedPointThreshold (const IVec4& bits); Vec4 computeFloatingPointThreshold (const IVec4& bits, const Vec4& value); +Vec4 computeColorBitsThreshold (const IVec4& bits, const IVec4& numAccurateBits); Vec2 computeLodBoundsFromDerivates (const float dudx, const float dudy, const LodPrecision& prec); Vec2 computeLodBoundsFromDerivates (const float dudx, const float dvdx, const float dudy, const float dvdy, const LodPrecision& prec); diff --git a/framework/common/tcuTexVerifierUtil.cpp b/framework/common/tcuTexVerifierUtil.cpp index 425e037..ce2a449 100644 --- a/framework/common/tcuTexVerifierUtil.cpp +++ b/framework/common/tcuTexVerifierUtil.cpp @@ -43,6 +43,15 @@ float computeFixedPointError (const int numAccurateBits) return computeFloatingPointError(1.0f, numAccurateBits); } +float computeColorBitsError(const int bits, const int numAccurateBits) +{ + // Color bits error is not a generic function, it just for compute the error value that cannot be accurately shown in integer data format. + // + // "bits" is color bit width, "numAccurateBits" is the number of accurate bits in color bits, "1 << (bits - numAccurateBits)" is the threshold in integer. + // "1.0f / 256.0f" is epsilon value, to make sure the threshold use to calculate in float can be a little bigger than the real value. + return (float(1 << (bits - numAccurateBits)) + 1.0f / 256.0f) / float((1 << bits) - 1); +} + Vec2 computeNonNormalizedCoordBounds (const bool normalizedCoords, const int dim, const float coord, const int coordBits, const int uvBits) { const float coordErr = computeFloatingPointError(coord, coordBits); diff --git a/framework/common/tcuTexVerifierUtil.hpp b/framework/common/tcuTexVerifierUtil.hpp index cb9051d..f52d3f4 100644 --- a/framework/common/tcuTexVerifierUtil.hpp +++ b/framework/common/tcuTexVerifierUtil.hpp @@ -35,6 +35,7 @@ namespace TexVerifierUtil float computeFloatingPointError (const float value, const int numAccurateBits); float computeFixedPointError (const int numAccurateBits); +float computeColorBitsError (const int bits, const int numAccurateBits); template inline Vector computeFloatingPointError (const Vector& value, const Vector& numAccurateBits) @@ -54,6 +55,15 @@ inline Vector computeFixedPointError (const Vector& return res; } +template +inline Vector computeColorBitsError(const Vector& bits, const Vector& numAccurateBits) +{ + Vector res; + for (int ndx = 0; ndx < Size; ndx++) + res[ndx] = computeColorBitsError(bits[ndx], numAccurateBits[ndx]); + return res; +} + // Sampler introspection inline bool isNearestMipmapFilter(const Sampler::FilterMode mode) diff --git a/framework/common/tcuTextureUtil.cpp b/framework/common/tcuTextureUtil.cpp index d70a959..f1b9cc9 100644 --- a/framework/common/tcuTextureUtil.cpp +++ b/framework/common/tcuTextureUtil.cpp @@ -831,7 +831,8 @@ void clearStencil (const PixelBufferAccess& access, int stencil) enum GradientStyle { GRADIENT_STYLE_OLD = 0, - GRADIENT_STYLE_NEW = 1 + GRADIENT_STYLE_NEW = 1, + GRADIENT_STYLE_PYRAMID = 2 }; static void fillWithComponentGradients1D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal, GradientStyle) @@ -850,21 +851,59 @@ static void fillWithComponentGradients1D (const PixelBufferAccess& access, const } } -static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal, GradientStyle) +static void fillWithComponentGradients2D (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal, GradientStyle style) { - for (int y = 0; y < access.getHeight(); y++) + if (style == GRADIENT_STYLE_PYRAMID) { - for (int x = 0; x < access.getWidth(); x++) + int xedge = deFloorFloatToInt32(float(access.getWidth()) * 0.6f); + int yedge = deFloorFloatToInt32(float(access.getHeight()) * 0.6f); + + for (int y = 0; y < access.getHeight(); y++) { - float s = ((float)x + 0.5f) / (float)access.getWidth(); - float t = ((float)y + 0.5f) / (float)access.getHeight(); + for (int x = 0; x < access.getWidth(); x++) + { + float s = ((float)x + 0.5f) / (float)access.getWidth(); + float t = ((float)y + 0.5f) / (float)access.getHeight(); + float coefR = 0.0f; + float coefG = 0.0f; + float coefB = 0.0f; + float coefA = 0.0f; + + coefR = (x < xedge) ? s * 0.4f : (1 - s) * 0.6f; + coefG = (x < xedge) ? s * 0.4f : (1 - s) * 0.6f; + coefB = (x < xedge) ? (1.0f - s) * 0.4f : s * 0.6f - 0.2f; + coefA = (x < xedge) ? (1.0f - s) * 0.4f : s * 0.6f - 0.2f; + + coefR += (y < yedge) ? t * 0.4f : (1 - t) * 0.6f; + coefG += (y < yedge) ? (1.0f - t) * 0.4f : t * 0.6f - 0.2f; + coefB += (y < yedge) ? t * 0.4f : (1 - t) * 0.6f; + coefA += (y < yedge) ? (1.0f - t) * 0.4f : t * 0.6f - 0.2f; + + float r = linearInterpolate(coefR, minVal.x(), maxVal.x()); + float g = linearInterpolate(coefG, minVal.y(), maxVal.y()); + float b = linearInterpolate(coefB, minVal.z(), maxVal.z()); + float a = linearInterpolate(coefA, minVal.w(), maxVal.w()); + + access.setPixel(tcu::Vec4(r, g, b, a), x, y); + } + } + } + else + { + for (int y = 0; y < access.getHeight(); y++) + { + for (int x = 0; x < access.getWidth(); x++) + { + float s = ((float)x + 0.5f) / (float)access.getWidth(); + float t = ((float)y + 0.5f) / (float)access.getHeight(); - float r = linearInterpolate(( s + t) *0.5f, minVal.x(), maxVal.x()); - float g = linearInterpolate(( s + (1.0f-t))*0.5f, minVal.y(), maxVal.y()); - float b = linearInterpolate(((1.0f-s) + t) *0.5f, minVal.z(), maxVal.z()); - float a = linearInterpolate(((1.0f-s) + (1.0f-t))*0.5f, minVal.w(), maxVal.w()); + float r = linearInterpolate((s + t) *0.5f, minVal.x(), maxVal.x()); + float g = linearInterpolate((s + (1.0f - t))*0.5f, minVal.y(), maxVal.y()); + float b = linearInterpolate(((1.0f - s) + t) *0.5f, minVal.z(), maxVal.z()); + float a = linearInterpolate(((1.0f - s) + (1.0f - t))*0.5f, minVal.w(), maxVal.w()); - access.setPixel(tcu::Vec4(r, g, b, a), x, y); + access.setPixel(tcu::Vec4(r, g, b, a), x, y); + } } } } @@ -942,6 +981,11 @@ void fillWithComponentGradients2 (const PixelBufferAccess& access, const Vec4& m fillWithComponentGradientsStyled(access, minVal, maxVal, GRADIENT_STYLE_NEW); } +void fillWithComponentGradients3(const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal) +{ + fillWithComponentGradientsStyled(access, minVal, maxVal, GRADIENT_STYLE_PYRAMID); +} + static void fillWithGrid1D (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB) { for (int x = 0; x < access.getWidth(); x++) diff --git a/framework/common/tcuTextureUtil.hpp b/framework/common/tcuTextureUtil.hpp index 5512033..be9ed3f 100644 --- a/framework/common/tcuTextureUtil.hpp +++ b/framework/common/tcuTextureUtil.hpp @@ -117,6 +117,7 @@ void clearDepth (const PixelBufferAccess& access, float depth); void clearStencil (const PixelBufferAccess& access, int stencil); void fillWithComponentGradients (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal); void fillWithComponentGradients2 (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal); +void fillWithComponentGradients3 (const PixelBufferAccess& access, const Vec4& minVal, const Vec4& maxVal); void fillWithGrid (const PixelBufferAccess& access, int cellSize, const Vec4& colorA, const Vec4& colorB); void fillWithRepeatableGradient (const PixelBufferAccess& access, const Vec4& colorA, const Vec4& colorB); void fillWithMetaballs (const PixelBufferAccess& access, int numMetaballs, deUint32 seed); diff --git a/modules/gles2/functional/es2fTextureWrapTests.cpp b/modules/gles2/functional/es2fTextureWrapTests.cpp index f776a86..0a3bfa2 100644 --- a/modules/gles2/functional/es2fTextureWrapTests.cpp +++ b/modules/gles2/functional/es2fTextureWrapTests.cpp @@ -143,7 +143,16 @@ void TextureWrapCase::init (void) // Fill level 0. m_texture->getRefTexture().allocLevel(0); - tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + if (m_wrapS == GL_REPEAT || + m_wrapT == GL_REPEAT) + { + // If run in repeat mode, use conical style texture to avoid edge sample result have a huge difference when coordinate offset in allow range. + tcu::fillWithComponentGradients3(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + } + else + { + tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + } m_texture->upload(); } @@ -169,8 +178,18 @@ TextureWrapCase::IterateResult TextureWrapCase::iterate (void) int leftWidth = viewport.width / 2; int rightWidth = viewport.width - leftWidth; vector texCoord; - tcu::RGBA threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() - + (isCompressedTex ? tcu::RGBA(7,7,7,7) : tcu::RGBA(3,3,3,3)); + + tcu::RGBA threshold; + if (m_texture->getRefTexture().getFormat().type == tcu::TextureFormat::UNORM_SHORT_4444 || + m_texture->getRefTexture().getFormat().type == tcu::TextureFormat::UNSIGNED_SHORT_4444) + { + threshold = tcu::PixelFormat(4, 4, 4, 4).getColorThreshold() + tcu::RGBA(1, 1, 1, 1); + } + else + { + threshold = m_renderCtx.getRenderTarget().getPixelFormat().getColorThreshold() + + (isCompressedTex ? tcu::RGBA(7, 7, 7, 7) : tcu::RGBA(3, 3, 3, 3)); + } // Bind to unit 0. gl.activeTexture(GL_TEXTURE0); diff --git a/modules/gles3/functional/es3fTextureWrapTests.cpp b/modules/gles3/functional/es3fTextureWrapTests.cpp index a36e4ce..33e0334 100644 --- a/modules/gles3/functional/es3fTextureWrapTests.cpp +++ b/modules/gles3/functional/es3fTextureWrapTests.cpp @@ -267,7 +267,16 @@ void TextureWrapCase::init (void) // Fill level 0. m_texture->getRefTexture().allocLevel(0); - tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 2.0f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + if (m_wrapS == GL_REPEAT || + m_wrapT == GL_REPEAT) + { + // If run in repeat mode, use conical style texture to avoid edge sample result have a huge difference when coordinate offset in allow range. + tcu::fillWithComponentGradients3(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + } + else + { + tcu::fillWithComponentGradients(m_texture->getRefTexture().getLevel(0), tcu::Vec4(-0.5f, -0.5f, -0.5f, 1.5f), tcu::Vec4(1.0f, 1.0f, 1.0f, 0.0f)); + } m_texture->upload(); } @@ -339,7 +348,7 @@ TextureWrapCase::IterateResult TextureWrapCase::iterate (void) lodPrecision.derivateBits = 18; lodPrecision.lodBits = 5; - lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / refParams.colorScale; + lookupPrecision.colorThreshold = tcu::computeColorBitsThreshold(getBitsVec(pixelFormat), colorBits) / refParams.colorScale; lookupPrecision.coordBits = tcu::IVec3(20,20,0); lookupPrecision.uvwBits = tcu::IVec3(5,5,0); lookupPrecision.colorMask = getCompareMask(pixelFormat); -- 2.7.4