1/*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 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 Multisample interpolation tests 22 *//*--------------------------------------------------------------------*/ 23 24#include "es31fShaderMultisampleInterpolationTests.hpp" 25#include "es31fMultisampleShaderRenderCase.hpp" 26#include "tcuTestLog.hpp" 27#include "tcuRGBA.hpp" 28#include "tcuSurface.hpp" 29#include "tcuStringTemplate.hpp" 30#include "tcuRenderTarget.hpp" 31#include "gluContextInfo.hpp" 32#include "gluShaderProgram.hpp" 33#include "gluRenderContext.hpp" 34#include "glwFunctions.hpp" 35#include "glwEnums.hpp" 36#include "deArrayUtil.hpp" 37#include "deStringUtil.hpp" 38#include "deMath.h" 39 40#include <map> 41 42namespace deqp 43{ 44namespace gles31 45{ 46namespace Functional 47{ 48namespace 49{ 50 51 52static bool verifyGreenImage (const tcu::Surface& image, tcu::TestLog& log) 53{ 54 bool error = false; 55 56 log << tcu::TestLog::Message << "Verifying result image, expecting green." << tcu::TestLog::EndMessage; 57 58 // all pixels must be green 59 60 for (int y = 0; y < image.getHeight(); ++y) 61 for (int x = 0; x < image.getWidth(); ++x) 62 { 63 const tcu::RGBA color = image.getPixel(x, y); 64 const int greenThreshold = 8; 65 66 if (color.getRed() > 0 || color.getGreen() < 255-greenThreshold || color.getBlue() > 0) 67 error = true; 68 } 69 70 if (error) 71 log << tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess()) 72 << tcu::TestLog::Message 73 << "Image verification failed." 74 << tcu::TestLog::EndMessage; 75 else 76 log << tcu::TestLog::Image("ResultImage", "Result Image", image.getAccess()) 77 << tcu::TestLog::Message 78 << "Image verification passed." 79 << tcu::TestLog::EndMessage; 80 81 return !error; 82} 83 84class MultisampleShadeCountRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 85{ 86public: 87 MultisampleShadeCountRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target); 88 virtual ~MultisampleShadeCountRenderCase (void); 89 90 void init (void); 91 92private: 93 enum 94 { 95 RENDER_SIZE = 128 96 }; 97 98 virtual std::string getIterationDescription (int iteration) const; 99 bool verifyImage (const tcu::Surface& resultImage); 100}; 101 102MultisampleShadeCountRenderCase::MultisampleShadeCountRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target) 103 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_PER_ITERATION_SHADER) 104{ 105 m_numIterations = -1; // must be set by deriving class 106} 107 108MultisampleShadeCountRenderCase::~MultisampleShadeCountRenderCase (void) 109{ 110} 111 112void MultisampleShadeCountRenderCase::init (void) 113{ 114 // requirements 115 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 116 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 117 118 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 119} 120 121std::string MultisampleShadeCountRenderCase::getIterationDescription (int iteration) const 122{ 123 // must be overriden 124 DE_UNREF(iteration); 125 DE_ASSERT(false); 126 return ""; 127} 128 129bool MultisampleShadeCountRenderCase::verifyImage (const tcu::Surface& resultImage) 130{ 131 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1); 132 const int numShadesRequired = (isSingleSampleTarget) ? (2) : (m_numTargetSamples + 1); 133 const int rareThreshold = 100; 134 int rareCount = 0; 135 std::map<deUint32, int> shadeFrequency; 136 137 m_testCtx.getLog() 138 << tcu::TestLog::Image("ResultImage", "Result Image", resultImage.getAccess()) 139 << tcu::TestLog::Message 140 << "Verifying image has (at least) " << numShadesRequired << " different shades.\n" 141 << "Excluding pixels with no full coverage (pixels on the shared edge of the triangle pair)." 142 << tcu::TestLog::EndMessage; 143 144 for (int y = 0; y < RENDER_SIZE; ++y) 145 for (int x = 0; x < RENDER_SIZE; ++x) 146 { 147 const tcu::RGBA color = resultImage.getPixel(x, y); 148 const deUint32 packed = ((deUint32)color.getRed()) + ((deUint32)color.getGreen() << 8) + ((deUint32)color.getGreen() << 16); 149 150 // on the triangle edge, skip 151 if (x == y) 152 continue; 153 154 if (shadeFrequency.find(packed) == shadeFrequency.end()) 155 shadeFrequency[packed] = 1; 156 else 157 shadeFrequency[packed] = shadeFrequency[packed] + 1; 158 } 159 160 for (std::map<deUint32, int>::const_iterator it = shadeFrequency.begin(); it != shadeFrequency.end(); ++it) 161 if (it->second < rareThreshold) 162 rareCount++; 163 164 m_testCtx.getLog() 165 << tcu::TestLog::Message 166 << "Found " << (int)shadeFrequency.size() << " different shades.\n" 167 << "\tRare (less than " << rareThreshold << " pixels): " << rareCount << "\n" 168 << "\tCommon: " << (int)shadeFrequency.size() - rareCount << "\n" 169 << tcu::TestLog::EndMessage; 170 171 if ((int)shadeFrequency.size() < numShadesRequired) 172 { 173 m_testCtx.getLog() << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage; 174 return false; 175 } 176 return true; 177} 178 179class SampleQualifierRenderCase : public MultisampleShadeCountRenderCase 180{ 181public: 182 SampleQualifierRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target); 183 ~SampleQualifierRenderCase (void); 184 185 void init (void); 186 187private: 188 std::string genVertexSource (int numTargetSamples) const; 189 std::string genFragmentSource (int numTargetSamples) const; 190 std::string getIterationDescription (int iteration) const; 191}; 192 193SampleQualifierRenderCase::SampleQualifierRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target) 194 : MultisampleShadeCountRenderCase(context, name, description, numSamples, target) 195{ 196 m_numIterations = 6; // float, vec2, .3, .4, array, struct 197} 198 199SampleQualifierRenderCase::~SampleQualifierRenderCase (void) 200{ 201} 202 203void SampleQualifierRenderCase::init (void) 204{ 205 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1); 206 207 // test purpose and expectations 208 if (isSingleSampleTarget) 209 { 210 m_testCtx.getLog() 211 << tcu::TestLog::Message 212 << "Verifying that a sample-qualified varying is given different values for different samples.\n" 213 << " Render high-frequency function, map result to black/white.\n" 214 << " => Resulting image image should contain both black and white pixels.\n" 215 << tcu::TestLog::EndMessage; 216 } 217 else 218 { 219 m_testCtx.getLog() 220 << tcu::TestLog::Message 221 << "Verifying that a sample-qualified varying is given different values for different samples.\n" 222 << " Render high-frequency function, map result to black/white.\n" 223 << " => Resulting image should contain n+1 shades of gray, n = sample count.\n" 224 << tcu::TestLog::EndMessage; 225 } 226 227 MultisampleShadeCountRenderCase::init(); 228} 229 230std::string SampleQualifierRenderCase::genVertexSource (int numTargetSamples) const 231{ 232 DE_UNREF(numTargetSamples); 233 234 std::ostringstream buf; 235 236 buf << "#version 310 es\n" 237 "#extension GL_OES_shader_multisample_interpolation : require\n" 238 "in highp vec4 a_position;\n"; 239 240 if (m_iteration == 0) 241 buf << "sample out highp float v_input;\n"; 242 else if (m_iteration == 1) 243 buf << "sample out highp vec2 v_input;\n"; 244 else if (m_iteration == 2) 245 buf << "sample out highp vec3 v_input;\n"; 246 else if (m_iteration == 3) 247 buf << "sample out highp vec4 v_input;\n"; 248 else if (m_iteration == 4) 249 buf << "sample out highp float[2] v_input;\n"; 250 else if (m_iteration == 5) 251 buf << "struct VaryingStruct { highp float a; highp float b; };\n" 252 "sample out VaryingStruct v_input;\n"; 253 else 254 DE_ASSERT(false); 255 256 buf << "void main (void)\n" 257 "{\n" 258 " gl_Position = a_position;\n"; 259 260 if (m_iteration == 0) 261 buf << " v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n"; 262 else if (m_iteration == 1) 263 buf << " v_input = a_position.xy;\n"; 264 else if (m_iteration == 2) 265 buf << " v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n"; 266 else if (m_iteration == 3) 267 buf << " v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n"; 268 else if (m_iteration == 4) 269 buf << " v_input[0] = a_position.x;\n" 270 " v_input[1] = a_position.y;\n"; 271 else if (m_iteration == 5) 272 buf << " v_input.a = a_position.x;\n" 273 " v_input.b = a_position.y;\n"; 274 else 275 DE_ASSERT(false); 276 277 buf << "}"; 278 279 return buf.str(); 280} 281 282std::string SampleQualifierRenderCase::genFragmentSource (int numTargetSamples) const 283{ 284 DE_UNREF(numTargetSamples); 285 286 std::ostringstream buf; 287 288 buf << "#version 310 es\n" 289 "#extension GL_OES_shader_multisample_interpolation : require\n"; 290 291 if (m_iteration == 0) 292 buf << "sample in highp float v_input;\n"; 293 else if (m_iteration == 1) 294 buf << "sample in highp vec2 v_input;\n"; 295 else if (m_iteration == 2) 296 buf << "sample in highp vec3 v_input;\n"; 297 else if (m_iteration == 3) 298 buf << "sample in highp vec4 v_input;\n"; 299 else if (m_iteration == 4) 300 buf << "sample in highp float[2] v_input;\n"; 301 else if (m_iteration == 5) 302 buf << "struct VaryingStruct { highp float a; highp float b; };\n" 303 "sample in VaryingStruct v_input;\n"; 304 else 305 DE_ASSERT(false); 306 307 buf << "layout(location = 0) out mediump vec4 fragColor;\n" 308 "void main (void)\n" 309 "{\n"; 310 311 if (m_iteration == 0) 312 buf << " highp float field = exp(v_input) + v_input*v_input;\n"; 313 else if (m_iteration == 1) 314 buf << " highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.xx, sin(3.1 * v_input.xy));\n"; 315 else if (m_iteration == 2) 316 buf << " highp float field = dot(v_input.xy, v_input.xy) + dot(21.0 * v_input.zx, sin(3.1 * v_input.zy));\n"; 317 else if (m_iteration == 3) 318 buf << " highp float field = dot(v_input.xy, v_input.zw) + dot(21.0 * v_input.zy, sin(3.1 * v_input.zw));\n"; 319 else if (m_iteration == 4) 320 buf << " highp float field = dot(vec2(v_input[0], v_input[1]), vec2(v_input[0], v_input[1])) + dot(21.0 * vec2(v_input[0]), sin(3.1 * vec2(v_input[0], v_input[1])));\n"; 321 else if (m_iteration == 5) 322 buf << " highp float field = dot(vec2(v_input.a, v_input.b), vec2(v_input.a, v_input.b)) + dot(21.0 * vec2(v_input.a), sin(3.1 * vec2(v_input.a, v_input.b)));\n"; 323 else 324 DE_ASSERT(false); 325 326 buf << " fragColor = vec4(1.0, 1.0, 1.0, 1.0);\n" 327 "\n" 328 " if (fract(field) > 0.5)\n" 329 " fragColor = vec4(0.0, 0.0, 0.0, 1.0);\n" 330 "}"; 331 332 return buf.str(); 333} 334 335std::string SampleQualifierRenderCase::getIterationDescription (int iteration) const 336{ 337 if (iteration == 0) 338 return "Test with float varying"; 339 else if (iteration == 1) 340 return "Test with vec2 varying"; 341 else if (iteration == 2) 342 return "Test with vec3 varying"; 343 else if (iteration == 3) 344 return "Test with vec4 varying"; 345 else if (iteration == 4) 346 return "Test with array varying"; 347 else if (iteration == 5) 348 return "Test with struct varying"; 349 350 DE_ASSERT(false); 351 return ""; 352} 353 354class InterpolateAtSampleRenderCase : public MultisampleShadeCountRenderCase 355{ 356public: 357 enum IndexingMode 358 { 359 INDEXING_STATIC, 360 INDEXING_DYNAMIC, 361 362 INDEXING_LAST 363 }; 364 InterpolateAtSampleRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode); 365 ~InterpolateAtSampleRenderCase (void); 366 367 void init (void); 368 void preDraw (void); 369 370private: 371 std::string genVertexSource (int numTargetSamples) const; 372 std::string genFragmentSource (int numTargetSamples) const; 373 std::string getIterationDescription (int iteration) const; 374 375 const IndexingMode m_indexMode; 376}; 377 378InterpolateAtSampleRenderCase::InterpolateAtSampleRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, IndexingMode mode) 379 : MultisampleShadeCountRenderCase (context, name, description, numSamples, target) 380 , m_indexMode (mode) 381{ 382 DE_ASSERT(mode < INDEXING_LAST); 383 384 m_numIterations = 5; // float, vec2, .3, .4, array 385} 386 387InterpolateAtSampleRenderCase::~InterpolateAtSampleRenderCase (void) 388{ 389} 390 391void InterpolateAtSampleRenderCase::init (void) 392{ 393 const bool isSingleSampleTarget = (m_renderTarget != TARGET_DEFAULT && m_numRequestedSamples == 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() <= 1); 394 395 // test purpose and expectations 396 if (isSingleSampleTarget) 397 { 398 m_testCtx.getLog() 399 << tcu::TestLog::Message 400 << "Verifying that a interpolateAtSample returns different values for different samples.\n" 401 << " Render high-frequency function, map result to black/white.\n" 402 << " => Resulting image image should contain both black and white pixels.\n" 403 << tcu::TestLog::EndMessage; 404 } 405 else 406 { 407 m_testCtx.getLog() 408 << tcu::TestLog::Message 409 << "Verifying that a interpolateAtSample returns different values for different samples.\n" 410 << " Render high-frequency function, map result to black/white.\n" 411 << " => Resulting image should contain n+1 shades of gray, n = sample count.\n" 412 << tcu::TestLog::EndMessage; 413 } 414 415 MultisampleShadeCountRenderCase::init(); 416} 417 418void InterpolateAtSampleRenderCase::preDraw (void) 419{ 420 if (m_indexMode == INDEXING_DYNAMIC) 421 { 422 const deInt32 range = m_numTargetSamples; 423 const deInt32 offset = 1; 424 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 425 const deInt32 offsetLoc = gl.getUniformLocation(m_program->getProgram(), "u_offset"); 426 const deInt32 rangeLoc = gl.getUniformLocation(m_program->getProgram(), "u_range"); 427 428 if (offsetLoc == -1) 429 throw tcu::TestError("Location of u_offset was -1"); 430 if (rangeLoc == -1) 431 throw tcu::TestError("Location of u_range was -1"); 432 433 gl.uniform1i(offsetLoc, 0); 434 gl.uniform1i(rangeLoc, m_numTargetSamples); 435 GLU_EXPECT_NO_ERROR(gl.getError(), "set uniforms"); 436 437 m_testCtx.getLog() 438 << tcu::TestLog::Message 439 << "Set u_offset = " << offset << "\n" 440 << "Set u_range = " << range 441 << tcu::TestLog::EndMessage; 442 } 443} 444 445std::string InterpolateAtSampleRenderCase::genVertexSource (int numTargetSamples) const 446{ 447 DE_UNREF(numTargetSamples); 448 449 std::ostringstream buf; 450 451 buf << "#version 310 es\n" 452 "in highp vec4 a_position;\n"; 453 454 if (m_iteration == 0) 455 buf << "out highp float v_input;\n"; 456 else if (m_iteration == 1) 457 buf << "out highp vec2 v_input;\n"; 458 else if (m_iteration == 2) 459 buf << "out highp vec3 v_input;\n"; 460 else if (m_iteration == 3) 461 buf << "out highp vec4 v_input;\n"; 462 else if (m_iteration == 4) 463 buf << "out highp vec2[2] v_input;\n"; 464 else 465 DE_ASSERT(false); 466 467 buf << "void main (void)\n" 468 "{\n" 469 " gl_Position = a_position;\n"; 470 471 if (m_iteration == 0) 472 buf << " v_input = a_position.x + exp(a_position.y) + step(0.9, a_position.x)*step(a_position.y, -0.9)*8.0;\n"; 473 else if (m_iteration == 1) 474 buf << " v_input = a_position.xy;\n"; 475 else if (m_iteration == 2) 476 buf << " v_input = vec3(a_position.xy, a_position.x * 2.0 - a_position.y);\n"; 477 else if (m_iteration == 3) 478 buf << " v_input = vec4(a_position.xy, a_position.x * 2.0 - a_position.y, a_position.x*a_position.y);\n"; 479 else if (m_iteration == 4) 480 buf << " v_input[0] = a_position.yx + vec2(0.5, 0.5);\n" 481 " v_input[1] = a_position.xy;\n"; 482 else 483 DE_ASSERT(false); 484 485 buf << "}"; 486 487 return buf.str(); 488} 489 490std::string InterpolateAtSampleRenderCase::genFragmentSource (int numTargetSamples) const 491{ 492 std::ostringstream buf; 493 494 buf << "#version 310 es\n" 495 "#extension GL_OES_shader_multisample_interpolation : require\n"; 496 497 if (m_iteration == 0) 498 buf << "in highp float v_input;\n"; 499 else if (m_iteration == 1) 500 buf << "in highp vec2 v_input;\n"; 501 else if (m_iteration == 2) 502 buf << "in highp vec3 v_input;\n"; 503 else if (m_iteration == 3) 504 buf << "in highp vec4 v_input;\n"; 505 else if (m_iteration == 4) 506 buf << "in highp vec2[2] v_input;\n"; 507 else 508 DE_ASSERT(false); 509 510 buf << "layout(location = 0) out mediump vec4 fragColor;\n"; 511 512 if (m_indexMode == INDEXING_DYNAMIC) 513 buf << "uniform highp int u_offset;\n" 514 "uniform highp int u_range;\n"; 515 516 buf << "void main (void)\n" 517 "{\n" 518 " mediump int coverage = 0;\n" 519 "\n"; 520 521 if (m_indexMode == INDEXING_STATIC) 522 { 523 for (int ndx = 0; ndx < numTargetSamples; ++ndx) 524 { 525 if (m_iteration == 0) 526 buf << " highp float sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n"; 527 else if (m_iteration == 1) 528 buf << " highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n"; 529 else if (m_iteration == 2) 530 buf << " highp vec3 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n"; 531 else if (m_iteration == 3) 532 buf << " highp vec4 sampleInput" << ndx << " = interpolateAtSample(v_input, " << ndx << ");\n"; 533 else if (m_iteration == 4) 534 buf << " highp vec2 sampleInput" << ndx << " = interpolateAtSample(v_input[1], " << ndx << ");\n"; 535 else 536 DE_ASSERT(false); 537 } 538 buf << "\n"; 539 540 for (int ndx = 0; ndx < numTargetSamples; ++ndx) 541 { 542 if (m_iteration == 0) 543 buf << " highp float field" << ndx << " = exp(sampleInput" << ndx << ") + sampleInput" << ndx << "*sampleInput" << ndx << ";\n"; 544 else if (m_iteration == 1 || m_iteration == 4) 545 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ", sampleInput" << ndx << ") + dot(21.0 * sampleInput" << ndx << ".xx, sin(3.1 * sampleInput" << ndx << "));\n"; 546 else if (m_iteration == 2) 547 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".xy) + dot(21.0 * sampleInput" << ndx << ".zx, sin(3.1 * sampleInput" << ndx << ".zy));\n"; 548 else if (m_iteration == 3) 549 buf << " highp float field" << ndx << " = dot(sampleInput" << ndx << ".xy, sampleInput" << ndx << ".zw) + dot(21.0 * sampleInput" << ndx << ".zy, sin(3.1 * sampleInput" << ndx << ".zw));\n"; 550 else 551 DE_ASSERT(false); 552 } 553 buf << "\n"; 554 555 for (int ndx = 0; ndx < numTargetSamples; ++ndx) 556 buf << " if (fract(field" << ndx << ") <= 0.5)\n" 557 " ++coverage;\n"; 558 } 559 else if (m_indexMode == INDEXING_DYNAMIC) 560 { 561 buf << " for (int ndx = 0; ndx < " << numTargetSamples << "; ++ndx)\n" 562 " {\n"; 563 564 if (m_iteration == 0) 565 buf << " highp float sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n"; 566 else if (m_iteration == 1) 567 buf << " highp vec2 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n"; 568 else if (m_iteration == 2) 569 buf << " highp vec3 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n"; 570 else if (m_iteration == 3) 571 buf << " highp vec4 sampleInput = interpolateAtSample(v_input, (u_offset + ndx) % u_range);\n"; 572 else if (m_iteration == 4) 573 buf << " highp vec2 sampleInput = interpolateAtSample(v_input[1], (u_offset + ndx) % u_range);\n"; 574 else 575 DE_ASSERT(false); 576 577 if (m_iteration == 0) 578 buf << " highp float field = exp(sampleInput) + sampleInput*sampleInput;\n"; 579 else if (m_iteration == 1 || m_iteration == 4) 580 buf << " highp float field = dot(sampleInput, sampleInput) + dot(21.0 * sampleInput.xx, sin(3.1 * sampleInput));\n"; 581 else if (m_iteration == 2) 582 buf << " highp float field = dot(sampleInput.xy, sampleInput.xy) + dot(21.0 * sampleInput.zx, sin(3.1 * sampleInput.zy));\n"; 583 else if (m_iteration == 3) 584 buf << " highp float field = dot(sampleInput.xy, sampleInput.zw) + dot(21.0 * sampleInput.zy, sin(3.1 * sampleInput.zw));\n"; 585 else 586 DE_ASSERT(false); 587 588 buf << " if (fract(field) <= 0.5)\n" 589 " ++coverage;\n" 590 " }\n"; 591 } 592 593 buf << " fragColor = vec4(vec3(float(coverage) / float(" << numTargetSamples << ")), 1.0);\n" 594 "}"; 595 596 return buf.str(); 597} 598 599std::string InterpolateAtSampleRenderCase::getIterationDescription (int iteration) const 600{ 601 if (iteration == 0) 602 return "Test with float varying"; 603 else if (iteration < 4) 604 return "Test with vec" + de::toString(iteration+1) + " varying"; 605 else if (iteration == 4) 606 return "Test with array varying"; 607 608 DE_ASSERT(false); 609 return ""; 610} 611 612class SingleSampleInterpolateAtSampleCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 613{ 614public: 615 enum SampleCase 616 { 617 SAMPLE_0 = 0, 618 SAMPLE_N, 619 620 SAMPLE_LAST 621 }; 622 623 SingleSampleInterpolateAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase); 624 virtual ~SingleSampleInterpolateAtSampleCase (void); 625 626 void init (void); 627 628private: 629 enum 630 { 631 RENDER_SIZE = 32 632 }; 633 634 std::string genVertexSource (int numTargetSamples) const; 635 std::string genFragmentSource (int numTargetSamples) const; 636 bool verifyImage (const tcu::Surface& resultImage); 637 638 const SampleCase m_sampleCase; 639}; 640 641SingleSampleInterpolateAtSampleCase::SingleSampleInterpolateAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, SampleCase sampleCase) 642 : MultisampleShaderRenderUtil::MultisampleRenderCase (context, name, description, numSamples, target, RENDER_SIZE) 643 , m_sampleCase (sampleCase) 644{ 645 DE_ASSERT(numSamples == 0); 646 DE_ASSERT(sampleCase < SAMPLE_LAST); 647} 648 649SingleSampleInterpolateAtSampleCase::~SingleSampleInterpolateAtSampleCase (void) 650{ 651} 652 653void SingleSampleInterpolateAtSampleCase::init (void) 654{ 655 // requirements 656 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 657 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 658 if (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1) 659 TCU_THROW(NotSupportedError, "Non-multisample framebuffer required"); 660 661 // test purpose and expectations 662 m_testCtx.getLog() 663 << tcu::TestLog::Message 664 << "Verifying that using interpolateAtSample with multisample buffers not available returns sample evaluated at the center of the pixel.\n" 665 << " Interpolate varying containing screen space location.\n" 666 << " => fract(screen space location) should be (about) (0.5, 0.5)\n" 667 << tcu::TestLog::EndMessage; 668 669 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 670} 671 672std::string SingleSampleInterpolateAtSampleCase::genVertexSource (int numTargetSamples) const 673{ 674 DE_UNREF(numTargetSamples); 675 676 std::ostringstream buf; 677 678 buf << "#version 310 es\n" 679 "in highp vec4 a_position;\n" 680 "out highp vec2 v_position;\n" 681 "void main (void)\n" 682 "{\n" 683 " gl_Position = a_position;\n" 684 " v_position = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n" 685 "}\n"; 686 687 return buf.str(); 688} 689 690std::string SingleSampleInterpolateAtSampleCase::genFragmentSource (int numTargetSamples) const 691{ 692 DE_UNREF(numTargetSamples); 693 694 std::ostringstream buf; 695 696 buf << "#version 310 es\n" 697 "#extension GL_OES_shader_multisample_interpolation : require\n" 698 "in highp vec2 v_position;\n" 699 "layout(location = 0) out mediump vec4 fragColor;\n" 700 "void main (void)\n" 701 "{\n" 702 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n"; // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE) 703 704 if (m_sampleCase == SAMPLE_0) 705 { 706 buf << " highp vec2 samplePosition = interpolateAtSample(v_position, 0);\n" 707 " highp vec2 positionInsideAPixel = fract(samplePosition);\n" 708 "\n" 709 " if (abs(positionInsideAPixel.x - 0.5) <= threshold && abs(positionInsideAPixel.y - 0.5) <= threshold)\n" 710 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 711 " else\n" 712 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 713 "}\n"; 714 } 715 else if (m_sampleCase == SAMPLE_N) 716 { 717 buf << " bool allOk = true;\n" 718 " for (int sampleNdx = 159; sampleNdx < 163; ++sampleNdx)\n" 719 " {\n" 720 " highp vec2 samplePosition = interpolateAtSample(v_position, sampleNdx);\n" 721 " highp vec2 positionInsideAPixel = fract(samplePosition);\n" 722 " if (abs(positionInsideAPixel.x - 0.5) > threshold || abs(positionInsideAPixel.y - 0.5) > threshold)\n" 723 " allOk = false;\n" 724 " }\n" 725 "\n" 726 " if (allOk)\n" 727 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 728 " else\n" 729 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 730 "}\n"; 731 } 732 else 733 DE_ASSERT(false); 734 735 return buf.str(); 736} 737 738bool SingleSampleInterpolateAtSampleCase::verifyImage (const tcu::Surface& resultImage) 739{ 740 return verifyGreenImage(resultImage, m_testCtx.getLog()); 741} 742 743class CentroidRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 744{ 745public: 746 CentroidRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize); 747 virtual ~CentroidRenderCase (void); 748 749 void init (void); 750 751private: 752 void setupRenderData (void); 753}; 754 755CentroidRenderCase::CentroidRenderCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, int renderSize) 756 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, renderSize) 757{ 758} 759 760CentroidRenderCase::~CentroidRenderCase (void) 761{ 762} 763 764void CentroidRenderCase::init (void) 765{ 766 // requirements 767 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 768 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 769 770 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 771} 772 773void CentroidRenderCase::setupRenderData (void) 774{ 775 const int numTriangles = 200; 776 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 777 std::vector<tcu::Vec4> data (numTriangles * 3 * 3); 778 779 m_renderMode = GL_TRIANGLES; 780 m_renderCount = numTriangles * 3; 781 m_renderSceneDescription = "triangle fan of narrow triangles"; 782 783 m_renderAttribs["a_position"].offset = 0; 784 m_renderAttribs["a_position"].stride = sizeof(float[4]) * 3; 785 m_renderAttribs["a_barycentricsA"].offset = sizeof(float[4]); 786 m_renderAttribs["a_barycentricsA"].stride = sizeof(float[4]) * 3; 787 m_renderAttribs["a_barycentricsB"].offset = sizeof(float[4]) * 2; 788 m_renderAttribs["a_barycentricsB"].stride = sizeof(float[4]) * 3; 789 790 for (int triangleNdx = 0; triangleNdx < numTriangles; ++triangleNdx) 791 { 792 const float angle = ((float)triangleNdx) / numTriangles * 2.0f * DE_PI; 793 const float nextAngle = ((float)triangleNdx + 1.0f) / numTriangles * 2.0f * DE_PI; 794 795 data[(triangleNdx * 3 + 0) * 3 + 0] = tcu::Vec4(0.2f, -0.3f, 0.0f, 1.0f); 796 data[(triangleNdx * 3 + 0) * 3 + 1] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 797 data[(triangleNdx * 3 + 0) * 3 + 2] = tcu::Vec4(1.0f, 0.0f, 0.0f, 0.0f); 798 799 data[(triangleNdx * 3 + 1) * 3 + 0] = tcu::Vec4(2.0f * cos(angle), 2.0f * sin(angle), 0.0f, 1.0f); 800 data[(triangleNdx * 3 + 1) * 3 + 1] = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f); 801 data[(triangleNdx * 3 + 1) * 3 + 2] = tcu::Vec4(0.0f, 1.0f, 0.0f, 0.0f); 802 803 data[(triangleNdx * 3 + 2) * 3 + 0] = tcu::Vec4(2.0f * cos(nextAngle), 2.0f * sin(nextAngle), 0.0f, 1.0f); 804 data[(triangleNdx * 3 + 2) * 3 + 1] = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f); 805 data[(triangleNdx * 3 + 2) * 3 + 2] = tcu::Vec4(0.0f, 0.0f, 1.0f, 0.0f); 806 } 807 808 gl.bindBuffer(GL_ARRAY_BUFFER, m_buffer); 809 gl.bufferData(GL_ARRAY_BUFFER, (glw::GLsizeiptr)(data.size() * sizeof(tcu::Vec4)), data[0].getPtr(), GL_STATIC_DRAW); 810} 811 812class CentroidQualifierAtSampleCase : public CentroidRenderCase 813{ 814public: 815 CentroidQualifierAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target); 816 virtual ~CentroidQualifierAtSampleCase (void); 817 818 void init (void); 819 820private: 821 enum 822 { 823 RENDER_SIZE = 128 824 }; 825 826 std::string genVertexSource (int numTargetSamples) const; 827 std::string genFragmentSource (int numTargetSamples) const; 828 bool verifyImage (const tcu::Surface& resultImage); 829}; 830 831CentroidQualifierAtSampleCase::CentroidQualifierAtSampleCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target) 832 : CentroidRenderCase(context, name, description, numSamples, target, RENDER_SIZE) 833{ 834} 835 836CentroidQualifierAtSampleCase::~CentroidQualifierAtSampleCase (void) 837{ 838} 839 840void CentroidQualifierAtSampleCase::init (void) 841{ 842 // test purpose and expectations 843 m_testCtx.getLog() 844 << tcu::TestLog::Message 845 << "Verifying that interpolateAtSample ignores the centroid-qualifier.\n" 846 << " Draw a fan of narrow triangles (large number of pixels on the edges).\n" 847 << " Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n" 848 << " Add centroid-qualifier for barycentricsB.\n" 849 << " => interpolateAtSample(barycentricsB, N) ~= interpolateAtSample(barycentricsA, N)\n" 850 << tcu::TestLog::EndMessage; 851 852 CentroidRenderCase::init(); 853} 854 855std::string CentroidQualifierAtSampleCase::genVertexSource (int numTargetSamples) const 856{ 857 DE_UNREF(numTargetSamples); 858 859 return "#version 310 es\n" 860 "in highp vec4 a_position;\n" 861 "in highp vec4 a_barycentricsA;\n" 862 "in highp vec4 a_barycentricsB;\n" 863 "out highp vec3 v_barycentricsA;\n" 864 "centroid out highp vec3 v_barycentricsB;\n" 865 "void main (void)\n" 866 "{\n" 867 " gl_Position = a_position;\n" 868 " v_barycentricsA = a_barycentricsA.xyz;\n" 869 " v_barycentricsB = a_barycentricsB.xyz;\n" 870 "}\n"; 871} 872 873std::string CentroidQualifierAtSampleCase::genFragmentSource (int numTargetSamples) const 874{ 875 DE_UNREF(numTargetSamples); 876 877 std::ostringstream buf; 878 879 buf << "#version 310 es\n" 880 "#extension GL_OES_shader_multisample_interpolation : require\n" 881 "in highp vec3 v_barycentricsA;\n" 882 "centroid in highp vec3 v_barycentricsB;\n" 883 "layout(location = 0) out mediump vec4 fragColor;\n" 884 "void main (void)\n" 885 "{\n" 886 " const highp float threshold = 0.0005;\n" 887 " bool allOk = true;\n" 888 "\n" 889 " for (int sampleNdx = 0; sampleNdx < " << numTargetSamples << "; ++sampleNdx)\n" 890 " {\n" 891 " highp vec3 sampleA = interpolateAtSample(v_barycentricsA, sampleNdx);\n" 892 " highp vec3 sampleB = interpolateAtSample(v_barycentricsB, sampleNdx);\n" 893 " bool valuesEqual = all(lessThan(abs(sampleA - sampleB), vec3(threshold)));\n" 894 " if (!valuesEqual)\n" 895 " allOk = false;\n" 896 " }\n" 897 "\n" 898 " if (allOk)\n" 899 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 900 " else\n" 901 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 902 "}\n"; 903 904 return buf.str(); 905} 906 907bool CentroidQualifierAtSampleCase::verifyImage (const tcu::Surface& resultImage) 908{ 909 return verifyGreenImage(resultImage, m_testCtx.getLog()); 910} 911 912class InterpolateAtSampleIDCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 913{ 914public: 915 InterpolateAtSampleIDCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target); 916 virtual ~InterpolateAtSampleIDCase (void); 917 918 void init (void); 919private: 920 enum 921 { 922 RENDER_SIZE = 32 923 }; 924 925 std::string genVertexSource (int numTargetSamples) const; 926 std::string genFragmentSource (int numTargetSamples) const; 927 bool verifyImage (const tcu::Surface& resultImage); 928}; 929 930InterpolateAtSampleIDCase::InterpolateAtSampleIDCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target) 931 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE) 932{ 933} 934 935InterpolateAtSampleIDCase::~InterpolateAtSampleIDCase (void) 936{ 937} 938 939void InterpolateAtSampleIDCase::init (void) 940{ 941 // requirements 942 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 943 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 944 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables")) 945 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension"); 946 947 // test purpose and expectations 948 m_testCtx.getLog() 949 << tcu::TestLog::Message 950 << "Verifying that interpolateAtSample with the sample set to the current sampleID returns consistent values.\n" 951 << " Interpolate varying containing screen space location.\n" 952 << " => interpolateAtSample(varying, sampleID) = varying" 953 << tcu::TestLog::EndMessage; 954 955 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 956} 957 958std::string InterpolateAtSampleIDCase::genVertexSource (int numTargetSamples) const 959{ 960 DE_UNREF(numTargetSamples); 961 962 std::ostringstream buf; 963 964 buf << "#version 310 es\n" 965 "#extension GL_OES_shader_multisample_interpolation : require\n" 966 "in highp vec4 a_position;\n" 967 "sample out highp vec2 v_screenPosition;\n" 968 "void main (void)\n" 969 "{\n" 970 " gl_Position = a_position;\n" 971 " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n" 972 "}\n"; 973 974 return buf.str(); 975} 976 977std::string InterpolateAtSampleIDCase::genFragmentSource (int numTargetSamples) const 978{ 979 DE_UNREF(numTargetSamples); 980 981 return "#version 310 es\n" 982 "#extension GL_OES_sample_variables : require\n" 983 "#extension GL_OES_shader_multisample_interpolation : require\n" 984 "sample in highp vec2 v_screenPosition;\n" 985 "layout(location = 0) out mediump vec4 fragColor;\n" 986 "void main (void)\n" 987 "{\n" 988 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE) 989 "\n" 990 " highp vec2 offsetValue = interpolateAtSample(v_screenPosition, gl_SampleID);\n" 991 " highp vec2 refValue = v_screenPosition;\n" 992 "\n" 993 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n" 994 " if (valuesEqual)\n" 995 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 996 " else\n" 997 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 998 "}\n"; 999} 1000 1001bool InterpolateAtSampleIDCase::verifyImage (const tcu::Surface& resultImage) 1002{ 1003 return verifyGreenImage(resultImage, m_testCtx.getLog()); 1004} 1005 1006class InterpolateAtCentroidCase : public CentroidRenderCase 1007{ 1008public: 1009 enum TestType 1010 { 1011 TEST_CONSISTENCY = 0, 1012 TEST_ARRAY_ELEMENT, 1013 1014 TEST_LAST 1015 }; 1016 1017 InterpolateAtCentroidCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type); 1018 virtual ~InterpolateAtCentroidCase (void); 1019 1020 void init (void); 1021 1022private: 1023 enum 1024 { 1025 RENDER_SIZE = 128 1026 }; 1027 1028 std::string genVertexSource (int numTargetSamples) const; 1029 std::string genFragmentSource (int numTargetSamples) const; 1030 bool verifyImage (const tcu::Surface& resultImage); 1031 1032 const TestType m_type; 1033}; 1034 1035InterpolateAtCentroidCase::InterpolateAtCentroidCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType type) 1036 : CentroidRenderCase (context, name, description, numSamples, target, RENDER_SIZE) 1037 , m_type (type) 1038{ 1039} 1040 1041InterpolateAtCentroidCase::~InterpolateAtCentroidCase (void) 1042{ 1043} 1044 1045void InterpolateAtCentroidCase::init (void) 1046{ 1047 // test purpose and expectations 1048 if (m_type == TEST_CONSISTENCY) 1049 { 1050 m_testCtx.getLog() 1051 << tcu::TestLog::Message 1052 << "Verifying that interpolateAtCentroid does not return different values than a corresponding centroid-qualified varying.\n" 1053 << " Draw a fan of narrow triangles (large number of pixels on the edges).\n" 1054 << " Set varyings 'barycentricsA' and 'barycentricsB' to contain barycentric coordinates.\n" 1055 << " Add centroid-qualifier for barycentricsB.\n" 1056 << " => interpolateAtCentroid(barycentricsA) ~= barycentricsB\n" 1057 << tcu::TestLog::EndMessage; 1058 } 1059 else if (m_type == TEST_ARRAY_ELEMENT) 1060 { 1061 m_testCtx.getLog() 1062 << tcu::TestLog::Message 1063 << "Testing interpolateAtCentroid with element of array as an argument." 1064 << tcu::TestLog::EndMessage; 1065 } 1066 else 1067 DE_ASSERT(false); 1068 1069 CentroidRenderCase::init(); 1070} 1071 1072std::string InterpolateAtCentroidCase::genVertexSource (int numTargetSamples) const 1073{ 1074 DE_UNREF(numTargetSamples); 1075 1076 if (m_type == TEST_CONSISTENCY) 1077 return "#version 310 es\n" 1078 "in highp vec4 a_position;\n" 1079 "in highp vec4 a_barycentricsA;\n" 1080 "in highp vec4 a_barycentricsB;\n" 1081 "out highp vec3 v_barycentricsA;\n" 1082 "centroid out highp vec3 v_barycentricsB;\n" 1083 "void main (void)\n" 1084 "{\n" 1085 " gl_Position = a_position;\n" 1086 " v_barycentricsA = a_barycentricsA.xyz;\n" 1087 " v_barycentricsB = a_barycentricsB.xyz;\n" 1088 "}\n"; 1089 else if (m_type == TEST_ARRAY_ELEMENT) 1090 return "#version 310 es\n" 1091 "in highp vec4 a_position;\n" 1092 "in highp vec4 a_barycentricsA;\n" 1093 "in highp vec4 a_barycentricsB;\n" 1094 "out highp vec3[2] v_barycentrics;\n" 1095 "void main (void)\n" 1096 "{\n" 1097 " gl_Position = a_position;\n" 1098 " v_barycentrics[0] = a_barycentricsA.xyz;\n" 1099 " v_barycentrics[1] = a_barycentricsB.xyz;\n" 1100 "}\n"; 1101 1102 DE_ASSERT(false); 1103 return ""; 1104} 1105 1106std::string InterpolateAtCentroidCase::genFragmentSource (int numTargetSamples) const 1107{ 1108 DE_UNREF(numTargetSamples); 1109 1110 if (m_type == TEST_CONSISTENCY) 1111 return "#version 310 es\n" 1112 "#extension GL_OES_shader_multisample_interpolation : require\n" 1113 "in highp vec3 v_barycentricsA;\n" 1114 "centroid in highp vec3 v_barycentricsB;\n" 1115 "layout(location = 0) out highp vec4 fragColor;\n" 1116 "void main (void)\n" 1117 "{\n" 1118 " const highp float threshold = 0.0005;\n" 1119 "\n" 1120 " highp vec3 centroidASampled = interpolateAtCentroid(v_barycentricsA);\n" 1121 " bool valuesEqual = all(lessThan(abs(centroidASampled - v_barycentricsB), vec3(threshold)));\n" 1122 " bool centroidAIsInvalid = any(greaterThan(centroidASampled, vec3(1.0))) ||\n" 1123 " any(lessThan(centroidASampled, vec3(0.0)));\n" 1124 " bool centroidBIsInvalid = any(greaterThan(v_barycentricsB, vec3(1.0))) ||\n" 1125 " any(lessThan(v_barycentricsB, vec3(0.0)));\n" 1126 "\n" 1127 " if (valuesEqual && !centroidAIsInvalid && !centroidBIsInvalid)\n" 1128 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1129 " else if (centroidAIsInvalid || centroidBIsInvalid)\n" 1130 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1131 " else\n" 1132 " fragColor = vec4(1.0, 1.0, 0.0, 1.0);\n" 1133 "}\n"; 1134 else if (m_type == TEST_ARRAY_ELEMENT) 1135 return "#version 310 es\n" 1136 "#extension GL_OES_shader_multisample_interpolation : require\n" 1137 "in highp vec3[2] v_barycentrics;\n" 1138 "layout(location = 0) out mediump vec4 fragColor;\n" 1139 "void main (void)\n" 1140 "{\n" 1141 " const highp float threshold = 0.0005;\n" 1142 "\n" 1143 " highp vec3 centroidInterpolated = interpolateAtCentroid(v_barycentrics[1]);\n" 1144 " bool centroidIsInvalid = any(greaterThan(centroidInterpolated, vec3(1.0))) ||\n" 1145 " any(lessThan(centroidInterpolated, vec3(0.0)));\n" 1146 "\n" 1147 " if (!centroidIsInvalid)\n" 1148 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1149 " else\n" 1150 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1151 "}\n"; 1152 1153 DE_ASSERT(false); 1154 return ""; 1155} 1156 1157bool InterpolateAtCentroidCase::verifyImage (const tcu::Surface& resultImage) 1158{ 1159 return verifyGreenImage(resultImage, m_testCtx.getLog()); 1160} 1161 1162class InterpolateAtOffsetCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 1163{ 1164public: 1165 enum TestType 1166 { 1167 TEST_QUALIFIER_NONE = 0, 1168 TEST_QUALIFIER_CENTROID, 1169 TEST_QUALIFIER_SAMPLE, 1170 TEST_ARRAY_ELEMENT, 1171 1172 TEST_LAST 1173 }; 1174 InterpolateAtOffsetCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType); 1175 virtual ~InterpolateAtOffsetCase (void); 1176 1177 void init (void); 1178private: 1179 enum 1180 { 1181 RENDER_SIZE = 32 1182 }; 1183 1184 std::string genVertexSource (int numTargetSamples) const; 1185 std::string genFragmentSource (int numTargetSamples) const; 1186 bool verifyImage (const tcu::Surface& resultImage); 1187 1188 const TestType m_testType; 1189}; 1190 1191InterpolateAtOffsetCase::InterpolateAtOffsetCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target, TestType testType) 1192 : MultisampleShaderRenderUtil::MultisampleRenderCase (context, name, description, numSamples, target, RENDER_SIZE) 1193 , m_testType (testType) 1194{ 1195 DE_ASSERT(testType < TEST_LAST); 1196} 1197 1198InterpolateAtOffsetCase::~InterpolateAtOffsetCase (void) 1199{ 1200} 1201 1202void InterpolateAtOffsetCase::init (void) 1203{ 1204 // requirements 1205 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 1206 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 1207 1208 // test purpose and expectations 1209 m_testCtx.getLog() 1210 << tcu::TestLog::Message 1211 << "Verifying that interpolateAtOffset returns correct values.\n" 1212 << " Interpolate varying containing screen space location.\n" 1213 << " => interpolateAtOffset(varying, offset) should be \"varying value at the pixel center\" + offset" 1214 << tcu::TestLog::EndMessage; 1215 1216 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 1217} 1218 1219std::string InterpolateAtOffsetCase::genVertexSource (int numTargetSamples) const 1220{ 1221 DE_UNREF(numTargetSamples); 1222 1223 std::ostringstream buf; 1224 buf << "#version 310 es\n" 1225 << "#extension GL_OES_shader_multisample_interpolation : require\n" 1226 << "in highp vec4 a_position;\n"; 1227 1228 if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE) 1229 { 1230 const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : (""); 1231 buf << qualifier << "out highp vec2 v_screenPosition;\n" 1232 << qualifier << "out highp vec2 v_offset;\n"; 1233 } 1234 else if (m_testType == TEST_ARRAY_ELEMENT) 1235 { 1236 buf << "out highp vec2[2] v_screenPosition;\n" 1237 << "out highp vec2 v_offset;\n"; 1238 } 1239 else 1240 DE_ASSERT(false); 1241 1242 buf << "void main (void)\n" 1243 << "{\n" 1244 << " gl_Position = a_position;\n"; 1245 1246 if (m_testType != TEST_ARRAY_ELEMENT) 1247 buf << " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"; 1248 else 1249 buf << " v_screenPosition[0] = a_position.xy; // not used\n" 1250 " v_screenPosition[1] = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n"; 1251 1252 buf << " v_offset = a_position.xy * 0.5f;\n" 1253 << "}\n"; 1254 1255 return buf.str(); 1256} 1257 1258std::string InterpolateAtOffsetCase::genFragmentSource (int numTargetSamples) const 1259{ 1260 DE_UNREF(numTargetSamples); 1261 1262 const char* const arrayIndexing = (m_testType == TEST_ARRAY_ELEMENT) ? ("[1]") : (""); 1263 std::ostringstream buf; 1264 1265 buf << "#version 310 es\n" 1266 "#extension GL_OES_shader_multisample_interpolation : require\n"; 1267 1268 if (m_testType == TEST_QUALIFIER_NONE || m_testType == TEST_QUALIFIER_CENTROID || m_testType == TEST_QUALIFIER_SAMPLE) 1269 { 1270 const char* const qualifier = (m_testType == TEST_QUALIFIER_CENTROID) ? ("centroid ") : (m_testType == TEST_QUALIFIER_SAMPLE) ? ("sample ") : (""); 1271 buf << qualifier << "in highp vec2 v_screenPosition;\n" 1272 << qualifier << "in highp vec2 v_offset;\n"; 1273 } 1274 else if (m_testType == TEST_ARRAY_ELEMENT) 1275 { 1276 buf << "in highp vec2[2] v_screenPosition;\n" 1277 << "in highp vec2 v_offset;\n"; 1278 } 1279 else 1280 DE_ASSERT(false); 1281 1282 buf << "layout(location = 0) out mediump vec4 fragColor;\n" 1283 "void main (void)\n" 1284 "{\n" 1285 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE) 1286 "\n" 1287 " highp vec2 pixelCenter = floor(v_screenPosition" << arrayIndexing << ") + vec2(0.5, 0.5);\n" 1288 " highp vec2 offsetValue = interpolateAtOffset(v_screenPosition" << arrayIndexing << ", v_offset);\n" 1289 " highp vec2 refValue = pixelCenter + v_offset;\n" 1290 "\n" 1291 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n" 1292 " if (valuesEqual)\n" 1293 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1294 " else\n" 1295 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1296 "}\n"; 1297 1298 return buf.str(); 1299} 1300 1301bool InterpolateAtOffsetCase::verifyImage (const tcu::Surface& resultImage) 1302{ 1303 return verifyGreenImage(resultImage, m_testCtx.getLog()); 1304} 1305 1306class InterpolateAtSamplePositionCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 1307{ 1308public: 1309 InterpolateAtSamplePositionCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target); 1310 virtual ~InterpolateAtSamplePositionCase (void); 1311 1312 void init (void); 1313private: 1314 enum 1315 { 1316 RENDER_SIZE = 32 1317 }; 1318 1319 std::string genVertexSource (int numTargetSamples) const; 1320 std::string genFragmentSource (int numTargetSamples) const; 1321 bool verifyImage (const tcu::Surface& resultImage); 1322}; 1323 1324InterpolateAtSamplePositionCase::InterpolateAtSamplePositionCase (Context& context, const char* name, const char* description, int numSamples, RenderTarget target) 1325 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, description, numSamples, target, RENDER_SIZE) 1326{ 1327} 1328 1329InterpolateAtSamplePositionCase::~InterpolateAtSamplePositionCase (void) 1330{ 1331} 1332 1333void InterpolateAtSamplePositionCase::init (void) 1334{ 1335 // requirements 1336 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 1337 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 1338 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables")) 1339 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension"); 1340 1341 // test purpose and expectations 1342 m_testCtx.getLog() 1343 << tcu::TestLog::Message 1344 << "Verifying that interpolateAtOffset with the offset of current sample position returns consistent values.\n" 1345 << " Interpolate varying containing screen space location.\n" 1346 << " => interpolateAtOffset(varying, currentOffset) = varying" 1347 << tcu::TestLog::EndMessage; 1348 1349 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 1350} 1351 1352std::string InterpolateAtSamplePositionCase::genVertexSource (int numTargetSamples) const 1353{ 1354 DE_UNREF(numTargetSamples); 1355 1356 std::ostringstream buf; 1357 1358 buf << "#version 310 es\n" 1359 "#extension GL_OES_shader_multisample_interpolation : require\n" 1360 "in highp vec4 a_position;\n" 1361 "sample out highp vec2 v_screenPosition;\n" 1362 "void main (void)\n" 1363 "{\n" 1364 " gl_Position = a_position;\n" 1365 " v_screenPosition = (a_position.xy + vec2(1.0, 1.0)) / 2.0 * vec2(" << (int)RENDER_SIZE << ".0, " << (int)RENDER_SIZE << ".0);\n" 1366 "}\n"; 1367 1368 return buf.str(); 1369} 1370 1371std::string InterpolateAtSamplePositionCase::genFragmentSource (int numTargetSamples) const 1372{ 1373 DE_UNREF(numTargetSamples); 1374 1375 return "#version 310 es\n" 1376 "#extension GL_OES_sample_variables : require\n" 1377 "#extension GL_OES_shader_multisample_interpolation : require\n" 1378 "sample in highp vec2 v_screenPosition;\n" 1379 "layout(location = 0) out mediump vec4 fragColor;\n" 1380 "void main (void)\n" 1381 "{\n" 1382 " const highp float threshold = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE) 1383 "\n" 1384 " highp vec2 offset = gl_SamplePosition - vec2(0.5, 0.5);\n" 1385 " highp vec2 offsetValue = interpolateAtOffset(v_screenPosition, offset);\n" 1386 " highp vec2 refValue = v_screenPosition;\n" 1387 "\n" 1388 " bool valuesEqual = all(lessThan(abs(offsetValue - refValue), vec2(threshold)));\n" 1389 " if (valuesEqual)\n" 1390 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1391 " else\n" 1392 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1393 "}\n"; 1394} 1395 1396bool InterpolateAtSamplePositionCase::verifyImage (const tcu::Surface& resultImage) 1397{ 1398 return verifyGreenImage(resultImage, m_testCtx.getLog()); 1399} 1400 1401class NegativeCompileInterpolationCase : public TestCase 1402{ 1403public: 1404 enum CaseType 1405 { 1406 CASE_VEC4_IDENTITY_SWIZZLE = 0, 1407 CASE_VEC4_CROP_SWIZZLE, 1408 CASE_VEC4_MIXED_SWIZZLE, 1409 CASE_INTERPOLATE_IVEC4, 1410 CASE_INTERPOLATE_UVEC4, 1411 CASE_INTERPOLATE_ARRAY, 1412 CASE_INTERPOLATE_STRUCT, 1413 CASE_INTERPOLATE_STRUCT_MEMBER, 1414 CASE_INTERPOLATE_LOCAL, 1415 CASE_INTERPOLATE_GLOBAL, 1416 CASE_INTERPOLATE_CONSTANT, 1417 1418 CASE_LAST 1419 }; 1420 enum InterpolatorType 1421 { 1422 INTERPOLATE_AT_SAMPLE = 0, 1423 INTERPOLATE_AT_CENTROID, 1424 INTERPOLATE_AT_OFFSET, 1425 1426 INTERPOLATE_LAST 1427 }; 1428 1429 NegativeCompileInterpolationCase (Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator); 1430 1431private: 1432 void init (void); 1433 IterateResult iterate (void); 1434 1435 std::string genShaderSource (void) const; 1436 1437 const CaseType m_caseType; 1438 const InterpolatorType m_interpolation; 1439}; 1440 1441NegativeCompileInterpolationCase::NegativeCompileInterpolationCase (Context& context, const char* name, const char* description, CaseType caseType, InterpolatorType interpolator) 1442 : TestCase (context, name, description) 1443 , m_caseType (caseType) 1444 , m_interpolation (interpolator) 1445{ 1446 DE_ASSERT(m_caseType < CASE_LAST); 1447 DE_ASSERT(m_interpolation < INTERPOLATE_LAST); 1448} 1449 1450void NegativeCompileInterpolationCase::init (void) 1451{ 1452 if (!m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation")) 1453 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation extension"); 1454 1455 m_testCtx.getLog() << tcu::TestLog::Message << "Trying to compile illegal shader, expecting compile to fail." << tcu::TestLog::EndMessage; 1456} 1457 1458NegativeCompileInterpolationCase::IterateResult NegativeCompileInterpolationCase::iterate (void) 1459{ 1460 const std::string source = genShaderSource(); 1461 glu::Shader shader (m_context.getRenderContext(), glu::SHADERTYPE_FRAGMENT); 1462 const char* const sourceStrPtr = source.c_str(); 1463 1464 m_testCtx.getLog() << tcu::TestLog::Message 1465 << "Fragment shader source:" 1466 << tcu::TestLog::EndMessage 1467 << tcu::TestLog::KernelSource(source); 1468 1469 shader.setSources(1, &sourceStrPtr, DE_NULL); 1470 shader.compile(); 1471 1472 m_testCtx.getLog() << tcu::TestLog::Message 1473 << "Info log:" 1474 << tcu::TestLog::EndMessage 1475 << tcu::TestLog::KernelSource(shader.getInfoLog()); 1476 1477 if (shader.getCompileStatus()) 1478 { 1479 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Illegal shader compiled successfully." << tcu::TestLog::EndMessage; 1480 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Unexpected compile status"); 1481 } 1482 else 1483 { 1484 m_testCtx.getLog() << tcu::TestLog::Message << "Compile failed as expected." << tcu::TestLog::EndMessage; 1485 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 1486 } 1487 return STOP; 1488} 1489 1490std::string NegativeCompileInterpolationCase::genShaderSource (void) const 1491{ 1492 std::ostringstream buf; 1493 std::string interpolation; 1494 const char* interpolationTemplate; 1495 const char* description; 1496 const char* globalDeclarations = ""; 1497 const char* localDeclarations = ""; 1498 const char* interpolationTarget = ""; 1499 const char* postSelector = ""; 1500 1501 switch (m_caseType) 1502 { 1503 case CASE_VEC4_IDENTITY_SWIZZLE: 1504 globalDeclarations = "in highp vec4 v_var;\n"; 1505 interpolationTarget = "v_var.xyzw"; 1506 description = "component selection is illegal"; 1507 break; 1508 1509 case CASE_VEC4_CROP_SWIZZLE: 1510 globalDeclarations = "in highp vec4 v_var;\n"; 1511 interpolationTarget = "v_var.xy"; 1512 postSelector = ".x"; 1513 description = "component selection is illegal"; 1514 break; 1515 1516 case CASE_VEC4_MIXED_SWIZZLE: 1517 globalDeclarations = "in highp vec4 v_var;\n"; 1518 interpolationTarget = "v_var.yzxw"; 1519 description = "component selection is illegal"; 1520 break; 1521 1522 case CASE_INTERPOLATE_IVEC4: 1523 globalDeclarations = "flat in highp ivec4 v_var;\n"; 1524 interpolationTarget = "v_var"; 1525 description = "no overload for ivec"; 1526 break; 1527 1528 case CASE_INTERPOLATE_UVEC4: 1529 globalDeclarations = "flat in highp uvec4 v_var;\n"; 1530 interpolationTarget = "v_var"; 1531 description = "no overload for uvec"; 1532 break; 1533 1534 case CASE_INTERPOLATE_ARRAY: 1535 globalDeclarations = "in highp float v_var[2];\n"; 1536 interpolationTarget = "v_var"; 1537 postSelector = "[1]"; 1538 description = "no overload for arrays"; 1539 break; 1540 1541 case CASE_INTERPOLATE_STRUCT: 1542 case CASE_INTERPOLATE_STRUCT_MEMBER: 1543 globalDeclarations = "struct S\n" 1544 "{\n" 1545 " highp float a;\n" 1546 " highp float b;\n" 1547 "};\n" 1548 "in S v_var;\n"; 1549 1550 interpolationTarget = (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("v_var") : ("v_var.a"); 1551 postSelector = (m_caseType == CASE_INTERPOLATE_STRUCT) ? (".a") : (""); 1552 description = (m_caseType == CASE_INTERPOLATE_STRUCT) ? ("no overload for this type") : ("<interpolant> is not an input variable (just a member of)"); 1553 break; 1554 1555 case CASE_INTERPOLATE_LOCAL: 1556 localDeclarations = " highp vec4 local_var = gl_FragCoord;\n"; 1557 interpolationTarget = "local_var"; 1558 description = "<interpolant> is not an input variable"; 1559 break; 1560 1561 case CASE_INTERPOLATE_GLOBAL: 1562 globalDeclarations = "highp vec4 global_var;\n"; 1563 localDeclarations = " global_var = gl_FragCoord;\n"; 1564 interpolationTarget = "global_var"; 1565 description = "<interpolant> is not an input variable"; 1566 break; 1567 1568 case CASE_INTERPOLATE_CONSTANT: 1569 globalDeclarations = "const highp vec4 const_var = vec4(0.2);\n"; 1570 interpolationTarget = "const_var"; 1571 description = "<interpolant> is not an input variable"; 1572 break; 1573 1574 default: 1575 DE_ASSERT(false); 1576 return ""; 1577 } 1578 1579 switch (m_interpolation) 1580 { 1581 case INTERPOLATE_AT_SAMPLE: 1582 interpolationTemplate = "interpolateAtSample(${TARGET}, 0)${POST_SELECTOR}"; 1583 break; 1584 1585 case INTERPOLATE_AT_CENTROID: 1586 interpolationTemplate = "interpolateAtCentroid(${TARGET})${POST_SELECTOR}"; 1587 break; 1588 1589 case INTERPOLATE_AT_OFFSET: 1590 interpolationTemplate = "interpolateAtOffset(${TARGET}, vec2(0.2, 0.2))${POST_SELECTOR}"; 1591 break; 1592 1593 default: 1594 DE_ASSERT(false); 1595 return ""; 1596 } 1597 1598 { 1599 std::map<std::string, std::string> args; 1600 args["TARGET"] = interpolationTarget; 1601 args["POST_SELECTOR"] = postSelector; 1602 1603 interpolation = tcu::StringTemplate(interpolationTemplate).specialize(args); 1604 } 1605 1606 buf << "#version 310 es\n" 1607 "#extension GL_OES_shader_multisample_interpolation : require\n" 1608 << globalDeclarations 1609 << "layout(location = 0) out mediump vec4 fragColor;\n" 1610 "void main (void)\n" 1611 "{\n" 1612 << localDeclarations 1613 << " fragColor = vec4(" << interpolation << "); // " << description << "\n" 1614 "}\n"; 1615 1616 return buf.str(); 1617} 1618 1619} // anonymous 1620 1621ShaderMultisampleInterpolationTests::ShaderMultisampleInterpolationTests (Context& context) 1622 : TestCaseGroup(context, "multisample_interpolation", "Test multisample interpolation") 1623{ 1624} 1625 1626ShaderMultisampleInterpolationTests::~ShaderMultisampleInterpolationTests (void) 1627{ 1628} 1629 1630void ShaderMultisampleInterpolationTests::init (void) 1631{ 1632 using namespace MultisampleShaderRenderUtil; 1633 1634 static const struct RenderTarget 1635 { 1636 const char* name; 1637 const char* desc; 1638 int numSamples; 1639 MultisampleRenderCase::RenderTarget target; 1640 } targets[] = 1641 { 1642 { "default_framebuffer", "Test with default framebuffer", 0, MultisampleRenderCase::TARGET_DEFAULT }, 1643 { "singlesample_texture", "Test with singlesample texture", 0, MultisampleRenderCase::TARGET_TEXTURE }, 1644 { "multisample_texture_1", "Test with multisample texture", 1, MultisampleRenderCase::TARGET_TEXTURE }, 1645 { "multisample_texture_2", "Test with multisample texture", 2, MultisampleRenderCase::TARGET_TEXTURE }, 1646 { "multisample_texture_4", "Test with multisample texture", 4, MultisampleRenderCase::TARGET_TEXTURE }, 1647 { "multisample_texture_8", "Test with multisample texture", 8, MultisampleRenderCase::TARGET_TEXTURE }, 1648 { "multisample_texture_16", "Test with multisample texture", 16, MultisampleRenderCase::TARGET_TEXTURE }, 1649 { "singlesample_rbo", "Test with singlesample rbo", 0, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1650 { "multisample_rbo_1", "Test with multisample rbo", 1, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1651 { "multisample_rbo_2", "Test with multisample rbo", 2, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1652 { "multisample_rbo_4", "Test with multisample rbo", 4, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1653 { "multisample_rbo_8", "Test with multisample rbo", 8, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1654 { "multisample_rbo_16", "Test with multisample rbo", 16, MultisampleRenderCase::TARGET_RENDERBUFFER }, 1655 }; 1656 1657 static const struct 1658 { 1659 const char* name; 1660 const char* description; 1661 NegativeCompileInterpolationCase::CaseType caseType; 1662 } negativeCompileCases[] = 1663 { 1664 { "vec4_identity_swizzle", "use identity swizzle", NegativeCompileInterpolationCase::CASE_VEC4_IDENTITY_SWIZZLE }, 1665 { "vec4_crop_swizzle", "use cropped identity swizzle", NegativeCompileInterpolationCase::CASE_VEC4_CROP_SWIZZLE }, 1666 { "vec4_mixed_swizzle", "use swizzle", NegativeCompileInterpolationCase::CASE_VEC4_MIXED_SWIZZLE }, 1667 { "interpolate_ivec4", "interpolate integer variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_IVEC4 }, 1668 { "interpolate_uvec4", "interpolate integer variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_UVEC4 }, 1669 { "interpolate_array", "interpolate whole array", NegativeCompileInterpolationCase::CASE_INTERPOLATE_ARRAY }, 1670 { "interpolate_struct", "interpolate whole struct", NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT }, 1671 { "interpolate_struct_member", "interpolate struct member", NegativeCompileInterpolationCase::CASE_INTERPOLATE_STRUCT_MEMBER }, 1672 { "interpolate_local", "interpolate local variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_LOCAL }, 1673 { "interpolate_global", "interpolate global variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_GLOBAL }, 1674 { "interpolate_constant", "interpolate constant variable", NegativeCompileInterpolationCase::CASE_INTERPOLATE_CONSTANT }, 1675 }; 1676 1677 // .sample_qualifier 1678 { 1679 tcu::TestCaseGroup* const sampleQualifierGroup = new tcu::TestCaseGroup(m_testCtx, "sample_qualifier", "Test sample qualifier"); 1680 addChild(sampleQualifierGroup); 1681 1682 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1683 sampleQualifierGroup->addChild(new SampleQualifierRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 1684 } 1685 1686 // .interpolate_at_sample 1687 { 1688 tcu::TestCaseGroup* const interpolateAtSampleGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_sample", "Test interpolateAtSample"); 1689 addChild(interpolateAtSampleGroup); 1690 1691 // .static_sample_number 1692 { 1693 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "static_sample_number", "Test interpolateAtSample sample number"); 1694 interpolateAtSampleGroup->addChild(group); 1695 1696 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1697 group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_STATIC)); 1698 } 1699 1700 // .dynamic_sample_number 1701 { 1702 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "dynamic_sample_number", "Test interpolateAtSample sample number"); 1703 interpolateAtSampleGroup->addChild(group); 1704 1705 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1706 group->addChild(new InterpolateAtSampleRenderCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtSampleRenderCase::INDEXING_DYNAMIC)); 1707 } 1708 1709 // .non_multisample_buffer 1710 { 1711 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "non_multisample_buffer", "Test interpolateAtSample with non-multisample buffers"); 1712 interpolateAtSampleGroup->addChild(group); 1713 1714 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1715 if (targets[targetNdx].numSamples == 0) 1716 group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_0_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_0)); 1717 1718 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1719 if (targets[targetNdx].numSamples == 0) 1720 group->addChild(new SingleSampleInterpolateAtSampleCase(m_context, std::string("sample_n_").append(targets[targetNdx].name).c_str(), targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SingleSampleInterpolateAtSampleCase::SAMPLE_N)); 1721 } 1722 1723 // .centroid_qualifier 1724 { 1725 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "centroid_qualified", "Test interpolateAtSample with centroid qualified varying"); 1726 interpolateAtSampleGroup->addChild(group); 1727 1728 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1729 group->addChild(new CentroidQualifierAtSampleCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 1730 } 1731 1732 // .at_sample_id 1733 { 1734 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_id", "Test interpolateAtSample at current sample id"); 1735 interpolateAtSampleGroup->addChild(group); 1736 1737 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1738 group->addChild(new InterpolateAtSampleIDCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 1739 } 1740 1741 // .negative 1742 { 1743 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtSample negative tests"); 1744 interpolateAtSampleGroup->addChild(group); 1745 1746 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx) 1747 group->addChild(new NegativeCompileInterpolationCase(m_context, 1748 negativeCompileCases[ndx].name, 1749 negativeCompileCases[ndx].description, 1750 negativeCompileCases[ndx].caseType, 1751 NegativeCompileInterpolationCase::INTERPOLATE_AT_SAMPLE)); 1752 } 1753 } 1754 1755 // .interpolate_at_centroid 1756 { 1757 tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_centroid", "Test interpolateAtCentroid"); 1758 addChild(methodGroup); 1759 1760 // .consistency 1761 { 1762 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "consistency", "Test interpolateAtCentroid return value is consistent to centroid qualified value"); 1763 methodGroup->addChild(group); 1764 1765 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1766 group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_CONSISTENCY)); 1767 } 1768 1769 // .array_element 1770 { 1771 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtCentroid with array element"); 1772 methodGroup->addChild(group); 1773 1774 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1775 group->addChild(new InterpolateAtCentroidCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtCentroidCase::TEST_ARRAY_ELEMENT)); 1776 } 1777 1778 // .negative 1779 { 1780 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtCentroid negative tests"); 1781 methodGroup->addChild(group); 1782 1783 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx) 1784 group->addChild(new NegativeCompileInterpolationCase(m_context, 1785 negativeCompileCases[ndx].name, 1786 negativeCompileCases[ndx].description, 1787 negativeCompileCases[ndx].caseType, 1788 NegativeCompileInterpolationCase::INTERPOLATE_AT_CENTROID)); 1789 } 1790 } 1791 1792 // .interpolate_at_offset 1793 { 1794 static const struct TestConfig 1795 { 1796 const char* name; 1797 InterpolateAtOffsetCase::TestType type; 1798 } configs[] = 1799 { 1800 { "no_qualifiers", InterpolateAtOffsetCase::TEST_QUALIFIER_NONE }, 1801 { "centroid_qualifier", InterpolateAtOffsetCase::TEST_QUALIFIER_CENTROID }, 1802 { "sample_qualifier", InterpolateAtOffsetCase::TEST_QUALIFIER_SAMPLE }, 1803 }; 1804 1805 tcu::TestCaseGroup* const methodGroup = new tcu::TestCaseGroup(m_testCtx, "interpolate_at_offset", "Test interpolateAtOffset"); 1806 addChild(methodGroup); 1807 1808 // .no_qualifiers 1809 // .centroid_qualifier 1810 // .sample_qualifier 1811 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(configs); ++configNdx) 1812 { 1813 tcu::TestCaseGroup* const qualifierGroup = new tcu::TestCaseGroup(m_testCtx, configs[configNdx].name, "Test interpolateAtOffset with qualified/non-qualified varying"); 1814 methodGroup->addChild(qualifierGroup); 1815 1816 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1817 qualifierGroup->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, configs[configNdx].type)); 1818 } 1819 1820 // .at_sample_position 1821 { 1822 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "at_sample_position", "Test interpolateAtOffset at sample position"); 1823 methodGroup->addChild(group); 1824 1825 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1826 group->addChild(new InterpolateAtSamplePositionCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 1827 } 1828 1829 // .array_element 1830 { 1831 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "array_element", "Test interpolateAtOffset with array element"); 1832 methodGroup->addChild(group); 1833 1834 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 1835 group->addChild(new InterpolateAtOffsetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, InterpolateAtOffsetCase::TEST_ARRAY_ELEMENT)); 1836 } 1837 1838 // .negative 1839 { 1840 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "negative", "interpolateAtOffset negative tests"); 1841 methodGroup->addChild(group); 1842 1843 for (int ndx = 0; ndx < DE_LENGTH_OF_ARRAY(negativeCompileCases); ++ndx) 1844 group->addChild(new NegativeCompileInterpolationCase(m_context, 1845 negativeCompileCases[ndx].name, 1846 negativeCompileCases[ndx].description, 1847 negativeCompileCases[ndx].caseType, 1848 NegativeCompileInterpolationCase::INTERPOLATE_AT_OFFSET)); 1849 } 1850 } 1851} 1852 1853} // Functional 1854} // gles31 1855} // deqp 1856