1 /*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * 8 * Licensed under the Apache License, Version 2.0 (the "License"); 9 * you may not use this file except in compliance with the License. 10 * You may obtain a copy of the License at 11 * 12 * http://www.apache.org/licenses/LICENSE-2.0 13 * 14 * Unless required by applicable law or agreed to in writing, software 15 * distributed under the License is distributed on an "AS IS" BASIS, 16 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 17 * See the License for the specific language governing permissions and 18 * limitations under the License. 19 * 20 *//*! 21 * \file 22 * \brief Sampler Tests 23 *//*--------------------------------------------------------------------*/ 24 25 #include "vktPipelineSamplerTests.hpp" 26 #include "vktPipelineImageSamplingInstance.hpp" 27 #include "vktPipelineImageUtil.hpp" 28 #include "vktPipelineVertexUtil.hpp" 29 #include "vktTestCase.hpp" 30 #include "vkImageUtil.hpp" 31 #include "vkPrograms.hpp" 32 #include "tcuPlatform.hpp" 33 #include "tcuTextureUtil.hpp" 34 #include "deStringUtil.hpp" 35 #include "deMemory.h" 36 37 #include <iomanip> 38 #include <sstream> 39 #include <vector> 40 41 namespace vkt 42 { 43 namespace pipeline 44 { 45 46 using namespace vk; 47 using de::MovePtr; 48 49 namespace 50 { 51 52 class SamplerTest : public vkt::TestCase 53 { 54 public: 55 SamplerTest (tcu::TestContext& testContext, 56 const char* name, 57 const char* description, 58 VkImageViewType imageViewType, 59 VkFormat imageFormat, 60 int imageSize, 61 float samplerLod); 62 virtual ~SamplerTest (void) {} 63 64 virtual void initPrograms (SourceCollections& sourceCollections) const; 65 virtual TestInstance* createInstance (Context& context) const; 66 virtual tcu::UVec2 getRenderSize (VkImageViewType viewType) const; 67 virtual std::vector<Vertex4Tex4> createVertices (void) const; 68 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const; 69 70 static std::string getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type); 71 static tcu::IVec3 getImageSize (VkImageViewType viewType, int size); 72 static int getArraySize (VkImageViewType viewType); 73 74 protected: 75 VkImageViewType m_imageViewType; 76 VkFormat m_imageFormat; 77 int m_imageSize; 78 VkImageViewCreateInfo m_imageViewParams; 79 VkSamplerCreateInfo m_samplerParams; 80 float m_samplerLod; 81 }; 82 83 class SamplerMagFilterTest : public SamplerTest 84 { 85 public: 86 SamplerMagFilterTest (tcu::TestContext& testContext, 87 const char* name, 88 const char* description, 89 VkImageViewType imageViewType, 90 VkFormat imageFormat, 91 VkFilter magFilter); 92 virtual ~SamplerMagFilterTest (void) {} 93 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const; 94 95 private: 96 VkFilter m_magFilter; 97 }; 98 99 class SamplerMinFilterTest : public SamplerTest 100 { 101 public: 102 SamplerMinFilterTest (tcu::TestContext& testContext, 103 const char* name, 104 const char* description, 105 VkImageViewType imageViewType, 106 VkFormat imageFormat, 107 VkFilter minFilter); 108 virtual ~SamplerMinFilterTest (void) {} 109 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const; 110 111 private: 112 VkFilter m_minFilter; 113 }; 114 115 class SamplerLodTest : public SamplerTest 116 { 117 public: 118 SamplerLodTest (tcu::TestContext& testContext, 119 const char* name, 120 const char* description, 121 VkImageViewType imageViewType, 122 VkFormat imageFormat, 123 VkSamplerMipmapMode mipmapMode, 124 float minLod, 125 float maxLod, 126 float mipLodBias, 127 float samplerLod); 128 virtual ~SamplerLodTest (void) {} 129 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const; 130 131 private: 132 VkSamplerMipmapMode m_mipmapMode; 133 float m_minLod; 134 float m_maxLod; 135 float m_mipLodBias; 136 }; 137 138 class SamplerAddressModesTest : public SamplerTest 139 { 140 public: 141 SamplerAddressModesTest (tcu::TestContext& testContext, 142 const char* name, 143 const char* description, 144 VkImageViewType imageViewType, 145 VkFormat imageFormat, 146 VkSamplerAddressMode addressU, 147 VkSamplerAddressMode addressV, 148 VkSamplerAddressMode addressW, 149 VkBorderColor borderColor); 150 virtual ~SamplerAddressModesTest (void) {} 151 virtual tcu::UVec2 getRenderSize (VkImageViewType viewType) const; 152 virtual std::vector<Vertex4Tex4> createVertices (void) const; 153 virtual VkSamplerCreateInfo getSamplerCreateInfo (void) const; 154 155 private: 156 VkSamplerAddressMode m_addressU; 157 VkSamplerAddressMode m_addressV; 158 VkSamplerAddressMode m_addressW; 159 VkBorderColor m_borderColor; 160 }; 161 162 163 // SamplerTest 164 165 SamplerTest::SamplerTest (tcu::TestContext& testContext, 166 const char* name, 167 const char* description, 168 VkImageViewType imageViewType, 169 VkFormat imageFormat, 170 int imageSize, 171 float samplerLod) 172 : vkt::TestCase (testContext, name, description) 173 , m_imageViewType (imageViewType) 174 , m_imageFormat (imageFormat) 175 , m_imageSize (imageSize) 176 , m_samplerLod (samplerLod) 177 { 178 } 179 180 void SamplerTest::initPrograms (SourceCollections& sourceCollections) const 181 { 182 std::ostringstream vertexSrc; 183 std::ostringstream fragmentSrc; 184 const char* texCoordSwizzle = DE_NULL; 185 tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat)) 186 : mapVkFormat(m_imageFormat); 187 188 // \note We don't want to perform normalization on any compressed formats. 189 // In case of non-sRGB LDR ASTC it would lead to lack of coverage 190 // as uncompressed format for that is f16 but values will be in range 191 // 0..1 already. 192 const tcu::TextureFormatInfo formatInfo = (!isCompressedFormat(m_imageFormat) ? tcu::getTextureFormatInfo(format) 193 : tcu::getTextureFormatInfo(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::UNORM_INT8))); 194 195 switch (m_imageViewType) 196 { 197 case VK_IMAGE_VIEW_TYPE_1D: 198 texCoordSwizzle = "x"; 199 break; 200 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 201 case VK_IMAGE_VIEW_TYPE_2D: 202 texCoordSwizzle = "xy"; 203 break; 204 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 205 case VK_IMAGE_VIEW_TYPE_3D: 206 case VK_IMAGE_VIEW_TYPE_CUBE: 207 texCoordSwizzle = "xyz"; 208 break; 209 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 210 texCoordSwizzle = "xyzw"; 211 break; 212 default: 213 DE_ASSERT(false); 214 break; 215 } 216 217 vertexSrc << "#version 440\n" 218 << "layout(location = 0) in vec4 position;\n" 219 << "layout(location = 1) in vec4 texCoords;\n" 220 << "layout(location = 0) out highp vec4 vtxTexCoords;\n" 221 << "out gl_PerVertex {\n" 222 << " vec4 gl_Position;\n" 223 << "};\n" 224 << "void main (void)\n" 225 << "{\n" 226 << " gl_Position = position;\n" 227 << " vtxTexCoords = texCoords;\n" 228 << "}\n"; 229 230 fragmentSrc << "#version 440\n" 231 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n" 232 << "layout(location = 0) in highp vec4 vtxTexCoords;\n" 233 << "layout(location = 0) out highp vec4 fragColor;\n" 234 << "void main (void)\n" 235 << "{\n" 236 << " fragColor = "; 237 238 if (m_samplerLod > 0.0f) 239 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")"; 240 else 241 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed; 242 243 fragmentSrc << " * vec4" << std::scientific << formatInfo.lookupScale << " + vec4" << formatInfo.lookupBias << ";\n" 244 << "}\n"; 245 246 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str()); 247 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str()); 248 } 249 250 TestInstance* SamplerTest::createInstance (Context& context) const 251 { 252 const tcu::UVec2 renderSize = getRenderSize(m_imageViewType); 253 const std::vector<Vertex4Tex4> vertices = createVertices(); 254 const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo(); 255 const VkComponentMapping componentMapping = getFormatComponentMapping(m_imageFormat); 256 const VkImageSubresourceRange subresourceRange = 257 { 258 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 259 0u, // deUint32 baseMipLevel; 260 (deUint32)deLog2Floor32(m_imageSize) + 1, // deUint32 mipLevels; 261 0u, // deUint32 baseArrayLayer; 262 (deUint32)SamplerTest::getArraySize(m_imageViewType) // deUint32 arraySize; 263 }; 264 265 266 267 return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat, 268 getImageSize(m_imageViewType, m_imageSize), 269 getArraySize(m_imageViewType), 270 componentMapping, subresourceRange, 271 samplerParams, m_samplerLod,vertices); 272 } 273 274 tcu::UVec2 SamplerTest::getRenderSize (VkImageViewType viewType) const 275 { 276 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D) 277 { 278 return tcu::UVec2(16u, 16u); 279 } 280 else 281 { 282 return tcu::UVec2(16u * 3u, 16u * 2u); 283 } 284 } 285 286 std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const 287 { 288 std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType); 289 // Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries. 290 // TODO: Would be nice to base this on number of texels and subtexel precision. But this 291 // seems to work. 292 for (unsigned int i = 0; i < vertices.size(); ++i) { 293 vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f); 294 } 295 return vertices; 296 } 297 298 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const 299 { 300 const VkSamplerCreateInfo defaultSamplerParams = 301 { 302 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 303 DE_NULL, // const void* pNext; 304 0u, // VkSamplerCreateFlags flags; 305 VK_FILTER_NEAREST, // VkFilter magFilter; 306 VK_FILTER_NEAREST, // VkFilter minFilter; 307 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 308 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 309 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 310 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 311 0.0f, // float mipLodBias; 312 VK_FALSE, // VkBool32 anisotropyEnable; 313 1.0f, // float maxAnisotropy; 314 false, // VkBool32 compareEnable; 315 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 316 0.0f, // float minLod; 317 0.25f, // float maxLod; 318 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor; 319 false // VkBool32 unnormalizedCoordinates; 320 }; 321 322 return defaultSamplerParams; 323 } 324 325 std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type) 326 { 327 std::ostringstream samplerType; 328 329 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 330 samplerType << "u"; 331 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 332 samplerType << "i"; 333 334 switch (type) 335 { 336 case VK_IMAGE_VIEW_TYPE_1D: 337 samplerType << "sampler1D"; 338 break; 339 340 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 341 samplerType << "sampler1DArray"; 342 break; 343 344 case VK_IMAGE_VIEW_TYPE_2D: 345 samplerType << "sampler2D"; 346 break; 347 348 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 349 samplerType << "sampler2DArray"; 350 break; 351 352 case VK_IMAGE_VIEW_TYPE_3D: 353 samplerType << "sampler3D"; 354 break; 355 356 case VK_IMAGE_VIEW_TYPE_CUBE: 357 samplerType << "samplerCube"; 358 break; 359 360 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 361 samplerType << "samplerCubeArray"; 362 break; 363 364 default: 365 DE_FATAL("Unknown image view type"); 366 break; 367 } 368 369 return samplerType.str(); 370 } 371 372 tcu::IVec3 SamplerTest::getImageSize (VkImageViewType viewType, int size) 373 { 374 switch (viewType) 375 { 376 case VK_IMAGE_VIEW_TYPE_1D: 377 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 378 return tcu::IVec3(size, 1, 1); 379 380 case VK_IMAGE_VIEW_TYPE_3D: 381 return tcu::IVec3(size, size, 4); 382 383 default: 384 break; 385 } 386 387 return tcu::IVec3(size, size, 1); 388 } 389 390 int SamplerTest::getArraySize (VkImageViewType viewType) 391 { 392 switch (viewType) 393 { 394 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 395 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 396 case VK_IMAGE_VIEW_TYPE_CUBE: 397 return 6; 398 399 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 400 return 36; 401 402 default: 403 break; 404 } 405 406 return 1; 407 } 408 409 410 // SamplerMagFilterTest 411 412 SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext, 413 const char* name, 414 const char* description, 415 VkImageViewType imageViewType, 416 VkFormat imageFormat, 417 VkFilter magFilter) 418 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f) 419 , m_magFilter (magFilter) 420 { 421 } 422 423 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const 424 { 425 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 426 samplerParams.magFilter = m_magFilter; 427 428 return samplerParams; 429 } 430 431 432 // SamplerMinFilterTest 433 434 SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext, 435 const char* name, 436 const char* description, 437 VkImageViewType imageViewType, 438 VkFormat imageFormat, 439 VkFilter minFilter) 440 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, 0.0f) 441 , m_minFilter (minFilter) 442 { 443 } 444 445 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const 446 { 447 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 448 samplerParams.minFilter = m_minFilter; 449 // set minLod to epsilon, to force use of the minFilter 450 samplerParams.minLod = 0.01f; 451 452 return samplerParams; 453 } 454 455 456 // SamplerLodTest 457 458 SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext, 459 const char* name, 460 const char* description, 461 VkImageViewType imageViewType, 462 VkFormat imageFormat, 463 VkSamplerMipmapMode mipmapMode, 464 float minLod, 465 float maxLod, 466 float mipLodBias, 467 float samplerLod) 468 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, samplerLod) 469 , m_mipmapMode (mipmapMode) 470 , m_minLod (minLod) 471 , m_maxLod (maxLod) 472 , m_mipLodBias (mipLodBias) 473 { 474 } 475 476 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const 477 { 478 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 479 480 samplerParams.mipmapMode = m_mipmapMode; 481 samplerParams.minLod = m_minLod; 482 samplerParams.maxLod = m_maxLod; 483 samplerParams.mipLodBias = m_mipLodBias; 484 485 return samplerParams; 486 } 487 488 489 // SamplerAddressModesTest 490 491 SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext, 492 const char* name, 493 const char* description, 494 VkImageViewType imageViewType, 495 VkFormat imageFormat, 496 VkSamplerAddressMode addressU, 497 VkSamplerAddressMode addressV, 498 VkSamplerAddressMode addressW, 499 VkBorderColor borderColor) 500 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f) 501 , m_addressU (addressU) 502 , m_addressV (addressV) 503 , m_addressW (addressW) 504 , m_borderColor (borderColor) 505 { 506 } 507 508 tcu::UVec2 SamplerAddressModesTest::getRenderSize (VkImageViewType viewType) const 509 { 510 return 4u * SamplerTest::getRenderSize(viewType); 511 } 512 513 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const 514 { 515 std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices(); 516 517 switch (m_imageViewType) 518 { 519 case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 520 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 521 vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f; 522 523 break; 524 525 case VK_IMAGE_VIEW_TYPE_2D: 526 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 527 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 528 vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f; 529 530 break; 531 532 case VK_IMAGE_VIEW_TYPE_3D: 533 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 534 vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f; 535 536 break; 537 538 case VK_IMAGE_VIEW_TYPE_CUBE: 539 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 540 break; 541 542 default: 543 DE_ASSERT(false); 544 } 545 546 return vertices; 547 } 548 549 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const 550 { 551 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 552 samplerParams.addressModeU = m_addressU; 553 samplerParams.addressModeV = m_addressV; 554 samplerParams.addressModeW = m_addressW; 555 samplerParams.borderColor = m_borderColor; 556 557 return samplerParams; 558 } 559 560 561 // Utilities to create test nodes 562 563 std::string getFormatCaseName (const VkFormat format) 564 { 565 const std::string fullName = getFormatName(format); 566 567 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); 568 569 return de::toLower(fullName.substr(10)); 570 } 571 572 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 573 { 574 MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter")); 575 576 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 577 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR)); 578 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST)); 579 580 return samplerMagFilterTests; 581 } 582 583 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 584 { 585 MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter")); 586 587 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 588 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR)); 589 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST)); 590 591 return samplerMinFilterTests; 592 } 593 594 MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode) 595 { 596 struct TestCaseConfig 597 { 598 const char* name; 599 const char* description; 600 float minLod; 601 float maxLod; 602 float mipLodBias; 603 float lod; 604 }; 605 606 TestCaseConfig testCaseConfigs [] = 607 { 608 { "equal_min_3_max_3", "minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0", 3.0f, 3.0f, 0.0f, 0.0f }, 609 { "select_min_1", "minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0", 1.0f, 5.0f, 0.0f, 0.0f }, 610 { "select_max_4", "minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5", 0.0f, 4.0f, 0.0f, 5.0f }, 611 { "select_bias_2_1", "minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0", 0.0f, 2.1f, 5.0f, 0.0f }, 612 { "select_bias_2_5", "minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0", 0.0f, 5.0f, 2.5f, 0.00001f }, 613 { "select_bias_3_1", "minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0", 0.0f, 5.0f, -0.9f, 4.0f }, 614 { "select_bias_3_7", "minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7", 0.0f, 5.0f, 3.0f, 0.7f }, 615 }; 616 617 MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD")); 618 619 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++) 620 { 621 const TestCaseConfig& config = testCaseConfigs[configNdx]; 622 623 samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod)); 624 } 625 626 return samplerLodTests; 627 } 628 629 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 630 { 631 MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes")); 632 633 // Mipmap mode: nearest 634 MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST")); 635 mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST).release()); 636 samplerMipmapTests->addChild(mipmapNearestTests.release()); 637 638 // Mipmap mode: linear 639 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 640 { 641 MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR")); 642 mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR).release()); 643 samplerMipmapTests->addChild(mipmapLinearTests.release()); 644 } 645 646 return samplerMipmapTests; 647 } 648 649 std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border) 650 { 651 static const char* borderColorNames[BORDER_COLOR_COUNT] = 652 { 653 "opaque_black", 654 "opaque_white", 655 "transparent_black", 656 }; 657 658 std::ostringstream caseName; 659 660 if (u == v && v == w) 661 { 662 const std::string fullName = getSamplerAddressModeName(u); 663 DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_")); 664 665 caseName << "all_"; 666 caseName << de::toLower(fullName.substr(19)); 667 668 if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) 669 { 670 caseName << "_" << borderColorNames[border]; 671 } 672 } 673 else 674 { 675 const std::string fullNameU = getSamplerAddressModeName(u); 676 const std::string fullNameV = getSamplerAddressModeName(v); 677 const std::string fullNameW = getSamplerAddressModeName(w); 678 679 DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_")); 680 DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_")); 681 DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_")); 682 683 caseName << "uvw" 684 << "_" << de::toLower(fullNameU.substr(19)) 685 << "_" << de::toLower(fullNameV.substr(19)) 686 << "_" << de::toLower(fullNameW.substr(19)); 687 } 688 689 return caseName.str(); 690 } 691 692 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 693 { 694 struct TestCaseConfig 695 { 696 VkSamplerAddressMode u; 697 VkSamplerAddressMode v; 698 VkSamplerAddressMode w; 699 BorderColor border; 700 }; 701 702 const TestCaseConfig testCaseConfigs[] = 703 { 704 // All address modes equal 705 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK }, 706 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK }, 707 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK }, 708 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_TRANSPARENT_BLACK }, 709 710 // All address modes equal using border color 711 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_TRANSPARENT_BLACK }, 712 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_BLACK }, 713 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 714 715 // Pairwise combinations of address modes not covered by previous tests 716 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE}, 717 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 718 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 719 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 720 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 721 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 722 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 723 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 724 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 725 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 726 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 727 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 728 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 729 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 730 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 731 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 732 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 733 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 734 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 735 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 736 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 737 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 738 }; 739 740 MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes")); 741 742 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++) 743 { 744 const TestCaseConfig& config = testCaseConfigs[configNdx]; 745 746 samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx, 747 getAddressModesCaseName(config.u, config.v, config.w, config.border).c_str(), 748 "", 749 imageViewType, 750 imageFormat, 751 config.u, config.v, config.w, 752 getFormatBorderColor(config.border, imageFormat))); 753 } 754 755 return samplerAddressModesTests; 756 } 757 758 } // anonymous 759 760 tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx) 761 { 762 const struct 763 { 764 VkImageViewType type; 765 const char* name; 766 } 767 imageViewTypes[] = 768 { 769 { VK_IMAGE_VIEW_TYPE_1D, "1d" }, 770 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" }, 771 { VK_IMAGE_VIEW_TYPE_2D, "2d" }, 772 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" }, 773 { VK_IMAGE_VIEW_TYPE_3D, "3d" }, 774 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" }, 775 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" } 776 }; 777 778 const VkFormat formats[] = 779 { 780 // Packed formats 781 VK_FORMAT_R4G4_UNORM_PACK8, 782 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 783 VK_FORMAT_R5G6B5_UNORM_PACK16, 784 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 785 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 786 VK_FORMAT_A2R10G10B10_UINT_PACK32, 787 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 788 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 789 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 790 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 791 792 // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order 793 VK_FORMAT_R8_SRGB, 794 VK_FORMAT_R8G8B8_UINT, 795 VK_FORMAT_B8G8R8A8_SINT, 796 VK_FORMAT_R8G8_UNORM, 797 VK_FORMAT_B8G8R8_SNORM, 798 VK_FORMAT_R8G8B8A8_SNORM, 799 VK_FORMAT_R8G8_UINT, 800 VK_FORMAT_R8_SINT, 801 VK_FORMAT_R8G8B8A8_SRGB, 802 VK_FORMAT_R8G8B8A8_UNORM, 803 VK_FORMAT_B8G8R8A8_UNORM, 804 VK_FORMAT_B8G8R8_SRGB, 805 VK_FORMAT_R8G8_SRGB, 806 VK_FORMAT_R8_UINT, 807 VK_FORMAT_R8G8B8A8_UINT, 808 VK_FORMAT_R8G8_SINT, 809 VK_FORMAT_R8_SNORM, 810 VK_FORMAT_B8G8R8_SINT, 811 VK_FORMAT_R8G8_SNORM, 812 VK_FORMAT_B8G8R8_UNORM, 813 VK_FORMAT_R8_UNORM, 814 815 // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels 816 VK_FORMAT_R32G32_SFLOAT, 817 VK_FORMAT_R32G32B32_UINT, 818 VK_FORMAT_R16G16B16A16_SFLOAT, 819 VK_FORMAT_R16G16_UINT, 820 VK_FORMAT_R32G32B32A32_SINT, 821 VK_FORMAT_R16G16B16_SINT, 822 VK_FORMAT_R16_SFLOAT, 823 VK_FORMAT_R32_SINT, 824 VK_FORMAT_R32_UINT, 825 VK_FORMAT_R16G16B16_SFLOAT, 826 VK_FORMAT_R16G16_SINT, 827 828 // Scaled formats 829 VK_FORMAT_R8G8B8A8_SSCALED, 830 VK_FORMAT_A2R10G10B10_USCALED_PACK32, 831 832 // Compressed formats 833 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, 834 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 835 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, 836 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 837 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, 838 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 839 VK_FORMAT_EAC_R11_UNORM_BLOCK, 840 VK_FORMAT_EAC_R11_SNORM_BLOCK, 841 VK_FORMAT_EAC_R11G11_UNORM_BLOCK, 842 VK_FORMAT_EAC_R11G11_SNORM_BLOCK, 843 VK_FORMAT_ASTC_4x4_UNORM_BLOCK, 844 VK_FORMAT_ASTC_5x4_SRGB_BLOCK, 845 VK_FORMAT_ASTC_6x5_UNORM_BLOCK, 846 VK_FORMAT_ASTC_6x6_SRGB_BLOCK, 847 VK_FORMAT_ASTC_8x6_UNORM_BLOCK, 848 VK_FORMAT_ASTC_8x8_SRGB_BLOCK, 849 VK_FORMAT_ASTC_10x6_UNORM_BLOCK, 850 VK_FORMAT_ASTC_10x8_SRGB_BLOCK, 851 VK_FORMAT_ASTC_12x10_UNORM_BLOCK, 852 VK_FORMAT_ASTC_12x12_SRGB_BLOCK, 853 }; 854 855 de::MovePtr<tcu::TestCaseGroup> samplerTests (new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests")); 856 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", "")); 857 858 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++) 859 { 860 const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type; 861 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str())); 862 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats")); 863 864 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 865 { 866 const VkFormat format = formats[formatNdx]; 867 const bool isCompressed = isCompressedFormat(format); 868 869 if (isCompressed) 870 { 871 // Do not use compressed formats with 1D and 1D array textures. 872 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY) 873 break; 874 } 875 876 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, 877 getFormatCaseName(format).c_str(), 878 (std::string("Samples a texture of format ") + getFormatName(format)).c_str())); 879 880 if (!isCompressed) 881 { 882 // Do not include minFilter tests with compressed formats. 883 // Randomly generated compressed textures are too noisy and will derive in false positives. 884 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, viewType, format); 885 formatGroup->addChild(minFilterTests.release()); 886 } 887 888 de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, viewType, format); 889 de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, viewType, format); 890 891 formatGroup->addChild(magFilterTests.release()); 892 formatGroup->addChild(mipmapTests.release()); 893 894 if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 895 { 896 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, viewType, format); 897 formatGroup->addChild(addressModesTests.release()); 898 } 899 900 formatTests->addChild(formatGroup.release()); 901 } 902 903 viewTypeGroup->addChild(formatTests.release()); 904 viewTypeTests->addChild(viewTypeGroup.release()); 905 } 906 907 samplerTests->addChild(viewTypeTests.release()); 908 909 return samplerTests.release(); 910 } 911 912 } // pipeline 913 } // vkt 914