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