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