1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2015 The Khronos Group Inc. 6 * Copyright (c) 2015 Imagination Technologies Ltd. 7 * Copyright (c) 2023 LunarG, Inc. 8 * Copyright (c) 2023 Nintendo 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 *//*! 23 * \file 24 * \brief Image View Tests 25 *//*--------------------------------------------------------------------*/ 26 27#include "vktPipelineImageViewTests.hpp" 28#include "vktPipelineImageSamplingInstance.hpp" 29#include "vktPipelineImageUtil.hpp" 30#include "vktPipelineVertexUtil.hpp" 31#include "vktTestCase.hpp" 32#include "vkImageUtil.hpp" 33#include "vkPrograms.hpp" 34#include "tcuPlatform.hpp" 35#include "tcuTextureUtil.hpp" 36#include "deStringUtil.hpp" 37#include "deMemory.h" 38 39#include <sstream> 40#include <vector> 41 42namespace vkt 43{ 44namespace pipeline 45{ 46 47using namespace vk; 48using de::MovePtr; 49 50namespace 51{ 52 53 54class ImageViewTest : public vkt::TestCase 55{ 56public: 57 ImageViewTest (tcu::TestContext& testContext, 58 const char* name, 59 PipelineConstructionType pipelineConstructionType, 60 VkImageViewType imageViewType, 61 VkFormat imageFormat, 62 float samplerLod, 63 const VkComponentMapping& componentMapping, 64 const VkImageSubresourceRange& subresourceRange); 65 virtual ~ImageViewTest (void) {} 66 67 ImageSamplingInstanceParams getImageSamplingInstanceParams (VkImageViewType imageViewType, 68 VkFormat imageFormat, 69 float samplerLod, 70 const VkComponentMapping& componentMapping, 71 const VkImageSubresourceRange& subresourceRange) const; 72 73 virtual void initPrograms (SourceCollections& sourceCollections) const; 74 virtual void checkSupport (Context& context) const; 75 virtual TestInstance* createInstance (Context& context) const; 76 static std::string getGlslSamplerType (const tcu::TextureFormat& format, 77 VkImageViewType type); 78 static tcu::UVec2 getRenderSize (VkImageViewType viewType); 79 static tcu::IVec3 getImageSize (VkImageViewType viewType); 80 static int getArraySize (VkImageViewType viewType); 81 static int getNumLevels (VkImageViewType viewType); 82 static tcu::Vec4 swizzle (tcu::Vec4 inputData, 83 VkComponentMapping componentMapping); 84private: 85 PipelineConstructionType m_pipelineConstructionType; 86 VkImageViewType m_imageViewType; 87 VkFormat m_imageFormat; 88 float m_samplerLod; 89 VkComponentMapping m_componentMapping; 90 VkImageSubresourceRange m_subresourceRange; 91}; 92 93ImageViewTest::ImageViewTest (tcu::TestContext& testContext, 94 const char* name, 95 PipelineConstructionType pipelineConstructionType, 96 VkImageViewType imageViewType, 97 VkFormat imageFormat, 98 float samplerLod, 99 const VkComponentMapping& componentMapping, 100 const VkImageSubresourceRange& subresourceRange) 101 102 : vkt::TestCase (testContext, name) 103 , m_pipelineConstructionType (pipelineConstructionType) 104 , m_imageViewType (imageViewType) 105 , m_imageFormat (imageFormat) 106 , m_samplerLod (samplerLod) 107 , m_componentMapping (componentMapping) 108 , m_subresourceRange (subresourceRange) 109{ 110} 111 112ImageSamplingInstanceParams ImageViewTest::getImageSamplingInstanceParams (VkImageViewType imageViewType, 113 VkFormat imageFormat, 114 float samplerLod, 115 const VkComponentMapping& componentMapping, 116 const VkImageSubresourceRange& subresourceRange) const 117{ 118 const tcu::UVec2 renderSize = getRenderSize(imageViewType); 119 const tcu::IVec3 imageSize = getImageSize(imageViewType); 120 const int arraySize = getArraySize(imageViewType); 121 const std::vector<Vertex4Tex4> vertices = createTestQuadMosaic(imageViewType); 122 123 const VkSamplerCreateInfo samplerParams = 124 { 125 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 126 DE_NULL, // const void* pNext; 127 0u, // VkSamplerCreateFlags flags; 128 VK_FILTER_NEAREST, // VkFilter magFilter; 129 VK_FILTER_NEAREST, // VkFilter minFilter; 130 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 131 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeU; 132 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeV; 133 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // VkSamplerAddressMode addressModeW; 134 0.0f, // float mipLodBias; 135 VK_FALSE, // VkBool32 anisotropyEnable; 136 1.0f, // float maxAnisotropy; 137 false, // VkBool32 compareEnable; 138 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 139 0.0f, // float minLod; 140 (float)(subresourceRange.levelCount - 1), // float maxLod; 141 getFormatBorderColor(BORDER_COLOR_TRANSPARENT_BLACK, imageFormat, false), // VkBorderColor borderColor; 142 false // VkBool32 unnormalizedCoordinates; 143 }; 144 145 return ImageSamplingInstanceParams(m_pipelineConstructionType, renderSize, imageViewType, imageFormat, imageSize, arraySize, componentMapping, subresourceRange, samplerParams, samplerLod, vertices); 146} 147 148void ImageViewTest::checkSupport (Context& context) const 149{ 150 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_pipelineConstructionType); 151 152#ifndef CTS_USES_VULKANSC 153 if (m_imageFormat == VK_FORMAT_A8_UNORM_KHR || m_imageFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR) 154 context.requireDeviceFunctionality("VK_KHR_maintenance5"); 155#endif // CTS_USES_VULKANSC 156 157 checkSupportImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange)); 158} 159 160tcu::Vec4 ImageViewTest::swizzle (tcu::Vec4 inputData, VkComponentMapping componentMapping) 161{ 162 // array map with enum VkComponentSwizzle 163 const float channelValues[] = 164 { 165 -1.0f, 166 0.0f, 167 1.0f, 168 inputData.x(), 169 inputData.y(), 170 inputData.z(), 171 inputData.w(), 172 -1.0f 173 }; 174 175 return tcu::Vec4(channelValues[componentMapping.r], 176 channelValues[componentMapping.g], 177 channelValues[componentMapping.b], 178 channelValues[componentMapping.a]); 179} 180 181void ImageViewTest::initPrograms (SourceCollections& sourceCollections) const 182{ 183 std::ostringstream vertexSrc; 184 std::ostringstream fragmentSrc; 185 const char* texCoordSwizzle = DE_NULL; 186 const tcu::TextureFormat format = (isCompressedFormat(m_imageFormat)) ? tcu::getUncompressedFormat(mapVkCompressedFormat(m_imageFormat)) 187 : mapVkFormat(m_imageFormat); 188 189 tcu::Vec4 lookupScale; 190 tcu::Vec4 lookupBias; 191 192 getLookupScaleBias(m_imageFormat, lookupScale, lookupBias); 193 194 tcu::Vec4 swizzledScale = swizzle(lookupScale, m_componentMapping); 195 tcu::Vec4 swizzledBias = swizzle(lookupBias, m_componentMapping); 196 197 switch (m_imageViewType) 198 { 199 case VK_IMAGE_VIEW_TYPE_1D: 200 texCoordSwizzle = "x"; 201 break; 202 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 203 case VK_IMAGE_VIEW_TYPE_2D: 204 texCoordSwizzle = "xy"; 205 break; 206 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 207 case VK_IMAGE_VIEW_TYPE_3D: 208 case VK_IMAGE_VIEW_TYPE_CUBE: 209 texCoordSwizzle = "xyz"; 210 break; 211 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 212 texCoordSwizzle = "xyzw"; 213 break; 214 default: 215 DE_ASSERT(false); 216 break; 217 } 218 219 vertexSrc << "#version 440\n" 220 << "layout(location = 0) in vec4 position;\n" 221 << "layout(location = 1) in vec4 texCoords;\n" 222 << "layout(location = 0) out highp vec4 vtxTexCoords;\n" 223 << "out gl_PerVertex {\n" 224 << " vec4 gl_Position;\n" 225 << "};\n" 226 << "void main (void)\n" 227 << "{\n" 228 << " gl_Position = position;\n" 229 << " vtxTexCoords = texCoords;\n" 230 << "}\n"; 231 232 fragmentSrc << "#version 440\n" 233 << "layout(set = 0, binding = 0) uniform highp " << getGlslSamplerType(format, m_imageViewType) << " texSampler;\n" 234 << "layout(location = 0) in highp vec4 vtxTexCoords;\n" 235 << "layout(location = 0) out highp vec4 fragColor;\n" 236 << "void main (void)\n" 237 << "{\n" 238 << " fragColor = "; 239 240 if (m_samplerLod > 0.0f) 241 fragmentSrc << "textureLod(texSampler, vtxTexCoords." << texCoordSwizzle << ", " << std::fixed << m_samplerLod << ")"; 242 else 243 fragmentSrc << "texture(texSampler, vtxTexCoords." << texCoordSwizzle << ")" << std::fixed; 244 245 fragmentSrc << " * vec4" << std::scientific << swizzledScale << " + vec4" << swizzledBias << ";\n" 246 << "}\n"; 247 248 sourceCollections.glslSources.add("tex_vert") << glu::VertexSource(vertexSrc.str()); 249 sourceCollections.glslSources.add("tex_frag") << glu::FragmentSource(fragmentSrc.str()); 250} 251 252TestInstance* ImageViewTest::createInstance (Context& context) const 253{ 254 return new ImageSamplingInstance(context, getImageSamplingInstanceParams(m_imageViewType, m_imageFormat, m_samplerLod, m_componentMapping, m_subresourceRange)); 255} 256 257std::string ImageViewTest::getGlslSamplerType (const tcu::TextureFormat& format, VkImageViewType type) 258{ 259 std::ostringstream samplerType; 260 261 if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER) 262 samplerType << "u"; 263 else if (tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER) 264 samplerType << "i"; 265 266 switch (type) 267 { 268 case VK_IMAGE_VIEW_TYPE_1D: 269 samplerType << "sampler1D"; 270 break; 271 272 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 273 samplerType << "sampler1DArray"; 274 break; 275 276 case VK_IMAGE_VIEW_TYPE_2D: 277 samplerType << "sampler2D"; 278 break; 279 280 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 281 samplerType << "sampler2DArray"; 282 break; 283 284 case VK_IMAGE_VIEW_TYPE_3D: 285 samplerType << "sampler3D"; 286 break; 287 288 case VK_IMAGE_VIEW_TYPE_CUBE: 289 samplerType << "samplerCube"; 290 break; 291 292 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 293 samplerType << "samplerCubeArray"; 294 break; 295 296 default: 297 DE_FATAL("Unknown image view type"); 298 break; 299 } 300 301 return samplerType.str(); 302} 303 304tcu::UVec2 ImageViewTest::getRenderSize (VkImageViewType viewType) 305{ 306 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D) 307 return tcu::UVec2(16u, 16u); 308 else 309 return tcu::UVec2(16u * 3u, 16u * 2u); 310} 311 312tcu::IVec3 ImageViewTest::getImageSize (VkImageViewType viewType) 313{ 314 switch (viewType) 315 { 316 case VK_IMAGE_VIEW_TYPE_1D: 317 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 318 return tcu::IVec3(16, 1, 1); 319 320 case VK_IMAGE_VIEW_TYPE_3D: 321 return tcu::IVec3(16); 322 323 default: 324 break; 325 } 326 327 return tcu::IVec3(16, 16, 1); 328} 329 330int ImageViewTest::getArraySize (VkImageViewType viewType) 331{ 332 switch (viewType) 333 { 334 case VK_IMAGE_VIEW_TYPE_3D: 335 return 1; 336 337 case VK_IMAGE_VIEW_TYPE_CUBE: 338 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 339 return 18; 340 341 default: 342 break; 343 } 344 345 return 6; 346} 347 348int ImageViewTest::getNumLevels (VkImageViewType viewType) 349{ 350 const tcu::IVec3 imageSize = getImageSize(viewType); 351 352 return deLog2Floor32(deMax32(imageSize.x(), deMax32(imageSize.y(), imageSize.z()))) + 1; 353} 354 355static std::string getFormatCaseName (const VkFormat format) 356{ 357 const std::string fullName = getFormatName(format); 358 359 DE_ASSERT(de::beginsWith(fullName, "VK_FORMAT_")); 360 361 return de::toLower(fullName.substr(10)); 362} 363 364static de::MovePtr<tcu::TestCaseGroup> createSubresourceRangeTests(tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, VkImageViewType viewType, VkFormat imageFormat) 365{ 366 struct TestCaseConfig 367 { 368 const char* name; 369 float samplerLod; 370 VkImageSubresourceRange subresourceRange; 371 }; 372 373 const deUint32 numLevels = ImageViewTest::getNumLevels(viewType); 374 const deUint32 arraySize = ImageViewTest::getArraySize(viewType); 375 const VkImageAspectFlags imageAspectFlags = VK_IMAGE_ASPECT_COLOR_BIT; 376 const VkComponentMapping componentMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 377 378 de::MovePtr<tcu::TestCaseGroup> rangeTests (new tcu::TestCaseGroup(testCtx, "subresource_range")); 379 380#define ADD_SUBRESOURCE_RANGE_TESTS(TEST_CASES) \ 381 do { \ 382 for (int configNdx = 0; configNdx < DE_LENGTH_OF_ARRAY(TEST_CASES); configNdx++) \ 383 { \ 384 const TestCaseConfig config = (TEST_CASES)[configNdx]; \ 385 rangeTests->addChild(new ImageViewTest(testCtx, config.name, \ 386 pipelineConstructionType,viewType, imageFormat, \ 387 config.samplerLod, componentMapping, \ 388 config.subresourceRange)); \ 389 } \ 390 } while (deGetFalse()) 391 392 if (viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY || viewType == VK_IMAGE_VIEW_TYPE_2D_ARRAY) 393 { 394 const TestCaseConfig mipLevelRangeCases[] = 395 { 396 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 397 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } }, 398 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } }, 399 }; 400 401 const TestCaseConfig arrayRangeCases[] = 402 { 403 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 404 { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, arraySize - 1u } }, 405 { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 4u } }, 406 { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 2u, 3u } }, 407 }; 408 409 const TestCaseConfig mipLevelAndArrayRangeCases[] = 410 { 411 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 412 { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 5u } }, 413 { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 1u, 5u } }, 414 415 { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 4u } }, 416 { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 4u } }, 417 418 { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 2u, 3u } }, 419 { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 2u, 3u } }, 420 }; 421 422 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] = 423 { 424 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 425 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } }, 426 { "base_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, VK_REMAINING_ARRAY_LAYERS } }, 427 { "lod_base_mip_level_base_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 2u, VK_REMAINING_ARRAY_LAYERS } }, 428 }; 429 430 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases); 431 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases); 432 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases); 433 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases); 434 } 435 else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY) 436 { 437 const TestCaseConfig mipLevelRangeCases[] = 438 { 439 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 440 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } }, 441 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } }, 442 }; 443 444 const TestCaseConfig arrayRangeCases[] = 445 { 446 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 447 { "base_array_layer", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, arraySize - 6u } }, 448 { "array_size", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, 6u } }, 449 { "array_base_and_size", 0.0f, { imageAspectFlags, 0u, numLevels, 12u, 6u } }, 450 }; 451 452 const TestCaseConfig mipLevelAndArrayRangeCases[] = 453 { 454 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 455 { "lod_base_mip_level_base_array_layer", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, arraySize - 6u } }, 456 { "lod_mip_levels_base_array_layer", 4.0f, { imageAspectFlags, 0u, 3u, 6u, arraySize - 6u } }, 457 458 { "lod_base_mip_level_array_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } }, 459 { "lod_mip_levels_array_size", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } }, 460 461 { "lod_base_mip_level_array_base_and_size", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 12u, 6u } }, 462 { "lod_mip_levels_array_base_and_size", 4.0f, { imageAspectFlags, 0u, 3u, 12u, 6u } }, 463 }; 464 465 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] = 466 { 467 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 468 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } }, 469 { "base_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, VK_REMAINING_ARRAY_LAYERS } }, 470 { "lod_base_mip_level_base_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 12u, VK_REMAINING_ARRAY_LAYERS } }, 471 }; 472 473 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases); 474 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases); 475 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases); 476 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases); 477 } 478 else if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_2D) 479 { 480 const TestCaseConfig mipLevelRangeCases[] = 481 { 482 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 483 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 1u } }, 484 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 1u } }, 485 }; 486 487 const TestCaseConfig arrayRangeCases[] = 488 { 489 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 490 { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 1u, 1u } }, 491 { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 1u, 1u } }, 492 }; 493 494 const TestCaseConfig mipLevelAndArrayRangeCases[] = 495 { 496 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 497 { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 1u, 1u } }, 498 { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } }, 499 500 { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 5u, 1u } }, 501 { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 1u, 1u } }, 502 }; 503 504 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] = 505 { 506 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 507 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, 1u } }, 508 { "array_layer_last_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 1u, VK_REMAINING_ARRAY_LAYERS } }, 509 { "lod_base_mip_level_array_layer_last_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, arraySize - 1u, VK_REMAINING_ARRAY_LAYERS } }, 510 }; 511 512 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases); 513 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases); 514 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases); 515 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases); 516 } 517 else if (viewType == VK_IMAGE_VIEW_TYPE_CUBE) 518 { 519 const TestCaseConfig mipLevelRangeCases[] = 520 { 521 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 522 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, 6u } }, 523 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, 6u } }, 524 }; 525 526 const TestCaseConfig arrayRangeCases[] = 527 { 528 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 529 { "array_layer_second", 0.0f, { imageAspectFlags, 0u, numLevels, 6u, 6u } }, 530 { "array_layer_last", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 6u, 6u } }, 531 }; 532 533 const TestCaseConfig mipLevelAndArrayRangeCases[] = 534 { 535 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 536 { "lod_base_mip_level_array_layer_second", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 6u, 6u } }, 537 { "lod_mip_levels_array_layer_second", 4.0f, { imageAspectFlags, 0u, 3u, 6u, 6u } }, 538 539 { "lod_base_mip_level_array_layer_last", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, arraySize - 6u, 6u } }, 540 { "lod_mip_levels_array_layer_last", 4.0f, { imageAspectFlags, 0u, 3u, arraySize - 6u, 6u } }, 541 }; 542 543 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] = 544 { 545 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 546 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, 6u } }, 547 { "array_layer_last_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, arraySize - 6u, VK_REMAINING_ARRAY_LAYERS } }, 548 { "lod_base_mip_level_array_layer_last_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, arraySize - 6u, VK_REMAINING_ARRAY_LAYERS } }, 549 }; 550 551 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases); 552 ADD_SUBRESOURCE_RANGE_TESTS(arrayRangeCases); 553 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRangeCases); 554 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases); 555 } 556 else if (viewType == VK_IMAGE_VIEW_TYPE_3D) 557 { 558 const TestCaseConfig mipLevelRangeCases[] = 559 { 560 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 561 { "lod_base_mip_level", 0.0f, { imageAspectFlags, 2u, numLevels - 2u, 0u, arraySize } }, 562 { "lod_mip_levels", 4.0f, { imageAspectFlags, 0u, 3u, 0u, arraySize } }, 563 }; 564 565 const TestCaseConfig mipLevelAndArrayRemainingRangeCases[] = 566 { 567 // name samplerLod subresourceRange (aspectMask, baseMipLevel, mipLevels, baseArrayLayer, arraySize) 568 { "lod_base_mip_level_remaining_levels", 0.0f, { imageAspectFlags, 1u, VK_REMAINING_MIP_LEVELS, 0u, arraySize } }, 569 { "single_array_layer_remaining_layers", 0.0f, { imageAspectFlags, 0u, numLevels, 0u, VK_REMAINING_ARRAY_LAYERS } }, 570 { "lod_base_mip_level_single_array_layer_remaining_levels_and_layers", 0.0f, { imageAspectFlags, 2u, VK_REMAINING_MIP_LEVELS, 0u, VK_REMAINING_ARRAY_LAYERS } }, 571 }; 572 573 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelRangeCases); 574 ADD_SUBRESOURCE_RANGE_TESTS(mipLevelAndArrayRemainingRangeCases); 575 } 576 577#undef ADD_SUBRESOURCE_RANGE_TESTS 578 579 return rangeTests; 580} 581 582static std::vector<VkComponentMapping> getComponentMappingPermutations (const VkComponentMapping& componentMapping) 583{ 584 std::vector<VkComponentMapping> mappings; 585 586 const VkComponentSwizzle channelSwizzles[4] = { componentMapping.r, componentMapping.g, componentMapping.b, componentMapping.a }; 587 588 // Rearranges the channels by shifting their positions. 589 for (int firstChannelNdx = 0; firstChannelNdx < 4; firstChannelNdx++) 590 { 591 VkComponentSwizzle currentChannel[4]; 592 593 for (int channelNdx = 0; channelNdx < 4; channelNdx++) 594 currentChannel[channelNdx] = channelSwizzles[(firstChannelNdx + channelNdx) % 4]; 595 596 const VkComponentMapping mappingPermutation = 597 { 598 currentChannel[0], 599 currentChannel[1], 600 currentChannel[2], 601 currentChannel[3] 602 }; 603 604 mappings.push_back(mappingPermutation); 605 } 606 607 return mappings; 608} 609 610static std::string getComponentSwizzleCaseName (VkComponentSwizzle componentSwizzle) 611{ 612 const std::string fullName = getComponentSwizzleName(componentSwizzle); 613 614 DE_ASSERT(de::beginsWith(fullName, "VK_COMPONENT_SWIZZLE_")); 615 616 return de::toLower(fullName.substr(21)); 617} 618 619static std::string getComponentMappingCaseName (const VkComponentMapping& componentMapping) 620{ 621 std::ostringstream name; 622 623 name << getComponentSwizzleCaseName(componentMapping.r) << "_" 624 << getComponentSwizzleCaseName(componentMapping.g) << "_" 625 << getComponentSwizzleCaseName(componentMapping.b) << "_" 626 << getComponentSwizzleCaseName(componentMapping.a); 627 628 return name.str(); 629} 630 631static de::MovePtr<tcu::TestCaseGroup> createComponentSwizzleTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType, VkImageViewType viewType, VkFormat imageFormat) 632{ 633 deUint32 arraySize = 0; 634 635 switch (viewType) 636 { 637 case VK_IMAGE_VIEW_TYPE_1D: 638 case VK_IMAGE_VIEW_TYPE_2D: 639 case VK_IMAGE_VIEW_TYPE_3D: 640 arraySize = 1; 641 break; 642 643 case VK_IMAGE_VIEW_TYPE_CUBE: 644 arraySize = 6; 645 break; 646 647 case VK_IMAGE_VIEW_TYPE_1D_ARRAY: 648 case VK_IMAGE_VIEW_TYPE_2D_ARRAY: 649 case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY: 650 arraySize = ImageViewTest::getArraySize(viewType); 651 break; 652 653 default: 654 break; 655 } 656 657 const VkImageSubresourceRange subresourceRange = 658 { 659 VK_IMAGE_ASPECT_COLOR_BIT, // VkImageAspectFlags aspectMask; 660 0u, // deUint32 baseMipLevel; 661 (deUint32)ImageViewTest::getNumLevels(viewType), // deUint32 mipLevels; 662 0u, // deUint32 baseArrayLayer; 663 arraySize, // deUint32 arraySize; 664 }; 665 666 const VkComponentMapping baseMapping = { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }; 667 const std::vector<VkComponentMapping> componentMappings = getComponentMappingPermutations(baseMapping); 668 de::MovePtr<tcu::TestCaseGroup> swizzleTests (new tcu::TestCaseGroup(testCtx, "component_swizzle")); 669 670 for (size_t mappingNdx = 0; mappingNdx < componentMappings.size(); mappingNdx++) 671 { 672 swizzleTests->addChild(new ImageViewTest(testCtx, 673 getComponentMappingCaseName(componentMappings[mappingNdx]).c_str(), 674 pipelineConstructionType, 675 viewType, 676 imageFormat, 677 0.0f, 678 componentMappings[mappingNdx], 679 subresourceRange)); 680 } 681 682 return swizzleTests; 683} 684 685} // anonymous 686 687tcu::TestCaseGroup* createImageViewTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 688{ 689 const struct 690 { 691 VkImageViewType type; 692 const char* name; 693 } 694 imageViewTypes[] = 695 { 696 { VK_IMAGE_VIEW_TYPE_1D, "1d" }, 697 { VK_IMAGE_VIEW_TYPE_1D_ARRAY, "1d_array" }, 698 { VK_IMAGE_VIEW_TYPE_2D, "2d" }, 699 { VK_IMAGE_VIEW_TYPE_2D_ARRAY, "2d_array" }, 700 { VK_IMAGE_VIEW_TYPE_3D, "3d" }, 701 { VK_IMAGE_VIEW_TYPE_CUBE, "cube" }, 702 { VK_IMAGE_VIEW_TYPE_CUBE_ARRAY, "cube_array" } 703 }; 704 705 const VkFormat formats[] = 706 { 707 VK_FORMAT_R4G4_UNORM_PACK8, 708 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 709 VK_FORMAT_R5G6B5_UNORM_PACK16, 710 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 711#ifndef CTS_USES_VULKANSC 712 VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR, 713#endif // CTS_USES_VULKANSC 714 VK_FORMAT_R8_UNORM, 715 VK_FORMAT_R8_SNORM, 716 VK_FORMAT_R8_USCALED, 717 VK_FORMAT_R8_SSCALED, 718 VK_FORMAT_R8_UINT, 719 VK_FORMAT_R8_SINT, 720 VK_FORMAT_R8_SRGB, 721#ifndef CTS_USES_VULKANSC 722 VK_FORMAT_A8_UNORM_KHR, 723#endif // CTS_USES_VULKANSC 724 VK_FORMAT_R8G8_UNORM, 725 VK_FORMAT_R8G8_SNORM, 726 VK_FORMAT_R8G8_USCALED, 727 VK_FORMAT_R8G8_SSCALED, 728 VK_FORMAT_R8G8_UINT, 729 VK_FORMAT_R8G8_SINT, 730 VK_FORMAT_R8G8_SRGB, 731 VK_FORMAT_R8G8B8_UNORM, 732 VK_FORMAT_R8G8B8_SNORM, 733 VK_FORMAT_R8G8B8_USCALED, 734 VK_FORMAT_R8G8B8_SSCALED, 735 VK_FORMAT_R8G8B8_UINT, 736 VK_FORMAT_R8G8B8_SINT, 737 VK_FORMAT_R8G8B8_SRGB, 738 VK_FORMAT_B8G8R8_UNORM, 739 VK_FORMAT_B8G8R8_SNORM, 740 VK_FORMAT_B8G8R8_USCALED, 741 VK_FORMAT_B8G8R8_SSCALED, 742 VK_FORMAT_B8G8R8_UINT, 743 VK_FORMAT_B8G8R8_SINT, 744 VK_FORMAT_B8G8R8_SRGB, 745 VK_FORMAT_R8G8B8A8_UNORM, 746 VK_FORMAT_R8G8B8A8_SNORM, 747 VK_FORMAT_R8G8B8A8_USCALED, 748 VK_FORMAT_R8G8B8A8_SSCALED, 749 VK_FORMAT_R8G8B8A8_UINT, 750 VK_FORMAT_R8G8B8A8_SINT, 751 VK_FORMAT_R8G8B8A8_SRGB, 752 VK_FORMAT_B8G8R8A8_UNORM, 753 VK_FORMAT_B8G8R8A8_SNORM, 754 VK_FORMAT_B8G8R8A8_USCALED, 755 VK_FORMAT_B8G8R8A8_SSCALED, 756 VK_FORMAT_B8G8R8A8_UINT, 757 VK_FORMAT_B8G8R8A8_SINT, 758 VK_FORMAT_B8G8R8A8_SRGB, 759 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 760 VK_FORMAT_A2R10G10B10_UINT_PACK32, 761 VK_FORMAT_A2B10G10R10_USCALED_PACK32, 762 VK_FORMAT_R16_UNORM, 763 VK_FORMAT_R16_SNORM, 764 VK_FORMAT_R16_USCALED, 765 VK_FORMAT_R16_SSCALED, 766 VK_FORMAT_R16_UINT, 767 VK_FORMAT_R16_SINT, 768 VK_FORMAT_R16_SFLOAT, 769 VK_FORMAT_R16G16_UNORM, 770 VK_FORMAT_R16G16_SNORM, 771 VK_FORMAT_R16G16_USCALED, 772 VK_FORMAT_R16G16_SSCALED, 773 VK_FORMAT_R16G16_UINT, 774 VK_FORMAT_R16G16_SINT, 775 VK_FORMAT_R16G16_SFLOAT, 776 VK_FORMAT_R16G16B16_UNORM, 777 VK_FORMAT_R16G16B16_SNORM, 778 VK_FORMAT_R16G16B16_USCALED, 779 VK_FORMAT_R16G16B16_SSCALED, 780 VK_FORMAT_R16G16B16_UINT, 781 VK_FORMAT_R16G16B16_SINT, 782 VK_FORMAT_R16G16B16_SFLOAT, 783 VK_FORMAT_R16G16B16A16_UNORM, 784 VK_FORMAT_R16G16B16A16_SNORM, 785 VK_FORMAT_R16G16B16A16_USCALED, 786 VK_FORMAT_R16G16B16A16_SSCALED, 787 VK_FORMAT_R16G16B16A16_UINT, 788 VK_FORMAT_R16G16B16A16_SINT, 789 VK_FORMAT_R16G16B16A16_SFLOAT, 790 VK_FORMAT_R32_UINT, 791 VK_FORMAT_R32_SINT, 792 VK_FORMAT_R32_SFLOAT, 793 VK_FORMAT_R32G32_UINT, 794 VK_FORMAT_R32G32_SINT, 795 VK_FORMAT_R32G32_SFLOAT, 796 VK_FORMAT_R32G32B32_UINT, 797 VK_FORMAT_R32G32B32_SINT, 798 VK_FORMAT_R32G32B32_SFLOAT, 799 VK_FORMAT_R32G32B32A32_UINT, 800 VK_FORMAT_R32G32B32A32_SINT, 801 VK_FORMAT_R32G32B32A32_SFLOAT, 802 VK_FORMAT_B10G11R11_UFLOAT_PACK32, 803 VK_FORMAT_E5B9G9R9_UFLOAT_PACK32, 804 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 805 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 806 VK_FORMAT_A4R4G4B4_UNORM_PACK16_EXT, 807 VK_FORMAT_A4B4G4R4_UNORM_PACK16_EXT, 808 VK_FORMAT_R10X6G10X6B10X6A10X6_UNORM_4PACK16, 809 810 // Compressed formats 811 VK_FORMAT_ETC2_R8G8B8_UNORM_BLOCK, 812 VK_FORMAT_ETC2_R8G8B8_SRGB_BLOCK, 813 VK_FORMAT_ETC2_R8G8B8A1_UNORM_BLOCK, 814 VK_FORMAT_ETC2_R8G8B8A1_SRGB_BLOCK, 815 VK_FORMAT_ETC2_R8G8B8A8_UNORM_BLOCK, 816 VK_FORMAT_ETC2_R8G8B8A8_SRGB_BLOCK, 817 VK_FORMAT_EAC_R11_UNORM_BLOCK, 818 VK_FORMAT_EAC_R11_SNORM_BLOCK, 819 VK_FORMAT_EAC_R11G11_UNORM_BLOCK, 820 VK_FORMAT_EAC_R11G11_SNORM_BLOCK, 821 VK_FORMAT_ASTC_4x4_UNORM_BLOCK, 822 VK_FORMAT_ASTC_4x4_SRGB_BLOCK, 823 VK_FORMAT_ASTC_5x4_UNORM_BLOCK, 824 VK_FORMAT_ASTC_5x4_SRGB_BLOCK, 825 VK_FORMAT_ASTC_5x5_UNORM_BLOCK, 826 VK_FORMAT_ASTC_5x5_SRGB_BLOCK, 827 VK_FORMAT_ASTC_6x5_UNORM_BLOCK, 828 VK_FORMAT_ASTC_6x5_SRGB_BLOCK, 829 VK_FORMAT_ASTC_6x6_UNORM_BLOCK, 830 VK_FORMAT_ASTC_6x6_SRGB_BLOCK, 831 VK_FORMAT_ASTC_8x5_UNORM_BLOCK, 832 VK_FORMAT_ASTC_8x5_SRGB_BLOCK, 833 VK_FORMAT_ASTC_8x6_UNORM_BLOCK, 834 VK_FORMAT_ASTC_8x6_SRGB_BLOCK, 835 VK_FORMAT_ASTC_8x8_UNORM_BLOCK, 836 VK_FORMAT_ASTC_8x8_SRGB_BLOCK, 837 VK_FORMAT_ASTC_10x5_UNORM_BLOCK, 838 VK_FORMAT_ASTC_10x5_SRGB_BLOCK, 839 VK_FORMAT_ASTC_10x6_UNORM_BLOCK, 840 VK_FORMAT_ASTC_10x6_SRGB_BLOCK, 841 VK_FORMAT_ASTC_10x8_UNORM_BLOCK, 842 VK_FORMAT_ASTC_10x8_SRGB_BLOCK, 843 VK_FORMAT_ASTC_10x10_UNORM_BLOCK, 844 VK_FORMAT_ASTC_10x10_SRGB_BLOCK, 845 VK_FORMAT_ASTC_12x10_UNORM_BLOCK, 846 VK_FORMAT_ASTC_12x10_SRGB_BLOCK, 847 VK_FORMAT_ASTC_12x12_UNORM_BLOCK, 848 VK_FORMAT_ASTC_12x12_SRGB_BLOCK, 849 VK_FORMAT_BC5_UNORM_BLOCK, 850 VK_FORMAT_BC5_SNORM_BLOCK, 851 }; 852 853 de::MovePtr<tcu::TestCaseGroup> imageTests (new tcu::TestCaseGroup(testCtx, "image_view")); 854 de::MovePtr<tcu::TestCaseGroup> viewTypeTests (new tcu::TestCaseGroup(testCtx, "view_type")); 855 856 for (int viewTypeNdx = 0; viewTypeNdx < DE_LENGTH_OF_ARRAY(imageViewTypes); viewTypeNdx++) 857 { 858 const VkImageViewType viewType = imageViewTypes[viewTypeNdx].type; 859 de::MovePtr<tcu::TestCaseGroup> viewTypeGroup (new tcu::TestCaseGroup(testCtx, imageViewTypes[viewTypeNdx].name)); 860 // Uses samplable formats 861 de::MovePtr<tcu::TestCaseGroup> formatTests (new tcu::TestCaseGroup(testCtx, "format")); 862 863 for (size_t formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++) 864 { 865 const VkFormat format = formats[formatNdx]; 866 867 if (isCompressedFormat(format)) 868 { 869 // Do not use compressed formats with 1D and 1D array textures. 870 if (viewType == VK_IMAGE_VIEW_TYPE_1D || viewType == VK_IMAGE_VIEW_TYPE_1D_ARRAY) 871 break; 872 } 873 874 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, 875 getFormatCaseName(format).c_str(), 876 (std::string("Samples a texture of format ") + getFormatName(format)).c_str())); 877 878 de::MovePtr<tcu::TestCaseGroup> subresourceRangeTests = createSubresourceRangeTests(testCtx, pipelineConstructionType, viewType, format); 879 de::MovePtr<tcu::TestCaseGroup> componentSwizzleTests = createComponentSwizzleTests(testCtx, pipelineConstructionType, viewType, format); 880 881 formatGroup->addChild(componentSwizzleTests.release()); 882 formatGroup->addChild(subresourceRangeTests.release()); 883 formatTests->addChild(formatGroup.release()); 884 } 885 886 viewTypeGroup->addChild(formatTests.release()); 887 viewTypeTests->addChild(viewTypeGroup.release()); 888 } 889 890 imageTests->addChild(viewTypeTests.release()); 891 892 return imageTests.release(); 893} 894 895} // pipeline 896} // vkt 897