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 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> 66 static int getInteger (const glw::Functions& gl) 67 { 68 return getInteger(gl, Pname); 69 } 70 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> 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 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 110 ShaderBuiltinConstantCase::~ShaderBuiltinConstantCase (void) 111 { 112 } 113 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 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 { 165 DepthRangeParams (void) 166 : zNear (0.0f) 167 , zFar (1.0f) 168 { 169 } 170 171 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: 184 DepthRangeEvaluator (const DepthRangeParams& params) 185 : m_params(params) 186 { 187 } 188 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: 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 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 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: 288 FragCoordXYZCase (Context& context) 289 : TestCase(context, "fragcoord_xyz", "gl_FragCoord.xyz Test") 290 { 291 } 292 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 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: 385 FragCoordWCase (Context& context) 386 : TestCase(context, "fragcoord_w", "gl_FragCoord.w Test") 387 { 388 } 389 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: 475 PointCoordCase (Context& context) 476 : TestCase(context, "pointcoord", "gl_PointCoord Test") 477 { 478 } 479 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: 595 FrontFacingCase (Context& context) 596 : TestCase(context, "frontfacing", "gl_FrontFacing Test") 597 { 598 } 599 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.frontFace(GL_CCW); 658 659 gl.viewport(viewportX, viewportY, width/2, height/2); 660 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding, 661 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0])); 662 663 gl.viewport(viewportX + width/2, viewportY, width-width/2, height/2); 664 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding, 665 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0])); 666 667 gl.frontFace(GL_CW); 668 669 gl.viewport(viewportX, viewportY + height/2, width/2, height-height/2); 670 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding, 671 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCCW), &indicesCCW[0])); 672 673 gl.viewport(viewportX + width/2, viewportY + height/2, width-width/2, height-height/2); 674 glu::draw(m_context.getRenderContext(), program.getProgram(), 1, &posBinding, 675 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indicesCW), &indicesCW[0])); 676 677 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess()); 678 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 679 } 680 681 // Draw reference 682 { 683 for(int y = 0; y < refImg.getHeight() / 2; y++) 684 for(int x = 0; x < refImg.getWidth() / 2; x++) 685 refImg.setPixel(x, y, tcu::RGBA::green()); 686 687 for(int y = 0; y < refImg.getHeight() / 2; y++) 688 for(int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++) 689 refImg.setPixel(x, y, tcu::RGBA::blue()); 690 691 for(int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++) 692 for(int x = 0; x < refImg.getWidth() / 2; x++) 693 refImg.setPixel(x, y, tcu::RGBA::blue()); 694 695 for(int y = refImg.getHeight() / 2; y < refImg.getHeight(); y++) 696 for(int x = refImg.getWidth() / 2; x < refImg.getWidth(); x++) 697 refImg.setPixel(x, y, tcu::RGBA::green()); 698 } 699 700 // Compare 701 { 702 bool isOk = tcu::pixelThresholdCompare(log, "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT); 703 m_testCtx.setTestResult(isOk ? QP_TEST_RESULT_PASS : QP_TEST_RESULT_FAIL, 704 isOk ? "Pass" : "Image comparison failed"); 705 } 706 707 return STOP; 708 } 709 }; 710 711 // VertexIDCase 712 713 class VertexIDCase : public TestCase 714 { 715 public: 716 VertexIDCase (Context& context); 717 ~VertexIDCase (void); 718 719 void init (void); 720 void deinit (void); 721 IterateResult iterate (void); 722 723 private: 724 enum 725 { 726 MAX_VERTICES = 8*3 //!< 8 triangles, totals 24 vertices 727 }; 728 729 void renderReference (const tcu::PixelBufferAccess& dst, const int numVertices, const deUint16* const indices, const tcu::Vec4* const positions, const tcu::Vec4* const colors); 730 731 glu::ShaderProgram* m_program; 732 deUint32 m_positionBuffer; 733 deUint32 m_elementBuffer; 734 735 vector<tcu::Vec4> m_positions; 736 vector<tcu::Vec4> m_colors; 737 int m_viewportW; 738 int m_viewportH; 739 740 int m_iterNdx; 741 }; 742 743 VertexIDCase::VertexIDCase (Context& context) 744 : TestCase (context, "vertex_id", "gl_VertexID Test") 745 , m_program (DE_NULL) 746 , m_positionBuffer (0) 747 , m_elementBuffer (0) 748 , m_viewportW (0) 749 , m_viewportH (0) 750 , m_iterNdx (0) 751 { 752 } 753 754 VertexIDCase::~VertexIDCase (void) 755 { 756 VertexIDCase::deinit(); 757 } 758 759 void VertexIDCase::init (void) 760 { 761 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 762 const int width = m_context.getRenderTarget().getWidth(); 763 const int height = m_context.getRenderTarget().getHeight(); 764 765 const int quadWidth = 32; 766 const int quadHeight = 32; 767 768 if (width < quadWidth) 769 throw tcu::NotSupportedError("Too small render target"); 770 771 const int maxQuadsX = width/quadWidth; 772 const int numVertices = MAX_VERTICES; 773 774 const int numQuads = numVertices/6 + (numVertices%6 != 0 ? 1 : 0); 775 const int viewportW = de::min(numQuads, maxQuadsX)*quadWidth; 776 const int viewportH = (numQuads/maxQuadsX + (numQuads%maxQuadsX != 0 ? 1 : 0))*quadHeight; 777 778 if (viewportH > height) 779 throw tcu::NotSupportedError("Too small render target"); 780 781 DE_ASSERT(viewportW <= width && viewportH <= height); 782 783 DE_ASSERT(!m_program); 784 m_program = new glu::ShaderProgram(m_context.getRenderContext(), glu::makeVtxFragSources( 785 "#version 300 es\n" 786 "in highp vec4 a_position;\n" 787 "out mediump vec4 v_color;\n" 788 "uniform highp vec4 u_colors[24];\n" 789 "void main (void)\n" 790 "{\n" 791 " gl_Position = a_position;\n" 792 " v_color = u_colors[gl_VertexID];\n" 793 "}\n", 794 795 "#version 300 es\n" 796 "in mediump vec4 v_color;\n" 797 "layout(location = 0) out mediump vec4 o_color;\n" 798 "void main (void)\n" 799 "{\n" 800 " o_color = v_color;\n" 801 "}\n")); 802 803 m_testCtx.getLog() << *m_program; 804 805 if (!m_program->isOk()) 806 { 807 delete m_program; 808 m_program = DE_NULL; 809 throw tcu::TestError("Compile failed"); 810 } 811 812 gl.genBuffers(1, &m_positionBuffer); 813 gl.genBuffers(1, &m_elementBuffer); 814 815 // Set colors (in dynamic memory to save static data space). 816 m_colors.resize(numVertices); 817 m_colors[ 0] = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f); 818 m_colors[ 1] = tcu::Vec4(0.5f, 1.0f, 0.5f, 1.0f); 819 m_colors[ 2] = tcu::Vec4(0.0f, 0.5f, 1.0f, 1.0f); 820 m_colors[ 3] = tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f); 821 m_colors[ 4] = tcu::Vec4(0.0f, 1.0f, 1.0f, 1.0f); 822 m_colors[ 5] = tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f); 823 m_colors[ 6] = tcu::Vec4(0.5f, 0.0f, 1.0f, 1.0f); 824 m_colors[ 7] = tcu::Vec4(0.5f, 0.0f, 0.5f, 1.0f); 825 m_colors[ 8] = tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f); 826 m_colors[ 9] = tcu::Vec4(0.5f, 1.0f, 0.0f, 1.0f); 827 m_colors[10] = tcu::Vec4(0.0f, 0.5f, 0.0f, 1.0f); 828 m_colors[11] = tcu::Vec4(0.5f, 1.0f, 1.0f, 1.0f); 829 m_colors[12] = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f); 830 m_colors[13] = tcu::Vec4(1.0f, 0.0f, 0.5f, 1.0f); 831 m_colors[14] = tcu::Vec4(0.0f, 0.5f, 0.5f, 1.0f); 832 m_colors[15] = tcu::Vec4(1.0f, 1.0f, 0.5f, 1.0f); 833 m_colors[16] = tcu::Vec4(1.0f, 0.0f, 1.0f, 1.0f); 834 m_colors[17] = tcu::Vec4(1.0f, 0.5f, 0.0f, 1.0f); 835 m_colors[18] = tcu::Vec4(0.0f, 1.0f, 0.5f, 1.0f); 836 m_colors[19] = tcu::Vec4(1.0f, 0.5f, 1.0f, 1.0f); 837 m_colors[20] = tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f); 838 m_colors[21] = tcu::Vec4(1.0f, 0.5f, 0.5f, 1.0f); 839 m_colors[22] = tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f); 840 m_colors[23] = tcu::Vec4(1.0f, 1.0f, 1.0f, 1.0f); 841 842 // Compute positions. 843 m_positions.resize(numVertices); 844 DE_ASSERT(numVertices%3 == 0); 845 for (int vtxNdx = 0; vtxNdx < numVertices; vtxNdx += 3) 846 { 847 const float h = 2.0f * float(quadHeight)/float(viewportH); 848 const float w = 2.0f * float(quadWidth)/float(viewportW); 849 850 const int triNdx = vtxNdx/3; 851 const int quadNdx = triNdx/2; 852 const int quadY = quadNdx/maxQuadsX; 853 const int quadX = quadNdx%maxQuadsX; 854 855 const float x0 = -1.0f + float(quadX)*w; 856 const float y0 = -1.0f + float(quadY)*h; 857 858 if (triNdx%2 == 0) 859 { 860 m_positions[vtxNdx+0] = tcu::Vec4(x0, y0, 0.0f, 1.0f); 861 m_positions[vtxNdx+1] = tcu::Vec4(x0+w, y0+h, 0.0f, 1.0f); 862 m_positions[vtxNdx+2] = tcu::Vec4(x0, y0+h, 0.0f, 1.0f); 863 } 864 else 865 { 866 m_positions[vtxNdx+0] = tcu::Vec4(x0+w, y0+h, 0.0f, 1.0f); 867 m_positions[vtxNdx+1] = tcu::Vec4(x0, y0, 0.0f, 1.0f); 868 m_positions[vtxNdx+2] = tcu::Vec4(x0+w, y0, 0.0f, 1.0f); 869 } 870 } 871 872 m_viewportW = viewportW; 873 m_viewportH = viewportH; 874 m_iterNdx = 0; 875 876 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 877 } 878 879 void VertexIDCase::deinit (void) 880 { 881 delete m_program; 882 m_program = DE_NULL; 883 884 if (m_positionBuffer) 885 { 886 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_positionBuffer); 887 m_positionBuffer = 0; 888 } 889 890 if (m_elementBuffer) 891 { 892 m_context.getRenderContext().getFunctions().deleteBuffers(1, &m_elementBuffer); 893 m_elementBuffer = 0; 894 } 895 896 m_positions.clear(); 897 m_colors.clear(); 898 } 899 900 class VertexIDReferenceShader : public rr::VertexShader, public rr::FragmentShader 901 { 902 public: 903 enum 904 { 905 VARYINGLOC_COLOR = 0 906 }; 907 908 VertexIDReferenceShader () 909 : rr::VertexShader (2, 1) // color and pos in => color out 910 , rr::FragmentShader(1, 1) // color in => color out 911 { 912 this->rr::VertexShader::m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 913 this->rr::VertexShader::m_inputs[1].type = rr::GENERICVECTYPE_FLOAT; 914 915 this->rr::VertexShader::m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 916 this->rr::VertexShader::m_outputs[0].flatshade = false; 917 918 this->rr::FragmentShader::m_inputs[0].type = rr::GENERICVECTYPE_FLOAT; 919 this->rr::FragmentShader::m_inputs[0].flatshade = false; 920 921 this->rr::FragmentShader::m_outputs[0].type = rr::GENERICVECTYPE_FLOAT; 922 } 923 924 void shadeVertices (const rr::VertexAttrib* inputs, rr::VertexPacket* const* packets, const int numPackets) const 925 { 926 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 927 { 928 const int positionAttrLoc = 0; 929 const int colorAttrLoc = 1; 930 931 rr::VertexPacket& packet = *packets[packetNdx]; 932 933 // Transform to position 934 packet.position = rr::readVertexAttribFloat(inputs[positionAttrLoc], packet.instanceNdx, packet.vertexNdx); 935 936 // Pass color to FS 937 packet.outputs[VARYINGLOC_COLOR] = rr::readVertexAttribFloat(inputs[colorAttrLoc], packet.instanceNdx, packet.vertexNdx); 938 } 939 } 940 941 void shadeFragments (rr::FragmentPacket* packets, const int numPackets, const rr::FragmentShadingContext& context) const 942 { 943 for (int packetNdx = 0; packetNdx < numPackets; ++packetNdx) 944 { 945 rr::FragmentPacket& packet = packets[packetNdx]; 946 947 for (int fragNdx = 0; fragNdx < 4; ++fragNdx) 948 rr::writeFragmentOutput(context, packetNdx, fragNdx, 0, rr::readVarying<float>(packet, context, VARYINGLOC_COLOR, fragNdx)); 949 } 950 } 951 }; 952 953 void VertexIDCase::renderReference (const tcu::PixelBufferAccess& dst, const int numVertices, const deUint16* const indices, const tcu::Vec4* const positions, const tcu::Vec4* const colors) 954 { 955 const rr::Renderer referenceRenderer; 956 const rr::RenderState referenceState ((rr::ViewportState)(rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst))); 957 const rr::RenderTarget referenceTarget (rr::MultisamplePixelBufferAccess::fromSinglesampleAccess(dst)); 958 const VertexIDReferenceShader referenceShader; 959 rr::VertexAttrib attribs[2]; 960 961 attribs[0].type = rr::VERTEXATTRIBTYPE_FLOAT; 962 attribs[0].size = 4; 963 attribs[0].stride = 0; 964 attribs[0].instanceDivisor = 0; 965 attribs[0].pointer = positions; 966 967 attribs[1].type = rr::VERTEXATTRIBTYPE_FLOAT; 968 attribs[1].size = 4; 969 attribs[1].stride = 0; 970 attribs[1].instanceDivisor = 0; 971 attribs[1].pointer = colors; 972 973 referenceRenderer.draw( 974 rr::DrawCommand( 975 referenceState, 976 referenceTarget, 977 rr::Program(&referenceShader, &referenceShader), 978 2, 979 attribs, 980 rr::PrimitiveList(rr::PRIMITIVETYPE_TRIANGLES, numVertices, rr::DrawIndices(indices)))); 981 } 982 983 VertexIDCase::IterateResult VertexIDCase::iterate (void) 984 { 985 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 986 const int width = m_context.getRenderTarget().getWidth(); 987 const int height = m_context.getRenderTarget().getHeight(); 988 const int viewportW = m_viewportW; 989 const int viewportH = m_viewportH; 990 991 const float threshold = 0.02f; 992 993 de::Random rnd (0xcf23ab1 ^ deInt32Hash(m_iterNdx)); 994 tcu::Surface refImg (viewportW, viewportH); 995 tcu::Surface testImg (viewportW, viewportH); 996 997 const int viewportX = rnd.getInt(0, width-viewportW); 998 const int viewportY = rnd.getInt(0, height-viewportH); 999 1000 const int posLoc = gl.getAttribLocation(m_program->getProgram(), "a_position"); 1001 const int colorsLoc = gl.getUniformLocation(m_program->getProgram(), "u_colors[0]"); 1002 const tcu::Vec4 clearColor (0.0f, 0.0f, 0.0f, 1.0f); 1003 1004 // Setup common state. 1005 gl.viewport (viewportX, viewportY, viewportW, viewportH); 1006 gl.useProgram (m_program->getProgram()); 1007 gl.bindBuffer (GL_ARRAY_BUFFER, m_positionBuffer); 1008 gl.enableVertexAttribArray (posLoc); 1009 gl.vertexAttribPointer (posLoc, 4, GL_FLOAT, GL_FALSE, 0, DE_NULL); 1010 gl.uniform4fv (colorsLoc, (int)m_colors.size(), (const float*)&m_colors[0]); 1011 1012 // Clear render target to black. 1013 gl.clearColor (clearColor.x(), clearColor.y(), clearColor.z(), clearColor.w()); 1014 gl.clear (GL_COLOR_BUFFER_BIT); 1015 1016 tcu::clear(refImg.getAccess(), clearColor); 1017 1018 if (m_iterNdx == 0) 1019 { 1020 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter0", "glDrawArrays()"); 1021 vector<deUint16> indices (m_positions.size()); 1022 1023 gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size()*sizeof(tcu::Vec4)), &m_positions[0], GL_DYNAMIC_DRAW); 1024 gl.drawArrays(GL_TRIANGLES, 0, (int)m_positions.size()); 1025 1026 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess()); 1027 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 1028 1029 // Reference indices 1030 for (int ndx = 0; ndx < (int)indices.size(); ndx++) 1031 indices[ndx] = (deUint16)ndx; 1032 1033 renderReference(refImg.getAccess(), (int)m_positions.size(), &indices[0], &m_positions[0], &m_colors[0]); 1034 } 1035 else if (m_iterNdx == 1) 1036 { 1037 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter1", "glDrawElements(), indices in client-side array"); 1038 vector<deUint16> 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] = (deUint16)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 } 1058 else if (m_iterNdx == 2) 1059 { 1060 tcu::ScopedLogSection logSection (m_testCtx.getLog(), "Iter2", "glDrawElements(), indices in buffer"); 1061 vector<deUint16> indices (m_positions.size()); 1062 vector<tcu::Vec4> mappedPos (m_positions.size()); 1063 1064 // Compute initial indices and suffle 1065 for (int ndx = 0; ndx < (int)indices.size(); ndx++) 1066 indices[ndx] = (deUint16)ndx; 1067 rnd.shuffle(indices.begin(), indices.end()); 1068 1069 // Use indices to re-map positions. 1070 for (int ndx = 0; ndx < (int)indices.size(); ndx++) 1071 mappedPos[indices[ndx]] = m_positions[ndx]; 1072 1073 gl.bindBuffer(GL_ELEMENT_ARRAY_BUFFER, m_elementBuffer); 1074 gl.bufferData(GL_ELEMENT_ARRAY_BUFFER, (int)(indices.size()*sizeof(deUint16)), &indices[0], GL_DYNAMIC_DRAW); 1075 1076 gl.bufferData(GL_ARRAY_BUFFER, (int)(m_positions.size()*sizeof(tcu::Vec4)), &mappedPos[0], GL_DYNAMIC_DRAW); 1077 gl.drawElements(GL_TRIANGLES, (int)indices.size(), GL_UNSIGNED_SHORT, DE_NULL); 1078 1079 glu::readPixels(m_context.getRenderContext(), viewportX, viewportY, testImg.getAccess()); 1080 GLU_EXPECT_NO_ERROR(gl.getError(), "Draw"); 1081 1082 tcu::clear(refImg.getAccess(), clearColor); 1083 renderReference(refImg.getAccess(), (int)indices.size(), &indices[0], &mappedPos[0], &m_colors[0]); 1084 } 1085 else 1086 DE_ASSERT(false); 1087 1088 if (!tcu::fuzzyCompare(m_testCtx.getLog(), "Result", "Image comparison result", refImg, testImg, threshold, tcu::COMPARE_LOG_RESULT)) 1089 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image comparison failed"); 1090 1091 m_iterNdx += 1; 1092 return (m_iterNdx < 3) ? CONTINUE : STOP; 1093 } 1094 1095 ShaderBuiltinVarTests::ShaderBuiltinVarTests (Context& context) 1096 : TestCaseGroup(context, "builtin_variable", "Built-in Variable Tests") 1097 { 1098 } 1099 1100 ShaderBuiltinVarTests::~ShaderBuiltinVarTests (void) 1101 { 1102 } 1103 1104 void ShaderBuiltinVarTests::init (void) 1105 { 1106 // Builtin constants. 1107 1108 static const struct 1109 { 1110 const char* caseName; 1111 const char* varName; 1112 ShaderBuiltinConstantCase::GetConstantValueFunc getValue; 1113 } builtinConstants[] = 1114 { 1115 // GLES 2. 1116 1117 { "max_vertex_attribs", "gl_MaxVertexAttribs", getInteger<GL_MAX_VERTEX_ATTRIBS> }, 1118 { "max_vertex_uniform_vectors", "gl_MaxVertexUniformVectors", getInteger<GL_MAX_VERTEX_UNIFORM_VECTORS> }, 1119 { "max_fragment_uniform_vectors", "gl_MaxFragmentUniformVectors", getInteger<GL_MAX_FRAGMENT_UNIFORM_VECTORS> }, 1120 { "max_texture_image_units", "gl_MaxTextureImageUnits", getInteger<GL_MAX_TEXTURE_IMAGE_UNITS> }, 1121 { "max_vertex_texture_image_units", "gl_MaxVertexTextureImageUnits", getInteger<GL_MAX_VERTEX_TEXTURE_IMAGE_UNITS> }, 1122 { "max_combined_texture_image_units", "gl_MaxCombinedTextureImageUnits", getInteger<GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS> }, 1123 { "max_draw_buffers", "gl_MaxDrawBuffers", getInteger<GL_MAX_DRAW_BUFFERS> }, 1124 1125 // GLES 3. 1126 1127 { "max_vertex_output_vectors", "gl_MaxVertexOutputVectors", getVectorsFromComps<GL_MAX_VERTEX_OUTPUT_COMPONENTS> }, 1128 { "max_fragment_input_vectors", "gl_MaxFragmentInputVectors", getVectorsFromComps<GL_MAX_FRAGMENT_INPUT_COMPONENTS> }, 1129 { "min_program_texel_offset", "gl_MinProgramTexelOffset", getInteger<GL_MIN_PROGRAM_TEXEL_OFFSET> }, 1130 { "max_program_texel_offset", "gl_MaxProgramTexelOffset", getInteger<GL_MAX_PROGRAM_TEXEL_OFFSET> } 1131 }; 1132 1133 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(builtinConstants); ndx++) 1134 { 1135 const char* const caseName = builtinConstants[ndx].caseName; 1136 const char* const varName = builtinConstants[ndx].varName; 1137 const ShaderBuiltinConstantCase::GetConstantValueFunc getValue = builtinConstants[ndx].getValue; 1138 1139 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_vertex").c_str(), varName, varName, getValue, glu::SHADERTYPE_VERTEX)); 1140 addChild(new ShaderBuiltinConstantCase(m_context, (string(caseName) + "_fragment").c_str(), varName, varName, getValue, glu::SHADERTYPE_FRAGMENT)); 1141 } 1142 1143 addChild(new ShaderDepthRangeTest(m_context, "depth_range_vertex", "gl_DepthRange", true)); 1144 addChild(new ShaderDepthRangeTest(m_context, "depth_range_fragment", "gl_DepthRange", false)); 1145 1146 // Vertex shader builtin variables. 1147 addChild(new VertexIDCase (m_context)); 1148 // \todo [2013-03-20 pyry] gl_InstanceID -- tested in instancing tests quite thoroughly. 1149 1150 // Fragment shader builtin variables. 1151 1152 addChild(new FragCoordXYZCase (m_context)); 1153 addChild(new FragCoordWCase (m_context)); 1154 addChild(new PointCoordCase (m_context)); 1155 addChild(new FrontFacingCase (m_context)); 1156 } 1157 1158 } // Functional 1159 } // gles3 1160 } // deqp 1161