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