From 1dfe5d68bd78ebc44ee80222452e4a5f5656aab6 Mon Sep 17 00:00:00 2001 From: Jeff Leger Date: Wed, 31 Jan 2018 20:31:13 -0500 Subject: [PATCH] Relax the precision requirements for derivate built-ins Allow for relaxed precision thredholds for derivatives, with a quality warning. Affects: dEQP-GLES3.functional.shaders.derivate.* Components: AOSP Khronos vk-gl-cts issue: 977 Change-Id: I1d69ad71b79a30a36daf2bf75b2f50d309bc5496 --- .../gles3/functional/es3fShaderDerivateTests.cpp | 247 +++++++++++++++------ 1 file changed, 177 insertions(+), 70 deletions(-) diff --git a/modules/gles3/functional/es3fShaderDerivateTests.cpp b/modules/gles3/functional/es3fShaderDerivateTests.cpp index 70e61b4..15013bf 100644 --- a/modules/gles3/functional/es3fShaderDerivateTests.cpp +++ b/modules/gles3/functional/es3fShaderDerivateTests.cpp @@ -214,7 +214,7 @@ float computeFloatingPointError (const float value, const int numAccurateBits) { const int numGarbageBits = 23-numAccurateBits; const deUint32 mask = (1u< 0 && logPolicy == LOG_ALL) log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage; - return numFailedPixels == 0; + return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL; } struct Linear2DFunctionEvaluator @@ -433,7 +462,7 @@ tcu::Vec4 Linear2DFunctionEvaluator::evaluateAt (float screenX, float screenY) c return matrix * position; } -static bool reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog& log, +static qpTestResult reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog& log, const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask, glu::DataType dataType, @@ -551,7 +580,7 @@ static bool reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog& lo if (numFailedPixels > 0) log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage; - return numFailedPixels == 0; + return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL; } // TriangleDerivateCase @@ -559,34 +588,34 @@ static bool reverifyConstantDerivateWithFlushRelaxations (tcu::TestLog& lo class TriangleDerivateCase : public TestCase { public: - TriangleDerivateCase (Context& context, const char* name, const char* description); - ~TriangleDerivateCase (void); + TriangleDerivateCase (Context& context, const char* name, const char* description); + ~TriangleDerivateCase (void); - IterateResult iterate (void); + IterateResult iterate (void); protected: - virtual void setupRenderState (deUint32 program) { DE_UNREF(program); } - virtual bool verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL; + virtual void setupRenderState (deUint32 program) { DE_UNREF(program); } + virtual qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) = DE_NULL; - tcu::IVec2 getViewportSize (void) const; - tcu::Vec4 getSurfaceThreshold (void) const; + tcu::IVec2 getViewportSize (void) const; + tcu::Vec4 getSurfaceThreshold (void) const; - glu::DataType m_dataType; - glu::Precision m_precision; + glu::DataType m_dataType; + glu::Precision m_precision; - glu::DataType m_coordDataType; - glu::Precision m_coordPrecision; + glu::DataType m_coordDataType; + glu::Precision m_coordPrecision; - std::string m_fragmentSrc; + std::string m_fragmentSrc; - tcu::Vec4 m_coordMin; - tcu::Vec4 m_coordMax; - tcu::Vec4 m_derivScale; - tcu::Vec4 m_derivBias; + tcu::Vec4 m_coordMin; + tcu::Vec4 m_coordMax; + tcu::Vec4 m_derivScale; + tcu::Vec4 m_derivBias; - SurfaceType m_surfaceType; - int m_numSamples; - deUint32 m_hint; + SurfaceType m_surfaceType; + int m_numSamples; + deUint32 m_hint; }; TriangleDerivateCase::TriangleDerivateCase (Context& context, const char* name, const char* description) @@ -825,18 +854,24 @@ TriangleDerivateCase::IterateResult TriangleDerivateCase::iterate (void) tcu::Surface errorMask(result.getWidth(), result.getHeight()); tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); - const bool isOk = verify(result.getAccess(), errorMask.getAccess()); + const qpTestResult testResult = verify(result.getAccess(), errorMask.getAccess()); + const char* failStr = "Fail"; m_testCtx.getLog() << TestLog::ImageSet("Result", "Result images") << TestLog::Image("Rendered", "Rendered image", result); - if (!isOk) + if (testResult != QP_TEST_RESULT_PASS) m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask); m_testCtx.getLog() << TestLog::EndImageSet; - m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, - isOk ? "Pass" : "Image comparison failed"); + if (testResult == QP_TEST_RESULT_PASS) + failStr = "Pass"; + else if (testResult == QP_TEST_RESULT_QUALITY_WARNING) + failStr = "QualityWarning"; + + m_testCtx.setTestResult(testResult, failStr); + } return STOP; @@ -875,7 +910,7 @@ public: void init (void); protected: - bool verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); + qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); private: DerivateFunc m_func; @@ -922,7 +957,7 @@ void ConstantDerivateCase::init (void) m_derivBias = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f); } -bool ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) +qpTestResult ConstantDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) { const tcu::Vec4 reference (0.0f); // Derivate of constant argument should always be 0 const tcu::Vec4 threshold = getSurfaceThreshold() / abs(m_derivScale); @@ -942,7 +977,7 @@ public: void init (void); protected: - bool verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); + qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); private: DerivateFunc m_func; @@ -1049,7 +1084,7 @@ void LinearDerivateCase::init (void) } } -bool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) +qpTestResult LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) { const tcu::Vec4 xScale = tcu::Vec4(1.0f, 0.0f, 0.5f, -0.5f); const tcu::Vec4 yScale = tcu::Vec4(0.0f, 1.0f, 0.5f, -0.5f); @@ -1057,13 +1092,15 @@ bool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, cons if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY) { - const bool isX = m_func == DERIVATE_DFDX; - const float div = isX ? float(result.getWidth()) : float(result.getHeight()); - const tcu::Vec4 scale = isX ? xScale : yScale; - const tcu::Vec4 reference = ((m_coordMax - m_coordMin) / div) * scale; - const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_coordMin*scale, m_coordMax*scale, reference); - const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); - const int numComps = glu::getDataTypeFloatScalars(m_dataType); + const bool isX = m_func == DERIVATE_DFDX; + const float div = isX ? float(result.getWidth()) : float(result.getHeight()); + const tcu::Vec4 scale = isX ? xScale : yScale; + const tcu::Vec4 reference = ((m_coordMax - m_coordMin) / div) * scale; + const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_coordMin*scale, m_coordMax*scale, reference); + const tcu::Vec4 opThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin*scale, m_coordMax*scale, reference); + const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); + const tcu::Vec4 thresholdW = max(surfaceThreshold, opThresholdW); + const int numComps = glu::getDataTypeFloatScalars(m_dataType); m_testCtx.getLog() << tcu::TestLog::Message @@ -1075,14 +1112,27 @@ bool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, cons // This improves performance significantly. if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, threshold, m_derivScale, m_derivBias, - LOG_NOTHING)) + LOG_NOTHING) == QP_TEST_RESULT_PASS) { m_testCtx.getLog() << tcu::TestLog::Message << "No incorrect derivatives found, result valid." << tcu::TestLog::EndMessage; - return true; + return QP_TEST_RESULT_PASS; + } + + // Check with relaxed threshold value + if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, + reference, thresholdW, m_derivScale, m_derivBias, + LOG_NOTHING) == QP_TEST_RESULT_PASS) + { + m_testCtx.getLog() + << tcu::TestLog::Message + << "No incorrect derivatives found, result valid with quality warning." + << tcu::TestLog::EndMessage; + + return QP_TEST_RESULT_QUALITY_WARNING; } // some pixels exceed error bounds calculated for normal values. Verify that these @@ -1115,18 +1165,36 @@ bool LinearDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, cons else { DE_ASSERT(m_func == DERIVATE_FWIDTH); - const float w = float(result.getWidth()); - const float h = float(result.getHeight()); + const float w = float(result.getWidth()); + const float h = float(result.getHeight()); + + const tcu::Vec4 dx = ((m_coordMax - m_coordMin) / w) * xScale; + const tcu::Vec4 dy = ((m_coordMax - m_coordMin) / h) * yScale; + const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); + const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx); + const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy); + const tcu::Vec4 dxThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx); + const tcu::Vec4 dyThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy); + const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); + const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW)); + qpTestResult testResult = QP_TEST_RESULT_FAIL; + + testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, + reference, threshold, m_derivScale, m_derivBias); - const tcu::Vec4 dx = ((m_coordMax - m_coordMin) / w) * xScale; - const tcu::Vec4 dy = ((m_coordMax - m_coordMin) / h) * yScale; - const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); - const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_coordMin*xScale, m_coordMax*xScale, dx); - const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_coordMin*yScale, m_coordMax*yScale, dy); - const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); + // return if result is pass + if (testResult == QP_TEST_RESULT_PASS) + return testResult; - return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, - reference, threshold, m_derivScale, m_derivBias); + // re-check with relaxed threshold + testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, + reference, thresholdW, m_derivScale, m_derivBias); + + // if with relaxed threshold test is passing then mark the result with quality warning. + if (testResult == QP_TEST_RESULT_PASS) + testResult = QP_TEST_RESULT_QUALITY_WARNING; + + return testResult; } } @@ -1143,7 +1211,7 @@ public: protected: void setupRenderState (deUint32 program); - bool verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); + qpTestResult verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask); private: DerivateFunc m_func; @@ -1335,7 +1403,7 @@ void TextureDerivateCase::setupRenderState (deUint32 program) gl.uniform1i (gl.getUniformLocation(program, "u_sampler"), texUnit); } -bool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) +qpTestResult TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, const tcu::PixelBufferAccess& errorMask) { // \note Edges are ignored in comparison if (result.getWidth() < 2 || result.getHeight() < 2) @@ -1352,13 +1420,15 @@ bool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, con if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY) { - const bool isX = m_func == DERIVATE_DFDX; - const float div = isX ? w : h; - const tcu::Vec4 scale = isX ? xScale : yScale; - const tcu::Vec4 reference = ((m_texValueMax - m_texValueMin) / div) * scale; - const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference); - const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); - const int numComps = glu::getDataTypeFloatScalars(m_dataType); + const bool isX = m_func == DERIVATE_DFDX; + const float div = isX ? w : h; + const tcu::Vec4 scale = isX ? xScale : yScale; + const tcu::Vec4 reference = ((m_texValueMax - m_texValueMin) / div) * scale; + const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference); + const tcu::Vec4 opThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin*scale, m_texValueMax*scale, reference); + const tcu::Vec4 threshold = max(surfaceThreshold, opThreshold); + const tcu::Vec4 thresholdW = max(surfaceThreshold, opThresholdW); + const int numComps = glu::getDataTypeFloatScalars(m_dataType); m_testCtx.getLog() << tcu::TestLog::Message @@ -1370,16 +1440,36 @@ bool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, con // This improves performance significantly. if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference, threshold, m_derivScale, m_derivBias, - LOG_NOTHING)) + LOG_NOTHING) == QP_TEST_RESULT_PASS) { m_testCtx.getLog() << tcu::TestLog::Message << "No incorrect derivatives found, result valid." << tcu::TestLog::EndMessage; - return true; + return QP_TEST_RESULT_PASS; } + m_testCtx.getLog() + << tcu::TestLog::Message + << "Verifying result image.\n" + << "\tValid derivative is " << LogVecComps(reference, numComps) << " with Warning threshold " << LogVecComps(thresholdW, numComps) + << tcu::TestLog::EndMessage; + + // Re-check with relaxed threshold + if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, + reference, thresholdW, m_derivScale, m_derivBias, + LOG_NOTHING) == QP_TEST_RESULT_PASS) + { + m_testCtx.getLog() + << tcu::TestLog::Message + << "No incorrect derivatives found, result valid with quality warning." + << tcu::TestLog::EndMessage; + + return QP_TEST_RESULT_QUALITY_WARNING; + } + + // some pixels exceed error bounds calculated for normal values. Verify that these // potentially invalid pixels are in fact valid due to (for example) subnorm flushing. @@ -1407,15 +1497,32 @@ bool TextureDerivateCase::verify (const tcu::ConstPixelBufferAccess& result, con else { DE_ASSERT(m_func == DERIVATE_FWIDTH); - const tcu::Vec4 dx = ((m_texValueMax - m_texValueMin) / w) * xScale; - const tcu::Vec4 dy = ((m_texValueMax - m_texValueMin) / h) * yScale; - const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); - const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx); - const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy); - const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); - - return verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, + const tcu::Vec4 dx = ((m_texValueMax - m_texValueMin) / w) * xScale; + const tcu::Vec4 dy = ((m_texValueMax - m_texValueMin) / h) * yScale; + const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy); + const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx); + const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy); + const tcu::Vec4 dxThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin*xScale, m_texValueMax*xScale, dx); + const tcu::Vec4 dyThresholdW = getDerivateThresholdWarning(m_precision, m_texValueMin*yScale, m_texValueMax*yScale, dy); + const tcu::Vec4 threshold = max(surfaceThreshold, max(dxThreshold, dyThreshold)); + const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW)); + qpTestResult testResult = QP_TEST_RESULT_FAIL; + + testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference, threshold, m_derivScale, m_derivBias); + + if (testResult == QP_TEST_RESULT_PASS) + return testResult; + + // Re-Check with relaxed threshold + testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, + reference, thresholdW, m_derivScale, m_derivBias); + + // If test is passing with relaxed threshold then mark quality warning + if (testResult == QP_TEST_RESULT_PASS) + testResult = QP_TEST_RESULT_QUALITY_WARNING; + + return testResult; } } -- 2.7.4