xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fShaderDerivateTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
1*35238bceSAndroid Build Coastguard Worker /*-------------------------------------------------------------------------
2*35238bceSAndroid Build Coastguard Worker  * drawElements Quality Program OpenGL ES 3.0 Module
3*35238bceSAndroid Build Coastguard Worker  * -------------------------------------------------
4*35238bceSAndroid Build Coastguard Worker  *
5*35238bceSAndroid Build Coastguard Worker  * Copyright 2014 The Android Open Source Project
6*35238bceSAndroid Build Coastguard Worker  *
7*35238bceSAndroid Build Coastguard Worker  * Licensed under the Apache License, Version 2.0 (the "License");
8*35238bceSAndroid Build Coastguard Worker  * you may not use this file except in compliance with the License.
9*35238bceSAndroid Build Coastguard Worker  * You may obtain a copy of the License at
10*35238bceSAndroid Build Coastguard Worker  *
11*35238bceSAndroid Build Coastguard Worker  *      http://www.apache.org/licenses/LICENSE-2.0
12*35238bceSAndroid Build Coastguard Worker  *
13*35238bceSAndroid Build Coastguard Worker  * Unless required by applicable law or agreed to in writing, software
14*35238bceSAndroid Build Coastguard Worker  * distributed under the License is distributed on an "AS IS" BASIS,
15*35238bceSAndroid Build Coastguard Worker  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16*35238bceSAndroid Build Coastguard Worker  * See the License for the specific language governing permissions and
17*35238bceSAndroid Build Coastguard Worker  * limitations under the License.
18*35238bceSAndroid Build Coastguard Worker  *
19*35238bceSAndroid Build Coastguard Worker  *//*!
20*35238bceSAndroid Build Coastguard Worker  * \file
21*35238bceSAndroid Build Coastguard Worker  * \brief Shader derivate function tests.
22*35238bceSAndroid Build Coastguard Worker  *
23*35238bceSAndroid Build Coastguard Worker  * \todo [2013-06-25 pyry] Missing features:
24*35238bceSAndroid Build Coastguard Worker  *  - lines and points
25*35238bceSAndroid Build Coastguard Worker  *  - projected coordinates
26*35238bceSAndroid Build Coastguard Worker  *  - continous non-trivial functions (sin, exp)
27*35238bceSAndroid Build Coastguard Worker  *  - non-continous functions (step)
28*35238bceSAndroid Build Coastguard Worker  *//*--------------------------------------------------------------------*/
29*35238bceSAndroid Build Coastguard Worker 
30*35238bceSAndroid Build Coastguard Worker #include "es3fShaderDerivateTests.hpp"
31*35238bceSAndroid Build Coastguard Worker #include "gluShaderProgram.hpp"
32*35238bceSAndroid Build Coastguard Worker #include "gluRenderContext.hpp"
33*35238bceSAndroid Build Coastguard Worker #include "gluDrawUtil.hpp"
34*35238bceSAndroid Build Coastguard Worker #include "gluPixelTransfer.hpp"
35*35238bceSAndroid Build Coastguard Worker #include "gluShaderUtil.hpp"
36*35238bceSAndroid Build Coastguard Worker #include "gluStrUtil.hpp"
37*35238bceSAndroid Build Coastguard Worker #include "gluTextureUtil.hpp"
38*35238bceSAndroid Build Coastguard Worker #include "gluTexture.hpp"
39*35238bceSAndroid Build Coastguard Worker #include "tcuStringTemplate.hpp"
40*35238bceSAndroid Build Coastguard Worker #include "tcuRenderTarget.hpp"
41*35238bceSAndroid Build Coastguard Worker #include "tcuSurface.hpp"
42*35238bceSAndroid Build Coastguard Worker #include "tcuTestLog.hpp"
43*35238bceSAndroid Build Coastguard Worker #include "tcuVectorUtil.hpp"
44*35238bceSAndroid Build Coastguard Worker #include "tcuTextureUtil.hpp"
45*35238bceSAndroid Build Coastguard Worker #include "tcuRGBA.hpp"
46*35238bceSAndroid Build Coastguard Worker #include "tcuFloat.hpp"
47*35238bceSAndroid Build Coastguard Worker #include "tcuInterval.hpp"
48*35238bceSAndroid Build Coastguard Worker #include "deRandom.hpp"
49*35238bceSAndroid Build Coastguard Worker #include "deUniquePtr.hpp"
50*35238bceSAndroid Build Coastguard Worker #include "deString.h"
51*35238bceSAndroid Build Coastguard Worker #include "glwEnums.hpp"
52*35238bceSAndroid Build Coastguard Worker #include "glwFunctions.hpp"
53*35238bceSAndroid Build Coastguard Worker #include "glsShaderRenderCase.hpp" // gls::setupDefaultUniforms()
54*35238bceSAndroid Build Coastguard Worker 
55*35238bceSAndroid Build Coastguard Worker #include <sstream>
56*35238bceSAndroid Build Coastguard Worker 
57*35238bceSAndroid Build Coastguard Worker namespace deqp
58*35238bceSAndroid Build Coastguard Worker {
59*35238bceSAndroid Build Coastguard Worker namespace gles3
60*35238bceSAndroid Build Coastguard Worker {
61*35238bceSAndroid Build Coastguard Worker namespace Functional
62*35238bceSAndroid Build Coastguard Worker {
63*35238bceSAndroid Build Coastguard Worker 
64*35238bceSAndroid Build Coastguard Worker using std::map;
65*35238bceSAndroid Build Coastguard Worker using std::ostringstream;
66*35238bceSAndroid Build Coastguard Worker using std::string;
67*35238bceSAndroid Build Coastguard Worker using std::vector;
68*35238bceSAndroid Build Coastguard Worker using tcu::TestLog;
69*35238bceSAndroid Build Coastguard Worker 
70*35238bceSAndroid Build Coastguard Worker enum
71*35238bceSAndroid Build Coastguard Worker {
72*35238bceSAndroid Build Coastguard Worker     VIEWPORT_WIDTH      = 167,
73*35238bceSAndroid Build Coastguard Worker     VIEWPORT_HEIGHT     = 103,
74*35238bceSAndroid Build Coastguard Worker     FBO_WIDTH           = 99,
75*35238bceSAndroid Build Coastguard Worker     FBO_HEIGHT          = 133,
76*35238bceSAndroid Build Coastguard Worker     MAX_FAILED_MESSAGES = 10
77*35238bceSAndroid Build Coastguard Worker };
78*35238bceSAndroid Build Coastguard Worker 
79*35238bceSAndroid Build Coastguard Worker enum DerivateFunc
80*35238bceSAndroid Build Coastguard Worker {
81*35238bceSAndroid Build Coastguard Worker     DERIVATE_DFDX = 0,
82*35238bceSAndroid Build Coastguard Worker     DERIVATE_DFDY,
83*35238bceSAndroid Build Coastguard Worker     DERIVATE_FWIDTH,
84*35238bceSAndroid Build Coastguard Worker 
85*35238bceSAndroid Build Coastguard Worker     DERIVATE_LAST
86*35238bceSAndroid Build Coastguard Worker };
87*35238bceSAndroid Build Coastguard Worker 
88*35238bceSAndroid Build Coastguard Worker enum SurfaceType
89*35238bceSAndroid Build Coastguard Worker {
90*35238bceSAndroid Build Coastguard Worker     SURFACETYPE_DEFAULT_FRAMEBUFFER = 0,
91*35238bceSAndroid Build Coastguard Worker     SURFACETYPE_UNORM_FBO,
92*35238bceSAndroid Build Coastguard Worker     SURFACETYPE_FLOAT_FBO, // \note Uses RGBA32UI fbo actually, since FP rendertargets are not in core spec.
93*35238bceSAndroid Build Coastguard Worker 
94*35238bceSAndroid Build Coastguard Worker     SURFACETYPE_LAST
95*35238bceSAndroid Build Coastguard Worker };
96*35238bceSAndroid Build Coastguard Worker 
97*35238bceSAndroid Build Coastguard Worker // Utilities
98*35238bceSAndroid Build Coastguard Worker 
99*35238bceSAndroid Build Coastguard Worker namespace
100*35238bceSAndroid Build Coastguard Worker {
101*35238bceSAndroid Build Coastguard Worker 
102*35238bceSAndroid Build Coastguard Worker class AutoFbo
103*35238bceSAndroid Build Coastguard Worker {
104*35238bceSAndroid Build Coastguard Worker public:
AutoFbo(const glw::Functions & gl)105*35238bceSAndroid Build Coastguard Worker     AutoFbo(const glw::Functions &gl) : m_gl(gl), m_fbo(0)
106*35238bceSAndroid Build Coastguard Worker     {
107*35238bceSAndroid Build Coastguard Worker     }
108*35238bceSAndroid Build Coastguard Worker 
~AutoFbo(void)109*35238bceSAndroid Build Coastguard Worker     ~AutoFbo(void)
110*35238bceSAndroid Build Coastguard Worker     {
111*35238bceSAndroid Build Coastguard Worker         if (m_fbo)
112*35238bceSAndroid Build Coastguard Worker             m_gl.deleteFramebuffers(1, &m_fbo);
113*35238bceSAndroid Build Coastguard Worker     }
114*35238bceSAndroid Build Coastguard Worker 
gen(void)115*35238bceSAndroid Build Coastguard Worker     void gen(void)
116*35238bceSAndroid Build Coastguard Worker     {
117*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_fbo);
118*35238bceSAndroid Build Coastguard Worker         m_gl.genFramebuffers(1, &m_fbo);
119*35238bceSAndroid Build Coastguard Worker     }
120*35238bceSAndroid Build Coastguard Worker 
operator *(void) const121*35238bceSAndroid Build Coastguard Worker     uint32_t operator*(void) const
122*35238bceSAndroid Build Coastguard Worker     {
123*35238bceSAndroid Build Coastguard Worker         return m_fbo;
124*35238bceSAndroid Build Coastguard Worker     }
125*35238bceSAndroid Build Coastguard Worker 
126*35238bceSAndroid Build Coastguard Worker private:
127*35238bceSAndroid Build Coastguard Worker     const glw::Functions &m_gl;
128*35238bceSAndroid Build Coastguard Worker     uint32_t m_fbo;
129*35238bceSAndroid Build Coastguard Worker };
130*35238bceSAndroid Build Coastguard Worker 
131*35238bceSAndroid Build Coastguard Worker class AutoRbo
132*35238bceSAndroid Build Coastguard Worker {
133*35238bceSAndroid Build Coastguard Worker public:
AutoRbo(const glw::Functions & gl)134*35238bceSAndroid Build Coastguard Worker     AutoRbo(const glw::Functions &gl) : m_gl(gl), m_rbo(0)
135*35238bceSAndroid Build Coastguard Worker     {
136*35238bceSAndroid Build Coastguard Worker     }
137*35238bceSAndroid Build Coastguard Worker 
~AutoRbo(void)138*35238bceSAndroid Build Coastguard Worker     ~AutoRbo(void)
139*35238bceSAndroid Build Coastguard Worker     {
140*35238bceSAndroid Build Coastguard Worker         if (m_rbo)
141*35238bceSAndroid Build Coastguard Worker             m_gl.deleteRenderbuffers(1, &m_rbo);
142*35238bceSAndroid Build Coastguard Worker     }
143*35238bceSAndroid Build Coastguard Worker 
gen(void)144*35238bceSAndroid Build Coastguard Worker     void gen(void)
145*35238bceSAndroid Build Coastguard Worker     {
146*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_rbo);
147*35238bceSAndroid Build Coastguard Worker         m_gl.genRenderbuffers(1, &m_rbo);
148*35238bceSAndroid Build Coastguard Worker     }
149*35238bceSAndroid Build Coastguard Worker 
operator *(void) const150*35238bceSAndroid Build Coastguard Worker     uint32_t operator*(void) const
151*35238bceSAndroid Build Coastguard Worker     {
152*35238bceSAndroid Build Coastguard Worker         return m_rbo;
153*35238bceSAndroid Build Coastguard Worker     }
154*35238bceSAndroid Build Coastguard Worker 
155*35238bceSAndroid Build Coastguard Worker private:
156*35238bceSAndroid Build Coastguard Worker     const glw::Functions &m_gl;
157*35238bceSAndroid Build Coastguard Worker     uint32_t m_rbo;
158*35238bceSAndroid Build Coastguard Worker };
159*35238bceSAndroid Build Coastguard Worker 
160*35238bceSAndroid Build Coastguard Worker } // namespace
161*35238bceSAndroid Build Coastguard Worker 
getDerivateFuncName(DerivateFunc func)162*35238bceSAndroid Build Coastguard Worker static const char *getDerivateFuncName(DerivateFunc func)
163*35238bceSAndroid Build Coastguard Worker {
164*35238bceSAndroid Build Coastguard Worker     switch (func)
165*35238bceSAndroid Build Coastguard Worker     {
166*35238bceSAndroid Build Coastguard Worker     case DERIVATE_DFDX:
167*35238bceSAndroid Build Coastguard Worker         return "dFdx";
168*35238bceSAndroid Build Coastguard Worker     case DERIVATE_DFDY:
169*35238bceSAndroid Build Coastguard Worker         return "dFdy";
170*35238bceSAndroid Build Coastguard Worker     case DERIVATE_FWIDTH:
171*35238bceSAndroid Build Coastguard Worker         return "fwidth";
172*35238bceSAndroid Build Coastguard Worker     default:
173*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
174*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
175*35238bceSAndroid Build Coastguard Worker     }
176*35238bceSAndroid Build Coastguard Worker }
177*35238bceSAndroid Build Coastguard Worker 
getDerivateFuncCaseName(DerivateFunc func)178*35238bceSAndroid Build Coastguard Worker static const char *getDerivateFuncCaseName(DerivateFunc func)
179*35238bceSAndroid Build Coastguard Worker {
180*35238bceSAndroid Build Coastguard Worker     switch (func)
181*35238bceSAndroid Build Coastguard Worker     {
182*35238bceSAndroid Build Coastguard Worker     case DERIVATE_DFDX:
183*35238bceSAndroid Build Coastguard Worker         return "dfdx";
184*35238bceSAndroid Build Coastguard Worker     case DERIVATE_DFDY:
185*35238bceSAndroid Build Coastguard Worker         return "dfdy";
186*35238bceSAndroid Build Coastguard Worker     case DERIVATE_FWIDTH:
187*35238bceSAndroid Build Coastguard Worker         return "fwidth";
188*35238bceSAndroid Build Coastguard Worker     default:
189*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
190*35238bceSAndroid Build Coastguard Worker         return DE_NULL;
191*35238bceSAndroid Build Coastguard Worker     }
192*35238bceSAndroid Build Coastguard Worker }
193*35238bceSAndroid Build Coastguard Worker 
getDerivateMask(glu::DataType type)194*35238bceSAndroid Build Coastguard Worker static inline tcu::BVec4 getDerivateMask(glu::DataType type)
195*35238bceSAndroid Build Coastguard Worker {
196*35238bceSAndroid Build Coastguard Worker     switch (type)
197*35238bceSAndroid Build Coastguard Worker     {
198*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_FLOAT:
199*35238bceSAndroid Build Coastguard Worker         return tcu::BVec4(true, false, false, false);
200*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_FLOAT_VEC2:
201*35238bceSAndroid Build Coastguard Worker         return tcu::BVec4(true, true, false, false);
202*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_FLOAT_VEC3:
203*35238bceSAndroid Build Coastguard Worker         return tcu::BVec4(true, true, true, false);
204*35238bceSAndroid Build Coastguard Worker     case glu::TYPE_FLOAT_VEC4:
205*35238bceSAndroid Build Coastguard Worker         return tcu::BVec4(true, true, true, true);
206*35238bceSAndroid Build Coastguard Worker     default:
207*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
208*35238bceSAndroid Build Coastguard Worker         return tcu::BVec4(true);
209*35238bceSAndroid Build Coastguard Worker     }
210*35238bceSAndroid Build Coastguard Worker }
211*35238bceSAndroid Build Coastguard Worker 
readDerivate(const tcu::ConstPixelBufferAccess & surface,const tcu::Vec4 & derivScale,const tcu::Vec4 & derivBias,int x,int y)212*35238bceSAndroid Build Coastguard Worker static inline tcu::Vec4 readDerivate(const tcu::ConstPixelBufferAccess &surface, const tcu::Vec4 &derivScale,
213*35238bceSAndroid Build Coastguard Worker                                      const tcu::Vec4 &derivBias, int x, int y)
214*35238bceSAndroid Build Coastguard Worker {
215*35238bceSAndroid Build Coastguard Worker     return (surface.getPixel(x, y) - derivBias) / derivScale;
216*35238bceSAndroid Build Coastguard Worker }
217*35238bceSAndroid Build Coastguard Worker 
getCompExpBits(const tcu::Vec4 & v)218*35238bceSAndroid Build Coastguard Worker static inline tcu::UVec4 getCompExpBits(const tcu::Vec4 &v)
219*35238bceSAndroid Build Coastguard Worker {
220*35238bceSAndroid Build Coastguard Worker     return tcu::UVec4(tcu::Float32(v[0]).exponentBits(), tcu::Float32(v[1]).exponentBits(),
221*35238bceSAndroid Build Coastguard Worker                       tcu::Float32(v[2]).exponentBits(), tcu::Float32(v[3]).exponentBits());
222*35238bceSAndroid Build Coastguard Worker }
223*35238bceSAndroid Build Coastguard Worker 
computeFloatingPointError(const float value,const int numAccurateBits)224*35238bceSAndroid Build Coastguard Worker float computeFloatingPointError(const float value, const int numAccurateBits)
225*35238bceSAndroid Build Coastguard Worker {
226*35238bceSAndroid Build Coastguard Worker     const int numGarbageBits = 23 - numAccurateBits;
227*35238bceSAndroid Build Coastguard Worker     const uint32_t mask      = (1u << numGarbageBits) - 1u;
228*35238bceSAndroid Build Coastguard Worker     const int exp            = (tcu::Float32(value).exponent() < -3) ? -3 : tcu::Float32(value).exponent();
229*35238bceSAndroid Build Coastguard Worker 
230*35238bceSAndroid Build Coastguard Worker     return tcu::Float32::construct(+1, exp, (1u << 23) | mask).asFloat() -
231*35238bceSAndroid Build Coastguard Worker            tcu::Float32::construct(+1, exp, 1u << 23).asFloat();
232*35238bceSAndroid Build Coastguard Worker }
233*35238bceSAndroid Build Coastguard Worker 
getNumMantissaBits(const glu::Precision precision)234*35238bceSAndroid Build Coastguard Worker static int getNumMantissaBits(const glu::Precision precision)
235*35238bceSAndroid Build Coastguard Worker {
236*35238bceSAndroid Build Coastguard Worker     switch (precision)
237*35238bceSAndroid Build Coastguard Worker     {
238*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_HIGHP:
239*35238bceSAndroid Build Coastguard Worker         return 23;
240*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_MEDIUMP:
241*35238bceSAndroid Build Coastguard Worker         return 10;
242*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_LOWP:
243*35238bceSAndroid Build Coastguard Worker         return 6;
244*35238bceSAndroid Build Coastguard Worker     default:
245*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
246*35238bceSAndroid Build Coastguard Worker         return 0;
247*35238bceSAndroid Build Coastguard Worker     }
248*35238bceSAndroid Build Coastguard Worker }
249*35238bceSAndroid Build Coastguard Worker 
getMinExponent(const glu::Precision precision)250*35238bceSAndroid Build Coastguard Worker static int getMinExponent(const glu::Precision precision)
251*35238bceSAndroid Build Coastguard Worker {
252*35238bceSAndroid Build Coastguard Worker     switch (precision)
253*35238bceSAndroid Build Coastguard Worker     {
254*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_HIGHP:
255*35238bceSAndroid Build Coastguard Worker         return -126;
256*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_MEDIUMP:
257*35238bceSAndroid Build Coastguard Worker         return -14;
258*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_LOWP:
259*35238bceSAndroid Build Coastguard Worker         return -8;
260*35238bceSAndroid Build Coastguard Worker     default:
261*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
262*35238bceSAndroid Build Coastguard Worker         return 0;
263*35238bceSAndroid Build Coastguard Worker     }
264*35238bceSAndroid Build Coastguard Worker }
265*35238bceSAndroid Build Coastguard Worker 
getSingleULPForExponent(int exp,int numMantissaBits)266*35238bceSAndroid Build Coastguard Worker static float getSingleULPForExponent(int exp, int numMantissaBits)
267*35238bceSAndroid Build Coastguard Worker {
268*35238bceSAndroid Build Coastguard Worker     if (numMantissaBits > 0)
269*35238bceSAndroid Build Coastguard Worker     {
270*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(numMantissaBits <= 23);
271*35238bceSAndroid Build Coastguard Worker 
272*35238bceSAndroid Build Coastguard Worker         const int ulpBitNdx = 23 - numMantissaBits;
273*35238bceSAndroid Build Coastguard Worker         return tcu::Float32::construct(+1, exp, (1 << 23) | (1 << ulpBitNdx)).asFloat() -
274*35238bceSAndroid Build Coastguard Worker                tcu::Float32::construct(+1, exp, (1 << 23)).asFloat();
275*35238bceSAndroid Build Coastguard Worker     }
276*35238bceSAndroid Build Coastguard Worker     else
277*35238bceSAndroid Build Coastguard Worker     {
278*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(numMantissaBits == 0);
279*35238bceSAndroid Build Coastguard Worker         return tcu::Float32::construct(+1, exp, (1 << 23)).asFloat();
280*35238bceSAndroid Build Coastguard Worker     }
281*35238bceSAndroid Build Coastguard Worker }
282*35238bceSAndroid Build Coastguard Worker 
getSingleULPForValue(float value,int numMantissaBits)283*35238bceSAndroid Build Coastguard Worker static float getSingleULPForValue(float value, int numMantissaBits)
284*35238bceSAndroid Build Coastguard Worker {
285*35238bceSAndroid Build Coastguard Worker     const int exp = tcu::Float32(value).exponent();
286*35238bceSAndroid Build Coastguard Worker     return getSingleULPForExponent(exp, numMantissaBits);
287*35238bceSAndroid Build Coastguard Worker }
288*35238bceSAndroid Build Coastguard Worker 
convertFloatFlushToZeroRtn(float value,int minExponent,int numAccurateBits)289*35238bceSAndroid Build Coastguard Worker static float convertFloatFlushToZeroRtn(float value, int minExponent, int numAccurateBits)
290*35238bceSAndroid Build Coastguard Worker {
291*35238bceSAndroid Build Coastguard Worker     if (value == 0.0f)
292*35238bceSAndroid Build Coastguard Worker     {
293*35238bceSAndroid Build Coastguard Worker         return 0.0f;
294*35238bceSAndroid Build Coastguard Worker     }
295*35238bceSAndroid Build Coastguard Worker     else
296*35238bceSAndroid Build Coastguard Worker     {
297*35238bceSAndroid Build Coastguard Worker         const tcu::Float32 inputFloat = tcu::Float32(value);
298*35238bceSAndroid Build Coastguard Worker         const int numTruncatedBits    = 23 - numAccurateBits;
299*35238bceSAndroid Build Coastguard Worker         const uint32_t truncMask      = (1u << numTruncatedBits) - 1u;
300*35238bceSAndroid Build Coastguard Worker 
301*35238bceSAndroid Build Coastguard Worker         if (value > 0.0f)
302*35238bceSAndroid Build Coastguard Worker         {
303*35238bceSAndroid Build Coastguard Worker             if (value > 0.0f && tcu::Float32(value).exponent() < minExponent)
304*35238bceSAndroid Build Coastguard Worker             {
305*35238bceSAndroid Build Coastguard Worker                 // flush to zero if possible
306*35238bceSAndroid Build Coastguard Worker                 return 0.0f;
307*35238bceSAndroid Build Coastguard Worker             }
308*35238bceSAndroid Build Coastguard Worker             else
309*35238bceSAndroid Build Coastguard Worker             {
310*35238bceSAndroid Build Coastguard Worker                 // just mask away non-representable bits
311*35238bceSAndroid Build Coastguard Worker                 return tcu::Float32::construct(+1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask).asFloat();
312*35238bceSAndroid Build Coastguard Worker             }
313*35238bceSAndroid Build Coastguard Worker         }
314*35238bceSAndroid Build Coastguard Worker         else
315*35238bceSAndroid Build Coastguard Worker         {
316*35238bceSAndroid Build Coastguard Worker             if (inputFloat.mantissa() & truncMask)
317*35238bceSAndroid Build Coastguard Worker             {
318*35238bceSAndroid Build Coastguard Worker                 // decrement one ulp if truncated bits are non-zero (i.e. if value is not representable)
319*35238bceSAndroid Build Coastguard Worker                 return tcu::Float32::construct(-1, inputFloat.exponent(), inputFloat.mantissa() & ~truncMask)
320*35238bceSAndroid Build Coastguard Worker                            .asFloat() -
321*35238bceSAndroid Build Coastguard Worker                        getSingleULPForExponent(inputFloat.exponent(), numAccurateBits);
322*35238bceSAndroid Build Coastguard Worker             }
323*35238bceSAndroid Build Coastguard Worker             else
324*35238bceSAndroid Build Coastguard Worker             {
325*35238bceSAndroid Build Coastguard Worker                 // value is representable, no need to do anything
326*35238bceSAndroid Build Coastguard Worker                 return value;
327*35238bceSAndroid Build Coastguard Worker             }
328*35238bceSAndroid Build Coastguard Worker         }
329*35238bceSAndroid Build Coastguard Worker     }
330*35238bceSAndroid Build Coastguard Worker }
331*35238bceSAndroid Build Coastguard Worker 
convertFloatFlushToZeroRtp(float value,int minExponent,int numAccurateBits)332*35238bceSAndroid Build Coastguard Worker static float convertFloatFlushToZeroRtp(float value, int minExponent, int numAccurateBits)
333*35238bceSAndroid Build Coastguard Worker {
334*35238bceSAndroid Build Coastguard Worker     return -convertFloatFlushToZeroRtn(-value, minExponent, numAccurateBits);
335*35238bceSAndroid Build Coastguard Worker }
336*35238bceSAndroid Build Coastguard Worker 
addErrorUlp(float value,float numUlps,int numMantissaBits)337*35238bceSAndroid Build Coastguard Worker static float addErrorUlp(float value, float numUlps, int numMantissaBits)
338*35238bceSAndroid Build Coastguard Worker {
339*35238bceSAndroid Build Coastguard Worker     return value + numUlps * getSingleULPForValue(value, numMantissaBits);
340*35238bceSAndroid Build Coastguard Worker }
341*35238bceSAndroid Build Coastguard Worker 
342*35238bceSAndroid Build Coastguard Worker enum
343*35238bceSAndroid Build Coastguard Worker {
344*35238bceSAndroid Build Coastguard Worker     INTERPOLATION_LOST_BITS = 3, // number mantissa of bits allowed to be lost in varying interpolation
345*35238bceSAndroid Build Coastguard Worker };
346*35238bceSAndroid Build Coastguard Worker 
getInterpolationLostBitsWarning(const glu::Precision precision)347*35238bceSAndroid Build Coastguard Worker static int getInterpolationLostBitsWarning(const glu::Precision precision)
348*35238bceSAndroid Build Coastguard Worker {
349*35238bceSAndroid Build Coastguard Worker     // number mantissa of bits allowed to be lost in varying interpolation
350*35238bceSAndroid Build Coastguard Worker     switch (precision)
351*35238bceSAndroid Build Coastguard Worker     {
352*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_HIGHP:
353*35238bceSAndroid Build Coastguard Worker         return 9;
354*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_MEDIUMP:
355*35238bceSAndroid Build Coastguard Worker         return 3;
356*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_LOWP:
357*35238bceSAndroid Build Coastguard Worker         return 3;
358*35238bceSAndroid Build Coastguard Worker     default:
359*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
360*35238bceSAndroid Build Coastguard Worker         return 0;
361*35238bceSAndroid Build Coastguard Worker     }
362*35238bceSAndroid Build Coastguard Worker }
363*35238bceSAndroid Build Coastguard Worker 
getDerivateThreshold(const glu::Precision precision,const tcu::Vec4 & valueMin,const tcu::Vec4 & valueMax,const tcu::Vec4 & expectedDerivate)364*35238bceSAndroid Build Coastguard Worker static inline tcu::Vec4 getDerivateThreshold(const glu::Precision precision, const tcu::Vec4 &valueMin,
365*35238bceSAndroid Build Coastguard Worker                                              const tcu::Vec4 &valueMax, const tcu::Vec4 &expectedDerivate)
366*35238bceSAndroid Build Coastguard Worker {
367*35238bceSAndroid Build Coastguard Worker     const int baseBits           = getNumMantissaBits(precision);
368*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 derivExp    = getCompExpBits(expectedDerivate);
369*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 maxValueExp = max(getCompExpBits(valueMin), getCompExpBits(valueMax));
370*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 numBitsLost = maxValueExp - min(maxValueExp, derivExp);
371*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 numAccurateBits =
372*35238bceSAndroid Build Coastguard Worker         max(baseBits - numBitsLost.asInt() - (int)INTERPOLATION_LOST_BITS, tcu::IVec4(0));
373*35238bceSAndroid Build Coastguard Worker 
374*35238bceSAndroid Build Coastguard Worker     return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]),
375*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]),
376*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]),
377*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[3], numAccurateBits[3]));
378*35238bceSAndroid Build Coastguard Worker }
379*35238bceSAndroid Build Coastguard Worker 
getDerivateThresholdWarning(const glu::Precision precision,const tcu::Vec4 & valueMin,const tcu::Vec4 & valueMax,const tcu::Vec4 & expectedDerivate)380*35238bceSAndroid Build Coastguard Worker static inline tcu::Vec4 getDerivateThresholdWarning(const glu::Precision precision, const tcu::Vec4 &valueMin,
381*35238bceSAndroid Build Coastguard Worker                                                     const tcu::Vec4 &valueMax, const tcu::Vec4 &expectedDerivate)
382*35238bceSAndroid Build Coastguard Worker {
383*35238bceSAndroid Build Coastguard Worker     const int baseBits           = getNumMantissaBits(precision);
384*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 derivExp    = getCompExpBits(expectedDerivate);
385*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 maxValueExp = max(getCompExpBits(valueMin), getCompExpBits(valueMax));
386*35238bceSAndroid Build Coastguard Worker     const tcu::UVec4 numBitsLost = maxValueExp - min(maxValueExp, derivExp);
387*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 numAccurateBits =
388*35238bceSAndroid Build Coastguard Worker         max(baseBits - numBitsLost.asInt() - getInterpolationLostBitsWarning(precision), tcu::IVec4(0));
389*35238bceSAndroid Build Coastguard Worker 
390*35238bceSAndroid Build Coastguard Worker     return tcu::Vec4(computeFloatingPointError(expectedDerivate[0], numAccurateBits[0]),
391*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[1], numAccurateBits[1]),
392*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[2], numAccurateBits[2]),
393*35238bceSAndroid Build Coastguard Worker                      computeFloatingPointError(expectedDerivate[3], numAccurateBits[3]));
394*35238bceSAndroid Build Coastguard Worker }
395*35238bceSAndroid Build Coastguard Worker 
396*35238bceSAndroid Build Coastguard Worker namespace
397*35238bceSAndroid Build Coastguard Worker {
398*35238bceSAndroid Build Coastguard Worker 
399*35238bceSAndroid Build Coastguard Worker struct LogVecComps
400*35238bceSAndroid Build Coastguard Worker {
401*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 &v;
402*35238bceSAndroid Build Coastguard Worker     int numComps;
403*35238bceSAndroid Build Coastguard Worker 
LogVecCompsdeqp::gles3::Functional::__anonf22f2d770411::LogVecComps404*35238bceSAndroid Build Coastguard Worker     LogVecComps(const tcu::Vec4 &v_, int numComps_) : v(v_), numComps(numComps_)
405*35238bceSAndroid Build Coastguard Worker     {
406*35238bceSAndroid Build Coastguard Worker     }
407*35238bceSAndroid Build Coastguard Worker };
408*35238bceSAndroid Build Coastguard Worker 
operator <<(std::ostream & str,const LogVecComps & v)409*35238bceSAndroid Build Coastguard Worker std::ostream &operator<<(std::ostream &str, const LogVecComps &v)
410*35238bceSAndroid Build Coastguard Worker {
411*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(de::inRange(v.numComps, 1, 4));
412*35238bceSAndroid Build Coastguard Worker     if (v.numComps == 1)
413*35238bceSAndroid Build Coastguard Worker         return str << v.v[0];
414*35238bceSAndroid Build Coastguard Worker     else if (v.numComps == 2)
415*35238bceSAndroid Build Coastguard Worker         return str << v.v.toWidth<2>();
416*35238bceSAndroid Build Coastguard Worker     else if (v.numComps == 3)
417*35238bceSAndroid Build Coastguard Worker         return str << v.v.toWidth<3>();
418*35238bceSAndroid Build Coastguard Worker     else
419*35238bceSAndroid Build Coastguard Worker         return str << v.v;
420*35238bceSAndroid Build Coastguard Worker }
421*35238bceSAndroid Build Coastguard Worker 
422*35238bceSAndroid Build Coastguard Worker } // namespace
423*35238bceSAndroid Build Coastguard Worker 
424*35238bceSAndroid Build Coastguard Worker enum VerificationLogging
425*35238bceSAndroid Build Coastguard Worker {
426*35238bceSAndroid Build Coastguard Worker     LOG_ALL = 0,
427*35238bceSAndroid Build Coastguard Worker     LOG_NOTHING
428*35238bceSAndroid Build Coastguard Worker };
429*35238bceSAndroid Build Coastguard Worker 
verifyConstantDerivate(tcu::TestLog & log,const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask,glu::DataType dataType,const tcu::Vec4 & reference,const tcu::Vec4 & threshold,const tcu::Vec4 & scale,const tcu::Vec4 & bias,VerificationLogging logPolicy=LOG_ALL)430*35238bceSAndroid Build Coastguard Worker static qpTestResult verifyConstantDerivate(tcu::TestLog &log, const tcu::ConstPixelBufferAccess &result,
431*35238bceSAndroid Build Coastguard Worker                                            const tcu::PixelBufferAccess &errorMask, glu::DataType dataType,
432*35238bceSAndroid Build Coastguard Worker                                            const tcu::Vec4 &reference, const tcu::Vec4 &threshold,
433*35238bceSAndroid Build Coastguard Worker                                            const tcu::Vec4 &scale, const tcu::Vec4 &bias,
434*35238bceSAndroid Build Coastguard Worker                                            VerificationLogging logPolicy = LOG_ALL)
435*35238bceSAndroid Build Coastguard Worker {
436*35238bceSAndroid Build Coastguard Worker     const int numComps    = glu::getDataTypeFloatScalars(dataType);
437*35238bceSAndroid Build Coastguard Worker     const tcu::BVec4 mask = tcu::logicalNot(getDerivateMask(dataType));
438*35238bceSAndroid Build Coastguard Worker     int numFailedPixels   = 0;
439*35238bceSAndroid Build Coastguard Worker 
440*35238bceSAndroid Build Coastguard Worker     if (logPolicy == LOG_ALL)
441*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "Expecting " << LogVecComps(reference, numComps) << " with threshold "
442*35238bceSAndroid Build Coastguard Worker             << LogVecComps(threshold, numComps) << TestLog::EndMessage;
443*35238bceSAndroid Build Coastguard Worker 
444*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < result.getHeight(); y++)
445*35238bceSAndroid Build Coastguard Worker     {
446*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < result.getWidth(); x++)
447*35238bceSAndroid Build Coastguard Worker         {
448*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 resDerivate = readDerivate(result, scale, bias, x, y);
449*35238bceSAndroid Build Coastguard Worker             const bool isOk =
450*35238bceSAndroid Build Coastguard Worker                 tcu::allEqual(tcu::logicalOr(tcu::lessThanEqual(tcu::abs(reference - resDerivate), threshold), mask),
451*35238bceSAndroid Build Coastguard Worker                               tcu::BVec4(true));
452*35238bceSAndroid Build Coastguard Worker 
453*35238bceSAndroid Build Coastguard Worker             if (!isOk)
454*35238bceSAndroid Build Coastguard Worker             {
455*35238bceSAndroid Build Coastguard Worker                 if (numFailedPixels < MAX_FAILED_MESSAGES && logPolicy == LOG_ALL)
456*35238bceSAndroid Build Coastguard Worker                     log << TestLog::Message << "FAIL: got " << LogVecComps(resDerivate, numComps)
457*35238bceSAndroid Build Coastguard Worker                         << ", diff = " << LogVecComps(tcu::abs(reference - resDerivate), numComps) << ", at x = " << x
458*35238bceSAndroid Build Coastguard Worker                         << ", y = " << y << TestLog::EndMessage;
459*35238bceSAndroid Build Coastguard Worker                 numFailedPixels += 1;
460*35238bceSAndroid Build Coastguard Worker                 errorMask.setPixel(tcu::RGBA::red().toVec(), x, y);
461*35238bceSAndroid Build Coastguard Worker             }
462*35238bceSAndroid Build Coastguard Worker         }
463*35238bceSAndroid Build Coastguard Worker     }
464*35238bceSAndroid Build Coastguard Worker 
465*35238bceSAndroid Build Coastguard Worker     if (numFailedPixels >= MAX_FAILED_MESSAGES && logPolicy == LOG_ALL)
466*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "..." << TestLog::EndMessage;
467*35238bceSAndroid Build Coastguard Worker 
468*35238bceSAndroid Build Coastguard Worker     if (numFailedPixels > 0 && logPolicy == LOG_ALL)
469*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
470*35238bceSAndroid Build Coastguard Worker 
471*35238bceSAndroid Build Coastguard Worker     return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
472*35238bceSAndroid Build Coastguard Worker }
473*35238bceSAndroid Build Coastguard Worker 
474*35238bceSAndroid Build Coastguard Worker struct Linear2DFunctionEvaluator
475*35238bceSAndroid Build Coastguard Worker {
476*35238bceSAndroid Build Coastguard Worker     tcu::Matrix<float, 4, 3> matrix;
477*35238bceSAndroid Build Coastguard Worker 
478*35238bceSAndroid Build Coastguard Worker     //      .-----.
479*35238bceSAndroid Build Coastguard Worker     //      | s_x |
480*35238bceSAndroid Build Coastguard Worker     //  M x | s_y |
481*35238bceSAndroid Build Coastguard Worker     //      | 1.0 |
482*35238bceSAndroid Build Coastguard Worker     //      '-----'
483*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 evaluateAt(float screenX, float screenY) const;
484*35238bceSAndroid Build Coastguard Worker };
485*35238bceSAndroid Build Coastguard Worker 
evaluateAt(float screenX,float screenY) const486*35238bceSAndroid Build Coastguard Worker tcu::Vec4 Linear2DFunctionEvaluator::evaluateAt(float screenX, float screenY) const
487*35238bceSAndroid Build Coastguard Worker {
488*35238bceSAndroid Build Coastguard Worker     const tcu::Vec3 position(screenX, screenY, 1.0f);
489*35238bceSAndroid Build Coastguard Worker     return matrix * position;
490*35238bceSAndroid Build Coastguard Worker }
491*35238bceSAndroid Build Coastguard Worker 
reverifyConstantDerivateWithFlushRelaxations(tcu::TestLog & log,const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask,glu::DataType dataType,glu::Precision precision,const tcu::Vec4 & derivScale,const tcu::Vec4 & derivBias,const tcu::Vec4 & surfaceThreshold,DerivateFunc derivateFunc,const Linear2DFunctionEvaluator & function)492*35238bceSAndroid Build Coastguard Worker static qpTestResult reverifyConstantDerivateWithFlushRelaxations(
493*35238bceSAndroid Build Coastguard Worker     tcu::TestLog &log, const tcu::ConstPixelBufferAccess &result, const tcu::PixelBufferAccess &errorMask,
494*35238bceSAndroid Build Coastguard Worker     glu::DataType dataType, glu::Precision precision, const tcu::Vec4 &derivScale, const tcu::Vec4 &derivBias,
495*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 &surfaceThreshold, DerivateFunc derivateFunc, const Linear2DFunctionEvaluator &function)
496*35238bceSAndroid Build Coastguard Worker {
497*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(result.getWidth() == errorMask.getWidth());
498*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(result.getHeight() == errorMask.getHeight());
499*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(derivateFunc == DERIVATE_DFDX || derivateFunc == DERIVATE_DFDY);
500*35238bceSAndroid Build Coastguard Worker 
501*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 red(255, 0, 0, 255);
502*35238bceSAndroid Build Coastguard Worker     const tcu::IVec4 green(0, 255, 0, 255);
503*35238bceSAndroid Build Coastguard Worker     const float divisionErrorUlps = 2.5f;
504*35238bceSAndroid Build Coastguard Worker 
505*35238bceSAndroid Build Coastguard Worker     const int numComponents = glu::getDataTypeFloatScalars(dataType);
506*35238bceSAndroid Build Coastguard Worker     const int numBits       = getNumMantissaBits(precision);
507*35238bceSAndroid Build Coastguard Worker     const int minExponent   = getMinExponent(precision);
508*35238bceSAndroid Build Coastguard Worker 
509*35238bceSAndroid Build Coastguard Worker     const int numVaryingSampleBits = numBits - INTERPOLATION_LOST_BITS;
510*35238bceSAndroid Build Coastguard Worker     int numFailedPixels            = 0;
511*35238bceSAndroid Build Coastguard Worker 
512*35238bceSAndroid Build Coastguard Worker     tcu::clear(errorMask, green);
513*35238bceSAndroid Build Coastguard Worker 
514*35238bceSAndroid Build Coastguard Worker     // search for failed pixels
515*35238bceSAndroid Build Coastguard Worker     for (int y = 0; y < result.getHeight(); ++y)
516*35238bceSAndroid Build Coastguard Worker         for (int x = 0; x < result.getWidth(); ++x)
517*35238bceSAndroid Build Coastguard Worker         {
518*35238bceSAndroid Build Coastguard Worker             //                 flushToZero?(f2z?(functionValueCurrent) - f2z?(functionValueBefore))
519*35238bceSAndroid Build Coastguard Worker             // flushToZero? ( ------------------------------------------------------------------------ +- 2.5 ULP )
520*35238bceSAndroid Build Coastguard Worker             //                                                  dx
521*35238bceSAndroid Build Coastguard Worker 
522*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 resultDerivative = readDerivate(result, derivScale, derivBias, x, y);
523*35238bceSAndroid Build Coastguard Worker 
524*35238bceSAndroid Build Coastguard Worker             // sample at the front of the back pixel and the back of the front pixel to cover the whole area of
525*35238bceSAndroid Build Coastguard Worker             // legal sample positions. In general case this is NOT OK, but we know that the target function is
526*35238bceSAndroid Build Coastguard Worker             // (mostly*) linear which allows us to take the sample points at arbitrary points. This gets us the
527*35238bceSAndroid Build Coastguard Worker             // maximum difference possible in exponents which are used in error bound calculations.
528*35238bceSAndroid Build Coastguard Worker             // * non-linearity may happen around zero or with very high function values due to subnorms not
529*35238bceSAndroid Build Coastguard Worker             //   behaving well.
530*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 functionValueForward  = (derivateFunc == DERIVATE_DFDX) ?
531*35238bceSAndroid Build Coastguard Worker                                                         (function.evaluateAt((float)x + 2.0f, (float)y + 0.5f)) :
532*35238bceSAndroid Build Coastguard Worker                                                         (function.evaluateAt((float)x + 0.5f, (float)y + 2.0f));
533*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 functionValueBackward = (derivateFunc == DERIVATE_DFDX) ?
534*35238bceSAndroid Build Coastguard Worker                                                         (function.evaluateAt((float)x - 1.0f, (float)y + 0.5f)) :
535*35238bceSAndroid Build Coastguard Worker                                                         (function.evaluateAt((float)x + 0.5f, (float)y - 1.0f));
536*35238bceSAndroid Build Coastguard Worker 
537*35238bceSAndroid Build Coastguard Worker             bool anyComponentFailed = false;
538*35238bceSAndroid Build Coastguard Worker 
539*35238bceSAndroid Build Coastguard Worker             // check components separately
540*35238bceSAndroid Build Coastguard Worker             for (int c = 0; c < numComponents; ++c)
541*35238bceSAndroid Build Coastguard Worker             {
542*35238bceSAndroid Build Coastguard Worker                 // Simulate interpolation. Add allowed interpolation error and round to target precision. Allow one half ULP (i.e. correct rounding)
543*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval forwardComponent(
544*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtn(addErrorUlp((float)functionValueForward[c], -0.5f, numVaryingSampleBits),
545*35238bceSAndroid Build Coastguard Worker                                                minExponent, numBits),
546*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtp(addErrorUlp((float)functionValueForward[c], +0.5f, numVaryingSampleBits),
547*35238bceSAndroid Build Coastguard Worker                                                minExponent, numBits));
548*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval backwardComponent(
549*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtn(
550*35238bceSAndroid Build Coastguard Worker                         addErrorUlp((float)functionValueBackward[c], -0.5f, numVaryingSampleBits), minExponent,
551*35238bceSAndroid Build Coastguard Worker                         numBits),
552*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtp(
553*35238bceSAndroid Build Coastguard Worker                         addErrorUlp((float)functionValueBackward[c], +0.5f, numVaryingSampleBits), minExponent,
554*35238bceSAndroid Build Coastguard Worker                         numBits));
555*35238bceSAndroid Build Coastguard Worker                 const int maxValueExp = de::max(de::max(tcu::Float32(forwardComponent.lo()).exponent(),
556*35238bceSAndroid Build Coastguard Worker                                                         tcu::Float32(forwardComponent.hi()).exponent()),
557*35238bceSAndroid Build Coastguard Worker                                                 de::max(tcu::Float32(backwardComponent.lo()).exponent(),
558*35238bceSAndroid Build Coastguard Worker                                                         tcu::Float32(backwardComponent.hi()).exponent()));
559*35238bceSAndroid Build Coastguard Worker 
560*35238bceSAndroid Build Coastguard Worker                 // subtraction in numerator will likely cause a cancellation of the most
561*35238bceSAndroid Build Coastguard Worker                 // significant bits. Apply error bounds.
562*35238bceSAndroid Build Coastguard Worker 
563*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval numerator(forwardComponent - backwardComponent);
564*35238bceSAndroid Build Coastguard Worker                 const int numeratorLoExp      = tcu::Float32(numerator.lo()).exponent();
565*35238bceSAndroid Build Coastguard Worker                 const int numeratorHiExp      = tcu::Float32(numerator.hi()).exponent();
566*35238bceSAndroid Build Coastguard Worker                 const int numeratorLoBitsLost = de::max(
567*35238bceSAndroid Build Coastguard Worker                     0,
568*35238bceSAndroid Build Coastguard Worker                     maxValueExp -
569*35238bceSAndroid Build Coastguard Worker                         numeratorLoExp); //!< must clamp to zero since if forward and backward components have different
570*35238bceSAndroid Build Coastguard Worker                 const int numeratorHiBitsLost = de::max(
571*35238bceSAndroid Build Coastguard Worker                     0, maxValueExp - numeratorHiExp); //!< sign, numerator might have larger exponent than its operands.
572*35238bceSAndroid Build Coastguard Worker                 const int numeratorLoBits = de::max(0, numBits - numeratorLoBitsLost);
573*35238bceSAndroid Build Coastguard Worker                 const int numeratorHiBits = de::max(0, numBits - numeratorHiBitsLost);
574*35238bceSAndroid Build Coastguard Worker 
575*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval numeratorRange(
576*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtn((float)numerator.lo(), minExponent, numeratorLoBits),
577*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtp((float)numerator.hi(), minExponent, numeratorHiBits));
578*35238bceSAndroid Build Coastguard Worker 
579*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval divisionRange =
580*35238bceSAndroid Build Coastguard Worker                     numeratorRange /
581*35238bceSAndroid Build Coastguard Worker                     3.0f; // legal sample area is anywhere within this and neighboring pixels (i.e. size = 3)
582*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval divisionResultRange(
583*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtn(addErrorUlp((float)divisionRange.lo(), -divisionErrorUlps, numBits),
584*35238bceSAndroid Build Coastguard Worker                                                minExponent, numBits),
585*35238bceSAndroid Build Coastguard Worker                     convertFloatFlushToZeroRtp(addErrorUlp((float)divisionRange.hi(), +divisionErrorUlps, numBits),
586*35238bceSAndroid Build Coastguard Worker                                                minExponent, numBits));
587*35238bceSAndroid Build Coastguard Worker                 const tcu::Interval finalResultRange(divisionResultRange.lo() - surfaceThreshold[c],
588*35238bceSAndroid Build Coastguard Worker                                                      divisionResultRange.hi() + surfaceThreshold[c]);
589*35238bceSAndroid Build Coastguard Worker 
590*35238bceSAndroid Build Coastguard Worker                 if (resultDerivative[c] >= finalResultRange.lo() && resultDerivative[c] <= finalResultRange.hi())
591*35238bceSAndroid Build Coastguard Worker                 {
592*35238bceSAndroid Build Coastguard Worker                     // value ok
593*35238bceSAndroid Build Coastguard Worker                 }
594*35238bceSAndroid Build Coastguard Worker                 else
595*35238bceSAndroid Build Coastguard Worker                 {
596*35238bceSAndroid Build Coastguard Worker                     if (numFailedPixels < MAX_FAILED_MESSAGES)
597*35238bceSAndroid Build Coastguard Worker                         log << tcu::TestLog::Message << "Error in pixel at " << x << ", " << y << " with component "
598*35238bceSAndroid Build Coastguard Worker                             << c << " (channel " << ("rgba"[c]) << ")\n"
599*35238bceSAndroid Build Coastguard Worker                             << "\tGot pixel value " << result.getPixelInt(x, y) << "\n"
600*35238bceSAndroid Build Coastguard Worker                             << "\t\tdFd" << ((derivateFunc == DERIVATE_DFDX) ? ('x') : ('y'))
601*35238bceSAndroid Build Coastguard Worker                             << " ~= " << resultDerivative[c] << "\n"
602*35238bceSAndroid Build Coastguard Worker                             << "\t\tdifference to a valid range: "
603*35238bceSAndroid Build Coastguard Worker                             << ((resultDerivative[c] < finalResultRange.lo()) ? ("-") : ("+"))
604*35238bceSAndroid Build Coastguard Worker                             << ((resultDerivative[c] < finalResultRange.lo()) ?
605*35238bceSAndroid Build Coastguard Worker                                     (finalResultRange.lo() - resultDerivative[c]) :
606*35238bceSAndroid Build Coastguard Worker                                     (resultDerivative[c] - finalResultRange.hi()))
607*35238bceSAndroid Build Coastguard Worker                             << "\n"
608*35238bceSAndroid Build Coastguard Worker                             << "\tDerivative value range:\n"
609*35238bceSAndroid Build Coastguard Worker                             << "\t\tMin: " << finalResultRange.lo() << "\n"
610*35238bceSAndroid Build Coastguard Worker                             << "\t\tMax: " << finalResultRange.hi() << "\n"
611*35238bceSAndroid Build Coastguard Worker                             << tcu::TestLog::EndMessage;
612*35238bceSAndroid Build Coastguard Worker 
613*35238bceSAndroid Build Coastguard Worker                     ++numFailedPixels;
614*35238bceSAndroid Build Coastguard Worker                     anyComponentFailed = true;
615*35238bceSAndroid Build Coastguard Worker                 }
616*35238bceSAndroid Build Coastguard Worker             }
617*35238bceSAndroid Build Coastguard Worker 
618*35238bceSAndroid Build Coastguard Worker             if (anyComponentFailed)
619*35238bceSAndroid Build Coastguard Worker                 errorMask.setPixel(red, x, y);
620*35238bceSAndroid Build Coastguard Worker         }
621*35238bceSAndroid Build Coastguard Worker 
622*35238bceSAndroid Build Coastguard Worker     if (numFailedPixels >= MAX_FAILED_MESSAGES)
623*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "..." << TestLog::EndMessage;
624*35238bceSAndroid Build Coastguard Worker 
625*35238bceSAndroid Build Coastguard Worker     if (numFailedPixels > 0)
626*35238bceSAndroid Build Coastguard Worker         log << TestLog::Message << "FAIL: found " << numFailedPixels << " failed pixels" << TestLog::EndMessage;
627*35238bceSAndroid Build Coastguard Worker 
628*35238bceSAndroid Build Coastguard Worker     return (numFailedPixels == 0) ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL;
629*35238bceSAndroid Build Coastguard Worker }
630*35238bceSAndroid Build Coastguard Worker 
631*35238bceSAndroid Build Coastguard Worker // TriangleDerivateCase
632*35238bceSAndroid Build Coastguard Worker 
633*35238bceSAndroid Build Coastguard Worker class TriangleDerivateCase : public TestCase
634*35238bceSAndroid Build Coastguard Worker {
635*35238bceSAndroid Build Coastguard Worker public:
636*35238bceSAndroid Build Coastguard Worker     TriangleDerivateCase(Context &context, const char *name, const char *description);
637*35238bceSAndroid Build Coastguard Worker     ~TriangleDerivateCase(void);
638*35238bceSAndroid Build Coastguard Worker 
639*35238bceSAndroid Build Coastguard Worker     IterateResult iterate(void);
640*35238bceSAndroid Build Coastguard Worker 
641*35238bceSAndroid Build Coastguard Worker protected:
setupRenderState(uint32_t program)642*35238bceSAndroid Build Coastguard Worker     virtual void setupRenderState(uint32_t program)
643*35238bceSAndroid Build Coastguard Worker     {
644*35238bceSAndroid Build Coastguard Worker         DE_UNREF(program);
645*35238bceSAndroid Build Coastguard Worker     }
646*35238bceSAndroid Build Coastguard Worker     virtual qpTestResult verify(const tcu::ConstPixelBufferAccess &result,
647*35238bceSAndroid Build Coastguard Worker                                 const tcu::PixelBufferAccess &errorMask) = DE_NULL;
648*35238bceSAndroid Build Coastguard Worker 
649*35238bceSAndroid Build Coastguard Worker     tcu::IVec2 getViewportSize(void) const;
650*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 getSurfaceThreshold(void) const;
651*35238bceSAndroid Build Coastguard Worker 
652*35238bceSAndroid Build Coastguard Worker     glu::DataType m_dataType;
653*35238bceSAndroid Build Coastguard Worker     glu::Precision m_precision;
654*35238bceSAndroid Build Coastguard Worker 
655*35238bceSAndroid Build Coastguard Worker     glu::DataType m_coordDataType;
656*35238bceSAndroid Build Coastguard Worker     glu::Precision m_coordPrecision;
657*35238bceSAndroid Build Coastguard Worker 
658*35238bceSAndroid Build Coastguard Worker     std::string m_fragmentSrc;
659*35238bceSAndroid Build Coastguard Worker 
660*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_coordMin;
661*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_coordMax;
662*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_derivScale;
663*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_derivBias;
664*35238bceSAndroid Build Coastguard Worker 
665*35238bceSAndroid Build Coastguard Worker     SurfaceType m_surfaceType;
666*35238bceSAndroid Build Coastguard Worker     int m_numSamples;
667*35238bceSAndroid Build Coastguard Worker     uint32_t m_hint;
668*35238bceSAndroid Build Coastguard Worker 
669*35238bceSAndroid Build Coastguard Worker     bool m_useAsymmetricCoords;
670*35238bceSAndroid Build Coastguard Worker };
671*35238bceSAndroid Build Coastguard Worker 
TriangleDerivateCase(Context & context,const char * name,const char * description)672*35238bceSAndroid Build Coastguard Worker TriangleDerivateCase::TriangleDerivateCase(Context &context, const char *name, const char *description)
673*35238bceSAndroid Build Coastguard Worker     : TestCase(context, name, description)
674*35238bceSAndroid Build Coastguard Worker     , m_dataType(glu::TYPE_LAST)
675*35238bceSAndroid Build Coastguard Worker     , m_precision(glu::PRECISION_LAST)
676*35238bceSAndroid Build Coastguard Worker     , m_coordDataType(glu::TYPE_LAST)
677*35238bceSAndroid Build Coastguard Worker     , m_coordPrecision(glu::PRECISION_LAST)
678*35238bceSAndroid Build Coastguard Worker     , m_surfaceType(SURFACETYPE_DEFAULT_FRAMEBUFFER)
679*35238bceSAndroid Build Coastguard Worker     , m_numSamples(0)
680*35238bceSAndroid Build Coastguard Worker     , m_hint(GL_DONT_CARE)
681*35238bceSAndroid Build Coastguard Worker     , m_useAsymmetricCoords(false)
682*35238bceSAndroid Build Coastguard Worker {
683*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER || m_numSamples == 0);
684*35238bceSAndroid Build Coastguard Worker }
685*35238bceSAndroid Build Coastguard Worker 
~TriangleDerivateCase(void)686*35238bceSAndroid Build Coastguard Worker TriangleDerivateCase::~TriangleDerivateCase(void)
687*35238bceSAndroid Build Coastguard Worker {
688*35238bceSAndroid Build Coastguard Worker     TriangleDerivateCase::deinit();
689*35238bceSAndroid Build Coastguard Worker }
690*35238bceSAndroid Build Coastguard Worker 
genVertexSource(glu::DataType coordType,glu::Precision precision)691*35238bceSAndroid Build Coastguard Worker static std::string genVertexSource(glu::DataType coordType, glu::Precision precision)
692*35238bceSAndroid Build Coastguard Worker {
693*35238bceSAndroid Build Coastguard Worker     DE_ASSERT(glu::isDataTypeFloatOrVec(coordType));
694*35238bceSAndroid Build Coastguard Worker 
695*35238bceSAndroid Build Coastguard Worker     const char *vertexTmpl = "#version 300 es\n"
696*35238bceSAndroid Build Coastguard Worker                              "in highp vec4 a_position;\n"
697*35238bceSAndroid Build Coastguard Worker                              "in ${PRECISION} ${DATATYPE} a_coord;\n"
698*35238bceSAndroid Build Coastguard Worker                              "out ${PRECISION} ${DATATYPE} v_coord;\n"
699*35238bceSAndroid Build Coastguard Worker                              "void main (void)\n"
700*35238bceSAndroid Build Coastguard Worker                              "{\n"
701*35238bceSAndroid Build Coastguard Worker                              "    gl_Position = a_position;\n"
702*35238bceSAndroid Build Coastguard Worker                              "    v_coord = a_coord;\n"
703*35238bceSAndroid Build Coastguard Worker                              "}\n";
704*35238bceSAndroid Build Coastguard Worker 
705*35238bceSAndroid Build Coastguard Worker     map<string, string> vertexParams;
706*35238bceSAndroid Build Coastguard Worker 
707*35238bceSAndroid Build Coastguard Worker     vertexParams["PRECISION"] = glu::getPrecisionName(precision);
708*35238bceSAndroid Build Coastguard Worker     vertexParams["DATATYPE"]  = glu::getDataTypeName(coordType);
709*35238bceSAndroid Build Coastguard Worker 
710*35238bceSAndroid Build Coastguard Worker     return tcu::StringTemplate(vertexTmpl).specialize(vertexParams);
711*35238bceSAndroid Build Coastguard Worker }
712*35238bceSAndroid Build Coastguard Worker 
getViewportSize(void) const713*35238bceSAndroid Build Coastguard Worker inline tcu::IVec2 TriangleDerivateCase::getViewportSize(void) const
714*35238bceSAndroid Build Coastguard Worker {
715*35238bceSAndroid Build Coastguard Worker     if (m_surfaceType == SURFACETYPE_DEFAULT_FRAMEBUFFER)
716*35238bceSAndroid Build Coastguard Worker     {
717*35238bceSAndroid Build Coastguard Worker         const int width  = de::min<int>(m_context.getRenderTarget().getWidth(), VIEWPORT_WIDTH);
718*35238bceSAndroid Build Coastguard Worker         const int height = de::min<int>(m_context.getRenderTarget().getHeight(), VIEWPORT_HEIGHT);
719*35238bceSAndroid Build Coastguard Worker         return tcu::IVec2(width, height);
720*35238bceSAndroid Build Coastguard Worker     }
721*35238bceSAndroid Build Coastguard Worker     else
722*35238bceSAndroid Build Coastguard Worker         return tcu::IVec2(FBO_WIDTH, FBO_HEIGHT);
723*35238bceSAndroid Build Coastguard Worker }
724*35238bceSAndroid Build Coastguard Worker 
iterate(void)725*35238bceSAndroid Build Coastguard Worker TriangleDerivateCase::IterateResult TriangleDerivateCase::iterate(void)
726*35238bceSAndroid Build Coastguard Worker {
727*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
728*35238bceSAndroid Build Coastguard Worker     const glu::ShaderProgram program(
729*35238bceSAndroid Build Coastguard Worker         m_context.getRenderContext(),
730*35238bceSAndroid Build Coastguard Worker         glu::makeVtxFragSources(genVertexSource(m_coordDataType, m_coordPrecision), m_fragmentSrc));
731*35238bceSAndroid Build Coastguard Worker     de::Random rnd(deStringHash(getName()) ^ 0xbbc24);
732*35238bceSAndroid Build Coastguard Worker     const bool useFbo             = m_surfaceType != SURFACETYPE_DEFAULT_FRAMEBUFFER;
733*35238bceSAndroid Build Coastguard Worker     const uint32_t fboFormat      = m_surfaceType == SURFACETYPE_FLOAT_FBO ? GL_RGBA32UI : GL_RGBA8;
734*35238bceSAndroid Build Coastguard Worker     const tcu::IVec2 viewportSize = getViewportSize();
735*35238bceSAndroid Build Coastguard Worker     const int viewportX = useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getWidth() - viewportSize.x());
736*35238bceSAndroid Build Coastguard Worker     const int viewportY = useFbo ? 0 : rnd.getInt(0, m_context.getRenderTarget().getHeight() - viewportSize.y());
737*35238bceSAndroid Build Coastguard Worker     AutoFbo fbo(gl);
738*35238bceSAndroid Build Coastguard Worker     AutoRbo rbo(gl);
739*35238bceSAndroid Build Coastguard Worker     tcu::TextureLevel result;
740*35238bceSAndroid Build Coastguard Worker 
741*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << program;
742*35238bceSAndroid Build Coastguard Worker 
743*35238bceSAndroid Build Coastguard Worker     if (!program.isOk())
744*35238bceSAndroid Build Coastguard Worker         TCU_FAIL("Compile failed");
745*35238bceSAndroid Build Coastguard Worker 
746*35238bceSAndroid Build Coastguard Worker     if (useFbo)
747*35238bceSAndroid Build Coastguard Worker     {
748*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::Message << "Rendering to FBO, format = " << glu::getTextureFormatStr(fboFormat)
749*35238bceSAndroid Build Coastguard Worker                            << ", samples = " << m_numSamples << TestLog::EndMessage;
750*35238bceSAndroid Build Coastguard Worker 
751*35238bceSAndroid Build Coastguard Worker         fbo.gen();
752*35238bceSAndroid Build Coastguard Worker         rbo.gen();
753*35238bceSAndroid Build Coastguard Worker 
754*35238bceSAndroid Build Coastguard Worker         gl.bindRenderbuffer(GL_RENDERBUFFER, *rbo);
755*35238bceSAndroid Build Coastguard Worker         gl.renderbufferStorageMultisample(GL_RENDERBUFFER, m_numSamples, fboFormat, viewportSize.x(), viewportSize.y());
756*35238bceSAndroid Build Coastguard Worker         gl.bindFramebuffer(GL_FRAMEBUFFER, *fbo);
757*35238bceSAndroid Build Coastguard Worker         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *rbo);
758*35238bceSAndroid Build Coastguard Worker         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
759*35238bceSAndroid Build Coastguard Worker     }
760*35238bceSAndroid Build Coastguard Worker     else
761*35238bceSAndroid Build Coastguard Worker     {
762*35238bceSAndroid Build Coastguard Worker         const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
763*35238bceSAndroid Build Coastguard Worker 
764*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::Message << "Rendering to default framebuffer\n"
765*35238bceSAndroid Build Coastguard Worker                            << "\tColor depth: R=" << pixelFormat.redBits << ", G=" << pixelFormat.greenBits
766*35238bceSAndroid Build Coastguard Worker                            << ", B=" << pixelFormat.blueBits << ", A=" << pixelFormat.alphaBits << TestLog::EndMessage;
767*35238bceSAndroid Build Coastguard Worker     }
768*35238bceSAndroid Build Coastguard Worker 
769*35238bceSAndroid Build Coastguard Worker     m_testCtx.getLog() << TestLog::Message << "in: " << m_coordMin << " -> " << m_coordMax << "\n"
770*35238bceSAndroid Build Coastguard Worker                        << (m_useAsymmetricCoords ? "v_coord.x = in.x * (x+y)/2\n" : "v_coord.x = in.x * x\n")
771*35238bceSAndroid Build Coastguard Worker                        << (m_useAsymmetricCoords ? "v_coord.y = in.y * (x+y)/2\n" : "v_coord.y = in.y * y\n")
772*35238bceSAndroid Build Coastguard Worker                        << "v_coord.z = in.z * (x+y)/2\n"
773*35238bceSAndroid Build Coastguard Worker                        << "v_coord.w = in.w * (1 - (x+y)/2)\n"
774*35238bceSAndroid Build Coastguard Worker                        << TestLog::EndMessage << TestLog::Message << "u_scale: " << m_derivScale
775*35238bceSAndroid Build Coastguard Worker                        << ", u_bias: " << m_derivBias << " (displayed values have scale/bias removed)"
776*35238bceSAndroid Build Coastguard Worker                        << TestLog::EndMessage << TestLog::Message << "Viewport: " << viewportSize.x() << "x"
777*35238bceSAndroid Build Coastguard Worker                        << viewportSize.y() << TestLog::EndMessage << TestLog::Message
778*35238bceSAndroid Build Coastguard Worker                        << "GL_FRAGMENT_SHADER_DERIVATE_HINT: " << glu::getHintModeStr(m_hint) << TestLog::EndMessage;
779*35238bceSAndroid Build Coastguard Worker 
780*35238bceSAndroid Build Coastguard Worker     // Draw
781*35238bceSAndroid Build Coastguard Worker     {
782*35238bceSAndroid Build Coastguard Worker         const float positions[] = {-1.0f, -1.0f, 0.0f, 1.0f, -1.0f, 1.0f, 0.0f, 1.0f,
783*35238bceSAndroid Build Coastguard Worker                                    1.0f,  -1.0f, 0.0f, 1.0f, 1.0f,  1.0f, 0.0f, 1.0f};
784*35238bceSAndroid Build Coastguard Worker         float coords[]          = {m_coordMin.x(),
785*35238bceSAndroid Build Coastguard Worker                                    m_coordMin.y(),
786*35238bceSAndroid Build Coastguard Worker                                    m_coordMin.z(),
787*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.w(),
788*35238bceSAndroid Build Coastguard Worker                                    m_coordMin.x(),
789*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.y(),
790*35238bceSAndroid Build Coastguard Worker                                    (m_coordMin.z() + m_coordMax.z()) * 0.5f,
791*35238bceSAndroid Build Coastguard Worker                                    (m_coordMin.w() + m_coordMax.w()) * 0.5f,
792*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.x(),
793*35238bceSAndroid Build Coastguard Worker                                    m_coordMin.y(),
794*35238bceSAndroid Build Coastguard Worker                                    (m_coordMin.z() + m_coordMax.z()) * 0.5f,
795*35238bceSAndroid Build Coastguard Worker                                    (m_coordMin.w() + m_coordMax.w()) * 0.5f,
796*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.x(),
797*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.y(),
798*35238bceSAndroid Build Coastguard Worker                                    m_coordMax.z(),
799*35238bceSAndroid Build Coastguard Worker                                    m_coordMin.w()};
800*35238bceSAndroid Build Coastguard Worker 
801*35238bceSAndroid Build Coastguard Worker         // For linear tests we want varying data x and y to vary along both axes
802*35238bceSAndroid Build Coastguard Worker         // to get nonzero x for dfdy and nonzero y for dfdx. To make the gradient
803*35238bceSAndroid Build Coastguard Worker         // the same for both triangles we set vertices 2 and 3 to middle values.
804*35238bceSAndroid Build Coastguard Worker         // This way the values go from min -> (max+min) / 2 or (max+min) / 2 -> max
805*35238bceSAndroid Build Coastguard Worker         // depending on the triangle, but the derivative is the same for both.
806*35238bceSAndroid Build Coastguard Worker         if (m_useAsymmetricCoords)
807*35238bceSAndroid Build Coastguard Worker         {
808*35238bceSAndroid Build Coastguard Worker             coords[4] = coords[8] = (m_coordMin.x() + m_coordMax.x()) * 0.5f;
809*35238bceSAndroid Build Coastguard Worker             coords[5] = coords[9] = (m_coordMin.y() + m_coordMax.y()) * 0.5f;
810*35238bceSAndroid Build Coastguard Worker         }
811*35238bceSAndroid Build Coastguard Worker 
812*35238bceSAndroid Build Coastguard Worker         const glu::VertexArrayBinding vertexArrays[] = {glu::va::Float("a_position", 4, 4, 0, &positions[0]),
813*35238bceSAndroid Build Coastguard Worker                                                         glu::va::Float("a_coord", 4, 4, 0, &coords[0])};
814*35238bceSAndroid Build Coastguard Worker         const uint16_t indices[]                     = {0, 2, 1, 2, 3, 1};
815*35238bceSAndroid Build Coastguard Worker 
816*35238bceSAndroid Build Coastguard Worker         gl.clearColor(0.125f, 0.25f, 0.5f, 1.0f);
817*35238bceSAndroid Build Coastguard Worker         gl.clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
818*35238bceSAndroid Build Coastguard Worker         gl.disable(GL_DITHER);
819*35238bceSAndroid Build Coastguard Worker 
820*35238bceSAndroid Build Coastguard Worker         gl.useProgram(program.getProgram());
821*35238bceSAndroid Build Coastguard Worker 
822*35238bceSAndroid Build Coastguard Worker         {
823*35238bceSAndroid Build Coastguard Worker             const int scaleLoc = gl.getUniformLocation(program.getProgram(), "u_scale");
824*35238bceSAndroid Build Coastguard Worker             const int biasLoc  = gl.getUniformLocation(program.getProgram(), "u_bias");
825*35238bceSAndroid Build Coastguard Worker 
826*35238bceSAndroid Build Coastguard Worker             switch (m_dataType)
827*35238bceSAndroid Build Coastguard Worker             {
828*35238bceSAndroid Build Coastguard Worker             case glu::TYPE_FLOAT:
829*35238bceSAndroid Build Coastguard Worker                 gl.uniform1f(scaleLoc, m_derivScale.x());
830*35238bceSAndroid Build Coastguard Worker                 gl.uniform1f(biasLoc, m_derivBias.x());
831*35238bceSAndroid Build Coastguard Worker                 break;
832*35238bceSAndroid Build Coastguard Worker 
833*35238bceSAndroid Build Coastguard Worker             case glu::TYPE_FLOAT_VEC2:
834*35238bceSAndroid Build Coastguard Worker                 gl.uniform2fv(scaleLoc, 1, m_derivScale.getPtr());
835*35238bceSAndroid Build Coastguard Worker                 gl.uniform2fv(biasLoc, 1, m_derivBias.getPtr());
836*35238bceSAndroid Build Coastguard Worker                 break;
837*35238bceSAndroid Build Coastguard Worker 
838*35238bceSAndroid Build Coastguard Worker             case glu::TYPE_FLOAT_VEC3:
839*35238bceSAndroid Build Coastguard Worker                 gl.uniform3fv(scaleLoc, 1, m_derivScale.getPtr());
840*35238bceSAndroid Build Coastguard Worker                 gl.uniform3fv(biasLoc, 1, m_derivBias.getPtr());
841*35238bceSAndroid Build Coastguard Worker                 break;
842*35238bceSAndroid Build Coastguard Worker 
843*35238bceSAndroid Build Coastguard Worker             case glu::TYPE_FLOAT_VEC4:
844*35238bceSAndroid Build Coastguard Worker                 gl.uniform4fv(scaleLoc, 1, m_derivScale.getPtr());
845*35238bceSAndroid Build Coastguard Worker                 gl.uniform4fv(biasLoc, 1, m_derivBias.getPtr());
846*35238bceSAndroid Build Coastguard Worker                 break;
847*35238bceSAndroid Build Coastguard Worker 
848*35238bceSAndroid Build Coastguard Worker             default:
849*35238bceSAndroid Build Coastguard Worker                 DE_ASSERT(false);
850*35238bceSAndroid Build Coastguard Worker             }
851*35238bceSAndroid Build Coastguard Worker         }
852*35238bceSAndroid Build Coastguard Worker 
853*35238bceSAndroid Build Coastguard Worker         gls::setupDefaultUniforms(m_context.getRenderContext(), program.getProgram());
854*35238bceSAndroid Build Coastguard Worker         setupRenderState(program.getProgram());
855*35238bceSAndroid Build Coastguard Worker 
856*35238bceSAndroid Build Coastguard Worker         gl.hint(GL_FRAGMENT_SHADER_DERIVATIVE_HINT, m_hint);
857*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "Setup program state");
858*35238bceSAndroid Build Coastguard Worker 
859*35238bceSAndroid Build Coastguard Worker         gl.viewport(viewportX, viewportY, viewportSize.x(), viewportSize.y());
860*35238bceSAndroid Build Coastguard Worker         glu::draw(m_context.getRenderContext(), program.getProgram(), DE_LENGTH_OF_ARRAY(vertexArrays),
861*35238bceSAndroid Build Coastguard Worker                   &vertexArrays[0], glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
862*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
863*35238bceSAndroid Build Coastguard Worker     }
864*35238bceSAndroid Build Coastguard Worker 
865*35238bceSAndroid Build Coastguard Worker     // Read back results
866*35238bceSAndroid Build Coastguard Worker     {
867*35238bceSAndroid Build Coastguard Worker         const bool isMSAA = useFbo && m_numSamples > 0;
868*35238bceSAndroid Build Coastguard Worker         AutoFbo resFbo(gl);
869*35238bceSAndroid Build Coastguard Worker         AutoRbo resRbo(gl);
870*35238bceSAndroid Build Coastguard Worker 
871*35238bceSAndroid Build Coastguard Worker         // Resolve if necessary
872*35238bceSAndroid Build Coastguard Worker         if (isMSAA)
873*35238bceSAndroid Build Coastguard Worker         {
874*35238bceSAndroid Build Coastguard Worker             resFbo.gen();
875*35238bceSAndroid Build Coastguard Worker             resRbo.gen();
876*35238bceSAndroid Build Coastguard Worker 
877*35238bceSAndroid Build Coastguard Worker             gl.bindRenderbuffer(GL_RENDERBUFFER, *resRbo);
878*35238bceSAndroid Build Coastguard Worker             gl.renderbufferStorageMultisample(GL_RENDERBUFFER, 0, fboFormat, viewportSize.x(), viewportSize.y());
879*35238bceSAndroid Build Coastguard Worker             gl.bindFramebuffer(GL_DRAW_FRAMEBUFFER, *resFbo);
880*35238bceSAndroid Build Coastguard Worker             gl.framebufferRenderbuffer(GL_DRAW_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, *resRbo);
881*35238bceSAndroid Build Coastguard Worker             TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
882*35238bceSAndroid Build Coastguard Worker 
883*35238bceSAndroid Build Coastguard Worker             gl.blitFramebuffer(0, 0, viewportSize.x(), viewportSize.y(), 0, 0, viewportSize.x(), viewportSize.y(),
884*35238bceSAndroid Build Coastguard Worker                                GL_COLOR_BUFFER_BIT, GL_NEAREST);
885*35238bceSAndroid Build Coastguard Worker             GLU_EXPECT_NO_ERROR(gl.getError(), "Resolve blit");
886*35238bceSAndroid Build Coastguard Worker 
887*35238bceSAndroid Build Coastguard Worker             gl.bindFramebuffer(GL_READ_FRAMEBUFFER, *resFbo);
888*35238bceSAndroid Build Coastguard Worker         }
889*35238bceSAndroid Build Coastguard Worker 
890*35238bceSAndroid Build Coastguard Worker         switch (m_surfaceType)
891*35238bceSAndroid Build Coastguard Worker         {
892*35238bceSAndroid Build Coastguard Worker         case SURFACETYPE_DEFAULT_FRAMEBUFFER:
893*35238bceSAndroid Build Coastguard Worker         case SURFACETYPE_UNORM_FBO:
894*35238bceSAndroid Build Coastguard Worker             result.setStorage(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8),
895*35238bceSAndroid Build Coastguard Worker                               viewportSize.x(), viewportSize.y());
896*35238bceSAndroid Build Coastguard Worker             glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, result);
897*35238bceSAndroid Build Coastguard Worker             break;
898*35238bceSAndroid Build Coastguard Worker 
899*35238bceSAndroid Build Coastguard Worker         case SURFACETYPE_FLOAT_FBO:
900*35238bceSAndroid Build Coastguard Worker         {
901*35238bceSAndroid Build Coastguard Worker             const tcu::TextureFormat dataFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT);
902*35238bceSAndroid Build Coastguard Worker             const tcu::TextureFormat transferFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNSIGNED_INT32);
903*35238bceSAndroid Build Coastguard Worker 
904*35238bceSAndroid Build Coastguard Worker             result.setStorage(dataFormat, viewportSize.x(), viewportSize.y());
905*35238bceSAndroid Build Coastguard Worker             glu::readPixels(m_context.getRenderContext(), viewportX, viewportY,
906*35238bceSAndroid Build Coastguard Worker                             tcu::PixelBufferAccess(transferFormat, result.getWidth(), result.getHeight(),
907*35238bceSAndroid Build Coastguard Worker                                                    result.getDepth(), result.getAccess().getDataPtr()));
908*35238bceSAndroid Build Coastguard Worker             break;
909*35238bceSAndroid Build Coastguard Worker         }
910*35238bceSAndroid Build Coastguard Worker 
911*35238bceSAndroid Build Coastguard Worker         default:
912*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
913*35238bceSAndroid Build Coastguard Worker         }
914*35238bceSAndroid Build Coastguard Worker 
915*35238bceSAndroid Build Coastguard Worker         GLU_EXPECT_NO_ERROR(gl.getError(), "Read pixels");
916*35238bceSAndroid Build Coastguard Worker     }
917*35238bceSAndroid Build Coastguard Worker 
918*35238bceSAndroid Build Coastguard Worker     // Verify
919*35238bceSAndroid Build Coastguard Worker     {
920*35238bceSAndroid Build Coastguard Worker         tcu::Surface errorMask(result.getWidth(), result.getHeight());
921*35238bceSAndroid Build Coastguard Worker         tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec());
922*35238bceSAndroid Build Coastguard Worker 
923*35238bceSAndroid Build Coastguard Worker         const qpTestResult testResult = verify(result.getAccess(), errorMask.getAccess());
924*35238bceSAndroid Build Coastguard Worker         const char *failStr           = "Fail";
925*35238bceSAndroid Build Coastguard Worker 
926*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::ImageSet("Result", "Result images")
927*35238bceSAndroid Build Coastguard Worker                            << TestLog::Image("Rendered", "Rendered image", result);
928*35238bceSAndroid Build Coastguard Worker 
929*35238bceSAndroid Build Coastguard Worker         if (testResult != QP_TEST_RESULT_PASS)
930*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << TestLog::Image("ErrorMask", "Error mask", errorMask);
931*35238bceSAndroid Build Coastguard Worker 
932*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << TestLog::EndImageSet;
933*35238bceSAndroid Build Coastguard Worker 
934*35238bceSAndroid Build Coastguard Worker         if (testResult == QP_TEST_RESULT_PASS)
935*35238bceSAndroid Build Coastguard Worker             failStr = "Pass";
936*35238bceSAndroid Build Coastguard Worker         else if (testResult == QP_TEST_RESULT_QUALITY_WARNING)
937*35238bceSAndroid Build Coastguard Worker             failStr = "QualityWarning";
938*35238bceSAndroid Build Coastguard Worker 
939*35238bceSAndroid Build Coastguard Worker         m_testCtx.setTestResult(testResult, failStr);
940*35238bceSAndroid Build Coastguard Worker     }
941*35238bceSAndroid Build Coastguard Worker 
942*35238bceSAndroid Build Coastguard Worker     return STOP;
943*35238bceSAndroid Build Coastguard Worker }
944*35238bceSAndroid Build Coastguard Worker 
getSurfaceThreshold(void) const945*35238bceSAndroid Build Coastguard Worker tcu::Vec4 TriangleDerivateCase::getSurfaceThreshold(void) const
946*35238bceSAndroid Build Coastguard Worker {
947*35238bceSAndroid Build Coastguard Worker     switch (m_surfaceType)
948*35238bceSAndroid Build Coastguard Worker     {
949*35238bceSAndroid Build Coastguard Worker     case SURFACETYPE_DEFAULT_FRAMEBUFFER:
950*35238bceSAndroid Build Coastguard Worker     {
951*35238bceSAndroid Build Coastguard Worker         const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat();
952*35238bceSAndroid Build Coastguard Worker         const tcu::IVec4 channelBits(pixelFormat.redBits, pixelFormat.greenBits, pixelFormat.blueBits,
953*35238bceSAndroid Build Coastguard Worker                                      pixelFormat.alphaBits);
954*35238bceSAndroid Build Coastguard Worker         const tcu::IVec4 intThreshold = tcu::IVec4(1) << (8 - channelBits);
955*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 normThreshold = intThreshold.asFloat() / 255.0f;
956*35238bceSAndroid Build Coastguard Worker 
957*35238bceSAndroid Build Coastguard Worker         return normThreshold;
958*35238bceSAndroid Build Coastguard Worker     }
959*35238bceSAndroid Build Coastguard Worker 
960*35238bceSAndroid Build Coastguard Worker     case SURFACETYPE_UNORM_FBO:
961*35238bceSAndroid Build Coastguard Worker         return tcu::IVec4(1).asFloat() / 255.0f;
962*35238bceSAndroid Build Coastguard Worker     case SURFACETYPE_FLOAT_FBO:
963*35238bceSAndroid Build Coastguard Worker         return tcu::Vec4(0.0f);
964*35238bceSAndroid Build Coastguard Worker     default:
965*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
966*35238bceSAndroid Build Coastguard Worker         return tcu::Vec4(0.0f);
967*35238bceSAndroid Build Coastguard Worker     }
968*35238bceSAndroid Build Coastguard Worker }
969*35238bceSAndroid Build Coastguard Worker 
970*35238bceSAndroid Build Coastguard Worker // ConstantDerivateCase
971*35238bceSAndroid Build Coastguard Worker 
972*35238bceSAndroid Build Coastguard Worker class ConstantDerivateCase : public TriangleDerivateCase
973*35238bceSAndroid Build Coastguard Worker {
974*35238bceSAndroid Build Coastguard Worker public:
975*35238bceSAndroid Build Coastguard Worker     ConstantDerivateCase(Context &context, const char *name, const char *description, DerivateFunc func,
976*35238bceSAndroid Build Coastguard Worker                          glu::DataType type);
~ConstantDerivateCase(void)977*35238bceSAndroid Build Coastguard Worker     ~ConstantDerivateCase(void)
978*35238bceSAndroid Build Coastguard Worker     {
979*35238bceSAndroid Build Coastguard Worker     }
980*35238bceSAndroid Build Coastguard Worker 
981*35238bceSAndroid Build Coastguard Worker     void init(void);
982*35238bceSAndroid Build Coastguard Worker 
983*35238bceSAndroid Build Coastguard Worker protected:
984*35238bceSAndroid Build Coastguard Worker     qpTestResult verify(const tcu::ConstPixelBufferAccess &result, const tcu::PixelBufferAccess &errorMask);
985*35238bceSAndroid Build Coastguard Worker 
986*35238bceSAndroid Build Coastguard Worker private:
987*35238bceSAndroid Build Coastguard Worker     DerivateFunc m_func;
988*35238bceSAndroid Build Coastguard Worker };
989*35238bceSAndroid Build Coastguard Worker 
ConstantDerivateCase(Context & context,const char * name,const char * description,DerivateFunc func,glu::DataType type)990*35238bceSAndroid Build Coastguard Worker ConstantDerivateCase::ConstantDerivateCase(Context &context, const char *name, const char *description,
991*35238bceSAndroid Build Coastguard Worker                                            DerivateFunc func, glu::DataType type)
992*35238bceSAndroid Build Coastguard Worker     : TriangleDerivateCase(context, name, description)
993*35238bceSAndroid Build Coastguard Worker     , m_func(func)
994*35238bceSAndroid Build Coastguard Worker {
995*35238bceSAndroid Build Coastguard Worker     m_dataType       = type;
996*35238bceSAndroid Build Coastguard Worker     m_precision      = glu::PRECISION_HIGHP;
997*35238bceSAndroid Build Coastguard Worker     m_coordDataType  = m_dataType;
998*35238bceSAndroid Build Coastguard Worker     m_coordPrecision = m_precision;
999*35238bceSAndroid Build Coastguard Worker }
1000*35238bceSAndroid Build Coastguard Worker 
init(void)1001*35238bceSAndroid Build Coastguard Worker void ConstantDerivateCase::init(void)
1002*35238bceSAndroid Build Coastguard Worker {
1003*35238bceSAndroid Build Coastguard Worker     const char *fragmentTmpl = "#version 300 es\n"
1004*35238bceSAndroid Build Coastguard Worker                                "layout(location = 0) out mediump vec4 o_color;\n"
1005*35238bceSAndroid Build Coastguard Worker                                "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1006*35238bceSAndroid Build Coastguard Worker                                "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1007*35238bceSAndroid Build Coastguard Worker                                "void main (void)\n"
1008*35238bceSAndroid Build Coastguard Worker                                "{\n"
1009*35238bceSAndroid Build Coastguard Worker                                "    ${PRECISION} ${DATATYPE} res = ${FUNC}(${VALUE}) * u_scale + u_bias;\n"
1010*35238bceSAndroid Build Coastguard Worker                                "    o_color = ${CAST_TO_OUTPUT};\n"
1011*35238bceSAndroid Build Coastguard Worker                                "}\n";
1012*35238bceSAndroid Build Coastguard Worker     map<string, string> fragmentParams;
1013*35238bceSAndroid Build Coastguard Worker     fragmentParams["PRECISION"]      = glu::getPrecisionName(m_precision);
1014*35238bceSAndroid Build Coastguard Worker     fragmentParams["DATATYPE"]       = glu::getDataTypeName(m_dataType);
1015*35238bceSAndroid Build Coastguard Worker     fragmentParams["FUNC"]           = getDerivateFuncName(m_func);
1016*35238bceSAndroid Build Coastguard Worker     fragmentParams["VALUE"]          = m_dataType == glu::TYPE_FLOAT_VEC4 ? "vec4(1.0, 7.2, -1e5, 0.0)" :
1017*35238bceSAndroid Build Coastguard Worker                                        m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec3(1e2, 8.0, 0.01)" :
1018*35238bceSAndroid Build Coastguard Worker                                        m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec2(-0.0, 2.7)" :
1019*35238bceSAndroid Build Coastguard Worker                                                                             /* TYPE_FLOAT */ "7.7";
1020*35238bceSAndroid Build Coastguard Worker     fragmentParams["CAST_TO_OUTPUT"] = m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
1021*35238bceSAndroid Build Coastguard Worker                                        m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
1022*35238bceSAndroid Build Coastguard Worker                                        m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
1023*35238bceSAndroid Build Coastguard Worker                                                                             /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)";
1024*35238bceSAndroid Build Coastguard Worker 
1025*35238bceSAndroid Build Coastguard Worker     m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams);
1026*35238bceSAndroid Build Coastguard Worker 
1027*35238bceSAndroid Build Coastguard Worker     m_derivScale = tcu::Vec4(1e3f, 1e3f, 1e3f, 1e3f);
1028*35238bceSAndroid Build Coastguard Worker     m_derivBias  = tcu::Vec4(0.5f, 0.5f, 0.5f, 0.5f);
1029*35238bceSAndroid Build Coastguard Worker }
1030*35238bceSAndroid Build Coastguard Worker 
verify(const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask)1031*35238bceSAndroid Build Coastguard Worker qpTestResult ConstantDerivateCase::verify(const tcu::ConstPixelBufferAccess &result,
1032*35238bceSAndroid Build Coastguard Worker                                           const tcu::PixelBufferAccess &errorMask)
1033*35238bceSAndroid Build Coastguard Worker {
1034*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 reference(0.0f); // Derivate of constant argument should always be 0
1035*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 threshold = getSurfaceThreshold() / abs(m_derivScale);
1036*35238bceSAndroid Build Coastguard Worker 
1037*35238bceSAndroid Build Coastguard Worker     return verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, threshold, m_derivScale,
1038*35238bceSAndroid Build Coastguard Worker                                   m_derivBias);
1039*35238bceSAndroid Build Coastguard Worker }
1040*35238bceSAndroid Build Coastguard Worker 
1041*35238bceSAndroid Build Coastguard Worker // LinearDerivateCase
1042*35238bceSAndroid Build Coastguard Worker 
1043*35238bceSAndroid Build Coastguard Worker class LinearDerivateCase : public TriangleDerivateCase
1044*35238bceSAndroid Build Coastguard Worker {
1045*35238bceSAndroid Build Coastguard Worker public:
1046*35238bceSAndroid Build Coastguard Worker     LinearDerivateCase(Context &context, const char *name, const char *description, DerivateFunc func,
1047*35238bceSAndroid Build Coastguard Worker                        glu::DataType type, glu::Precision precision, uint32_t hint, SurfaceType surfaceType,
1048*35238bceSAndroid Build Coastguard Worker                        int numSamples, const char *fragmentSrcTmpl);
~LinearDerivateCase(void)1049*35238bceSAndroid Build Coastguard Worker     ~LinearDerivateCase(void)
1050*35238bceSAndroid Build Coastguard Worker     {
1051*35238bceSAndroid Build Coastguard Worker     }
1052*35238bceSAndroid Build Coastguard Worker 
1053*35238bceSAndroid Build Coastguard Worker     void init(void);
1054*35238bceSAndroid Build Coastguard Worker 
1055*35238bceSAndroid Build Coastguard Worker protected:
1056*35238bceSAndroid Build Coastguard Worker     qpTestResult verify(const tcu::ConstPixelBufferAccess &result, const tcu::PixelBufferAccess &errorMask);
1057*35238bceSAndroid Build Coastguard Worker 
1058*35238bceSAndroid Build Coastguard Worker private:
1059*35238bceSAndroid Build Coastguard Worker     DerivateFunc m_func;
1060*35238bceSAndroid Build Coastguard Worker     std::string m_fragmentTmpl;
1061*35238bceSAndroid Build Coastguard Worker };
1062*35238bceSAndroid Build Coastguard Worker 
LinearDerivateCase(Context & context,const char * name,const char * description,DerivateFunc func,glu::DataType type,glu::Precision precision,uint32_t hint,SurfaceType surfaceType,int numSamples,const char * fragmentSrcTmpl)1063*35238bceSAndroid Build Coastguard Worker LinearDerivateCase::LinearDerivateCase(Context &context, const char *name, const char *description, DerivateFunc func,
1064*35238bceSAndroid Build Coastguard Worker                                        glu::DataType type, glu::Precision precision, uint32_t hint,
1065*35238bceSAndroid Build Coastguard Worker                                        SurfaceType surfaceType, int numSamples, const char *fragmentSrcTmpl)
1066*35238bceSAndroid Build Coastguard Worker     : TriangleDerivateCase(context, name, description)
1067*35238bceSAndroid Build Coastguard Worker     , m_func(func)
1068*35238bceSAndroid Build Coastguard Worker     , m_fragmentTmpl(fragmentSrcTmpl)
1069*35238bceSAndroid Build Coastguard Worker {
1070*35238bceSAndroid Build Coastguard Worker     m_dataType            = type;
1071*35238bceSAndroid Build Coastguard Worker     m_precision           = precision;
1072*35238bceSAndroid Build Coastguard Worker     m_coordDataType       = m_dataType;
1073*35238bceSAndroid Build Coastguard Worker     m_coordPrecision      = m_precision;
1074*35238bceSAndroid Build Coastguard Worker     m_hint                = hint;
1075*35238bceSAndroid Build Coastguard Worker     m_surfaceType         = surfaceType;
1076*35238bceSAndroid Build Coastguard Worker     m_numSamples          = numSamples;
1077*35238bceSAndroid Build Coastguard Worker     m_useAsymmetricCoords = true;
1078*35238bceSAndroid Build Coastguard Worker }
1079*35238bceSAndroid Build Coastguard Worker 
init(void)1080*35238bceSAndroid Build Coastguard Worker void LinearDerivateCase::init(void)
1081*35238bceSAndroid Build Coastguard Worker {
1082*35238bceSAndroid Build Coastguard Worker     const tcu::IVec2 viewportSize = getViewportSize();
1083*35238bceSAndroid Build Coastguard Worker     const float w                 = float(viewportSize.x());
1084*35238bceSAndroid Build Coastguard Worker     const float h                 = float(viewportSize.y());
1085*35238bceSAndroid Build Coastguard Worker     const bool packToInt          = m_surfaceType == SURFACETYPE_FLOAT_FBO;
1086*35238bceSAndroid Build Coastguard Worker     map<string, string> fragmentParams;
1087*35238bceSAndroid Build Coastguard Worker 
1088*35238bceSAndroid Build Coastguard Worker     fragmentParams["OUTPUT_TYPE"] = glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4);
1089*35238bceSAndroid Build Coastguard Worker     fragmentParams["OUTPUT_PREC"] = glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision);
1090*35238bceSAndroid Build Coastguard Worker     fragmentParams["PRECISION"]   = glu::getPrecisionName(m_precision);
1091*35238bceSAndroid Build Coastguard Worker     fragmentParams["DATATYPE"]    = glu::getDataTypeName(m_dataType);
1092*35238bceSAndroid Build Coastguard Worker     fragmentParams["FUNC"]        = getDerivateFuncName(m_func);
1093*35238bceSAndroid Build Coastguard Worker 
1094*35238bceSAndroid Build Coastguard Worker     if (packToInt)
1095*35238bceSAndroid Build Coastguard Worker     {
1096*35238bceSAndroid Build Coastguard Worker         fragmentParams["CAST_TO_OUTPUT"] =
1097*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" :
1098*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" :
1099*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" :
1100*35238bceSAndroid Build Coastguard Worker                                                  /* TYPE_FLOAT */ "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))";
1101*35238bceSAndroid Build Coastguard Worker     }
1102*35238bceSAndroid Build Coastguard Worker     else
1103*35238bceSAndroid Build Coastguard Worker     {
1104*35238bceSAndroid Build Coastguard Worker         fragmentParams["CAST_TO_OUTPUT"] =
1105*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
1106*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
1107*35238bceSAndroid Build Coastguard Worker             m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
1108*35238bceSAndroid Build Coastguard Worker                                                  /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)";
1109*35238bceSAndroid Build Coastguard Worker     }
1110*35238bceSAndroid Build Coastguard Worker 
1111*35238bceSAndroid Build Coastguard Worker     m_fragmentSrc = tcu::StringTemplate(m_fragmentTmpl.c_str()).specialize(fragmentParams);
1112*35238bceSAndroid Build Coastguard Worker 
1113*35238bceSAndroid Build Coastguard Worker     switch (m_precision)
1114*35238bceSAndroid Build Coastguard Worker     {
1115*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_HIGHP:
1116*35238bceSAndroid Build Coastguard Worker         m_coordMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f);
1117*35238bceSAndroid Build Coastguard Worker         m_coordMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f);
1118*35238bceSAndroid Build Coastguard Worker         break;
1119*35238bceSAndroid Build Coastguard Worker 
1120*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_MEDIUMP:
1121*35238bceSAndroid Build Coastguard Worker         m_coordMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f);
1122*35238bceSAndroid Build Coastguard Worker         m_coordMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f);
1123*35238bceSAndroid Build Coastguard Worker         break;
1124*35238bceSAndroid Build Coastguard Worker 
1125*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_LOWP:
1126*35238bceSAndroid Build Coastguard Worker         m_coordMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f);
1127*35238bceSAndroid Build Coastguard Worker         m_coordMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f);
1128*35238bceSAndroid Build Coastguard Worker         break;
1129*35238bceSAndroid Build Coastguard Worker 
1130*35238bceSAndroid Build Coastguard Worker     default:
1131*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1132*35238bceSAndroid Build Coastguard Worker     }
1133*35238bceSAndroid Build Coastguard Worker 
1134*35238bceSAndroid Build Coastguard Worker     if (m_surfaceType == SURFACETYPE_FLOAT_FBO)
1135*35238bceSAndroid Build Coastguard Worker     {
1136*35238bceSAndroid Build Coastguard Worker         // No scale or bias used for accuracy.
1137*35238bceSAndroid Build Coastguard Worker         m_derivScale = tcu::Vec4(1.0f);
1138*35238bceSAndroid Build Coastguard Worker         m_derivBias  = tcu::Vec4(0.0f);
1139*35238bceSAndroid Build Coastguard Worker     }
1140*35238bceSAndroid Build Coastguard Worker     else
1141*35238bceSAndroid Build Coastguard Worker     {
1142*35238bceSAndroid Build Coastguard Worker         // Compute scale - bias that normalizes to 0..1 range.
1143*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dx = (m_coordMax - m_coordMin) / tcu::Vec4(w, w, w * 0.5f, -w * 0.5f);
1144*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dy = (m_coordMax - m_coordMin) / tcu::Vec4(h, h, h * 0.5f, -h * 0.5f);
1145*35238bceSAndroid Build Coastguard Worker 
1146*35238bceSAndroid Build Coastguard Worker         switch (m_func)
1147*35238bceSAndroid Build Coastguard Worker         {
1148*35238bceSAndroid Build Coastguard Worker         case DERIVATE_DFDX:
1149*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / dx;
1150*35238bceSAndroid Build Coastguard Worker             break;
1151*35238bceSAndroid Build Coastguard Worker 
1152*35238bceSAndroid Build Coastguard Worker         case DERIVATE_DFDY:
1153*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / dy;
1154*35238bceSAndroid Build Coastguard Worker             break;
1155*35238bceSAndroid Build Coastguard Worker 
1156*35238bceSAndroid Build Coastguard Worker         case DERIVATE_FWIDTH:
1157*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy));
1158*35238bceSAndroid Build Coastguard Worker             break;
1159*35238bceSAndroid Build Coastguard Worker 
1160*35238bceSAndroid Build Coastguard Worker         default:
1161*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1162*35238bceSAndroid Build Coastguard Worker         }
1163*35238bceSAndroid Build Coastguard Worker 
1164*35238bceSAndroid Build Coastguard Worker         m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
1165*35238bceSAndroid Build Coastguard Worker     }
1166*35238bceSAndroid Build Coastguard Worker }
1167*35238bceSAndroid Build Coastguard Worker 
verify(const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask)1168*35238bceSAndroid Build Coastguard Worker qpTestResult LinearDerivateCase::verify(const tcu::ConstPixelBufferAccess &result,
1169*35238bceSAndroid Build Coastguard Worker                                         const tcu::PixelBufferAccess &errorMask)
1170*35238bceSAndroid Build Coastguard Worker {
1171*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 xScale = tcu::Vec4(0.5f, 0.5f, 0.5f, -0.5f);
1172*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 yScale = tcu::Vec4(0.5f, 0.5f, 0.5f, -0.5f);
1173*35238bceSAndroid Build Coastguard Worker 
1174*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 surfaceThreshold = getSurfaceThreshold() / abs(m_derivScale);
1175*35238bceSAndroid Build Coastguard Worker 
1176*35238bceSAndroid Build Coastguard Worker     if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
1177*35238bceSAndroid Build Coastguard Worker     {
1178*35238bceSAndroid Build Coastguard Worker         const bool isX               = m_func == DERIVATE_DFDX;
1179*35238bceSAndroid Build Coastguard Worker         const float div              = isX ? float(result.getWidth()) : float(result.getHeight());
1180*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 scale        = isX ? xScale : yScale;
1181*35238bceSAndroid Build Coastguard Worker         tcu::Vec4 reference          = ((m_coordMax - m_coordMin) / div);
1182*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 opThreshold  = getDerivateThreshold(m_precision, m_coordMin, m_coordMax, reference);
1183*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 opThresholdW = getDerivateThresholdWarning(m_precision, m_coordMin, m_coordMax, reference);
1184*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 threshold    = max(surfaceThreshold, opThreshold);
1185*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 thresholdW   = max(surfaceThreshold, opThresholdW);
1186*35238bceSAndroid Build Coastguard Worker         const int numComps           = glu::getDataTypeFloatScalars(m_dataType);
1187*35238bceSAndroid Build Coastguard Worker 
1188*35238bceSAndroid Build Coastguard Worker         /* adjust the reference value for the correct dfdx or dfdy sample adjacency */
1189*35238bceSAndroid Build Coastguard Worker         reference = reference * scale;
1190*35238bceSAndroid Build Coastguard Worker 
1191*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result image.\n"
1192*35238bceSAndroid Build Coastguard Worker                            << "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold "
1193*35238bceSAndroid Build Coastguard Worker                            << LogVecComps(threshold, numComps) << tcu::TestLog::EndMessage;
1194*35238bceSAndroid Build Coastguard Worker 
1195*35238bceSAndroid Build Coastguard Worker         // short circuit if result is strictly within the normal value error bounds.
1196*35238bceSAndroid Build Coastguard Worker         // This improves performance significantly.
1197*35238bceSAndroid Build Coastguard Worker         if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, threshold,
1198*35238bceSAndroid Build Coastguard Worker                                    m_derivScale, m_derivBias, LOG_NOTHING) == QP_TEST_RESULT_PASS)
1199*35238bceSAndroid Build Coastguard Worker         {
1200*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "No incorrect derivatives found, result valid."
1201*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1202*35238bceSAndroid Build Coastguard Worker 
1203*35238bceSAndroid Build Coastguard Worker             return QP_TEST_RESULT_PASS;
1204*35238bceSAndroid Build Coastguard Worker         }
1205*35238bceSAndroid Build Coastguard Worker 
1206*35238bceSAndroid Build Coastguard Worker         // Check with relaxed threshold value
1207*35238bceSAndroid Build Coastguard Worker         if (verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, thresholdW,
1208*35238bceSAndroid Build Coastguard Worker                                    m_derivScale, m_derivBias, LOG_NOTHING) == QP_TEST_RESULT_PASS)
1209*35238bceSAndroid Build Coastguard Worker         {
1210*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message
1211*35238bceSAndroid Build Coastguard Worker                                << "No incorrect derivatives found, result valid with quality warning."
1212*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1213*35238bceSAndroid Build Coastguard Worker 
1214*35238bceSAndroid Build Coastguard Worker             return QP_TEST_RESULT_QUALITY_WARNING;
1215*35238bceSAndroid Build Coastguard Worker         }
1216*35238bceSAndroid Build Coastguard Worker 
1217*35238bceSAndroid Build Coastguard Worker         // some pixels exceed error bounds calculated for normal values. Verify that these
1218*35238bceSAndroid Build Coastguard Worker         // potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
1219*35238bceSAndroid Build Coastguard Worker 
1220*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message
1221*35238bceSAndroid Build Coastguard Worker                            << "Initial verification failed, verifying image by calculating accurate error bounds for "
1222*35238bceSAndroid Build Coastguard Worker                               "each result pixel.\n"
1223*35238bceSAndroid Build Coastguard Worker                            << "\tVerifying each result derivative is within its range of legal result values."
1224*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1225*35238bceSAndroid Build Coastguard Worker 
1226*35238bceSAndroid Build Coastguard Worker         {
1227*35238bceSAndroid Build Coastguard Worker             const tcu::IVec2 viewportSize = getViewportSize();
1228*35238bceSAndroid Build Coastguard Worker             const float w                 = float(viewportSize.x());
1229*35238bceSAndroid Build Coastguard Worker             const float h                 = float(viewportSize.y());
1230*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 valueRamp     = (m_coordMax - m_coordMin);
1231*35238bceSAndroid Build Coastguard Worker             Linear2DFunctionEvaluator function;
1232*35238bceSAndroid Build Coastguard Worker 
1233*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(0,
1234*35238bceSAndroid Build Coastguard Worker                                    tcu::Vec3((valueRamp.x() / w) / 2.0f, (valueRamp.x() / h) / 2.0f, m_coordMin.x()));
1235*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(1,
1236*35238bceSAndroid Build Coastguard Worker                                    tcu::Vec3((valueRamp.y() / w) / 2.0f, (valueRamp.y() / h) / 2.0f, m_coordMin.y()));
1237*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_coordMin.z() + m_coordMin.z()) /
1238*35238bceSAndroid Build Coastguard Worker                                           2.0f);
1239*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(
1240*35238bceSAndroid Build Coastguard Worker                 3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_coordMax.w() + m_coordMax.w()) / 2.0f);
1241*35238bceSAndroid Build Coastguard Worker 
1242*35238bceSAndroid Build Coastguard Worker             return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), result, errorMask, m_dataType,
1243*35238bceSAndroid Build Coastguard Worker                                                                 m_precision, m_derivScale, m_derivBias,
1244*35238bceSAndroid Build Coastguard Worker                                                                 surfaceThreshold, m_func, function);
1245*35238bceSAndroid Build Coastguard Worker         }
1246*35238bceSAndroid Build Coastguard Worker     }
1247*35238bceSAndroid Build Coastguard Worker     else
1248*35238bceSAndroid Build Coastguard Worker     {
1249*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_func == DERIVATE_FWIDTH);
1250*35238bceSAndroid Build Coastguard Worker         const float w = float(result.getWidth());
1251*35238bceSAndroid Build Coastguard Worker         const float h = float(result.getHeight());
1252*35238bceSAndroid Build Coastguard Worker 
1253*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dx          = ((m_coordMax - m_coordMin) / w) * xScale;
1254*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dy          = ((m_coordMax - m_coordMin) / h) * yScale;
1255*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 reference   = tcu::abs(dx) + tcu::abs(dy);
1256*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dxThreshold = getDerivateThreshold(m_precision, m_coordMin * xScale, m_coordMax * xScale, dx);
1257*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dyThreshold = getDerivateThreshold(m_precision, m_coordMin * yScale, m_coordMax * yScale, dy);
1258*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dxThresholdW =
1259*35238bceSAndroid Build Coastguard Worker             getDerivateThresholdWarning(m_precision, m_coordMin * xScale, m_coordMax * xScale, dx);
1260*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dyThresholdW =
1261*35238bceSAndroid Build Coastguard Worker             getDerivateThresholdWarning(m_precision, m_coordMin * yScale, m_coordMax * yScale, dy);
1262*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 threshold  = max(surfaceThreshold, max(dxThreshold, dyThreshold));
1263*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW));
1264*35238bceSAndroid Build Coastguard Worker         qpTestResult testResult    = QP_TEST_RESULT_FAIL;
1265*35238bceSAndroid Build Coastguard Worker 
1266*35238bceSAndroid Build Coastguard Worker         testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, threshold,
1267*35238bceSAndroid Build Coastguard Worker                                             m_derivScale, m_derivBias);
1268*35238bceSAndroid Build Coastguard Worker 
1269*35238bceSAndroid Build Coastguard Worker         // return if result is pass
1270*35238bceSAndroid Build Coastguard Worker         if (testResult == QP_TEST_RESULT_PASS)
1271*35238bceSAndroid Build Coastguard Worker             return testResult;
1272*35238bceSAndroid Build Coastguard Worker 
1273*35238bceSAndroid Build Coastguard Worker         // re-check with relaxed threshold
1274*35238bceSAndroid Build Coastguard Worker         testResult = verifyConstantDerivate(m_testCtx.getLog(), result, errorMask, m_dataType, reference, thresholdW,
1275*35238bceSAndroid Build Coastguard Worker                                             m_derivScale, m_derivBias);
1276*35238bceSAndroid Build Coastguard Worker 
1277*35238bceSAndroid Build Coastguard Worker         // if with relaxed threshold test is passing then mark the result with quality warning.
1278*35238bceSAndroid Build Coastguard Worker         if (testResult == QP_TEST_RESULT_PASS)
1279*35238bceSAndroid Build Coastguard Worker             testResult = QP_TEST_RESULT_QUALITY_WARNING;
1280*35238bceSAndroid Build Coastguard Worker 
1281*35238bceSAndroid Build Coastguard Worker         return testResult;
1282*35238bceSAndroid Build Coastguard Worker     }
1283*35238bceSAndroid Build Coastguard Worker }
1284*35238bceSAndroid Build Coastguard Worker 
1285*35238bceSAndroid Build Coastguard Worker // TextureDerivateCase
1286*35238bceSAndroid Build Coastguard Worker 
1287*35238bceSAndroid Build Coastguard Worker class TextureDerivateCase : public TriangleDerivateCase
1288*35238bceSAndroid Build Coastguard Worker {
1289*35238bceSAndroid Build Coastguard Worker public:
1290*35238bceSAndroid Build Coastguard Worker     TextureDerivateCase(Context &context, const char *name, const char *description, DerivateFunc func,
1291*35238bceSAndroid Build Coastguard Worker                         glu::DataType type, glu::Precision precision, uint32_t hint, SurfaceType surfaceType,
1292*35238bceSAndroid Build Coastguard Worker                         int numSamples);
1293*35238bceSAndroid Build Coastguard Worker     ~TextureDerivateCase(void);
1294*35238bceSAndroid Build Coastguard Worker 
1295*35238bceSAndroid Build Coastguard Worker     void init(void);
1296*35238bceSAndroid Build Coastguard Worker     void deinit(void);
1297*35238bceSAndroid Build Coastguard Worker 
1298*35238bceSAndroid Build Coastguard Worker protected:
1299*35238bceSAndroid Build Coastguard Worker     void setupRenderState(uint32_t program);
1300*35238bceSAndroid Build Coastguard Worker     qpTestResult verify(const tcu::ConstPixelBufferAccess &result, const tcu::PixelBufferAccess &errorMask);
1301*35238bceSAndroid Build Coastguard Worker 
1302*35238bceSAndroid Build Coastguard Worker private:
1303*35238bceSAndroid Build Coastguard Worker     DerivateFunc m_func;
1304*35238bceSAndroid Build Coastguard Worker 
1305*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_texValueMin;
1306*35238bceSAndroid Build Coastguard Worker     tcu::Vec4 m_texValueMax;
1307*35238bceSAndroid Build Coastguard Worker     glu::Texture2D *m_texture;
1308*35238bceSAndroid Build Coastguard Worker };
1309*35238bceSAndroid Build Coastguard Worker 
TextureDerivateCase(Context & context,const char * name,const char * description,DerivateFunc func,glu::DataType type,glu::Precision precision,uint32_t hint,SurfaceType surfaceType,int numSamples)1310*35238bceSAndroid Build Coastguard Worker TextureDerivateCase::TextureDerivateCase(Context &context, const char *name, const char *description, DerivateFunc func,
1311*35238bceSAndroid Build Coastguard Worker                                          glu::DataType type, glu::Precision precision, uint32_t hint,
1312*35238bceSAndroid Build Coastguard Worker                                          SurfaceType surfaceType, int numSamples)
1313*35238bceSAndroid Build Coastguard Worker     : TriangleDerivateCase(context, name, description)
1314*35238bceSAndroid Build Coastguard Worker     , m_func(func)
1315*35238bceSAndroid Build Coastguard Worker     , m_texture(DE_NULL)
1316*35238bceSAndroid Build Coastguard Worker {
1317*35238bceSAndroid Build Coastguard Worker     m_dataType       = type;
1318*35238bceSAndroid Build Coastguard Worker     m_precision      = precision;
1319*35238bceSAndroid Build Coastguard Worker     m_coordDataType  = glu::TYPE_FLOAT_VEC2;
1320*35238bceSAndroid Build Coastguard Worker     m_coordPrecision = glu::PRECISION_HIGHP;
1321*35238bceSAndroid Build Coastguard Worker     m_hint           = hint;
1322*35238bceSAndroid Build Coastguard Worker     m_surfaceType    = surfaceType;
1323*35238bceSAndroid Build Coastguard Worker     m_numSamples     = numSamples;
1324*35238bceSAndroid Build Coastguard Worker }
1325*35238bceSAndroid Build Coastguard Worker 
~TextureDerivateCase(void)1326*35238bceSAndroid Build Coastguard Worker TextureDerivateCase::~TextureDerivateCase(void)
1327*35238bceSAndroid Build Coastguard Worker {
1328*35238bceSAndroid Build Coastguard Worker     delete m_texture;
1329*35238bceSAndroid Build Coastguard Worker }
1330*35238bceSAndroid Build Coastguard Worker 
init(void)1331*35238bceSAndroid Build Coastguard Worker void TextureDerivateCase::init(void)
1332*35238bceSAndroid Build Coastguard Worker {
1333*35238bceSAndroid Build Coastguard Worker     // Generate shader
1334*35238bceSAndroid Build Coastguard Worker     {
1335*35238bceSAndroid Build Coastguard Worker         const char *fragmentTmpl = "#version 300 es\n"
1336*35238bceSAndroid Build Coastguard Worker                                    "in highp vec2 v_coord;\n"
1337*35238bceSAndroid Build Coastguard Worker                                    "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1338*35238bceSAndroid Build Coastguard Worker                                    "uniform ${PRECISION} sampler2D u_sampler;\n"
1339*35238bceSAndroid Build Coastguard Worker                                    "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1340*35238bceSAndroid Build Coastguard Worker                                    "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1341*35238bceSAndroid Build Coastguard Worker                                    "void main (void)\n"
1342*35238bceSAndroid Build Coastguard Worker                                    "{\n"
1343*35238bceSAndroid Build Coastguard Worker                                    "    ${PRECISION} vec4 tex = texture(u_sampler, v_coord);\n"
1344*35238bceSAndroid Build Coastguard Worker                                    "    ${PRECISION} ${DATATYPE} res = ${FUNC}(tex${SWIZZLE}) * u_scale + u_bias;\n"
1345*35238bceSAndroid Build Coastguard Worker                                    "    o_color = ${CAST_TO_OUTPUT};\n"
1346*35238bceSAndroid Build Coastguard Worker                                    "}\n";
1347*35238bceSAndroid Build Coastguard Worker 
1348*35238bceSAndroid Build Coastguard Worker         const bool packToInt = m_surfaceType == SURFACETYPE_FLOAT_FBO;
1349*35238bceSAndroid Build Coastguard Worker         map<string, string> fragmentParams;
1350*35238bceSAndroid Build Coastguard Worker 
1351*35238bceSAndroid Build Coastguard Worker         fragmentParams["OUTPUT_TYPE"] = glu::getDataTypeName(packToInt ? glu::TYPE_UINT_VEC4 : glu::TYPE_FLOAT_VEC4);
1352*35238bceSAndroid Build Coastguard Worker         fragmentParams["OUTPUT_PREC"] = glu::getPrecisionName(packToInt ? glu::PRECISION_HIGHP : m_precision);
1353*35238bceSAndroid Build Coastguard Worker         fragmentParams["PRECISION"]   = glu::getPrecisionName(m_precision);
1354*35238bceSAndroid Build Coastguard Worker         fragmentParams["DATATYPE"]    = glu::getDataTypeName(m_dataType);
1355*35238bceSAndroid Build Coastguard Worker         fragmentParams["FUNC"]        = getDerivateFuncName(m_func);
1356*35238bceSAndroid Build Coastguard Worker         fragmentParams["SWIZZLE"]     = m_dataType == glu::TYPE_FLOAT_VEC4 ? "" :
1357*35238bceSAndroid Build Coastguard Worker                                         m_dataType == glu::TYPE_FLOAT_VEC3 ? ".xyz" :
1358*35238bceSAndroid Build Coastguard Worker                                         m_dataType == glu::TYPE_FLOAT_VEC2 ? ".xy" :
1359*35238bceSAndroid Build Coastguard Worker                                                                              /* TYPE_FLOAT */ ".x";
1360*35238bceSAndroid Build Coastguard Worker 
1361*35238bceSAndroid Build Coastguard Worker         if (packToInt)
1362*35238bceSAndroid Build Coastguard Worker         {
1363*35238bceSAndroid Build Coastguard Worker             fragmentParams["CAST_TO_OUTPUT"] =
1364*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC4 ? "floatBitsToUint(res)" :
1365*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC3 ? "floatBitsToUint(vec4(res, 1.0))" :
1366*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC2 ? "floatBitsToUint(vec4(res, 0.0, 1.0))" :
1367*35238bceSAndroid Build Coastguard Worker                                                      /* TYPE_FLOAT */ "floatBitsToUint(vec4(res, 0.0, 0.0, 1.0))";
1368*35238bceSAndroid Build Coastguard Worker         }
1369*35238bceSAndroid Build Coastguard Worker         else
1370*35238bceSAndroid Build Coastguard Worker         {
1371*35238bceSAndroid Build Coastguard Worker             fragmentParams["CAST_TO_OUTPUT"] =
1372*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC4 ? "res" :
1373*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC3 ? "vec4(res, 1.0)" :
1374*35238bceSAndroid Build Coastguard Worker                 m_dataType == glu::TYPE_FLOAT_VEC2 ? "vec4(res, 0.0, 1.0)" :
1375*35238bceSAndroid Build Coastguard Worker                                                      /* TYPE_FLOAT */ "vec4(res, 0.0, 0.0, 1.0)";
1376*35238bceSAndroid Build Coastguard Worker         }
1377*35238bceSAndroid Build Coastguard Worker 
1378*35238bceSAndroid Build Coastguard Worker         m_fragmentSrc = tcu::StringTemplate(fragmentTmpl).specialize(fragmentParams);
1379*35238bceSAndroid Build Coastguard Worker     }
1380*35238bceSAndroid Build Coastguard Worker 
1381*35238bceSAndroid Build Coastguard Worker     // Texture size matches viewport and nearest sampling is used. Thus texture sampling
1382*35238bceSAndroid Build Coastguard Worker     // is equal to just interpolating the texture value range.
1383*35238bceSAndroid Build Coastguard Worker 
1384*35238bceSAndroid Build Coastguard Worker     // Determine value range for texture.
1385*35238bceSAndroid Build Coastguard Worker 
1386*35238bceSAndroid Build Coastguard Worker     switch (m_precision)
1387*35238bceSAndroid Build Coastguard Worker     {
1388*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_HIGHP:
1389*35238bceSAndroid Build Coastguard Worker         m_texValueMin = tcu::Vec4(-97.f, 0.2f, 71.f, 74.f);
1390*35238bceSAndroid Build Coastguard Worker         m_texValueMax = tcu::Vec4(-13.2f, -77.f, 44.f, 76.f);
1391*35238bceSAndroid Build Coastguard Worker         break;
1392*35238bceSAndroid Build Coastguard Worker 
1393*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_MEDIUMP:
1394*35238bceSAndroid Build Coastguard Worker         m_texValueMin = tcu::Vec4(-37.0f, 47.f, -7.f, 0.0f);
1395*35238bceSAndroid Build Coastguard Worker         m_texValueMax = tcu::Vec4(-1.0f, 12.f, 7.f, 19.f);
1396*35238bceSAndroid Build Coastguard Worker         break;
1397*35238bceSAndroid Build Coastguard Worker 
1398*35238bceSAndroid Build Coastguard Worker     case glu::PRECISION_LOWP:
1399*35238bceSAndroid Build Coastguard Worker         m_texValueMin = tcu::Vec4(0.0f, -1.0f, 0.0f, 1.0f);
1400*35238bceSAndroid Build Coastguard Worker         m_texValueMax = tcu::Vec4(1.0f, 1.0f, -1.0f, -1.0f);
1401*35238bceSAndroid Build Coastguard Worker         break;
1402*35238bceSAndroid Build Coastguard Worker 
1403*35238bceSAndroid Build Coastguard Worker     default:
1404*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(false);
1405*35238bceSAndroid Build Coastguard Worker     }
1406*35238bceSAndroid Build Coastguard Worker 
1407*35238bceSAndroid Build Coastguard Worker     // Lowp and mediump cases use RGBA16F format, while highp uses RGBA32F.
1408*35238bceSAndroid Build Coastguard Worker     {
1409*35238bceSAndroid Build Coastguard Worker         const tcu::IVec2 viewportSize = getViewportSize();
1410*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(!m_texture);
1411*35238bceSAndroid Build Coastguard Worker         m_texture = new glu::Texture2D(m_context.getRenderContext(),
1412*35238bceSAndroid Build Coastguard Worker                                        m_precision == glu::PRECISION_HIGHP ? GL_RGBA32F : GL_RGBA16F, viewportSize.x(),
1413*35238bceSAndroid Build Coastguard Worker                                        viewportSize.y());
1414*35238bceSAndroid Build Coastguard Worker         m_texture->getRefTexture().allocLevel(0);
1415*35238bceSAndroid Build Coastguard Worker     }
1416*35238bceSAndroid Build Coastguard Worker 
1417*35238bceSAndroid Build Coastguard Worker     // Texture coordinates
1418*35238bceSAndroid Build Coastguard Worker     m_coordMin = tcu::Vec4(0.0f);
1419*35238bceSAndroid Build Coastguard Worker     m_coordMax = tcu::Vec4(1.0f);
1420*35238bceSAndroid Build Coastguard Worker 
1421*35238bceSAndroid Build Coastguard Worker     // Fill with gradients.
1422*35238bceSAndroid Build Coastguard Worker     {
1423*35238bceSAndroid Build Coastguard Worker         const tcu::PixelBufferAccess level0 = m_texture->getRefTexture().getLevel(0);
1424*35238bceSAndroid Build Coastguard Worker         for (int y = 0; y < level0.getHeight(); y++)
1425*35238bceSAndroid Build Coastguard Worker         {
1426*35238bceSAndroid Build Coastguard Worker             for (int x = 0; x < level0.getWidth(); x++)
1427*35238bceSAndroid Build Coastguard Worker             {
1428*35238bceSAndroid Build Coastguard Worker                 const float xf = (float(x) + 0.5f) / float(level0.getWidth());
1429*35238bceSAndroid Build Coastguard Worker                 const float yf = (float(y) + 0.5f) / float(level0.getHeight());
1430*35238bceSAndroid Build Coastguard Worker                 // Make x and y data to have dependency to both axes so that dfdx(tex).y and dfdy(tex).x are nonzero.
1431*35238bceSAndroid Build Coastguard Worker                 const tcu::Vec4 s =
1432*35238bceSAndroid Build Coastguard Worker                     tcu::Vec4(xf + yf / 2.0f, yf + xf / 2.0f, (xf + yf) / 2.0f, 1.0f - (xf + yf) / 2.0f);
1433*35238bceSAndroid Build Coastguard Worker 
1434*35238bceSAndroid Build Coastguard Worker                 level0.setPixel(m_texValueMin + (m_texValueMax - m_texValueMin) * s, x, y);
1435*35238bceSAndroid Build Coastguard Worker             }
1436*35238bceSAndroid Build Coastguard Worker         }
1437*35238bceSAndroid Build Coastguard Worker     }
1438*35238bceSAndroid Build Coastguard Worker 
1439*35238bceSAndroid Build Coastguard Worker     m_texture->upload();
1440*35238bceSAndroid Build Coastguard Worker 
1441*35238bceSAndroid Build Coastguard Worker     if (m_surfaceType == SURFACETYPE_FLOAT_FBO)
1442*35238bceSAndroid Build Coastguard Worker     {
1443*35238bceSAndroid Build Coastguard Worker         // No scale or bias used for accuracy.
1444*35238bceSAndroid Build Coastguard Worker         m_derivScale = tcu::Vec4(1.0f);
1445*35238bceSAndroid Build Coastguard Worker         m_derivBias  = tcu::Vec4(0.0f);
1446*35238bceSAndroid Build Coastguard Worker     }
1447*35238bceSAndroid Build Coastguard Worker     else
1448*35238bceSAndroid Build Coastguard Worker     {
1449*35238bceSAndroid Build Coastguard Worker         // Compute scale - bias that normalizes to 0..1 range.
1450*35238bceSAndroid Build Coastguard Worker         const tcu::IVec2 viewportSize = getViewportSize();
1451*35238bceSAndroid Build Coastguard Worker         const float w                 = float(viewportSize.x());
1452*35238bceSAndroid Build Coastguard Worker         const float h                 = float(viewportSize.y());
1453*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dx            = (m_texValueMax - m_texValueMin) / tcu::Vec4(w, w, w * 0.5f, -w * 0.5f);
1454*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dy            = (m_texValueMax - m_texValueMin) / tcu::Vec4(h, h, h * 0.5f, -h * 0.5f);
1455*35238bceSAndroid Build Coastguard Worker 
1456*35238bceSAndroid Build Coastguard Worker         switch (m_func)
1457*35238bceSAndroid Build Coastguard Worker         {
1458*35238bceSAndroid Build Coastguard Worker         case DERIVATE_DFDX:
1459*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / dx;
1460*35238bceSAndroid Build Coastguard Worker             break;
1461*35238bceSAndroid Build Coastguard Worker 
1462*35238bceSAndroid Build Coastguard Worker         case DERIVATE_DFDY:
1463*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / dy;
1464*35238bceSAndroid Build Coastguard Worker             break;
1465*35238bceSAndroid Build Coastguard Worker 
1466*35238bceSAndroid Build Coastguard Worker         case DERIVATE_FWIDTH:
1467*35238bceSAndroid Build Coastguard Worker             m_derivScale = 0.5f / (tcu::abs(dx) + tcu::abs(dy));
1468*35238bceSAndroid Build Coastguard Worker             break;
1469*35238bceSAndroid Build Coastguard Worker 
1470*35238bceSAndroid Build Coastguard Worker         default:
1471*35238bceSAndroid Build Coastguard Worker             DE_ASSERT(false);
1472*35238bceSAndroid Build Coastguard Worker         }
1473*35238bceSAndroid Build Coastguard Worker 
1474*35238bceSAndroid Build Coastguard Worker         m_derivBias = tcu::Vec4(0.0f, 0.0f, 0.0f, 0.0f);
1475*35238bceSAndroid Build Coastguard Worker     }
1476*35238bceSAndroid Build Coastguard Worker }
1477*35238bceSAndroid Build Coastguard Worker 
deinit(void)1478*35238bceSAndroid Build Coastguard Worker void TextureDerivateCase::deinit(void)
1479*35238bceSAndroid Build Coastguard Worker {
1480*35238bceSAndroid Build Coastguard Worker     delete m_texture;
1481*35238bceSAndroid Build Coastguard Worker     m_texture = DE_NULL;
1482*35238bceSAndroid Build Coastguard Worker }
1483*35238bceSAndroid Build Coastguard Worker 
setupRenderState(uint32_t program)1484*35238bceSAndroid Build Coastguard Worker void TextureDerivateCase::setupRenderState(uint32_t program)
1485*35238bceSAndroid Build Coastguard Worker {
1486*35238bceSAndroid Build Coastguard Worker     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
1487*35238bceSAndroid Build Coastguard Worker     const int texUnit        = 1;
1488*35238bceSAndroid Build Coastguard Worker 
1489*35238bceSAndroid Build Coastguard Worker     gl.activeTexture(GL_TEXTURE0 + texUnit);
1490*35238bceSAndroid Build Coastguard Worker     gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture());
1491*35238bceSAndroid Build Coastguard Worker     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST);
1492*35238bceSAndroid Build Coastguard Worker     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST);
1493*35238bceSAndroid Build Coastguard Worker     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_CLAMP_TO_EDGE);
1494*35238bceSAndroid Build Coastguard Worker     gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_CLAMP_TO_EDGE);
1495*35238bceSAndroid Build Coastguard Worker 
1496*35238bceSAndroid Build Coastguard Worker     gl.uniform1i(gl.getUniformLocation(program, "u_sampler"), texUnit);
1497*35238bceSAndroid Build Coastguard Worker }
1498*35238bceSAndroid Build Coastguard Worker 
verify(const tcu::ConstPixelBufferAccess & result,const tcu::PixelBufferAccess & errorMask)1499*35238bceSAndroid Build Coastguard Worker qpTestResult TextureDerivateCase::verify(const tcu::ConstPixelBufferAccess &result,
1500*35238bceSAndroid Build Coastguard Worker                                          const tcu::PixelBufferAccess &errorMask)
1501*35238bceSAndroid Build Coastguard Worker {
1502*35238bceSAndroid Build Coastguard Worker     // \note Edges are ignored in comparison
1503*35238bceSAndroid Build Coastguard Worker     if (result.getWidth() < 2 || result.getHeight() < 2)
1504*35238bceSAndroid Build Coastguard Worker         throw tcu::NotSupportedError("Too small viewport");
1505*35238bceSAndroid Build Coastguard Worker 
1506*35238bceSAndroid Build Coastguard Worker     tcu::ConstPixelBufferAccess compareArea =
1507*35238bceSAndroid Build Coastguard Worker         tcu::getSubregion(result, 1, 1, result.getWidth() - 2, result.getHeight() - 2);
1508*35238bceSAndroid Build Coastguard Worker     tcu::PixelBufferAccess maskArea =
1509*35238bceSAndroid Build Coastguard Worker         tcu::getSubregion(errorMask, 1, 1, errorMask.getWidth() - 2, errorMask.getHeight() - 2);
1510*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 xScale = tcu::Vec4(1.0f, 0.5f, 0.5f, -0.5f);
1511*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 yScale = tcu::Vec4(0.5f, 1.0f, 0.5f, -0.5f);
1512*35238bceSAndroid Build Coastguard Worker     const float w          = float(result.getWidth());
1513*35238bceSAndroid Build Coastguard Worker     const float h          = float(result.getHeight());
1514*35238bceSAndroid Build Coastguard Worker 
1515*35238bceSAndroid Build Coastguard Worker     const tcu::Vec4 surfaceThreshold = getSurfaceThreshold() / abs(m_derivScale);
1516*35238bceSAndroid Build Coastguard Worker 
1517*35238bceSAndroid Build Coastguard Worker     if (m_func == DERIVATE_DFDX || m_func == DERIVATE_DFDY)
1518*35238bceSAndroid Build Coastguard Worker     {
1519*35238bceSAndroid Build Coastguard Worker         const bool isX              = m_func == DERIVATE_DFDX;
1520*35238bceSAndroid Build Coastguard Worker         const float div             = isX ? w : h;
1521*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 scale       = isX ? xScale : yScale;
1522*35238bceSAndroid Build Coastguard Worker         tcu::Vec4 reference         = ((m_texValueMax - m_texValueMin) / div);
1523*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 opThreshold = getDerivateThreshold(m_precision, m_texValueMin, m_texValueMax, reference);
1524*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 opThresholdW =
1525*35238bceSAndroid Build Coastguard Worker             getDerivateThresholdWarning(m_precision, m_texValueMin, m_texValueMax, reference);
1526*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 threshold  = max(surfaceThreshold, opThreshold);
1527*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 thresholdW = max(surfaceThreshold, opThresholdW);
1528*35238bceSAndroid Build Coastguard Worker         const int numComps         = glu::getDataTypeFloatScalars(m_dataType);
1529*35238bceSAndroid Build Coastguard Worker 
1530*35238bceSAndroid Build Coastguard Worker         /* adjust the reference value for the correct dfdx or dfdy sample adjacency */
1531*35238bceSAndroid Build Coastguard Worker         reference = reference * scale;
1532*35238bceSAndroid Build Coastguard Worker 
1533*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result image.\n"
1534*35238bceSAndroid Build Coastguard Worker                            << "\tValid derivative is " << LogVecComps(reference, numComps) << " with threshold "
1535*35238bceSAndroid Build Coastguard Worker                            << LogVecComps(threshold, numComps) << tcu::TestLog::EndMessage;
1536*35238bceSAndroid Build Coastguard Worker 
1537*35238bceSAndroid Build Coastguard Worker         // short circuit if result is strictly within the normal value error bounds.
1538*35238bceSAndroid Build Coastguard Worker         // This improves performance significantly.
1539*35238bceSAndroid Build Coastguard Worker         if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference, threshold,
1540*35238bceSAndroid Build Coastguard Worker                                    m_derivScale, m_derivBias, LOG_NOTHING) == QP_TEST_RESULT_PASS)
1541*35238bceSAndroid Build Coastguard Worker         {
1542*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message << "No incorrect derivatives found, result valid."
1543*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1544*35238bceSAndroid Build Coastguard Worker 
1545*35238bceSAndroid Build Coastguard Worker             return QP_TEST_RESULT_PASS;
1546*35238bceSAndroid Build Coastguard Worker         }
1547*35238bceSAndroid Build Coastguard Worker 
1548*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message << "Verifying result image.\n"
1549*35238bceSAndroid Build Coastguard Worker                            << "\tValid derivative is " << LogVecComps(reference, numComps) << " with Warning threshold "
1550*35238bceSAndroid Build Coastguard Worker                            << LogVecComps(thresholdW, numComps) << tcu::TestLog::EndMessage;
1551*35238bceSAndroid Build Coastguard Worker 
1552*35238bceSAndroid Build Coastguard Worker         // Re-check with relaxed threshold
1553*35238bceSAndroid Build Coastguard Worker         if (verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference, thresholdW,
1554*35238bceSAndroid Build Coastguard Worker                                    m_derivScale, m_derivBias, LOG_NOTHING) == QP_TEST_RESULT_PASS)
1555*35238bceSAndroid Build Coastguard Worker         {
1556*35238bceSAndroid Build Coastguard Worker             m_testCtx.getLog() << tcu::TestLog::Message
1557*35238bceSAndroid Build Coastguard Worker                                << "No incorrect derivatives found, result valid with quality warning."
1558*35238bceSAndroid Build Coastguard Worker                                << tcu::TestLog::EndMessage;
1559*35238bceSAndroid Build Coastguard Worker 
1560*35238bceSAndroid Build Coastguard Worker             return QP_TEST_RESULT_QUALITY_WARNING;
1561*35238bceSAndroid Build Coastguard Worker         }
1562*35238bceSAndroid Build Coastguard Worker 
1563*35238bceSAndroid Build Coastguard Worker         // some pixels exceed error bounds calculated for normal values. Verify that these
1564*35238bceSAndroid Build Coastguard Worker         // potentially invalid pixels are in fact valid due to (for example) subnorm flushing.
1565*35238bceSAndroid Build Coastguard Worker 
1566*35238bceSAndroid Build Coastguard Worker         m_testCtx.getLog() << tcu::TestLog::Message
1567*35238bceSAndroid Build Coastguard Worker                            << "Initial verification failed, verifying image by calculating accurate error bounds for "
1568*35238bceSAndroid Build Coastguard Worker                               "each result pixel.\n"
1569*35238bceSAndroid Build Coastguard Worker                            << "\tVerifying each result derivative is within its range of legal result values."
1570*35238bceSAndroid Build Coastguard Worker                            << tcu::TestLog::EndMessage;
1571*35238bceSAndroid Build Coastguard Worker 
1572*35238bceSAndroid Build Coastguard Worker         {
1573*35238bceSAndroid Build Coastguard Worker             const tcu::Vec4 valueRamp = (m_texValueMax - m_texValueMin);
1574*35238bceSAndroid Build Coastguard Worker             Linear2DFunctionEvaluator function;
1575*35238bceSAndroid Build Coastguard Worker 
1576*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(0, tcu::Vec3(valueRamp.x() / w, (valueRamp.x() / h) / 2.0f, m_texValueMin.x()));
1577*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(1, tcu::Vec3((valueRamp.y() / w) / 2.0f, valueRamp.y() / h, m_texValueMin.y()));
1578*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(
1579*35238bceSAndroid Build Coastguard Worker                 2, tcu::Vec3(valueRamp.z() / w, valueRamp.z() / h, m_texValueMin.z() + m_texValueMin.z()) / 2.0f);
1580*35238bceSAndroid Build Coastguard Worker             function.matrix.setRow(
1581*35238bceSAndroid Build Coastguard Worker                 3, tcu::Vec3(-valueRamp.w() / w, -valueRamp.w() / h, m_texValueMax.w() + m_texValueMax.w()) / 2.0f);
1582*35238bceSAndroid Build Coastguard Worker 
1583*35238bceSAndroid Build Coastguard Worker             return reverifyConstantDerivateWithFlushRelaxations(m_testCtx.getLog(), compareArea, maskArea, m_dataType,
1584*35238bceSAndroid Build Coastguard Worker                                                                 m_precision, m_derivScale, m_derivBias,
1585*35238bceSAndroid Build Coastguard Worker                                                                 surfaceThreshold, m_func, function);
1586*35238bceSAndroid Build Coastguard Worker         }
1587*35238bceSAndroid Build Coastguard Worker     }
1588*35238bceSAndroid Build Coastguard Worker     else
1589*35238bceSAndroid Build Coastguard Worker     {
1590*35238bceSAndroid Build Coastguard Worker         DE_ASSERT(m_func == DERIVATE_FWIDTH);
1591*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dx        = ((m_texValueMax - m_texValueMin) / w) * xScale;
1592*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dy        = ((m_texValueMax - m_texValueMin) / h) * yScale;
1593*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 reference = tcu::abs(dx) + tcu::abs(dy);
1594*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dxThreshold =
1595*35238bceSAndroid Build Coastguard Worker             getDerivateThreshold(m_precision, m_texValueMin * xScale, m_texValueMax * xScale, dx);
1596*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dyThreshold =
1597*35238bceSAndroid Build Coastguard Worker             getDerivateThreshold(m_precision, m_texValueMin * yScale, m_texValueMax * yScale, dy);
1598*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dxThresholdW =
1599*35238bceSAndroid Build Coastguard Worker             getDerivateThresholdWarning(m_precision, m_texValueMin * xScale, m_texValueMax * xScale, dx);
1600*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 dyThresholdW =
1601*35238bceSAndroid Build Coastguard Worker             getDerivateThresholdWarning(m_precision, m_texValueMin * yScale, m_texValueMax * yScale, dy);
1602*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 threshold  = max(surfaceThreshold, max(dxThreshold, dyThreshold));
1603*35238bceSAndroid Build Coastguard Worker         const tcu::Vec4 thresholdW = max(surfaceThreshold, max(dxThresholdW, dyThresholdW));
1604*35238bceSAndroid Build Coastguard Worker         qpTestResult testResult    = QP_TEST_RESULT_FAIL;
1605*35238bceSAndroid Build Coastguard Worker 
1606*35238bceSAndroid Build Coastguard Worker         testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference, threshold,
1607*35238bceSAndroid Build Coastguard Worker                                             m_derivScale, m_derivBias);
1608*35238bceSAndroid Build Coastguard Worker 
1609*35238bceSAndroid Build Coastguard Worker         if (testResult == QP_TEST_RESULT_PASS)
1610*35238bceSAndroid Build Coastguard Worker             return testResult;
1611*35238bceSAndroid Build Coastguard Worker 
1612*35238bceSAndroid Build Coastguard Worker         // Re-Check with relaxed threshold
1613*35238bceSAndroid Build Coastguard Worker         testResult = verifyConstantDerivate(m_testCtx.getLog(), compareArea, maskArea, m_dataType, reference,
1614*35238bceSAndroid Build Coastguard Worker                                             thresholdW, m_derivScale, m_derivBias);
1615*35238bceSAndroid Build Coastguard Worker 
1616*35238bceSAndroid Build Coastguard Worker         // If test is passing with relaxed threshold then mark quality warning
1617*35238bceSAndroid Build Coastguard Worker         if (testResult == QP_TEST_RESULT_PASS)
1618*35238bceSAndroid Build Coastguard Worker             testResult = QP_TEST_RESULT_QUALITY_WARNING;
1619*35238bceSAndroid Build Coastguard Worker 
1620*35238bceSAndroid Build Coastguard Worker         return testResult;
1621*35238bceSAndroid Build Coastguard Worker     }
1622*35238bceSAndroid Build Coastguard Worker }
1623*35238bceSAndroid Build Coastguard Worker 
ShaderDerivateTests(Context & context)1624*35238bceSAndroid Build Coastguard Worker ShaderDerivateTests::ShaderDerivateTests(Context &context)
1625*35238bceSAndroid Build Coastguard Worker     : TestCaseGroup(context, "derivate", "Derivate Function Tests")
1626*35238bceSAndroid Build Coastguard Worker {
1627*35238bceSAndroid Build Coastguard Worker }
1628*35238bceSAndroid Build Coastguard Worker 
~ShaderDerivateTests(void)1629*35238bceSAndroid Build Coastguard Worker ShaderDerivateTests::~ShaderDerivateTests(void)
1630*35238bceSAndroid Build Coastguard Worker {
1631*35238bceSAndroid Build Coastguard Worker }
1632*35238bceSAndroid Build Coastguard Worker 
1633*35238bceSAndroid Build Coastguard Worker struct FunctionSpec
1634*35238bceSAndroid Build Coastguard Worker {
1635*35238bceSAndroid Build Coastguard Worker     std::string name;
1636*35238bceSAndroid Build Coastguard Worker     DerivateFunc function;
1637*35238bceSAndroid Build Coastguard Worker     glu::DataType dataType;
1638*35238bceSAndroid Build Coastguard Worker     glu::Precision precision;
1639*35238bceSAndroid Build Coastguard Worker 
FunctionSpecdeqp::gles3::Functional::FunctionSpec1640*35238bceSAndroid Build Coastguard Worker     FunctionSpec(const std::string &name_, DerivateFunc function_, glu::DataType dataType_, glu::Precision precision_)
1641*35238bceSAndroid Build Coastguard Worker         : name(name_)
1642*35238bceSAndroid Build Coastguard Worker         , function(function_)
1643*35238bceSAndroid Build Coastguard Worker         , dataType(dataType_)
1644*35238bceSAndroid Build Coastguard Worker         , precision(precision_)
1645*35238bceSAndroid Build Coastguard Worker     {
1646*35238bceSAndroid Build Coastguard Worker     }
1647*35238bceSAndroid Build Coastguard Worker };
1648*35238bceSAndroid Build Coastguard Worker 
init(void)1649*35238bceSAndroid Build Coastguard Worker void ShaderDerivateTests::init(void)
1650*35238bceSAndroid Build Coastguard Worker {
1651*35238bceSAndroid Build Coastguard Worker     static const struct
1652*35238bceSAndroid Build Coastguard Worker     {
1653*35238bceSAndroid Build Coastguard Worker         const char *name;
1654*35238bceSAndroid Build Coastguard Worker         const char *description;
1655*35238bceSAndroid Build Coastguard Worker         const char *source;
1656*35238bceSAndroid Build Coastguard Worker     } s_linearDerivateCases[] = {
1657*35238bceSAndroid Build Coastguard Worker         {"linear", "Basic derivate of linearly interpolated argument",
1658*35238bceSAndroid Build Coastguard Worker 
1659*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1660*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1661*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1662*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1663*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1664*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1665*35238bceSAndroid Build Coastguard Worker          "{\n"
1666*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
1667*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1668*35238bceSAndroid Build Coastguard Worker          "}\n"},
1669*35238bceSAndroid Build Coastguard Worker         {"in_function", "Derivate of linear function argument",
1670*35238bceSAndroid Build Coastguard Worker 
1671*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1672*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1673*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1674*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1675*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1676*35238bceSAndroid Build Coastguard Worker          "\n"
1677*35238bceSAndroid Build Coastguard Worker          "${PRECISION} ${DATATYPE} computeRes (${PRECISION} ${DATATYPE} value)\n"
1678*35238bceSAndroid Build Coastguard Worker          "{\n"
1679*35238bceSAndroid Build Coastguard Worker          "    return ${FUNC}(v_coord) * u_scale + u_bias;\n"
1680*35238bceSAndroid Build Coastguard Worker          "}\n"
1681*35238bceSAndroid Build Coastguard Worker          "\n"
1682*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1683*35238bceSAndroid Build Coastguard Worker          "{\n"
1684*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res = computeRes(v_coord);\n"
1685*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1686*35238bceSAndroid Build Coastguard Worker          "}\n"},
1687*35238bceSAndroid Build Coastguard Worker         {"static_if", "Derivate of linearly interpolated value in static if",
1688*35238bceSAndroid Build Coastguard Worker 
1689*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1690*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1691*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1692*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1693*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1694*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1695*35238bceSAndroid Build Coastguard Worker          "{\n"
1696*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res;\n"
1697*35238bceSAndroid Build Coastguard Worker          "    if (false)\n"
1698*35238bceSAndroid Build Coastguard Worker          "        res = ${FUNC}(-v_coord) * u_scale + u_bias;\n"
1699*35238bceSAndroid Build Coastguard Worker          "    else\n"
1700*35238bceSAndroid Build Coastguard Worker          "        res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
1701*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1702*35238bceSAndroid Build Coastguard Worker          "}\n"},
1703*35238bceSAndroid Build Coastguard Worker         {"static_loop", "Derivate of linearly interpolated value in static loop",
1704*35238bceSAndroid Build Coastguard Worker 
1705*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1706*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1707*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1708*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1709*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1710*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1711*35238bceSAndroid Build Coastguard Worker          "{\n"
1712*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n"
1713*35238bceSAndroid Build Coastguard Worker          "    for (int i = 0; i < 2; i++)\n"
1714*35238bceSAndroid Build Coastguard Worker          "        res += ${FUNC}(v_coord * float(i));\n"
1715*35238bceSAndroid Build Coastguard Worker          "    res = res * u_scale + u_bias;\n"
1716*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1717*35238bceSAndroid Build Coastguard Worker          "}\n"},
1718*35238bceSAndroid Build Coastguard Worker         {"static_switch", "Derivate of linearly interpolated value in static switch",
1719*35238bceSAndroid Build Coastguard Worker 
1720*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1721*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1722*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1723*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1724*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1725*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1726*35238bceSAndroid Build Coastguard Worker          "{\n"
1727*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res;\n"
1728*35238bceSAndroid Build Coastguard Worker          "    switch (1)\n"
1729*35238bceSAndroid Build Coastguard Worker          "    {\n"
1730*35238bceSAndroid Build Coastguard Worker          "        case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias;    break;\n"
1731*35238bceSAndroid Build Coastguard Worker          "        case 1: res = ${FUNC}(v_coord) * u_scale + u_bias;    break;\n"
1732*35238bceSAndroid Build Coastguard Worker          "    }\n"
1733*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1734*35238bceSAndroid Build Coastguard Worker          "}\n"},
1735*35238bceSAndroid Build Coastguard Worker         {"uniform_if", "Derivate of linearly interpolated value in uniform if",
1736*35238bceSAndroid Build Coastguard Worker 
1737*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1738*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1739*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1740*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1741*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1742*35238bceSAndroid Build Coastguard Worker          "uniform bool ub_true;\n"
1743*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1744*35238bceSAndroid Build Coastguard Worker          "{\n"
1745*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res;\n"
1746*35238bceSAndroid Build Coastguard Worker          "    if (ub_true)"
1747*35238bceSAndroid Build Coastguard Worker          "        res = ${FUNC}(v_coord) * u_scale + u_bias;\n"
1748*35238bceSAndroid Build Coastguard Worker          "    else\n"
1749*35238bceSAndroid Build Coastguard Worker          "        res = ${FUNC}(-v_coord) * u_scale + u_bias;\n"
1750*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1751*35238bceSAndroid Build Coastguard Worker          "}\n"},
1752*35238bceSAndroid Build Coastguard Worker         {"uniform_loop", "Derivate of linearly interpolated value in uniform loop",
1753*35238bceSAndroid Build Coastguard Worker 
1754*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1755*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1756*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1757*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1758*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1759*35238bceSAndroid Build Coastguard Worker          "uniform int ui_two;\n"
1760*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1761*35238bceSAndroid Build Coastguard Worker          "{\n"
1762*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res = ${DATATYPE}(0.0);\n"
1763*35238bceSAndroid Build Coastguard Worker          "    for (int i = 0; i < ui_two; i++)\n"
1764*35238bceSAndroid Build Coastguard Worker          "        res += ${FUNC}(v_coord * float(i));\n"
1765*35238bceSAndroid Build Coastguard Worker          "    res = res * u_scale + u_bias;\n"
1766*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1767*35238bceSAndroid Build Coastguard Worker          "}\n"},
1768*35238bceSAndroid Build Coastguard Worker         {"uniform_switch", "Derivate of linearly interpolated value in uniform switch",
1769*35238bceSAndroid Build Coastguard Worker 
1770*35238bceSAndroid Build Coastguard Worker          "#version 300 es\n"
1771*35238bceSAndroid Build Coastguard Worker          "in ${PRECISION} ${DATATYPE} v_coord;\n"
1772*35238bceSAndroid Build Coastguard Worker          "layout(location = 0) out ${OUTPUT_PREC} ${OUTPUT_TYPE} o_color;\n"
1773*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_scale;\n"
1774*35238bceSAndroid Build Coastguard Worker          "uniform ${PRECISION} ${DATATYPE} u_bias;\n"
1775*35238bceSAndroid Build Coastguard Worker          "uniform int ui_one;\n"
1776*35238bceSAndroid Build Coastguard Worker          "void main (void)\n"
1777*35238bceSAndroid Build Coastguard Worker          "{\n"
1778*35238bceSAndroid Build Coastguard Worker          "    ${PRECISION} ${DATATYPE} res;\n"
1779*35238bceSAndroid Build Coastguard Worker          "    switch (ui_one)\n"
1780*35238bceSAndroid Build Coastguard Worker          "    {\n"
1781*35238bceSAndroid Build Coastguard Worker          "        case 0: res = ${FUNC}(-v_coord) * u_scale + u_bias;    break;\n"
1782*35238bceSAndroid Build Coastguard Worker          "        case 1: res = ${FUNC}(v_coord) * u_scale + u_bias;    break;\n"
1783*35238bceSAndroid Build Coastguard Worker          "    }\n"
1784*35238bceSAndroid Build Coastguard Worker          "    o_color = ${CAST_TO_OUTPUT};\n"
1785*35238bceSAndroid Build Coastguard Worker          "}\n"},
1786*35238bceSAndroid Build Coastguard Worker     };
1787*35238bceSAndroid Build Coastguard Worker 
1788*35238bceSAndroid Build Coastguard Worker     static const struct
1789*35238bceSAndroid Build Coastguard Worker     {
1790*35238bceSAndroid Build Coastguard Worker         const char *name;
1791*35238bceSAndroid Build Coastguard Worker         SurfaceType surfaceType;
1792*35238bceSAndroid Build Coastguard Worker         int numSamples;
1793*35238bceSAndroid Build Coastguard Worker     } s_fboConfigs[] = {
1794*35238bceSAndroid Build Coastguard Worker         {"fbo", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0},
1795*35238bceSAndroid Build Coastguard Worker         {"fbo_msaa2", SURFACETYPE_UNORM_FBO, 2},
1796*35238bceSAndroid Build Coastguard Worker         {"fbo_msaa4", SURFACETYPE_UNORM_FBO, 4},
1797*35238bceSAndroid Build Coastguard Worker         {"fbo_float", SURFACETYPE_FLOAT_FBO, 0},
1798*35238bceSAndroid Build Coastguard Worker     };
1799*35238bceSAndroid Build Coastguard Worker 
1800*35238bceSAndroid Build Coastguard Worker     static const struct
1801*35238bceSAndroid Build Coastguard Worker     {
1802*35238bceSAndroid Build Coastguard Worker         const char *name;
1803*35238bceSAndroid Build Coastguard Worker         uint32_t hint;
1804*35238bceSAndroid Build Coastguard Worker     } s_hints[] = {
1805*35238bceSAndroid Build Coastguard Worker         {"fastest", GL_FASTEST},
1806*35238bceSAndroid Build Coastguard Worker         {"nicest", GL_NICEST},
1807*35238bceSAndroid Build Coastguard Worker     };
1808*35238bceSAndroid Build Coastguard Worker 
1809*35238bceSAndroid Build Coastguard Worker     static const struct
1810*35238bceSAndroid Build Coastguard Worker     {
1811*35238bceSAndroid Build Coastguard Worker         const char *name;
1812*35238bceSAndroid Build Coastguard Worker         SurfaceType surfaceType;
1813*35238bceSAndroid Build Coastguard Worker         int numSamples;
1814*35238bceSAndroid Build Coastguard Worker     } s_hintFboConfigs[] = {{"default", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0},
1815*35238bceSAndroid Build Coastguard Worker                             {"fbo_msaa4", SURFACETYPE_UNORM_FBO, 4},
1816*35238bceSAndroid Build Coastguard Worker                             {"fbo_float", SURFACETYPE_FLOAT_FBO, 0}};
1817*35238bceSAndroid Build Coastguard Worker 
1818*35238bceSAndroid Build Coastguard Worker     static const struct
1819*35238bceSAndroid Build Coastguard Worker     {
1820*35238bceSAndroid Build Coastguard Worker         const char *name;
1821*35238bceSAndroid Build Coastguard Worker         SurfaceType surfaceType;
1822*35238bceSAndroid Build Coastguard Worker         int numSamples;
1823*35238bceSAndroid Build Coastguard Worker         uint32_t hint;
1824*35238bceSAndroid Build Coastguard Worker     } s_textureConfigs[] = {
1825*35238bceSAndroid Build Coastguard Worker         {"basic", SURFACETYPE_DEFAULT_FRAMEBUFFER, 0, GL_DONT_CARE},
1826*35238bceSAndroid Build Coastguard Worker         {"msaa4", SURFACETYPE_UNORM_FBO, 4, GL_DONT_CARE},
1827*35238bceSAndroid Build Coastguard Worker         {"float_fastest", SURFACETYPE_FLOAT_FBO, 0, GL_FASTEST},
1828*35238bceSAndroid Build Coastguard Worker         {"float_nicest", SURFACETYPE_FLOAT_FBO, 0, GL_NICEST},
1829*35238bceSAndroid Build Coastguard Worker     };
1830*35238bceSAndroid Build Coastguard Worker 
1831*35238bceSAndroid Build Coastguard Worker     // .dfdx, .dfdy, .fwidth
1832*35238bceSAndroid Build Coastguard Worker     for (int funcNdx = 0; funcNdx < DERIVATE_LAST; funcNdx++)
1833*35238bceSAndroid Build Coastguard Worker     {
1834*35238bceSAndroid Build Coastguard Worker         const DerivateFunc function = DerivateFunc(funcNdx);
1835*35238bceSAndroid Build Coastguard Worker         tcu::TestCaseGroup *const functionGroup =
1836*35238bceSAndroid Build Coastguard Worker             new tcu::TestCaseGroup(m_testCtx, getDerivateFuncCaseName(function), getDerivateFuncName(function));
1837*35238bceSAndroid Build Coastguard Worker         addChild(functionGroup);
1838*35238bceSAndroid Build Coastguard Worker 
1839*35238bceSAndroid Build Coastguard Worker         // .constant - no precision variants, checks that derivate of constant arguments is 0
1840*35238bceSAndroid Build Coastguard Worker         {
1841*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *const constantGroup =
1842*35238bceSAndroid Build Coastguard Worker                 new tcu::TestCaseGroup(m_testCtx, "constant", "Derivate of constant argument");
1843*35238bceSAndroid Build Coastguard Worker             functionGroup->addChild(constantGroup);
1844*35238bceSAndroid Build Coastguard Worker 
1845*35238bceSAndroid Build Coastguard Worker             for (int vecSize = 1; vecSize <= 4; vecSize++)
1846*35238bceSAndroid Build Coastguard Worker             {
1847*35238bceSAndroid Build Coastguard Worker                 const glu::DataType dataType = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1848*35238bceSAndroid Build Coastguard Worker                 constantGroup->addChild(
1849*35238bceSAndroid Build Coastguard Worker                     new ConstantDerivateCase(m_context, glu::getDataTypeName(dataType), "", function, dataType));
1850*35238bceSAndroid Build Coastguard Worker             }
1851*35238bceSAndroid Build Coastguard Worker         }
1852*35238bceSAndroid Build Coastguard Worker 
1853*35238bceSAndroid Build Coastguard Worker         // Cases based on LinearDerivateCase
1854*35238bceSAndroid Build Coastguard Worker         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_linearDerivateCases); caseNdx++)
1855*35238bceSAndroid Build Coastguard Worker         {
1856*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *const linearCaseGroup = new tcu::TestCaseGroup(
1857*35238bceSAndroid Build Coastguard Worker                 m_testCtx, s_linearDerivateCases[caseNdx].name, s_linearDerivateCases[caseNdx].description);
1858*35238bceSAndroid Build Coastguard Worker             const char *source = s_linearDerivateCases[caseNdx].source;
1859*35238bceSAndroid Build Coastguard Worker             functionGroup->addChild(linearCaseGroup);
1860*35238bceSAndroid Build Coastguard Worker 
1861*35238bceSAndroid Build Coastguard Worker             for (int vecSize = 1; vecSize <= 4; vecSize++)
1862*35238bceSAndroid Build Coastguard Worker             {
1863*35238bceSAndroid Build Coastguard Worker                 for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1864*35238bceSAndroid Build Coastguard Worker                 {
1865*35238bceSAndroid Build Coastguard Worker                     const glu::DataType dataType   = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1866*35238bceSAndroid Build Coastguard Worker                     const glu::Precision precision = glu::Precision(precNdx);
1867*35238bceSAndroid Build Coastguard Worker                     const SurfaceType surfaceType  = SURFACETYPE_DEFAULT_FRAMEBUFFER;
1868*35238bceSAndroid Build Coastguard Worker                     const int numSamples           = 0;
1869*35238bceSAndroid Build Coastguard Worker                     const uint32_t hint            = GL_DONT_CARE;
1870*35238bceSAndroid Build Coastguard Worker                     ostringstream caseName;
1871*35238bceSAndroid Build Coastguard Worker 
1872*35238bceSAndroid Build Coastguard Worker                     if (caseNdx != 0 && precision == glu::PRECISION_LOWP)
1873*35238bceSAndroid Build Coastguard Worker                         continue; // Skip as lowp doesn't actually produce any bits when rendered to default FB.
1874*35238bceSAndroid Build Coastguard Worker 
1875*35238bceSAndroid Build Coastguard Worker                     caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
1876*35238bceSAndroid Build Coastguard Worker 
1877*35238bceSAndroid Build Coastguard Worker                     linearCaseGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function,
1878*35238bceSAndroid Build Coastguard Worker                                                                      dataType, precision, hint, surfaceType, numSamples,
1879*35238bceSAndroid Build Coastguard Worker                                                                      source));
1880*35238bceSAndroid Build Coastguard Worker                 }
1881*35238bceSAndroid Build Coastguard Worker             }
1882*35238bceSAndroid Build Coastguard Worker         }
1883*35238bceSAndroid Build Coastguard Worker 
1884*35238bceSAndroid Build Coastguard Worker         // Fbo cases
1885*35238bceSAndroid Build Coastguard Worker         for (int caseNdx = 0; caseNdx < DE_LENGTH_OF_ARRAY(s_fboConfigs); caseNdx++)
1886*35238bceSAndroid Build Coastguard Worker         {
1887*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *const fboGroup =
1888*35238bceSAndroid Build Coastguard Worker                 new tcu::TestCaseGroup(m_testCtx, s_fboConfigs[caseNdx].name, "Derivate usage when rendering into FBO");
1889*35238bceSAndroid Build Coastguard Worker             const char *source            = s_linearDerivateCases[0].source; // use source from .linear group
1890*35238bceSAndroid Build Coastguard Worker             const SurfaceType surfaceType = s_fboConfigs[caseNdx].surfaceType;
1891*35238bceSAndroid Build Coastguard Worker             const int numSamples          = s_fboConfigs[caseNdx].numSamples;
1892*35238bceSAndroid Build Coastguard Worker             functionGroup->addChild(fboGroup);
1893*35238bceSAndroid Build Coastguard Worker 
1894*35238bceSAndroid Build Coastguard Worker             for (int vecSize = 1; vecSize <= 4; vecSize++)
1895*35238bceSAndroid Build Coastguard Worker             {
1896*35238bceSAndroid Build Coastguard Worker                 for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1897*35238bceSAndroid Build Coastguard Worker                 {
1898*35238bceSAndroid Build Coastguard Worker                     const glu::DataType dataType   = vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1899*35238bceSAndroid Build Coastguard Worker                     const glu::Precision precision = glu::Precision(precNdx);
1900*35238bceSAndroid Build Coastguard Worker                     const uint32_t hint            = GL_DONT_CARE;
1901*35238bceSAndroid Build Coastguard Worker                     ostringstream caseName;
1902*35238bceSAndroid Build Coastguard Worker 
1903*35238bceSAndroid Build Coastguard Worker                     if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
1904*35238bceSAndroid Build Coastguard Worker                         continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
1905*35238bceSAndroid Build Coastguard Worker 
1906*35238bceSAndroid Build Coastguard Worker                     caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
1907*35238bceSAndroid Build Coastguard Worker 
1908*35238bceSAndroid Build Coastguard Worker                     fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function, dataType,
1909*35238bceSAndroid Build Coastguard Worker                                                               precision, hint, surfaceType, numSamples, source));
1910*35238bceSAndroid Build Coastguard Worker                 }
1911*35238bceSAndroid Build Coastguard Worker             }
1912*35238bceSAndroid Build Coastguard Worker         }
1913*35238bceSAndroid Build Coastguard Worker 
1914*35238bceSAndroid Build Coastguard Worker         // .fastest, .nicest
1915*35238bceSAndroid Build Coastguard Worker         for (int hintCaseNdx = 0; hintCaseNdx < DE_LENGTH_OF_ARRAY(s_hints); hintCaseNdx++)
1916*35238bceSAndroid Build Coastguard Worker         {
1917*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *const hintGroup =
1918*35238bceSAndroid Build Coastguard Worker                 new tcu::TestCaseGroup(m_testCtx, s_hints[hintCaseNdx].name, "Shader derivate hints");
1919*35238bceSAndroid Build Coastguard Worker             const char *source  = s_linearDerivateCases[0].source; // use source from .linear group
1920*35238bceSAndroid Build Coastguard Worker             const uint32_t hint = s_hints[hintCaseNdx].hint;
1921*35238bceSAndroid Build Coastguard Worker             functionGroup->addChild(hintGroup);
1922*35238bceSAndroid Build Coastguard Worker 
1923*35238bceSAndroid Build Coastguard Worker             for (int fboCaseNdx = 0; fboCaseNdx < DE_LENGTH_OF_ARRAY(s_hintFboConfigs); fboCaseNdx++)
1924*35238bceSAndroid Build Coastguard Worker             {
1925*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *const fboGroup =
1926*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, s_hintFboConfigs[fboCaseNdx].name, "");
1927*35238bceSAndroid Build Coastguard Worker                 const SurfaceType surfaceType = s_hintFboConfigs[fboCaseNdx].surfaceType;
1928*35238bceSAndroid Build Coastguard Worker                 const int numSamples          = s_hintFboConfigs[fboCaseNdx].numSamples;
1929*35238bceSAndroid Build Coastguard Worker                 hintGroup->addChild(fboGroup);
1930*35238bceSAndroid Build Coastguard Worker 
1931*35238bceSAndroid Build Coastguard Worker                 for (int vecSize = 1; vecSize <= 4; vecSize++)
1932*35238bceSAndroid Build Coastguard Worker                 {
1933*35238bceSAndroid Build Coastguard Worker                     for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1934*35238bceSAndroid Build Coastguard Worker                     {
1935*35238bceSAndroid Build Coastguard Worker                         const glu::DataType dataType =
1936*35238bceSAndroid Build Coastguard Worker                             vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1937*35238bceSAndroid Build Coastguard Worker                         const glu::Precision precision = glu::Precision(precNdx);
1938*35238bceSAndroid Build Coastguard Worker                         ostringstream caseName;
1939*35238bceSAndroid Build Coastguard Worker 
1940*35238bceSAndroid Build Coastguard Worker                         if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
1941*35238bceSAndroid Build Coastguard Worker                             continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
1942*35238bceSAndroid Build Coastguard Worker 
1943*35238bceSAndroid Build Coastguard Worker                         caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
1944*35238bceSAndroid Build Coastguard Worker 
1945*35238bceSAndroid Build Coastguard Worker                         fboGroup->addChild(new LinearDerivateCase(m_context, caseName.str().c_str(), "", function,
1946*35238bceSAndroid Build Coastguard Worker                                                                   dataType, precision, hint, surfaceType, numSamples,
1947*35238bceSAndroid Build Coastguard Worker                                                                   source));
1948*35238bceSAndroid Build Coastguard Worker                     }
1949*35238bceSAndroid Build Coastguard Worker                 }
1950*35238bceSAndroid Build Coastguard Worker             }
1951*35238bceSAndroid Build Coastguard Worker         }
1952*35238bceSAndroid Build Coastguard Worker 
1953*35238bceSAndroid Build Coastguard Worker         // .texture
1954*35238bceSAndroid Build Coastguard Worker         {
1955*35238bceSAndroid Build Coastguard Worker             tcu::TestCaseGroup *const textureGroup =
1956*35238bceSAndroid Build Coastguard Worker                 new tcu::TestCaseGroup(m_testCtx, "texture", "Derivate of texture lookup result");
1957*35238bceSAndroid Build Coastguard Worker             functionGroup->addChild(textureGroup);
1958*35238bceSAndroid Build Coastguard Worker 
1959*35238bceSAndroid Build Coastguard Worker             for (int texCaseNdx = 0; texCaseNdx < DE_LENGTH_OF_ARRAY(s_textureConfigs); texCaseNdx++)
1960*35238bceSAndroid Build Coastguard Worker             {
1961*35238bceSAndroid Build Coastguard Worker                 tcu::TestCaseGroup *const caseGroup =
1962*35238bceSAndroid Build Coastguard Worker                     new tcu::TestCaseGroup(m_testCtx, s_textureConfigs[texCaseNdx].name, "");
1963*35238bceSAndroid Build Coastguard Worker                 const SurfaceType surfaceType = s_textureConfigs[texCaseNdx].surfaceType;
1964*35238bceSAndroid Build Coastguard Worker                 const int numSamples          = s_textureConfigs[texCaseNdx].numSamples;
1965*35238bceSAndroid Build Coastguard Worker                 const uint32_t hint           = s_textureConfigs[texCaseNdx].hint;
1966*35238bceSAndroid Build Coastguard Worker                 textureGroup->addChild(caseGroup);
1967*35238bceSAndroid Build Coastguard Worker 
1968*35238bceSAndroid Build Coastguard Worker                 for (int vecSize = 1; vecSize <= 4; vecSize++)
1969*35238bceSAndroid Build Coastguard Worker                 {
1970*35238bceSAndroid Build Coastguard Worker                     for (int precNdx = 0; precNdx < glu::PRECISION_LAST; precNdx++)
1971*35238bceSAndroid Build Coastguard Worker                     {
1972*35238bceSAndroid Build Coastguard Worker                         const glu::DataType dataType =
1973*35238bceSAndroid Build Coastguard Worker                             vecSize > 1 ? glu::getDataTypeFloatVec(vecSize) : glu::TYPE_FLOAT;
1974*35238bceSAndroid Build Coastguard Worker                         const glu::Precision precision = glu::Precision(precNdx);
1975*35238bceSAndroid Build Coastguard Worker                         ostringstream caseName;
1976*35238bceSAndroid Build Coastguard Worker 
1977*35238bceSAndroid Build Coastguard Worker                         if (surfaceType != SURFACETYPE_FLOAT_FBO && precision == glu::PRECISION_LOWP)
1978*35238bceSAndroid Build Coastguard Worker                             continue; // Skip as lowp doesn't actually produce any bits when rendered to U8 RT.
1979*35238bceSAndroid Build Coastguard Worker 
1980*35238bceSAndroid Build Coastguard Worker                         caseName << glu::getDataTypeName(dataType) << "_" << glu::getPrecisionName(precision);
1981*35238bceSAndroid Build Coastguard Worker 
1982*35238bceSAndroid Build Coastguard Worker                         caseGroup->addChild(new TextureDerivateCase(m_context, caseName.str().c_str(), "", function,
1983*35238bceSAndroid Build Coastguard Worker                                                                     dataType, precision, hint, surfaceType,
1984*35238bceSAndroid Build Coastguard Worker                                                                     numSamples));
1985*35238bceSAndroid Build Coastguard Worker                     }
1986*35238bceSAndroid Build Coastguard Worker                 }
1987*35238bceSAndroid Build Coastguard Worker             }
1988*35238bceSAndroid Build Coastguard Worker         }
1989*35238bceSAndroid Build Coastguard Worker     }
1990*35238bceSAndroid Build Coastguard Worker }
1991*35238bceSAndroid Build Coastguard Worker 
1992*35238bceSAndroid Build Coastguard Worker } // namespace Functional
1993*35238bceSAndroid Build Coastguard Worker } // namespace gles3
1994*35238bceSAndroid Build Coastguard Worker } // namespace deqp
1995