1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 Module 3 * ------------------------------------------------- 4 * 5 * Copyright 2015 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 Texture border clamp tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fTextureBorderClampTests.hpp" 25 26 #include "glsTextureTestUtil.hpp" 27 28 #include "tcuTextureUtil.hpp" 29 #include "tcuTexLookupVerifier.hpp" 30 #include "tcuTexCompareVerifier.hpp" 31 #include "tcuCompressedTexture.hpp" 32 #include "tcuResultCollector.hpp" 33 #include "tcuSurface.hpp" 34 #include "tcuSeedBuilder.hpp" 35 #include "tcuVectorUtil.hpp" 36 37 #include "rrGenericVector.hpp" 38 39 #include "gluContextInfo.hpp" 40 #include "gluTexture.hpp" 41 #include "gluTextureUtil.hpp" 42 #include "gluPixelTransfer.hpp" 43 #include "gluStrUtil.hpp" 44 #include "gluObjectWrapper.hpp" 45 #include "gluShaderProgram.hpp" 46 #include "gluDrawUtil.hpp" 47 48 #include "glwEnums.hpp" 49 #include "glwFunctions.hpp" 50 51 #include "deStringUtil.hpp" 52 #include "deUniquePtr.hpp" 53 #include "deRandom.hpp" 54 55 #include <limits> 56 57 58 namespace deqp 59 { 60 namespace gles31 61 { 62 namespace Functional 63 { 64 namespace 65 { 66 67 enum SizeType 68 { 69 SIZE_POT = 0, 70 SIZE_NPOT 71 }; 72 73 bool filterRequiresFilterability (deUint32 filter) 74 { 75 switch (filter) 76 { 77 case GL_NEAREST: 78 case GL_NEAREST_MIPMAP_NEAREST: 79 return false; 80 81 case GL_LINEAR: 82 case GL_LINEAR_MIPMAP_NEAREST: 83 case GL_NEAREST_MIPMAP_LINEAR: 84 case GL_LINEAR_MIPMAP_LINEAR: 85 return true; 86 87 default: 88 DE_ASSERT(false); 89 return false; 90 } 91 } 92 93 bool isDepthFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode) 94 { 95 if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) 96 { 97 // Unsized formats are a special case 98 return false; 99 } 100 else if (glu::isCompressedFormat(format)) 101 { 102 // no known compressed depth formats 103 return false; 104 } 105 else 106 { 107 const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); 108 109 if (fmt.order == tcu::TextureFormat::D) 110 { 111 DE_ASSERT(mode == tcu::Sampler::MODE_DEPTH); 112 return true; 113 } 114 else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_DEPTH) 115 return true; 116 else 117 return false; 118 } 119 } 120 121 bool isStencilFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode) 122 { 123 if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) 124 { 125 // Unsized formats are a special case 126 return false; 127 } 128 else if (glu::isCompressedFormat(format)) 129 { 130 // no known compressed stencil formats 131 return false; 132 } 133 else 134 { 135 const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); 136 137 if (fmt.order == tcu::TextureFormat::S) 138 { 139 DE_ASSERT(mode == tcu::Sampler::MODE_STENCIL); 140 return true; 141 } 142 else if (fmt.order == tcu::TextureFormat::DS && mode == tcu::Sampler::MODE_STENCIL) 143 return true; 144 else 145 return false; 146 } 147 } 148 149 tcu::TextureChannelClass getFormatChannelClass (deUint32 format, tcu::Sampler::DepthStencilMode mode) 150 { 151 if (format == GL_LUMINANCE || format == GL_LUMINANCE_ALPHA || format == GL_ALPHA || format == GL_BGRA) 152 { 153 // Unsized formats are a special c, use UNORM8 154 return tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 155 } 156 else if (glu::isCompressedFormat(format)) 157 { 158 const tcu::CompressedTexFormat compressedFmt = glu::mapGLCompressedTexFormat(format); 159 const tcu::TextureFormat uncompressedFmt = tcu::getUncompressedFormat(compressedFmt); 160 return tcu::getTextureChannelClass(uncompressedFmt.type); 161 } 162 else 163 { 164 const tcu::TextureFormat fmt = glu::mapGLInternalFormat(format); 165 const tcu::TextureFormat effectiveFmt = tcu::getEffectiveDepthStencilTextureFormat(fmt, mode); 166 167 return tcu::getTextureChannelClass(effectiveFmt.type); 168 } 169 } 170 171 int getDimensionNumBlocks (int dimensionSize, int blockSize) 172 { 173 // ceil( a / b ) 174 return (dimensionSize + blockSize - 1) / blockSize; 175 } 176 177 void generateDummyCompressedData (tcu::CompressedTexture& dst, const tcu::CompressedTexFormat& format) 178 { 179 const int blockByteSize = tcu::getBlockSize(format); 180 const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(format); 181 const tcu::IVec3 numBlocks (getDimensionNumBlocks(dst.getWidth(), blockPixelSize.x()), 182 getDimensionNumBlocks(dst.getHeight(), blockPixelSize.y()), 183 getDimensionNumBlocks(dst.getDepth(), blockPixelSize.z())); 184 const int numTotalBlocks = numBlocks.x() * numBlocks.y() * numBlocks.z(); 185 const int dataSize = numTotalBlocks * blockByteSize; 186 187 DE_ASSERT(dst.getDataSize() == dataSize); 188 189 if (tcu::isAstcFormat(format)) 190 { 191 // generate data that is valid in LDR mode 192 const int BLOCK_SIZE = 16; 193 const deUint8 block[BLOCK_SIZE] = { 252, 253, 255, 255, 255, 255, 255, 255, 223, 251, 28, 206, 54, 251, 160, 174 }; 194 195 DE_ASSERT(blockByteSize == BLOCK_SIZE); 196 for (int ndx = 0; ndx < numTotalBlocks; ++ndx) 197 deMemcpy((deUint8*)dst.getData() + ndx * BLOCK_SIZE, block, BLOCK_SIZE); 198 } 199 else 200 { 201 // any data is ok 202 de::Random rnd(0xabc); 203 204 for (int ndx = 0; ndx < dataSize; ++ndx) 205 ((deUint8*)dst.getData())[ndx] = rnd.getUint8(); 206 } 207 } 208 209 template <typename T> 210 struct TextureTraits 211 { 212 }; 213 214 template <> 215 struct TextureTraits<glu::Texture2D> 216 { 217 typedef tcu::IVec2 SizeType; 218 219 static de::MovePtr<glu::Texture2D> createTextureFromInternalFormat (glu::RenderContext& renderCtx, deUint32 texFormat, const tcu::IVec2& size) 220 { 221 return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, size.x(), size.y())); 222 } 223 224 static de::MovePtr<glu::Texture2D> createTextureFromFormatAndType (glu::RenderContext& renderCtx, deUint32 texFormat, deUint32 type, const tcu::IVec2& size) 225 { 226 return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, texFormat, type, size.x(), size.y())); 227 } 228 229 static de::MovePtr<glu::Texture2D> createTextureFromCompressedData (glu::RenderContext& renderCtx, 230 const glu::ContextInfo& ctxInfo, 231 const tcu::CompressedTexture& compressedLevel, 232 const tcu::TexDecompressionParams& decompressionParams) 233 { 234 return de::MovePtr<glu::Texture2D>(new glu::Texture2D(renderCtx, 235 ctxInfo, 236 1, 237 &compressedLevel, 238 decompressionParams)); 239 } 240 241 static int getTextureNumLayers (const tcu::IVec2& size) 242 { 243 // 2D textures have one layer 244 DE_UNREF(size); 245 return 1; 246 } 247 }; 248 249 template <> 250 struct TextureTraits<glu::Texture3D> 251 { 252 typedef tcu::IVec3 SizeType; 253 254 static de::MovePtr<glu::Texture3D> createTextureFromInternalFormat (glu::RenderContext& renderCtx, deUint32 texFormat, const tcu::IVec3& size) 255 { 256 return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, size.x(), size.y(), size.z())); 257 } 258 259 static de::MovePtr<glu::Texture3D> createTextureFromFormatAndType (glu::RenderContext& renderCtx, deUint32 texFormat, deUint32 type, const tcu::IVec3& size) 260 { 261 return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, texFormat, type, size.x(), size.y(), size.z())); 262 } 263 264 static de::MovePtr<glu::Texture3D> createTextureFromCompressedData (glu::RenderContext& renderCtx, 265 const glu::ContextInfo& ctxInfo, 266 const tcu::CompressedTexture& compressedLevel, 267 const tcu::TexDecompressionParams& decompressionParams) 268 { 269 return de::MovePtr<glu::Texture3D>(new glu::Texture3D(renderCtx, 270 ctxInfo, 271 1, 272 &compressedLevel, 273 decompressionParams)); 274 } 275 276 static int getTextureNumLayers (const tcu::IVec3& size) 277 { 278 // 3D textures have Z layers 279 return size.z(); 280 } 281 }; 282 283 template <typename T> 284 de::MovePtr<T> genDummyTexture (glu::RenderContext& renderCtx, const glu::ContextInfo& ctxInfo, deUint32 texFormat, const typename TextureTraits<T>::SizeType& size) 285 { 286 de::MovePtr<T> texture; 287 288 if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH) || isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL)) 289 { 290 // fill different channels with different gradients 291 texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size); 292 texture->getRefTexture().allocLevel(0); 293 294 if (isDepthFormat(texFormat, tcu::Sampler::MODE_DEPTH)) 295 { 296 // fill depth with 0 -> 1 297 const tcu::PixelBufferAccess depthAccess = tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_DEPTH); 298 tcu::fillWithComponentGradients(depthAccess, tcu::Vec4(0.0f), tcu::Vec4(1.0f)); 299 } 300 301 if (isStencilFormat(texFormat, tcu::Sampler::MODE_STENCIL)) 302 { 303 // fill stencil with 0 -> max 304 const tcu::PixelBufferAccess stencilAccess = tcu::getEffectiveDepthStencilAccess(texture->getRefTexture().getLevel(0), tcu::Sampler::MODE_STENCIL); 305 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(stencilAccess.getFormat()); 306 307 // Flip y to make stencil and depth cases not look identical 308 tcu::fillWithComponentGradients(tcu::flipYAccess(stencilAccess), texFormatInfo.valueMax, texFormatInfo.valueMin); 309 } 310 311 texture->upload(); 312 } 313 else if (!glu::isCompressedFormat(texFormat)) 314 { 315 if (texFormat == GL_LUMINANCE || texFormat == GL_LUMINANCE_ALPHA || texFormat == GL_ALPHA || texFormat == GL_BGRA) 316 texture = TextureTraits<T>::createTextureFromFormatAndType(renderCtx, texFormat, GL_UNSIGNED_BYTE, size); 317 else 318 texture = TextureTraits<T>::createTextureFromInternalFormat(renderCtx, texFormat, size); 319 320 // Fill level 0. 321 texture->getRefTexture().allocLevel(0); 322 323 // fill with gradient min -> max 324 { 325 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texture->getRefTexture().getFormat()); 326 const tcu::Vec4 rampLow = texFormatInfo.valueMin; 327 const tcu::Vec4 rampHigh = texFormatInfo.valueMax; 328 tcu::fillWithComponentGradients(texture->getRefTexture().getLevel(0), rampLow, rampHigh); 329 } 330 331 texture->upload(); 332 } 333 else 334 { 335 const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat); 336 const int numLayers = TextureTraits<T>::getTextureNumLayers(size); 337 tcu::CompressedTexture compressedLevel (compressedFormat, size.x(), size.y(), numLayers); 338 const bool isAstcFormat = tcu::isAstcFormat(compressedFormat); 339 tcu::TexDecompressionParams decompressionParams ((isAstcFormat) ? (tcu::TexDecompressionParams::ASTCMODE_LDR) : (tcu::TexDecompressionParams::ASTCMODE_LAST)); 340 341 generateDummyCompressedData(compressedLevel, compressedFormat); 342 343 texture = TextureTraits<T>::createTextureFromCompressedData(renderCtx, 344 ctxInfo, 345 compressedLevel, 346 decompressionParams); 347 } 348 349 return texture; 350 } 351 352 int getNBitIntegerMaxValue (bool isSigned, int numBits) 353 { 354 DE_ASSERT(numBits < 32); 355 356 if (numBits == 0) 357 return 0; 358 else if (isSigned) 359 return deIntMaxValue32(numBits); 360 else 361 return deUintMaxValue32(numBits); 362 } 363 364 int getNBitIntegerMinValue (bool isSigned, int numBits) 365 { 366 DE_ASSERT(numBits < 32); 367 368 if (numBits == 0) 369 return 0; 370 else if (isSigned) 371 return deIntMinValue32(numBits); 372 else 373 return 0; 374 } 375 376 tcu::IVec4 getNBitIntegerVec4MaxValue (bool isSigned, const tcu::IVec4& numBits) 377 { 378 return tcu::IVec4(getNBitIntegerMaxValue(isSigned, numBits[0]), 379 getNBitIntegerMaxValue(isSigned, numBits[1]), 380 getNBitIntegerMaxValue(isSigned, numBits[2]), 381 getNBitIntegerMaxValue(isSigned, numBits[3])); 382 } 383 384 tcu::IVec4 getNBitIntegerVec4MinValue (bool isSigned, const tcu::IVec4& numBits) 385 { 386 return tcu::IVec4(getNBitIntegerMinValue(isSigned, numBits[0]), 387 getNBitIntegerMinValue(isSigned, numBits[1]), 388 getNBitIntegerMinValue(isSigned, numBits[2]), 389 getNBitIntegerMinValue(isSigned, numBits[3])); 390 } 391 392 rr::GenericVec4 mapToFormatColorUnits (const tcu::TextureFormat& texFormat, const tcu::Vec4& normalizedRange) 393 { 394 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); 395 396 switch (tcu::getTextureChannelClass(texFormat.type)) 397 { 398 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: return rr::GenericVec4(normalizedRange); 399 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: return rr::GenericVec4(normalizedRange * 2.0f - 1.0f); 400 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: return rr::GenericVec4(texFormatInfo.valueMin + normalizedRange * texFormatInfo.valueMax); 401 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: return rr::GenericVec4(tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<deInt32>()); 402 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: return rr::GenericVec4(tcu::mix(texFormatInfo.valueMin, texFormatInfo.valueMax, normalizedRange).cast<deUint32>()); 403 404 default: 405 DE_ASSERT(false); 406 return rr::GenericVec4(); 407 } 408 } 409 410 rr::GenericVec4 mapToFormatColorRepresentable (const tcu::TextureFormat& texFormat, const tcu::Vec4& normalizedRange) 411 { 412 // make sure value is representable in the target format and clear channels 413 // not present in the target format. 414 415 const rr::GenericVec4 inFormatUnits = mapToFormatColorUnits(texFormat, normalizedRange); 416 const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(texFormat); 417 de::ArrayBuffer<deUint8, 4> buffer (texFormat.getPixelSize()); 418 tcu::PixelBufferAccess access (texFormat, tcu::IVec3(1, 1, 1), buffer.getPtr()); 419 420 if (tcu::isSRGB(texFormat)) 421 { 422 DE_ASSERT(texFormat.type == tcu::TextureFormat::UNORM_INT8); 423 424 // make sure border color (in linear space) can be converted to 8-bit sRGB space without 425 // significant loss. 426 const tcu::Vec4 sRGB = tcu::linearToSRGB(normalizedRange); 427 const tcu::IVec4 sRGB8 = tcu::IVec4(tcu::floatToU8(sRGB[0]), 428 tcu::floatToU8(sRGB[1]), 429 tcu::floatToU8(sRGB[2]), 430 tcu::floatToU8(sRGB[3])); 431 const tcu::Vec4 linearized = tcu::sRGBToLinear(tcu::Vec4((float)sRGB8[0] / 255.0f, 432 (float)sRGB8[1] / 255.0f, 433 (float)sRGB8[2] / 255.0f, 434 (float)sRGB8[3] / 255.0f)); 435 436 return rr::GenericVec4(tcu::select(linearized, tcu::Vec4(0.0f), channelMask)); 437 } 438 439 switch (tcu::getTextureChannelClass(texFormat.type)) 440 { 441 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 442 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 443 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 444 { 445 access.setPixel(inFormatUnits.get<float>(), 0, 0); 446 return rr::GenericVec4(tcu::select(access.getPixel(0, 0), tcu::Vec4(0.0f), channelMask)); 447 } 448 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 449 { 450 access.setPixel(inFormatUnits.get<deInt32>(), 0, 0); 451 return rr::GenericVec4(tcu::select(access.getPixelInt(0, 0), tcu::IVec4(0), channelMask)); 452 } 453 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 454 { 455 access.setPixel(inFormatUnits.get<deUint32>(), 0, 0); 456 return rr::GenericVec4(tcu::select(access.getPixelUint(0, 0), tcu::UVec4(0u), channelMask)); 457 } 458 default: 459 { 460 DE_ASSERT(false); 461 return rr::GenericVec4(); 462 } 463 } 464 } 465 466 bool isCoreFilterableFormat (deUint32 format, tcu::Sampler::DepthStencilMode mode) 467 { 468 const bool isLuminanceOrAlpha = (format == GL_LUMINANCE || format == GL_ALPHA || format == GL_LUMINANCE_ALPHA); // special case for luminance/alpha 469 const bool isUnsizedColorFormat = (format == GL_BGRA); 470 const bool isCompressed = glu::isCompressedFormat(format); 471 const bool isDepth = isDepthFormat(format, mode); 472 const bool isStencil = isStencilFormat(format, mode); 473 474 // special cases 475 if (isLuminanceOrAlpha || isUnsizedColorFormat || isCompressed) 476 return true; 477 if (isStencil || isDepth) 478 return false; 479 480 // color case 481 return glu::isGLInternalColorFormatFilterable(format); 482 } 483 484 class TextureBorderClampTest : public TestCase 485 { 486 public: 487 enum StateType 488 { 489 STATE_SAMPLER_PARAM = 0, 490 STATE_TEXTURE_PARAM, 491 492 STATE_LAST 493 }; 494 495 enum SamplingFunction 496 { 497 SAMPLE_FILTER = 0, 498 SAMPLE_GATHER, 499 500 SAMPLE_LAST 501 }; 502 503 enum Flag 504 { 505 FLAG_USE_SHADOW_SAMPLER = (1u << 0), 506 }; 507 508 struct IterationConfig 509 { 510 tcu::Vec2 p0; 511 tcu::Vec2 p1; 512 rr::GenericVec4 borderColor; 513 tcu::Vec4 lookupScale; 514 tcu::Vec4 lookupBias; 515 deUint32 minFilter; 516 deUint32 magFilter; 517 std::string description; 518 deUint32 sWrapMode; 519 deUint32 tWrapMode; 520 deUint32 compareMode; 521 float compareRef; 522 }; 523 524 TextureBorderClampTest (Context& context, 525 const char* name, 526 const char* description, 527 deUint32 texFormat, 528 tcu::Sampler::DepthStencilMode mode, 529 StateType stateType, 530 int texWidth, 531 int texHeight, 532 SamplingFunction samplingFunction, 533 deUint32 flags = 0); 534 ~TextureBorderClampTest (void); 535 536 protected: 537 void init (void); 538 void deinit (void); 539 540 private: 541 IterateResult iterate (void); 542 543 void logParams (const IterationConfig& config, 544 const glu::TextureTestUtil::ReferenceParams& samplerParams); 545 546 void renderTo (tcu::Surface& surface, 547 const IterationConfig& config, 548 const glu::TextureTestUtil::ReferenceParams& samplerParams); 549 void renderQuad (const float* texCoord, 550 const glu::TextureTestUtil::ReferenceParams& samplerParams); 551 552 void verifyImage (const tcu::Surface& image, 553 const IterationConfig& config, 554 const glu::TextureTestUtil::ReferenceParams& samplerParams); 555 556 bool verifyTextureSampleResult (const tcu::ConstPixelBufferAccess& renderedFrame, 557 const float* texCoord, 558 const glu::TextureTestUtil::ReferenceParams& samplerParams, 559 const tcu::LodPrecision& lodPrecision, 560 const tcu::LookupPrecision& lookupPrecision); 561 562 bool verifyTextureCompareResult (const tcu::ConstPixelBufferAccess& renderedFrame, 563 const float* texCoord, 564 const glu::TextureTestUtil::ReferenceParams& samplerParams, 565 const tcu::TexComparePrecision& texComparePrecision, 566 const tcu::TexComparePrecision& lowQualityTexComparePrecision, 567 const tcu::LodPrecision& lodPrecision, 568 const tcu::LodPrecision& lowQualityLodPrecision); 569 570 bool verifyTextureGatherResult (const tcu::ConstPixelBufferAccess& renderedFrame, 571 const float* texCoord, 572 const glu::TextureTestUtil::ReferenceParams& samplerParams, 573 const tcu::LookupPrecision& lookupPrecision); 574 575 bool verifyTextureGatherCmpResult(const tcu::ConstPixelBufferAccess& renderedFrame, 576 const float* texCoord, 577 const glu::TextureTestUtil::ReferenceParams& samplerParams, 578 const tcu::TexComparePrecision& texComparePrecision, 579 const tcu::TexComparePrecision& lowQualityTexComparePrecision); 580 581 deUint32 getIterationSeed (const IterationConfig& config) const; 582 glu::TextureTestUtil::ReferenceParams genSamplerParams (const IterationConfig& config) const; 583 glu::ShaderProgram* genGatherProgram (void) const; 584 585 virtual int getNumIterations (void) const = 0; 586 virtual IterationConfig getIteration (int ndx) const = 0; 587 588 protected: 589 const glu::Texture2D* getTexture (void) const; 590 591 const deUint32 m_texFormat; 592 const tcu::Sampler::DepthStencilMode m_sampleMode; 593 const tcu::TextureChannelClass m_channelClass; 594 const StateType m_stateType; 595 596 const int m_texHeight; 597 const int m_texWidth; 598 599 const SamplingFunction m_samplingFunction; 600 const bool m_useShadowSampler; 601 private: 602 enum 603 { 604 VIEWPORT_WIDTH = 128, 605 VIEWPORT_HEIGHT = 128, 606 }; 607 608 de::MovePtr<glu::Texture2D> m_texture; 609 de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer; 610 de::MovePtr<glu::ShaderProgram> m_gatherProgram; 611 612 int m_iterationNdx; 613 tcu::ResultCollector m_result; 614 }; 615 616 TextureBorderClampTest::TextureBorderClampTest (Context& context, 617 const char* name, 618 const char* description, 619 deUint32 texFormat, 620 tcu::Sampler::DepthStencilMode mode, 621 StateType stateType, 622 int texWidth, 623 int texHeight, 624 SamplingFunction samplingFunction, 625 deUint32 flags) 626 : TestCase (context, name, description) 627 , m_texFormat (texFormat) 628 , m_sampleMode (mode) 629 , m_channelClass (getFormatChannelClass(texFormat, mode)) 630 , m_stateType (stateType) 631 , m_texHeight (texHeight) 632 , m_texWidth (texWidth) 633 , m_samplingFunction (samplingFunction) 634 , m_useShadowSampler ((flags & FLAG_USE_SHADOW_SAMPLER) != 0) 635 , m_iterationNdx (0) 636 , m_result (context.getTestContext().getLog()) 637 { 638 DE_ASSERT(stateType < STATE_LAST); 639 DE_ASSERT(samplingFunction < SAMPLE_LAST); 640 // mode must be set for combined depth-stencil formats 641 DE_ASSERT(m_channelClass != tcu::TEXTURECHANNELCLASS_LAST || mode != tcu::Sampler::MODE_LAST); 642 } 643 644 TextureBorderClampTest::~TextureBorderClampTest (void) 645 { 646 deinit(); 647 } 648 649 void TextureBorderClampTest::init (void) 650 { 651 // requirements 652 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 653 654 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp")) 655 throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension"); 656 657 if (glu::isCompressedFormat(m_texFormat) && 658 !supportsES32 && 659 tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) && 660 !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr")) 661 { 662 throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension"); 663 } 664 665 if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888")) 666 throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension"); 667 668 if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH || 669 m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT) 670 { 671 throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport"); 672 } 673 674 // resources 675 676 m_texture = genDummyTexture<glu::Texture2D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, tcu::IVec2(m_texWidth, m_texHeight)); 677 678 m_testCtx.getLog() << tcu::TestLog::Message 679 << "Created texture with format " << glu::getTextureFormatName(m_texFormat) 680 << ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ")\n" 681 << "Setting sampling state using " << ((m_stateType == STATE_TEXTURE_PARAM) ? ("texture state") : ("sampler state")) 682 << tcu::TestLog::EndMessage; 683 684 if (m_samplingFunction == SAMPLE_FILTER) 685 { 686 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()); 687 688 m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP)); 689 } 690 else 691 { 692 m_gatherProgram = de::MovePtr<glu::ShaderProgram>(genGatherProgram()); 693 694 m_testCtx.getLog() << tcu::TestLog::Message 695 << "Using texture gather to sample texture" 696 << tcu::TestLog::EndMessage 697 << *m_gatherProgram; 698 699 if (!m_gatherProgram->isOk()) 700 throw tcu::TestError("failed to build program"); 701 } 702 } 703 704 void TextureBorderClampTest::deinit (void) 705 { 706 m_texture.clear(); 707 m_renderer.clear(); 708 m_gatherProgram.clear(); 709 } 710 711 TextureBorderClampTest::IterateResult TextureBorderClampTest::iterate (void) 712 { 713 const IterationConfig iterationConfig = getIteration(m_iterationNdx); 714 const std::string iterationDesc = "Iteration " + de::toString(m_iterationNdx+1) + (iterationConfig.description.empty() ? ("") : (" - " + iterationConfig.description)); 715 const tcu::ScopedLogSection section (m_testCtx.getLog(), "Iteration", iterationDesc); 716 tcu::Surface renderedFrame (VIEWPORT_WIDTH, VIEWPORT_HEIGHT); 717 const glu::TextureTestUtil::ReferenceParams samplerParams = genSamplerParams(iterationConfig); 718 719 logParams(iterationConfig, samplerParams); 720 renderTo(renderedFrame, iterationConfig, samplerParams); 721 verifyImage(renderedFrame, iterationConfig, samplerParams); 722 723 if (++m_iterationNdx == getNumIterations()) 724 { 725 m_result.setTestContextResult(m_testCtx); 726 return STOP; 727 } 728 return CONTINUE; 729 } 730 731 void TextureBorderClampTest::logParams (const IterationConfig& config, const glu::TextureTestUtil::ReferenceParams& samplerParams) 732 { 733 const std::string borderColorString = (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (de::toString(config.borderColor.get<deInt32>())) 734 : (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(config.borderColor.get<deUint32>())) 735 : (de::toString(config.borderColor.get<float>())); 736 737 m_testCtx.getLog() << tcu::TestLog::Message 738 << "Rendering full screen quad, tex coords bottom-left: " << config.p0 << ", top-right " << config.p1 << "\n" 739 << "Border color is " << borderColorString << "\n" 740 << "Texture lookup bias: " << samplerParams.colorBias << "\n" 741 << "Texture lookup scale: " << samplerParams.colorScale << "\n" 742 << "Filters: min = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.minFilter)) 743 << ", mag = " << glu::getTextureFilterName(glu::getGLFilterMode(samplerParams.sampler.magFilter)) << "\n" 744 << "Wrap mode: s = " << glu::getRepeatModeStr(config.sWrapMode) 745 << ", t = " << glu::getRepeatModeStr(config.tWrapMode) << "\n" 746 << tcu::TestLog::EndMessage; 747 748 if (m_sampleMode == tcu::Sampler::MODE_DEPTH) 749 m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is DEPTH_COMPONENT" << tcu::TestLog::EndMessage; 750 else if (m_sampleMode == tcu::Sampler::MODE_STENCIL) 751 m_testCtx.getLog() << tcu::TestLog::Message << "Depth stencil texture mode is STENCIL_INDEX" << tcu::TestLog::EndMessage; 752 753 if (config.compareMode != GL_NONE) 754 { 755 m_testCtx.getLog() << tcu::TestLog::Message 756 << "Texture mode is COMPARE_REF_TO_TEXTURE, mode = " << glu::getCompareFuncStr(config.compareMode) << "\n" 757 << "Compare reference value = " << config.compareRef << "\n" 758 << tcu::TestLog::EndMessage; 759 } 760 } 761 762 void TextureBorderClampTest::renderTo (tcu::Surface& surface, 763 const IterationConfig& config, 764 const glu::TextureTestUtil::ReferenceParams& samplerParams) 765 { 766 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 767 const gls::TextureTestUtil::RandomViewport viewport (m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getIterationSeed(config)); 768 std::vector<float> texCoord; 769 de::MovePtr<glu::Sampler> sampler; 770 771 glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1); 772 773 // Bind to unit 0. 774 gl.activeTexture(GL_TEXTURE0); 775 gl.bindTexture(GL_TEXTURE_2D, m_texture->getGLTexture()); 776 777 if (m_sampleMode == tcu::Sampler::MODE_DEPTH) 778 gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_DEPTH_COMPONENT); 779 else if (m_sampleMode == tcu::Sampler::MODE_STENCIL) 780 gl.texParameteri(GL_TEXTURE_2D, GL_DEPTH_STENCIL_TEXTURE_MODE, GL_STENCIL_INDEX); 781 782 if (config.compareMode == GL_NONE) 783 { 784 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_NONE); 785 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, GL_ALWAYS); 786 } 787 else 788 { 789 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_MODE, GL_COMPARE_REF_TO_TEXTURE); 790 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_COMPARE_FUNC, config.compareMode); 791 } 792 793 if (m_stateType == STATE_TEXTURE_PARAM) 794 { 795 // Setup filtering and wrap modes. 796 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); 797 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); 798 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); 799 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); 800 801 switch (m_channelClass) 802 { 803 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 804 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 805 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 806 gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>()); 807 break; 808 809 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 810 gl.texParameterIiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>()); 811 break; 812 813 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 814 gl.texParameterIuiv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>()); 815 break; 816 817 default: 818 DE_ASSERT(false); 819 } 820 } 821 else if (m_stateType == STATE_SAMPLER_PARAM) 822 { 823 const tcu::Vec4 blue(0.0f, 0.0f, 1.0f, 1.0f); 824 825 // Setup filtering and wrap modes to bad values 826 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT); 827 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT); 828 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); 829 gl.texParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); 830 gl.texParameterfv(GL_TEXTURE_2D, GL_TEXTURE_BORDER_COLOR, blue.getPtr()); // just set some unlikely color 831 832 // setup sampler to correct values 833 sampler = de::MovePtr<glu::Sampler>(new glu::Sampler(m_context.getRenderContext())); 834 835 gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); 836 gl.samplerParameteri(**sampler, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); 837 gl.samplerParameteri(**sampler, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); 838 gl.samplerParameteri(**sampler, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); 839 840 switch (m_channelClass) 841 { 842 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 843 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 844 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 845 gl.samplerParameterfv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<float>()); 846 break; 847 848 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 849 gl.samplerParameterIiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deInt32>()); 850 break; 851 852 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 853 gl.samplerParameterIuiv(**sampler, GL_TEXTURE_BORDER_COLOR, config.borderColor.getAccess<deUint32>()); 854 break; 855 856 default: 857 DE_ASSERT(false); 858 } 859 860 gl.bindSampler(0, **sampler); 861 } 862 863 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); 864 865 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 866 renderQuad(&texCoord[0], samplerParams); 867 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess()); 868 } 869 870 void TextureBorderClampTest::renderQuad (const float* texCoord, const glu::TextureTestUtil::ReferenceParams& samplerParams) 871 { 872 // use TextureRenderer for basic rendering, use custom for gather 873 if (m_samplingFunction == SAMPLE_FILTER) 874 m_renderer->renderQuad(0, texCoord, samplerParams); 875 else 876 { 877 static const float position[] = 878 { 879 -1.0f, -1.0f, 0.0f, 1.0f, 880 -1.0f, +1.0f, 0.0f, 1.0f, 881 +1.0f, -1.0f, 0.0f, 1.0f, 882 +1.0f, +1.0f, 0.0f, 1.0f 883 }; 884 static const deUint16 indices[] = 885 { 886 0, 1, 2, 2, 1, 3 887 }; 888 const glu::VertexArrayBinding vertexArrays[] = 889 { 890 glu::va::Float("a_position", 4, 4, 0, &position[0]), 891 glu::va::Float("a_texcoord", 2, 4, 0, texCoord) 892 }; 893 894 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 895 const deUint32 progId = m_gatherProgram->getProgram(); 896 897 gl.useProgram(progId); 898 gl.uniform1i(gl.getUniformLocation(progId, "u_sampler"), 0); 899 if (m_useShadowSampler) 900 gl.uniform1f(gl.getUniformLocation(progId, "u_ref"), samplerParams.ref); 901 gl.uniform4fv(gl.getUniformLocation(progId, "u_colorScale"), 1, samplerParams.colorScale.getPtr()); 902 gl.uniform4fv(gl.getUniformLocation(progId, "u_colorBias"), 1, samplerParams.colorBias.getPtr()); 903 904 glu::draw(m_context.getRenderContext(), progId, DE_LENGTH_OF_ARRAY(vertexArrays), &vertexArrays[0], 905 glu::pr::Triangles(DE_LENGTH_OF_ARRAY(indices), &indices[0])); 906 } 907 } 908 909 void TextureBorderClampTest::verifyImage (const tcu::Surface& renderedFrame, 910 const IterationConfig& config, 911 const glu::TextureTestUtil::ReferenceParams& samplerParams) 912 { 913 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 914 915 tcu::LodPrecision lodPrecision; 916 std::vector<float> texCoord; 917 bool verificationOk; 918 919 glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, config.p0, config.p1); 920 921 lodPrecision.derivateBits = 18; 922 lodPrecision.lodBits = 5; 923 924 if (samplerParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE) 925 { 926 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode); 927 const bool isNearestMinFilter = samplerParams.sampler.minFilter == tcu::Sampler::NEAREST || samplerParams.sampler.minFilter == tcu::Sampler::NEAREST_MIPMAP_NEAREST; 928 const bool isNearestMagFilter = samplerParams.sampler.magFilter == tcu::Sampler::NEAREST; 929 const bool isNearestOnly = isNearestMinFilter && isNearestMagFilter; 930 const bool isSRGB = texFormat.order == tcu::TextureFormat::sRGB || texFormat.order == tcu::TextureFormat::sRGBA; 931 const int colorErrorBits = (isNearestOnly && !isSRGB) ? (1) : (2); 932 const tcu::IVec4 colorBits = tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); 933 tcu::LookupPrecision lookupPrecision; 934 935 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale; 936 lookupPrecision.coordBits = tcu::IVec3(20,20,0); 937 lookupPrecision.uvwBits = tcu::IVec3(5,5,0); 938 lookupPrecision.colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); 939 940 if (m_samplingFunction == SAMPLE_FILTER) 941 { 942 verificationOk = verifyTextureSampleResult(renderedFrame.getAccess(), 943 &texCoord[0], 944 samplerParams, 945 lodPrecision, 946 lookupPrecision); 947 } 948 else if (m_samplingFunction == SAMPLE_GATHER) 949 { 950 verificationOk = verifyTextureGatherResult(renderedFrame.getAccess(), 951 &texCoord[0], 952 samplerParams, 953 lookupPrecision); 954 } 955 else 956 { 957 DE_ASSERT(false); 958 verificationOk = false; 959 } 960 } 961 else 962 { 963 tcu::TexComparePrecision texComparePrecision; 964 tcu::TexComparePrecision lowQualityTexComparePrecision; 965 tcu::LodPrecision lowQualityLodPrecision = lodPrecision; 966 967 texComparePrecision.coordBits = tcu::IVec3(20,20,0); 968 texComparePrecision.uvwBits = tcu::IVec3(7,7,0); 969 texComparePrecision.pcfBits = 5; 970 texComparePrecision.referenceBits = 16; 971 texComparePrecision.resultBits = de::max(0, pixelFormat.redBits - 1); 972 973 lowQualityTexComparePrecision.coordBits = tcu::IVec3(20,20,0); 974 lowQualityTexComparePrecision.uvwBits = tcu::IVec3(4,4,0); 975 lowQualityTexComparePrecision.pcfBits = 0; 976 lowQualityTexComparePrecision.referenceBits = 16; 977 lowQualityTexComparePrecision.resultBits = de::max(0, pixelFormat.redBits - 1); 978 979 lowQualityLodPrecision.lodBits = 4; 980 981 if (m_samplingFunction == SAMPLE_FILTER) 982 { 983 verificationOk = verifyTextureCompareResult(renderedFrame.getAccess(), 984 &texCoord[0], 985 samplerParams, 986 texComparePrecision, 987 lowQualityTexComparePrecision, 988 lodPrecision, 989 lowQualityLodPrecision); 990 } 991 else if (m_samplingFunction == SAMPLE_GATHER) 992 { 993 verificationOk = verifyTextureGatherCmpResult(renderedFrame.getAccess(), 994 &texCoord[0], 995 samplerParams, 996 texComparePrecision, 997 lowQualityTexComparePrecision); 998 } 999 else 1000 { 1001 DE_ASSERT(false); 1002 verificationOk = false; 1003 } 1004 } 1005 1006 if (!verificationOk) 1007 m_result.fail("Image verification failed"); 1008 } 1009 1010 bool TextureBorderClampTest::verifyTextureSampleResult (const tcu::ConstPixelBufferAccess& renderedFrame, 1011 const float* texCoord, 1012 const glu::TextureTestUtil::ReferenceParams& samplerParams, 1013 const tcu::LodPrecision& lodPrecision, 1014 const tcu::LookupPrecision& lookupPrecision) 1015 { 1016 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1017 tcu::Surface reference (renderedFrame.getWidth(), renderedFrame.getHeight()); 1018 tcu::Surface errorMask (renderedFrame.getWidth(), renderedFrame.getHeight()); 1019 int numFailedPixels; 1020 1021 glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), texCoord, samplerParams); 1022 1023 numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(), 1024 texCoord, samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog()); 1025 1026 if (numFailedPixels > 0) 1027 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1028 m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1029 << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); 1030 if (numFailedPixels > 0) 1031 { 1032 m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1033 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1034 } 1035 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 1036 1037 return (numFailedPixels == 0); 1038 } 1039 1040 bool TextureBorderClampTest::verifyTextureCompareResult (const tcu::ConstPixelBufferAccess& renderedFrame, 1041 const float* texCoord, 1042 const glu::TextureTestUtil::ReferenceParams& samplerParams, 1043 const tcu::TexComparePrecision& texComparePrecision, 1044 const tcu::TexComparePrecision& lowQualityTexComparePrecision, 1045 const tcu::LodPrecision& lodPrecision, 1046 const tcu::LodPrecision& lowQualityLodPrecision) 1047 { 1048 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1049 const int colorErrorBits = 1; 1050 const tcu::IVec4 nonShadowBits = tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); 1051 const tcu::Vec3 nonShadowThreshold = tcu::computeFixedPointThreshold(nonShadowBits).swizzle(1,2,3); 1052 std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1053 const tcu::Texture2DView effectiveView = tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); 1054 tcu::Surface reference (renderedFrame.getWidth(), renderedFrame.getHeight()); 1055 tcu::Surface errorMask (renderedFrame.getWidth(), renderedFrame.getHeight()); 1056 int numFailedPixels; 1057 1058 glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), effectiveView, texCoord, samplerParams); 1059 1060 numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, 1061 texCoord, samplerParams, texComparePrecision, lodPrecision, nonShadowThreshold); 1062 1063 if (numFailedPixels > 0) 1064 { 1065 m_testCtx.getLog() << tcu::TestLog::Message 1066 << "Warning: Verification assuming high-quality PCF filtering failed." 1067 << tcu::TestLog::EndMessage; 1068 1069 numFailedPixels = glu::TextureTestUtil::computeTextureCompareDiff(renderedFrame, reference.getAccess(), errorMask.getAccess(), effectiveView, 1070 texCoord, samplerParams, lowQualityTexComparePrecision, lowQualityLodPrecision, nonShadowThreshold); 1071 1072 if (numFailedPixels > 0) 1073 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Verification against low precision requirements failed, failing test case." << tcu::TestLog::EndMessage; 1074 else if (m_testCtx.getTestResult() == QP_TEST_RESULT_PASS) 1075 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); 1076 } 1077 1078 if (numFailedPixels > 0) 1079 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1080 m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1081 << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); 1082 if (numFailedPixels > 0) 1083 { 1084 m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1085 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1086 } 1087 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 1088 1089 return (numFailedPixels == 0); 1090 } 1091 1092 template <typename T> 1093 static inline T triQuadInterpolate (const T (&values)[4], float xFactor, float yFactor) 1094 { 1095 if (xFactor + yFactor < 1.0f) 1096 return values[0] + (values[2]-values[0])*xFactor + (values[1]-values[0])*yFactor; 1097 else 1098 return values[3] + (values[1]-values[3])*(1.0f-xFactor) + (values[2]-values[3])*(1.0f-yFactor); 1099 } 1100 1101 bool TextureBorderClampTest::verifyTextureGatherResult (const tcu::ConstPixelBufferAccess& renderedFrame, 1102 const float* texCoordArray, 1103 const glu::TextureTestUtil::ReferenceParams& samplerParams, 1104 const tcu::LookupPrecision& lookupPrecision) 1105 { 1106 const tcu::Vec2 texCoords[4] = 1107 { 1108 tcu::Vec2(texCoordArray[0], texCoordArray[1]), 1109 tcu::Vec2(texCoordArray[2], texCoordArray[3]), 1110 tcu::Vec2(texCoordArray[4], texCoordArray[5]), 1111 tcu::Vec2(texCoordArray[6], texCoordArray[7]), 1112 }; 1113 1114 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1115 const deUint8 fbColormask = tcu::getColorMask(pixelFormat); 1116 1117 std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1118 const tcu::Texture2DView effectiveView = tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); 1119 1120 tcu::Surface reference (renderedFrame.getWidth(), renderedFrame.getHeight()); 1121 tcu::Surface errorMask (renderedFrame.getWidth(), renderedFrame.getHeight()); 1122 int numFailedPixels = 0; 1123 1124 tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); 1125 1126 for (int py = 0; py < reference.getHeight(); ++py) 1127 for (int px = 0; px < reference.getWidth(); ++px) 1128 { 1129 const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight()); 1130 const tcu::Vec2 texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y()); 1131 const tcu::Vec4 referenceValue = effectiveView.gatherOffsets(samplerParams.sampler, texCoord.x(), texCoord.y(), 0, glu::getDefaultGatherOffsets()); 1132 const tcu::Vec4 referencePixel = referenceValue * samplerParams.colorScale + samplerParams.colorBias; 1133 const tcu::Vec4 resultPixel = renderedFrame.getPixel(px, py); 1134 const tcu::Vec4 resultValue = (resultPixel - samplerParams.colorBias) / samplerParams.colorScale; 1135 1136 reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask)); 1137 1138 if (tcu::boolAny(tcu::logicalAnd(lookupPrecision.colorMask, 1139 tcu::greaterThan(tcu::absDiff(resultPixel, referencePixel), 1140 lookupPrecision.colorThreshold)))) 1141 { 1142 if (!tcu::isGatherOffsetsResultValid(effectiveView, samplerParams.sampler, lookupPrecision, texCoord, 0, glu::getDefaultGatherOffsets(), resultValue)) 1143 { 1144 errorMask.setPixel(px, py, tcu::RGBA::red()); 1145 ++numFailedPixels; 1146 } 1147 } 1148 } 1149 1150 if (numFailedPixels > 0) 1151 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1152 m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1153 << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); 1154 if (numFailedPixels > 0) 1155 { 1156 m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1157 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1158 } 1159 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 1160 1161 return (numFailedPixels == 0); 1162 } 1163 1164 bool TextureBorderClampTest::verifyTextureGatherCmpResult (const tcu::ConstPixelBufferAccess& renderedFrame, 1165 const float* texCoordArray, 1166 const glu::TextureTestUtil::ReferenceParams& samplerParams, 1167 const tcu::TexComparePrecision& texComparePrecision, 1168 const tcu::TexComparePrecision& lowQualityTexComparePrecision) 1169 { 1170 const tcu::Vec2 texCoords[4] = 1171 { 1172 tcu::Vec2(texCoordArray[0], texCoordArray[1]), 1173 tcu::Vec2(texCoordArray[2], texCoordArray[3]), 1174 tcu::Vec2(texCoordArray[4], texCoordArray[5]), 1175 tcu::Vec2(texCoordArray[6], texCoordArray[7]), 1176 }; 1177 1178 std::vector<tcu::ConstPixelBufferAccess> srcLevelStorage; 1179 const tcu::Texture2DView effectiveView = tcu::getEffectiveTextureView(m_texture->getRefTexture(), srcLevelStorage, samplerParams.sampler); 1180 1181 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 1182 const tcu::BVec4 colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); 1183 const deUint8 fbColormask = tcu::getColorMask(pixelFormat); 1184 tcu::Surface reference (renderedFrame.getWidth(), renderedFrame.getHeight()); 1185 tcu::Surface errorMask (renderedFrame.getWidth(), renderedFrame.getHeight()); 1186 int numFailedPixels = 0; 1187 bool lowQuality = false; 1188 1189 tcu::clear(errorMask.getAccess(), tcu::RGBA::green().toVec()); 1190 1191 for (int py = 0; py < reference.getHeight(); ++py) 1192 for (int px = 0; px < reference.getWidth(); ++px) 1193 { 1194 const tcu::Vec2 viewportCoord = (tcu::Vec2((float)px, (float)py) + tcu::Vec2(0.5f)) / tcu::Vec2((float)reference.getWidth(), (float)reference.getHeight()); 1195 const tcu::Vec2 texCoord = triQuadInterpolate(texCoords, viewportCoord.x(), viewportCoord.y()); 1196 const float refZ = samplerParams.ref; 1197 const tcu::Vec4 referenceValue = effectiveView.gatherOffsetsCompare(samplerParams.sampler, refZ, texCoord.x(), texCoord.y(), glu::getDefaultGatherOffsets()); 1198 const tcu::Vec4 resultValue = renderedFrame.getPixel(px, py); 1199 1200 reference.setPixel(px, py, tcu::toRGBAMasked(referenceValue, fbColormask)); 1201 1202 if (tcu::boolAny(tcu::logicalAnd(colorMask, tcu::notEqual(referenceValue, resultValue)))) 1203 { 1204 if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, texComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue)) 1205 { 1206 lowQuality = true; 1207 1208 // fall back to low quality verification 1209 if (!tcu::isGatherOffsetsCompareResultValid(effectiveView, samplerParams.sampler, lowQualityTexComparePrecision, texCoord, glu::getDefaultGatherOffsets(), refZ, resultValue)) 1210 { 1211 errorMask.setPixel(px, py, tcu::RGBA::red()); 1212 ++numFailedPixels; 1213 } 1214 } 1215 } 1216 } 1217 1218 if (numFailedPixels > 0) 1219 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 1220 else if (lowQuality) 1221 { 1222 m_testCtx.getLog() << tcu::TestLog::Message << "Warning: Verification assuming high-quality PCF filtering failed." << tcu::TestLog::EndMessage; 1223 m_result.addResult(QP_TEST_RESULT_QUALITY_WARNING, "Low-quality result"); 1224 } 1225 1226 m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 1227 << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); 1228 if (numFailedPixels > 0) 1229 { 1230 m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 1231 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 1232 } 1233 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 1234 1235 return (numFailedPixels == 0); 1236 } 1237 1238 const glu::Texture2D* TextureBorderClampTest::getTexture (void) const 1239 { 1240 return m_texture.get(); 1241 } 1242 1243 deUint32 TextureBorderClampTest::getIterationSeed (const IterationConfig& config) const 1244 { 1245 tcu::SeedBuilder builder; 1246 builder << std::string(getName()) 1247 << m_iterationNdx 1248 << m_texFormat 1249 << config.minFilter << config.magFilter 1250 << m_texture->getRefTexture().getWidth() << m_texture->getRefTexture().getHeight(); 1251 return builder.get(); 1252 } 1253 1254 glu::TextureTestUtil::ReferenceParams TextureBorderClampTest::genSamplerParams (const IterationConfig& config) const 1255 { 1256 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(m_texture->getRefTexture().getFormat(), m_sampleMode); 1257 glu::TextureTestUtil::ReferenceParams refParams (glu::TextureTestUtil::TEXTURETYPE_2D); 1258 1259 refParams.sampler = glu::mapGLSampler(config.sWrapMode, config.tWrapMode, config.minFilter, config.magFilter); 1260 refParams.sampler.borderColor = config.borderColor; 1261 refParams.sampler.compare = (!m_useShadowSampler) ? (tcu::Sampler::COMPAREMODE_NONE) : (glu::mapGLCompareFunc(config.compareMode)); 1262 refParams.sampler.depthStencilMode = m_sampleMode; 1263 refParams.lodMode = glu::TextureTestUtil::LODMODE_EXACT; 1264 refParams.samplerType = (!m_useShadowSampler) ? (glu::TextureTestUtil::getSamplerType(texFormat)) : (glu::TextureTestUtil::SAMPLERTYPE_SHADOW); 1265 refParams.colorScale = config.lookupScale; 1266 refParams.colorBias = config.lookupBias; 1267 refParams.ref = config.compareRef; 1268 1269 // compare can only be used with depth textures 1270 if (!isDepthFormat(m_texFormat, m_sampleMode)) 1271 DE_ASSERT(refParams.sampler.compare == tcu::Sampler::COMPAREMODE_NONE); 1272 1273 // sampler type must match compare mode 1274 DE_ASSERT(m_useShadowSampler == (config.compareMode != GL_NONE)); 1275 1276 // in gather, weird mapping is most likely an error 1277 if (m_samplingFunction == SAMPLE_GATHER) 1278 { 1279 DE_ASSERT(refParams.colorScale == tcu::Vec4(refParams.colorScale.x())); 1280 DE_ASSERT(refParams.colorBias == tcu::Vec4(refParams.colorBias.x())); 1281 } 1282 1283 return refParams; 1284 } 1285 1286 glu::ShaderProgram* TextureBorderClampTest::genGatherProgram (void) const 1287 { 1288 const std::string glslVersionDecl = glu::getGLSLVersionDeclaration(glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType())); 1289 const std::string vtxSource = glslVersionDecl + "\n" 1290 "in highp vec4 a_position;\n" 1291 "in highp vec2 a_texcoord;\n" 1292 "out highp vec2 v_texcoord;\n" 1293 "void main()\n" 1294 "{\n" 1295 " gl_Position = a_position;\n" 1296 " v_texcoord = a_texcoord;\n" 1297 "}\n"; 1298 const char* samplerType; 1299 const char* lookup; 1300 std::ostringstream fragSource; 1301 1302 if (m_useShadowSampler) 1303 { 1304 samplerType = "sampler2DShadow"; 1305 lookup = "textureGather(u_sampler, v_texcoord, u_ref)"; 1306 } 1307 else 1308 { 1309 switch (m_channelClass) 1310 { 1311 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1312 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1313 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 1314 samplerType = "sampler2D"; 1315 lookup = "textureGather(u_sampler, v_texcoord)"; 1316 break; 1317 1318 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1319 samplerType = "isampler2D"; 1320 lookup = "vec4(textureGather(u_sampler, v_texcoord))"; 1321 break; 1322 1323 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1324 samplerType = "usampler2D"; 1325 lookup = "vec4(textureGather(u_sampler, v_texcoord))"; 1326 break; 1327 1328 default: 1329 samplerType = ""; 1330 lookup = ""; 1331 DE_ASSERT(false); 1332 } 1333 } 1334 1335 fragSource << glslVersionDecl + "\n" 1336 "uniform highp " << samplerType << " u_sampler;\n" 1337 "uniform highp vec4 u_colorScale;\n" 1338 "uniform highp vec4 u_colorBias;\n" 1339 << ((m_useShadowSampler) ? ("uniform highp float u_ref;\n") : ("")) 1340 << "in highp vec2 v_texcoord;\n" 1341 "layout(location=0) out highp vec4 o_color;\n" 1342 "void main()\n" 1343 "{\n" 1344 " o_color = " << lookup << " * u_colorScale + u_colorBias;\n" 1345 "}\n"; 1346 1347 return new glu::ShaderProgram(m_context.getRenderContext(), glu::ProgramSources() << glu::VertexSource(vtxSource) << glu::FragmentSource(fragSource.str())); 1348 } 1349 1350 class TextureBorderClampFormatCase : public TextureBorderClampTest 1351 { 1352 public: 1353 TextureBorderClampFormatCase (Context& context, 1354 const char* name, 1355 const char* description, 1356 deUint32 texFormat, 1357 tcu::Sampler::DepthStencilMode mode, 1358 StateType stateType, 1359 SizeType sizeType, 1360 deUint32 filter, 1361 SamplingFunction samplingFunction); 1362 1363 private: 1364 void init (void); 1365 1366 int getNumIterations (void) const; 1367 IterationConfig getIteration (int ndx) const; 1368 1369 const SizeType m_sizeType; 1370 const deUint32 m_filter; 1371 1372 std::vector<IterationConfig> m_iterations; 1373 }; 1374 1375 1376 TextureBorderClampFormatCase::TextureBorderClampFormatCase (Context& context, 1377 const char* name, 1378 const char* description, 1379 deUint32 texFormat, 1380 tcu::Sampler::DepthStencilMode mode, 1381 StateType stateType, 1382 SizeType sizeType, 1383 deUint32 filter, 1384 SamplingFunction samplingFunction) 1385 : TextureBorderClampTest(context, 1386 name, 1387 description, 1388 texFormat, 1389 mode, 1390 stateType, 1391 (sizeType == SIZE_POT) ? (32) : (17), 1392 (sizeType == SIZE_POT) ? (16) : (31), 1393 samplingFunction) 1394 , m_sizeType (sizeType) 1395 , m_filter (filter) 1396 { 1397 if (m_sizeType == SIZE_POT) 1398 DE_ASSERT(deIsPowerOfTwo32(m_texWidth) && deIsPowerOfTwo32(m_texHeight)); 1399 else 1400 DE_ASSERT(!deIsPowerOfTwo32(m_texWidth) && !deIsPowerOfTwo32(m_texHeight)); 1401 1402 if (glu::isCompressedFormat(texFormat)) 1403 { 1404 const tcu::CompressedTexFormat compressedFormat = glu::mapGLCompressedTexFormat(texFormat); 1405 const tcu::IVec3 blockPixelSize = tcu::getBlockPixelSize(compressedFormat); 1406 1407 // is (not) multiple of a block size 1408 if (m_sizeType == SIZE_POT) 1409 DE_ASSERT((m_texWidth % blockPixelSize.x()) == 0 && (m_texHeight % blockPixelSize.y()) == 0); 1410 else 1411 DE_ASSERT((m_texWidth % blockPixelSize.x()) != 0 && (m_texHeight % blockPixelSize.y()) != 0); 1412 1413 DE_UNREF(blockPixelSize); 1414 } 1415 } 1416 1417 void TextureBorderClampFormatCase::init (void) 1418 { 1419 TextureBorderClampTest::init(); 1420 1421 // \note TextureBorderClampTest::init() creates texture 1422 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); 1423 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); 1424 1425 // iterations 1426 1427 { 1428 IterationConfig iteration; 1429 iteration.p0 = tcu::Vec2(-1.5f, -3.0f); 1430 iteration.p1 = tcu::Vec2( 1.5f, 2.5f); 1431 iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.3f, 0.7f, 0.2f, 0.5f)); 1432 m_iterations.push_back(iteration); 1433 } 1434 { 1435 IterationConfig iteration; 1436 iteration.p0 = tcu::Vec2(-0.5f, 0.75f); 1437 iteration.p1 = tcu::Vec2(0.25f, 1.25f); 1438 iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.9f, 0.2f, 0.4f, 0.6f)); 1439 m_iterations.push_back(iteration); 1440 } 1441 1442 // common parameters 1443 for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) 1444 { 1445 IterationConfig& iteration = m_iterations[ndx]; 1446 1447 if (m_samplingFunction == SAMPLE_GATHER) 1448 { 1449 iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x()); 1450 iteration.lookupBias = tcu::Vec4(texFormatInfo.lookupBias.x()); 1451 } 1452 else 1453 { 1454 iteration.lookupScale = texFormatInfo.lookupScale; 1455 iteration.lookupBias = texFormatInfo.lookupBias; 1456 } 1457 1458 iteration.minFilter = m_filter; 1459 iteration.magFilter = m_filter; 1460 iteration.sWrapMode = GL_CLAMP_TO_BORDER; 1461 iteration.tWrapMode = GL_CLAMP_TO_BORDER; 1462 iteration.compareMode = GL_NONE; 1463 iteration.compareRef = 0.0f; 1464 } 1465 } 1466 1467 int TextureBorderClampFormatCase::getNumIterations (void) const 1468 { 1469 return (int)m_iterations.size(); 1470 } 1471 1472 TextureBorderClampTest::IterationConfig TextureBorderClampFormatCase::getIteration (int ndx) const 1473 { 1474 return m_iterations[ndx]; 1475 } 1476 1477 class TextureBorderClampRangeClampCase : public TextureBorderClampTest 1478 { 1479 public: 1480 TextureBorderClampRangeClampCase (Context& context, 1481 const char* name, 1482 const char* description, 1483 deUint32 texFormat, 1484 tcu::Sampler::DepthStencilMode mode, 1485 deUint32 filter); 1486 1487 private: 1488 void init (void); 1489 1490 int getNumIterations (void) const; 1491 IterationConfig getIteration (int ndx) const; 1492 1493 const deUint32 m_filter; 1494 std::vector<IterationConfig> m_iterations; 1495 }; 1496 1497 TextureBorderClampRangeClampCase::TextureBorderClampRangeClampCase (Context& context, 1498 const char* name, 1499 const char* description, 1500 deUint32 texFormat, 1501 tcu::Sampler::DepthStencilMode mode, 1502 deUint32 filter) 1503 : TextureBorderClampTest(context, name, description, texFormat, mode, TextureBorderClampTest::STATE_TEXTURE_PARAM, 8, 32, SAMPLE_FILTER) 1504 , m_filter (filter) 1505 { 1506 } 1507 1508 void TextureBorderClampRangeClampCase::init (void) 1509 { 1510 TextureBorderClampTest::init(); 1511 1512 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); 1513 const bool isDepth = isDepthFormat(m_texFormat, m_sampleMode); 1514 const bool isFloat = m_channelClass == tcu::TEXTURECHANNELCLASS_FLOATING_POINT; 1515 const bool isFixed = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT; 1516 const bool isPureInteger = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER || m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER; 1517 1518 if (isDepth || isFloat) 1519 { 1520 // infinities are commonly used values on depth/float borders 1521 { 1522 IterationConfig iteration; 1523 iteration.p0 = tcu::Vec2(-1.2f, -3.0f); 1524 iteration.p1 = tcu::Vec2( 1.2f, 2.5f); 1525 iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity())); 1526 iteration.lookupScale = tcu::Vec4(0.5f); // scale & bias to [0.25, 0.5] range to make out-of-range values visible 1527 iteration.lookupBias = tcu::Vec4(0.25f); 1528 iteration.description = "border value infinity"; 1529 m_iterations.push_back(iteration); 1530 } 1531 { 1532 IterationConfig iteration; 1533 iteration.p0 = tcu::Vec2(-0.25f, -0.75f); 1534 iteration.p1 = tcu::Vec2( 2.25f, 1.25f); 1535 iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity())); 1536 iteration.lookupScale = tcu::Vec4(0.5f); 1537 iteration.lookupBias = tcu::Vec4(0.25f); 1538 iteration.description = "border value negative infinity"; 1539 m_iterations.push_back(iteration); 1540 } 1541 } 1542 else if (isPureInteger) 1543 { 1544 const tcu::IVec4 numBits = tcu::getTextureFormatBitDepth(texFormat); 1545 const bool isSigned = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER; 1546 1547 // can't overflow 32bit integers with 32bit integers 1548 for (int ndx = 0; ndx < 4; ++ndx) 1549 DE_ASSERT(numBits[ndx] == 0 || numBits[ndx] == 8 || numBits[ndx] == 16); 1550 1551 const tcu::IVec4 minValue = getNBitIntegerVec4MinValue(isSigned, numBits); 1552 const tcu::IVec4 maxValue = getNBitIntegerVec4MaxValue(isSigned, numBits); 1553 const tcu::IVec4 valueRange = maxValue - minValue; 1554 const tcu::IVec4 divSafeRange ((valueRange[0]==0) ? (1) : (valueRange[0]), 1555 (valueRange[1]==0) ? (1) : (valueRange[1]), 1556 (valueRange[2]==0) ? (1) : (valueRange[2]), 1557 (valueRange[3]==0) ? (1) : (valueRange[3])); 1558 1559 // format max 1560 { 1561 const tcu::IVec4 value = maxValue + tcu::IVec4(1); 1562 1563 IterationConfig iteration; 1564 iteration.p0 = tcu::Vec2(-1.2f, -3.0f); 1565 iteration.p1 = tcu::Vec2( 1.2f, 2.5f); 1566 iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>())); 1567 iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); 1568 iteration.lookupBias = (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f)); 1569 iteration.description = "border values one larger than maximum"; 1570 m_iterations.push_back(iteration); 1571 } 1572 // format min 1573 if (isSigned) 1574 { 1575 const tcu::IVec4 value = minValue - tcu::IVec4(1); 1576 1577 IterationConfig iteration; 1578 iteration.p0 = tcu::Vec2(-0.25f, -0.75f); 1579 iteration.p1 = tcu::Vec2( 2.25f, 1.25f); 1580 iteration.borderColor = rr::GenericVec4(value); 1581 iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); 1582 iteration.lookupBias = tcu::Vec4(0.5f); 1583 iteration.description = "border values one less than minimum"; 1584 m_iterations.push_back(iteration); 1585 } 1586 // (u)int32 max 1587 { 1588 const tcu::IVec4 value = (isSigned) ? (tcu::IVec4(std::numeric_limits<deInt32>::max())) : (tcu::IVec4(std::numeric_limits<deUint32>::max())); 1589 1590 IterationConfig iteration; 1591 iteration.p0 = tcu::Vec2(-1.6f, -2.1f); 1592 iteration.p1 = tcu::Vec2( 1.2f, 3.5f); 1593 iteration.borderColor = (isSigned) ? (rr::GenericVec4(value)) : (rr::GenericVec4(value.cast<deUint32>())); 1594 iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); 1595 iteration.lookupBias = tcu::Vec4(0.25f); 1596 iteration.description = "border values 32-bit maximum"; 1597 m_iterations.push_back(iteration); 1598 } 1599 // int32 min 1600 if (isSigned) 1601 { 1602 const tcu::IVec4 value = tcu::IVec4(std::numeric_limits<deInt32>::min()); 1603 1604 IterationConfig iteration; 1605 iteration.p0 = tcu::Vec2(-2.6f, -4.0f); 1606 iteration.p1 = tcu::Vec2( 1.1f, 1.5f); 1607 iteration.borderColor = rr::GenericVec4(value); 1608 iteration.lookupScale = tcu::Vec4(0.5f) / divSafeRange.cast<float>(); 1609 iteration.lookupBias = tcu::Vec4(0.25f); 1610 iteration.description = "border values 0"; 1611 m_iterations.push_back(iteration); 1612 } 1613 } 1614 else if (isFixed) 1615 { 1616 const bool isSigned = m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT;; 1617 const tcu::Vec4 lookupBias = (isSigned) ? (tcu::Vec4(0.5f)) : (tcu::Vec4(0.25f)); // scale & bias to [0.25, 0.5] range to make out-of-range values visible 1618 const tcu::Vec4 lookupScale = (isSigned) ? (tcu::Vec4(0.25f)) : (tcu::Vec4(0.5f)); 1619 1620 { 1621 IterationConfig iteration; 1622 iteration.p0 = tcu::Vec2(-1.2f, -3.0f); 1623 iteration.p1 = tcu::Vec2( 1.2f, 2.5f); 1624 iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(1.1f, 1.3f, 2.2f, 1.3f)); 1625 iteration.lookupScale = lookupScale; 1626 iteration.lookupBias = lookupBias; 1627 iteration.description = "border values larger than maximum"; 1628 m_iterations.push_back(iteration); 1629 } 1630 { 1631 IterationConfig iteration; 1632 iteration.p0 = tcu::Vec2(-0.25f, -0.75f); 1633 iteration.p1 = tcu::Vec2( 2.25f, 1.25f); 1634 iteration.borderColor = mapToFormatColorUnits(texFormat, tcu::Vec4(-0.2f, -0.9f, -2.4f, -0.6f)); 1635 iteration.lookupScale = lookupScale; 1636 iteration.lookupBias = lookupBias; 1637 iteration.description = "border values less than minimum"; 1638 m_iterations.push_back(iteration); 1639 } 1640 } 1641 else 1642 DE_ASSERT(false); 1643 1644 // common parameters 1645 for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) 1646 { 1647 IterationConfig& iteration = m_iterations[ndx]; 1648 1649 iteration.minFilter = m_filter; 1650 iteration.magFilter = m_filter; 1651 iteration.sWrapMode = GL_CLAMP_TO_BORDER; 1652 iteration.tWrapMode = GL_CLAMP_TO_BORDER; 1653 iteration.compareMode = GL_NONE; 1654 iteration.compareRef = 0.0f; 1655 } 1656 } 1657 1658 int TextureBorderClampRangeClampCase::getNumIterations (void) const 1659 { 1660 return (int)m_iterations.size(); 1661 } 1662 1663 TextureBorderClampTest::IterationConfig TextureBorderClampRangeClampCase::getIteration (int ndx) const 1664 { 1665 return m_iterations[ndx]; 1666 } 1667 1668 class TextureBorderClampPerAxisCase2D : public TextureBorderClampTest 1669 { 1670 public: 1671 TextureBorderClampPerAxisCase2D (Context& context, 1672 const char* name, 1673 const char* description, 1674 deUint32 texFormat, 1675 tcu::Sampler::DepthStencilMode mode, 1676 SizeType sizeType, 1677 deUint32 filter, 1678 deUint32 texSWrap, 1679 deUint32 texTWrap, 1680 SamplingFunction samplingFunction); 1681 1682 private: 1683 void init (void); 1684 1685 int getNumIterations (void) const; 1686 IterationConfig getIteration (int ndx) const; 1687 1688 const deUint32 m_texSWrap; 1689 const deUint32 m_texTWrap; 1690 const deUint32 m_filter; 1691 1692 std::vector<IterationConfig> m_iterations; 1693 }; 1694 1695 TextureBorderClampPerAxisCase2D::TextureBorderClampPerAxisCase2D (Context& context, 1696 const char* name, 1697 const char* description, 1698 deUint32 texFormat, 1699 tcu::Sampler::DepthStencilMode mode, 1700 SizeType sizeType, 1701 deUint32 filter, 1702 deUint32 texSWrap, 1703 deUint32 texTWrap, 1704 SamplingFunction samplingFunction) 1705 : TextureBorderClampTest(context, 1706 name, 1707 description, 1708 texFormat, 1709 mode, 1710 TextureBorderClampTest::STATE_TEXTURE_PARAM, 1711 (sizeType == SIZE_POT) ? (16) : (7), 1712 (sizeType == SIZE_POT) ? (8) : (9), 1713 samplingFunction) 1714 , m_texSWrap (texSWrap) 1715 , m_texTWrap (texTWrap) 1716 , m_filter (filter) 1717 { 1718 } 1719 1720 void TextureBorderClampPerAxisCase2D::init (void) 1721 { 1722 TextureBorderClampTest::init(); 1723 1724 // \note TextureBorderClampTest::init() creates texture 1725 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); 1726 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); 1727 1728 IterationConfig iteration; 1729 iteration.p0 = tcu::Vec2(-0.25f, -0.75f); 1730 iteration.p1 = tcu::Vec2( 2.25f, 1.25f); 1731 iteration.borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.4f, 0.9f, 0.1f, 0.2f)); 1732 1733 if (m_samplingFunction == SAMPLE_GATHER) 1734 { 1735 iteration.lookupScale = tcu::Vec4(texFormatInfo.lookupScale.x()); 1736 iteration.lookupBias = tcu::Vec4(texFormatInfo.lookupBias.x()); 1737 } 1738 else 1739 { 1740 iteration.lookupScale = texFormatInfo.lookupScale; 1741 iteration.lookupBias = texFormatInfo.lookupBias; 1742 } 1743 1744 iteration.minFilter = m_filter; 1745 iteration.magFilter = m_filter; 1746 iteration.sWrapMode = m_texSWrap; 1747 iteration.tWrapMode = m_texTWrap; 1748 iteration.compareMode = GL_NONE; 1749 iteration.compareRef = 0.0f; 1750 1751 m_iterations.push_back(iteration); 1752 } 1753 1754 int TextureBorderClampPerAxisCase2D::getNumIterations (void) const 1755 { 1756 return (int)m_iterations.size(); 1757 } 1758 1759 TextureBorderClampTest::IterationConfig TextureBorderClampPerAxisCase2D::getIteration (int ndx) const 1760 { 1761 return m_iterations[ndx]; 1762 } 1763 1764 class TextureBorderClampDepthCompareCase : public TextureBorderClampTest 1765 { 1766 public: 1767 TextureBorderClampDepthCompareCase (Context& context, 1768 const char* name, 1769 const char* description, 1770 deUint32 texFormat, 1771 SizeType sizeType, 1772 deUint32 filter, 1773 SamplingFunction samplingFunction); 1774 1775 private: 1776 void init (void); 1777 1778 int getNumIterations (void) const; 1779 IterationConfig getIteration (int ndx) const; 1780 1781 const deUint32 m_filter; 1782 std::vector<IterationConfig> m_iterations; 1783 }; 1784 1785 TextureBorderClampDepthCompareCase::TextureBorderClampDepthCompareCase (Context& context, 1786 const char* name, 1787 const char* description, 1788 deUint32 texFormat, 1789 SizeType sizeType, 1790 deUint32 filter, 1791 SamplingFunction samplingFunction) 1792 : TextureBorderClampTest(context, 1793 name, 1794 description, 1795 texFormat, 1796 tcu::Sampler::MODE_DEPTH, 1797 TextureBorderClampTest::STATE_TEXTURE_PARAM, 1798 (sizeType == SIZE_POT) ? (32) : (13), 1799 (sizeType == SIZE_POT) ? (16) : (17), 1800 samplingFunction, 1801 FLAG_USE_SHADOW_SAMPLER) 1802 , m_filter (filter) 1803 { 1804 } 1805 1806 void TextureBorderClampDepthCompareCase::init (void) 1807 { 1808 TextureBorderClampTest::init(); 1809 1810 // 0.5 <= 0.7 1811 { 1812 IterationConfig iteration; 1813 iteration.p0 = tcu::Vec2(-0.15f, -0.35f); 1814 iteration.p1 = tcu::Vec2( 1.25f, 1.1f); 1815 iteration.borderColor = rr::GenericVec4(tcu::Vec4(0.7f, 0.0f, 0.0f, 0.0f)); 1816 iteration.description = "Border color in [0, 1] range"; 1817 iteration.compareMode = GL_LEQUAL; 1818 iteration.compareRef = 0.5f; 1819 m_iterations.push_back(iteration); 1820 } 1821 1822 // 1.5 <= 1.0 1823 { 1824 IterationConfig iteration; 1825 iteration.p0 = tcu::Vec2(-0.15f, -0.35f); 1826 iteration.p1 = tcu::Vec2( 1.25f, 1.1f); 1827 iteration.borderColor = rr::GenericVec4(tcu::Vec4(1.5f, 0.0f, 0.0f, 0.0f)); 1828 iteration.description = "Border color > 1, should be clamped"; 1829 iteration.compareMode = GL_LEQUAL; 1830 iteration.compareRef = 1.0f; 1831 m_iterations.push_back(iteration); 1832 } 1833 1834 // -0.5 >= 0.0 1835 { 1836 IterationConfig iteration; 1837 iteration.p0 = tcu::Vec2(-0.15f, -0.35f); 1838 iteration.p1 = tcu::Vec2( 1.25f, 1.1f); 1839 iteration.borderColor = rr::GenericVec4(tcu::Vec4(-0.5f, 0.0f, 0.0f, 0.0f)); 1840 iteration.description = "Border color < 0, should be clamped"; 1841 iteration.compareMode = GL_GEQUAL; 1842 iteration.compareRef = 0.0f; 1843 m_iterations.push_back(iteration); 1844 } 1845 1846 // inf < 1.25 1847 { 1848 IterationConfig iteration; 1849 iteration.p0 = tcu::Vec2(-0.15f, -0.35f); 1850 iteration.p1 = tcu::Vec2( 1.25f, 1.1f); 1851 iteration.borderColor = rr::GenericVec4(tcu::Vec4(std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f)); 1852 iteration.description = "Border color == inf, should be clamped; ref > 1"; 1853 iteration.compareMode = GL_LESS; 1854 iteration.compareRef = 1.25f; 1855 m_iterations.push_back(iteration); 1856 } 1857 1858 // -inf > -0.5 1859 { 1860 IterationConfig iteration; 1861 iteration.p0 = tcu::Vec2(-0.15f, -0.35f); 1862 iteration.p1 = tcu::Vec2( 1.25f, 1.1f); 1863 iteration.borderColor = rr::GenericVec4(tcu::Vec4(-std::numeric_limits<float>::infinity(), 0.0f, 0.0f, 0.0f)); 1864 iteration.description = "Border color == inf, should be clamped; ref < 0"; 1865 iteration.compareMode = GL_GREATER; 1866 iteration.compareRef = -0.5f; 1867 m_iterations.push_back(iteration); 1868 } 1869 1870 // common parameters 1871 for (int ndx = 0; ndx < (int)m_iterations.size(); ++ndx) 1872 { 1873 IterationConfig& iteration = m_iterations[ndx]; 1874 1875 iteration.lookupScale = tcu::Vec4(1.0); 1876 iteration.lookupBias = tcu::Vec4(0.0); 1877 iteration.minFilter = m_filter; 1878 iteration.magFilter = m_filter; 1879 iteration.sWrapMode = GL_CLAMP_TO_BORDER; 1880 iteration.tWrapMode = GL_CLAMP_TO_BORDER; 1881 } 1882 } 1883 1884 int TextureBorderClampDepthCompareCase::getNumIterations (void) const 1885 { 1886 return (int)m_iterations.size(); 1887 } 1888 1889 TextureBorderClampTest::IterationConfig TextureBorderClampDepthCompareCase::getIteration (int ndx) const 1890 { 1891 return m_iterations[ndx]; 1892 } 1893 1894 class TextureBorderClampUnusedChannelCase : public TextureBorderClampTest 1895 { 1896 public: 1897 TextureBorderClampUnusedChannelCase (Context& context, 1898 const char* name, 1899 const char* description, 1900 deUint32 texFormat, 1901 tcu::Sampler::DepthStencilMode depthStencilMode); 1902 1903 private: 1904 void init (void); 1905 1906 int getNumIterations (void) const; 1907 IterationConfig getIteration (int ndx) const; 1908 1909 std::vector<IterationConfig> m_iterations; 1910 }; 1911 1912 TextureBorderClampUnusedChannelCase::TextureBorderClampUnusedChannelCase (Context& context, 1913 const char* name, 1914 const char* description, 1915 deUint32 texFormat, 1916 tcu::Sampler::DepthStencilMode depthStencilMode) 1917 : TextureBorderClampTest(context, 1918 name, 1919 description, 1920 texFormat, 1921 depthStencilMode, 1922 TextureBorderClampTest::STATE_TEXTURE_PARAM, 1923 8, 1924 8, 1925 SAMPLE_FILTER) 1926 { 1927 } 1928 1929 static rr::GenericVec4 selectComponents (const rr::GenericVec4& trueComponents, const rr::GenericVec4& falseComponents, const tcu::BVec4& m) 1930 { 1931 return rr::GenericVec4(tcu::select(trueComponents.get<deUint32>(), falseComponents.get<deUint32>(), m)); 1932 } 1933 1934 void TextureBorderClampUnusedChannelCase::init (void) 1935 { 1936 TextureBorderClampTest::init(); 1937 1938 // \note TextureBorderClampTest::init() creates texture 1939 const tcu::TextureFormat texFormat = tcu::getEffectiveDepthStencilTextureFormat(getTexture()->getRefTexture().getFormat(), m_sampleMode); 1940 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); 1941 const tcu::BVec4 channelMask = tcu::getTextureFormatChannelMask(texFormat); 1942 const float maxChannelValue = (channelMask[0]) ? (texFormatInfo.valueMax[0]) 1943 : (channelMask[1]) ? (texFormatInfo.valueMax[1]) 1944 : (channelMask[2]) ? (texFormatInfo.valueMax[2]) 1945 : (texFormatInfo.valueMax[3]); 1946 1947 const rr::GenericVec4 effectiveColors = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.6f)); 1948 rr::GenericVec4 nonEffectiveColors; 1949 1950 switch (m_channelClass) 1951 { 1952 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 1953 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 1954 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 1955 nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f)); 1956 break; 1957 1958 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 1959 nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deInt32>()); 1960 break; 1961 1962 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 1963 nonEffectiveColors = rr::GenericVec4(tcu::Vec4(maxChannelValue * 0.8f).cast<deUint32>()); 1964 break; 1965 default: 1966 DE_ASSERT(false); 1967 } 1968 1969 IterationConfig iteration; 1970 iteration.p0 = tcu::Vec2(-0.25f, -0.75f); 1971 iteration.p1 = tcu::Vec2( 2.25f, 1.25f); 1972 iteration.borderColor = selectComponents(effectiveColors, nonEffectiveColors, channelMask); 1973 iteration.lookupScale = texFormatInfo.lookupScale; 1974 iteration.lookupBias = texFormatInfo.lookupBias; 1975 iteration.minFilter = GL_NEAREST; 1976 iteration.magFilter = GL_NEAREST; 1977 iteration.sWrapMode = GL_CLAMP_TO_BORDER; 1978 iteration.tWrapMode = GL_CLAMP_TO_BORDER; 1979 iteration.compareMode = GL_NONE; 1980 iteration.compareRef = 0.0f; 1981 iteration.description = "Setting values to unused border color components"; 1982 1983 m_iterations.push_back(iteration); 1984 } 1985 1986 int TextureBorderClampUnusedChannelCase::getNumIterations (void) const 1987 { 1988 return (int)m_iterations.size(); 1989 } 1990 1991 TextureBorderClampTest::IterationConfig TextureBorderClampUnusedChannelCase::getIteration (int ndx) const 1992 { 1993 return m_iterations[ndx]; 1994 } 1995 1996 class TextureBorderClampPerAxisCase3D : public TestCase 1997 { 1998 public: 1999 TextureBorderClampPerAxisCase3D (Context& context, 2000 const char* name, 2001 const char* description, 2002 deUint32 texFormat, 2003 SizeType size, 2004 deUint32 filter, 2005 deUint32 sWrap, 2006 deUint32 tWrap, 2007 deUint32 rWrap); 2008 2009 private: 2010 void init (void); 2011 void deinit (void); 2012 IterateResult iterate (void); 2013 2014 void renderTo (tcu::Surface& surface, 2015 const glu::TextureTestUtil::ReferenceParams& samplerParams); 2016 2017 void logParams (const glu::TextureTestUtil::ReferenceParams& samplerParams); 2018 2019 void verifyImage (const tcu::Surface& image, 2020 const glu::TextureTestUtil::ReferenceParams& samplerParams); 2021 2022 glu::TextureTestUtil::ReferenceParams getSamplerParams (void) const; 2023 deUint32 getCaseSeed (void) const; 2024 2025 enum 2026 { 2027 VIEWPORT_WIDTH = 128, 2028 VIEWPORT_HEIGHT = 128, 2029 }; 2030 2031 const deUint32 m_texFormat; 2032 const tcu::TextureChannelClass m_channelClass; 2033 const tcu::IVec3 m_size; 2034 const deUint32 m_filter; 2035 const deUint32 m_sWrap; 2036 const deUint32 m_tWrap; 2037 const deUint32 m_rWrap; 2038 2039 de::MovePtr<glu::Texture3D> m_texture; 2040 de::MovePtr<gls::TextureTestUtil::TextureRenderer> m_renderer; 2041 2042 rr::GenericVec4 m_borderColor; 2043 std::vector<float> m_texCoords; 2044 tcu::Vec4 m_lookupScale; 2045 tcu::Vec4 m_lookupBias; 2046 }; 2047 2048 TextureBorderClampPerAxisCase3D::TextureBorderClampPerAxisCase3D (Context& context, 2049 const char* name, 2050 const char* description, 2051 deUint32 texFormat, 2052 SizeType size, 2053 deUint32 filter, 2054 deUint32 sWrap, 2055 deUint32 tWrap, 2056 deUint32 rWrap) 2057 : TestCase (context, name, description) 2058 , m_texFormat (texFormat) 2059 , m_channelClass (getFormatChannelClass(texFormat, tcu::Sampler::MODE_LAST)) 2060 , m_size ((size == SIZE_POT) ? (tcu::IVec3(8, 16, 4)) : (tcu::IVec3(13, 5, 7))) 2061 , m_filter (filter) 2062 , m_sWrap (sWrap) 2063 , m_tWrap (tWrap) 2064 , m_rWrap (rWrap) 2065 { 2066 } 2067 2068 void TextureBorderClampPerAxisCase3D::init (void) 2069 { 2070 const bool supportsES32 = glu::contextSupports(m_context.getRenderContext().getType(), glu::ApiType::es(3, 2)); 2071 const glu::GLSLVersion glslVersion = glu::getContextTypeGLSLVersion(m_context.getRenderContext().getType()); 2072 2073 if (!supportsES32 && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_border_clamp")) 2074 throw tcu::NotSupportedError("Test requires GL_EXT_texture_border_clamp extension"); 2075 2076 if (glu::isCompressedFormat(m_texFormat) && 2077 !supportsES32 && 2078 tcu::isAstcFormat(glu::mapGLCompressedTexFormat(m_texFormat)) && 2079 !m_context.getContextInfo().isExtensionSupported("GL_KHR_texture_compression_astc_ldr")) 2080 { 2081 throw tcu::NotSupportedError("Test requires GL_KHR_texture_compression_astc_ldr extension"); 2082 } 2083 if (m_texFormat == GL_BGRA && !m_context.getContextInfo().isExtensionSupported("GL_EXT_texture_format_BGRA8888")) 2084 throw tcu::NotSupportedError("Test requires GL_EXT_texture_format_BGRA8888 extension"); 2085 if (m_context.getRenderTarget().getWidth() < VIEWPORT_WIDTH || 2086 m_context.getRenderTarget().getHeight() < VIEWPORT_HEIGHT) 2087 { 2088 throw tcu::NotSupportedError("Test requires " + de::toString<int>(VIEWPORT_WIDTH) + "x" + de::toString<int>(VIEWPORT_HEIGHT) + " viewport"); 2089 } 2090 2091 // resources 2092 m_texture = genDummyTexture<glu::Texture3D>(m_context.getRenderContext(), m_context.getContextInfo(), m_texFormat, m_size); 2093 m_renderer = de::MovePtr<gls::TextureTestUtil::TextureRenderer>(new gls::TextureTestUtil::TextureRenderer(m_context.getRenderContext(), m_testCtx.getLog(), glslVersion, glu::PRECISION_HIGHP)); 2094 2095 // texture info 2096 m_testCtx.getLog() << tcu::TestLog::Message 2097 << "Created 3D texture with format " << glu::getTextureFormatName(m_texFormat) 2098 << ", size (" << m_texture->getRefTexture().getWidth() << ", " << m_texture->getRefTexture().getHeight() << ", " << m_texture->getRefTexture().getDepth() << ")\n" 2099 << tcu::TestLog::EndMessage; 2100 2101 // tex coord 2102 { 2103 m_testCtx.getLog() << tcu::TestLog::Message 2104 << "Setting tex coords bottom-left: (-1, -1, -1.5), top-right (2, 2, 2.5)\n" 2105 << tcu::TestLog::EndMessage; 2106 2107 m_texCoords.resize(4*3); 2108 2109 m_texCoords[0] = -1.0f; m_texCoords[ 1] = -1.0f; m_texCoords[ 2] = -1.5f; 2110 m_texCoords[3] = -1.0f; m_texCoords[ 4] = 2.0f; m_texCoords[ 5] = 0.5f; 2111 m_texCoords[6] = 2.0f; m_texCoords[ 7] = -1.0f; m_texCoords[ 8] = 0.5f; 2112 m_texCoords[9] = 2.0f; m_texCoords[10] = 2.0f; m_texCoords[11] = 2.5f; 2113 } 2114 2115 // set render params 2116 { 2117 const tcu::TextureFormat texFormat = m_texture->getRefTexture().getFormat(); 2118 const tcu::TextureFormatInfo texFormatInfo = tcu::getTextureFormatInfo(texFormat); 2119 2120 m_borderColor = mapToFormatColorRepresentable(texFormat, tcu::Vec4(0.2f, 0.6f, 0.9f, 0.4f)); 2121 2122 m_lookupScale = texFormatInfo.lookupScale; 2123 m_lookupBias = texFormatInfo.lookupBias; 2124 } 2125 } 2126 2127 void TextureBorderClampPerAxisCase3D::deinit (void) 2128 { 2129 m_texture.clear(); 2130 m_renderer.clear(); 2131 } 2132 2133 TextureBorderClampPerAxisCase3D::IterateResult TextureBorderClampPerAxisCase3D::iterate (void) 2134 { 2135 tcu::Surface renderedFrame (VIEWPORT_WIDTH, VIEWPORT_HEIGHT); 2136 const glu::TextureTestUtil::ReferenceParams samplerParams = getSamplerParams(); 2137 2138 logParams(samplerParams); 2139 renderTo(renderedFrame, samplerParams); 2140 verifyImage(renderedFrame, samplerParams); 2141 2142 return STOP; 2143 } 2144 2145 void TextureBorderClampPerAxisCase3D::logParams (const glu::TextureTestUtil::ReferenceParams& samplerParams) 2146 { 2147 const std::string borderColorString = (m_channelClass == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) ? (de::toString(m_borderColor.get<deInt32>())) 2148 : (m_channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) ? (de::toString(m_borderColor.get<deUint32>())) 2149 : (de::toString(m_borderColor.get<float>())); 2150 2151 m_testCtx.getLog() << tcu::TestLog::Message 2152 << "Border color is " << borderColorString << "\n" 2153 << "Texture lookup bias: " << samplerParams.colorBias << "\n" 2154 << "Texture lookup scale: " << samplerParams.colorScale << "\n" 2155 << "Filter: " << glu::getTextureFilterName(m_filter) << "\n" 2156 << "Wrap mode: s = " << glu::getRepeatModeStr(m_sWrap) 2157 << ", t = " << glu::getRepeatModeStr(m_tWrap) 2158 << ", r = " << glu::getRepeatModeStr(m_rWrap) << "\n" 2159 << tcu::TestLog::EndMessage; 2160 } 2161 2162 void TextureBorderClampPerAxisCase3D::renderTo (tcu::Surface& surface, 2163 const glu::TextureTestUtil::ReferenceParams& samplerParams) 2164 { 2165 const glw::Functions& gl = m_context.getRenderContext().getFunctions(); 2166 const gls::TextureTestUtil::RandomViewport viewport (m_context.getRenderTarget(), VIEWPORT_WIDTH, VIEWPORT_HEIGHT, getCaseSeed()); 2167 2168 // Bind to unit 0. 2169 gl.activeTexture(GL_TEXTURE0); 2170 gl.bindTexture(GL_TEXTURE_3D, m_texture->getGLTexture()); 2171 2172 // Setup filtering and wrap modes. 2173 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_S, glu::getGLWrapMode(samplerParams.sampler.wrapS)); 2174 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_T, glu::getGLWrapMode(samplerParams.sampler.wrapT)); 2175 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_WRAP_R, glu::getGLWrapMode(samplerParams.sampler.wrapR)); 2176 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MIN_FILTER, glu::getGLFilterMode(samplerParams.sampler.minFilter)); 2177 gl.texParameteri(GL_TEXTURE_3D, GL_TEXTURE_MAG_FILTER, glu::getGLFilterMode(samplerParams.sampler.magFilter)); 2178 2179 switch (m_channelClass) 2180 { 2181 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 2182 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 2183 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 2184 gl.texParameterfv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<float>()); 2185 break; 2186 2187 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 2188 gl.texParameterIiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deInt32>()); 2189 break; 2190 2191 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 2192 gl.texParameterIuiv(GL_TEXTURE_3D, GL_TEXTURE_BORDER_COLOR, m_borderColor.getAccess<deUint32>()); 2193 break; 2194 2195 default: 2196 DE_ASSERT(false); 2197 } 2198 2199 GLU_EXPECT_NO_ERROR(gl.getError(), "Set texturing state"); 2200 2201 gl.viewport(viewport.x, viewport.y, viewport.width, viewport.height); 2202 m_renderer->renderQuad(0, &m_texCoords[0], samplerParams); 2203 glu::readPixels(m_context.getRenderContext(), viewport.x, viewport.y, surface.getAccess()); 2204 } 2205 2206 void TextureBorderClampPerAxisCase3D::verifyImage (const tcu::Surface& renderedFrame, 2207 const glu::TextureTestUtil::ReferenceParams& samplerParams) 2208 { 2209 const tcu::PixelFormat pixelFormat = m_context.getRenderTarget().getPixelFormat(); 2210 const int colorErrorBits = 2; 2211 const tcu::IVec4 colorBits = tcu::max(glu::TextureTestUtil::getBitsVec(pixelFormat) - tcu::IVec4(colorErrorBits), tcu::IVec4(0)); 2212 tcu::Surface reference (renderedFrame.getWidth(), renderedFrame.getHeight()); 2213 tcu::Surface errorMask (renderedFrame.getWidth(), renderedFrame.getHeight()); 2214 tcu::LodPrecision lodPrecision; 2215 tcu::LookupPrecision lookupPrecision; 2216 int numFailedPixels; 2217 2218 lodPrecision.derivateBits = 18; 2219 lodPrecision.lodBits = 5; 2220 2221 lookupPrecision.colorThreshold = tcu::computeFixedPointThreshold(colorBits) / samplerParams.colorScale; 2222 lookupPrecision.coordBits = tcu::IVec3(20,20,0); 2223 lookupPrecision.uvwBits = tcu::IVec3(5,5,0); 2224 lookupPrecision.colorMask = glu::TextureTestUtil::getCompareMask(pixelFormat); 2225 2226 glu::TextureTestUtil::sampleTexture(tcu::SurfaceAccess(reference, pixelFormat), m_texture->getRefTexture(), &m_texCoords[0], samplerParams); 2227 2228 numFailedPixels = glu::TextureTestUtil::computeTextureLookupDiff(renderedFrame.getAccess(), reference.getAccess(), errorMask.getAccess(), m_texture->getRefTexture(), 2229 &m_texCoords[0], samplerParams, lookupPrecision, lodPrecision, m_testCtx.getWatchDog()); 2230 2231 if (numFailedPixels > 0) 2232 m_testCtx.getLog() << tcu::TestLog::Message << "ERROR: Result verification failed, got " << numFailedPixels << " invalid pixels!" << tcu::TestLog::EndMessage; 2233 m_testCtx.getLog() << tcu::TestLog::ImageSet("VerifyResult", "Verification result") 2234 << tcu::TestLog::Image("Rendered", "Rendered image", renderedFrame); 2235 if (numFailedPixels > 0) 2236 { 2237 m_testCtx.getLog() << tcu::TestLog::Image("Reference", "Ideal reference image", reference) 2238 << tcu::TestLog::Image("ErrorMask", "Error mask", errorMask); 2239 } 2240 m_testCtx.getLog() << tcu::TestLog::EndImageSet; 2241 2242 if (numFailedPixels == 0) 2243 m_testCtx.setTestResult(QP_TEST_RESULT_PASS, "Pass"); 2244 else 2245 m_testCtx.setTestResult(QP_TEST_RESULT_FAIL, "Image verification failed"); 2246 } 2247 2248 glu::TextureTestUtil::ReferenceParams TextureBorderClampPerAxisCase3D::getSamplerParams (void) const 2249 { 2250 const tcu::TextureFormat texFormat = m_texture->getRefTexture().getFormat(); 2251 glu::TextureTestUtil::ReferenceParams refParams (glu::TextureTestUtil::TEXTURETYPE_3D); 2252 2253 refParams.sampler = glu::mapGLSampler(m_sWrap, m_tWrap, m_rWrap, m_filter, m_filter); 2254 refParams.sampler.borderColor = m_borderColor; 2255 refParams.lodMode = glu::TextureTestUtil::LODMODE_EXACT; 2256 refParams.samplerType = glu::TextureTestUtil::getSamplerType(texFormat); 2257 refParams.colorScale = m_lookupScale; 2258 refParams.colorBias = m_lookupBias; 2259 2260 return refParams; 2261 } 2262 2263 deUint32 TextureBorderClampPerAxisCase3D::getCaseSeed (void) const 2264 { 2265 tcu::SeedBuilder builder; 2266 builder << std::string(getName()) 2267 << m_texFormat 2268 << m_filter 2269 << m_sWrap 2270 << m_tWrap 2271 << m_rWrap 2272 << m_texture->getRefTexture().getWidth() 2273 << m_texture->getRefTexture().getHeight() 2274 << m_texture->getRefTexture().getDepth(); 2275 return builder.get(); 2276 } 2277 2278 } // anonymous 2279 2280 TextureBorderClampTests::TextureBorderClampTests (Context& context) 2281 : TestCaseGroup(context, "border_clamp", "EXT_texture_border_clamp tests") 2282 { 2283 } 2284 2285 TextureBorderClampTests::~TextureBorderClampTests (void) 2286 { 2287 } 2288 2289 void TextureBorderClampTests::init (void) 2290 { 2291 static const struct 2292 { 2293 const char* name; 2294 deUint32 filter; 2295 TextureBorderClampTest::SamplingFunction sampling; 2296 } s_filters[] = 2297 { 2298 { "nearest", GL_NEAREST, TextureBorderClampTest::SAMPLE_FILTER }, 2299 { "linear", GL_LINEAR, TextureBorderClampTest::SAMPLE_FILTER }, 2300 { "gather", GL_NEAREST, TextureBorderClampTest::SAMPLE_GATHER }, 2301 }; 2302 2303 // .formats 2304 { 2305 static const struct 2306 { 2307 const char* name; 2308 deUint32 format; 2309 tcu::Sampler::DepthStencilMode mode; 2310 } formats[] = 2311 { 2312 { "luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST }, 2313 { "alpha", GL_ALPHA, tcu::Sampler::MODE_LAST }, 2314 { "luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST }, 2315 { "bgra", GL_BGRA, tcu::Sampler::MODE_LAST }, 2316 { "r8", GL_R8, tcu::Sampler::MODE_LAST }, 2317 { "r8_snorm", GL_R8_SNORM, tcu::Sampler::MODE_LAST }, 2318 { "rg8", GL_RG8, tcu::Sampler::MODE_LAST }, 2319 { "rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST }, 2320 { "rgb8", GL_RGB8, tcu::Sampler::MODE_LAST }, 2321 { "rgb8_snorm", GL_RGB8_SNORM, tcu::Sampler::MODE_LAST }, 2322 { "rgb565", GL_RGB565, tcu::Sampler::MODE_LAST }, 2323 { "rgba4", GL_RGBA4, tcu::Sampler::MODE_LAST }, 2324 { "rgb5_a1", GL_RGB5_A1, tcu::Sampler::MODE_LAST }, 2325 { "rgba8", GL_RGBA8, tcu::Sampler::MODE_LAST }, 2326 { "rgba8_snorm", GL_RGBA8_SNORM, tcu::Sampler::MODE_LAST }, 2327 { "rgb10_a2", GL_RGB10_A2, tcu::Sampler::MODE_LAST }, 2328 { "rgb10_a2ui", GL_RGB10_A2UI, tcu::Sampler::MODE_LAST }, 2329 { "srgb8", GL_SRGB8, tcu::Sampler::MODE_LAST }, 2330 { "srgb8_alpha8", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST }, 2331 { "r16f", GL_R16F, tcu::Sampler::MODE_LAST }, 2332 { "rg16f", GL_RG16F, tcu::Sampler::MODE_LAST }, 2333 { "rgb16f", GL_RGB16F, tcu::Sampler::MODE_LAST }, 2334 { "rgba16f", GL_RGBA16F, tcu::Sampler::MODE_LAST }, 2335 { "r32f", GL_R32F, tcu::Sampler::MODE_LAST }, 2336 { "rg32f", GL_RG32F, tcu::Sampler::MODE_LAST }, 2337 { "rgb32f", GL_RGB32F, tcu::Sampler::MODE_LAST }, 2338 { "rgba32f", GL_RGBA32F, tcu::Sampler::MODE_LAST }, 2339 { "r11f_g11f_b10f", GL_R11F_G11F_B10F, tcu::Sampler::MODE_LAST }, 2340 { "rgb9_e5", GL_RGB9_E5, tcu::Sampler::MODE_LAST }, 2341 { "r8i", GL_R8I, tcu::Sampler::MODE_LAST }, 2342 { "r8ui", GL_R8UI, tcu::Sampler::MODE_LAST }, 2343 { "r16i", GL_R16I, tcu::Sampler::MODE_LAST }, 2344 { "r16ui", GL_R16UI, tcu::Sampler::MODE_LAST }, 2345 { "r32i", GL_R32I, tcu::Sampler::MODE_LAST }, 2346 { "r32ui", GL_R32UI, tcu::Sampler::MODE_LAST }, 2347 { "rg8i", GL_RG8I, tcu::Sampler::MODE_LAST }, 2348 { "rg8ui", GL_RG8UI, tcu::Sampler::MODE_LAST }, 2349 { "rg16i", GL_RG16I, tcu::Sampler::MODE_LAST }, 2350 { "rg16ui", GL_RG16UI, tcu::Sampler::MODE_LAST }, 2351 { "rg32i", GL_RG32I, tcu::Sampler::MODE_LAST }, 2352 { "rg32ui", GL_RG32UI, tcu::Sampler::MODE_LAST }, 2353 { "rgb8i", GL_RGB8I, tcu::Sampler::MODE_LAST }, 2354 { "rgb8ui", GL_RGB8UI, tcu::Sampler::MODE_LAST }, 2355 { "rgb16i", GL_RGB16I, tcu::Sampler::MODE_LAST }, 2356 { "rgb16ui", GL_RGB16UI, tcu::Sampler::MODE_LAST }, 2357 { "rgb32i", GL_RGB32I, tcu::Sampler::MODE_LAST }, 2358 { "rgb32ui", GL_RGB32UI, tcu::Sampler::MODE_LAST }, 2359 { "rgba8i", GL_RGBA8I, tcu::Sampler::MODE_LAST }, 2360 { "rgba8ui", GL_RGBA8UI, tcu::Sampler::MODE_LAST }, 2361 { "rgba16i", GL_RGBA16I, tcu::Sampler::MODE_LAST }, 2362 { "rgba16ui", GL_RGBA16UI, tcu::Sampler::MODE_LAST }, 2363 { "rgba32i", GL_RGBA32I, tcu::Sampler::MODE_LAST }, 2364 { "rgba32ui", GL_RGBA32UI, tcu::Sampler::MODE_LAST }, 2365 { "depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH }, 2366 { "depth_component24", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH }, 2367 { "depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH }, 2368 { "stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL }, 2369 { "depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2370 { "depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2371 { "depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2372 { "depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2373 { "compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST }, 2374 { "compressed_signed_r11_eac", GL_COMPRESSED_SIGNED_R11_EAC, tcu::Sampler::MODE_LAST }, 2375 { "compressed_rg11_eac", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST }, 2376 { "compressed_signed_rg11_eac", GL_COMPRESSED_SIGNED_RG11_EAC, tcu::Sampler::MODE_LAST }, 2377 { "compressed_rgb8_etc2", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST }, 2378 { "compressed_srgb8_etc2", GL_COMPRESSED_SRGB8_ETC2, tcu::Sampler::MODE_LAST }, 2379 { "compressed_rgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_RGB8_PUNCHTHROUGH_ALPHA1_ETC2, tcu::Sampler::MODE_LAST }, 2380 { "compressed_srgb8_punchthrough_alpha1_etc2", GL_COMPRESSED_SRGB8_PUNCHTHROUGH_ALPHA1_ETC2, tcu::Sampler::MODE_LAST }, 2381 { "compressed_rgba8_etc2_eac", GL_COMPRESSED_RGBA8_ETC2_EAC, tcu::Sampler::MODE_LAST }, 2382 { "compressed_srgb8_alpha8_etc2_eac", GL_COMPRESSED_SRGB8_ALPHA8_ETC2_EAC, tcu::Sampler::MODE_LAST }, 2383 }; 2384 2385 tcu::TestCaseGroup* const formatsGroup = new tcu::TestCaseGroup(m_testCtx, "formats", "Format tests"); 2386 addChild(formatsGroup); 2387 2388 // .format 2389 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2390 { 2391 const deUint32 format = formats[formatNdx].format; 2392 const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; 2393 const bool isCompressed = glu::isCompressedFormat(format); 2394 const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); 2395 tcu::TestCaseGroup* const formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); 2396 2397 formatsGroup->addChild(formatGroup); 2398 2399 // .nearest 2400 // .linear 2401 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) 2402 { 2403 // [not-compressed] 2404 // .size_pot 2405 // .size_npot 2406 // [compressed] 2407 // .size_tile_multiple (also pot) 2408 // .size_not_tile_multiple (also npot) 2409 for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) 2410 { 2411 const bool isNpotCase = (sizeNdx == 1); 2412 const char* const sizePotName = (!isCompressed) ? ("size_pot") : ("size_tile_multiple"); 2413 const char* const sizeNpotName = (!isCompressed) ? ("size_npot") : ("size_not_tile_multiple"); 2414 const char* const sizeName = (isNpotCase) ? (sizeNpotName) : (sizePotName); 2415 const SizeType sizeType = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); 2416 const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + sizeName; 2417 const deUint32 filter = s_filters[filterNdx].filter; 2418 2419 if (coreFilterable || !filterRequiresFilterability(filter)) 2420 formatGroup->addChild(new TextureBorderClampFormatCase(m_context, 2421 caseName.c_str(), 2422 "", 2423 format, 2424 sampleMode, 2425 TextureBorderClampFormatCase::STATE_TEXTURE_PARAM, 2426 sizeType, 2427 filter, 2428 s_filters[filterNdx].sampling)); 2429 } 2430 } 2431 } 2432 } 2433 2434 // .range_clamp 2435 { 2436 static const struct 2437 { 2438 const char* name; 2439 deUint32 format; 2440 tcu::Sampler::DepthStencilMode mode; 2441 } formats[] = 2442 { 2443 { "unorm_color", GL_R8, tcu::Sampler::MODE_LAST }, 2444 { "snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST }, 2445 { "float_color", GL_RG32F, tcu::Sampler::MODE_LAST }, 2446 { "int_color", GL_R8I, tcu::Sampler::MODE_LAST }, 2447 { "uint_color", GL_R16UI, tcu::Sampler::MODE_LAST }, 2448 { "srgb_color", GL_SRGB8_ALPHA8, tcu::Sampler::MODE_LAST }, 2449 { "unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH }, 2450 { "float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH }, 2451 { "uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL }, 2452 { "float_depth_uint_stencil_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2453 { "float_depth_uint_stencil_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2454 { "unorm_depth_uint_stencil_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2455 { "unorm_depth_uint_stencil_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2456 { "compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST }, 2457 }; 2458 2459 tcu::TestCaseGroup* const rangeClampGroup = new tcu::TestCaseGroup(m_testCtx, "range_clamp", "Range clamp tests"); 2460 addChild(rangeClampGroup); 2461 2462 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2463 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) 2464 { 2465 const deUint32 format = formats[formatNdx].format; 2466 const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; 2467 const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + formats[formatNdx].name; 2468 const deUint32 filter = s_filters[filterNdx].filter; 2469 const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); 2470 2471 if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER) 2472 continue; 2473 2474 if (coreFilterable || !filterRequiresFilterability(filter)) 2475 rangeClampGroup->addChild(new TextureBorderClampRangeClampCase(m_context, caseName.c_str(), "", format, sampleMode, filter)); 2476 } 2477 } 2478 2479 // .sampler 2480 { 2481 static const struct 2482 { 2483 const char* name; 2484 deUint32 format; 2485 tcu::Sampler::DepthStencilMode mode; 2486 } formats[] = 2487 { 2488 { "unorm_color", GL_R8, tcu::Sampler::MODE_LAST }, 2489 { "snorm_color", GL_R8_SNORM, tcu::Sampler::MODE_LAST }, 2490 { "float_color", GL_RG32F, tcu::Sampler::MODE_LAST }, 2491 { "int_color", GL_R8I, tcu::Sampler::MODE_LAST }, 2492 { "uint_color", GL_R16UI, tcu::Sampler::MODE_LAST }, 2493 { "unorm_depth", GL_DEPTH_COMPONENT24, tcu::Sampler::MODE_DEPTH }, 2494 { "float_depth", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH }, 2495 { "uint_stencil", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL }, 2496 { "compressed_color", GL_COMPRESSED_RG11_EAC, tcu::Sampler::MODE_LAST }, 2497 }; 2498 2499 tcu::TestCaseGroup* const samplerGroup = new tcu::TestCaseGroup(m_testCtx, "sampler", "Sampler param tests"); 2500 addChild(samplerGroup); 2501 2502 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2503 { 2504 const deUint32 format = formats[formatNdx].format; 2505 const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; 2506 const char* caseName = formats[formatNdx].name; 2507 2508 samplerGroup->addChild(new TextureBorderClampFormatCase(m_context, 2509 caseName, 2510 "", 2511 format, 2512 sampleMode, 2513 TextureBorderClampFormatCase::STATE_SAMPLER_PARAM, 2514 SIZE_POT, 2515 GL_NEAREST, 2516 TextureBorderClampFormatCase::SAMPLE_FILTER)); 2517 } 2518 } 2519 2520 // .per_axis_wrap_mode 2521 { 2522 static const struct 2523 { 2524 const char* name; 2525 bool is3D; 2526 } targets[] = 2527 { 2528 { "texture_2d", false }, 2529 { "texture_3d", true }, 2530 }; 2531 static const struct 2532 { 2533 const char* name; 2534 deUint32 format; 2535 tcu::Sampler::DepthStencilMode mode; 2536 bool supports3D; 2537 } formats[] = 2538 { 2539 { "unorm_color", GL_RG8, tcu::Sampler::MODE_LAST, true }, 2540 { "snorm_color", GL_RG8_SNORM, tcu::Sampler::MODE_LAST, true }, 2541 { "float_color", GL_R32F, tcu::Sampler::MODE_LAST, true }, 2542 { "int_color", GL_RG16I, tcu::Sampler::MODE_LAST, true }, 2543 { "uint_color", GL_R8UI, tcu::Sampler::MODE_LAST, true }, 2544 { "unorm_depth", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH, false }, 2545 { "float_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH, false }, 2546 { "uint_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL, false }, 2547 { "compressed_color", GL_COMPRESSED_RGB8_ETC2, tcu::Sampler::MODE_LAST, false }, 2548 }; 2549 static const struct 2550 { 2551 const char* name; 2552 deUint32 sWrap; 2553 deUint32 tWrap; 2554 deUint32 rWrap; 2555 bool is3D; 2556 } wrapConfigs[] = 2557 { 2558 // 2d configs 2559 { "s_clamp_to_edge_t_clamp_to_border", GL_CLAMP_TO_EDGE, GL_CLAMP_TO_BORDER, GL_NONE, false }, 2560 { "s_repeat_t_clamp_to_border", GL_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false }, 2561 { "s_mirrored_repeat_t_clamp_to_border", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_NONE, false }, 2562 2563 // 3d configs 2564 { "s_clamp_to_border_t_clamp_to_border_r_clamp_to_border", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, true }, 2565 { "s_clamp_to_border_t_clamp_to_border_r_repeat", GL_CLAMP_TO_BORDER, GL_CLAMP_TO_BORDER, GL_REPEAT, true }, 2566 { "s_mirrored_repeat_t_clamp_to_border_r_repeat", GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, GL_REPEAT, true }, 2567 { "s_repeat_t_mirrored_repeat_r_clamp_to_border", GL_REPEAT, GL_MIRRORED_REPEAT, GL_CLAMP_TO_BORDER, true }, 2568 }; 2569 2570 tcu::TestCaseGroup* const perAxisGroup = new tcu::TestCaseGroup(m_testCtx, "per_axis_wrap_mode", "Per-axis wrapping modes"); 2571 addChild(perAxisGroup); 2572 2573 // .texture_nd 2574 for (int targetNdx = 0; targetNdx < DE_LENGTH_OF_ARRAY(targets); ++targetNdx) 2575 { 2576 tcu::TestCaseGroup* const targetGroup = new tcu::TestCaseGroup(m_testCtx, targets[targetNdx].name, "Texture target test"); 2577 perAxisGroup->addChild(targetGroup); 2578 2579 // .format 2580 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2581 { 2582 if (targets[targetNdx].is3D && !formats[formatNdx].supports3D) 2583 continue; 2584 else 2585 { 2586 const deUint32 format = formats[formatNdx].format; 2587 const tcu::Sampler::DepthStencilMode sampleMode = formats[formatNdx].mode; 2588 const bool coreFilterable = isCoreFilterableFormat(format, sampleMode); 2589 tcu::TestCaseGroup* const formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); 2590 targetGroup->addChild(formatGroup); 2591 2592 // .linear 2593 // .nearest 2594 // .gather 2595 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) 2596 { 2597 const deUint32 filter = s_filters[filterNdx].filter; 2598 2599 if (!coreFilterable && filterRequiresFilterability(filter)) 2600 { 2601 // skip linear on pure integers 2602 continue; 2603 } 2604 else if (s_filters[filterNdx].sampling == TextureBorderClampTest::SAMPLE_GATHER && targets[targetNdx].is3D) 2605 { 2606 // skip gather on 3d 2607 continue; 2608 } 2609 else 2610 { 2611 tcu::TestCaseGroup* const filteringGroup = new tcu::TestCaseGroup(m_testCtx, s_filters[filterNdx].name, "Tests with specific filter"); 2612 formatGroup->addChild(filteringGroup); 2613 2614 // .s_XXX_t_XXX(_r_XXX) 2615 for (int wrapNdx = 0; wrapNdx < DE_LENGTH_OF_ARRAY(wrapConfigs); ++wrapNdx) 2616 { 2617 if (wrapConfigs[wrapNdx].is3D != targets[targetNdx].is3D) 2618 continue; 2619 else 2620 { 2621 for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) 2622 { 2623 const char* const wrapName = wrapConfigs[wrapNdx].name; 2624 const bool isNpotCase = (sizeNdx == 1); 2625 const char* const sizeNameExtension = (isNpotCase) ? ("_npot") : ("_pot"); 2626 const SizeType size = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); 2627 2628 if (!targets[targetNdx].is3D) 2629 filteringGroup->addChild(new TextureBorderClampPerAxisCase2D(m_context, 2630 (std::string() + wrapName + sizeNameExtension).c_str(), 2631 "", 2632 format, 2633 sampleMode, 2634 size, 2635 filter, 2636 wrapConfigs[wrapNdx].sWrap, 2637 wrapConfigs[wrapNdx].tWrap, 2638 s_filters[filterNdx].sampling)); 2639 else 2640 { 2641 DE_ASSERT(sampleMode == tcu::Sampler::MODE_LAST); 2642 filteringGroup->addChild(new TextureBorderClampPerAxisCase3D(m_context, 2643 (std::string() + wrapName + sizeNameExtension).c_str(), 2644 "", 2645 format, 2646 size, 2647 filter, 2648 wrapConfigs[wrapNdx].sWrap, 2649 wrapConfigs[wrapNdx].tWrap, 2650 wrapConfigs[wrapNdx].rWrap)); 2651 } 2652 } 2653 } 2654 } 2655 } 2656 } 2657 } 2658 } 2659 } 2660 } 2661 2662 // .depth_compare_mode 2663 { 2664 static const struct 2665 { 2666 const char* name; 2667 deUint32 format; 2668 } formats[] = 2669 { 2670 { "depth_component16", GL_DEPTH_COMPONENT16 }, 2671 { "depth_component24", GL_DEPTH_COMPONENT24 }, 2672 { "depth24_stencil8", GL_DEPTH24_STENCIL8 }, 2673 { "depth32f_stencil8", GL_DEPTH32F_STENCIL8 }, 2674 }; 2675 2676 tcu::TestCaseGroup* const compareGroup = new tcu::TestCaseGroup(m_testCtx, "depth_compare_mode", "Tests depth compare mode"); 2677 addChild(compareGroup); 2678 2679 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2680 { 2681 const deUint32 format = formats[formatNdx].format; 2682 tcu::TestCaseGroup* const formatGroup = new tcu::TestCaseGroup(m_testCtx, formats[formatNdx].name, "Format test"); 2683 2684 compareGroup->addChild(formatGroup); 2685 2686 // (format).(linear|nearest|gather)_(pot|npot) 2687 for (int filterNdx = 0; filterNdx < DE_LENGTH_OF_ARRAY(s_filters); ++filterNdx) 2688 for (int sizeNdx = 0; sizeNdx < 2; ++sizeNdx) 2689 { 2690 const bool isNpotCase = (sizeNdx == 1); 2691 const char* const sizeName = (isNpotCase) ? ("size_npot") : ("size_pot"); 2692 const SizeType sizeType = (isNpotCase) ? (SIZE_NPOT) : (SIZE_POT); 2693 const std::string caseName = std::string() + s_filters[filterNdx].name + "_" + sizeName; 2694 const deUint32 filter = s_filters[filterNdx].filter; 2695 2696 formatGroup->addChild(new TextureBorderClampDepthCompareCase(m_context, 2697 caseName.c_str(), 2698 "", 2699 format, 2700 sizeType, 2701 filter, 2702 s_filters[filterNdx].sampling)); 2703 } 2704 } 2705 } 2706 2707 // unused channels (A in rgb, G in stencil etc.) 2708 { 2709 static const struct 2710 { 2711 const char* name; 2712 deUint32 format; 2713 tcu::Sampler::DepthStencilMode mode; 2714 } formats[] = 2715 { 2716 { "r8", GL_R8, tcu::Sampler::MODE_LAST }, 2717 { "rg8_snorm", GL_RG8_SNORM, tcu::Sampler::MODE_LAST }, 2718 { "rgb8", GL_RGB8, tcu::Sampler::MODE_LAST }, 2719 { "rg32f", GL_RG32F, tcu::Sampler::MODE_LAST }, 2720 { "r16i", GL_RG16I, tcu::Sampler::MODE_LAST }, 2721 { "luminance", GL_LUMINANCE, tcu::Sampler::MODE_LAST }, 2722 { "alpha", GL_ALPHA, tcu::Sampler::MODE_LAST }, 2723 { "luminance_alpha", GL_LUMINANCE_ALPHA, tcu::Sampler::MODE_LAST }, 2724 { "depth_component16", GL_DEPTH_COMPONENT16, tcu::Sampler::MODE_DEPTH }, 2725 { "depth_component32f", GL_DEPTH_COMPONENT32F, tcu::Sampler::MODE_DEPTH }, 2726 { "stencil_index8", GL_STENCIL_INDEX8, tcu::Sampler::MODE_STENCIL }, 2727 { "depth32f_stencil8_sample_depth", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2728 { "depth32f_stencil8_sample_stencil", GL_DEPTH32F_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2729 { "depth24_stencil8_sample_depth", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_DEPTH }, 2730 { "depth24_stencil8_sample_stencil", GL_DEPTH24_STENCIL8, tcu::Sampler::MODE_STENCIL }, 2731 { "compressed_r11_eac", GL_COMPRESSED_R11_EAC, tcu::Sampler::MODE_LAST }, 2732 }; 2733 2734 tcu::TestCaseGroup* const unusedGroup = new tcu::TestCaseGroup(m_testCtx, "unused_channels", "Tests channels that are not present in the internal format"); 2735 addChild(unusedGroup); 2736 2737 for (int formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); ++formatNdx) 2738 { 2739 unusedGroup->addChild(new TextureBorderClampUnusedChannelCase(m_context, 2740 formats[formatNdx].name, 2741 "", 2742 formats[formatNdx].format, 2743 formats[formatNdx].mode)); 2744 } 2745 } 2746 } 2747 2748 } // Functional 2749 } // gles31 2750 } // deqp 2751