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