From: Pyry Haulos Date: Thu, 19 Feb 2015 22:15:03 +0000 (-0800) Subject: Relax fma() verification in builtin_functions.common.fma X-Git-Tag: upstream/0.1.0~1788^2^2^2~5 X-Git-Url: http://review.tizen.org/git/?a=commitdiff_plain;h=e5fc2a804322422a6d50270e9e00fb1c193b6f90;p=platform%2Fupstream%2FVK-GL-CTS.git Relax fma() verification in builtin_functions.common.fma GL_EXT_gpu_shader5 allows fma() to be implemented either as a single, or two correctly-rounded operations. Current tests assumed fma() for lowp and mediump to be implemented as a single operation as no rounding was allowed mid-operation. This change relaxes fma() tests to allow for a*b+c expansion. Bug: 19431850 Change-Id: I46eea74bf3b95bfdbc510e13ef7315854be623ee --- diff --git a/modules/gles31/functional/es31fShaderCommonFunctionTests.cpp b/modules/gles31/functional/es31fShaderCommonFunctionTests.cpp index 3aec886..1bac102 100644 --- a/modules/gles31/functional/es31fShaderCommonFunctionTests.cpp +++ b/modules/gles31/functional/es31fShaderCommonFunctionTests.cpp @@ -27,6 +27,8 @@ #include "tcuTestLog.hpp" #include "tcuFormatUtil.hpp" #include "tcuFloat.hpp" +#include "tcuInterval.hpp" +#include "tcuFloatFormat.hpp" #include "deRandom.hpp" #include "deMath.h" #include "deString.h" @@ -2020,32 +2022,57 @@ public: } } + static tcu::Interval fma (glu::Precision precision, float a, float b, float c) + { + const tcu::FloatFormat formats[] = + { + // minExp maxExp mantissa exact, subnormals infinities NaN + tcu::FloatFormat(0, 0, 7, false, tcu::YES, tcu::MAYBE, tcu::MAYBE), + tcu::FloatFormat(-13, 13, 9, false, tcu::MAYBE, tcu::MAYBE, tcu::MAYBE), + tcu::FloatFormat(-126, 127, 23, true, tcu::MAYBE, tcu::YES, tcu::MAYBE) + }; + const tcu::FloatFormat& format = de::getSizedArrayElement(formats, precision); + const tcu::Interval ia = format.convert(a); + const tcu::Interval ib = format.convert(b); + const tcu::Interval ic = format.convert(c); + tcu::Interval prod0; + tcu::Interval prod1; + tcu::Interval prod2; + tcu::Interval prod3; + tcu::Interval prod; + tcu::Interval res; + + TCU_SET_INTERVAL(prod0, tmp, tmp = ia.lo() * ib.lo()); + TCU_SET_INTERVAL(prod1, tmp, tmp = ia.lo() * ib.hi()); + TCU_SET_INTERVAL(prod2, tmp, tmp = ia.hi() * ib.lo()); + TCU_SET_INTERVAL(prod3, tmp, tmp = ia.hi() * ib.hi()); + + prod = format.convert(format.roundOut(prod0 | prod1 | prod2 | prod3, ia.isFinite() && ib.isFinite())); + + TCU_SET_INTERVAL_BOUNDS(res, tmp, + tmp = prod.lo() + ic.lo(), + tmp = prod.hi() + ic.hi()); + + return format.convert(format.roundOut(res, prod.isFinite() && ic.isFinite())); + } + bool compare (const void* const* inputs, const void* const* outputs) { const glu::DataType type = m_spec.inputs[0].varType.getBasicType(); const glu::Precision precision = m_spec.inputs[0].varType.getPrecision(); const int scalarSize = glu::getDataTypeScalarSize(type); - const bool signedZero = supportsSignedZero(precision); - - const int mantissaBits = getMinMantissaBits(precision); for (int compNdx = 0; compNdx < scalarSize; compNdx++) { - const float a = ((const float*)inputs[0])[compNdx]; - const float b = ((const float*)inputs[1])[compNdx]; - const float c = ((const float*)inputs[2])[compNdx]; - const float res = ((const float*)outputs[0])[compNdx]; - const float ref = a*b + c; - - const int numBitsLost = 1; // allow last bit to vary - const deUint32 maxUlpDiff = getMaxUlpDiffFromBits(de::max(0, mantissaBits-numBitsLost)); + const float a = ((const float*)inputs[0])[compNdx]; + const float b = ((const float*)inputs[1])[compNdx]; + const float c = ((const float*)inputs[2])[compNdx]; + const float res = ((const float*)outputs[0])[compNdx]; + const tcu::Interval ref = fma(precision, a, b, c); - const deUint32 ulpDiff = signedZero ? getUlpDiff(res, ref) : getUlpDiffIgnoreZeroSign(res, ref); - - if (ulpDiff > maxUlpDiff) + if (!ref.contains(res)) { - m_failMsg << "Expected [" << compNdx << "] = " << HexFloat(ref) << " with ULP threshold " - << tcu::toHex(maxUlpDiff) << ", got ULP diff " << tcu::toHex(ulpDiff); + m_failMsg << "Expected [" << compNdx << "] = " << ref; return false; } }