x11: Call XInitThreads() am: 5d11c9d2c0 am: f465d82fa5 am: 0ed6cc912e am: e7ee6541a9...
[platform/upstream/VK-GL-CTS.git] / modules / gles3 / functional / es3fShaderPrecisionTests.cpp
1 /*-------------------------------------------------------------------------
2  * drawElements Quality Program OpenGL ES 3.0 Module
3  * -------------------------------------------------
4  *
5  * Copyright 2014 The Android Open Source Project
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief Shader precision tests.
22  *
23  * \note Floating-point case uses R32UI render target and uses
24  *               floatBitsToUint() in shader to write out floating-point value bits.
25  *               This is done since ES3 core doesn't support FP render targets.
26  *//*--------------------------------------------------------------------*/
27
28 #include "es3fShaderPrecisionTests.hpp"
29 #include "tcuVector.hpp"
30 #include "tcuTestLog.hpp"
31 #include "tcuVectorUtil.hpp"
32 #include "tcuFloat.hpp"
33 #include "tcuFormatUtil.hpp"
34 #include "gluRenderContext.hpp"
35 #include "gluShaderProgram.hpp"
36 #include "gluShaderUtil.hpp"
37 #include "gluDrawUtil.hpp"
38 #include "deRandom.hpp"
39 #include "deString.h"
40
41 #include "glwEnums.hpp"
42 #include "glwFunctions.hpp"
43
44 #include <algorithm>
45
46 namespace deqp
47 {
48 namespace gles3
49 {
50 namespace Functional
51 {
52
53 using std::string;
54 using std::vector;
55 using std::ostringstream;
56 using tcu::TestLog;
57
58 enum
59 {
60         FRAMEBUFFER_WIDTH       = 32,
61         FRAMEBUFFER_HEIGHT      = 32
62 };
63
64 static glu::ShaderProgram* createFloatPrecisionEvalProgram (const glu::RenderContext& context, glu::Precision precision, const char* evalOp, bool isVertexCase)
65 {
66         glu::DataType   type            = glu::TYPE_FLOAT;
67         glu::DataType   outType         = glu::TYPE_UINT;
68         const char*             typeName        = glu::getDataTypeName(type);
69         const char*             outTypeName     = glu::getDataTypeName(outType);
70         const char*             precName        = glu::getPrecisionName(precision);
71         ostringstream   vtx;
72         ostringstream   frag;
73         ostringstream&  op                      = isVertexCase ? vtx : frag;
74
75         vtx << "#version 300 es\n"
76                 << "in highp vec4 a_position;\n"
77                 << "in " << precName << " " << typeName << " a_in0;\n"
78                 << "in " << precName << " " << typeName << " a_in1;\n";
79         frag << "#version 300 es\n"
80                  << "layout(location = 0) out highp " << outTypeName << " o_out;\n";
81
82         if (isVertexCase)
83         {
84                 vtx << "flat out " << precName << " " << typeName << " v_out;\n";
85                 frag << "flat in " << precName << " " << typeName << " v_out;\n";
86         }
87         else
88         {
89                 vtx << "flat out " << precName << " " << typeName << " v_in0;\n"
90                         << "flat out " << precName << " " << typeName << " v_in1;\n";
91                 frag << "flat in " << precName << " " << typeName << " v_in0;\n"
92                          << "flat in " << precName << " " << typeName << " v_in1;\n";
93         }
94
95         vtx << "\nvoid main (void)\n{\n"
96                 << "    gl_Position = a_position;\n";
97         frag << "\nvoid main (void)\n{\n";
98
99         op << "\t" << precName << " " << typeName << " in0 = " << (isVertexCase ? "a_" : "v_") << "in0;\n"
100            << "\t" << precName << " " << typeName << " in1 = " << (isVertexCase ? "a_" : "v_") << "in1;\n";
101
102         if (!isVertexCase)
103                 op << "\t" << precName << " " << typeName << " res;\n";
104
105         op << "\t" << (isVertexCase ? "v_out" : "res") << " = " << evalOp << ";\n";
106
107         if (isVertexCase)
108         {
109                 frag << "       o_out = floatBitsToUint(v_out);\n";
110         }
111         else
112         {
113                 vtx << "        v_in0 = a_in0;\n"
114                         << "    v_in1 = a_in1;\n";
115                 frag << "       o_out = floatBitsToUint(res);\n";
116         }
117
118         vtx << "}\n";
119         frag << "}\n";
120
121         return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str()));
122 }
123
124 static glu::ShaderProgram* createIntUintPrecisionEvalProgram (const glu::RenderContext& context, glu::DataType type, glu::Precision precision, const char* evalOp, bool isVertexCase)
125 {
126         const char*             typeName        = glu::getDataTypeName(type);
127         const char*             precName        = glu::getPrecisionName(precision);
128         ostringstream   vtx;
129         ostringstream   frag;
130         ostringstream&  op                      = isVertexCase ? vtx : frag;
131
132         vtx << "#version 300 es\n"
133                 << "in highp vec4 a_position;\n"
134                 << "in " << precName << " " << typeName << " a_in0;\n"
135                 << "in " << precName << " " << typeName << " a_in1;\n";
136         frag << "#version 300 es\n"
137                  << "layout(location = 0) out " << precName << " " << typeName << " o_out;\n";
138
139         if (isVertexCase)
140         {
141                 vtx << "flat out " << precName << " " << typeName << " v_out;\n";
142                 frag << "flat in " << precName << " " << typeName << " v_out;\n";
143         }
144         else
145         {
146                 vtx << "flat out " << precName << " " << typeName << " v_in0;\n"
147                         << "flat out " << precName << " " << typeName << " v_in1;\n";
148                 frag << "flat in " << precName << " " << typeName << " v_in0;\n"
149                          << "flat in " << precName << " " << typeName << " v_in1;\n";
150         }
151
152         vtx << "\nvoid main (void)\n{\n"
153                 << "    gl_Position = a_position;\n";
154         frag << "\nvoid main (void)\n{\n";
155
156         op << "\t" << precName << " " << typeName << " in0 = " << (isVertexCase ? "a_" : "v_") << "in0;\n"
157            << "\t" << precName << " " << typeName << " in1 = " << (isVertexCase ? "a_" : "v_") << "in1;\n";
158
159         op << "\t" << (isVertexCase ? "v_" : "o_") << "out = " << evalOp << ";\n";
160
161         if (isVertexCase)
162         {
163                 frag << "       o_out = v_out;\n";
164         }
165         else
166         {
167                 vtx << "        v_in0 = a_in0;\n"
168                         << "    v_in1 = a_in1;\n";
169         }
170
171         vtx << "}\n";
172         frag << "}\n";
173
174         return new glu::ShaderProgram(context, glu::makeVtxFragSources(vtx.str(), frag.str()));
175 }
176
177 class ShaderFloatPrecisionCase : public TestCase
178 {
179 public:
180         typedef double (*EvalFunc) (double in0, double in1);
181
182                                                                 ShaderFloatPrecisionCase        (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, const tcu::Vec2& rangeA, const tcu::Vec2& rangeB, bool isVertexCase);
183                                                                 ~ShaderFloatPrecisionCase       (void);
184
185         void                                            init                                            (void);
186         void                                            deinit                                          (void);
187         IterateResult                           iterate                                         (void);
188
189 protected:
190         bool                                            compare                                         (float in0, float in1, double reference, float result);
191
192 private:
193                                                                 ShaderFloatPrecisionCase        (const ShaderFloatPrecisionCase& other);
194         ShaderFloatPrecisionCase&       operator=                                       (const ShaderFloatPrecisionCase& other);
195
196         // Case parameters.
197         std::string                                     m_op;
198         EvalFunc                                        m_evalFunc;
199         glu::Precision                          m_precision;
200         tcu::Vec2                                       m_rangeA;
201         tcu::Vec2                                       m_rangeB;
202         bool                                            m_isVertexCase;
203
204         int                                                     m_numTestsPerIter;
205         int                                                     m_numIters;
206         de::Random                                      m_rnd;
207
208         // Iteration state.
209         glu::ShaderProgram*                     m_program;
210         deUint32                                        m_framebuffer;
211         deUint32                                        m_renderbuffer;
212         int                                                     m_iterNdx;
213 };
214
215 ShaderFloatPrecisionCase::ShaderFloatPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, const tcu::Vec2& rangeA, const tcu::Vec2& rangeB, bool isVertexCase)
216         : TestCase                      (context, name, desc)
217         , m_op                          (op)
218         , m_evalFunc            (evalFunc)
219         , m_precision           (precision)
220         , m_rangeA                      (rangeA)
221         , m_rangeB                      (rangeB)
222         , m_isVertexCase        (isVertexCase)
223         , m_numTestsPerIter     (32)
224         , m_numIters            (4)
225         , m_rnd                         (deStringHash(name))
226         , m_program                     (DE_NULL)
227         , m_framebuffer         (0)
228         , m_renderbuffer        (0)
229         , m_iterNdx                     (0)
230 {
231 }
232
233 ShaderFloatPrecisionCase::~ShaderFloatPrecisionCase (void)
234 {
235         ShaderFloatPrecisionCase::deinit();
236 }
237
238 void ShaderFloatPrecisionCase::init (void)
239 {
240         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
241         TestLog&                                log     = m_testCtx.getLog();
242
243         DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
244
245         // Create program.
246         m_program = createFloatPrecisionEvalProgram(m_context.getRenderContext(), m_precision, m_op.c_str(), m_isVertexCase);
247         log << *m_program;
248
249         TCU_CHECK(m_program->isOk());
250
251         // Create framebuffer.
252         gl.genFramebuffers(1, &m_framebuffer);
253         gl.genRenderbuffers(1, &m_renderbuffer);
254
255         gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
256         gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
257
258         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
259         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
260
261         GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
262         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
263
264         gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
265
266         // Initialize test result to pass.
267         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
268         m_iterNdx = 0;
269 }
270
271 void ShaderFloatPrecisionCase::deinit (void)
272 {
273         delete m_program;
274
275         if (m_framebuffer)
276                 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
277
278         if (m_renderbuffer)
279                 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
280
281         m_program               = DE_NULL;
282         m_framebuffer   = 0;
283         m_renderbuffer  = 0;
284 }
285
286 bool ShaderFloatPrecisionCase::compare (float in0, float in1, double reference, float result)
287 {
288         // Comparison is done using 64-bit reference value to accurately evaluate rounding mode error.
289         // If 32-bit reference value is used, 2 bits of rounding error must be allowed.
290
291         // For mediump and lowp types the comparison currently allows 3 bits of rounding error:
292         // two bits from conversions and one from actual operation.
293
294         // \todo [2013-09-30 pyry] Make this more strict: determine if rounding can actually happen.
295
296         const int               mantissaBits            = m_precision == glu::PRECISION_HIGHP ? 23 : 10;
297         const int               numPrecBits                     = 52 - mantissaBits;
298
299         const int               in0Exp                          = tcu::Float32(in0).exponent();
300         const int               in1Exp                          = tcu::Float32(in1).exponent();
301         const int               resExp                          = tcu::Float32(result).exponent();
302         const int               numLostBits                     = de::max(de::max(in0Exp-resExp, in1Exp-resExp), 0); // Lost due to mantissa shift.
303
304         const int               roundingUlpError        = m_precision == glu::PRECISION_HIGHP ? 1 : 3;
305         const int               maskBits                        = numLostBits + numPrecBits;
306
307         m_testCtx.getLog() << TestLog::Message << "Assuming " << mantissaBits << " mantissa bits, " << numLostBits << " bits lost in operation, and " << roundingUlpError << " ULP rounding error."
308                                            << TestLog::EndMessage;
309
310         {
311                 const deUint64  refBits                         = tcu::Float64(reference).bits();
312                 const deUint64  resBits                         = tcu::Float64(result).bits();
313                 const deUint64  accurateRefBits         = maskBits < 64 ? refBits >> (deUint64)maskBits : 0u;
314                 const deUint64  accurateResBits         = maskBits < 64 ? resBits >> (deUint64)maskBits : 0u;
315                 const deUint64  ulpDiff                         = (deUint64)de::abs((deInt64)accurateRefBits - (deInt64)accurateResBits);
316
317                 if (ulpDiff > (deUint64)roundingUlpError)
318                 {
319                         m_testCtx.getLog() << TestLog::Message << "ERROR: comparison failed! ULP diff (ignoring lost/undefined bits) = " << ulpDiff << TestLog::EndMessage;
320                         return false;
321                 }
322                 else
323                         return true;
324         }
325 }
326
327 ShaderFloatPrecisionCase::IterateResult ShaderFloatPrecisionCase::iterate (void)
328 {
329         // Constant data.
330         const float position[] =
331         {
332                 -1.0f, -1.0f, 0.0f, 1.0f,
333                 -1.0f,  1.0f, 0.0f, 1.0f,
334                  1.0f, -1.0f, 0.0f, 1.0f,
335                  1.0f,  1.0f, 0.0f, 1.0f
336         };
337         const deUint16                                  indices[]       = { 0, 1, 2, 2, 1, 3 };
338
339         const int                                               numVertices     = 4;
340         float                                                   in0Arr[4]       = { 0.0f };
341         float                                                   in1Arr[4]       = { 0.0f };
342
343         TestLog&                                                log                     = m_testCtx.getLog();
344         const glw::Functions&                   gl                      = m_context.getRenderContext().getFunctions();
345         vector<glu::VertexArrayBinding> vertexArrays;
346
347         // Image read from GL.
348         std::vector<float>      pixels          (FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
349
350         // \todo [2012-05-03 pyry] Could be cached.
351         deUint32                        prog            = m_program->getProgram();
352
353         gl.useProgram(prog);
354         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
355
356         vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
357         vertexArrays.push_back(glu::va::Float("a_in0", 1, numVertices, 0, &in0Arr[0]));
358         vertexArrays.push_back(glu::va::Float("a_in1", 1, numVertices, 0, &in1Arr[0]));
359
360         GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
361
362         // Compute values and reference.
363         for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
364         {
365                 const float             in0             = m_rnd.getFloat(m_rangeA.x(), m_rangeA.y());
366                 const float             in1             = m_rnd.getFloat(m_rangeB.x(), m_rangeB.y());
367                 const double    refD    = m_evalFunc((double)in0, (double)in1);
368                 const float             refF    = tcu::Float64(refD).asFloat(); // Uses RTE rounding mode.
369
370                 log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
371                                                                 << "in0 = " << in0 << " / " << tcu::toHex(tcu::Float32(in0).bits())
372                                                                 << ", in1 = " << in1 << " / " << tcu::toHex(tcu::Float32(in1).bits())
373                         << TestLog::EndMessage
374                         << TestLog::Message << "  reference = " << refF << " / " << tcu::toHex(tcu::Float32(refF).bits()) << TestLog::EndMessage;
375
376                 std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
377                 std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
378
379                 glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
380                                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
381                 gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
382                 GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
383
384                 log << TestLog::Message << "  result = " << pixels[0] << " / " << tcu::toHex(tcu::Float32(pixels[0]).bits()) << TestLog::EndMessage;
385
386                 // Verify results
387                 {
388                         const bool firstPixelOk = compare(in0, in1, refD, pixels[0]);
389
390                         if (firstPixelOk)
391                         {
392                                 // Check that rest of pixels match to first one.
393                                 const deUint32  firstPixelBits  = tcu::Float32(pixels[0]).bits();
394                                 bool                    allPixelsOk             = true;
395
396                                 for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
397                                 {
398                                         for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
399                                         {
400                                                 const deUint32 pixelBits = tcu::Float32(pixels[(y*FRAMEBUFFER_WIDTH + x)*4]).bits();
401
402                                                 if (pixelBits != firstPixelBits)
403                                                 {
404                                                         log << TestLog::Message << "ERROR: Inconsistent results, got " << tcu::toHex(pixelBits) << " at (" << x << ", " << y << ")" << TestLog::EndMessage;
405                                                         allPixelsOk = false;
406                                                 }
407                                         }
408
409                                         if (!allPixelsOk)
410                                                 break;
411                                 }
412
413                                 if (!allPixelsOk)
414                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Inconsistent values in framebuffer");
415                         }
416                         else
417                                 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Result comparison failed");
418                 }
419
420                 if (m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
421                         break;
422         }
423
424         gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
425         GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
426
427         m_iterNdx += 1;
428         return (m_iterNdx < m_numIters && m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) ? CONTINUE : STOP;
429 }
430
431 class ShaderIntPrecisionCase : public TestCase
432 {
433 public:
434         typedef int                                     (*EvalFunc)                                     (int a, int b);
435
436                                                                 ShaderIntPrecisionCase          (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::IVec2& rangeA, const tcu::IVec2& rangeB, bool isVertexCase);
437                                                                 ~ShaderIntPrecisionCase         (void);
438
439         void                                            init                                            (void);
440         void                                            deinit                                          (void);
441         IterateResult                           iterate                                         (void);
442
443 private:
444                                                                 ShaderIntPrecisionCase          (const ShaderIntPrecisionCase& other);
445         ShaderIntPrecisionCase&         operator=                                       (const ShaderIntPrecisionCase& other);
446
447         // Case parameters.
448         std::string                                     m_op;
449         EvalFunc                                        m_evalFunc;
450         glu::Precision                          m_precision;
451         int                                                     m_bits;
452         tcu::IVec2                                      m_rangeA;
453         tcu::IVec2                                      m_rangeB;
454         bool                                            m_isVertexCase;
455
456         int                                                     m_numTestsPerIter;
457         int                                                     m_numIters;
458         de::Random                                      m_rnd;
459
460         // Iteration state.
461         glu::ShaderProgram*                     m_program;
462         deUint32                                        m_framebuffer;
463         deUint32                                        m_renderbuffer;
464         int                                                     m_iterNdx;
465 };
466
467 ShaderIntPrecisionCase::ShaderIntPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::IVec2& rangeA, const tcu::IVec2& rangeB, bool isVertexCase)
468         : TestCase                      (context, name, desc)
469         , m_op                          (op)
470         , m_evalFunc            (evalFunc)
471         , m_precision           (precision)
472         , m_bits                        (bits)
473         , m_rangeA                      (rangeA)
474         , m_rangeB                      (rangeB)
475         , m_isVertexCase        (isVertexCase)
476         , m_numTestsPerIter     (32)
477         , m_numIters            (4)
478         , m_rnd                         (deStringHash(name))
479         , m_program                     (DE_NULL)
480         , m_framebuffer         (0)
481         , m_renderbuffer        (0)
482         , m_iterNdx                     (0)
483 {
484 }
485
486 ShaderIntPrecisionCase::~ShaderIntPrecisionCase (void)
487 {
488         ShaderIntPrecisionCase::deinit();
489 }
490
491 void ShaderIntPrecisionCase::init (void)
492 {
493         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
494         TestLog&                                log     = m_testCtx.getLog();
495
496         DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
497
498         // Create program.
499         m_program = createIntUintPrecisionEvalProgram(m_context.getRenderContext(), glu::TYPE_INT, m_precision, m_op.c_str(), m_isVertexCase);
500         log << *m_program;
501
502         TCU_CHECK(m_program->isOk());
503
504         // Create framebuffer.
505         gl.genFramebuffers(1, &m_framebuffer);
506         gl.genRenderbuffers(1, &m_renderbuffer);
507
508         gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
509         gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32I, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
510
511         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
512         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
513
514         GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
515         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
516
517         gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
518
519         // Initialize test result to pass.
520         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
521         m_iterNdx = 0;
522
523         log << TestLog::Message << "Number of accurate bits assumed = " << m_bits << TestLog::EndMessage;
524 }
525
526 void ShaderIntPrecisionCase::deinit (void)
527 {
528         delete m_program;
529
530         if (m_framebuffer)
531                 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
532
533         if (m_renderbuffer)
534                 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
535
536         m_program               = DE_NULL;
537         m_framebuffer   = 0;
538         m_renderbuffer  = 0;
539 }
540
541 ShaderIntPrecisionCase::IterateResult ShaderIntPrecisionCase::iterate (void)
542 {
543         // Constant data.
544         const float position[] =
545         {
546                 -1.0f, -1.0f, 0.0f, 1.0f,
547                 -1.0f,  1.0f, 0.0f, 1.0f,
548                  1.0f, -1.0f, 0.0f, 1.0f,
549                  1.0f,  1.0f, 0.0f, 1.0f
550         };
551         const deUint16                                  indices[]       = { 0, 1, 2, 2, 1, 3 };
552
553         const int                                               numVertices     = 4;
554         int                                                             in0Arr[4]       = { 0 };
555         int                                                             in1Arr[4]       = { 0 };
556
557         TestLog&                                                log                     = m_testCtx.getLog();
558         const glw::Functions&                   gl                      = m_context.getRenderContext().getFunctions();
559         deUint32                                                mask            = m_bits == 32 ? 0xffffffffu : ((1u<<m_bits)-1);
560         vector<int>                                             pixels          (FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
561         vector<glu::VertexArrayBinding> vertexArrays;
562
563         deUint32                                                prog            = m_program->getProgram();
564
565         // \todo [2012-05-03 pyry] A bit hacky. getInt() should work fine with ranges like this.
566         bool                                                    isMaxRangeA     = m_rangeA.x() == (int)0x80000000 && m_rangeA.y() == (int)0x7fffffff;
567         bool                                                    isMaxRangeB     = m_rangeB.x() == (int)0x80000000 && m_rangeB.y() == (int)0x7fffffff;
568
569         gl.useProgram(prog);
570         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
571
572         vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
573         vertexArrays.push_back(glu::va::Int32("a_in0", 1, numVertices, 0, &in0Arr[0]));
574         vertexArrays.push_back(glu::va::Int32("a_in1", 1, numVertices, 0, &in1Arr[0]));
575
576         GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
577
578         // Compute values and reference.
579         for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
580         {
581                 int             in0                     = deSignExtendTo32(((isMaxRangeA ? (int)m_rnd.getUint32() : m_rnd.getInt(m_rangeA.x(), m_rangeA.y())) & mask), m_bits);
582                 int             in1                     = deSignExtendTo32(((isMaxRangeB ? (int)m_rnd.getUint32() : m_rnd.getInt(m_rangeB.x(), m_rangeB.y())) & mask), m_bits);
583                 int             refMasked       = m_evalFunc(in0, in1) & mask;
584                 int             refOut          = deSignExtendTo32(refMasked, m_bits);
585
586                 log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
587                                                                 << "in0 = " << in0 << ", in1 = " << in1 << ", ref out = " << refOut << " / " << tcu::toHex(refMasked)
588                         << TestLog::EndMessage;
589
590                 std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
591                 std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
592
593                 glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
594                                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
595                 gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_INT, &pixels[0]);
596                 GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
597
598                 // Compare pixels.
599                 for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
600                 {
601                         for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
602                         {
603                                 int                     cmpOut          = pixels[(y*FRAMEBUFFER_WIDTH + x)*4];
604                                 int                     cmpMasked       = cmpOut & mask;
605
606                                 if (cmpMasked != refMasked)
607                                 {
608                                         log << TestLog::Message << "Comparison failed (at " << x << ", " << y << "): "
609                                                                                         << "got " << cmpOut << " / " << tcu::toHex(cmpOut)
610                                                 << TestLog::EndMessage;
611                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
612                                         return STOP;
613                                 }
614                         }
615                 }
616         }
617
618         gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
619         GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
620
621         m_iterNdx += 1;
622         return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
623 }
624
625 class ShaderUintPrecisionCase : public TestCase
626 {
627 public:
628         typedef deUint32                        (*EvalFunc)                                     (deUint32 a, deUint32 b);
629
630                                                                 ShaderUintPrecisionCase         (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::UVec2& rangeA, const tcu::UVec2& rangeB, bool isVertexCase);
631                                                                 ~ShaderUintPrecisionCase        (void);
632
633         void                                            init                                            (void);
634         void                                            deinit                                          (void);
635         IterateResult                           iterate                                         (void);
636
637 private:
638                                                                 ShaderUintPrecisionCase         (const ShaderUintPrecisionCase& other);
639         ShaderUintPrecisionCase&        operator=                                       (const ShaderUintPrecisionCase& other);
640
641         // Case parameters.
642         std::string                                     m_op;
643         EvalFunc                                        m_evalFunc;
644         glu::Precision                          m_precision;
645         int                                                     m_bits;
646         tcu::UVec2                                      m_rangeA;
647         tcu::UVec2                                      m_rangeB;
648         bool                                            m_isVertexCase;
649
650         int                                                     m_numTestsPerIter;
651         int                                                     m_numIters;
652         de::Random                                      m_rnd;
653
654         // Iteration state.
655         glu::ShaderProgram*                     m_program;
656         deUint32                                        m_framebuffer;
657         deUint32                                        m_renderbuffer;
658         int                                                     m_iterNdx;
659 };
660
661 ShaderUintPrecisionCase::ShaderUintPrecisionCase (Context& context, const char* name, const char* desc, const char* op, EvalFunc evalFunc, glu::Precision precision, int bits, const tcu::UVec2& rangeA, const tcu::UVec2& rangeB, bool isVertexCase)
662         : TestCase                      (context, name, desc)
663         , m_op                          (op)
664         , m_evalFunc            (evalFunc)
665         , m_precision           (precision)
666         , m_bits                        (bits)
667         , m_rangeA                      (rangeA)
668         , m_rangeB                      (rangeB)
669         , m_isVertexCase        (isVertexCase)
670         , m_numTestsPerIter     (32)
671         , m_numIters            (4)
672         , m_rnd                         (deStringHash(name))
673         , m_program                     (DE_NULL)
674         , m_framebuffer         (0)
675         , m_renderbuffer        (0)
676         , m_iterNdx                     (0)
677 {
678 }
679
680 ShaderUintPrecisionCase::~ShaderUintPrecisionCase (void)
681 {
682         ShaderUintPrecisionCase::deinit();
683 }
684
685 void ShaderUintPrecisionCase::init (void)
686 {
687         const glw::Functions&   gl      = m_context.getRenderContext().getFunctions();
688         TestLog&                                log     = m_testCtx.getLog();
689
690         DE_ASSERT(!m_program && !m_framebuffer && !m_renderbuffer);
691
692         // Create program.
693         m_program = createIntUintPrecisionEvalProgram(m_context.getRenderContext(), glu::TYPE_UINT, m_precision, m_op.c_str(), m_isVertexCase);
694         log << *m_program;
695
696         TCU_CHECK(m_program->isOk());
697
698         // Create framebuffer.
699         gl.genFramebuffers(1, &m_framebuffer);
700         gl.genRenderbuffers(1, &m_renderbuffer);
701
702         gl.bindRenderbuffer(GL_RENDERBUFFER, m_renderbuffer);
703         gl.renderbufferStorage(GL_RENDERBUFFER, GL_R32UI, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT);
704
705         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
706         gl.framebufferRenderbuffer(GL_FRAMEBUFFER, GL_COLOR_ATTACHMENT0, GL_RENDERBUFFER, m_renderbuffer);
707
708         GLU_EXPECT_NO_ERROR(gl.getError(), "Post framebuffer setup");
709         TCU_CHECK(gl.checkFramebufferStatus(GL_FRAMEBUFFER) == GL_FRAMEBUFFER_COMPLETE);
710
711         gl.bindFramebuffer(GL_FRAMEBUFFER, m_context.getRenderContext().getDefaultFramebuffer());
712
713         // Initialize test result to pass.
714         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
715         m_iterNdx = 0;
716
717         log << TestLog::Message << "Number of accurate bits assumed = " << m_bits << TestLog::EndMessage;
718 }
719
720 void ShaderUintPrecisionCase::deinit (void)
721 {
722         delete m_program;
723
724         if (m_framebuffer)
725                 m_context.getRenderContext().getFunctions().deleteFramebuffers(1, &m_framebuffer);
726
727         if (m_renderbuffer)
728                 m_context.getRenderContext().getFunctions().deleteRenderbuffers(1, &m_renderbuffer);
729
730         m_program               = DE_NULL;
731         m_framebuffer   = 0;
732         m_renderbuffer  = 0;
733 }
734
735 ShaderUintPrecisionCase::IterateResult ShaderUintPrecisionCase::iterate (void)
736 {
737         // Constant data.
738         const float position[] =
739         {
740                 -1.0f, -1.0f, 0.0f, 1.0f,
741                 -1.0f,  1.0f, 0.0f, 1.0f,
742                  1.0f, -1.0f, 0.0f, 1.0f,
743                  1.0f,  1.0f, 0.0f, 1.0f
744         };
745         const deUint16                                  indices[]       = { 0, 1, 2, 2, 1, 3 };
746
747         const int                                               numVertices     = 4;
748         deUint32                                                in0Arr[4]       = { 0 };
749         deUint32                                                in1Arr[4]       = { 0 };
750
751         TestLog&                                                log                     = m_testCtx.getLog();
752         const glw::Functions&                   gl                      = m_context.getRenderContext().getFunctions();
753         deUint32                                                mask            = m_bits == 32 ? 0xffffffffu : ((1u<<m_bits)-1);
754         vector<deUint32>                                pixels          (FRAMEBUFFER_WIDTH*FRAMEBUFFER_HEIGHT*4);
755         vector<glu::VertexArrayBinding> vertexArrays;
756
757         deUint32                                                prog            = m_program->getProgram();
758
759         // \todo [2012-05-03 pyry] A bit hacky.
760         bool                                                    isMaxRangeA     = m_rangeA.x() == 0 && m_rangeA.y() == 0xffffffff;
761         bool                                                    isMaxRangeB     = m_rangeB.x() == 0 && m_rangeB.y() == 0xffffffff;
762
763         gl.useProgram(prog);
764         gl.bindFramebuffer(GL_FRAMEBUFFER, m_framebuffer);
765
766         vertexArrays.push_back(glu::va::Float("a_position", 4, numVertices, 0, &position[0]));
767         vertexArrays.push_back(glu::va::Uint32("a_in0", 1, numVertices, 0, &in0Arr[0]));
768         vertexArrays.push_back(glu::va::Uint32("a_in1", 1, numVertices, 0, &in1Arr[0]));
769
770         GLU_EXPECT_NO_ERROR(gl.getError(), "After program setup");
771
772         // Compute values and reference.
773         for (int testNdx = 0; testNdx < m_numTestsPerIter; testNdx++)
774         {
775                 deUint32        in0             = (isMaxRangeA ? m_rnd.getUint32() : (m_rangeA.x() + m_rnd.getUint32()%(m_rangeA.y()-m_rangeA.x()+1))) & mask;
776                 deUint32        in1             = (isMaxRangeB ? m_rnd.getUint32() : (m_rangeB.x() + m_rnd.getUint32()%(m_rangeB.y()-m_rangeB.x()+1))) & mask;
777                 deUint32        refOut  = m_evalFunc(in0, in1) & mask;
778
779                 log << TestLog::Message << "iter " << m_iterNdx << ", test " << testNdx << ": "
780                                                                 << "in0 = " << tcu::toHex(in0) << ", in1 = " << tcu::toHex(in1) << ", ref out = " << tcu::toHex(refOut)
781                         << TestLog::EndMessage;
782
783                 std::fill(&in0Arr[0], &in0Arr[0] + DE_LENGTH_OF_ARRAY(in0Arr), in0);
784                 std::fill(&in1Arr[0], &in1Arr[0] + DE_LENGTH_OF_ARRAY(in1Arr), in1);
785
786                 glu::draw(m_context.getRenderContext(), prog, (int)vertexArrays.size(), &vertexArrays[0],
787                                   glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
788                 gl.readPixels(0, 0, FRAMEBUFFER_WIDTH, FRAMEBUFFER_HEIGHT, GL_RGBA_INTEGER, GL_UNSIGNED_INT, &pixels[0]);
789                 GLU_EXPECT_NO_ERROR(gl.getError(), "After render");
790
791                 // Compare pixels.
792                 for (int y = 0; y < FRAMEBUFFER_HEIGHT; y++)
793                 {
794                         for (int x = 0; x < FRAMEBUFFER_WIDTH; x++)
795                         {
796                                 deUint32        cmpOut          = pixels[(y*FRAMEBUFFER_WIDTH + x)*4];
797                                 deUint32        cmpMasked       = cmpOut & mask;
798
799                                 if (cmpMasked != refOut)
800                                 {
801                                         log << TestLog::Message << "Comparison failed (at " << x << ", " << y << "): "
802                                                                                         << "got " << tcu::toHex(cmpOut)
803                                                 << TestLog::EndMessage;
804                                         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Fail");
805                                         return STOP;
806                                 }
807                         }
808                 }
809         }
810
811         gl.bindFramebuffer(GL_FRAMEBUFFER, 0);
812         GLU_EXPECT_NO_ERROR(gl.getError(), "After iteration");
813
814         m_iterNdx += 1;
815         return (m_iterNdx < m_numIters) ? CONTINUE : STOP;
816 }
817
818 ShaderPrecisionTests::ShaderPrecisionTests (Context& context)
819         : TestCaseGroup(context, "precision", "Shader precision requirements validation tests")
820 {
821 }
822
823 ShaderPrecisionTests::~ShaderPrecisionTests (void)
824 {
825 }
826
827 void ShaderPrecisionTests::init (void)
828 {
829         using tcu::add;
830         using tcu::sub;
831         using tcu::mul;
832         using tcu::div;
833         using tcu::Vec2;
834         using tcu::IVec2;
835         using tcu::UVec2;
836
837         // Exp = Emax-2, Mantissa = 0
838         float           minF32                  = tcu::Float32((1u<<31) | (0xfdu<<23) | 0x0u).asFloat();
839         float           maxF32                  = tcu::Float32((0u<<31) | (0xfdu<<23) | 0x0u).asFloat();
840         float           minF16                  = tcu::Float16((deUint16)((1u<<15) | (0x1du<<10) | 0x0u)).asFloat();
841         float           maxF16                  = tcu::Float16((deUint16)((0u<<15) | (0x1du<<10) | 0x0u)).asFloat();
842         tcu::Vec2       fullRange32F    (minF32, maxF32);
843         tcu::Vec2       fullRange16F    (minF16, maxF16);
844         tcu::IVec2      fullRange32I    (0x80000000, 0x7fffffff);
845         tcu::IVec2      fullRange16I    (-(1<<15), (1<<15)-1);
846         tcu::IVec2      fullRange8I             (-(1<<7), (1<<7)-1);
847         tcu::UVec2      fullRange32U    (0u, 0xffffffffu);
848         tcu::UVec2      fullRange16U    (0u, 0xffffu);
849         tcu::UVec2      fullRange8U             (0u, 0xffu);
850
851         // \note Right now it is not programmatically verified that the results shouldn't end up being inf/nan but
852         //       actual values used are ok.
853
854         static const struct
855         {
856                 const char*                                                     name;
857                 const char*                                                     op;
858                 ShaderFloatPrecisionCase::EvalFunc      evalFunc;
859                 glu::Precision                                          precision;
860                 tcu::Vec2                                                       rangeA;
861                 tcu::Vec2                                                       rangeB;
862         } floatCases[] =
863         {
864                 // Name                         Op                              Eval                    Precision                               RangeA                          RangeB
865                 { "highp_add",          "in0 + in1",    add<double>,    glu::PRECISION_HIGHP,   fullRange32F,           fullRange32F            },
866                 { "highp_sub",          "in0 - in1",    sub<double>,    glu::PRECISION_HIGHP,   fullRange32F,           fullRange32F            },
867                 { "highp_mul",          "in0 * in1",    mul<double>,    glu::PRECISION_HIGHP,   Vec2(-1e5f, 1e5f),      Vec2(-1e5f, 1e5f)       },
868                 { "highp_div",          "in0 / in1",    div<double>,    glu::PRECISION_HIGHP,   Vec2(-1e5f, 1e5f),      Vec2(-1e5f, 1e5f)       },
869                 { "mediump_add",        "in0 + in1",    add<double>,    glu::PRECISION_MEDIUMP, fullRange16F,           fullRange16F            },
870                 { "mediump_sub",        "in0 - in1",    sub<double>,    glu::PRECISION_MEDIUMP, fullRange16F,           fullRange16F            },
871                 { "mediump_mul",        "in0 * in1",    mul<double>,    glu::PRECISION_MEDIUMP, Vec2(-1e2f, 1e2f),      Vec2(-1e2f, 1e2f)       },
872                 { "mediump_div",        "in0 / in1",    div<double>,    glu::PRECISION_MEDIUMP, Vec2(-1e2f, 1e2f),      Vec2(-1e2f, 1e2f)       }
873         };
874
875         static const struct
876         {
877                 const char*                                                     name;
878                 const char*                                                     op;
879                 ShaderIntPrecisionCase::EvalFunc        evalFunc;
880                 glu::Precision                                          precision;
881                 int                                                                     bits;
882                 tcu::IVec2                                                      rangeA;
883                 tcu::IVec2                                                      rangeB;
884         } intCases[] =
885         {
886                 // Name                         Op                              Eval                            Precision                               Bits    RangeA                  RangeB
887                 { "highp_add",          "in0 + in1",    add<int>,                       glu::PRECISION_HIGHP,   32,             fullRange32I,   fullRange32I },
888                 { "highp_sub",          "in0 - in1",    sub<int>,                       glu::PRECISION_HIGHP,   32,             fullRange32I,   fullRange32I },
889                 { "highp_mul",          "in0 * in1",    mul<int>,                       glu::PRECISION_HIGHP,   32,             fullRange32I,   fullRange32I },
890                 { "highp_div",          "in0 / in1",    div<int>,                       glu::PRECISION_HIGHP,   32,             fullRange32I,   IVec2(-10000, -1) },
891                 { "mediump_add",        "in0 + in1",    add<int>,                       glu::PRECISION_MEDIUMP, 16,             fullRange16I,   fullRange16I },
892                 { "mediump_sub",        "in0 - in1",    sub<int>,                       glu::PRECISION_MEDIUMP, 16,             fullRange16I,   fullRange16I },
893                 { "mediump_mul",        "in0 * in1",    mul<int>,                       glu::PRECISION_MEDIUMP, 16,             fullRange16I,   fullRange16I },
894                 { "mediump_div",        "in0 / in1",    div<int>,                       glu::PRECISION_MEDIUMP, 16,             fullRange16I,   IVec2(1, 1000) },
895                 { "lowp_add",           "in0 + in1",    add<int>,                       glu::PRECISION_LOWP,    8,              fullRange8I,    fullRange8I },
896                 { "lowp_sub",           "in0 - in1",    sub<int>,                       glu::PRECISION_LOWP,    8,              fullRange8I,    fullRange8I },
897                 { "lowp_mul",           "in0 * in1",    mul<int>,                       glu::PRECISION_LOWP,    8,              fullRange8I,    fullRange8I },
898                 { "lowp_div",           "in0 / in1",    div<int>,                       glu::PRECISION_LOWP,    8,              fullRange8I,    IVec2(-50, -1) }
899         };
900
901         static const struct
902         {
903                 const char*                                                     name;
904                 const char*                                                     op;
905                 ShaderUintPrecisionCase::EvalFunc       evalFunc;
906                 glu::Precision                                          precision;
907                 int                                                                     bits;
908                 tcu::UVec2                                                      rangeA;
909                 tcu::UVec2                                                      rangeB;
910         } uintCases[] =
911         {
912                 // Name                         Op                              Eval                            Precision                               Bits    RangeA                  RangeB
913                 { "highp_add",          "in0 + in1",    add<deUint32>,          glu::PRECISION_HIGHP,   32,             fullRange32U,   fullRange32U },
914                 { "highp_sub",          "in0 - in1",    sub<deUint32>,          glu::PRECISION_HIGHP,   32,             fullRange32U,   fullRange32U },
915                 { "highp_mul",          "in0 * in1",    mul<deUint32>,          glu::PRECISION_HIGHP,   32,             fullRange32U,   fullRange32U },
916                 { "highp_div",          "in0 / in1",    div<deUint32>,          glu::PRECISION_HIGHP,   32,             fullRange32U,   UVec2(1u, 10000u) },
917                 { "mediump_add",        "in0 + in1",    add<deUint32>,          glu::PRECISION_MEDIUMP, 16,             fullRange16U,   fullRange16U },
918                 { "mediump_sub",        "in0 - in1",    sub<deUint32>,          glu::PRECISION_MEDIUMP, 16,             fullRange16U,   fullRange16U },
919                 { "mediump_mul",        "in0 * in1",    mul<deUint32>,          glu::PRECISION_MEDIUMP, 16,             fullRange16U,   fullRange16U },
920                 { "mediump_div",        "in0 / in1",    div<deUint32>,          glu::PRECISION_MEDIUMP, 16,             fullRange16U,   UVec2(1, 1000u) },
921                 { "lowp_add",           "in0 + in1",    add<deUint32>,          glu::PRECISION_LOWP,    8,              fullRange8U,    fullRange8U },
922                 { "lowp_sub",           "in0 - in1",    sub<deUint32>,          glu::PRECISION_LOWP,    8,              fullRange8U,    fullRange8U },
923                 { "lowp_mul",           "in0 * in1",    mul<deUint32>,          glu::PRECISION_LOWP,    8,              fullRange8U,    fullRange8U },
924                 { "lowp_div",           "in0 / in1",    div<deUint32>,          glu::PRECISION_LOWP,    8,              fullRange8U,    UVec2(1, 50u) }
925         };
926
927         tcu::TestCaseGroup* floatGroup = new tcu::TestCaseGroup(m_testCtx, "float", "Floating-point precision tests");
928         addChild(floatGroup);
929         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(floatCases); ndx++)
930         {
931                 floatGroup->addChild(new ShaderFloatPrecisionCase(m_context,
932                                                                                                                   (string(floatCases[ndx].name) + "_vertex").c_str(), "",
933                                                                                                                   floatCases[ndx].op,
934                                                                                                                   floatCases[ndx].evalFunc,
935                                                                                                                   floatCases[ndx].precision,
936                                                                                                                   floatCases[ndx].rangeA,
937                                                                                                                   floatCases[ndx].rangeB,
938                                                                                                                   true));
939                 floatGroup->addChild(new ShaderFloatPrecisionCase(m_context,
940                                                                                                                   (string(floatCases[ndx].name) + "_fragment").c_str(), "",
941                                                                                                                   floatCases[ndx].op,
942                                                                                                                   floatCases[ndx].evalFunc,
943                                                                                                                   floatCases[ndx].precision,
944                                                                                                                   floatCases[ndx].rangeA,
945                                                                                                                   floatCases[ndx].rangeB,
946                                                                                                                   false));
947         }
948
949         tcu::TestCaseGroup* intGroup = new tcu::TestCaseGroup(m_testCtx, "int", "Integer precision tests");
950         addChild(intGroup);
951         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(intCases); ndx++)
952         {
953                 intGroup->addChild(new ShaderIntPrecisionCase(m_context,
954                                                                                                           (string(intCases[ndx].name) + "_vertex").c_str(), "",
955                                                                                                           intCases[ndx].op,
956                                                                                                           intCases[ndx].evalFunc,
957                                                                                                           intCases[ndx].precision,
958                                                                                                           intCases[ndx].bits,
959                                                                                                           intCases[ndx].rangeA,
960                                                                                                           intCases[ndx].rangeB,
961                                                                                                           true));
962                 intGroup->addChild(new ShaderIntPrecisionCase(m_context,
963                                                                                                           (string(intCases[ndx].name) + "_fragment").c_str(), "",
964                                                                                                           intCases[ndx].op,
965                                                                                                           intCases[ndx].evalFunc,
966                                                                                                           intCases[ndx].precision,
967                                                                                                           intCases[ndx].bits,
968                                                                                                           intCases[ndx].rangeA,
969                                                                                                           intCases[ndx].rangeB,
970                                                                                                           false));
971         }
972
973         tcu::TestCaseGroup* uintGroup = new tcu::TestCaseGroup(m_testCtx, "uint", "Unsigned integer precision tests");
974         addChild(uintGroup);
975         for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(uintCases); ndx++)
976         {
977                 uintGroup->addChild(new ShaderUintPrecisionCase(m_context,
978                                                                                                                 (string(uintCases[ndx].name) + "_vertex").c_str(), "",
979                                                                                                                 uintCases[ndx].op,
980                                                                                                                 uintCases[ndx].evalFunc,
981                                                                                                                 uintCases[ndx].precision,
982                                                                                                                 uintCases[ndx].bits,
983                                                                                                                 uintCases[ndx].rangeA,
984                                                                                                                 uintCases[ndx].rangeB,
985                                                                                                                 true));
986                 uintGroup->addChild(new ShaderUintPrecisionCase(m_context,
987                                                                                                                 (string(uintCases[ndx].name) + "_fragment").c_str(), "",
988                                                                                                                 uintCases[ndx].op,
989                                                                                                                 uintCases[ndx].evalFunc,
990                                                                                                                 uintCases[ndx].precision,
991                                                                                                                 uintCases[ndx].bits,
992                                                                                                                 uintCases[ndx].rangeA,
993                                                                                                                 uintCases[ndx].rangeB,
994                                                                                                                 false));
995         }
996 }
997
998 } // Functional
999 } // gles3
1000 } // deqp