Home | History | Annotate | Download | only in ycbcr
      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 
     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 
    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 
    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 
    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 
    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 
    236 	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 
    251 	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 
    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 
    277 void checkSupport (Context& context, const TestParameters params)
    278 {
    279 	checkImageSupport(context, params.format, params.flags, params.tiling);
    280 }
    281 
    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 
    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 
    515 void initPrograms (SourceCollections& dst, TestParameters params)
    516 {
    517 	const ShaderSpec	spec	= getShaderSpec(params);
    518 
    519 	generateSources(params.shaderType, spec, dst);
    520 }
    521 
    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 
    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 
    585 tcu::TestCaseGroup* createFormatTests (tcu::TestContext& testCtx)
    586 {
    587 	return createTestGroup(testCtx, "format", "YCbCr Format Tests", populateFormatGroup);
    588 }
    589 
    590 } // ycbcr
    591 } // vkt
    592