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