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 Sample variable tests 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fSampleVariableTests.hpp" 25 #include "es31fMultisampleShaderRenderCase.hpp" 26 #include "tcuSurface.hpp" 27 #include "tcuTestLog.hpp" 28 #include "tcuRenderTarget.hpp" 29 #include "tcuTextureUtil.hpp" 30 #include "tcuVectorUtil.hpp" 31 #include "tcuFormatUtil.hpp" 32 #include "tcuStringTemplate.hpp" 33 #include "gluContextInfo.hpp" 34 #include "gluShaderProgram.hpp" 35 #include "gluRenderContext.hpp" 36 #include "glwFunctions.hpp" 37 #include "glwEnums.hpp" 38 #include "deStringUtil.hpp" 39 40 namespace deqp 41 { 42 43 using std::map; 44 using std::string; 45 46 namespace gles31 47 { 48 namespace Functional 49 { 50 namespace 51 { 52 53 class Verifier 54 { 55 public: 56 virtual bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const = 0; 57 virtual void logInfo (tcu::TestLog& log) const = 0; 58 }; 59 60 class ColorVerifier : public Verifier 61 { 62 public: 63 ColorVerifier (const tcu::Vec3& _color, int _threshold = 8) 64 : m_color (tcu::Vec4(_color.x(), _color.y(), _color.z(), 1.0f)) 65 , m_threshold (tcu::IVec3(_threshold)) 66 { 67 } 68 69 ColorVerifier (const tcu::Vec3& _color, tcu::IVec3 _threshold) 70 : m_color (tcu::Vec4(_color.x(), _color.y(), _color.z(), 1.0f)) 71 , m_threshold (_threshold) 72 { 73 } 74 75 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const 76 { 77 DE_UNREF(position); 78 return !tcu::boolAny(tcu::greaterThan(tcu::abs(m_color.toIVec().swizzle(0, 1, 2) - testColor.toIVec().swizzle(0, 1, 2)), tcu::IVec3(m_threshold))); 79 } 80 81 void logInfo (tcu::TestLog& log) const 82 { 83 // full threshold? print * for clarity 84 log << tcu::TestLog::Message 85 << "Expecting unicolored image, color = RGB(" 86 << ((m_threshold[0] >= 255) ? ("*") : (de::toString(m_color.getRed()))) << ", " 87 << ((m_threshold[1] >= 255) ? ("*") : (de::toString(m_color.getGreen()))) << ", " 88 << ((m_threshold[2] >= 255) ? ("*") : (de::toString(m_color.getBlue()))) << ")" 89 << tcu::TestLog::EndMessage; 90 } 91 92 const tcu::RGBA m_color; 93 const tcu::IVec3 m_threshold; 94 }; 95 96 class FullBlueSomeGreenVerifier : public Verifier 97 { 98 public: 99 FullBlueSomeGreenVerifier (void) 100 { 101 } 102 103 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const 104 { 105 DE_UNREF(position); 106 107 // Values from 0.0 and 1.0 are accurate 108 109 if (testColor.getRed() != 0) 110 return false; 111 if (testColor.getGreen() == 0) 112 return false; 113 if (testColor.getBlue() != 255) 114 return false; 115 return true; 116 } 117 118 void logInfo (tcu::TestLog& log) const 119 { 120 log << tcu::TestLog::Message << "Expecting color c = (0.0, x, 1.0), x > 0.0" << tcu::TestLog::EndMessage; 121 } 122 }; 123 124 class NoRedVerifier : public Verifier 125 { 126 public: 127 NoRedVerifier (void) 128 { 129 } 130 131 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const 132 { 133 DE_UNREF(position); 134 return testColor.getRed() == 0; 135 } 136 137 void logInfo (tcu::TestLog& log) const 138 { 139 log << tcu::TestLog::Message << "Expecting zero-valued red channel." << tcu::TestLog::EndMessage; 140 } 141 }; 142 143 class SampleAverageVerifier : public Verifier 144 { 145 public: 146 SampleAverageVerifier (int _numSamples); 147 148 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const; 149 void logInfo (tcu::TestLog& log) const; 150 151 const int m_numSamples; 152 const bool m_isStatisticallySignificant; 153 float m_distanceThreshold; 154 }; 155 156 SampleAverageVerifier::SampleAverageVerifier (int _numSamples) 157 : m_numSamples (_numSamples) 158 , m_isStatisticallySignificant (_numSamples >= 4) 159 , m_distanceThreshold (0.0f) 160 { 161 // approximate Bates distribution as normal 162 const float variance = (1.0f / (12.0f * (float)m_numSamples)); 163 const float standardDeviation = deFloatSqrt(variance); 164 165 // 95% of means of sample positions are within 2 standard deviations if 166 // they were randomly assigned. Sample patterns are expected to be more 167 // uniform than a random pattern. 168 m_distanceThreshold = 2 * standardDeviation; 169 } 170 171 bool SampleAverageVerifier::verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const 172 { 173 DE_UNREF(position); 174 DE_ASSERT(m_isStatisticallySignificant); 175 176 const tcu::Vec2 avgPosition ((float)testColor.getGreen() / 255.0f, (float)testColor.getBlue() / 255.0f); 177 const tcu::Vec2 distanceFromCenter = tcu::abs(avgPosition - tcu::Vec2(0.5f, 0.5f)); 178 179 return distanceFromCenter.x() < m_distanceThreshold && distanceFromCenter.y() < m_distanceThreshold; 180 } 181 182 void SampleAverageVerifier::logInfo (tcu::TestLog& log) const 183 { 184 log << tcu::TestLog::Message << "Expecting average sample position to be near the pixel center. Maximum per-axis distance " << m_distanceThreshold << tcu::TestLog::EndMessage; 185 } 186 187 class PartialDiscardVerifier : public Verifier 188 { 189 public: 190 PartialDiscardVerifier (void) 191 { 192 } 193 194 bool verify (const tcu::RGBA& testColor, const tcu::IVec2& position) const 195 { 196 DE_UNREF(position); 197 198 return (testColor.getGreen() != 0) && (testColor.getGreen() != 255); 199 } 200 201 void logInfo (tcu::TestLog& log) const 202 { 203 log << tcu::TestLog::Message << "Expecting color non-zero and non-saturated green channel" << tcu::TestLog::EndMessage; 204 } 205 }; 206 207 static bool verifyImageWithVerifier (const tcu::Surface& resultImage, tcu::TestLog& log, const Verifier& verifier, bool logOnSuccess = true) 208 { 209 tcu::Surface errorMask (resultImage.getWidth(), resultImage.getHeight()); 210 bool error = false; 211 212 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 213 214 if (logOnSuccess) 215 { 216 log << tcu::TestLog::Message << "Verifying image." << tcu::TestLog::EndMessage; 217 verifier.logInfo(log); 218 } 219 220 for (int y = 0; y < resultImage.getHeight(); ++y) 221 for (int x = 0; x < resultImage.getWidth(); ++x) 222 { 223 const tcu::RGBA color = resultImage.getPixel(x, y); 224 225 // verify color value is valid for this pixel position 226 if (!verifier.verify(color, tcu::IVec2(x,y))) 227 { 228 error = true; 229 errorMask.setPixel(x, y, tcu::RGBA::red()); 230 } 231 } 232 233 if (error) 234 { 235 // describe the verification logic if we haven't already 236 if (!logOnSuccess) 237 verifier.logInfo(log); 238 239 log << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage 240 << tcu::TestLog::ImageSet("Verification", "Image Verification") 241 << tcu::TestLog::Image("Result", "Result image", resultImage.getAccess()) 242 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess()) 243 << tcu::TestLog::EndImageSet; 244 } 245 else if (logOnSuccess) 246 { 247 log << tcu::TestLog::Message << "Image verification passed." << tcu::TestLog::EndMessage 248 << tcu::TestLog::ImageSet("Verification", "Image Verification") 249 << tcu::TestLog::Image("Result", "Result image", resultImage.getAccess()) 250 << tcu::TestLog::EndImageSet; 251 } 252 253 return !error; 254 } 255 256 class MultisampleRenderCase : public MultisampleShaderRenderUtil::MultisampleRenderCase 257 { 258 public: 259 MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags = 0); 260 virtual ~MultisampleRenderCase (void); 261 262 virtual void init (void); 263 264 }; 265 266 MultisampleRenderCase::MultisampleRenderCase (Context& context, const char* name, const char* desc, int numSamples, RenderTarget target, int renderSize, int flags) 267 : MultisampleShaderRenderUtil::MultisampleRenderCase(context, name, desc, numSamples, target, renderSize, flags) 268 { 269 DE_ASSERT(target < TARGET_LAST); 270 } 271 272 MultisampleRenderCase::~MultisampleRenderCase (void) 273 { 274 MultisampleRenderCase::deinit(); 275 } 276 277 void MultisampleRenderCase::init (void) 278 { 279 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 280 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_variables")) 281 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_variables extension or a context version 3.2 or higher."); 282 283 MultisampleShaderRenderUtil::MultisampleRenderCase::init(); 284 } 285 286 class NumSamplesCase : public MultisampleRenderCase 287 { 288 public: 289 NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 290 ~NumSamplesCase (void); 291 292 std::string genFragmentSource (int numTargetSamples) const; 293 bool verifyImage (const tcu::Surface& resultImage); 294 295 private: 296 enum 297 { 298 RENDER_SIZE = 64 299 }; 300 }; 301 302 NumSamplesCase::NumSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 303 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE) 304 { 305 } 306 307 NumSamplesCase::~NumSamplesCase (void) 308 { 309 } 310 311 std::string NumSamplesCase::genFragmentSource (int numTargetSamples) const 312 { 313 std::ostringstream buf; 314 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 315 map<string, string> args; 316 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 317 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 318 319 buf << "${GLSL_VERSION_DECL}\n" 320 "${GLSL_EXTENSION}\n" 321 "layout(location = 0) out mediump vec4 fragColor;\n" 322 "void main (void)\n" 323 "{\n" 324 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 325 " if (gl_NumSamples == " << numTargetSamples << ")\n" 326 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 327 "}\n"; 328 329 return tcu::StringTemplate(buf.str()).specialize(args); 330 } 331 332 bool NumSamplesCase::verifyImage (const tcu::Surface& resultImage) 333 { 334 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()); 335 } 336 337 class MaxSamplesCase : public MultisampleRenderCase 338 { 339 public: 340 MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 341 ~MaxSamplesCase (void); 342 343 private: 344 void preDraw (void); 345 std::string genFragmentSource (int numTargetSamples) const; 346 bool verifyImage (const tcu::Surface& resultImage); 347 348 enum 349 { 350 RENDER_SIZE = 64 351 }; 352 }; 353 354 MaxSamplesCase::MaxSamplesCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 355 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE) 356 { 357 } 358 359 MaxSamplesCase::~MaxSamplesCase (void) 360 { 361 } 362 363 void MaxSamplesCase::preDraw (void) 364 { 365 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 366 deInt32 maxSamples = -1; 367 368 // query samples 369 { 370 gl.getIntegerv(GL_MAX_SAMPLES, &maxSamples); 371 GLU_EXPECT_NO_ERROR(gl.getError(), "query GL_MAX_SAMPLES"); 372 373 m_testCtx.getLog() << tcu::TestLog::Message << "GL_MAX_SAMPLES = " << maxSamples << tcu::TestLog::EndMessage; 374 } 375 376 // set samples 377 { 378 const int maxSampleLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxSamples"); 379 if (maxSampleLoc == -1) 380 throw tcu::TestError("Location of u_maxSamples was -1"); 381 382 gl.uniform1i(maxSampleLoc, maxSamples); 383 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_maxSamples uniform"); 384 385 m_testCtx.getLog() << tcu::TestLog::Message << "Set u_maxSamples = " << maxSamples << tcu::TestLog::EndMessage; 386 } 387 } 388 389 std::string MaxSamplesCase::genFragmentSource (int numTargetSamples) const 390 { 391 DE_UNREF(numTargetSamples); 392 393 std::ostringstream buf; 394 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 395 map<string, string> args; 396 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 397 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 398 399 buf << "${GLSL_VERSION_DECL}\n" 400 "${GLSL_EXTENSION}\n" 401 "layout(location = 0) out mediump vec4 fragColor;\n" 402 "uniform mediump int u_maxSamples;\n" 403 "void main (void)\n" 404 "{\n" 405 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 406 " if (gl_MaxSamples == u_maxSamples)\n" 407 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 408 "}\n"; 409 410 return tcu::StringTemplate(buf.str()).specialize(args); 411 } 412 413 bool MaxSamplesCase::verifyImage (const tcu::Surface& resultImage) 414 { 415 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()); 416 } 417 418 class SampleIDCase : public MultisampleRenderCase 419 { 420 public: 421 SampleIDCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 422 ~SampleIDCase (void); 423 424 void init (void); 425 426 private: 427 std::string genFragmentSource (int numTargetSamples) const; 428 bool verifyImage (const tcu::Surface& resultImage); 429 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers); 430 431 enum 432 { 433 RENDER_SIZE = 64 434 }; 435 enum VerificationMode 436 { 437 VERIFY_USING_SAMPLES, 438 VERIFY_USING_SELECTION, 439 }; 440 441 const VerificationMode m_vericationMode; 442 }; 443 444 SampleIDCase::SampleIDCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 445 : MultisampleRenderCase (context, name, desc, sampleCount, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS) 446 , m_vericationMode ((target == TARGET_TEXTURE) ? (VERIFY_USING_SAMPLES) : (VERIFY_USING_SELECTION)) 447 { 448 } 449 450 SampleIDCase::~SampleIDCase (void) 451 { 452 } 453 454 void SampleIDCase::init (void) 455 { 456 // log the test method and expectations 457 if (m_vericationMode == VERIFY_USING_SAMPLES) 458 m_testCtx.getLog() 459 << tcu::TestLog::Message 460 << "Writing gl_SampleID to the green channel of the texture and verifying texture values, expecting:\n" 461 << " 1) 0 with non-multisample targets.\n" 462 << " 2) value N at sample index N of a multisample texture\n" 463 << tcu::TestLog::EndMessage; 464 else if (m_vericationMode == VERIFY_USING_SELECTION) 465 m_testCtx.getLog() 466 << tcu::TestLog::Message 467 << "Selecting a single sample id for each pixel and writing color only if gl_SampleID == selected.\n" 468 << "Expecting all output pixels to be partially (multisample) or fully (singlesample) colored.\n" 469 << tcu::TestLog::EndMessage; 470 else 471 DE_ASSERT(false); 472 473 MultisampleRenderCase::init(); 474 } 475 476 std::string SampleIDCase::genFragmentSource (int numTargetSamples) const 477 { 478 DE_ASSERT(numTargetSamples != 0); 479 480 std::ostringstream buf; 481 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 482 map<string, string> args; 483 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 484 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 485 486 if (m_vericationMode == VERIFY_USING_SAMPLES) 487 { 488 // encode the id to the output, and then verify it during sampling 489 buf << "${GLSL_VERSION_DECL}\n" 490 "${GLSL_EXTENSION}\n" 491 "layout(location = 0) out mediump vec4 fragColor;\n" 492 "void main (void)\n" 493 "{\n" 494 " highp float normalizedSample = float(gl_SampleID) / float(" << numTargetSamples << ");\n" 495 " fragColor = vec4(0.0, normalizedSample, 1.0, 1.0);\n" 496 "}\n"; 497 } 498 else if (m_vericationMode == VERIFY_USING_SELECTION) 499 { 500 if (numTargetSamples == 1) 501 { 502 // single sample, just verify value is 0 503 buf << "${GLSL_VERSION_DECL}\n" 504 "${GLSL_EXTENSION}\n" 505 "layout(location = 0) out mediump vec4 fragColor;\n" 506 "void main (void)\n" 507 "{\n" 508 " if (gl_SampleID == 0)\n" 509 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n" 510 " else\n" 511 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" 512 "}\n"; 513 } 514 else 515 { 516 // select only one sample per PIXEL 517 buf << "${GLSL_VERSION_DECL}\n" 518 "${GLSL_EXTENSION}\n" 519 "in highp vec4 v_position;\n" 520 "layout(location = 0) out mediump vec4 fragColor;\n" 521 "void main (void)\n" 522 "{\n" 523 " highp vec2 relPosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0;\n" 524 " highp ivec2 pixelPos = ivec2(floor(relPosition * " << (int)RENDER_SIZE << ".0));\n" 525 " highp int selectedID = abs(pixelPos.x + 17 * pixelPos.y) % " << numTargetSamples << ";\n" 526 "\n" 527 " if (gl_SampleID == selectedID)\n" 528 " fragColor = vec4(0.0, 1.0, 1.0, 1.0);\n" 529 " else\n" 530 " fragColor = vec4(0.0, 0.0, 1.0, 1.0);\n" 531 "}\n"; 532 } 533 } 534 else 535 DE_ASSERT(false); 536 537 return tcu::StringTemplate(buf.str()).specialize(args); 538 } 539 540 bool SampleIDCase::verifyImage (const tcu::Surface& resultImage) 541 { 542 if (m_vericationMode == VERIFY_USING_SAMPLES) 543 { 544 // never happens 545 DE_ASSERT(false); 546 return false; 547 } 548 else if (m_vericationMode == VERIFY_USING_SELECTION) 549 { 550 // should result in full blue and some green everywhere 551 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), FullBlueSomeGreenVerifier()); 552 } 553 else 554 { 555 DE_ASSERT(false); 556 return false; 557 } 558 } 559 560 bool SampleIDCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers) 561 { 562 // Verify all sample buffers 563 bool allOk = true; 564 565 // Log layers 566 { 567 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers"); 568 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 569 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess()); 570 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 571 } 572 573 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample buffers" << tcu::TestLog::EndMessage; 574 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 575 { 576 // sample id should be sample index 577 const int threshold = 255 / 4 / m_numTargetSamples + 1; 578 const float sampleIdColor = (float)sampleNdx / (float)m_numTargetSamples; 579 580 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage; 581 allOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, sampleIdColor, 1.0f), tcu::IVec3(1, threshold, 1)), false); 582 } 583 584 if (!allOk) 585 m_testCtx.getLog() << tcu::TestLog::Message << "Sample buffer verification failed" << tcu::TestLog::EndMessage; 586 587 return allOk; 588 } 589 590 class SamplePosDistributionCase : public MultisampleRenderCase 591 { 592 public: 593 SamplePosDistributionCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 594 ~SamplePosDistributionCase (void); 595 596 void init (void); 597 private: 598 enum 599 { 600 RENDER_SIZE = 64 601 }; 602 603 std::string genFragmentSource (int numTargetSamples) const; 604 bool verifyImage (const tcu::Surface& resultImage); 605 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers); 606 }; 607 608 SamplePosDistributionCase::SamplePosDistributionCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 609 : MultisampleRenderCase(context, name, desc, sampleCount, target, RENDER_SIZE, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS) 610 { 611 } 612 613 SamplePosDistributionCase::~SamplePosDistributionCase (void) 614 { 615 } 616 617 void SamplePosDistributionCase::init (void) 618 { 619 // log the test method and expectations 620 if (m_renderTarget == TARGET_TEXTURE) 621 { 622 m_testCtx.getLog() 623 << tcu::TestLog::Message 624 << "Verifying gl_SamplePosition value:\n" 625 << " 1) With non-multisample targets: Expect the center of the pixel.\n" 626 << " 2) With multisample targets:\n" 627 << " a) Expect legal sample position.\n" 628 << " b) Sample position is unique within the set of all sample positions of a pixel.\n" 629 << " c) Sample position distribution is uniform or almost uniform.\n" 630 << tcu::TestLog::EndMessage; 631 } 632 else 633 { 634 m_testCtx.getLog() 635 << tcu::TestLog::Message 636 << "Verifying gl_SamplePosition value:\n" 637 << " 1) With non-multisample targets: Expect the center of the pixel.\n" 638 << " 2) With multisample targets:\n" 639 << " a) Expect legal sample position.\n" 640 << " b) Sample position distribution is uniform or almost uniform.\n" 641 << tcu::TestLog::EndMessage; 642 } 643 644 MultisampleRenderCase::init(); 645 } 646 647 std::string SamplePosDistributionCase::genFragmentSource (int numTargetSamples) const 648 { 649 DE_ASSERT(numTargetSamples != 0); 650 DE_UNREF(numTargetSamples); 651 652 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1); 653 std::ostringstream buf; 654 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 655 map<string, string> args; 656 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 657 args["GLSL_EXTENSION"] = supportsES32 ? "\n" : "#extension GL_OES_sample_variables : require\n"; 658 659 if (multisampleTarget) 660 { 661 // encode the position to the output, use red channel as error channel 662 buf << "${GLSL_VERSION_DECL}\n" 663 "${GLSL_EXTENSION}\n" 664 "layout(location = 0) out mediump vec4 fragColor;\n" 665 "void main (void)\n" 666 "{\n" 667 " if (gl_SamplePosition.x < 0.0 || gl_SamplePosition.x > 1.0 || gl_SamplePosition.y < 0.0 || gl_SamplePosition.y > 1.0)\n" 668 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 669 " else\n" 670 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n" 671 "}\n"; 672 } 673 else 674 { 675 // verify value is ok 676 buf << "${GLSL_VERSION_DECL}\n" 677 "${GLSL_EXTENSION}\n" 678 "layout(location = 0) out mediump vec4 fragColor;\n" 679 "void main (void)\n" 680 "{\n" 681 " if (gl_SamplePosition.x != 0.5 || gl_SamplePosition.y != 0.5)\n" 682 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 683 " else\n" 684 " fragColor = vec4(0.0, gl_SamplePosition.x, gl_SamplePosition.y, 1.0);\n" 685 "}\n"; 686 } 687 688 return tcu::StringTemplate(buf.str()).specialize(args); 689 } 690 691 bool SamplePosDistributionCase::verifyImage (const tcu::Surface& resultImage) 692 { 693 const int sampleCount = (m_renderTarget == TARGET_DEFAULT) ? (m_context.getRenderTarget().getNumSamples()) : (m_numRequestedSamples); 694 SampleAverageVerifier verifier (sampleCount); 695 696 // check there is nothing in the error channel 697 if (!verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier())) 698 return false; 699 700 // position average should be around 0.5, 0.5 701 if (verifier.m_isStatisticallySignificant && !verifyImageWithVerifier(resultImage, m_testCtx.getLog(), verifier)) 702 throw MultisampleShaderRenderUtil::QualityWarning("Bias detected, sample positions are not uniformly distributed within the pixel"); 703 704 return true; 705 } 706 707 bool SamplePosDistributionCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers) 708 { 709 const int width = resultBuffers[0].getWidth(); 710 const int height = resultBuffers[0].getHeight(); 711 bool allOk = true; 712 bool distibutionError = false; 713 714 // Check sample range, uniqueness, and distribution, log layers 715 { 716 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers"); 717 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 718 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess()); 719 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 720 } 721 722 // verify range 723 { 724 bool rangeOk = true; 725 726 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position range" << tcu::TestLog::EndMessage; 727 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 728 { 729 // shader does the check, just check the shader error output (red) 730 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage; 731 rangeOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), NoRedVerifier(), false); 732 } 733 734 if (!rangeOk) 735 { 736 allOk = false; 737 738 m_testCtx.getLog() << tcu::TestLog::Message << "Sample position verification failed." << tcu::TestLog::EndMessage; 739 } 740 } 741 742 // Verify uniqueness 743 { 744 bool uniquenessOk = true; 745 tcu::Surface errorMask (width, height); 746 std::vector<tcu::Vec2> samplePositions (resultBuffers.size()); 747 int printCount = 0; 748 const int printFloodLimit = 5; 749 750 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 751 752 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position uniqueness." << tcu::TestLog::EndMessage; 753 754 for (int y = 0; y < height; ++y) 755 for (int x = 0; x < width; ++x) 756 { 757 bool samplePosNotUnique = false; 758 759 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 760 { 761 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y); 762 samplePositions[sampleNdx] = tcu::Vec2((float)color.getGreen() / 255.0f, (float)color.getBlue() / 255.0f); 763 } 764 765 // Just check there are no two samples with same positions 766 for (int sampleNdxA = 0; sampleNdxA < (int)resultBuffers.size() && (!samplePosNotUnique || printCount < printFloodLimit); ++sampleNdxA) 767 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < (int)resultBuffers.size() && (!samplePosNotUnique || printCount < printFloodLimit); ++sampleNdxB) 768 { 769 if (samplePositions[sampleNdxA] == samplePositions[sampleNdxB]) 770 { 771 if (++printCount <= printFloodLimit) 772 { 773 m_testCtx.getLog() 774 << tcu::TestLog::Message 775 << "Pixel (" << x << ", " << y << "): Samples " << sampleNdxA << " and " << sampleNdxB << " have the same position." 776 << tcu::TestLog::EndMessage; 777 } 778 779 samplePosNotUnique = true; 780 uniquenessOk = false; 781 errorMask.setPixel(x, y, tcu::RGBA::red()); 782 } 783 } 784 } 785 786 // end result 787 if (!uniquenessOk) 788 { 789 if (printCount > printFloodLimit) 790 m_testCtx.getLog() 791 << tcu::TestLog::Message 792 << "...\n" 793 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 794 << tcu::TestLog::EndMessage; 795 796 m_testCtx.getLog() 797 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage 798 << tcu::TestLog::ImageSet("Verification", "Image Verification") 799 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess()) 800 << tcu::TestLog::EndImageSet; 801 802 allOk = false; 803 } 804 } 805 806 // check distribution 807 { 808 const SampleAverageVerifier verifier (m_numTargetSamples); 809 tcu::Surface errorMask (width, height); 810 int printCount = 0; 811 const int printFloodLimit = 5; 812 813 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 814 815 // don't bother with small sample counts 816 if (verifier.m_isStatisticallySignificant) 817 { 818 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample position distribution is (nearly) unbiased." << tcu::TestLog::EndMessage; 819 verifier.logInfo(m_testCtx.getLog()); 820 821 for (int y = 0; y < height; ++y) 822 for (int x = 0; x < width; ++x) 823 { 824 tcu::IVec3 colorSum(0, 0, 0); 825 826 // color average 827 828 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 829 { 830 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y); 831 colorSum.x() += color.getRed(); 832 colorSum.y() += color.getBlue(); 833 colorSum.z() += color.getGreen(); 834 } 835 836 colorSum.x() /= m_numTargetSamples; 837 colorSum.y() /= m_numTargetSamples; 838 colorSum.z() /= m_numTargetSamples; 839 840 // verify average sample position 841 842 if (!verifier.verify(tcu::RGBA(colorSum.x(), colorSum.y(), colorSum.z(), 0), tcu::IVec2(x, y))) 843 { 844 if (++printCount <= printFloodLimit) 845 { 846 m_testCtx.getLog() 847 << tcu::TestLog::Message 848 << "Pixel (" << x << ", " << y << "): Sample distribution is biased." 849 << tcu::TestLog::EndMessage; 850 } 851 852 distibutionError = true; 853 errorMask.setPixel(x, y, tcu::RGBA::red()); 854 } 855 } 856 857 // sub-verification result 858 if (distibutionError) 859 { 860 if (printCount > printFloodLimit) 861 m_testCtx.getLog() 862 << tcu::TestLog::Message 863 << "...\n" 864 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 865 << tcu::TestLog::EndMessage; 866 867 m_testCtx.getLog() 868 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage 869 << tcu::TestLog::ImageSet("Verification", "Image Verification") 870 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess()) 871 << tcu::TestLog::EndImageSet; 872 } 873 } 874 } 875 876 // results 877 if (!allOk) 878 return false; 879 else if (distibutionError) 880 throw MultisampleShaderRenderUtil::QualityWarning("Bias detected, sample positions are not uniformly distributed within the pixel"); 881 else 882 { 883 m_testCtx.getLog() << tcu::TestLog::Message << "Verification ok." << tcu::TestLog::EndMessage; 884 return true; 885 } 886 } 887 888 class SamplePosCorrectnessCase : public MultisampleRenderCase 889 { 890 public: 891 SamplePosCorrectnessCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 892 ~SamplePosCorrectnessCase (void); 893 894 void init (void); 895 private: 896 enum 897 { 898 RENDER_SIZE = 32 899 }; 900 901 void preDraw (void); 902 void postDraw (void); 903 904 std::string genVertexSource (int numTargetSamples) const; 905 std::string genFragmentSource (int numTargetSamples) const; 906 bool verifyImage (const tcu::Surface& resultImage); 907 908 bool m_useSampleQualifier; 909 }; 910 911 SamplePosCorrectnessCase::SamplePosCorrectnessCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 912 : MultisampleRenderCase (context, name, desc, sampleCount, target, RENDER_SIZE) 913 , m_useSampleQualifier (false) 914 { 915 } 916 917 SamplePosCorrectnessCase::~SamplePosCorrectnessCase (void) 918 { 919 } 920 921 void SamplePosCorrectnessCase::init (void) 922 { 923 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 924 // requirements: per-invocation interpolation required 925 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation") && 926 !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading")) 927 TCU_THROW(NotSupportedError, "Test requires GL_OES_shader_multisample_interpolation or GL_OES_sample_shading extension or a context version 3.2 or higher."); 928 929 // prefer to use the sample qualifier path 930 m_useSampleQualifier = m_context.getContextInfo().isExtensionSupported("GL_OES_shader_multisample_interpolation"); 931 932 // log the test method and expectations 933 m_testCtx.getLog() 934 << tcu::TestLog::Message 935 << "Verifying gl_SamplePosition correctness:\n" 936 << " 1) Varying values should be sampled at the sample position.\n" 937 << " => fract(screenSpacePosition) == gl_SamplePosition\n" 938 << tcu::TestLog::EndMessage; 939 940 MultisampleRenderCase::init(); 941 } 942 943 void SamplePosCorrectnessCase::preDraw (void) 944 { 945 if (!m_useSampleQualifier) 946 { 947 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 948 949 // use GL_OES_sample_shading to set per fragment sample invocation interpolation 950 gl.enable(GL_SAMPLE_SHADING); 951 gl.minSampleShading(1.0f); 952 GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio"); 953 954 m_testCtx.getLog() << tcu::TestLog::Message << "Enabling per-sample interpolation with GL_SAMPLE_SHADING." << tcu::TestLog::EndMessage; 955 } 956 } 957 958 void SamplePosCorrectnessCase::postDraw (void) 959 { 960 if (!m_useSampleQualifier) 961 { 962 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 963 964 gl.disable(GL_SAMPLE_SHADING); 965 gl.minSampleShading(1.0f); 966 GLU_EXPECT_NO_ERROR(gl.getError(), "set ratio"); 967 } 968 } 969 970 std::string SamplePosCorrectnessCase::genVertexSource (int numTargetSamples) const 971 { 972 DE_UNREF(numTargetSamples); 973 974 std::ostringstream buf; 975 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 976 map<string, string> args; 977 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 978 args["GLSL_EXTENSION"] = supportsES32 ? "" : m_useSampleQualifier ? "#extension GL_OES_shader_multisample_interpolation : require" : ""; 979 980 buf << "${GLSL_VERSION_DECL}\n" 981 "${GLSL_EXTENSION}\n" 982 << "in highp vec4 a_position;\n" 983 << ((m_useSampleQualifier) ? ("sample ") : ("")) << "out highp vec4 v_position;\n" 984 "void main (void)\n" 985 "{\n" 986 " gl_Position = a_position;\n" 987 " v_position = a_position;\n" 988 "}\n"; 989 990 return tcu::StringTemplate(buf.str()).specialize(args); 991 } 992 993 std::string SamplePosCorrectnessCase::genFragmentSource (int numTargetSamples) const 994 { 995 DE_UNREF(numTargetSamples); 996 997 std::ostringstream buf; 998 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 999 map<string, string> args; 1000 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 1001 args["GLSL_SAMPLE_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 1002 args["GLSL_MULTISAMPLE_EXTENSION"] = supportsES32 ? "" : m_useSampleQualifier ? "#extension GL_OES_shader_multisample_interpolation : require" : ""; 1003 1004 // encode the position to the output, use red channel as error channel 1005 buf << "${GLSL_VERSION_DECL}\n" 1006 "${GLSL_SAMPLE_EXTENSION}\n" 1007 "${GLSL_MULTISAMPLE_EXTENSION}\n" 1008 << ((m_useSampleQualifier) ? ("sample ") : ("")) << "in highp vec4 v_position;\n" 1009 "layout(location = 0) out mediump vec4 fragColor;\n" 1010 "void main (void)\n" 1011 "{\n" 1012 " const highp float maxDistance = 0.15625; // 4 subpixel bits. Assume 3 accurate bits + 0.03125 for other errors\n" // 0.03125 = mediump epsilon when value = 32 (RENDER_SIZE) 1013 "\n" 1014 " highp vec2 screenSpacePosition = (v_position.xy + vec2(1.0, 1.0)) / 2.0 * " << (int)RENDER_SIZE << ".0;\n" 1015 " highp ivec2 nearbyPixel = ivec2(floor(screenSpacePosition));\n" 1016 " bool allOk = false;\n" 1017 "\n" 1018 " // sample at edge + inaccuaries may cause us to round to any neighboring pixel\n" 1019 " // check all neighbors for any match\n" 1020 " for (highp int dy = -1; dy <= 1; ++dy)\n" 1021 " for (highp int dx = -1; dx <= 1; ++dx)\n" 1022 " {\n" 1023 " highp ivec2 currentPixel = nearbyPixel + ivec2(dx, dy);\n" 1024 " highp vec2 candidateSamplingPos = vec2(currentPixel) + gl_SamplePosition.xy;\n" 1025 " highp vec2 positionDiff = abs(candidateSamplingPos - screenSpacePosition);\n" 1026 " if (positionDiff.x < maxDistance && positionDiff.y < maxDistance)\n" 1027 " allOk = true;\n" 1028 " }\n" 1029 "\n" 1030 " if (allOk)\n" 1031 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1032 " else\n" 1033 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1034 "}\n"; 1035 1036 return tcu::StringTemplate(buf.str()).specialize(args); 1037 } 1038 1039 bool SamplePosCorrectnessCase::verifyImage (const tcu::Surface& resultImage) 1040 { 1041 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()); 1042 } 1043 1044 class SampleMaskBaseCase : public MultisampleRenderCase 1045 { 1046 public: 1047 enum ShaderRunMode 1048 { 1049 RUN_PER_PIXEL = 0, 1050 RUN_PER_SAMPLE, 1051 RUN_PER_TWO_SAMPLES, 1052 1053 RUN_LAST 1054 }; 1055 1056 SampleMaskBaseCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, int renderSize, ShaderRunMode runMode, int flags = 0); 1057 virtual ~SampleMaskBaseCase (void); 1058 1059 protected: 1060 virtual void init (void); 1061 virtual void preDraw (void); 1062 virtual void postDraw (void); 1063 virtual bool verifyImage (const tcu::Surface& resultImage); 1064 1065 const ShaderRunMode m_runMode; 1066 }; 1067 1068 SampleMaskBaseCase::SampleMaskBaseCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, int renderSize, ShaderRunMode runMode, int flags) 1069 : MultisampleRenderCase (context, name, desc, sampleCount, target, renderSize, flags) 1070 , m_runMode (runMode) 1071 { 1072 DE_ASSERT(runMode < RUN_LAST); 1073 } 1074 1075 SampleMaskBaseCase::~SampleMaskBaseCase (void) 1076 { 1077 } 1078 1079 void SampleMaskBaseCase::init (void) 1080 { 1081 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1082 // required extra extension 1083 if (m_runMode == RUN_PER_TWO_SAMPLES && !supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_OES_sample_shading")) 1084 TCU_THROW(NotSupportedError, "Test requires GL_OES_sample_shading extension or a context version 3.2 or higher."); 1085 1086 MultisampleRenderCase::init(); 1087 } 1088 1089 void SampleMaskBaseCase::preDraw (void) 1090 { 1091 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1092 1093 if (m_runMode == RUN_PER_TWO_SAMPLES) 1094 { 1095 gl.enable(GL_SAMPLE_SHADING); 1096 gl.minSampleShading(0.5f); 1097 GLU_EXPECT_NO_ERROR(gl.getError(), "enable sample shading"); 1098 1099 m_testCtx.getLog() << tcu::TestLog::Message << "Enabled GL_SAMPLE_SHADING, value = 0.5" << tcu::TestLog::EndMessage; 1100 } 1101 } 1102 1103 void SampleMaskBaseCase::postDraw (void) 1104 { 1105 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1106 1107 if (m_runMode == RUN_PER_TWO_SAMPLES) 1108 { 1109 gl.disable(GL_SAMPLE_SHADING); 1110 gl.minSampleShading(1.0f); 1111 GLU_EXPECT_NO_ERROR(gl.getError(), "disable sample shading"); 1112 } 1113 } 1114 1115 bool SampleMaskBaseCase::verifyImage (const tcu::Surface& resultImage) 1116 { 1117 // shader does the verification 1118 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), NoRedVerifier()); 1119 } 1120 1121 class SampleMaskCase : public SampleMaskBaseCase 1122 { 1123 public: 1124 SampleMaskCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target); 1125 ~SampleMaskCase (void); 1126 1127 void init (void); 1128 void preDraw (void); 1129 void postDraw (void); 1130 1131 private: 1132 enum 1133 { 1134 RENDER_SIZE = 64 1135 }; 1136 1137 std::string genFragmentSource (int numTargetSamples) const; 1138 }; 1139 1140 SampleMaskCase::SampleMaskCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target) 1141 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, RUN_PER_PIXEL) 1142 { 1143 } 1144 1145 SampleMaskCase::~SampleMaskCase (void) 1146 { 1147 } 1148 1149 void SampleMaskCase::init (void) 1150 { 1151 // log the test method and expectations 1152 m_testCtx.getLog() 1153 << tcu::TestLog::Message 1154 << "Verifying gl_SampleMaskIn value with SAMPLE_MASK state. gl_SampleMaskIn does not contain any bits set that are have been killed by SAMPLE_MASK state. Expecting:\n" 1155 << " 1) With multisample targets: gl_SampleMaskIn AND ~(SAMPLE_MASK) should be zero.\n" 1156 << " 2) With non-multisample targets: SAMPLE_MASK state is only ANDed as a multisample operation. gl_SampleMaskIn should only have its last bit set regardless of SAMPLE_MASK state.\n" 1157 << tcu::TestLog::EndMessage; 1158 1159 SampleMaskBaseCase::init(); 1160 } 1161 1162 void SampleMaskCase::preDraw (void) 1163 { 1164 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1165 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1); 1166 const deUint32 fullMask = (deUint32)0xAAAAAAAAUL; 1167 const deUint32 maskMask = (1U << m_numTargetSamples) - 1; 1168 const deUint32 effectiveMask = fullMask & maskMask; 1169 1170 // set test mask 1171 gl.enable(GL_SAMPLE_MASK); 1172 gl.sampleMaski(0, effectiveMask); 1173 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask"); 1174 1175 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(effectiveMask) << tcu::TestLog::EndMessage; 1176 1177 // set multisample case uniforms 1178 if (multisampleTarget) 1179 { 1180 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_sampleMask"); 1181 if (maskLoc == -1) 1182 throw tcu::TestError("Location of u_mask was -1"); 1183 1184 gl.uniform1ui(maskLoc, effectiveMask); 1185 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform"); 1186 } 1187 1188 // base class logic 1189 SampleMaskBaseCase::preDraw(); 1190 } 1191 1192 void SampleMaskCase::postDraw (void) 1193 { 1194 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1195 const deUint32 fullMask = (1U << m_numTargetSamples) - 1; 1196 1197 gl.disable(GL_SAMPLE_MASK); 1198 gl.sampleMaski(0, fullMask); 1199 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask"); 1200 1201 // base class logic 1202 SampleMaskBaseCase::postDraw(); 1203 } 1204 1205 std::string SampleMaskCase::genFragmentSource (int numTargetSamples) const 1206 { 1207 DE_ASSERT(numTargetSamples != 0); 1208 1209 const bool multisampleTarget = (m_numRequestedSamples > 0) || (m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1); 1210 std::ostringstream buf; 1211 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1212 map<string, string> args; 1213 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 1214 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 1215 1216 // test supports only one sample mask word 1217 if (numTargetSamples > 32) 1218 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported."); 1219 1220 if (multisampleTarget) 1221 { 1222 buf << "${GLSL_VERSION_DECL}\n" 1223 "${GLSL_EXTENSION}\n" 1224 "layout(location = 0) out mediump vec4 fragColor;\n" 1225 "uniform highp uint u_sampleMask;\n" 1226 "void main (void)\n" 1227 "{\n" 1228 " if ((uint(gl_SampleMaskIn[0]) & (~u_sampleMask)) != 0u)\n" 1229 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1230 " else\n" 1231 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1232 "}\n"; 1233 } 1234 else 1235 { 1236 // non-multisample targets don't get multisample operations like ANDing with mask 1237 1238 buf << "${GLSL_VERSION_DECL}\n" 1239 "${GLSL_EXTENSION}\n" 1240 "layout(location = 0) out mediump vec4 fragColor;\n" 1241 "uniform highp uint u_sampleMask;\n" 1242 "void main (void)\n" 1243 "{\n" 1244 " if (gl_SampleMaskIn[0] != 1)\n" 1245 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1246 " else\n" 1247 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1248 "}\n"; 1249 } 1250 1251 return tcu::StringTemplate(buf.str()).specialize(args); 1252 } 1253 1254 class SampleMaskCountCase : public SampleMaskBaseCase 1255 { 1256 public: 1257 SampleMaskCountCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode); 1258 ~SampleMaskCountCase (void); 1259 1260 void init (void); 1261 void preDraw (void); 1262 void postDraw (void); 1263 1264 private: 1265 enum 1266 { 1267 RENDER_SIZE = 64 1268 }; 1269 1270 std::string genFragmentSource (int numTargetSamples) const; 1271 }; 1272 1273 SampleMaskCountCase::SampleMaskCountCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode) 1274 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode) 1275 { 1276 DE_ASSERT(runMode < RUN_LAST); 1277 } 1278 1279 SampleMaskCountCase::~SampleMaskCountCase (void) 1280 { 1281 } 1282 1283 void SampleMaskCountCase::init (void) 1284 { 1285 // log the test method and expectations 1286 if (m_runMode == RUN_PER_PIXEL) 1287 m_testCtx.getLog() 1288 << tcu::TestLog::Message 1289 << "Verifying gl_SampleMaskIn.\n" 1290 << " Fragment shader may be invoked [1, numSamples] times.\n" 1291 << " => gl_SampleMaskIn should have the number of bits set in range [1, numSamples]\n" 1292 << tcu::TestLog::EndMessage; 1293 else if (m_runMode == RUN_PER_SAMPLE) 1294 m_testCtx.getLog() 1295 << tcu::TestLog::Message 1296 << "Verifying gl_SampleMaskIn.\n" 1297 << " Fragment will be invoked numSamples times.\n" 1298 << " => gl_SampleMaskIn should have only one bit set.\n" 1299 << tcu::TestLog::EndMessage; 1300 else if (m_runMode == RUN_PER_TWO_SAMPLES) 1301 m_testCtx.getLog() 1302 << tcu::TestLog::Message 1303 << "Verifying gl_SampleMaskIn.\n" 1304 << " Fragment shader may be invoked [ceil(numSamples/2), numSamples] times.\n" 1305 << " => gl_SampleMaskIn should have the number of bits set in range [1, numSamples - ceil(numSamples/2) + 1]:\n" 1306 << tcu::TestLog::EndMessage; 1307 else 1308 DE_ASSERT(false); 1309 1310 SampleMaskBaseCase::init(); 1311 } 1312 1313 void SampleMaskCountCase::preDraw (void) 1314 { 1315 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1316 1317 if (m_runMode == RUN_PER_PIXEL) 1318 { 1319 const int maxLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxBitCount"); 1320 const int minLoc = gl.getUniformLocation(m_program->getProgram(), "u_minBitCount"); 1321 const int minBitCount = 1; 1322 const int maxBitCount = m_numTargetSamples; 1323 1324 if (maxLoc == -1) 1325 throw tcu::TestError("Location of u_maxBitCount was -1"); 1326 if (minLoc == -1) 1327 throw tcu::TestError("Location of u_minBitCount was -1"); 1328 1329 gl.uniform1i(minLoc, minBitCount); 1330 gl.uniform1i(maxLoc, maxBitCount); 1331 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits"); 1332 1333 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage; 1334 } 1335 else if (m_runMode == RUN_PER_TWO_SAMPLES) 1336 { 1337 const int maxLoc = gl.getUniformLocation(m_program->getProgram(), "u_maxBitCount"); 1338 const int minLoc = gl.getUniformLocation(m_program->getProgram(), "u_minBitCount"); 1339 1340 // Worst case: all but one shader invocations get one sample, one shader invocation the rest of the samples 1341 const int minInvocationCount = ((m_numTargetSamples + 1) / 2); 1342 const int minBitCount = 1; 1343 const int maxBitCount = m_numTargetSamples - ((minInvocationCount-1) * minBitCount); 1344 1345 if (maxLoc == -1) 1346 throw tcu::TestError("Location of u_maxBitCount was -1"); 1347 if (minLoc == -1) 1348 throw tcu::TestError("Location of u_minBitCount was -1"); 1349 1350 gl.uniform1i(minLoc, minBitCount); 1351 gl.uniform1i(maxLoc, maxBitCount); 1352 GLU_EXPECT_NO_ERROR(gl.getError(), "set limits"); 1353 1354 m_testCtx.getLog() << tcu::TestLog::Message << "Setting minBitCount = " << minBitCount << ", maxBitCount = " << maxBitCount << tcu::TestLog::EndMessage; 1355 } 1356 1357 SampleMaskBaseCase::preDraw(); 1358 } 1359 1360 void SampleMaskCountCase::postDraw (void) 1361 { 1362 SampleMaskBaseCase::postDraw(); 1363 } 1364 1365 std::string SampleMaskCountCase::genFragmentSource (int numTargetSamples) const 1366 { 1367 DE_ASSERT(numTargetSamples != 0); 1368 1369 std::ostringstream buf; 1370 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1371 map<string, string> args; 1372 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 1373 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 1374 1375 // test supports only one sample mask word 1376 if (numTargetSamples > 32) 1377 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported."); 1378 1379 // count the number of the bits in gl_SampleMask 1380 1381 buf << "${GLSL_VERSION_DECL}\n" 1382 "${GLSL_EXTENSION}\n" 1383 "layout(location = 0) out mediump vec4 fragColor;\n"; 1384 1385 if (m_runMode != RUN_PER_SAMPLE) 1386 buf << "uniform highp int u_minBitCount;\n" 1387 "uniform highp int u_maxBitCount;\n"; 1388 1389 buf << "void main (void)\n" 1390 "{\n" 1391 " mediump int maskBitCount = 0;\n" 1392 " for (int i = 0; i < 32; ++i)\n" 1393 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n" 1394 " ++maskBitCount;\n" 1395 "\n"; 1396 1397 if (m_runMode == RUN_PER_SAMPLE) 1398 { 1399 // check the validity here 1400 buf << " // force per-sample shading\n" 1401 " highp float blue = float(gl_SampleID);\n" 1402 "\n" 1403 " if (maskBitCount != 1)\n" 1404 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n" 1405 " else\n" 1406 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n" 1407 "}\n"; 1408 } 1409 else 1410 { 1411 // check the validity here 1412 buf << " if (maskBitCount < u_minBitCount || maskBitCount > u_maxBitCount)\n" 1413 " fragColor = vec4(1.0, 0.0, 0.0, 1.0);\n" 1414 " else\n" 1415 " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 1416 "}\n"; 1417 } 1418 1419 return tcu::StringTemplate(buf.str()).specialize(args); 1420 } 1421 1422 class SampleMaskUniqueCase : public SampleMaskBaseCase 1423 { 1424 public: 1425 SampleMaskUniqueCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode); 1426 ~SampleMaskUniqueCase (void); 1427 1428 void init (void); 1429 1430 private: 1431 enum 1432 { 1433 RENDER_SIZE = 64 1434 }; 1435 1436 std::string genFragmentSource (int numTargetSamples) const; 1437 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers); 1438 }; 1439 1440 SampleMaskUniqueCase::SampleMaskUniqueCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode) 1441 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS) 1442 { 1443 DE_ASSERT(runMode == RUN_PER_SAMPLE); 1444 DE_ASSERT(target == TARGET_TEXTURE); 1445 } 1446 1447 SampleMaskUniqueCase::~SampleMaskUniqueCase (void) 1448 { 1449 } 1450 1451 void SampleMaskUniqueCase::init (void) 1452 { 1453 // log the test method and expectations 1454 m_testCtx.getLog() 1455 << tcu::TestLog::Message 1456 << "Verifying gl_SampleMaskIn.\n" 1457 << " Fragment will be invoked numSamples times.\n" 1458 << " => gl_SampleMaskIn should have only one bit set\n" 1459 << " => and that bit index should be unique within other fragment shader invocations of that pixel.\n" 1460 << " Writing sampleMask bit index to green channel in render shader. Verifying uniqueness in sampler shader.\n" 1461 << tcu::TestLog::EndMessage; 1462 1463 SampleMaskBaseCase::init(); 1464 } 1465 1466 std::string SampleMaskUniqueCase::genFragmentSource (int numTargetSamples) const 1467 { 1468 DE_ASSERT(numTargetSamples != 0); 1469 1470 std::ostringstream buf; 1471 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1472 map<string, string> args; 1473 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 1474 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 1475 1476 // test supports only one sample mask word 1477 if (numTargetSamples > 32) 1478 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported."); 1479 1480 // find our sampleID by searching for unique bit. 1481 buf << "${GLSL_VERSION_DECL}\n" 1482 "${GLSL_EXTENSION}\n" 1483 "layout(location = 0) out mediump vec4 fragColor;\n" 1484 "void main (void)\n" 1485 "{\n" 1486 " mediump int firstIndex = -1;\n" 1487 " for (int i = 0; i < 32; ++i)\n" 1488 " {\n" 1489 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n" 1490 " {\n" 1491 " firstIndex = i;\n" 1492 " break;\n" 1493 " }\n" 1494 " }\n" 1495 "\n" 1496 " bool notUniqueError = false;\n" 1497 " for (int i = firstIndex + 1; i < 32; ++i)\n" 1498 " if (((gl_SampleMaskIn[0] >> i) & 0x01) == 0x01)\n" 1499 " notUniqueError = true;\n" 1500 "\n" 1501 " highp float encodedSampleId = float(firstIndex) / " << numTargetSamples <<".0;\n" 1502 "\n" 1503 " // force per-sample shading\n" 1504 " highp float blue = float(gl_SampleID);\n" 1505 "\n" 1506 " if (notUniqueError)\n" 1507 " fragColor = vec4(1.0, 0.0, blue, 1.0);\n" 1508 " else\n" 1509 " fragColor = vec4(0.0, encodedSampleId, blue, 1.0);\n" 1510 "}\n"; 1511 1512 return tcu::StringTemplate(buf.str()).specialize(args); 1513 } 1514 1515 bool SampleMaskUniqueCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers) 1516 { 1517 const int width = resultBuffers[0].getWidth(); 1518 const int height = resultBuffers[0].getHeight(); 1519 bool allOk = true; 1520 1521 // Log samples 1522 { 1523 m_testCtx.getLog() << tcu::TestLog::ImageSet("SampleBuffers", "Image sample buffers"); 1524 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 1525 m_testCtx.getLog() << tcu::TestLog::Image("Buffer" + de::toString(sampleNdx), "Sample " + de::toString(sampleNdx), resultBuffers[sampleNdx].getAccess()); 1526 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 1527 } 1528 1529 // check for earlier errors (in fragment shader) 1530 { 1531 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying fragment shader invocation found only one set sample mask bit." << tcu::TestLog::EndMessage; 1532 1533 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 1534 { 1535 // shader does the check, just check the shader error output (red) 1536 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample " << (sampleNdx+1) << "/" << (int)resultBuffers.size() << tcu::TestLog::EndMessage; 1537 allOk &= verifyImageWithVerifier(resultBuffers[sampleNdx], m_testCtx.getLog(), NoRedVerifier(), false); 1538 } 1539 1540 if (!allOk) 1541 { 1542 // can't check the uniqueness if the masks don't work at all 1543 m_testCtx.getLog() << tcu::TestLog::Message << "Could not get mask information from the rendered image, cannot continue verification." << tcu::TestLog::EndMessage; 1544 return false; 1545 } 1546 } 1547 1548 // verify index / index ranges 1549 1550 if (m_numRequestedSamples == 0) 1551 { 1552 // single sample target, expect index=0 1553 1554 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask bit index is 0." << tcu::TestLog::EndMessage; 1555 1556 // only check the mask index 1557 allOk &= verifyImageWithVerifier(resultBuffers[0], m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f), tcu::IVec3(255, 8, 255)), false); 1558 } 1559 else 1560 { 1561 // check uniqueness 1562 1563 tcu::Surface errorMask (width, height); 1564 bool uniquenessOk = true; 1565 int printCount = 0; 1566 const int printFloodLimit = 5; 1567 std::vector<int> maskBitIndices (resultBuffers.size()); 1568 1569 tcu::clear(errorMask.getAccess(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f)); 1570 1571 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying per-invocation sample mask bit is unique." << tcu::TestLog::EndMessage; 1572 1573 for (int y = 0; y < height; ++y) 1574 for (int x = 0; x < width; ++x) 1575 { 1576 bool maskNdxNotUnique = false; 1577 1578 // decode index 1579 for (int sampleNdx = 0; sampleNdx < (int)resultBuffers.size(); ++sampleNdx) 1580 { 1581 const tcu::RGBA color = resultBuffers[sampleNdx].getPixel(x, y); 1582 maskBitIndices[sampleNdx] = (int)deFloatRound((float)color.getGreen() / 255.0f * (float)m_numTargetSamples); 1583 } 1584 1585 // just check there are no two invocations with the same bit index 1586 for (int sampleNdxA = 0; sampleNdxA < (int)resultBuffers.size() && (!maskNdxNotUnique || printCount < printFloodLimit); ++sampleNdxA) 1587 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < (int)resultBuffers.size() && (!maskNdxNotUnique || printCount < printFloodLimit); ++sampleNdxB) 1588 { 1589 if (maskBitIndices[sampleNdxA] == maskBitIndices[sampleNdxB]) 1590 { 1591 if (++printCount <= printFloodLimit) 1592 { 1593 m_testCtx.getLog() 1594 << tcu::TestLog::Message 1595 << "Pixel (" << x << ", " << y << "): Samples " << sampleNdxA << " and " << sampleNdxB << " have the same sample mask. (Single bit at index " << maskBitIndices[sampleNdxA] << ")" 1596 << tcu::TestLog::EndMessage; 1597 } 1598 1599 maskNdxNotUnique = true; 1600 uniquenessOk = false; 1601 errorMask.setPixel(x, y, tcu::RGBA::red()); 1602 } 1603 } 1604 } 1605 1606 // end result 1607 if (!uniquenessOk) 1608 { 1609 if (printCount > printFloodLimit) 1610 m_testCtx.getLog() 1611 << tcu::TestLog::Message 1612 << "...\n" 1613 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 1614 << tcu::TestLog::EndMessage; 1615 1616 m_testCtx.getLog() 1617 << tcu::TestLog::Message << "Image verification failed." << tcu::TestLog::EndMessage 1618 << tcu::TestLog::ImageSet("Verification", "Image Verification") 1619 << tcu::TestLog::Image("ErrorMask", "Error Mask", errorMask.getAccess()) 1620 << tcu::TestLog::EndImageSet; 1621 1622 allOk = false; 1623 } 1624 } 1625 1626 return allOk; 1627 } 1628 1629 class SampleMaskUniqueSetCase : public SampleMaskBaseCase 1630 { 1631 public: 1632 SampleMaskUniqueSetCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode); 1633 ~SampleMaskUniqueSetCase (void); 1634 1635 void init (void); 1636 void deinit (void); 1637 1638 private: 1639 enum 1640 { 1641 RENDER_SIZE = 64 1642 }; 1643 1644 void preDraw (void); 1645 void postDraw (void); 1646 std::string genFragmentSource (int numTargetSamples) const; 1647 bool verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers); 1648 std::string getIterationDescription (int iteration) const; 1649 1650 void preTest (void); 1651 void postTest (void); 1652 1653 std::vector<tcu::Surface> m_iterationSampleBuffers; 1654 }; 1655 1656 SampleMaskUniqueSetCase::SampleMaskUniqueSetCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode) 1657 : SampleMaskBaseCase(context, name, desc, sampleCount, target, RENDER_SIZE, runMode, MultisampleShaderRenderUtil::MultisampleRenderCase::FLAG_VERIFY_MSAA_TEXTURE_SAMPLE_BUFFERS) 1658 { 1659 DE_ASSERT(runMode == RUN_PER_TWO_SAMPLES); 1660 DE_ASSERT(target == TARGET_TEXTURE); 1661 1662 // high and low bits 1663 m_numIterations = 2; 1664 } 1665 1666 SampleMaskUniqueSetCase::~SampleMaskUniqueSetCase (void) 1667 { 1668 } 1669 1670 void SampleMaskUniqueSetCase::init (void) 1671 { 1672 // log the test method and expectations 1673 m_testCtx.getLog() 1674 << tcu::TestLog::Message 1675 << "Verifying gl_SampleMaskIn.\n" 1676 << " Fragment shader may be invoked [ceil(numSamples/2), numSamples] times.\n" 1677 << " => Each invocation should have unique bit set\n" 1678 << " Writing highest and lowest bit index to color channels in render shader. Verifying:\n" 1679 << " 1) no other invocation contains these bits in sampler shader.\n" 1680 << " 2) number of invocations is at least ceil(numSamples/2).\n" 1681 << tcu::TestLog::EndMessage; 1682 1683 SampleMaskBaseCase::init(); 1684 } 1685 1686 void SampleMaskUniqueSetCase::deinit (void) 1687 { 1688 m_iterationSampleBuffers.clear(); 1689 } 1690 1691 void SampleMaskUniqueSetCase::preDraw (void) 1692 { 1693 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 1694 const int selectorLoc = gl.getUniformLocation(m_program->getProgram(), "u_bitSelector"); 1695 1696 gl.uniform1ui(selectorLoc, (deUint32)m_iteration); 1697 GLU_EXPECT_NO_ERROR(gl.getError(), "set u_bitSelector"); 1698 1699 m_testCtx.getLog() << tcu::TestLog::Message << "Setting u_bitSelector = " << m_iteration << tcu::TestLog::EndMessage; 1700 1701 SampleMaskBaseCase::preDraw(); 1702 } 1703 1704 void SampleMaskUniqueSetCase::postDraw (void) 1705 { 1706 SampleMaskBaseCase::postDraw(); 1707 } 1708 1709 std::string SampleMaskUniqueSetCase::genFragmentSource (int numTargetSamples) const 1710 { 1711 DE_ASSERT(numTargetSamples != 0); 1712 1713 std::ostringstream buf; 1714 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 1715 map<string, string> args; 1716 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 1717 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 1718 1719 // test supports only one sample mask word 1720 if (numTargetSamples > 32) 1721 TCU_THROW(NotSupportedError, "Sample count larger than 32 is not supported."); 1722 1723 // output min and max sample id 1724 buf << "${GLSL_VERSION_DECL}\n" 1725 "${GLSL_EXTENSION}\n" 1726 "uniform highp uint u_bitSelector;\n" 1727 "layout(location = 0) out mediump vec4 fragColor;\n" 1728 "void main (void)\n" 1729 "{\n" 1730 " highp int selectedBits;\n" 1731 " if (u_bitSelector == 0u)\n" 1732 " selectedBits = (gl_SampleMaskIn[0] & 0xFFFF);\n" 1733 " else\n" 1734 " selectedBits = ((gl_SampleMaskIn[0] >> 16) & 0xFFFF);\n" 1735 "\n" 1736 " // encode bits to color\n" 1737 " highp int redBits = selectedBits & 31;\n" 1738 " highp int greenBits = (selectedBits >> 5) & 63;\n" 1739 " highp int blueBits = (selectedBits >> 11) & 31;\n" 1740 "\n" 1741 " fragColor = vec4(float(redBits) / float(31), float(greenBits) / float(63), float(blueBits) / float(31), 1.0);\n" 1742 "}\n"; 1743 1744 return tcu::StringTemplate(buf.str()).specialize(args); 1745 } 1746 1747 bool SampleMaskUniqueSetCase::verifySampleBuffers (const std::vector<tcu::Surface>& resultBuffers) 1748 { 1749 // we need results from all passes to do verification. Store results and verify later (at postTest). 1750 1751 DE_ASSERT(m_numTargetSamples == (int)resultBuffers.size()); 1752 for (int ndx = 0; ndx < m_numTargetSamples; ++ndx) 1753 m_iterationSampleBuffers[m_iteration * m_numTargetSamples + ndx] = resultBuffers[ndx]; 1754 1755 return true; 1756 } 1757 1758 std::string SampleMaskUniqueSetCase::getIterationDescription (int iteration) const 1759 { 1760 if (iteration == 0) 1761 return "Reading low bits"; 1762 else if (iteration == 1) 1763 return "Reading high bits"; 1764 else 1765 DE_ASSERT(false); 1766 return ""; 1767 } 1768 1769 void SampleMaskUniqueSetCase::preTest (void) 1770 { 1771 m_iterationSampleBuffers.resize(m_numTargetSamples * 2); 1772 } 1773 1774 void SampleMaskUniqueSetCase::postTest (void) 1775 { 1776 DE_ASSERT((m_iterationSampleBuffers.size() % 2) == 0); 1777 DE_ASSERT((int)m_iterationSampleBuffers.size() / 2 == m_numTargetSamples); 1778 1779 const int width = m_iterationSampleBuffers[0].getWidth(); 1780 const int height = m_iterationSampleBuffers[0].getHeight(); 1781 bool allOk = true; 1782 std::vector<tcu::TextureLevel> sampleCoverage (m_numTargetSamples); 1783 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Verify", "Verify masks"); 1784 1785 // convert color layers to 32 bit coverage masks, 2 passes per coverage 1786 1787 for (int sampleNdx = 0; sampleNdx < (int)sampleCoverage.size(); ++sampleNdx) 1788 { 1789 sampleCoverage[sampleNdx].setStorage(tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32), width, height); 1790 1791 for (int y = 0; y < height; ++y) 1792 for (int x = 0; x < width; ++x) 1793 { 1794 const tcu::RGBA lowColor = m_iterationSampleBuffers[sampleNdx].getPixel(x, y); 1795 const tcu::RGBA highColor = m_iterationSampleBuffers[sampleNdx + (int)sampleCoverage.size()].getPixel(x, y); 1796 deUint16 low; 1797 deUint16 high; 1798 1799 { 1800 int redBits = (int)deFloatRound((float)lowColor.getRed() / 255.0f * 31); 1801 int greenBits = (int)deFloatRound((float)lowColor.getGreen() / 255.0f * 63); 1802 int blueBits = (int)deFloatRound((float)lowColor.getBlue() / 255.0f * 31); 1803 1804 low = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11)); 1805 } 1806 { 1807 int redBits = (int)deFloatRound((float)highColor.getRed() / 255.0f * 31); 1808 int greenBits = (int)deFloatRound((float)highColor.getGreen() / 255.0f * 63); 1809 int blueBits = (int)deFloatRound((float)highColor.getBlue() / 255.0f * 31); 1810 1811 high = (deUint16)(redBits | (greenBits << 5) | (blueBits << 11)); 1812 } 1813 1814 sampleCoverage[sampleNdx].getAccess().setPixel(tcu::UVec4((((deUint32)high) << 16) | low, 0, 0, 0), x, y); 1815 } 1816 } 1817 1818 // verify masks 1819 1820 if (m_numRequestedSamples == 0) 1821 { 1822 // single sample target, expect mask = 0x01 1823 const int printFloodLimit = 5; 1824 int printCount = 0; 1825 1826 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying sample mask is 0x00000001." << tcu::TestLog::EndMessage; 1827 1828 for (int y = 0; y < height; ++y) 1829 for (int x = 0; x < width; ++x) 1830 { 1831 deUint32 mask = sampleCoverage[0].getAccess().getPixelUint(x, y).x(); 1832 if (mask != 0x01) 1833 { 1834 allOk = false; 1835 1836 if (++printCount <= printFloodLimit) 1837 { 1838 m_testCtx.getLog() 1839 << tcu::TestLog::Message 1840 << "Pixel (" << x << ", " << y << "): Invalid mask, got " << tcu::Format::Hex<8>(mask) << ", expected " << tcu::Format::Hex<8>(0x01) << "\n" 1841 << tcu::TestLog::EndMessage; 1842 } 1843 } 1844 } 1845 1846 if (!allOk && printCount > printFloodLimit) 1847 { 1848 m_testCtx.getLog() 1849 << tcu::TestLog::Message 1850 << "...\n" 1851 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 1852 << tcu::TestLog::EndMessage; 1853 } 1854 } 1855 else 1856 { 1857 // check uniqueness 1858 { 1859 bool uniquenessOk = true; 1860 int printCount = 0; 1861 const int printFloodLimit = 5; 1862 1863 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying invocation sample masks do not share bits." << tcu::TestLog::EndMessage; 1864 1865 for (int y = 0; y < height; ++y) 1866 for (int x = 0; x < width; ++x) 1867 { 1868 bool maskBitsNotUnique = false; 1869 1870 for (int sampleNdxA = 0; sampleNdxA < m_numTargetSamples && (!maskBitsNotUnique || printCount < printFloodLimit); ++sampleNdxA) 1871 for (int sampleNdxB = sampleNdxA+1; sampleNdxB < m_numTargetSamples && (!maskBitsNotUnique || printCount < printFloodLimit); ++sampleNdxB) 1872 { 1873 const deUint32 maskA = sampleCoverage[sampleNdxA].getAccess().getPixelUint(x, y).x(); 1874 const deUint32 maskB = sampleCoverage[sampleNdxB].getAccess().getPixelUint(x, y).x(); 1875 1876 // equal mask == emitted by the same invocation 1877 if (maskA != maskB) 1878 { 1879 // shares samples? 1880 if (maskA & maskB) 1881 { 1882 maskBitsNotUnique = true; 1883 uniquenessOk = false; 1884 1885 if (++printCount <= printFloodLimit) 1886 { 1887 m_testCtx.getLog() 1888 << tcu::TestLog::Message 1889 << "Pixel (" << x << ", " << y << "):\n" 1890 << "\tSamples " << sampleNdxA << " and " << sampleNdxB << " share mask bits\n" 1891 << "\tMask" << sampleNdxA << " = " << tcu::Format::Hex<8>(maskA) << "\n" 1892 << "\tMask" << sampleNdxB << " = " << tcu::Format::Hex<8>(maskB) << "\n" 1893 << tcu::TestLog::EndMessage; 1894 } 1895 } 1896 } 1897 } 1898 } 1899 1900 if (!uniquenessOk) 1901 { 1902 allOk = false; 1903 1904 if (printCount > printFloodLimit) 1905 m_testCtx.getLog() 1906 << tcu::TestLog::Message 1907 << "...\n" 1908 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 1909 << tcu::TestLog::EndMessage; 1910 } 1911 } 1912 1913 // check number of sample mask bit groups is valid ( == number of invocations ) 1914 { 1915 const deUint32 minNumInvocations = (deUint32)de::max(1, (m_numTargetSamples+1)/2); 1916 bool countOk = true; 1917 int printCount = 0; 1918 const int printFloodLimit = 5; 1919 1920 m_testCtx.getLog() << tcu::TestLog::Message << "Verifying cardinality of separate sample mask bit sets. Expecting equal to the number of invocations, (greater or equal to " << minNumInvocations << ")" << tcu::TestLog::EndMessage; 1921 1922 for (int y = 0; y < height; ++y) 1923 for (int x = 0; x < width; ++x) 1924 { 1925 std::set<deUint32> masks; 1926 1927 for (int maskNdx = 0; maskNdx < m_numTargetSamples; ++maskNdx) 1928 { 1929 const deUint32 mask = sampleCoverage[maskNdx].getAccess().getPixelUint(x, y).x(); 1930 masks.insert(mask); 1931 } 1932 1933 if ((int)masks.size() < (int)minNumInvocations) 1934 { 1935 if (++printCount <= printFloodLimit) 1936 { 1937 m_testCtx.getLog() 1938 << tcu::TestLog::Message 1939 << "Pixel (" << x << ", " << y << "): Pixel invocations had only " << (int)masks.size() << " separate mask sets. Expected " << minNumInvocations << " or more. Found masks:" 1940 << tcu::TestLog::EndMessage; 1941 1942 for (std::set<deUint32>::iterator it = masks.begin(); it != masks.end(); ++it) 1943 m_testCtx.getLog() 1944 << tcu::TestLog::Message 1945 << "\tMask: " << tcu::Format::Hex<8>(*it) << "\n" 1946 << tcu::TestLog::EndMessage; 1947 } 1948 1949 countOk = false; 1950 } 1951 } 1952 1953 if (!countOk) 1954 { 1955 allOk = false; 1956 1957 if (printCount > printFloodLimit) 1958 m_testCtx.getLog() 1959 << tcu::TestLog::Message 1960 << "...\n" 1961 << "Omitted " << (printCount-printFloodLimit) << " error descriptions." 1962 << tcu::TestLog::EndMessage; 1963 } 1964 } 1965 } 1966 1967 if (!allOk) 1968 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 1969 } 1970 1971 class SampleMaskWriteCase : public SampleMaskBaseCase 1972 { 1973 public: 1974 enum TestMode 1975 { 1976 TEST_DISCARD = 0, 1977 TEST_INVERSE, 1978 1979 TEST_LAST 1980 }; 1981 SampleMaskWriteCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode, TestMode testMode); 1982 ~SampleMaskWriteCase (void); 1983 1984 void init (void); 1985 void preDraw (void); 1986 void postDraw (void); 1987 1988 private: 1989 enum 1990 { 1991 RENDER_SIZE = 64 1992 }; 1993 1994 std::string genFragmentSource (int numTargetSamples) const; 1995 bool verifyImage (const tcu::Surface& resultImage); 1996 1997 const TestMode m_testMode; 1998 }; 1999 2000 SampleMaskWriteCase::SampleMaskWriteCase (Context& context, const char* name, const char* desc, int sampleCount, RenderTarget target, ShaderRunMode runMode, TestMode testMode) 2001 : SampleMaskBaseCase (context, name, desc, sampleCount, target, RENDER_SIZE, runMode) 2002 , m_testMode (testMode) 2003 { 2004 DE_ASSERT(testMode < TEST_LAST); 2005 } 2006 2007 SampleMaskWriteCase::~SampleMaskWriteCase (void) 2008 { 2009 } 2010 2011 void SampleMaskWriteCase::init (void) 2012 { 2013 // log the test method and expectations 2014 if (m_testMode == TEST_DISCARD) 2015 m_testCtx.getLog() 2016 << tcu::TestLog::Message 2017 << "Discarding half of the samples using gl_SampleMask, expecting:\n" 2018 << " 1) half intensity on multisample targets (numSamples > 1)\n" 2019 << " 2) full discard on multisample targets (numSamples == 1)\n" 2020 << " 3) full intensity (no discard) on singlesample targets. (Mask is only applied as a multisample operation.)\n" 2021 << tcu::TestLog::EndMessage; 2022 else if (m_testMode == TEST_INVERSE) 2023 m_testCtx.getLog() 2024 << tcu::TestLog::Message 2025 << "Discarding half of the samples using GL_SAMPLE_MASK, setting inverse mask in fragment shader using gl_SampleMask, expecting:\n" 2026 << " 1) full discard on multisample targets (mask & modifiedCoverge == 0)\n" 2027 << " 2) full intensity (no discard) on singlesample targets. (Mask and coverage is only applied as a multisample operation.)\n" 2028 << tcu::TestLog::EndMessage; 2029 else 2030 DE_ASSERT(false); 2031 2032 SampleMaskBaseCase::init(); 2033 } 2034 2035 void SampleMaskWriteCase::preDraw (void) 2036 { 2037 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2038 2039 if (m_testMode == TEST_INVERSE) 2040 { 2041 // set mask to 0xAAAA.., set inverse mask bit coverage in shader 2042 2043 const int maskLoc = gl.getUniformLocation(m_program->getProgram(), "u_mask"); 2044 const deUint32 mask = (deUint32)0xAAAAAAAAUL; 2045 2046 if (maskLoc == -1) 2047 throw tcu::TestError("Location of u_mask was -1"); 2048 2049 gl.enable(GL_SAMPLE_MASK); 2050 gl.sampleMaski(0, mask); 2051 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask"); 2052 2053 gl.uniform1ui(maskLoc, mask); 2054 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask uniform"); 2055 2056 m_testCtx.getLog() << tcu::TestLog::Message << "Setting sample mask " << tcu::Format::Hex<4>(mask) << tcu::TestLog::EndMessage; 2057 } 2058 2059 SampleMaskBaseCase::preDraw(); 2060 } 2061 2062 void SampleMaskWriteCase::postDraw (void) 2063 { 2064 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2065 2066 if (m_testMode == TEST_INVERSE) 2067 { 2068 const deUint32 fullMask = (1U << m_numTargetSamples) - 1; 2069 2070 gl.disable(GL_SAMPLE_MASK); 2071 gl.sampleMaski(0, fullMask); 2072 GLU_EXPECT_NO_ERROR(gl.getError(), "set mask"); 2073 } 2074 2075 SampleMaskBaseCase::postDraw(); 2076 } 2077 2078 std::string SampleMaskWriteCase::genFragmentSource (int numTargetSamples) const 2079 { 2080 DE_ASSERT(numTargetSamples != 0); 2081 DE_UNREF(numTargetSamples); 2082 2083 std::ostringstream buf; 2084 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 2085 map<string, string> args; 2086 args["GLSL_VERSION_DECL"] = supportsES32 ? getGLSLVersionDeclaration(glu::GLSL_VERSION_320_ES) : getGLSLVersionDeclaration(glu::GLSL_VERSION_310_ES); 2087 args["GLSL_EXTENSION"] = supportsES32 ? "" : "#extension GL_OES_sample_variables : require"; 2088 2089 if (m_testMode == TEST_DISCARD) 2090 { 2091 // mask out every other coverage bit 2092 2093 buf << "${GLSL_VERSION_DECL}\n" 2094 "${GLSL_EXTENSION}\n" 2095 "layout(location = 0) out mediump vec4 fragColor;\n" 2096 "void main (void)\n" 2097 "{\n" 2098 " for (int i = 0; i < gl_SampleMask.length(); ++i)\n" 2099 " gl_SampleMask[i] = int(0xAAAAAAAA);\n" 2100 "\n"; 2101 2102 if (m_runMode == RUN_PER_SAMPLE) 2103 buf << " // force per-sample shading\n" 2104 " highp float blue = float(gl_SampleID);\n" 2105 "\n" 2106 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n" 2107 "}\n"; 2108 else 2109 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 2110 "}\n"; 2111 } 2112 else if (m_testMode == TEST_INVERSE) 2113 { 2114 // inverse every coverage bit 2115 2116 buf << "${GLSL_VERSION_DECL}\n" 2117 "${GLSL_EXTENSION}\n" 2118 "layout(location = 0) out mediump vec4 fragColor;\n" 2119 "uniform highp uint u_mask;\n" 2120 "void main (void)\n" 2121 "{\n" 2122 " gl_SampleMask[0] = int(~u_mask);\n" 2123 "\n"; 2124 2125 if (m_runMode == RUN_PER_SAMPLE) 2126 buf << " // force per-sample shading\n" 2127 " highp float blue = float(gl_SampleID);\n" 2128 "\n" 2129 " fragColor = vec4(0.0, 1.0, blue, 1.0);\n" 2130 "}\n"; 2131 else 2132 buf << " fragColor = vec4(0.0, 1.0, 0.0, 1.0);\n" 2133 "}\n"; 2134 } 2135 else 2136 DE_ASSERT(false); 2137 2138 return tcu::StringTemplate(buf.str()).specialize(args); 2139 } 2140 2141 bool SampleMaskWriteCase::verifyImage (const tcu::Surface& resultImage) 2142 { 2143 const bool singleSampleTarget = m_numRequestedSamples == 0 && !(m_renderTarget == TARGET_DEFAULT && m_context.getRenderTarget().getNumSamples() > 1); 2144 2145 if (m_testMode == TEST_DISCARD) 2146 { 2147 if (singleSampleTarget) 2148 { 2149 // single sample case => multisample operations are not effective => don't discard anything 2150 // expect green 2151 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f))); 2152 } 2153 else if (m_numTargetSamples == 1) 2154 { 2155 // total discard, expect black 2156 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f))); 2157 } 2158 else 2159 { 2160 // partial discard, expect something between black and green 2161 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), PartialDiscardVerifier()); 2162 } 2163 } 2164 else if (m_testMode == TEST_INVERSE) 2165 { 2166 if (singleSampleTarget) 2167 { 2168 // single sample case => multisample operations are not effective => don't discard anything 2169 // expect green 2170 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 1.0f, 0.0f))); 2171 } 2172 else 2173 { 2174 // total discard, expect black 2175 return verifyImageWithVerifier(resultImage, m_testCtx.getLog(), ColorVerifier(tcu::Vec3(0.0f, 0.0f, 0.0f))); 2176 } 2177 } 2178 else 2179 { 2180 DE_ASSERT(false); 2181 return false; 2182 } 2183 } 2184 2185 } // anonymous 2186 2187 SampleVariableTests::SampleVariableTests (Context& context) 2188 : TestCaseGroup(context, "sample_variables", "Test sample variables") 2189 { 2190 } 2191 2192 SampleVariableTests::~SampleVariableTests (void) 2193 { 2194 } 2195 2196 void SampleVariableTests::init (void) 2197 { 2198 tcu::TestCaseGroup* const numSampleGroup = new tcu::TestCaseGroup(m_testCtx, "num_samples", "Test NumSamples"); 2199 tcu::TestCaseGroup* const maxSampleGroup = new tcu::TestCaseGroup(m_testCtx, "max_samples", "Test MaxSamples"); 2200 tcu::TestCaseGroup* const sampleIDGroup = new tcu::TestCaseGroup(m_testCtx, "sample_id", "Test SampleID"); 2201 tcu::TestCaseGroup* const samplePosGroup = new tcu::TestCaseGroup(m_testCtx, "sample_pos", "Test SamplePosition"); 2202 tcu::TestCaseGroup* const sampleMaskInGroup = new tcu::TestCaseGroup(m_testCtx, "sample_mask_in", "Test SampleMaskIn"); 2203 tcu::TestCaseGroup* const sampleMaskGroup = new tcu::TestCaseGroup(m_testCtx, "sample_mask", "Test SampleMask"); 2204 2205 addChild(numSampleGroup); 2206 addChild(maxSampleGroup); 2207 addChild(sampleIDGroup); 2208 addChild(samplePosGroup); 2209 addChild(sampleMaskInGroup); 2210 addChild(sampleMaskGroup); 2211 2212 static const struct RenderTarget 2213 { 2214 const char* name; 2215 const char* desc; 2216 int numSamples; 2217 MultisampleRenderCase::RenderTarget target; 2218 } targets[] = 2219 { 2220 { "default_framebuffer", "Test with default framebuffer", 0, MultisampleRenderCase::TARGET_DEFAULT }, 2221 { "singlesample_texture", "Test with singlesample texture", 0, MultisampleRenderCase::TARGET_TEXTURE }, 2222 { "multisample_texture_1", "Test with multisample texture", 1, MultisampleRenderCase::TARGET_TEXTURE }, 2223 { "multisample_texture_2", "Test with multisample texture", 2, MultisampleRenderCase::TARGET_TEXTURE }, 2224 { "multisample_texture_4", "Test with multisample texture", 4, MultisampleRenderCase::TARGET_TEXTURE }, 2225 { "multisample_texture_8", "Test with multisample texture", 8, MultisampleRenderCase::TARGET_TEXTURE }, 2226 { "multisample_texture_16", "Test with multisample texture", 16, MultisampleRenderCase::TARGET_TEXTURE }, 2227 { "singlesample_rbo", "Test with singlesample rbo", 0, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2228 { "multisample_rbo_1", "Test with multisample rbo", 1, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2229 { "multisample_rbo_2", "Test with multisample rbo", 2, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2230 { "multisample_rbo_4", "Test with multisample rbo", 4, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2231 { "multisample_rbo_8", "Test with multisample rbo", 8, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2232 { "multisample_rbo_16", "Test with multisample rbo", 16, MultisampleRenderCase::TARGET_RENDERBUFFER }, 2233 }; 2234 2235 // .num_samples 2236 { 2237 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2238 numSampleGroup->addChild(new NumSamplesCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2239 } 2240 2241 // .max_samples 2242 { 2243 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2244 maxSampleGroup->addChild(new MaxSamplesCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2245 } 2246 2247 // .sample_ID 2248 { 2249 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2250 sampleIDGroup->addChild(new SampleIDCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2251 } 2252 2253 // .sample_pos 2254 { 2255 { 2256 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "correctness", "Test SamplePos correctness"); 2257 samplePosGroup->addChild(group); 2258 2259 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2260 group->addChild(new SamplePosCorrectnessCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2261 } 2262 2263 { 2264 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "distribution", "Test SamplePos distribution"); 2265 samplePosGroup->addChild(group); 2266 2267 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2268 group->addChild(new SamplePosDistributionCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2269 } 2270 } 2271 2272 // .sample_mask_in 2273 { 2274 // .sample_mask 2275 { 2276 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "sample_mask", "Test with GL_SAMPLE_MASK"); 2277 sampleMaskInGroup->addChild(group); 2278 2279 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2280 group->addChild(new SampleMaskCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target)); 2281 } 2282 // .bit_count_per_pixel 2283 { 2284 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_pixel", "Test number of coverage bits"); 2285 sampleMaskInGroup->addChild(group); 2286 2287 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2288 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_PIXEL)); 2289 } 2290 // .bit_count_per_sample 2291 { 2292 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_sample", "Test number of coverage bits"); 2293 sampleMaskInGroup->addChild(group); 2294 2295 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2296 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_SAMPLE)); 2297 } 2298 // .bit_count_per_two_samples 2299 { 2300 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bit_count_per_two_samples", "Test number of coverage bits"); 2301 sampleMaskInGroup->addChild(group); 2302 2303 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2304 group->addChild(new SampleMaskCountCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskCountCase::RUN_PER_TWO_SAMPLES)); 2305 } 2306 // .bits_unique_per_sample 2307 { 2308 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_sample", "Test coverage bits"); 2309 sampleMaskInGroup->addChild(group); 2310 2311 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2312 if (targets[targetNdx].target == MultisampleRenderCase::TARGET_TEXTURE) 2313 group->addChild(new SampleMaskUniqueCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskUniqueCase::RUN_PER_SAMPLE)); 2314 } 2315 // .bits_unique_per_two_samples 2316 { 2317 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "bits_unique_per_two_samples", "Test coverage bits"); 2318 sampleMaskInGroup->addChild(group); 2319 2320 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2321 if (targets[targetNdx].target == MultisampleRenderCase::TARGET_TEXTURE) 2322 group->addChild(new SampleMaskUniqueSetCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskUniqueCase::RUN_PER_TWO_SAMPLES)); 2323 } 2324 } 2325 2326 // .sample_mask 2327 { 2328 // .discard_half_per_pixel 2329 { 2330 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_pixel", "Test coverage bits"); 2331 sampleMaskGroup->addChild(group); 2332 2333 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2334 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_PIXEL, SampleMaskWriteCase::TEST_DISCARD)); 2335 } 2336 // .discard_half_per_sample 2337 { 2338 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_sample", "Test coverage bits"); 2339 sampleMaskGroup->addChild(group); 2340 2341 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2342 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_SAMPLE, SampleMaskWriteCase::TEST_DISCARD)); 2343 } 2344 // .discard_half_per_two_samples 2345 { 2346 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "discard_half_per_two_samples", "Test coverage bits"); 2347 sampleMaskGroup->addChild(group); 2348 2349 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2350 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_TWO_SAMPLES, SampleMaskWriteCase::TEST_DISCARD)); 2351 } 2352 2353 // .discard_half_per_two_samples 2354 { 2355 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_pixel", "Test coverage bits"); 2356 sampleMaskGroup->addChild(group); 2357 2358 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2359 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_PIXEL, SampleMaskWriteCase::TEST_INVERSE)); 2360 } 2361 // .inverse_per_sample 2362 { 2363 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_sample", "Test coverage bits"); 2364 sampleMaskGroup->addChild(group); 2365 2366 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2367 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_SAMPLE, SampleMaskWriteCase::TEST_INVERSE)); 2368 } 2369 // .inverse_per_two_samples 2370 { 2371 tcu::TestCaseGroup* const group = new tcu::TestCaseGroup(m_testCtx, "inverse_per_two_samples", "Test coverage bits"); 2372 sampleMaskGroup->addChild(group); 2373 2374 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2375 group->addChild(new SampleMaskWriteCase(m_context, targets[targetNdx].name, targets[targetNdx].desc, targets[targetNdx].numSamples, targets[targetNdx].target, SampleMaskWriteCase::RUN_PER_TWO_SAMPLES, SampleMaskWriteCase::TEST_INVERSE)); 2376 } 2377 } 2378 } 2379 2380 } // Functional 2381 } // gles31 2382 } // deqp 2383