1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 5 * Copyright (c) 2021 The Khronos Group Inc. 6 * Copyright (c) 2021 Valve Corporation. 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 Border color swizzle tests 25 *//*--------------------------------------------------------------------*/ 26#include "vktPipelineSamplerBorderSwizzleTests.hpp" 27#include "vktPipelineImageUtil.hpp" 28 29#include "vkImageUtil.hpp" 30#include "vkQueryUtil.hpp" 31#include "vkImageWithMemory.hpp" 32#include "vkTypeUtil.hpp" 33#include "vkObjUtil.hpp" 34#include "vkBuilderUtil.hpp" 35#include "vkCmdUtil.hpp" 36#include "vkBarrierUtil.hpp" 37 38#include "tcuMaybe.hpp" 39#include "tcuTextureUtil.hpp" 40#include "tcuVectorUtil.hpp" 41#include "tcuFloat.hpp" 42 43#include "deRandom.hpp" 44 45#include <string> 46#include <sstream> 47#include <array> 48#include <cstring> 49#include <algorithm> 50 51namespace vkt 52{ 53namespace pipeline 54{ 55 56namespace 57{ 58 59using namespace vk; 60 61// Returns true if the mapping doesn't alter each component. 62bool isIdentitySwizzle (const VkComponentMapping& mapping) 63{ 64 return ( 65 (mapping.r == VK_COMPONENT_SWIZZLE_R || mapping.r == VK_COMPONENT_SWIZZLE_IDENTITY) && 66 (mapping.g == VK_COMPONENT_SWIZZLE_G || mapping.g == VK_COMPONENT_SWIZZLE_IDENTITY) && 67 (mapping.b == VK_COMPONENT_SWIZZLE_B || mapping.b == VK_COMPONENT_SWIZZLE_IDENTITY) && 68 (mapping.a == VK_COMPONENT_SWIZZLE_A || mapping.a == VK_COMPONENT_SWIZZLE_IDENTITY) 69 ); 70} 71 72struct TestParams 73{ 74 PipelineConstructionType pipelineConstructionType; 75 VkFormat textureFormat; 76 VkClearColorValue textureColor; 77 VkClearDepthStencilValue textureDepthStencilValue; 78 VkComponentMapping componentMapping; 79 VkBorderColor borderColor; 80 tcu::Maybe<int> componentGather; 81 bool useSamplerSwizzleHint; 82 83 // Pseudorandom elements. 84 tcu::Vec2 textureCoordinates; 85 tcu::Maybe<VkClearColorValue> customBorderColor; 86 bool useStencilAspect; 87 88 bool isCustom (void) const 89 { 90 return (borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT || borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT); 91 } 92 93 bool isOpaqueBlack (void) const 94 { 95 return (borderColor == VK_BORDER_COLOR_INT_OPAQUE_BLACK || borderColor == VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK); 96 } 97 98 bool isIdentity (void) const 99 { 100 return isIdentitySwizzle(componentMapping); 101 } 102}; 103 104struct SpecConstants 105{ 106 float u; 107 float v; 108 deInt32 gatherFlag; 109 //deInt32 gatherComp; 110}; 111 112class BorderSwizzleCase : public vkt::TestCase 113{ 114public: 115 BorderSwizzleCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params); 116 virtual ~BorderSwizzleCase (void) {} 117 118 virtual void initPrograms (vk::SourceCollections& programCollection) const; 119 virtual TestInstance* createInstance (Context& context) const; 120 virtual void checkSupport (Context& context) const; 121 122protected: 123 TestParams m_params; 124}; 125 126class BorderSwizzleInstance : public vkt::TestInstance 127{ 128public: 129 BorderSwizzleInstance (Context& context, const TestParams ¶ms); 130 virtual ~BorderSwizzleInstance (void) {} 131 132 VkExtent3D getImageExtent (void) const; 133 virtual tcu::TestStatus iterate (void); 134 135protected: 136 TestParams m_params; 137}; 138 139BorderSwizzleCase::BorderSwizzleCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params) 140 : vkt::TestCase (testCtx, name) 141 , m_params (params) 142{ 143} 144 145void BorderSwizzleCase::checkSupport (Context& context) const 146{ 147 const auto& vki = context.getInstanceInterface(); 148 const auto physicalDevice = context.getPhysicalDevice(); 149 VkImageFormatProperties formatProperties; 150 151#ifndef CTS_USES_VULKANSC 152 if (m_params.textureFormat == VK_FORMAT_A8_UNORM_KHR || m_params.textureFormat == VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR) 153 context.requireDeviceFunctionality("VK_KHR_maintenance5"); 154#endif // CTS_USES_VULKANSC 155 156 const auto result = vki.getPhysicalDeviceImageFormatProperties( 157 physicalDevice, m_params.textureFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, (VK_IMAGE_USAGE_SAMPLED_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT), 0u, &formatProperties); 158 159 if (result != VK_SUCCESS) 160 { 161 if (result == VK_ERROR_FORMAT_NOT_SUPPORTED) 162 TCU_THROW(NotSupportedError, "Format not supported for sampling"); 163 TCU_FAIL("vkGetPhysicalDeviceImageFormatProperties returned " + de::toString(result)); 164 } 165 166 const auto& borderColorFeatures = context.getCustomBorderColorFeaturesEXT(); 167 const auto& borderSwizzleFeatures = context.getBorderColorSwizzleFeaturesEXT(); 168 const bool identity = m_params.isIdentity(); 169 170 if (m_params.useSamplerSwizzleHint) 171 context.requireDeviceFunctionality("VK_EXT_border_color_swizzle"); 172 173 // VK_COMPONENT_SWIZZLE_ONE is undefined when used with combined depth stencil formats, unless the maintenance5 property 'depthStencilSwizzleOneSupport' is supported 174 // For depth/stencil formats, VK_COMPONENT_SWIZZLE_A is aliased to VK_COMPONENT_SWIZZLE_ONE within this test group. 175 if (isCombinedDepthStencilType(mapVkFormat(m_params.textureFormat).type) && ( 176 (m_params.componentMapping.r == VK_COMPONENT_SWIZZLE_ONE) || (m_params.componentMapping.r == VK_COMPONENT_SWIZZLE_A) || 177 (m_params.componentMapping.g == VK_COMPONENT_SWIZZLE_ONE) || (m_params.componentMapping.g == VK_COMPONENT_SWIZZLE_A) || 178 (m_params.componentMapping.b == VK_COMPONENT_SWIZZLE_ONE) || (m_params.componentMapping.b == VK_COMPONENT_SWIZZLE_A) || 179 (m_params.componentMapping.a == VK_COMPONENT_SWIZZLE_ONE) || (m_params.componentMapping.a == VK_COMPONENT_SWIZZLE_A) 180 )) 181 { 182 context.requireDeviceFunctionality("VK_KHR_maintenance5"); 183 184 if (!context.getMaintenance5Properties().depthStencilSwizzleOneSupport) 185 TCU_THROW(NotSupportedError, "Swizzle results are undefined without depthStencilSwizzleOneSupport"); 186 } 187 188 checkPipelineConstructionRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), m_params.pipelineConstructionType); 189 190 if (m_params.isCustom()) 191 { 192 if (!borderColorFeatures.customBorderColors) 193 TCU_THROW(NotSupportedError, "Custom border colors not supported"); 194 195 if (!identity) 196 { 197 if (!borderSwizzleFeatures.borderColorSwizzle) 198 TCU_THROW(NotSupportedError, "Custom border color with non-identity swizzle not supported"); 199 200 if (!m_params.useSamplerSwizzleHint && !borderSwizzleFeatures.borderColorSwizzleFromImage) 201 TCU_THROW(NotSupportedError, "Custom border color with non-identity swizzle not supported without specifying sampler border mapping"); 202 } 203 } 204 else if (m_params.isOpaqueBlack()) 205 { 206 if (!identity) 207 { 208 if (!borderSwizzleFeatures.borderColorSwizzle) 209 TCU_THROW(NotSupportedError, "Opaque black with non-identity swizzle not supported"); 210 211 if (!m_params.useSamplerSwizzleHint && !borderSwizzleFeatures.borderColorSwizzleFromImage) 212 TCU_THROW(NotSupportedError, "Opaque black with non-identity swizzle not supported without specifying sampler border mapping"); 213 } 214 } 215} 216 217enum class FormatType 218{ 219 SIGNED_INT = 0, 220 UNSIGNED_INT, 221 FLOAT, 222}; 223 224FormatType getFormatType (VkFormat format, bool useStencil) 225{ 226 if (isIntFormat(format)) 227 return FormatType::SIGNED_INT; 228 229 if (isUintFormat(format) || useStencil) 230 return FormatType::UNSIGNED_INT; 231 232 return FormatType::FLOAT; 233} 234 235// Output color attachment format will vary slightly with the chosen texture format to accomodate different clear colors. 236VkFormat getColorAttachmentFormat (VkFormat textureFormat, bool useStencil) 237{ 238 const auto formatType = getFormatType(textureFormat, useStencil); 239 240 if (formatType == FormatType::SIGNED_INT) 241 return VK_FORMAT_R32G32B32A32_SINT; 242 243 if (formatType == FormatType::UNSIGNED_INT) 244 return VK_FORMAT_R32G32B32A32_UINT; 245 246 return VK_FORMAT_R32G32B32A32_SFLOAT; 247} 248 249void BorderSwizzleCase::initPrograms (vk::SourceCollections& programCollection) const 250{ 251 std::ostringstream vert; 252 vert 253 << "#version 450\n" 254 << "\n" 255 << "void main()\n" 256 << "{\n" 257 // Full-screen clockwise triangle strip with 4 vertices. 258 << " const float x = (-1.0+2.0*((gl_VertexIndex & 2)>>1));\n" 259 << " const float y = ( 1.0-2.0* (gl_VertexIndex % 2));\n" 260 << " gl_Position = vec4(x, y, 0.0, 1.0);\n" 261 << "}\n" 262 ; 263 264 const auto formatType = getFormatType(m_params.textureFormat, m_params.useStencilAspect); 265 266 std::string prefix; 267 if (formatType == FormatType::SIGNED_INT) 268 prefix = "i"; 269 else if (formatType == FormatType::UNSIGNED_INT) 270 prefix = "u"; 271 272 const std::string samplerType = prefix + "sampler2D"; 273 const std::string outColorType = prefix + "vec4"; 274 // Note: glslang will complain if the gather component is not a compile-time constant. 275 const int gatherComp = (m_params.componentGather ? m_params.componentGather.get() : 0); 276 277 // Note the spec constants here should match the SpecConstants structure. 278 std::ostringstream frag; 279 frag 280 << "#version 450\n" 281 << "\n" 282 << "layout (constant_id=0) const float u = 0.0f;\n" 283 << "layout (constant_id=1) const float v = 0.0f;\n" 284 << "layout (constant_id=2) const int gatherFlag = 0;\n" 285 //<< "layout (constant_id=3) const int gatherComp = 0;\n" 286 << "\n" 287 << "layout (set=0, binding=0) uniform " << samplerType << " texSampler;\n" 288 << "\n" 289 << "layout (location=0) out " << outColorType << " colorOut;\n" 290 << "\n" 291 << "void main()\n" 292 << "{\n" 293 << " const vec2 coords = vec2(u, v);\n" 294 << "\n" 295 << " if (gatherFlag != 0)\n" 296 << " {\n" 297 << " colorOut = textureGather(texSampler, coords, " << gatherComp << ");\n" 298 << " }\n" 299 << " else\n" 300 << " {\n" 301 << " colorOut = texture(texSampler, coords);\n" 302 << " }\n" 303 << "}\n" 304 ; 305 306 programCollection.glslSources.add("vert") << glu::VertexSource(vert.str()); 307 programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str()); 308} 309 310TestInstance* BorderSwizzleCase::createInstance (Context& context) const 311{ 312 return new BorderSwizzleInstance(context, m_params); 313} 314 315BorderSwizzleInstance::BorderSwizzleInstance (Context& context, const TestParams ¶ms) 316 : vkt::TestInstance (context) 317 , m_params (params) 318{} 319 320VkExtent3D BorderSwizzleInstance::getImageExtent (void) const 321{ 322 return makeExtent3D(16u, 16u, 1u); 323} 324 325// Reinterprets the exponent and mantissa in the floating point number as an integer. 326// Function copied from vktApiImageClearingTests.cpp but changed return type to deUint64. 327deUint64 calcFloatDiff (float a, float b) 328{ 329 const int asign = tcu::Float32(a).sign(); 330 const int bsign = tcu::Float32(a).sign(); 331 332 const deUint32 avalue = (tcu::Float32(a).bits() & ((0x1u << 31u) - 1u)); 333 const deUint32 bvalue = (tcu::Float32(b).bits() & ((0x1u << 31u) - 1u)); 334 335 if (asign != bsign) 336 return avalue + bvalue + 1u; 337 else if (avalue < bvalue) 338 return bvalue - avalue; 339 else 340 return avalue - bvalue; 341} 342 343// Convert VkComponentMapping to an array of 4 VkComponentSwizzle elements. 344tcu::Vector<VkComponentSwizzle, 4> makeComponentSwizzleVec(const VkComponentMapping& mapping) 345{ 346 const tcu::Vector<VkComponentSwizzle, 4> result = {{ mapping.r, mapping.g, mapping.b, mapping.a }}; 347 return result; 348} 349 350// Apply swizzling to an array of 4 elements. 351template <typename T> 352tcu::Vector<T, 4> applySwizzle (const tcu::Vector<T, 4>& orig, const VkComponentMapping& mapping) 353{ 354 const auto swizzles = makeComponentSwizzleVec(mapping); 355 tcu::Vector<T, 4> result; 356 357 for (int i = 0; i < decltype(swizzles)::SIZE; ++i) 358 { 359 const auto cs = swizzles[i]; 360 DE_ASSERT(cs >= VK_COMPONENT_SWIZZLE_IDENTITY && cs <= VK_COMPONENT_SWIZZLE_A); 361 362 if (cs == VK_COMPONENT_SWIZZLE_IDENTITY) 363 result[i] = orig[i]; 364 else if (cs == VK_COMPONENT_SWIZZLE_ZERO) 365 result[i] = static_cast<T>(0); 366 else if (cs == VK_COMPONENT_SWIZZLE_ONE) 367 result[i] = static_cast<T>(1); 368 else 369 result[i] = orig[cs - VK_COMPONENT_SWIZZLE_R]; 370 } 371 372 return result; 373} 374 375// Apply gathering to an array of 4 elements. 376template <typename T> 377tcu::Vector<T, 4> applyGather (const tcu::Vector<T, 4>& orig, int compNum) 378{ 379 tcu::Vector<T, 4> result; 380 381 for (int i = 0; i < decltype(result)::SIZE; ++i) 382 result[i] = orig[compNum]; 383 384 return result; 385} 386 387// Transforms an input border color, once expanded, to the expected output color. 388template <typename T> 389tcu::Vector<T, 4> getExpectedColor (const tcu::Vector<T, 4>& color, const TestParams& params) 390{ 391 tcu::Vector<T, 4> result = color; 392 393 result = applySwizzle(result, params.componentMapping); 394 395 if (params.componentGather) 396 result = applyGather(result, *params.componentGather); 397 398 return result; 399} 400 401// Transforms an input border color to the expected output color. 402// Uses the proper union member depending on the test parameters and takes into account "Conversion to RGBA" from the spec. 403VkClearColorValue getExpectedColor (const VkClearColorValue& color, const TestParams& params) 404{ 405 const auto tcuFormat = mapVkFormat(params.textureFormat); 406 const auto numComp = tcu::getNumUsedChannels(tcuFormat.order); 407 const auto formatType = getFormatType(params.textureFormat, params.useStencilAspect); 408 VkClearColorValue result; 409 410 DE_ASSERT(numComp >= 0 && numComp <= 4); 411 412 if (tcu::hasDepthComponent(tcuFormat.order) || tcu::hasStencilComponent(tcuFormat.order)) 413 { 414 if (params.useStencilAspect) 415 { 416 tcu::UVec4 borderColor (0u, 0u, 0u, 1u); 417 borderColor[0] = color.uint32[0]; 418 const auto expected = getExpectedColor(borderColor, params); 419 420 for (int i = 0; i < decltype(expected)::SIZE; ++i) 421 result.uint32[i] = expected[i]; 422 } 423 else 424 { 425 tcu::Vec4 borderColor (0.0f, 0.0f, 0.0f, 1.0f); 426 borderColor[0] = color.float32[0]; 427 428 const auto expected = getExpectedColor(borderColor, params); 429 for (int i = 0; i < decltype(expected)::SIZE; ++i) 430 result.float32[i] = expected[i]; 431 } 432 } 433 else if (formatType == FormatType::UNSIGNED_INT) 434 { 435 tcu::UVec4 borderColor (0u, 0u, 0u, 0u); 436 437 for (int i = 0; i < numComp; ++i) 438 borderColor[i] = color.uint32[i]; 439 440 if (numComp < 4) 441 borderColor[3] = 1u; 442 443 const auto expected = getExpectedColor(borderColor, params); 444 445 for (int i = 0; i < decltype(expected)::SIZE; ++i) 446 result.uint32[i] = expected[i]; 447 } 448 else if (formatType == FormatType::SIGNED_INT) 449 { 450 tcu::IVec4 borderColor (0, 0, 0, 0); 451 452 for (int i = 0; i < numComp; ++i) 453 borderColor[i] = color.int32[i]; 454 455 if (numComp < 4) 456 borderColor[3] = 1; 457 458 const auto expected = getExpectedColor(borderColor, params); 459 460 for (int i = 0; i < decltype(expected)::SIZE; ++i) 461 result.int32[i] = expected[i]; 462 } 463 else 464 { 465 DE_ASSERT(formatType == FormatType::FLOAT); 466 467 tcu::Vec4 borderColor (.0f, .0f, .0f, 1.f); 468 469#ifndef CTS_USES_VULKANSC 470 if (params.textureFormat == VK_FORMAT_A8_UNORM_KHR) 471 { 472 // This one is a bit special compared to others we test. Single component alpha format borders use [0,0,0,Ba] as the 473 // border texel components after replacing (Ba being the border alpha component). 474 borderColor[3] = color.float32[3]; 475 } 476 else 477#endif // CTS_USES_VULKANSC 478 { 479 // Other formats use the first color components from the border, and are expanded to 4 components by filling missing 480 // components with zero and the alpha component with 1. 481 for (int i = 0; i < numComp; ++i) 482 borderColor[i] = color.float32[i]; 483 } 484 485 const auto expected = getExpectedColor(borderColor, params); 486 487 for (int i = 0; i < decltype(expected)::SIZE; ++i) 488 result.float32[i] = expected[i]; 489 } 490 491 return result; 492} 493 494// Compare color buffer to the expected border color. 495// 496// This method was copied from vktApiImageClearingTests.cpp and adapted to this use case: 497// 498// * Taking into account the texture format instead of the color buffer format when calculating acceptable thresholds. 499// * Applying swizzles and gathering to said thresholds. 500// * Making thresholds more strict for components that do not come from custom borders. 501// * Checking the full image in a single pass. 502// 503// The color buffer format is supposed to be at least as precise as the texture format. 504bool comparePixelToColorClearValue (const TestParams& params, 505 const tcu::ConstPixelBufferAccess& access, 506 const tcu::TextureFormat& textureFormat_, 507 const VkClearColorValue& ref, 508 std::string& stringResult) 509{ 510 const auto bufferFormat = access.getFormat(); 511 tcu::TextureFormat textureFormat; 512 513 if (isCombinedDepthStencilType(textureFormat_.type)) 514 { 515 // Verification loop does not support reading from combined depth stencil texture levels. 516 // Get rid of stencil component. 517 518 tcu::TextureFormat::ChannelOrder channelOrder = tcu::TextureFormat::CHANNELORDER_LAST; 519 tcu::TextureFormat::ChannelType channelType = tcu::TextureFormat::CHANNELTYPE_LAST; 520 521 const auto hasStencil = params.useStencilAspect; 522 523 if (hasStencil) 524 { 525 channelOrder = tcu::TextureFormat::S; 526 channelType = tcu::TextureFormat::UNSIGNED_INT8; 527 } 528 else 529 { 530 channelOrder = tcu::TextureFormat::D; 531 532 switch (textureFormat_.type) 533 { 534 case tcu::TextureFormat::UNSIGNED_INT_16_8_8: 535 channelType = tcu::TextureFormat::UNORM_INT16; 536 break; 537 case tcu::TextureFormat::UNSIGNED_INT_24_8: 538 case tcu::TextureFormat::UNSIGNED_INT_24_8_REV: 539 channelType = tcu::TextureFormat::UNORM_INT24; 540 break; 541 case tcu::TextureFormat::FLOAT_UNSIGNED_INT_24_8_REV: 542 channelType = tcu::TextureFormat::FLOAT; 543 break; 544 default: 545 DE_FATAL("Unhandled texture format type in switch"); 546 } 547 } 548 549 textureFormat = tcu::TextureFormat(channelOrder, channelType); 550 } 551 else 552 { 553 textureFormat = textureFormat_; 554 } 555 556 const auto channelClass = getTextureChannelClass(textureFormat.type); 557 // We must compare all available channels in the color buffer to check RGBA conversion. 558 const auto channelMask = getTextureFormatChannelMask(bufferFormat); 559 // If the component mapping contains a SWIZZLE_ONE, overwrite this with a SWIZZLE_ZERO to ensure 560 // a strict tolerance when applying a swizzle of SWIZZLE_ONE to the threshold. 561 const VkComponentMapping thresholdComponentMapping = 562 { 563 (params.componentMapping.r == VK_COMPONENT_SWIZZLE_ONE ? VK_COMPONENT_SWIZZLE_ZERO : params.componentMapping.r), 564 (params.componentMapping.g == VK_COMPONENT_SWIZZLE_ONE ? VK_COMPONENT_SWIZZLE_ZERO : params.componentMapping.g), 565 (params.componentMapping.b == VK_COMPONENT_SWIZZLE_ONE ? VK_COMPONENT_SWIZZLE_ZERO : params.componentMapping.b), 566 (params.componentMapping.a == VK_COMPONENT_SWIZZLE_ONE ? VK_COMPONENT_SWIZZLE_ZERO : params.componentMapping.a), 567 }; 568 569 switch (channelClass) 570 { 571 case tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT: 572 case tcu::TEXTURECHANNELCLASS_SIGNED_FIXED_POINT: 573 { 574 tcu::Vec4 refColor (ref.float32[0], 575 ref.float32[1], 576 ref.float32[2], 577 ref.float32[3]); 578 tcu::Vec4 threshold (0.0f); 579 580 if (params.isCustom()) 581 { 582 // Relax thresholds for custom color components. 583 const tcu::IVec4 bitDepth (getTextureFormatBitDepth(textureFormat)); 584 const int modifier = (channelClass == tcu::TEXTURECHANNELCLASS_UNSIGNED_FIXED_POINT) ? 0 : 1; 585 586 threshold = tcu::Vec4 (bitDepth[0] > 0 ? 1.0f / ((float)(1 << (bitDepth[0] - modifier)) - 1.0f) : 0.0f, 587 bitDepth[1] > 0 ? 1.0f / ((float)(1 << (bitDepth[1] - modifier)) - 1.0f) : 0.0f, 588 bitDepth[2] > 0 ? 1.0f / ((float)(1 << (bitDepth[2] - modifier)) - 1.0f) : 0.0f, 589 bitDepth[3] > 0 ? 1.0f / ((float)(1 << (bitDepth[3] - modifier)) - 1.0f) : 0.0f); 590 591 if (isSRGB(textureFormat)) 592 { 593 // Widen thresholds a bit due to possible low-precision sRGB conversions. 594 for (int i = 0; i < decltype(threshold)::SIZE; ++i) 595 threshold[i] *= 2.0f; 596 } 597 } 598 599 // Apply swizzle and gather to thresholds. 600 threshold = applySwizzle(threshold, thresholdComponentMapping); 601 602 if (params.componentGather) 603 threshold = applyGather(threshold, *params.componentGather); 604 605 for (int z = 0; z < access.getDepth(); ++z) 606 for (int y = 0; y < access.getHeight(); ++y) 607 for (int x = 0; x < access.getWidth(); ++x) 608 { 609 const tcu::Vec4 resColor (access.getPixel(x, y, z)); 610 const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask)); 611 612 if (!result || (x == 0 && y == 0 && z == 0)) 613 { 614 std::stringstream s; 615 s << "Ref:" << refColor << " Threshold:" << threshold << " Color:" << resColor; 616 stringResult = s.str(); 617 } 618 619 if (!result) 620 return false; 621 } 622 623 return true; 624 } 625 626 case tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER: 627 { 628 const tcu::UVec4 refColor (ref.uint32[0], 629 ref.uint32[1], 630 ref.uint32[2], 631 ref.uint32[3]); 632 tcu::UVec4 threshold (0u); 633 634 if (params.isCustom()) 635 { 636 // Relax thresholds for custom color components. 637 const tcu::IVec4 bitDepth (getTextureFormatBitDepth(textureFormat)); 638 639 threshold = tcu::UVec4 ((bitDepth[0] > 0) ? 1 : 0, 640 (bitDepth[1] > 0) ? 1 : 0, 641 (bitDepth[2] > 0) ? 1 : 0, 642 (bitDepth[3] > 0) ? 1 : 0); 643 } 644 645 // Apply swizzle and gather to thresholds. 646 threshold = applySwizzle(threshold, thresholdComponentMapping); 647 648 if (params.componentGather) 649 threshold = applyGather(threshold, *params.componentGather); 650 651 for (int z = 0; z < access.getDepth(); ++z) 652 for (int y = 0; y < access.getHeight(); ++y) 653 for (int x = 0; x < access.getWidth(); ++x) 654 { 655 const tcu::UVec4 resColor (access.getPixelUint(x, y, z)); 656 const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask)); 657 658 if (!result || (x == 0 && y == 0 && z == 0)) 659 { 660 std::stringstream s; 661 s << "Ref:" << refColor << " Threshold:" << threshold << " Color:" << resColor; 662 stringResult = s.str(); 663 } 664 665 if (!result) 666 return false; 667 } 668 669 return true; 670 } 671 672 case tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER: 673 { 674 const tcu::IVec4 refColor (ref.int32[0], 675 ref.int32[1], 676 ref.int32[2], 677 ref.int32[3]); 678 tcu::IVec4 threshold (0); 679 680 if (params.isCustom()) 681 { 682 // Relax thresholds for custom color components. 683 const tcu::IVec4 bitDepth (getTextureFormatBitDepth(textureFormat)); 684 685 threshold = tcu::IVec4 ((bitDepth[0] > 0) ? 1 : 0, 686 (bitDepth[1] > 0) ? 1 : 0, 687 (bitDepth[2] > 0) ? 1 : 0, 688 (bitDepth[3] > 0) ? 1 : 0); 689 } 690 691 // Apply swizzle and gather to thresholds. 692 threshold = applySwizzle(threshold, thresholdComponentMapping); 693 694 if (params.componentGather) 695 threshold = applyGather(threshold, *params.componentGather); 696 697 for (int z = 0; z < access.getDepth(); ++z) 698 for (int y = 0; y < access.getHeight(); ++y) 699 for (int x = 0; x < access.getWidth(); ++x) 700 { 701 const tcu::IVec4 resColor (access.getPixelInt(x, y, z)); 702 const bool result = !(anyNotEqual(logicalAnd(lessThanEqual(absDiff(resColor, refColor), threshold), channelMask), channelMask)); 703 704 if (!result || (x == 0 && y == 0 && z == 0)) 705 { 706 std::stringstream s; 707 s << "Ref:" << refColor << " Threshold:" << threshold << " Color:" << resColor; 708 stringResult = s.str(); 709 } 710 711 if (!result) 712 return false; 713 } 714 715 return true; 716 } 717 718 case tcu::TEXTURECHANNELCLASS_FLOATING_POINT: 719 { 720 using u64v4 = tcu::Vector<deUint64, 4>; 721 722 const tcu::Vec4 refColor (ref.float32[0], 723 ref.float32[1], 724 ref.float32[2], 725 ref.float32[3]); 726 u64v4 threshold (0ull); 727 728 if (params.isCustom()) 729 { 730 // Relax thresholds for custom color components. 731 const tcu::IVec4 mantissaBitsI (getTextureFormatMantissaBitDepth(textureFormat)); 732 const u64v4 mantissaBits (mantissaBitsI.x(), mantissaBitsI.y(), mantissaBitsI.z(), mantissaBitsI.w()); 733 734 threshold = u64v4 ((mantissaBits[0] > 0ull) ? 10ull * (1ull << (23ull - mantissaBits[0])) : 0ull, 735 (mantissaBits[1] > 0ull) ? 10ull * (1ull << (23ull - mantissaBits[1])) : 0ull, 736 (mantissaBits[2] > 0ull) ? 10ull * (1ull << (23ull - mantissaBits[2])) : 0ull, 737 (mantissaBits[3] > 0ull) ? 10ull * (1ull << (23ull - mantissaBits[3])) : 0ull); 738 } 739 740 // Apply swizzle and gather to thresholds. 741 threshold = applySwizzle(threshold, thresholdComponentMapping); 742 743 if (params.componentGather) 744 threshold = applyGather(threshold, *params.componentGather); 745 746 DE_ASSERT(allEqual(greaterThanEqual(threshold, u64v4(0u)), tcu::BVec4(true))); 747 748 for (int z = 0; z < access.getDepth(); ++z) 749 for (int y = 0; y < access.getHeight(); ++y) 750 for (int x = 0; x < access.getWidth(); ++x) 751 { 752 const tcu::Vec4 resColor (access.getPixel(x, y, z)); 753 754 for (int ndx = 0; ndx < decltype(resColor)::SIZE; ndx++) 755 { 756 const bool result = !(calcFloatDiff(resColor[ndx], refColor[ndx]) > threshold[ndx] && channelMask[ndx]); 757 758 if (!result || (x == 0 && y == 0 && z == 0)) 759 { 760 float floatThreshold = tcu::Float32((deUint32)(threshold)[0]).asFloat(); 761 tcu::Vec4 thresholdVec4 (floatThreshold, 762 floatThreshold, 763 floatThreshold, 764 floatThreshold); 765 std::stringstream s; 766 767 s << "Ref:" << refColor << " Threshold:" << thresholdVec4 << " Color:" << resColor; 768 stringResult = s.str(); 769 } 770 771 if (!result) 772 return false; 773 } 774 } 775 776 return true; 777 } 778 779 default: 780 DE_FATAL("Invalid channel class"); 781 return false; 782 } 783} 784 785// Gets the clear color value from the border color. See "Texel Replacement" in the spec. 786VkClearColorValue getBorderClearColorValue (const TestParams& params) 787{ 788 VkClearColorValue result; 789 deMemset(&result, 0, sizeof(result)); 790 791 switch (params.borderColor) 792 { 793 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: /* memset works. */ break; 794 case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: /* memset works. */ break; 795 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: result.float32[3] = 1.0f; break; 796 case VK_BORDER_COLOR_INT_OPAQUE_BLACK: result.int32[3] = 1; break; 797 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: for (size_t i = 0; i < 4; ++i) result.float32[i] = 1.0f; break; 798 case VK_BORDER_COLOR_INT_OPAQUE_WHITE: for (size_t i = 0; i < 4; ++i) result.int32[i] = 1; break; 799 case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: // fallthrough. 800 case VK_BORDER_COLOR_INT_CUSTOM_EXT: DE_ASSERT(params.customBorderColor); result = *params.customBorderColor; break; 801 default: DE_ASSERT(false); break; 802 } 803 804 return result; 805} 806 807tcu::TestStatus BorderSwizzleInstance::iterate (void) 808{ 809 const auto& vki = m_context.getInstanceInterface(); 810 const auto& vkd = m_context.getDeviceInterface(); 811 const auto physicalDevice = m_context.getPhysicalDevice(); 812 const auto device = m_context.getDevice(); 813 auto& alloc = m_context.getDefaultAllocator(); 814 const auto queue = m_context.getUniversalQueue(); 815 const auto qIndex = m_context.getUniversalQueueFamilyIndex(); 816 const auto extent = getImageExtent(); 817 const auto custom = m_params.isCustom(); 818 const auto isDSFormat = isDepthStencilFormat(m_params.textureFormat); 819 const auto hasStencil = m_params.useStencilAspect; 820 const auto imageAspect = (isDSFormat ? (hasStencil ? VK_IMAGE_ASPECT_STENCIL_BIT : VK_IMAGE_ASPECT_DEPTH_BIT) : VK_IMAGE_ASPECT_COLOR_BIT); 821 const auto imageSubresourceRange = makeImageSubresourceRange(imageAspect, 0u, 1u, 0u, 1u); 822 const auto colorAttachmentFormat = getColorAttachmentFormat(m_params.textureFormat, hasStencil); 823 const auto colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u); 824 825 // Texture. 826 const VkImageCreateInfo textureCreateInfo = 827 { 828 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 829 nullptr, // const void* pNext; 830 0u, // VkImageCreateFlags flags; 831 VK_IMAGE_TYPE_2D, // VkImageType imageType; 832 m_params.textureFormat, // VkFormat format; 833 extent, // VkExtent3D extent; 834 1u, // deUint32 mipLevels; 835 1u, // deUint32 arrayLayers; 836 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 837 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 838 (VK_IMAGE_USAGE_SAMPLED_BIT // VkImageUsageFlags usage; 839 |VK_IMAGE_USAGE_TRANSFER_DST_BIT), 840 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 841 0u, // deUint32 queueFamilyIndexCount; 842 nullptr, // const deUint32* pQueueFamilyIndices; 843 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 844 }; 845 846 ImageWithMemory texture (vkd, device, alloc, textureCreateInfo, MemoryRequirement::Any); 847 848 const VkImageViewCreateInfo textureViewCreateInfo = 849 { 850 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, // VkStructureType sType; 851 nullptr, // const void* pNext; 852 0u, // VkImageViewCreateFlags flags; 853 texture.get(), // VkImage image; 854 VK_IMAGE_VIEW_TYPE_2D, // VkImageViewType viewType; 855 m_params.textureFormat, // VkFormat format; 856 m_params.componentMapping, // VkComponentMapping components; 857 imageSubresourceRange, // VkImageSubresourceRange subresourceRange; 858 }; 859 860 const auto textureView = createImageView(vkd, device, &textureViewCreateInfo); 861 862 // Color attachment. 863 const VkImageCreateInfo colorAttachmentInfo = 864 { 865 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO, // VkStructureType sType; 866 nullptr, // const void* pNext; 867 0u, // VkImageCreateFlags flags; 868 VK_IMAGE_TYPE_2D, // VkImageType imageType; 869 colorAttachmentFormat, // VkFormat format; 870 extent, // VkExtent3D extent; 871 1u, // deUint32 mipLevels; 872 1u, // deUint32 arrayLayers; 873 VK_SAMPLE_COUNT_1_BIT, // VkSampleCountFlagBits samples; 874 VK_IMAGE_TILING_OPTIMAL, // VkImageTiling tiling; 875 (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT 876 | VK_IMAGE_USAGE_TRANSFER_SRC_BIT), // VkImageUsageFlags usage; 877 VK_SHARING_MODE_EXCLUSIVE, // VkSharingMode sharingMode; 878 0u, // deUint32 queueFamilyIndexCount; 879 nullptr, // const deUint32* pQueueFamilyIndices; 880 VK_IMAGE_LAYOUT_UNDEFINED, // VkImageLayout initialLayout; 881 }; 882 883 ImageWithMemory colorAttachment (vkd, device, alloc, colorAttachmentInfo, MemoryRequirement::Any); 884 885 const auto colorAttachmentView = makeImageView(vkd, device, colorAttachment.get(), VK_IMAGE_VIEW_TYPE_2D, colorAttachmentInfo.format, colorSubresourceRange); 886 887 // Texure sampler. 888 de::MovePtr<VkSamplerCustomBorderColorCreateInfoEXT> customBorderColorInfo; 889 890 const VkSamplerBorderColorComponentMappingCreateInfoEXT borderColorMappingInfo = 891 { 892 VK_STRUCTURE_TYPE_SAMPLER_BORDER_COLOR_COMPONENT_MAPPING_CREATE_INFO_EXT, 893 nullptr, 894 m_params.componentMapping, 895 isSrgbFormat(m_params.textureFormat), 896 }; 897 898 const void* pNext = nullptr; 899 900 if (custom) 901 { 902 customBorderColorInfo = de::MovePtr<VkSamplerCustomBorderColorCreateInfoEXT>(new VkSamplerCustomBorderColorCreateInfoEXT); 903 *customBorderColorInfo = initVulkanStructure(); 904 905 DE_ASSERT(m_params.customBorderColor); 906 VkClearColorValue colorValue = m_params.customBorderColor.get(); 907 908 if (m_params.useSamplerSwizzleHint) 909 customBorderColorInfo->pNext = &borderColorMappingInfo; 910 911 // TODO: try combinations with customBorderColorWithoutFormat if supported? 912 customBorderColorInfo->format = m_params.textureFormat; 913 customBorderColorInfo->customBorderColor = colorValue; 914 915 pNext = customBorderColorInfo.get(); 916 } 917 else 918 { 919 if (m_params.useSamplerSwizzleHint) 920 pNext = &borderColorMappingInfo; 921 } 922 923 const VkSamplerCreateInfo samplerCreateInfo = 924 { 925 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO, // VkStructureType sType; 926 pNext, // const void* pNext; 927 0u, // VkSamplerCreateFlags flags; 928 VK_FILTER_NEAREST, // VkFilter magFilter; 929 VK_FILTER_NEAREST, // VkFilter minFilter; 930 VK_SAMPLER_MIPMAP_MODE_NEAREST, // VkSamplerMipmapMode mipmapMode; 931 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeU; 932 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeV; 933 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_BORDER, // VkSamplerAddressMode addressModeW; 934 0u, // float mipLodBias; 935 VK_FALSE, // VkBool32 anisotropyEnable; 936 0.0f, // float maxAnisotropy; 937 VK_FALSE, // VkBool32 compareEnable; 938 VK_COMPARE_OP_NEVER, // VkCompareOp compareOp; 939 0.0f, // float minLod; 940 1.0f, // float maxLod; 941 m_params.borderColor, // VkBorderColor borderColor; 942 VK_FALSE, // VkBool32 unnormalizedCoordinates; 943 }; 944 945 const auto sampler = createSampler(vkd, device, &samplerCreateInfo); 946 947 // Descriptor set layout. 948 DescriptorSetLayoutBuilder dsLayoutBuilder; 949 dsLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, VK_SHADER_STAGE_FRAGMENT_BIT); 950 const auto dsLayout = dsLayoutBuilder.build(vkd, device); 951 952 // Pipeline layout. 953 const PipelineLayoutWrapper pipelineLayout (m_params.pipelineConstructionType, vkd, device, dsLayout.get()); 954 955 // Descriptor pool. 956 DescriptorPoolBuilder poolBuilder; 957 poolBuilder.addType(VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER); 958 const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u); 959 960 // Descriptor set. 961 const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), dsLayout.get()); 962 963 // Update descriptor set. 964 { 965 DescriptorSetUpdateBuilder updateBuilder; 966 VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(sampler.get(), textureView.get(), VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL); 967 updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descriptorImageInfo); 968 updateBuilder.update(vkd, device); 969 } 970 971 // Render pass. 972 RenderPassWrapper renderPass (m_params.pipelineConstructionType, vkd, device, colorAttachmentFormat); 973 974 // Shader modules. 975 const auto vertShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u); 976 const auto fragShader = ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag"), 0u); 977 978 const SpecConstants specConstantData = 979 { 980 m_params.textureCoordinates.x(), 981 m_params.textureCoordinates.y(), 982 (m_params.componentGather ? 1 : 0), 983 //(m_params.componentGather ? *m_params.componentGather : -1), 984 }; 985 986 const VkSpecializationMapEntry specializationMap[] = 987 { 988 { 0u, offsetof(SpecConstants, u), sizeof(specConstantData.u) }, 989 { 1u, offsetof(SpecConstants, v), sizeof(specConstantData.v) }, 990 { 2u, offsetof(SpecConstants, gatherFlag), sizeof(specConstantData.gatherFlag) }, 991 //{ 3u, offsetof(SpecConstants, gatherComp), sizeof(specConstantData.gatherComp) }, 992 }; 993 994 const VkSpecializationInfo specializationInfo = 995 { 996 static_cast<deUint32>(DE_LENGTH_OF_ARRAY(specializationMap)), // deUint32 mapEntryCount; 997 specializationMap, // const VkSpecializationMapEntry* pMapEntries; 998 static_cast<deUintptr>(sizeof(specConstantData)), // deUintptr dataSize; 999 &specConstantData, // const void* pData; 1000 }; 1001 1002 const VkPipelineVertexInputStateCreateInfo vertexInputInfo = initVulkanStructure(); 1003 1004 const std::vector<VkViewport> viewport { makeViewport(extent) }; 1005 const std::vector<VkRect2D> scissor { makeRect2D(extent) }; 1006 1007 VkPipelineColorBlendAttachmentState colorBlendAttachmentState; 1008 deMemset(&colorBlendAttachmentState, 0, sizeof(colorBlendAttachmentState)); 1009 colorBlendAttachmentState.colorWriteMask = (VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT); 1010 1011 const VkPipelineColorBlendStateCreateInfo colorBlendInfo 1012 { 1013 VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, // VkStructureType sType; 1014 nullptr, // const void* pNext; 1015 0u, // VkPipelineColorBlendStateCreateFlags flags; 1016 VK_FALSE, // VkBool32 logicOpEnable; 1017 VK_LOGIC_OP_CLEAR, // VkLogicOp logicOp; 1018 1u, // deUint32 attachmentCount; 1019 &colorBlendAttachmentState, // const VkPipelineColorBlendAttachmentState* pAttachments; 1020 { .0f, .0f, .0f, .0f }, // float blendConstants[4]; 1021 }; 1022 1023 GraphicsPipelineWrapper graphicsPipeline(vki, vkd, physicalDevice, device, m_context.getDeviceExtensions(), m_params.pipelineConstructionType); 1024 graphicsPipeline.setDefaultTopology(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) 1025 .setDefaultDepthStencilState() 1026 .setDefaultRasterizationState() 1027 .setDefaultMultisampleState() 1028 .setupVertexInputState(&vertexInputInfo) 1029 .setupPreRasterizationShaderState(viewport, 1030 scissor, 1031 pipelineLayout, 1032 *renderPass, 1033 0u, 1034 vertShader) 1035 .setupFragmentShaderState(pipelineLayout, 1036 *renderPass, 1037 0u, 1038 fragShader, 1039 DE_NULL, 1040 DE_NULL, 1041 &specializationInfo) 1042 .setupFragmentOutputState(*renderPass, 0u, &colorBlendInfo) 1043 .setMonolithicPipelineLayout(pipelineLayout) 1044 .buildPipeline(); 1045 1046 // Framebuffer. 1047 renderPass.createFramebuffer(vkd, device, colorAttachment.get(), colorAttachmentView.get(), extent.width, extent.height); 1048 1049 // Command pool and buffer. 1050 const auto cmdPool = makeCommandPool(vkd, device, qIndex); 1051 const auto cmdBufferPtr = allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY); 1052 const auto cmdBuffer = cmdBufferPtr.get(); 1053 1054 // Empty clear color for the framebuffer. 1055 VkClearValue zeroClearColor; 1056 deMemset(&zeroClearColor, 0, sizeof(zeroClearColor)); 1057 1058 // Texture barriers to fill it before using it. 1059 const auto preClearBarrier = makeImageMemoryBarrier( 1060 0u, 1061 VK_ACCESS_TRANSFER_WRITE_BIT, 1062 VK_IMAGE_LAYOUT_UNDEFINED, 1063 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1064 texture.get(), 1065 imageSubresourceRange); 1066 1067 const auto postClearBarrier = makeImageMemoryBarrier( 1068 VK_ACCESS_TRANSFER_WRITE_BIT, 1069 VK_ACCESS_SHADER_READ_BIT, 1070 VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, 1071 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL, 1072 texture.get(), 1073 imageSubresourceRange); 1074 1075 // Record and submit. 1076 beginCommandBuffer(vkd, cmdBuffer); 1077 1078 // Prepare texture. 1079 vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preClearBarrier); 1080 if (isDSFormat) 1081 vkd.cmdClearDepthStencilImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.textureDepthStencilValue, 1u, &imageSubresourceRange); 1082 else 1083 vkd.cmdClearColorImage(cmdBuffer, texture.get(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_params.textureColor, 1u, &imageSubresourceRange); 1084 vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postClearBarrier); 1085 1086 // Read from the texture to render a full-screen quad to the color buffer. 1087 renderPass.begin(vkd, cmdBuffer, scissor[0], zeroClearColor); 1088 graphicsPipeline.bind(cmdBuffer); 1089 vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr); 1090 vkd.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u); 1091 renderPass.end(vkd, cmdBuffer); 1092 1093 endCommandBuffer(vkd, cmdBuffer); 1094 submitCommandsAndWait(vkd, device, queue, cmdBuffer); 1095 1096 // Verify color buffer. 1097 const auto renderSize = tcu::UVec2(extent.width, extent.height); 1098 const auto colorAttachmentLevel = readColorAttachment(vkd, device, queue, qIndex, alloc, colorAttachment.get(), colorAttachmentFormat, renderSize); 1099 const auto colorPixels = colorAttachmentLevel->getAccess(); 1100 const auto tcuTextureFormat = mapVkFormat(m_params.textureFormat); 1101 const auto borderColor = getBorderClearColorValue(m_params); 1102 const auto expectedColor = getExpectedColor(borderColor, m_params); 1103 std::string resultMsg; 1104 1105 if (!comparePixelToColorClearValue(m_params, colorPixels, tcuTextureFormat, expectedColor, resultMsg)) 1106 TCU_FAIL(resultMsg); 1107 1108 return tcu::TestStatus::pass(resultMsg); 1109} 1110 1111using ComponentSwizzleArray = std::array<VkComponentSwizzle, 4>; 1112 1113// Convert the component swizzle array to a component mapping structure. 1114void makeComponentMapping(VkComponentMapping& mapping, const ComponentSwizzleArray& array) 1115{ 1116 mapping.r = array[0]; 1117 mapping.g = array[1]; 1118 mapping.b = array[2]; 1119 mapping.a = array[3]; 1120} 1121 1122std::string swizzleArrayToString(const ComponentSwizzleArray& swizzles) 1123{ 1124 std::ostringstream stream; 1125 1126 for (const auto& s : swizzles) 1127 { 1128 switch (s) 1129 { 1130 case VK_COMPONENT_SWIZZLE_IDENTITY: stream << "i"; break; 1131 case VK_COMPONENT_SWIZZLE_ZERO: stream << "0"; break; 1132 case VK_COMPONENT_SWIZZLE_ONE: stream << "1"; break; 1133 case VK_COMPONENT_SWIZZLE_R: stream << "r"; break; 1134 case VK_COMPONENT_SWIZZLE_G: stream << "g"; break; 1135 case VK_COMPONENT_SWIZZLE_B: stream << "b"; break; 1136 case VK_COMPONENT_SWIZZLE_A: stream << "a"; break; 1137 default: 1138 DE_ASSERT(false); break; 1139 } 1140 } 1141 1142 return stream.str(); 1143} 1144 1145// Generate mapping permutations for the swizzle components. 1146// Note: using every permutation for component swizzle values results in 7^4=2401 combinations, which are too many. 1147std::vector<ComponentSwizzleArray> genMappingPermutations () 1148{ 1149 std::vector<ComponentSwizzleArray> result; 1150 const ComponentSwizzleArray standardSwizzle = {{ VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A }}; 1151 1152 // Standard normal swizzle. 1153 result.push_back(standardSwizzle); 1154 1155 // Add a few combinations with rotated swizzles. 1156 for (size_t rotations = 1u; rotations < standardSwizzle.size(); ++rotations) 1157 { 1158 ComponentSwizzleArray rotatedSwizzle = standardSwizzle; 1159 std::rotate(rotatedSwizzle.begin(), rotatedSwizzle.begin() + rotations, rotatedSwizzle.end()); 1160 result.push_back(rotatedSwizzle); 1161 } 1162 1163 // Try placing each special value in each of the positions. 1164 VkComponentSwizzle specialSwizzles[] = { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_ONE, VK_COMPONENT_SWIZZLE_ZERO }; 1165 for (const auto& special : specialSwizzles) 1166 { 1167 for (size_t pos = 0; pos < standardSwizzle.size(); ++pos) 1168 { 1169 ComponentSwizzleArray newArray = standardSwizzle; 1170 newArray[pos] = special; 1171 result.push_back(newArray); 1172 } 1173 } 1174 1175 return result; 1176} 1177 1178std::string gatherIndexToString(int gatherIndex) 1179{ 1180 if (gatherIndex < 0) 1181 return "no_gather"; 1182 return "gather_" + std::to_string(gatherIndex); 1183} 1184 1185bool isIntegerBorder (VkBorderColor borderType) 1186{ 1187 bool isInt = false; 1188 switch (borderType) 1189 { 1190 case VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK: 1191 case VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK: 1192 case VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE: 1193 case VK_BORDER_COLOR_FLOAT_CUSTOM_EXT: 1194 isInt = false; break; 1195 case VK_BORDER_COLOR_INT_TRANSPARENT_BLACK: 1196 case VK_BORDER_COLOR_INT_OPAQUE_BLACK: 1197 case VK_BORDER_COLOR_INT_OPAQUE_WHITE: 1198 case VK_BORDER_COLOR_INT_CUSTOM_EXT: 1199 isInt = true; break; 1200 default: 1201 DE_ASSERT(false); break; 1202 } 1203 1204 return isInt; 1205} 1206 1207tcu::Vec2 getRandomBorderCoordinates (de::Random& rnd) 1208{ 1209 tcu::Vec2 coords; 1210 1211 // Two bits to decide which coordinates will be out of range (at least one). 1212 const deUint32 outOfRangeMask = static_cast<deUint32>(rnd.getInt(1, 3)); 1213 1214 for (int i = 0; i < 2; ++i) 1215 { 1216 // Each coord will be in the [0.0, 0.9] range if in range, [1.1, 5.0] or [-5.0, -1.1] if out of range. 1217 bool outOfRange = (outOfRangeMask & (1<<i)); 1218 bool negative = (outOfRange && rnd.getBool()); 1219 float minCoord = (outOfRange ? 1.1f : 0.0f); 1220 float maxCoord = (outOfRange ? 5.0f : 0.9f); 1221 float value = (negative ? -1.0f : 1.0f) * rnd.getFloat(minCoord, maxCoord); 1222 1223 coords[i] = value; 1224 } 1225 1226 return coords; 1227} 1228 1229// Generate a random clear color usable for the given format. 1230VkClearColorValue getRandomClearColor (VkFormat format, de::Random& rnd, bool useStencil) 1231{ 1232 VkClearColorValue color; 1233 deMemset(&color, 0, sizeof(color)); 1234 1235 const auto tcuFormat = mapVkFormat(format); 1236 const auto numComponents = !useStencil ? tcu::getNumUsedChannels(tcuFormat.order) : 1; 1237 const auto formatType = getFormatType(format, useStencil); 1238 1239 for (int i = 0; i < numComponents; ++i) 1240 { 1241 if (formatType == FormatType::SIGNED_INT || formatType == FormatType::UNSIGNED_INT) 1242 { 1243 const auto componentSize = !useStencil ? tcu::getChannelSize(tcuFormat.type) : 1; 1244 1245 DE_ASSERT(componentSize > 0); 1246 1247 const deUint64 mask = (1ull << (componentSize*8)) - 1ull; 1248 const deUint64 signBit = (1ull << (componentSize*8-1)); 1249 const deUint64 signMask = (~mask); // Used to extend the sign bit. 1250 const auto value = rnd.getUint64(); 1251 1252 if (formatType == FormatType::SIGNED_INT) 1253 { 1254 // Extend sign bit for negative values. 1255 auto finalValue = (value & mask); 1256 if (finalValue & signBit) 1257 finalValue |= signMask; 1258 color.int32[i] = static_cast<deInt32>(finalValue); 1259 } 1260 else 1261 color.uint32[i] = static_cast<deUint32>(value & mask); 1262 } 1263 else 1264 color.float32[i] = rnd.getFloat(); 1265 } 1266 1267 return color; 1268} 1269 1270} // anonymous 1271 1272tcu::TestCaseGroup* createSamplerBorderSwizzleTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType) 1273{ 1274 const deUint32 baseSeed = 1610707317u; 1275 1276 const VkFormat textureFormats[] = 1277 { 1278 //VK_FORMAT_UNDEFINED, 1279 VK_FORMAT_R4G4_UNORM_PACK8, 1280 VK_FORMAT_R4G4B4A4_UNORM_PACK16, 1281 VK_FORMAT_B4G4R4A4_UNORM_PACK16, 1282 VK_FORMAT_R5G6B5_UNORM_PACK16, 1283 VK_FORMAT_B5G6R5_UNORM_PACK16, 1284 VK_FORMAT_R5G5B5A1_UNORM_PACK16, 1285 VK_FORMAT_B5G5R5A1_UNORM_PACK16, 1286 VK_FORMAT_A1R5G5B5_UNORM_PACK16, 1287#ifndef CTS_USES_VULKANSC 1288 VK_FORMAT_A1B5G5R5_UNORM_PACK16_KHR, 1289#endif // CTS_USES_VULKANSC 1290 VK_FORMAT_R8_UNORM, 1291 VK_FORMAT_R8_SNORM, 1292 //VK_FORMAT_R8_USCALED, 1293 //VK_FORMAT_R8_SSCALED, 1294 VK_FORMAT_R8_UINT, 1295 VK_FORMAT_R8_SINT, 1296 VK_FORMAT_R8_SRGB, 1297#ifndef CTS_USES_VULKANSC 1298 VK_FORMAT_A8_UNORM_KHR, 1299#endif // CTS_USES_VULKANSC 1300 VK_FORMAT_R8G8_UNORM, 1301 VK_FORMAT_R8G8_SNORM, 1302 //VK_FORMAT_R8G8_USCALED, 1303 //VK_FORMAT_R8G8_SSCALED, 1304 VK_FORMAT_R8G8_UINT, 1305 VK_FORMAT_R8G8_SINT, 1306 VK_FORMAT_R8G8_SRGB, 1307 VK_FORMAT_R8G8B8_UNORM, 1308 VK_FORMAT_R8G8B8_SNORM, 1309 //VK_FORMAT_R8G8B8_USCALED, 1310 //VK_FORMAT_R8G8B8_SSCALED, 1311 VK_FORMAT_R8G8B8_UINT, 1312 VK_FORMAT_R8G8B8_SINT, 1313 VK_FORMAT_R8G8B8_SRGB, 1314 VK_FORMAT_B8G8R8_UNORM, 1315 VK_FORMAT_B8G8R8_SNORM, 1316 //VK_FORMAT_B8G8R8_USCALED, 1317 //VK_FORMAT_B8G8R8_SSCALED, 1318 VK_FORMAT_B8G8R8_UINT, 1319 VK_FORMAT_B8G8R8_SINT, 1320 VK_FORMAT_B8G8R8_SRGB, 1321 VK_FORMAT_R8G8B8A8_UNORM, 1322 VK_FORMAT_R8G8B8A8_SNORM, 1323 //VK_FORMAT_R8G8B8A8_USCALED, 1324 //VK_FORMAT_R8G8B8A8_SSCALED, 1325 VK_FORMAT_R8G8B8A8_UINT, 1326 VK_FORMAT_R8G8B8A8_SINT, 1327 VK_FORMAT_R8G8B8A8_SRGB, 1328 VK_FORMAT_B8G8R8A8_UNORM, 1329 VK_FORMAT_B8G8R8A8_SNORM, 1330 //VK_FORMAT_B8G8R8A8_USCALED, 1331 //VK_FORMAT_B8G8R8A8_SSCALED, 1332 VK_FORMAT_B8G8R8A8_UINT, 1333 VK_FORMAT_B8G8R8A8_SINT, 1334 VK_FORMAT_B8G8R8A8_SRGB, 1335 VK_FORMAT_A8B8G8R8_UNORM_PACK32, 1336 VK_FORMAT_A8B8G8R8_SNORM_PACK32, 1337 // VK_FORMAT_A8B8G8R8_USCALED_PACK32, 1338 // VK_FORMAT_A8B8G8R8_SSCALED_PACK32, 1339 // VK_FORMAT_A8B8G8R8_UINT_PACK32, 1340 // VK_FORMAT_A8B8G8R8_SINT_PACK32, 1341 // VK_FORMAT_A8B8G8R8_SRGB_PACK32, 1342 VK_FORMAT_A2R10G10B10_UNORM_PACK32, 1343 VK_FORMAT_A2R10G10B10_SNORM_PACK32, 1344 // VK_FORMAT_A2R10G10B10_USCALED_PACK32, 1345 // VK_FORMAT_A2R10G10B10_SSCALED_PACK32, 1346 // VK_FORMAT_A2R10G10B10_UINT_PACK32, 1347 // VK_FORMAT_A2R10G10B10_SINT_PACK32, 1348 VK_FORMAT_A2B10G10R10_UNORM_PACK32, 1349 VK_FORMAT_A2B10G10R10_SNORM_PACK32, 1350 // VK_FORMAT_A2B10G10R10_USCALED_PACK32, 1351 // VK_FORMAT_A2B10G10R10_SSCALED_PACK32, 1352 // VK_FORMAT_A2B10G10R10_UINT_PACK32, 1353 // VK_FORMAT_A2B10G10R10_SINT_PACK32, 1354 VK_FORMAT_R16_UNORM, 1355 VK_FORMAT_R16_SNORM, 1356 //VK_FORMAT_R16_USCALED, 1357 //VK_FORMAT_R16_SSCALED, 1358 VK_FORMAT_R16_UINT, 1359 VK_FORMAT_R16_SINT, 1360 VK_FORMAT_R16_SFLOAT, 1361 VK_FORMAT_R16G16_UNORM, 1362 VK_FORMAT_R16G16_SNORM, 1363 //VK_FORMAT_R16G16_USCALED, 1364 //VK_FORMAT_R16G16_SSCALED, 1365 VK_FORMAT_R16G16_UINT, 1366 VK_FORMAT_R16G16_SINT, 1367 VK_FORMAT_R16G16_SFLOAT, 1368 VK_FORMAT_R16G16B16_UNORM, 1369 VK_FORMAT_R16G16B16_SNORM, 1370 //VK_FORMAT_R16G16B16_USCALED, 1371 //VK_FORMAT_R16G16B16_SSCALED, 1372 VK_FORMAT_R16G16B16_UINT, 1373 VK_FORMAT_R16G16B16_SINT, 1374 VK_FORMAT_R16G16B16_SFLOAT, 1375 VK_FORMAT_R16G16B16A16_UNORM, 1376 VK_FORMAT_R16G16B16A16_SNORM, 1377 //VK_FORMAT_R16G16B16A16_USCALED, 1378 //VK_FORMAT_R16G16B16A16_SSCALED, 1379 VK_FORMAT_R16G16B16A16_UINT, 1380 VK_FORMAT_R16G16B16A16_SINT, 1381 VK_FORMAT_R16G16B16A16_SFLOAT, 1382 VK_FORMAT_R32_UINT, 1383 VK_FORMAT_R32_SINT, 1384 VK_FORMAT_R32_SFLOAT, 1385 VK_FORMAT_R32G32_UINT, 1386 VK_FORMAT_R32G32_SINT, 1387 VK_FORMAT_R32G32_SFLOAT, 1388 VK_FORMAT_R32G32B32_UINT, 1389 VK_FORMAT_R32G32B32_SINT, 1390 VK_FORMAT_R32G32B32_SFLOAT, 1391 VK_FORMAT_R32G32B32A32_UINT, 1392 VK_FORMAT_R32G32B32A32_SINT, 1393 VK_FORMAT_R32G32B32A32_SFLOAT, 1394 1395 // Depth/Stencil formats. 1396 VK_FORMAT_D16_UNORM, 1397 VK_FORMAT_X8_D24_UNORM_PACK32, 1398 VK_FORMAT_D32_SFLOAT, 1399 VK_FORMAT_S8_UINT, 1400 VK_FORMAT_D16_UNORM_S8_UINT, 1401 VK_FORMAT_D24_UNORM_S8_UINT, 1402 VK_FORMAT_D32_SFLOAT_S8_UINT, 1403 }; 1404 1405 const std::array<bool, 2> sampleStencilFlag = {{ false, true }}; 1406 1407 const auto mappingPermutations = genMappingPermutations(); 1408 1409 const struct 1410 { 1411 VkBorderColor borderType; 1412 const char* borderTypeName; 1413 } 1414 borderColors[] = 1415 { 1416 { VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, "transparent_black" }, 1417 { VK_BORDER_COLOR_INT_TRANSPARENT_BLACK, "transparent_black" }, 1418 { VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK, "opaque_black" }, 1419 { VK_BORDER_COLOR_INT_OPAQUE_BLACK, "opaque_black" }, 1420 { VK_BORDER_COLOR_FLOAT_OPAQUE_WHITE, "opaque_white" }, 1421 { VK_BORDER_COLOR_INT_OPAQUE_WHITE, "opaque_white" }, 1422 { VK_BORDER_COLOR_FLOAT_CUSTOM_EXT, "custom" }, 1423 { VK_BORDER_COLOR_INT_CUSTOM_EXT, "custom" }, 1424 }; 1425 1426 const struct 1427 { 1428 bool useSwizzleHint; 1429 const char* name; 1430 } swizzleHintCases[] = 1431 { 1432 { false, "no_swizzle_hint" }, 1433 { true, "with_swizzle_hint" }, 1434 }; 1435 1436 de::MovePtr<tcu::TestCaseGroup> mainGroup(new tcu::TestCaseGroup(testCtx, "border_swizzle")); 1437 1438 for (const auto& format : textureFormats) 1439 { 1440 const auto skip = std::strlen("VK_FORMAT_"); 1441 const std::string formatName = de::toLower(std::string(getFormatName(format)).substr(skip)); 1442 1443 for (const auto sampleStencil : sampleStencilFlag) 1444 { 1445 const auto isDSFormat = isDepthStencilFormat(format); 1446 1447 if (!isDSFormat && sampleStencil) 1448 continue; 1449 1450 std::ostringstream formatGroupName; 1451 formatGroupName << formatName; 1452 1453 if (isDSFormat) 1454 { 1455 const auto tcuFormat = mapVkFormat(format); 1456 1457 if (!sampleStencil && !tcu::hasDepthComponent(tcuFormat.order)) 1458 continue; 1459 if (sampleStencil && !tcu::hasStencilComponent(tcuFormat.order)) 1460 continue; 1461 1462 if (sampleStencil) 1463 formatGroupName << "_stencil"; 1464 } 1465 1466 de::MovePtr<tcu::TestCaseGroup> formatGroup (new tcu::TestCaseGroup(testCtx, formatGroupName.str().c_str())); 1467 1468 for (size_t mappingIdx = 0u; mappingIdx < mappingPermutations.size(); ++mappingIdx) 1469 { 1470 const auto& mapping = mappingPermutations[mappingIdx]; 1471 de::MovePtr<tcu::TestCaseGroup> mappingGroup (new tcu::TestCaseGroup(testCtx, swizzleArrayToString(mapping).c_str())); 1472 1473 for (int borderColorIdx = 0; borderColorIdx < DE_LENGTH_OF_ARRAY(borderColors); ++borderColorIdx) 1474 { 1475 const auto& borderColor = borderColors[borderColorIdx]; 1476 de::MovePtr<tcu::TestCaseGroup> borderTypeGroup (new tcu::TestCaseGroup(testCtx, borderColor.borderTypeName)); 1477 1478 const auto formatType = getFormatType(format, sampleStencil); 1479 const auto isIntBorder = isIntegerBorder(borderColor.borderType); 1480 1481 // Skip cases that do not make sense for the format and border type combination. 1482 if (isIntBorder && formatType == FormatType::FLOAT) 1483 continue; 1484 else if (!isIntBorder && formatType != FormatType::FLOAT) 1485 continue; 1486 1487 for (int gatherIdx = -1; gatherIdx <= 3; ++gatherIdx) 1488 { 1489 const auto componentGather = gatherIndexToString(gatherIdx); 1490 de::MovePtr<tcu::TestCaseGroup> gatherGroup (new tcu::TestCaseGroup(testCtx, componentGather.c_str())); 1491 1492 for (const auto& swizzleHint : swizzleHintCases) 1493 { 1494 TestParams params; 1495 deMemset(¶ms, 0, sizeof(TestParams)); 1496 1497 const deUint32 seed = baseSeed + static_cast<deUint32>(format) + static_cast<deUint32>(mappingIdx) + static_cast<deUint32>(borderColorIdx) + static_cast<deUint32>(gatherIdx); 1498 de::Random rnd (seed); 1499 1500 params.pipelineConstructionType = pipelineConstructionType; 1501 params.textureFormat = format; 1502 params.textureColor = getRandomClearColor(format, rnd, false); 1503 params.textureDepthStencilValue = vk::makeClearDepthStencilValue(0.0f, 0u); 1504 1505 makeComponentMapping(params.componentMapping, mapping); 1506 params.borderColor = borderColor.borderType; 1507 params.componentGather = ((gatherIdx < 0) ? tcu::nothing<int>() : tcu::just(gatherIdx)); 1508 params.textureCoordinates = getRandomBorderCoordinates(rnd); 1509 1510 if (params.isCustom()) 1511 params.customBorderColor = tcu::just(getRandomClearColor(format, rnd, sampleStencil)); 1512 else 1513 params.customBorderColor = tcu::nothing<VkClearColorValue>(); 1514 1515 params.useSamplerSwizzleHint = swizzleHint.useSwizzleHint; 1516 params.useStencilAspect = sampleStencil; 1517 1518 gatherGroup->addChild(new BorderSwizzleCase(testCtx, swizzleHint.name, params)); 1519 } 1520 1521 borderTypeGroup->addChild(gatherGroup.release()); 1522 } 1523 1524 mappingGroup->addChild(borderTypeGroup.release()); 1525 } 1526 1527 formatGroup->addChild(mappingGroup.release()); 1528 } 1529 1530 mainGroup->addChild(formatGroup.release()); 1531 } 1532 } 1533 1534 return mainGroup.release(); 1535} 1536 1537} // pipeline 1538} // vkt 1539 1540