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 tcu::Vec4 lookupScale; 188 tcu::Vec4 lookupBias; 189 190 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias); 191 192 switch (m_imageViewType) 193 { 194 case VK_IMAGE_VIEW_TYPE_1D: 195 texCoordSwizzle = "x"; 196 break; 197 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 198 case VK_IMAGE_VIEW_TYPE_2D: 199 texCoordSwizzle = "xy"; 200 break; 201 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 202 case VK_IMAGE_VIEW_TYPE_3D: 203 case VK_IMAGE_VIEW_TYPE_CUBE: 204 texCoordSwizzle = "xyz"; 205 break; 206 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 207 texCoordSwizzle = "xyzw"; 208 break; 209 default: 210 DE_ASSERT(false); 211 break; 212 } 213 214 vertexSrc << "#version 440\n" 215 << "layout(location = 0) in vec4 position;\n" 216 << "layout(location = 1) in vec4 texCoords;\n" 217 << "layout(location = 0) out highp vec4 vtxTexCoords;\n" 218 << "out gl_PerVertex {\n" 219 << " vec4 gl_Position;\n" 220 << "};\n" 221 << "void main (void)\n" 222 << "{\n" 223 << " gl_Position = position;\n" 224 << " vtxTexCoords = texCoords;\n" 225 << "}\n"; 226 227 fragmentSrc << "#version 440\n" 228 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n" 229 << "layout(location = 0) in highp vec4 vtxTexCoords;\n" 230 << "layout(location = 0) out highp vec4 fragColor;\n" 231 << "void main (void)\n" 232 << "{\n" 233 << " fragColor = "; 234 235 if (m_samplerLod > 0.0f) 236 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")"; 237 else 238 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed; 239 240 fragmentSrc << " * vec4" << std::scientific << lookupScale << " + vec4" << lookupBias << ";\n" 241 << "}\n"; 242 243 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str()); 244 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str()); 245 } 246 247 TestInstance* SamplerTest::createInstance (Context& context) const 248 { 249 const tcu::UVec2 renderSize = getRenderSize(m_imageViewType); 250 const std::vector<Vertex4Tex4> vertices = createVertices(); 251 const VkSamplerCreateInfo samplerParams = getSamplerCreateInfo(); 252 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 253 const VkImageSubresourceRange subresourceRange = 254 { 255 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 256 0u, // deUint32 baseMipLevel; 257 (deUint32)deLog2Floor32(m_imageSize) + 1, // deUint32 mipLevels; 258 0u, // deUint32 baseArrayLayer; 259 (deUint32)SamplerTest::getArraySize(m_imageViewType) // deUint32 arraySize; 260 }; 261 262 263 264 return new ImageSamplingInstance(context, renderSize, m_imageViewType, m_imageFormat, 265 getImageSize(m_imageViewType, m_imageSize), 266 getArraySize(m_imageViewType), 267 componentMapping, subresourceRange, 268 samplerParams, m_samplerLod,vertices); 269 } 270 271 tcu::UVec2 SamplerTest::getRenderSize (VkImageViewType viewType) const 272 { 273 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D) 274 { 275 return tcu::UVec2(16u, 16u); 276 } 277 else 278 { 279 return tcu::UVec2(16u * 3u, 16u * 2u); 280 } 281 } 282 283 std::vector<Vertex4Tex4> SamplerTest::createVertices (void) const 284 { 285 std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(m_imageViewType); 286 // Adjust texture coordinate to avoid doing NEAREST filtering exactly on texel boundaries. 287 // TODO: Would be nice to base this on number of texels and subtexel precision. But this 288 // seems to work. 289 for (unsigned int i = 0; i < vertices.size(); ++i) { 290 vertices[i].texCoord += tcu::Vec4(0.002f, 0.002f, 0.002f, 0.0f); 291 } 292 return vertices; 293 } 294 295 VkSamplerCreateInfo SamplerTest::getSamplerCreateInfo (void) const 296 { 297 const VkSamplerCreateInfo defaultSamplerParams = 298 { 299 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 300 DE_NULL, // const void* pNext; 301 0u, // VkSamplerCreateFlags flags; 302 VK_FILTER_NEAREST, // VkFilter magFilter; 303 VK_FILTER_NEAREST, // VkFilter minFilter; 304 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 305 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 306 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 307 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 308 0.0f, // float mipLodBias; 309 VK_FALSE, // VkBool32 anisotropyEnable; 310 1.0f, // float maxAnisotropy; 311 false, // VkBool32 compareEnable; 312 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 313 0.0f, // float minLod; 314 0.25f, // float maxLod; 315 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, m_imageFormat), // VkBorderColor borderColor; 316 false // VkBool32 unnormalizedCoordinates; 317 }; 318 319 return defaultSamplerParams; 320 } 321 322 std::string SamplerTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type) 323 { 324 std::ostringstream samplerType; 325 326 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 327 samplerType << "u"; 328 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 329 samplerType << "i"; 330 331 switch (type) 332 { 333 case VK_IMAGE_VIEW_TYPE_1D: 334 samplerType << "sampler1D"; 335 break; 336 337 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 338 samplerType << "sampler1DArray"; 339 break; 340 341 case VK_IMAGE_VIEW_TYPE_2D: 342 samplerType << "sampler2D"; 343 break; 344 345 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 346 samplerType << "sampler2DArray"; 347 break; 348 349 case VK_IMAGE_VIEW_TYPE_3D: 350 samplerType << "sampler3D"; 351 break; 352 353 case VK_IMAGE_VIEW_TYPE_CUBE: 354 samplerType << "samplerCube"; 355 break; 356 357 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 358 samplerType << "samplerCubeArray"; 359 break; 360 361 default: 362 DE_FATAL("Unknown image view type"); 363 break; 364 } 365 366 return samplerType.str(); 367 } 368 369 tcu::IVec3 SamplerTest::getImageSize (VkImageViewType viewType, int size) 370 { 371 switch (viewType) 372 { 373 case VK_IMAGE_VIEW_TYPE_1D: 374 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 375 return tcu::IVec3(size, 1, 1); 376 377 case VK_IMAGE_VIEW_TYPE_3D: 378 return tcu::IVec3(size, size, 4); 379 380 default: 381 break; 382 } 383 384 return tcu::IVec3(size, size, 1); 385 } 386 387 int SamplerTest::getArraySize (VkImageViewType viewType) 388 { 389 switch (viewType) 390 { 391 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 392 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 393 case VK_IMAGE_VIEW_TYPE_CUBE: 394 return 6; 395 396 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 397 return 36; 398 399 default: 400 break; 401 } 402 403 return 1; 404 } 405 406 407 // SamplerMagFilterTest 408 409 SamplerMagFilterTest::SamplerMagFilterTest (tcu::TestContext& testContext, 410 const char* name, 411 const char* description, 412 VkImageViewType imageViewType, 413 VkFormat imageFormat, 414 VkFilter magFilter) 415 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f) 416 , m_magFilter (magFilter) 417 { 418 } 419 420 VkSamplerCreateInfo SamplerMagFilterTest::getSamplerCreateInfo (void) const 421 { 422 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 423 samplerParams.magFilter = m_magFilter; 424 425 return samplerParams; 426 } 427 428 429 // SamplerMinFilterTest 430 431 SamplerMinFilterTest::SamplerMinFilterTest (tcu::TestContext& testContext, 432 const char* name, 433 const char* description, 434 VkImageViewType imageViewType, 435 VkFormat imageFormat, 436 VkFilter minFilter) 437 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, 0.0f) 438 , m_minFilter (minFilter) 439 { 440 } 441 442 VkSamplerCreateInfo SamplerMinFilterTest::getSamplerCreateInfo (void) const 443 { 444 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 445 samplerParams.minFilter = m_minFilter; 446 // set minLod to epsilon, to force use of the minFilter 447 samplerParams.minLod = 0.01f; 448 449 return samplerParams; 450 } 451 452 453 // SamplerLodTest 454 455 SamplerLodTest::SamplerLodTest (tcu::TestContext& testContext, 456 const char* name, 457 const char* description, 458 VkImageViewType imageViewType, 459 VkFormat imageFormat, 460 VkSamplerMipmapMode mipmapMode, 461 float minLod, 462 float maxLod, 463 float mipLodBias, 464 float samplerLod) 465 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 32, samplerLod) 466 , m_mipmapMode (mipmapMode) 467 , m_minLod (minLod) 468 , m_maxLod (maxLod) 469 , m_mipLodBias (mipLodBias) 470 { 471 } 472 473 VkSamplerCreateInfo SamplerLodTest::getSamplerCreateInfo (void) const 474 { 475 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 476 477 samplerParams.mipmapMode = m_mipmapMode; 478 samplerParams.minLod = m_minLod; 479 samplerParams.maxLod = m_maxLod; 480 samplerParams.mipLodBias = m_mipLodBias; 481 482 return samplerParams; 483 } 484 485 486 // SamplerAddressModesTest 487 488 SamplerAddressModesTest::SamplerAddressModesTest (tcu::TestContext& testContext, 489 const char* name, 490 const char* description, 491 VkImageViewType imageViewType, 492 VkFormat imageFormat, 493 VkSamplerAddressMode addressU, 494 VkSamplerAddressMode addressV, 495 VkSamplerAddressMode addressW, 496 VkBorderColor borderColor) 497 : SamplerTest (testContext, name, description, imageViewType, imageFormat, 8, 0.0f) 498 , m_addressU (addressU) 499 , m_addressV (addressV) 500 , m_addressW (addressW) 501 , m_borderColor (borderColor) 502 { 503 } 504 505 tcu::UVec2 SamplerAddressModesTest::getRenderSize (VkImageViewType viewType) const 506 { 507 return 4u * SamplerTest::getRenderSize(viewType); 508 } 509 510 std::vector<Vertex4Tex4> SamplerAddressModesTest::createVertices (void) const 511 { 512 std::vector<Vertex4Tex4> vertices = SamplerTest::createVertices(); 513 514 switch (m_imageViewType) 515 { 516 case VK_IMAGE_VIEW_TYPE_1D: case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 517 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 518 vertices[vertexNdx].texCoord.x() = (vertices[vertexNdx].texCoord.x() - 0.5f) * 4.0f; 519 520 break; 521 522 case VK_IMAGE_VIEW_TYPE_2D: 523 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 524 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 525 vertices[vertexNdx].texCoord.xy() = (vertices[vertexNdx].texCoord.swizzle(0, 1) - tcu::Vec2(0.5f)) * 4.0f; 526 527 break; 528 529 case VK_IMAGE_VIEW_TYPE_3D: 530 for (size_t vertexNdx = 0; vertexNdx < vertices.size(); vertexNdx++) 531 vertices[vertexNdx].texCoord.xyz() = (vertices[vertexNdx].texCoord.swizzle(0, 1, 2) - tcu::Vec3(0.5f)) * 4.0f; 532 533 break; 534 535 case VK_IMAGE_VIEW_TYPE_CUBE: 536 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 537 break; 538 539 default: 540 DE_ASSERT(false); 541 } 542 543 return vertices; 544 } 545 546 VkSamplerCreateInfo SamplerAddressModesTest::getSamplerCreateInfo (void) const 547 { 548 VkSamplerCreateInfo samplerParams = SamplerTest::getSamplerCreateInfo(); 549 samplerParams.addressModeU = m_addressU; 550 samplerParams.addressModeV = m_addressV; 551 samplerParams.addressModeW = m_addressW; 552 samplerParams.borderColor = m_borderColor; 553 554 return samplerParams; 555 } 556 557 558 // Utilities to create test nodes 559 560 std::string getFormatCaseName (const VkFormat format) 561 { 562 const std::string fullName = getFormatName(format); 563 564 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); 565 566 return de::toLower(fullName.substr(10)); 567 } 568 569 MovePtr<tcu::TestCaseGroup> createSamplerMagFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 570 { 571 MovePtr<tcu::TestCaseGroup> samplerMagFilterTests (new tcu::TestCaseGroup(testCtx, "mag_filter", "Tests for magnification filter")); 572 573 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 574 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "linear", "Magnifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR)); 575 samplerMagFilterTests->addChild(new SamplerMagFilterTest(testCtx, "nearest", "Magnifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST)); 576 577 return samplerMagFilterTests; 578 } 579 580 MovePtr<tcu::TestCaseGroup> createSamplerMinFilterTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 581 { 582 MovePtr<tcu::TestCaseGroup> samplerMinFilterTests (new tcu::TestCaseGroup(testCtx, "min_filter", "Tests for minification filter")); 583 584 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 585 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "linear", "Minifies image using VK_TEX_FILTER_LINEAR", imageViewType, imageFormat, VK_FILTER_LINEAR)); 586 samplerMinFilterTests->addChild(new SamplerMinFilterTest(testCtx, "nearest", "Minifies image using VK_TEX_FILTER_NEAREST", imageViewType, imageFormat, VK_FILTER_NEAREST)); 587 588 return samplerMinFilterTests; 589 } 590 591 MovePtr<tcu::TestCaseGroup> createSamplerLodTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat, VkSamplerMipmapMode mipmapMode) 592 { 593 struct TestCaseConfig 594 { 595 const char* name; 596 const char* description; 597 float minLod; 598 float maxLod; 599 float mipLodBias; 600 float lod; 601 }; 602 603 TestCaseConfig testCaseConfigs [] = 604 { 605 { "equal_min_3_max_3", "minLod = 3, maxLod = 3, mipLodBias = 0, lod = 0", 3.0f, 3.0f, 0.0f, 0.0f }, 606 { "select_min_1", "minLod = 1, maxLod = 5, mipLodBias = 0, lod = 0", 1.0f, 5.0f, 0.0f, 0.0f }, 607 { "select_max_4", "minLod = 0, maxLod = 4, mipLodBias = 0, lod = 5", 0.0f, 4.0f, 0.0f, 5.0f }, 608 { "select_bias_2_1", "minLod = 0, maxLod = 2.1, mipLodBias = 5.0, lod = 0", 0.0f, 2.1f, 5.0f, 0.0f }, 609 { "select_bias_2_5", "minLod = 0, maxLod = 5, mipLodBias = 2.5, lod = 0", 0.0f, 5.0f, 2.5f, 0.00001f }, 610 { "select_bias_3_1", "minLod = 0, maxLod = 5, mipLodBias = -0.9, lod = 4.0", 0.0f, 5.0f, -0.9f, 4.0f }, 611 { "select_bias_3_7", "minLod = 0, maxLod = 5, mipLodBias = 3.0, lod = 0.7", 0.0f, 5.0f, 3.0f, 0.7f }, 612 }; 613 614 MovePtr<tcu::TestCaseGroup> samplerLodTests (new tcu::TestCaseGroup(testCtx, "lod", "Tests for sampler LOD")); 615 616 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++) 617 { 618 const TestCaseConfig& config = testCaseConfigs[configNdx]; 619 620 samplerLodTests->addChild(new SamplerLodTest(testCtx, config.name, config.description, imageViewType, imageFormat, mipmapMode, config.minLod, config.maxLod, config.mipLodBias, config.lod)); 621 } 622 623 return samplerLodTests; 624 } 625 626 MovePtr<tcu::TestCaseGroup> createSamplerMipmapTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 627 { 628 MovePtr<tcu::TestCaseGroup> samplerMipmapTests (new tcu::TestCaseGroup(testCtx, "mipmap", "Tests for mipmap modes")); 629 630 // Mipmap mode: nearest 631 MovePtr<tcu::TestCaseGroup> mipmapNearestTests (new tcu::TestCaseGroup(testCtx, "nearest", "Uses VK_TEX_MIPMAP_MODE_NEAREST")); 632 mipmapNearestTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_NEAREST).release()); 633 samplerMipmapTests->addChild(mipmapNearestTests.release()); 634 635 // Mipmap mode: linear 636 if (isCompressedFormat(imageFormat) || (!isIntFormat(imageFormat) && !isUintFormat(imageFormat))) 637 { 638 MovePtr<tcu::TestCaseGroup> mipmapLinearTests(new tcu::TestCaseGroup(testCtx, "linear", "Uses VK_TEX_MIPMAP_MODE_LINEAR")); 639 mipmapLinearTests->addChild(createSamplerLodTests(testCtx, imageViewType, imageFormat, VK_SAMPLER_MIPMAP_MODE_LINEAR).release()); 640 samplerMipmapTests->addChild(mipmapLinearTests.release()); 641 } 642 643 return samplerMipmapTests; 644 } 645 646 std::string getAddressModesCaseName (VkSamplerAddressMode u, VkSamplerAddressMode v, VkSamplerAddressMode w, BorderColor border) 647 { 648 static const char* borderColorNames[BORDER_COLOR_COUNT] = 649 { 650 "opaque_black", 651 "opaque_white", 652 "transparent_black", 653 }; 654 655 std::ostringstream caseName; 656 657 if (u == v && v == w) 658 { 659 const std::string fullName = getSamplerAddressModeName(u); 660 DE_ASSERT(de::beginsWith(fullName, "VK_SAMPLER_ADDRESS_")); 661 662 caseName << "all_"; 663 caseName << de::toLower(fullName.substr(19)); 664 665 if (u == VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER) 666 { 667 caseName << "_" << borderColorNames[border]; 668 } 669 } 670 else 671 { 672 const std::string fullNameU = getSamplerAddressModeName(u); 673 const std::string fullNameV = getSamplerAddressModeName(v); 674 const std::string fullNameW = getSamplerAddressModeName(w); 675 676 DE_ASSERT(de::beginsWith(fullNameU, "VK_SAMPLER_ADDRESS_")); 677 DE_ASSERT(de::beginsWith(fullNameV, "VK_SAMPLER_ADDRESS_")); 678 DE_ASSERT(de::beginsWith(fullNameW, "VK_SAMPLER_ADDRESS_")); 679 680 caseName << "uvw" 681 << "_" << de::toLower(fullNameU.substr(19)) 682 << "_" << de::toLower(fullNameV.substr(19)) 683 << "_" << de::toLower(fullNameW.substr(19)); 684 } 685 686 return caseName.str(); 687 } 688 689 MovePtr<tcu::TestCaseGroup> createSamplerAddressModesTests (tcu::TestContext& testCtx, VkImageViewType imageViewType, VkFormat imageFormat) 690 { 691 struct TestCaseConfig 692 { 693 VkSamplerAddressMode u; 694 VkSamplerAddressMode v; 695 VkSamplerAddressMode w; 696 BorderColor border; 697 }; 698 699 const TestCaseConfig testCaseConfigs[] = 700 { 701 // All address modes equal 702 { 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 }, 703 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK }, 704 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_TRANSPARENT_BLACK }, 705 { 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 }, 706 707 // All address modes equal using border color 708 { 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 }, 709 { 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 }, 710 { 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 }, 711 712 // Pairwise combinations of address modes not covered by previous tests 713 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE}, 714 { 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 }, 715 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 716 { 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 }, 717 { 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 }, 718 { 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 }, 719 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 720 { 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 }, 721 { VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 722 { 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 }, 723 { 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 }, 724 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 725 { VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 726 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 727 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, BORDER_COLOR_OPAQUE_WHITE }, 728 { VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 729 { 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 }, 730 { 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 }, 731 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, VK_SAMPLER_ADDRESS_MODE_REPEAT, BORDER_COLOR_OPAQUE_WHITE }, 732 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_REPEAT, VK_SAMPLER_ADDRESS_MODE_MIRROR_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 733 { VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, VK_SAMPLER_ADDRESS_MODE_MIRRORED_REPEAT, VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, BORDER_COLOR_OPAQUE_WHITE }, 734 { 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 }, 735 }; 736 737 MovePtr<tcu::TestCaseGroup> samplerAddressModesTests (new tcu::TestCaseGroup(testCtx, "address_modes", "Tests for address modes")); 738 739 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(testCaseConfigs); configNdx++) 740 { 741 const TestCaseConfig& config = testCaseConfigs[configNdx]; 742 743 samplerAddressModesTests->addChild(new SamplerAddressModesTest(testCtx, 744 getAddressModesCaseName(config.u, config.v, config.w, config.border).c_str(), 745 "", 746 imageViewType, 747 imageFormat, 748 config.u, config.v, config.w, 749 getFormatBorderColor(config.border, imageFormat))); 750 } 751 752 return samplerAddressModesTests; 753 } 754 755 } // anonymous 756 757 tcu::TestCaseGroup* createSamplerTests (tcu::TestContext& testCtx) 758 { 759 const struct 760 { 761 VkImageViewType type; 762 const char* name; 763 } 764 imageViewTypes[] = 765 { 766 { VK_IMAGE_VIEW_TYPE_1D, "1d" }, 767 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" }, 768 { VK_IMAGE_VIEW_TYPE_2D, "2d" }, 769 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" }, 770 { VK_IMAGE_VIEW_TYPE_3D, "3d" }, 771 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" }, 772 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" } 773 }; 774 775 const VkFormat formats[] = 776 { 777 // Packed formats 778 VK_FORMAT_R4G4_UNORM_PACK8, 779 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 780 VK_FORMAT_R5G6B5_UNORM_PACK16, 781 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 782 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 783 VK_FORMAT_A2R10G10B10_UINT_PACK32, 784 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 785 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 786 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 787 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 788 789 // Pairwise combinations of 8-bit channel formats, UNORM/SNORM/SINT/UINT/SRGB type x 1-to-4 channels x RGBA/BGRA order 790 VK_FORMAT_R8_SRGB, 791 VK_FORMAT_R8G8B8_UINT, 792 VK_FORMAT_B8G8R8A8_SINT, 793 VK_FORMAT_R8G8_UNORM, 794 VK_FORMAT_B8G8R8_SNORM, 795 VK_FORMAT_R8G8B8A8_SNORM, 796 VK_FORMAT_R8G8_UINT, 797 VK_FORMAT_R8_SINT, 798 VK_FORMAT_R8G8B8A8_SRGB, 799 VK_FORMAT_R8G8B8A8_UNORM, 800 VK_FORMAT_B8G8R8A8_UNORM, 801 VK_FORMAT_B8G8R8_SRGB, 802 VK_FORMAT_R8G8_SRGB, 803 VK_FORMAT_R8_UINT, 804 VK_FORMAT_R8G8B8A8_UINT, 805 VK_FORMAT_R8G8_SINT, 806 VK_FORMAT_R8_SNORM, 807 VK_FORMAT_B8G8R8_SINT, 808 VK_FORMAT_R8G8_SNORM, 809 VK_FORMAT_B8G8R8_UNORM, 810 VK_FORMAT_R8_UNORM, 811 812 // Pairwise combinations of 16/32-bit channel formats x SINT/UINT/SFLOAT type x 1-to-4 channels 813 VK_FORMAT_R32G32_SFLOAT, 814 VK_FORMAT_R32G32B32_UINT, 815 VK_FORMAT_R16G16B16A16_SFLOAT, 816 VK_FORMAT_R16G16_UINT, 817 VK_FORMAT_R32G32B32A32_SINT, 818 VK_FORMAT_R16G16B16_SINT, 819 VK_FORMAT_R16_SFLOAT, 820 VK_FORMAT_R32_SINT, 821 VK_FORMAT_R32_UINT, 822 VK_FORMAT_R16G16B16_SFLOAT, 823 VK_FORMAT_R16G16_SINT, 824 825 // Scaled formats 826 VK_FORMAT_R8G8B8A8_SSCALED, 827 VK_FORMAT_A2R10G10B10_USCALED_PACK32, 828 829 // Compressed formats 830 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, 831 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 832 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, 833 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 834 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, 835 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 836 VK_FORMAT_EAC_R11_UNORM_BLOCK, 837 VK_FORMAT_EAC_R11_SNORM_BLOCK, 838 VK_FORMAT_EAC_R11G11_UNORM_BLOCK, 839 VK_FORMAT_EAC_R11G11_SNORM_BLOCK, 840 VK_FORMAT_ASTC_4x4_UNORM_BLOCK, 841 VK_FORMAT_ASTC_5x4_SRGB_BLOCK, 842 VK_FORMAT_ASTC_6x5_UNORM_BLOCK, 843 VK_FORMAT_ASTC_6x6_SRGB_BLOCK, 844 VK_FORMAT_ASTC_8x6_UNORM_BLOCK, 845 VK_FORMAT_ASTC_8x8_SRGB_BLOCK, 846 VK_FORMAT_ASTC_10x6_UNORM_BLOCK, 847 VK_FORMAT_ASTC_10x8_SRGB_BLOCK, 848 VK_FORMAT_ASTC_12x10_UNORM_BLOCK, 849 VK_FORMAT_ASTC_12x12_SRGB_BLOCK, 850 }; 851 852 de::MovePtr<tcu::TestCaseGroup> samplerTests (new tcu::TestCaseGroup(testCtx, "sampler", "Sampler tests")); 853 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type", "")); 854 855 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++) 856 { 857 const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type; 858 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name, (std::string("Uses a ") + imageViewTypes[viewTypeNdx].name + " view").c_str())); 859 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format", "Tests samplable formats")); 860 861 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 862 { 863 const VkFormat format = formats[formatNdx]; 864 const bool isCompressed = isCompressedFormat(format); 865 866 if (isCompressed) 867 { 868 // Do not use compressed formats with 1D and 1D array textures. 869 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY) 870 break; 871 } 872 873 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, 874 getFormatCaseName(format).c_str(), 875 (std::string("Samples a texture of format ") + getFormatName(format)).c_str())); 876 877 if (!isCompressed) 878 { 879 // Do not include minFilter tests with compressed formats. 880 // Randomly generated compressed textures are too noisy and will derive in false positives. 881 de::MovePtr<tcu::TestCaseGroup> minFilterTests = createSamplerMinFilterTests(testCtx, viewType, format); 882 formatGroup->addChild(minFilterTests.release()); 883 } 884 885 de::MovePtr<tcu::TestCaseGroup> magFilterTests = createSamplerMagFilterTests(testCtx, viewType, format); 886 de::MovePtr<tcu::TestCaseGroup> mipmapTests = createSamplerMipmapTests(testCtx, viewType, format); 887 888 formatGroup->addChild(magFilterTests.release()); 889 formatGroup->addChild(mipmapTests.release()); 890 891 if (viewType != VK_IMAGE_VIEW_TYPE_CUBE && viewType != VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 892 { 893 de::MovePtr<tcu::TestCaseGroup> addressModesTests = createSamplerAddressModesTests(testCtx, viewType, format); 894 formatGroup->addChild(addressModesTests.release()); 895 } 896 897 formatTests->addChild(formatGroup.release()); 898 } 899 900 viewTypeGroup->addChild(formatTests.release()); 901 viewTypeTests->addChild(viewTypeGroup.release()); 902 } 903 904 samplerTests->addChild(viewTypeTests.release()); 905 906 return samplerTests.release(); 907 } 908 909 } // pipeline 910 } // vkt 911