xref: /aosp_15_r20/external/deqp/modules/gles3/functional/es3fShaderBuiltinVarTests.cpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 built-in variable tests.
22  *//*--------------------------------------------------------------------*/
23 
24 #include "es3fShaderBuiltinVarTests.hpp"
25 #include "glsShaderRenderCase.hpp"
26 #include "glsShaderExecUtil.hpp"
27 #include "deRandom.hpp"
28 #include "deString.h"
29 #include "deMath.h"
30 #include "deUniquePtr.hpp"
31 #include "deStringUtil.hpp"
32 #include "tcuTestLog.hpp"
33 #include "tcuTestCase.hpp"
34 #include "tcuTextureUtil.hpp"
35 #include "tcuRenderTarget.hpp"
36 #include "tcuImageCompare.hpp"
37 #include "gluPixelTransfer.hpp"
38 #include "gluDrawUtil.hpp"
39 #include "gluStrUtil.hpp"
40 #include "rrRenderer.hpp"
41 #include "rrFragmentOperations.hpp"
42 
43 #include "glwEnums.hpp"
44 #include "glwFunctions.hpp"
45 
46 using std::string;
47 using std::vector;
48 using tcu::TestLog;
49 
50 namespace deqp
51 {
52 namespace gles3
53 {
54 namespace Functional
55 {
56 
getInteger(const glw::Functions & gl,uint32_t pname)57 static int getInteger(const glw::Functions &gl, uint32_t pname)
58 {
59     int value = -1;
60     gl.getIntegerv(pname, &value);
61     GLU_EXPECT_NO_ERROR(gl.getError(),
62                         ("glGetIntegerv(" + glu::getGettableStateStr((int)pname).toString() + ")").c_str());
63     return value;
64 }
65 
66 template <uint32_t Pname>
getInteger(const glw::Functions & gl)67 static int getInteger(const glw::Functions &gl)
68 {
69     return getInteger(gl, Pname);
70 }
71 
getVectorsFromComps(const glw::Functions & gl,uint32_t pname)72 static int getVectorsFromComps(const glw::Functions &gl, uint32_t pname)
73 {
74     int value = -1;
75     gl.getIntegerv(pname, &value);
76     GLU_EXPECT_NO_ERROR(gl.getError(),
77                         ("glGetIntegerv(" + glu::getGettableStateStr((int)pname).toString() + ")").c_str());
78     // Accept truncated division. According to the spec, the number of vectors is number of components divided by four, plain and simple.
79     return value / 4;
80 }
81 
82 template <uint32_t Pname>
getVectorsFromComps(const glw::Functions & gl)83 static int getVectorsFromComps(const glw::Functions &gl)
84 {
85     return getVectorsFromComps(gl, Pname);
86 }
87 
88 class ShaderBuiltinConstantCase : public TestCase
89 {
90 public:
91     typedef int (*GetConstantValueFunc)(const glw::Functions &gl);
92 
93     ShaderBuiltinConstantCase(Context &context, const char *name, const char *desc, const char *varName,
94                               GetConstantValueFunc getValue, glu::ShaderType shaderType);
95     ~ShaderBuiltinConstantCase(void);
96 
97     IterateResult iterate(void);
98 
99 private:
100     const std::string m_varName;
101     const GetConstantValueFunc m_getValue;
102     const glu::ShaderType m_shaderType;
103 };
104 
ShaderBuiltinConstantCase(Context & context,const char * name,const char * desc,const char * varName,GetConstantValueFunc getValue,glu::ShaderType shaderType)105 ShaderBuiltinConstantCase::ShaderBuiltinConstantCase(Context &context, const char *name, const char *desc,
106                                                      const char *varName, GetConstantValueFunc getValue,
107                                                      glu::ShaderType shaderType)
108     : TestCase(context, name, desc)
109     , m_varName(varName)
110     , m_getValue(getValue)
111     , m_shaderType(shaderType)
112 {
113 }
114 
~ShaderBuiltinConstantCase(void)115 ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase(void)
116 {
117 }
118 
createGetConstantExecutor(const glu::RenderContext & renderCtx,glu::ShaderType shaderType,const std::string & varName)119 static gls::ShaderExecUtil::ShaderExecutor *createGetConstantExecutor(const glu::RenderContext &renderCtx,
120                                                                       glu::ShaderType shaderType,
121                                                                       const std::string &varName)
122 {
123     using namespace gls::ShaderExecUtil;
124 
125     ShaderSpec shaderSpec;
126 
127     shaderSpec.version = glu::GLSL_VERSION_300_ES;
128     shaderSpec.source  = string("result = ") + varName + ";\n";
129     shaderSpec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_INT, glu::PRECISION_HIGHP)));
130 
131     return createExecutor(renderCtx, shaderType, shaderSpec);
132 }
133 
iterate(void)134 ShaderBuiltinConstantCase::IterateResult ShaderBuiltinConstantCase::iterate(void)
135 {
136     using namespace gls::ShaderExecUtil;
137 
138     const de::UniquePtr<ShaderExecutor> shaderExecutor(
139         createGetConstantExecutor(m_context.getRenderContext(), m_shaderType, m_varName));
140     const int reference = m_getValue(m_context.getRenderContext().getFunctions());
141     int result          = -1;
142     void *const outputs = &result;
143 
144     if (!shaderExecutor->isOk())
145     {
146         shaderExecutor->log(m_testCtx.getLog());
147         TCU_FAIL("Compile failed");
148     }
149 
150     shaderExecutor->useProgram();
151     shaderExecutor->execute(1, DE_NULL, &outputs);
152 
153     m_testCtx.getLog() << TestLog::Integer(m_varName, m_varName, "", QP_KEY_TAG_NONE, result);
154 
155     if (result != reference)
156     {
157         m_testCtx.getLog() << TestLog::Message << "ERROR: Expected " << m_varName << " = " << reference
158                            << TestLog::EndMessage << TestLog::Message << "Test shader:" << TestLog::EndMessage;
159         shaderExecutor->log(m_testCtx.getLog());
160         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Invalid builtin constant value");
161     }
162     else
163         m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
164 
165     return STOP;
166 }
167 
168 namespace
169 {
170 
171 struct DepthRangeParams
172 {
DepthRangeParamsdeqp::gles3::Functional::__anon39e231830111::DepthRangeParams173     DepthRangeParams(void) : zNear(0.0f), zFar(1.0f)
174     {
175     }
176 
DepthRangeParamsdeqp::gles3::Functional::__anon39e231830111::DepthRangeParams177     DepthRangeParams(float zNear_, float zFar_) : zNear(zNear_), zFar(zFar_)
178     {
179     }
180 
181     float zNear;
182     float zFar;
183 };
184 
185 class DepthRangeEvaluator : public gls::ShaderEvaluator
186 {
187 public:
DepthRangeEvaluator(const DepthRangeParams & params)188     DepthRangeEvaluator(const DepthRangeParams &params) : m_params(params)
189     {
190     }
191 
evaluate(gls::ShaderEvalContext & c)192     void evaluate(gls::ShaderEvalContext &c)
193     {
194         float zNear   = deFloatClamp(m_params.zNear, 0.0f, 1.0f);
195         float zFar    = deFloatClamp(m_params.zFar, 0.0f, 1.0f);
196         float diff    = zFar - zNear;
197         c.color.xyz() = tcu::Vec3(zNear, zFar, diff * 0.5f + 0.5f);
198     }
199 
200 private:
201     const DepthRangeParams &m_params;
202 };
203 
204 } // namespace
205 
206 class ShaderDepthRangeTest : public gls::ShaderRenderCase
207 {
208 public:
ShaderDepthRangeTest(Context & context,const char * name,const char * desc,bool isVertexCase)209     ShaderDepthRangeTest(Context &context, const char *name, const char *desc, bool isVertexCase)
210         : ShaderRenderCase(context.getTestContext(), context.getRenderContext(), context.getContextInfo(), name, desc,
211                            isVertexCase, m_evaluator)
212         , m_evaluator(m_depthRange)
213         , m_iterNdx(0)
214     {
215     }
216 
init(void)217     void init(void)
218     {
219         static const char *defaultVertSrc = "#version 300 es\n"
220                                             "in highp vec4 a_position;\n"
221                                             "void main (void)\n"
222                                             "{\n"
223                                             "    gl_Position = a_position;\n"
224                                             "}\n";
225         static const char *defaultFragSrc = "#version 300 es\n"
226                                             "in mediump vec4 v_color;\n"
227                                             "layout(location = 0) out mediump vec4 o_color;\n\n"
228                                             "void main (void)\n"
229                                             "{\n"
230                                             "    o_color = v_color;\n"
231                                             "}\n";
232 
233         // Construct shader.
234         std::ostringstream src;
235         src << "#version 300 es\n";
236         if (m_isVertexCase)
237             src << "in highp vec4 a_position;\n"
238                 << "out mediump vec4 v_color;\n";
239         else
240             src << "layout(location = 0) out mediump vec4 o_color;\n";
241 
242         src << "void main (void)\n{\n";
243         src << "\t" << (m_isVertexCase ? "v_color" : "o_color")
244             << " = vec4(gl_DepthRange.near, gl_DepthRange.far, gl_DepthRange.diff*0.5 + 0.5, 1.0);\n";
245 
246         if (m_isVertexCase)
247             src << "\tgl_Position = a_position;\n";
248 
249         src << "}\n";
250 
251         m_vertShaderSource = m_isVertexCase ? src.str() : defaultVertSrc;
252         m_fragShaderSource = m_isVertexCase ? defaultFragSrc : src.str();
253 
254         gls::ShaderRenderCase::init();
255     }
256 
iterate(void)257     IterateResult iterate(void)
258     {
259         const glw::Functions &gl = m_renderCtx.getFunctions();
260 
261         const DepthRangeParams cases[] = {DepthRangeParams(0.0f, 1.0f), DepthRangeParams(1.5f, -1.0f),
262                                           DepthRangeParams(0.7f, 0.3f)};
263 
264         m_depthRange = cases[m_iterNdx];
265         m_testCtx.getLog() << tcu::TestLog::Message << "glDepthRangef(" << m_depthRange.zNear << ", "
266                            << m_depthRange.zFar << ")" << tcu::TestLog::EndMessage;
267         gl.depthRangef(m_depthRange.zNear, m_depthRange.zFar);
268         GLU_EXPECT_NO_ERROR(gl.getError(), "glDepthRangef()");
269 
270         gls::ShaderRenderCase::iterate();
271         m_iterNdx += 1;
272 
273         if (m_iterNdx == DE_LENGTH_OF_ARRAY(cases) || m_testCtx.getTestResult() != QP_TEST_RESULT_PASS)
274             return STOP;
275         else
276             return CONTINUE;
277     }
278 
279 private:
280     DepthRangeParams m_depthRange;
281     DepthRangeEvaluator m_evaluator;
282     int m_iterNdx;
283 };
284 
285 class FragCoordXYZCase : public TestCase
286 {
287 public:
FragCoordXYZCase(Context & context)288     FragCoordXYZCase(Context &context) : TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test")
289     {
290     }
291 
iterate(void)292     IterateResult iterate(void)
293     {
294         TestLog &log             = m_testCtx.getLog();
295         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
296         const int width          = m_context.getRenderTarget().getWidth();
297         const int height         = m_context.getRenderTarget().getHeight();
298         const tcu::RGBA threshold =
299             tcu::RGBA(1, 1, 1, 1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
300         const tcu::Vec3 scale(1.f / float(width), 1.f / float(height), 1.0f);
301 
302         tcu::Surface testImg(width, height);
303         tcu::Surface refImg(width, height);
304 
305         const glu::ShaderProgram program(m_context.getRenderContext(),
306                                          glu::makeVtxFragSources("#version 300 es\n"
307                                                                  "in highp vec4 a_position;\n"
308                                                                  "void main (void)\n"
309                                                                  "{\n"
310                                                                  "    gl_Position = a_position;\n"
311                                                                  "}\n",
312 
313                                                                  "#version 300 es\n"
314                                                                  "uniform highp vec3 u_scale;\n"
315                                                                  "layout(location = 0) out mediump vec4 o_color;\n"
316                                                                  "void main (void)\n"
317                                                                  "{\n"
318                                                                  "    o_color = vec4(gl_FragCoord.xyz*u_scale, 1.0);\n"
319                                                                  "}\n"));
320 
321         log << program;
322 
323         if (!program.isOk())
324             throw tcu::TestError("Compile failed");
325 
326         // Draw with GL.
327         {
328             const float positions[]  = {-1.0f, 1.0f, -1.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
329                                         1.0f,  1.0f, 0.0f,  1.0f, 1.0f,  -1.0f, 1.0f, 1.0f};
330             const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
331 
332             const int scaleLoc                 = gl.getUniformLocation(program.getProgram(), "u_scale");
333             glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
334 
335             gl.useProgram(program.getProgram());
336             gl.uniform3fv(scaleLoc, 1, scale.getPtr());
337 
338             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
339                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
340 
341             glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
342             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
343         }
344 
345         // Draw reference
346         for (int y = 0; y < refImg.getHeight(); y++)
347         {
348             for (int x = 0; x < refImg.getWidth(); x++)
349             {
350                 const float xf = (float(x) + .5f) / float(refImg.getWidth());
351                 const float yf = (float(refImg.getHeight() - y - 1) + .5f) / float(refImg.getHeight());
352                 const float z  = (xf + yf) / 2.0f;
353                 const tcu::Vec3 fragCoord(float(x) + .5f, float(y) + .5f, z);
354                 const tcu::Vec3 scaledFC = fragCoord * scale;
355                 const tcu::Vec4 color(scaledFC.x(), scaledFC.y(), scaledFC.z(), 1.0f);
356 
357                 refImg.setPixel(x, y, tcu::RGBA(color));
358             }
359         }
360 
361         // Compare
362         {
363             bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold,
364                                                    tcu::COMPARE_LOG_RESULT);
365             m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
366                                     isOk ? "Pass" : "Image comparison failed");
367         }
368 
369         return STOP;
370     }
371 };
372 
projectedTriInterpolate(const tcu::Vec3 & s,const tcu::Vec3 & w,float nx,float ny)373 static inline float projectedTriInterpolate(const tcu::Vec3 &s, const tcu::Vec3 &w, float nx, float ny)
374 {
375     return (s[0] * (1.0f - nx - ny) / w[0] + s[1] * ny / w[1] + s[2] * nx / w[2]) /
376            ((1.0f - nx - ny) / w[0] + ny / w[1] + nx / w[2]);
377 }
378 
379 class FragCoordWCase : public TestCase
380 {
381 public:
FragCoordWCase(Context & context)382     FragCoordWCase(Context &context) : TestCase(context, "fragcoord_w", "gl_FragCoord.w Test")
383     {
384     }
385 
iterate(void)386     IterateResult iterate(void)
387     {
388         TestLog &log             = m_testCtx.getLog();
389         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
390         const int width          = m_context.getRenderTarget().getWidth();
391         const int height         = m_context.getRenderTarget().getHeight();
392         const tcu::RGBA threshold =
393             tcu::RGBA(1, 1, 1, 1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
394 
395         tcu::Surface testImg(width, height);
396         tcu::Surface refImg(width, height);
397 
398         const float w[4] = {1.7f, 2.0f, 1.2f, 1.0f};
399 
400         const glu::ShaderProgram program(
401             m_context.getRenderContext(),
402             glu::makeVtxFragSources("#version 300 es\n"
403                                     "in highp vec4 a_position;\n"
404                                     "void main (void)\n"
405                                     "{\n"
406                                     "    gl_Position = a_position;\n"
407                                     "}\n",
408 
409                                     "#version 300 es\n"
410                                     "layout(location = 0) out mediump vec4 o_color;\n"
411                                     "void main (void)\n"
412                                     "{\n"
413                                     "    o_color = vec4(0.0, 1.0/gl_FragCoord.w - 1.0, 0.0, 1.0);\n"
414                                     "}\n"));
415 
416         log << program;
417 
418         if (!program.isOk())
419             throw tcu::TestError("Compile failed");
420 
421         // Draw with GL.
422         {
423             const float positions[]  = {-w[0], w[0], 0.0f, w[0], -w[1], -w[1], 0.0f, w[1],
424                                         w[2],  w[2], 0.0f, w[2], w[3],  -w[3], 0.0f, w[3]};
425             const uint16_t indices[] = {0, 1, 2, 2, 1, 3};
426 
427             glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
428 
429             gl.useProgram(program.getProgram());
430 
431             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
432                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0]));
433 
434             glu::readPixels(m_context.getRenderContext(), 0, 0, testImg.getAccess());
435             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
436         }
437 
438         // Draw reference
439         for (int y = 0; y < refImg.getHeight(); y++)
440         {
441             for (int x = 0; x < refImg.getWidth(); x++)
442             {
443                 const float xf = (float(x) + .5f) / float(refImg.getWidth());
444                 const float yf = (float(refImg.getHeight() - y - 1) + .5f) / float(refImg.getHeight());
445                 const float oow =
446                     ((xf + yf) < 1.0f) ?
447                         projectedTriInterpolate(tcu::Vec3(w[0], w[1], w[2]), tcu::Vec3(w[0], w[1], w[2]), xf, yf) :
448                         projectedTriInterpolate(tcu::Vec3(w[3], w[2], w[1]), tcu::Vec3(w[3], w[2], w[1]), 1.0f - xf,
449                                                 1.0f - yf);
450                 const tcu::Vec4 color(0.0f, oow - 1.0f, 0.0f, 1.0f);
451 
452                 refImg.setPixel(x, y, tcu::RGBA(color));
453             }
454         }
455 
456         // Compare
457         {
458             bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold,
459                                                    tcu::COMPARE_LOG_RESULT);
460             m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
461                                     isOk ? "Pass" : "Image comparison failed");
462         }
463 
464         return STOP;
465     }
466 };
467 
468 class PointCoordCase : public TestCase
469 {
470 public:
PointCoordCase(Context & context)471     PointCoordCase(Context &context) : TestCase(context, "pointcoord", "gl_PointCoord Test")
472     {
473     }
474 
iterate(void)475     IterateResult iterate(void)
476     {
477         TestLog &log             = m_testCtx.getLog();
478         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
479         const int width          = de::min(256, m_context.getRenderTarget().getWidth());
480         const int height         = de::min(256, m_context.getRenderTarget().getHeight());
481         const float threshold    = 0.02f;
482 
483         const int numPoints = 8;
484 
485         vector<tcu::Vec3> coords(numPoints);
486         float pointSizeRange[2] = {0.0f, 0.0f};
487 
488         de::Random rnd(0x145fa);
489         tcu::Surface testImg(width, height);
490         tcu::Surface refImg(width, height);
491 
492         gl.getFloatv(GL_ALIASED_POINT_SIZE_RANGE, &pointSizeRange[0]);
493         GLU_EXPECT_NO_ERROR(gl.getError(), "glGetFloatv(GL_ALIASED_POINT_SIZE_RANGE)");
494 
495         if (pointSizeRange[0] <= 0.0f || pointSizeRange[1] <= 0.0f || pointSizeRange[1] < pointSizeRange[0])
496             throw tcu::TestError("Invalid GL_ALIASED_POINT_SIZE_RANGE");
497 
498         // Compute coordinates.
499         {
500 
501             for (vector<tcu::Vec3>::iterator coord = coords.begin(); coord != coords.end(); ++coord)
502             {
503                 coord->x() = rnd.getFloat(-0.9f, 0.9f);
504                 coord->y() = rnd.getFloat(-0.9f, 0.9f);
505                 coord->z() = rnd.getFloat(pointSizeRange[0], pointSizeRange[1]);
506             }
507         }
508 
509         const glu::ShaderProgram program(
510             m_context.getRenderContext(),
511             glu::makeVtxFragSources("#version 300 es\n"
512                                     "in highp vec3 a_positionSize;\n"
513                                     "void main (void)\n"
514                                     "{\n"
515                                     "    gl_Position = vec4(a_positionSize.xy, 0.0, 1.0);\n"
516                                     "    gl_PointSize = a_positionSize.z;\n"
517                                     "}\n",
518 
519                                     "#version 300 es\n"
520                                     "layout(location = 0) out mediump vec4 o_color;\n"
521                                     "void main (void)\n"
522                                     "{\n"
523                                     "    o_color = vec4(gl_PointCoord, 0.0, 1.0);\n"
524                                     "}\n"));
525 
526         log << program;
527 
528         if (!program.isOk())
529             throw tcu::TestError("Compile failed");
530 
531         // Draw with GL.
532         {
533             glu::VertexArrayBinding posBinding =
534                 glu::va::Float("a_positionSize", 3, (int)coords.size(), 0, (const float *)&coords[0]);
535             const int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth() - width);
536             const int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight() - height);
537 
538             gl.viewport(viewportX, viewportY, width, height);
539             gl.clearColor(0.0f, 0.0f, 0.0f, 1.0f);
540             gl.clear(GL_COLOR_BUFFER_BIT);
541 
542             gl.useProgram(program.getProgram());
543 
544             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
545                       glu::pr::Points((int)coords.size()));
546 
547             glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
548             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
549         }
550 
551         // Draw reference
552         tcu::clear(refImg.getAccess(), tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f));
553         for (vector<tcu::Vec3>::const_iterator pointIter = coords.begin(); pointIter != coords.end(); ++pointIter)
554         {
555             const int x0 = deRoundFloatToInt32(float(width) * (pointIter->x() * 0.5f + 0.5f) - pointIter->z() * 0.5f);
556             const int y0 = deRoundFloatToInt32(float(height) * (pointIter->y() * 0.5f + 0.5f) - pointIter->z() * 0.5f);
557             const int x1 = deRoundFloatToInt32(float(width) * (pointIter->x() * 0.5f + 0.5f) + pointIter->z() * 0.5f);
558             const int y1 = deRoundFloatToInt32(float(height) * (pointIter->y() * 0.5f + 0.5f) + pointIter->z() * 0.5f);
559             const int w  = x1 - x0;
560             const int h  = y1 - y0;
561 
562             for (int yo = 0; yo < h; yo++)
563             {
564                 for (int xo = 0; xo < w; xo++)
565                 {
566                     const float xf = (float(xo) + 0.5f) / float(w);
567                     const float yf = (float(h - yo - 1) + 0.5f) / float(h);
568                     const tcu::Vec4 color(xf, yf, 0.0f, 1.0f);
569                     const int dx = x0 + xo;
570                     const int dy = y0 + yo;
571 
572                     if (de::inBounds(dx, 0, refImg.getWidth()) && de::inBounds(dy, 0, refImg.getHeight()))
573                         refImg.setPixel(dx, dy, tcu::RGBA(color));
574                 }
575             }
576         }
577 
578         // Compare
579         {
580             bool isOk = tcu::fuzzyCompare(log, "Result", "Image comparison result", refImg, testImg, threshold,
581                                           tcu::COMPARE_LOG_RESULT);
582             m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
583                                     isOk ? "Pass" : "Image comparison failed");
584         }
585 
586         return STOP;
587     }
588 };
589 
590 class FrontFacingCase : public TestCase
591 {
592 public:
FrontFacingCase(Context & context)593     FrontFacingCase(Context &context) : TestCase(context, "frontfacing", "gl_FrontFacing Test")
594     {
595     }
596 
iterate(void)597     IterateResult iterate(void)
598     {
599         // Test case renders two adjecent quads, where left is has front-facing
600         // triagles and right back-facing. Color is selected based on gl_FrontFacing
601         // value.
602 
603         TestLog &log             = m_testCtx.getLog();
604         const glw::Functions &gl = m_context.getRenderContext().getFunctions();
605         de::Random rnd(0x89f2c);
606         const int width     = de::min(64, m_context.getRenderTarget().getWidth());
607         const int height    = de::min(64, m_context.getRenderTarget().getHeight());
608         const int viewportX = rnd.getInt(0, m_context.getRenderTarget().getWidth() - width);
609         const int viewportY = rnd.getInt(0, m_context.getRenderTarget().getHeight() - height);
610         const tcu::RGBA threshold =
611             tcu::RGBA(1, 1, 1, 1) + m_context.getRenderTarget().getPixelFormat().getColorThreshold();
612 
613         tcu::Surface testImg(width, height);
614         tcu::Surface refImg(width, height);
615 
616         const glu::ShaderProgram program(m_context.getRenderContext(),
617                                          glu::makeVtxFragSources("#version 300 es\n"
618                                                                  "in highp vec4 a_position;\n"
619                                                                  "void main (void)\n"
620                                                                  "{\n"
621                                                                  "    gl_Position = a_position;\n"
622                                                                  "}\n",
623 
624                                                                  "#version 300 es\n"
625                                                                  "layout(location = 0) out mediump vec4 o_color;\n"
626                                                                  "void main (void)\n"
627                                                                  "{\n"
628                                                                  "    if (gl_FrontFacing)\n"
629                                                                  "        o_color = vec4(0.0, 1.0, 0.0, 1.0);\n"
630                                                                  "    else\n"
631                                                                  "        o_color = vec4(0.0, 0.0, 1.0, 1.0);\n"
632                                                                  "}\n"));
633 
634         log << program;
635 
636         if (!program.isOk())
637             throw tcu::TestError("Compile failed");
638 
639         // Draw with GL.
640         {
641             const float positions[]     = {-1.0f, 1.0f, 0.0f, 1.0f, -1.0f, -1.0f, 0.0f, 1.0f,
642                                            1.0f,  1.0f, 0.0f, 1.0f, 1.0f,  -1.0f, 0.0f, 1.0f};
643             const uint16_t indicesCCW[] = {0, 1, 2, 2, 1, 3};
644             const uint16_t indicesCW[]  = {2, 1, 0, 3, 1, 2};
645 
646             glu::VertexArrayBinding posBinding = glu::va::Float("a_position", 4, 4, 0, &positions[0]);
647 
648             gl.useProgram(program.getProgram());
649 
650             gl.frontFace(GL_CCW);
651 
652             gl.viewport(viewportX, viewportY, width / 2, height / 2);
653             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
654                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));
655 
656             gl.viewport(viewportX + width / 2, viewportY, width - width / 2, height / 2);
657             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
658                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));
659 
660             gl.frontFace(GL_CW);
661 
662             gl.viewport(viewportX, viewportY + height / 2, width / 2, height - height / 2);
663             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
664                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0]));
665 
666             gl.viewport(viewportX + width / 2, viewportY + height / 2, width - width / 2, height - height / 2);
667             glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding,
668                       glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0]));
669 
670             glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
671             GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
672         }
673 
674         // Draw reference
675         {
676             for (int y = 0; y < refImg.getHeight() / 2; y++)
677                 for (int x = 0; x < refImg.getWidth() / 2; x++)
678                     refImg.setPixel(x, y, tcu::RGBA::green());
679 
680             for (int y = 0; y < refImg.getHeight() / 2; y++)
681                 for (int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++)
682                     refImg.setPixel(x, y, tcu::RGBA::blue());
683 
684             for (int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++)
685                 for (int x = 0; x < refImg.getWidth() / 2; x++)
686                     refImg.setPixel(x, y, tcu::RGBA::blue());
687 
688             for (int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++)
689                 for (int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++)
690                     refImg.setPixel(x, y, tcu::RGBA::green());
691         }
692 
693         // Compare
694         {
695             bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold,
696                                                    tcu::COMPARE_LOG_RESULT);
697             m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL,
698                                     isOk ? "Pass" : "Image comparison failed");
699         }
700 
701         return STOP;
702     }
703 };
704 
705 // VertexIDCase
706 
707 class VertexIDCase : public TestCase
708 {
709 public:
710     VertexIDCase(Context &context);
711     ~VertexIDCase(void);
712 
713     void init(void);
714     void deinit(void);
715     IterateResult iterate(void);
716 
717 private:
718     enum
719     {
720         MAX_VERTICES = 8 * 3 //!< 8 triangles, totals 24 vertices
721     };
722 
723     void renderReference(const tcu::PixelBufferAccess &dst, const int numVertices, const uint16_t *const indices,
724                          const tcu::Vec4 *const positions, const tcu::Vec4 *const colors, const int subpixelBits);
725 
726     glu::ShaderProgram *m_program;
727     uint32_t m_positionBuffer;
728     uint32_t m_elementBuffer;
729 
730     vector<tcu::Vec4> m_positions;
731     vector<tcu::Vec4> m_colors;
732     int m_viewportW;
733     int m_viewportH;
734 
735     int m_iterNdx;
736 };
737 
VertexIDCase(Context & context)738 VertexIDCase::VertexIDCase(Context &context)
739     : TestCase(context, "vertex_id", "gl_VertexID Test")
740     , m_program(DE_NULL)
741     , m_positionBuffer(0)
742     , m_elementBuffer(0)
743     , m_viewportW(0)
744     , m_viewportH(0)
745     , m_iterNdx(0)
746 {
747 }
748 
~VertexIDCase(void)749 VertexIDCase::~VertexIDCase(void)
750 {
751     VertexIDCase::deinit();
752 }
753 
init(void)754 void VertexIDCase::init(void)
755 {
756     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
757     const int width          = m_context.getRenderTarget().getWidth();
758     const int height         = m_context.getRenderTarget().getHeight();
759 
760     const int quadWidth  = 32;
761     const int quadHeight = 32;
762 
763     if (width < quadWidth)
764         throw tcu::NotSupportedError("Too small render target");
765 
766     const int maxQuadsX   = width / quadWidth;
767     const int numVertices = MAX_VERTICES;
768 
769     const int numQuads  = numVertices / 6 + (numVertices % 6 != 0 ? 1 : 0);
770     const int viewportW = de::min(numQuads, maxQuadsX) * quadWidth;
771     const int viewportH = (numQuads / maxQuadsX + (numQuads % maxQuadsX != 0 ? 1 : 0)) * quadHeight;
772 
773     if (viewportH > height)
774         throw tcu::NotSupportedError("Too small render target");
775 
776     DE_ASSERT(viewportW <= width && viewportH <= height);
777 
778     DE_ASSERT(!m_program);
779     m_program = new glu::ShaderProgram(m_context.getRenderContext(),
780                                        glu::makeVtxFragSources("#version 300 es\n"
781                                                                "in highp vec4 a_position;\n"
782                                                                "out mediump vec4 v_color;\n"
783                                                                "uniform highp vec4 u_colors[24];\n"
784                                                                "void main (void)\n"
785                                                                "{\n"
786                                                                "    gl_Position = a_position;\n"
787                                                                "    v_color = u_colors[gl_VertexID];\n"
788                                                                "}\n",
789 
790                                                                "#version 300 es\n"
791                                                                "in mediump vec4 v_color;\n"
792                                                                "layout(location = 0) out mediump vec4 o_color;\n"
793                                                                "void main (void)\n"
794                                                                "{\n"
795                                                                "    o_color = v_color;\n"
796                                                                "}\n"));
797 
798     m_testCtx.getLog() << *m_program;
799 
800     if (!m_program->isOk())
801     {
802         delete m_program;
803         m_program = DE_NULL;
804         throw tcu::TestError("Compile failed");
805     }
806 
807     gl.genBuffers(1, &m_positionBuffer);
808     gl.genBuffers(1, &m_elementBuffer);
809 
810     // Set colors (in dynamic memory to save static data space).
811     m_colors.resize(numVertices);
812     m_colors[0]  = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
813     m_colors[1]  = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f);
814     m_colors[2]  = tcu::Vec4(0.0f, 0.5f, 1.0f, 1.0f);
815     m_colors[3]  = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f);
816     m_colors[4]  = tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f);
817     m_colors[5]  = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f);
818     m_colors[6]  = tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f);
819     m_colors[7]  = tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f);
820     m_colors[8]  = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f);
821     m_colors[9]  = tcu::Vec4(0.5f, 1.0f, 0.0f, 1.0f);
822     m_colors[10] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f);
823     m_colors[11] = tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f);
824     m_colors[12] = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);
825     m_colors[13] = tcu::Vec4(1.0f, 0.0f, 0.5f, 1.0f);
826     m_colors[14] = tcu::Vec4(0.0f, 0.5f, 0.5f, 1.0f);
827     m_colors[15] = tcu::Vec4(1.0f, 1.0f, 0.5f, 1.0f);
828     m_colors[16] = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f);
829     m_colors[17] = tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f);
830     m_colors[18] = tcu::Vec4(0.0f, 1.0f, 0.5f, 1.0f);
831     m_colors[19] = tcu::Vec4(1.0f, 0.5f, 1.0f, 1.0f);
832     m_colors[20] = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f);
833     m_colors[21] = tcu::Vec4(1.0f, 0.5f, 0.5f, 1.0f);
834     m_colors[22] = tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f);
835     m_colors[23] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f);
836 
837     // Compute positions.
838     m_positions.resize(numVertices);
839     DE_ASSERT(numVertices % 3 == 0);
840     for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx += 3)
841     {
842         const float h = 2.0f * float(quadHeight) / float(viewportH);
843         const float w = 2.0f * float(quadWidth) / float(viewportW);
844 
845         const int triNdx  = vtxNdx / 3;
846         const int quadNdx = triNdx / 2;
847         const int quadY   = quadNdx / maxQuadsX;
848         const int quadX   = quadNdx % maxQuadsX;
849 
850         const float x0 = -1.0f + float(quadX) * w;
851         const float y0 = -1.0f + float(quadY) * h;
852 
853         if (triNdx % 2 == 0)
854         {
855             m_positions[vtxNdx + 0] = tcu::Vec4(x0, y0, 0.0f, 1.0f);
856             m_positions[vtxNdx + 1] = tcu::Vec4(x0 + w, y0 + h, 0.0f, 1.0f);
857             m_positions[vtxNdx + 2] = tcu::Vec4(x0, y0 + h, 0.0f, 1.0f);
858         }
859         else
860         {
861             m_positions[vtxNdx + 0] = tcu::Vec4(x0 + w, y0 + h, 0.0f, 1.0f);
862             m_positions[vtxNdx + 1] = tcu::Vec4(x0, y0, 0.0f, 1.0f);
863             m_positions[vtxNdx + 2] = tcu::Vec4(x0 + w, y0, 0.0f, 1.0f);
864         }
865     }
866 
867     m_viewportW = viewportW;
868     m_viewportH = viewportH;
869     m_iterNdx   = 0;
870 
871     m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass");
872 }
873 
deinit(void)874 void VertexIDCase::deinit(void)
875 {
876     delete m_program;
877     m_program = DE_NULL;
878 
879     if (m_positionBuffer)
880     {
881         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_positionBuffer);
882         m_positionBuffer = 0;
883     }
884 
885     if (m_elementBuffer)
886     {
887         m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuffer);
888         m_elementBuffer = 0;
889     }
890 
891     m_positions.clear();
892     m_colors.clear();
893 }
894 
895 class VertexIDReferenceShader : public rr::VertexShader, public rr::FragmentShader
896 {
897 public:
898     enum
899     {
900         VARYINGLOC_COLOR = 0
901     };
902 
VertexIDReferenceShader()903     VertexIDReferenceShader()
904         : rr::VertexShader(2, 1)   // color and pos in => color out
905         , rr::FragmentShader(1, 1) // color in => color out
906     {
907         this->rr::VertexShader::m_inputs[0].type = rr::GENERICVECTYPE_FLOAT;
908         this->rr::VertexShader::m_inputs[1].type = rr::GENERICVECTYPE_FLOAT;
909 
910         this->rr::VertexShader::m_outputs[0].type      = rr::GENERICVECTYPE_FLOAT;
911         this->rr::VertexShader::m_outputs[0].flatshade = false;
912 
913         this->rr::FragmentShader::m_inputs[0].type      = rr::GENERICVECTYPE_FLOAT;
914         this->rr::FragmentShader::m_inputs[0].flatshade = false;
915 
916         this->rr::FragmentShader::m_outputs[0].type = rr::GENERICVECTYPE_FLOAT;
917     }
918 
shadeVertices(const rr::VertexAttrib * inputs,rr::VertexPacket * const * packets,const int numPackets) const919     void shadeVertices(const rr::VertexAttrib *inputs, rr::VertexPacket *const *packets, const int numPackets) const
920     {
921         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
922         {
923             const int positionAttrLoc = 0;
924             const int colorAttrLoc    = 1;
925 
926             rr::VertexPacket &packet = *packets[packetNdx];
927 
928             // Transform to position
929             packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx);
930 
931             // Pass color to FS
932             packet.outputs[VARYINGLOC_COLOR] =
933                 rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx);
934         }
935     }
936 
shadeFragments(rr::FragmentPacket * packets,const int numPackets,const rr::FragmentShadingContext & context) const937     void shadeFragments(rr::FragmentPacket *packets, const int numPackets,
938                         const rr::FragmentShadingContext &context) const
939     {
940         for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx)
941         {
942             rr::FragmentPacket &packet = packets[packetNdx];
943 
944             for (int fragNdx = 0; fragNdx < 4; ++fragNdx)
945                 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0,
946                                         rr::readVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx));
947         }
948     }
949 };
950 
renderReference(const tcu::PixelBufferAccess & dst,const int numVertices,const uint16_t * const indices,const tcu::Vec4 * const positions,const tcu::Vec4 * const colors,const int subpixelBits)951 void VertexIDCase::renderReference(const tcu::PixelBufferAccess &dst, const int numVertices,
952                                    const uint16_t *const indices, const tcu::Vec4 *const positions,
953                                    const tcu::Vec4 *const colors, const int subpixelBits)
954 {
955     const rr::Renderer referenceRenderer;
956     const rr::RenderState referenceState(
957         (rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst)), subpixelBits);
958     const rr::RenderTarget referenceTarget(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst));
959     const VertexIDReferenceShader referenceShader;
960     rr::VertexAttrib attribs[2];
961 
962     attribs[0].type            = rr::VERTEXATTRIBTYPE_FLOAT;
963     attribs[0].size            = 4;
964     attribs[0].stride          = 0;
965     attribs[0].instanceDivisor = 0;
966     attribs[0].pointer         = positions;
967 
968     attribs[1].type            = rr::VERTEXATTRIBTYPE_FLOAT;
969     attribs[1].size            = 4;
970     attribs[1].stride          = 0;
971     attribs[1].instanceDivisor = 0;
972     attribs[1].pointer         = colors;
973 
974     referenceRenderer.draw(
975         rr::DrawCommand(referenceState, referenceTarget, rr::Program(&referenceShader, &referenceShader), 2, attribs,
976                         rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, numVertices, rr::DrawIndices(indices))));
977 }
978 
iterate(void)979 VertexIDCase::IterateResult VertexIDCase::iterate(void)
980 {
981     const glw::Functions &gl = m_context.getRenderContext().getFunctions();
982     const int width          = m_context.getRenderTarget().getWidth();
983     const int height         = m_context.getRenderTarget().getHeight();
984     const int viewportW      = m_viewportW;
985     const int viewportH      = m_viewportH;
986 
987     const float threshold = 0.02f;
988 
989     de::Random rnd(0xcf23ab1 ^ deInt32Hash(m_iterNdx));
990     tcu::Surface refImg(viewportW, viewportH);
991     tcu::Surface testImg(viewportW, viewportH);
992 
993     const int viewportX = rnd.getInt(0, width - viewportW);
994     const int viewportY = rnd.getInt(0, height - viewportH);
995 
996     const int posLoc    = gl.getAttribLocation(m_program->getProgram(), "a_position");
997     const int colorsLoc = gl.getUniformLocation(m_program->getProgram(), "u_colors[0]");
998     const tcu::Vec4 clearColor(0.0f, 0.0f, 0.0f, 1.0f);
999 
1000     // Setup common state.
1001     gl.viewport(viewportX, viewportY, viewportW, viewportH);
1002     gl.useProgram(m_program->getProgram());
1003     gl.bindBuffer(GL_ARRAY_BUFFER, m_positionBuffer);
1004     gl.enableVertexAttribArray(posLoc);
1005     gl.vertexAttribPointer(posLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL);
1006     gl.uniform4fv(colorsLoc, (int)m_colors.size(), (const float *)&m_colors[0]);
1007 
1008     // Clear render target to black.
1009     gl.clearColor(clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w());
1010     gl.clear(GL_COLOR_BUFFER_BIT);
1011 
1012     tcu::clear(refImg.getAccess(), clearColor);
1013 
1014     int subpixelBits = 0;
1015     gl.getIntegerv(GL_SUBPIXEL_BITS, &subpixelBits);
1016 
1017     if (m_iterNdx == 0)
1018     {
1019         tcu::ScopedLogSection logSection(m_testCtx.getLog(), "Iter0", "glDrawArrays()");
1020         vector<uint16_t> indices(m_positions.size());
1021 
1022         gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size() * sizeof(tcu::Vec4)), &m_positions[0], GL_DYNAMIC_DRAW);
1023         gl.drawArrays(GL_TRIANGLES, 0, (int)m_positions.size());
1024 
1025         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1026         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1027 
1028         // Reference indices
1029         for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1030             indices[ndx] = (uint16_t)ndx;
1031 
1032         renderReference(refImg.getAccess(), (int)m_positions.size(), &indices[0], &m_positions[0], &m_colors[0],
1033                         subpixelBits);
1034     }
1035     else if (m_iterNdx == 1)
1036     {
1037         tcu::ScopedLogSection logSection(m_testCtx.getLog(), "Iter1", "glDrawElements(), indices in client-side array");
1038         vector<uint16_t> indices(m_positions.size());
1039         vector<tcu::Vec4> mappedPos(m_positions.size());
1040 
1041         // Compute initial indices and suffle
1042         for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1043             indices[ndx] = (uint16_t)ndx;
1044         rnd.shuffle(indices.begin(), indices.end());
1045 
1046         // Use indices to re-map positions.
1047         for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1048             mappedPos[indices[ndx]] = m_positions[ndx];
1049 
1050         gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size() * sizeof(tcu::Vec4)), &mappedPos[0], GL_DYNAMIC_DRAW);
1051         gl.drawElements(GL_TRIANGLES, (int)indices.size(), GL_UNSIGNED_SHORT, &indices[0]);
1052 
1053         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1054         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1055 
1056         renderReference(refImg.getAccess(), (int)indices.size(), &indices[0], &mappedPos[0], &m_colors[0],
1057                         subpixelBits);
1058     }
1059     else if (m_iterNdx == 2)
1060     {
1061         tcu::ScopedLogSection logSection(m_testCtx.getLog(), "Iter2", "glDrawElements(), indices in buffer");
1062         vector<uint16_t> indices(m_positions.size());
1063         vector<tcu::Vec4> mappedPos(m_positions.size());
1064 
1065         // Compute initial indices and suffle
1066         for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1067             indices[ndx] = (uint16_t)ndx;
1068         rnd.shuffle(indices.begin(), indices.end());
1069 
1070         // Use indices to re-map positions.
1071         for (int ndx = 0; ndx < (int)indices.size(); ndx++)
1072             mappedPos[indices[ndx]] = m_positions[ndx];
1073 
1074         gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer);
1075         gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size() * sizeof(uint16_t)), &indices[0], GL_DYNAMIC_DRAW);
1076 
1077         gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size() * sizeof(tcu::Vec4)), &mappedPos[0], GL_DYNAMIC_DRAW);
1078         gl.drawElements(GL_TRIANGLES, (int)indices.size(), GL_UNSIGNED_SHORT, DE_NULL);
1079 
1080         glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess());
1081         GLU_EXPECT_NO_ERROR(gl.getError(), "Draw");
1082 
1083         tcu::clear(refImg.getAccess(), clearColor);
1084         renderReference(refImg.getAccess(), (int)indices.size(), &indices[0], &mappedPos[0], &m_colors[0],
1085                         subpixelBits);
1086     }
1087     else
1088         DE_ASSERT(false);
1089 
1090     if (!tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", refImg, testImg, threshold,
1091                            tcu::COMPARE_LOG_RESULT))
1092         m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed");
1093 
1094     m_iterNdx += 1;
1095     return (m_iterNdx < 3) ? CONTINUE : STOP;
1096 }
1097 
ShaderBuiltinVarTests(Context & context)1098 ShaderBuiltinVarTests::ShaderBuiltinVarTests(Context &context)
1099     : TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests")
1100 {
1101 }
1102 
~ShaderBuiltinVarTests(void)1103 ShaderBuiltinVarTests::~ShaderBuiltinVarTests(void)
1104 {
1105 }
1106 
init(void)1107 void ShaderBuiltinVarTests::init(void)
1108 {
1109     // Builtin constants.
1110 
1111     static const struct
1112     {
1113         const char *caseName;
1114         const char *varName;
1115         ShaderBuiltinConstantCase::GetConstantValueFunc getValue;
1116     } builtinConstants[] = {
1117         // GLES 2.
1118 
1119         {"max_vertex_attribs", "gl_MaxVertexAttribs", getInteger<GL_MAX_VERTEX_ATTRIBS>},
1120         {"max_vertex_uniform_vectors", "gl_MaxVertexUniformVectors", getInteger<GL_MAX_VERTEX_UNIFORM_VECTORS>},
1121         {"max_fragment_uniform_vectors", "gl_MaxFragmentUniformVectors", getInteger<GL_MAX_FRAGMENT_UNIFORM_VECTORS>},
1122         {"max_texture_image_units", "gl_MaxTextureImageUnits", getInteger<GL_MAX_TEXTURE_IMAGE_UNITS>},
1123         {"max_vertex_texture_image_units", "gl_MaxVertexTextureImageUnits",
1124          getInteger<GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS>},
1125         {"max_combined_texture_image_units", "gl_MaxCombinedTextureImageUnits",
1126          getInteger<GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS>},
1127         {"max_draw_buffers", "gl_MaxDrawBuffers", getInteger<GL_MAX_DRAW_BUFFERS>},
1128 
1129         // GLES 3.
1130 
1131         {"max_vertex_output_vectors", "gl_MaxVertexOutputVectors",
1132          getVectorsFromComps<GL_MAX_VERTEX_OUTPUT_COMPONENTS>},
1133         {"max_fragment_input_vectors", "gl_MaxFragmentInputVectors",
1134          getVectorsFromComps<GL_MAX_FRAGMENT_INPUT_COMPONENTS>},
1135         {"min_program_texel_offset", "gl_MinProgramTexelOffset", getInteger<GL_MIN_PROGRAM_TEXEL_OFFSET>},
1136         {"max_program_texel_offset", "gl_MaxProgramTexelOffset", getInteger<GL_MAX_PROGRAM_TEXEL_OFFSET>}};
1137 
1138     for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtinConstants); ndx++)
1139     {
1140         const char *const caseName                                     = builtinConstants[ndx].caseName;
1141         const char *const varName                                      = builtinConstants[ndx].varName;
1142         const ShaderBuiltinConstantCase::GetConstantValueFunc getValue = builtinConstants[ndx].getValue;
1143 
1144         addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_vertex").c_str(), varName, varName,
1145                                                getValue, glu::SHADERTYPE_VERTEX));
1146         addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_fragment").c_str(), varName, varName,
1147                                                getValue, glu::SHADERTYPE_FRAGMENT));
1148     }
1149 
1150     addChild(new ShaderDepthRangeTest(m_context, "depth_range_vertex", "gl_DepthRange", true));
1151     addChild(new ShaderDepthRangeTest(m_context, "depth_range_fragment", "gl_DepthRange", false));
1152 
1153     // Vertex shader builtin variables.
1154     addChild(new VertexIDCase(m_context));
1155     // \todo [2013-03-20 pyry] gl_InstanceID -- tested in instancing tests quite thoroughly.
1156 
1157     // Fragment shader builtin variables.
1158 
1159     addChild(new FragCoordXYZCase(m_context));
1160     addChild(new FragCoordWCase(m_context));
1161     addChild(new PointCoordCase(m_context));
1162     addChild(new FrontFacingCase(m_context));
1163 }
1164 
1165 } // namespace Functional
1166 } // namespace gles3
1167 } // namespace deqp
1168