1 /*-------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
4 *
5 * Copyright (c) 2017 Google Inc.
6 *
7 * Licensed under the Apache License, Version 2.0 (the "License");
8 * you may not use this file except in compliance with the License.
9 * You may obtain a copy of the License at
10 *
11 * http://www.apache.org/licenses/LICENSE-2.0
12 *
13 * Unless required by applicable law or agreed to in writing, software
14 * distributed under the License is distributed on an "AS IS" BASIS,
15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16 * See the License for the specific language governing permissions and
17 * limitations under the License.
18 *
19 *//*!
20 * \file
21 * \brief YCbCr Format Tests
22 *//*--------------------------------------------------------------------*/
23
24 #include "vktYCbCrFormatTests.hpp"
25 #include "vktTestCaseUtil.hpp"
26 #include "vktTestGroupUtil.hpp"
27 #include "vktShaderExecutor.hpp"
28 #include "vktYCbCrUtil.hpp"
29
30 #include "vkStrUtil.hpp"
31 #include "vkRef.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkQueryUtil.hpp"
35 #include "vkMemUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkDeviceUtil.hpp"
38 #include "vkPlatform.hpp"
39
40 #include "tcuTestLog.hpp"
41 #include "tcuVectorUtil.hpp"
42
43 #include "deStringUtil.hpp"
44 #include "deSharedPtr.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deRandom.hpp"
47 #include "deSTLUtil.hpp"
48
49 namespace vkt
50 {
51 namespace ycbcr
52 {
53 namespace
54 {
55
56 // \todo [2017-05-24 pyry] Extend:
57 // * VK_IMAGE_TILING_LINEAR
58 // * Other shader types
59
60 using namespace vk;
61 using namespace shaderexecutor;
62
63 using tcu::UVec2;
64 using tcu::Vec2;
65 using tcu::Vec4;
66 using tcu::TestLog;
67 using de::MovePtr;
68 using de::UniquePtr;
69 using std::vector;
70 using std::string;
71
72 typedef de::SharedPtr<Allocation> AllocationSp;
73 typedef de::SharedPtr<vk::Unique<VkBuffer> > VkBufferSp;
74
createTestImage(const DeviceInterface & vkd,VkDevice device,VkFormat format,const UVec2 & size,VkImageCreateFlags createFlags,VkImageTiling tiling,VkImageLayout layout)75 Move<VkImage> createTestImage (const DeviceInterface& vkd,
76 VkDevice device,
77 VkFormat format,
78 const UVec2& size,
79 VkImageCreateFlags createFlags,
80 VkImageTiling tiling,
81 VkImageLayout layout)
82 {
83 const VkImageCreateInfo createInfo =
84 {
85 VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
86 DE_NULL,
87 createFlags,
88 VK_IMAGE_TYPE_2D,
89 format,
90 makeExtent3D(size.x(), size.y(), 1u),
91 1u, // mipLevels
92 1u, // arrayLayers
93 VK_SAMPLE_COUNT_1_BIT,
94 tiling,
95 VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
96 VK_SHARING_MODE_EXCLUSIVE,
97 0u,
98 (const deUint32*)DE_NULL,
99 layout,
100 };
101
102 return createImage(vkd, device, &createInfo);
103 }
104
createImageView(const DeviceInterface & vkd,VkDevice device,VkImage image,VkFormat format,VkSamplerYcbcrConversion conversion)105 Move<VkImageView> createImageView (const DeviceInterface& vkd,
106 VkDevice device,
107 VkImage image,
108 VkFormat format,
109 VkSamplerYcbcrConversion conversion)
110 {
111 const VkSamplerYcbcrConversionInfo conversionInfo =
112 {
113 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
114 DE_NULL,
115 conversion
116 };
117 const VkImageViewCreateInfo viewInfo =
118 {
119 VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
120 &conversionInfo,
121 (VkImageViewCreateFlags)0,
122 image,
123 VK_IMAGE_VIEW_TYPE_2D,
124 format,
125 {
126 VK_COMPONENT_SWIZZLE_IDENTITY,
127 VK_COMPONENT_SWIZZLE_IDENTITY,
128 VK_COMPONENT_SWIZZLE_IDENTITY,
129 VK_COMPONENT_SWIZZLE_IDENTITY,
130 },
131 { VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u },
132 };
133
134 return createImageView(vkd, device, &viewInfo);
135 }
136
createDescriptorSetLayout(const DeviceInterface & vkd,VkDevice device,VkSampler sampler)137 Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler sampler)
138 {
139 const VkDescriptorSetLayoutBinding binding =
140 {
141 0u, // binding
142 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
143 1u, // descriptorCount
144 VK_SHADER_STAGE_ALL,
145 &sampler
146 };
147 const VkDescriptorSetLayoutCreateInfo layoutInfo =
148 {
149 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
150 DE_NULL,
151 (VkDescriptorSetLayoutCreateFlags)0u,
152 1u,
153 &binding,
154 };
155
156 return createDescriptorSetLayout(vkd, device, &layoutInfo);
157 }
158
createDescriptorPool(const DeviceInterface & vkd,VkDevice device)159 Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device)
160 {
161 const VkDescriptorPoolSize poolSizes[] =
162 {
163 { VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u },
164 };
165 const VkDescriptorPoolCreateInfo poolInfo =
166 {
167 VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
168 DE_NULL,
169 (VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
170 1u, // maxSets
171 DE_LENGTH_OF_ARRAY(poolSizes),
172 poolSizes,
173 };
174
175 return createDescriptorPool(vkd, device, & poolInfo);
176 }
177
createDescriptorSet(const DeviceInterface & vkd,VkDevice device,VkDescriptorPool descPool,VkDescriptorSetLayout descLayout,VkImageView imageView,VkSampler sampler)178 Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface& vkd,
179 VkDevice device,
180 VkDescriptorPool descPool,
181 VkDescriptorSetLayout descLayout,
182 VkImageView imageView,
183 VkSampler sampler)
184 {
185 Move<VkDescriptorSet> descSet;
186
187 {
188 const VkDescriptorSetAllocateInfo allocInfo =
189 {
190 VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
191 DE_NULL,
192 descPool,
193 1u,
194 &descLayout,
195 };
196
197 descSet = allocateDescriptorSet(vkd, device, &allocInfo);
198 }
199
200 {
201 const VkDescriptorImageInfo imageInfo =
202 {
203 sampler,
204 imageView,
205 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
206 };
207 const VkWriteDescriptorSet descriptorWrite =
208 {
209 VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
210 DE_NULL,
211 *descSet,
212 0u, // dstBinding
213 0u, // dstArrayElement
214 1u, // descriptorCount
215 VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
216 &imageInfo,
217 (const VkDescriptorBufferInfo*)DE_NULL,
218 (const VkBufferView*)DE_NULL,
219 };
220
221 vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
222 }
223
224 return descSet;
225 }
226
227 struct TestParameters
228 {
229 VkFormat format;
230 UVec2 size;
231 VkImageCreateFlags flags;
232 VkImageTiling tiling;
233 glu::ShaderType shaderType;
234 bool useMappedMemory;
235
TestParametersvkt::ycbcr::__anonb656f1e50111::TestParameters236 TestParameters (VkFormat format_,
237 const UVec2& size_,
238 VkImageCreateFlags flags_,
239 VkImageTiling tiling_,
240 glu::ShaderType shaderType_,
241 bool useMappedMemory_)
242 : format (format_)
243 , size (size_)
244 , flags (flags_)
245 , tiling (tiling_)
246 , shaderType (shaderType_)
247 , useMappedMemory (useMappedMemory_)
248 {
249 }
250
TestParametersvkt::ycbcr::__anonb656f1e50111::TestParameters251 TestParameters (void)
252 : format (VK_FORMAT_UNDEFINED)
253 , flags (0u)
254 , tiling (VK_IMAGE_TILING_OPTIMAL)
255 , shaderType (glu::SHADERTYPE_LAST)
256 , useMappedMemory (false)
257 {
258 }
259 };
260
getShaderSpec(const TestParameters &)261 ShaderSpec getShaderSpec (const TestParameters&)
262 {
263 ShaderSpec spec;
264
265 spec.inputs.push_back(Symbol("texCoord", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
266 spec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));
267
268 spec.globalDeclarations =
269 "layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n";
270
271 spec.source =
272 "result = texture(u_image, texCoord);\n";
273
274 return spec;
275 }
276
checkSupport(Context & context,const TestParameters params)277 void checkSupport (Context& context, const TestParameters params)
278 {
279 checkImageSupport(context, params.format, params.flags, params.tiling);
280 }
281
generateLookupCoordinates(const UVec2 & imageSize,vector<Vec2> * dst)282 void generateLookupCoordinates (const UVec2& imageSize, vector<Vec2>* dst)
283 {
284 dst->resize(imageSize.x() * imageSize.y());
285
286 for (deUint32 texelY = 0; texelY < imageSize.y(); ++texelY)
287 for (deUint32 texelX = 0; texelX < imageSize.x(); ++texelX)
288 {
289 const float x = ((float)texelX + 0.5f) / (float)imageSize.x();
290 const float y = ((float)texelY + 0.5f) / (float)imageSize.y();
291
292 (*dst)[texelY*imageSize.x() + texelX] = Vec2(x, y);
293 }
294 }
295
testFormat(Context & context,TestParameters params)296 tcu::TestStatus testFormat (Context& context, TestParameters params)
297 {
298 const DeviceInterface& vkd = context.getDeviceInterface();
299 const VkDevice device = context.getDevice();
300
301 const VkFormat format = params.format;
302 const PlanarFormatDescription formatInfo = getPlanarFormatDescription(format);
303 const UVec2 size = params.size;
304 const VkImageCreateFlags createFlags = params.flags;
305 const VkImageTiling tiling = params.tiling;
306 const bool mappedMemory = params.useMappedMemory;
307
308 const Unique<VkImage> image (createTestImage(vkd, device, format, size, createFlags, tiling, mappedMemory ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED));
309 const vector<AllocationSp> allocations (allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags, mappedMemory ? MemoryRequirement::HostVisible : MemoryRequirement::Any));
310
311 const VkSamplerYcbcrConversionCreateInfo
312 conversionInfo =
313 {
314 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
315 DE_NULL,
316 format,
317 VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
318 VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
319 {
320 VK_COMPONENT_SWIZZLE_IDENTITY,
321 VK_COMPONENT_SWIZZLE_IDENTITY,
322 VK_COMPONENT_SWIZZLE_IDENTITY,
323 VK_COMPONENT_SWIZZLE_IDENTITY,
324 },
325 VK_CHROMA_LOCATION_MIDPOINT,
326 VK_CHROMA_LOCATION_MIDPOINT,
327 VK_FILTER_NEAREST,
328 VK_FALSE, // forceExplicitReconstruction
329 };
330 const Unique<VkSamplerYcbcrConversion> conversion (createSamplerYcbcrConversion(vkd, device, &conversionInfo));
331 const Unique<VkImageView> imageView (createImageView(vkd, device, *image, format, *conversion));
332
333 const VkSamplerYcbcrConversionInfo samplerConversionInfo =
334 {
335 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
336 DE_NULL,
337 *conversion,
338 };
339
340 const VkSamplerCreateInfo samplerInfo =
341 {
342 VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
343 &samplerConversionInfo,
344 0u,
345 VK_FILTER_NEAREST, // magFilter
346 VK_FILTER_NEAREST, // minFilter
347 VK_SAMPLER_MIPMAP_MODE_NEAREST, // mipmapMode
348 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeU
349 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeV
350 VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE, // addressModeW
351 0.0f, // mipLodBias
352 VK_FALSE, // anisotropyEnable
353 1.0f, // maxAnisotropy
354 VK_FALSE, // compareEnable
355 VK_COMPARE_OP_ALWAYS, // compareOp
356 0.0f, // minLod
357 0.0f, // maxLod
358 VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK, // borderColor
359 VK_FALSE, // unnormalizedCoords
360 };
361
362 const Unique<VkSampler> sampler (createSampler(vkd, device, &samplerInfo));
363
364 const Unique<VkDescriptorSetLayout> descLayout (createDescriptorSetLayout(vkd, device, *sampler));
365 const Unique<VkDescriptorPool> descPool (createDescriptorPool(vkd, device));
366 const Unique<VkDescriptorSet> descSet (createDescriptorSet(vkd, device, *descPool, *descLayout, *imageView, *sampler));
367
368 MultiPlaneImageData imageData (format, size);
369
370 const VkPhysicalDeviceImageFormatInfo2 imageFormatInfo =
371 {
372 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
373 DE_NULL,
374 params.format,
375 VK_IMAGE_TYPE_2D,
376 params.tiling,
377 VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
378 params.flags,
379 };
380 VkSamplerYcbcrConversionImageFormatProperties ycbcrProperties =
381 {
382 VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES,
383 DE_NULL,
384 0,
385 };
386 VkImageFormatProperties2 extProperties =
387 {
388 VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
389 &ycbcrProperties,
390 {
391 {
392 0, // width
393 0, // height
394 0, // depth
395 },
396 0u, // maxMipLevels
397 0u, // maxArrayLayers
398 0, // sampleCounts
399 0u, // maxResourceSize
400 },
401 };
402 VkResult propsResult;
403 const PlatformInterface& vkp = context.getPlatformInterface();
404 const Unique<VkInstance> instance (createInstanceWithExtension(vkp, context.getUsedApiVersion(), "VK_KHR_get_physical_device_properties2"));
405 const InstanceDriver vki (vkp, *instance);
406
407 // Verify that a yuv image consumes at least one descriptor
408 propsResult = vki.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &extProperties);
409
410 TCU_CHECK(propsResult == VK_SUCCESS);
411 TCU_CHECK(ycbcrProperties.combinedImageSamplerDescriptorCount >= 1);
412
413 // Prepare texture data
414 fillGradient(&imageData, Vec4(0.0f), Vec4(1.0f));
415
416 if (mappedMemory)
417 {
418 // Fill and prepare image
419 fillImageMemory(vkd,
420 device,
421 context.getUniversalQueueFamilyIndex(),
422 *image,
423 allocations,
424 imageData,
425 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
426 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
427 }
428 else
429 {
430 // Upload and prepare image
431 uploadImage(vkd,
432 device,
433 context.getUniversalQueueFamilyIndex(),
434 context.getDefaultAllocator(),
435 *image,
436 imageData,
437 (VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
438 VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
439 }
440
441 {
442 vector<Vec2> texCoord;
443 vector<Vec4> result;
444 vector<Vec4> reference;
445 bool allOk = true;
446 Vec4 threshold (0.02f);
447
448 generateLookupCoordinates(size, &texCoord);
449
450 result.resize(texCoord.size());
451 reference.resize(texCoord.size());
452
453 {
454 UniquePtr<ShaderExecutor> executor (createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
455 const void* inputs[] = { texCoord[0].getPtr() };
456 void* outputs[] = { result[0].getPtr() };
457
458 executor->execute((int)texCoord.size(), inputs, outputs, *descSet);
459 }
460
461 for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++)
462 {
463 if (formatInfo.hasChannelNdx(channelNdx))
464 {
465 const tcu::ConstPixelBufferAccess channelAccess = imageData.getChannelAccess(channelNdx);
466 const tcu::Sampler refSampler = mapVkSampler(samplerInfo);
467 const tcu::Texture2DView refTexView (1u, &channelAccess);
468
469 for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
470 {
471 const Vec2& coord = texCoord[ndx];
472 reference[ndx][channelNdx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f)[0];
473 }
474 }
475 else
476 {
477 for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
478 reference[ndx][channelNdx] = channelNdx == 3 ? 1.0f : 0.0f;
479 }
480 }
481
482 for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
483 {
484 if (boolAny(greaterThanEqual(abs(result[ndx] - reference[ndx]), threshold)))
485 {
486 context.getTestContext().getLog()
487 << TestLog::Message << "ERROR: At " << texCoord[ndx]
488 << ": got " << result[ndx]
489 << ", expected " << reference[ndx]
490 << TestLog::EndMessage;
491 allOk = false;
492 }
493 }
494
495 if (allOk)
496 return tcu::TestStatus::pass("All samples passed");
497 else
498 {
499 const tcu::ConstPixelBufferAccess refAccess (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
500 tcu::IVec3((int)size.x(), (int)size.y(), 1u),
501 reference[0].getPtr());
502 const tcu::ConstPixelBufferAccess resAccess (tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
503 tcu::IVec3((int)size.x(), (int)size.y(), 1u),
504 result[0].getPtr());
505
506 context.getTestContext().getLog()
507 << TestLog::Image("Result", "Result Image", resAccess, Vec4(1.0f), Vec4(0.0f))
508 << TestLog::Image("Reference", "Reference Image", refAccess, Vec4(1.0f), Vec4(0.0f));
509
510 return tcu::TestStatus::fail("Got invalid results");
511 }
512 }
513 }
514
initPrograms(SourceCollections & dst,TestParameters params)515 void initPrograms (SourceCollections& dst, TestParameters params)
516 {
517 const ShaderSpec spec = getShaderSpec(params);
518
519 generateSources(params.shaderType, spec, dst);
520 }
521
populatePerFormatGroup(tcu::TestCaseGroup * group,VkFormat format)522 void populatePerFormatGroup (tcu::TestCaseGroup* group, VkFormat format)
523 {
524 const UVec2 size (66, 32);
525 const struct
526 {
527 const char* name;
528 glu::ShaderType value;
529 } shaderTypes[] =
530 {
531 { "vertex", glu::SHADERTYPE_VERTEX },
532 { "fragment", glu::SHADERTYPE_FRAGMENT },
533 { "geometry", glu::SHADERTYPE_GEOMETRY },
534 { "tess_control", glu::SHADERTYPE_TESSELLATION_CONTROL },
535 { "tess_eval", glu::SHADERTYPE_TESSELLATION_EVALUATION },
536 { "compute", glu::SHADERTYPE_COMPUTE }
537 };
538 const struct
539 {
540 const char* name;
541 VkImageTiling value;
542 } tilings[] =
543 {
544 { "optimal", VK_IMAGE_TILING_OPTIMAL },
545 { "linear", VK_IMAGE_TILING_LINEAR }
546 };
547
548 for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); shaderTypeNdx++)
549 for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(tilings); tilingNdx++)
550 {
551 const VkImageTiling tiling = tilings[tilingNdx].value;
552 const char* const tilingName = tilings[tilingNdx].name;
553 const glu::ShaderType shaderType = shaderTypes[shaderTypeNdx].value;
554 const char* const shaderTypeName = shaderTypes[shaderTypeNdx].name;
555 const string name = string(shaderTypeName) + "_" + tilingName;
556
557 addFunctionCaseWithPrograms(group, name, "", checkSupport, initPrograms, testFormat, TestParameters(format, size, 0u, tiling, shaderType, false));
558
559 if (getPlaneCount(format) > 1)
560 addFunctionCaseWithPrograms(group, name + "_disjoint", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT, tiling, shaderType, false));
561
562 if (tiling == VK_IMAGE_TILING_LINEAR)
563 {
564 addFunctionCaseWithPrograms(group, name + "_mapped", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, 0u, tiling, shaderType, true));
565
566 if (getPlaneCount(format) > 1)
567 addFunctionCaseWithPrograms(group, name + "_disjoint_mapped", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT, tiling, shaderType, true));
568 }
569 }
570 }
571
populateFormatGroup(tcu::TestCaseGroup * group)572 void populateFormatGroup (tcu::TestCaseGroup* group)
573 {
574 for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
575 {
576 const VkFormat format = (VkFormat)formatNdx;
577 const string formatName = de::toLower(de::toString(format).substr(10));
578
579 group->addChild(createTestGroup<VkFormat>(group->getTestContext(), formatName, "", populatePerFormatGroup, format));
580 }
581 }
582
583 } // namespace
584
createFormatTests(tcu::TestContext & testCtx)585 tcu::TestCaseGroup* createFormatTests (tcu::TestContext& testCtx)
586 {
587 return createTestGroup(testCtx, "format", "YCbCr Format Tests", populateFormatGroup);
588 }
589
590 } // ycbcr
591 } // vkt
592