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 (
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
72 struct 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
isCustomvkt::pipeline::__anon3941c96b0111::TestParams88 bool isCustom (void) const
89 {
90 return (borderColor == VK_BORDER_COLOR_INT_CUSTOM_EXT || borderColor == VK_BORDER_COLOR_FLOAT_CUSTOM_EXT);
91 }
92
isOpaqueBlackvkt::pipeline::__anon3941c96b0111::TestParams93 bool isOpaqueBlack (void) const
94 {
95 return (borderColor == VK_BORDER_COLOR_INT_OPAQUE_BLACK || borderColor == VK_BORDER_COLOR_FLOAT_OPAQUE_BLACK);
96 }
97
isIdentityvkt::pipeline::__anon3941c96b0111::TestParams98 bool isIdentity (void) const
99 {
100 return isIdentitySwizzle(componentMapping);
101 }
102 };
103
104 struct SpecConstants
105 {
106 float u;
107 float v;
108 deInt32 gatherFlag;
109 //deInt32 gatherComp;
110 };
111
112 class BorderSwizzleCase : public vkt::TestCase
113 {
114 public:
115 BorderSwizzleCase (tcu::TestContext& testCtx, const std::string& name, const TestParams& params);
~BorderSwizzleCase(void)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
122 protected:
123 TestParams m_params;
124 };
125
126 class BorderSwizzleInstance : public vkt::TestInstance
127 {
128 public:
129 BorderSwizzleInstance (Context& context, const TestParams ¶ms);
~BorderSwizzleInstance(void)130 virtual ~BorderSwizzleInstance (void) {}
131
132 VkExtent3D getImageExtent (void) const;
133 virtual tcu::TestStatus iterate (void);
134
135 protected:
136 TestParams m_params;
137 };
138
BorderSwizzleCase(tcu::TestContext & testCtx,const std::string & name,const TestParams & params)139 BorderSwizzleCase::BorderSwizzleCase(tcu::TestContext& testCtx, const std::string& name, const TestParams& params)
140 : vkt::TestCase (testCtx, name)
141 , m_params (params)
142 {
143 }
144
checkSupport(Context & context) const145 void 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
217 enum class FormatType
218 {
219 SIGNED_INT = 0,
220 UNSIGNED_INT,
221 FLOAT,
222 };
223
getFormatType(VkFormat format,bool useStencil)224 FormatType 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.
getColorAttachmentFormat(VkFormat textureFormat,bool useStencil)236 VkFormat 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
initPrograms(vk::SourceCollections & programCollection) const249 void 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
createInstance(Context & context) const310 TestInstance* BorderSwizzleCase::createInstance (Context& context) const
311 {
312 return new BorderSwizzleInstance(context, m_params);
313 }
314
BorderSwizzleInstance(Context & context,const TestParams & params)315 BorderSwizzleInstance::BorderSwizzleInstance (Context& context, const TestParams ¶ms)
316 : vkt::TestInstance (context)
317 , m_params (params)
318 {}
319
getImageExtent(void) const320 VkExtent3D 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.
calcFloatDiff(float a,float b)327 deUint64 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.
makeComponentSwizzleVec(const VkComponentMapping & mapping)344 tcu::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.
351 template <typename T>
applySwizzle(const tcu::Vector<T,4> & orig,const VkComponentMapping & mapping)352 tcu::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.
376 template <typename T>
applyGather(const tcu::Vector<T,4> & orig,int compNum)377 tcu::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.
388 template <typename T>
getExpectedColor(const tcu::Vector<T,4> & color,const TestParams & params)389 tcu::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.
getExpectedColor(const VkClearColorValue & color,const TestParams & params)403 VkClearColorValue 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.
comparePixelToColorClearValue(const TestParams & params,const tcu::ConstPixelBufferAccess & access,const tcu::TextureFormat & textureFormat_,const VkClearColorValue & ref,std::string & stringResult)504 bool 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.
getBorderClearColorValue(const TestParams & params)786 VkClearColorValue 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
iterate(void)807 tcu::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
1111 using ComponentSwizzleArray = std::array<VkComponentSwizzle, 4>;
1112
1113 // Convert the component swizzle array to a component mapping structure.
makeComponentMapping(VkComponentMapping & mapping,const ComponentSwizzleArray & array)1114 void 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
swizzleArrayToString(const ComponentSwizzleArray & swizzles)1122 std::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.
genMappingPermutations()1147 std::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
gatherIndexToString(int gatherIndex)1178 std::string gatherIndexToString(int gatherIndex)
1179 {
1180 if (gatherIndex < 0)
1181 return "no_gather";
1182 return "gather_" + std::to_string(gatherIndex);
1183 }
1184
isIntegerBorder(VkBorderColor borderType)1185 bool 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
getRandomBorderCoordinates(de::Random & rnd)1207 tcu::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.
getRandomClearColor(VkFormat format,de::Random & rnd,bool useStencil)1230 VkClearColorValue 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
createSamplerBorderSwizzleTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)1272 tcu::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