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