/*-------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2017 Google Inc.
 *
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *      http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 *
 *//*!
 * \file
 * \brief YCbCr Format Tests
 *//*--------------------------------------------------------------------*/

#include "vktYCbCrFormatTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktCustomInstancesDevices.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktShaderExecutor.hpp"
#include "vktYCbCrUtil.hpp"

#include "vkStrUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkDeviceUtil.hpp"
#include "vkPlatform.hpp"

#include "tcuTestLog.hpp"
#include "tcuVectorUtil.hpp"

#include "deStringUtil.hpp"
#include "deSharedPtr.hpp"
#include "deUniquePtr.hpp"
#include "deRandom.hpp"
#include "deSTLUtil.hpp"

namespace vkt
{
namespace ycbcr
{
namespace
{

using namespace vk;
using namespace shaderexecutor;

using tcu::UVec2;
using tcu::Vec2;
using tcu::Vec4;
using tcu::TestLog;
using de::MovePtr;
using de::UniquePtr;
using std::vector;
using std::string;

Move<VkImage> createTestImage (const DeviceInterface&	vkd,
							   VkDevice					device,
							   VkFormat					format,
							   const UVec2&				size,
							   VkImageCreateFlags		createFlags,
							   VkImageTiling			tiling,
							   VkImageLayout			layout,
							   deUint32					arrayLayers)
{
	const VkImageCreateInfo		createInfo	=
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
		DE_NULL,
		createFlags,
		VK_IMAGE_TYPE_2D,
		format,
		makeExtent3D(size.x(), size.y(), 1u),
		1u,				// mipLevels
		arrayLayers,	// arrayLayers
		VK_SAMPLE_COUNT_1_BIT,
		tiling,
		VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
		VK_SHARING_MODE_EXCLUSIVE,
		0u,
		(const deUint32*)DE_NULL,
		layout,
	};

	return createImage(vkd, device, &createInfo);
}

Move<VkImageView> createImageView (const DeviceInterface&		vkd,
								   VkDevice						device,
								   VkImage						image,
								   VkFormat						format,
								   VkSamplerYcbcrConversion		conversion,
								   deUint32						layerCount)
{
	const VkSamplerYcbcrConversionInfo		conversionInfo	=
	{
		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
		DE_NULL,
		conversion
	};
	const VkImageViewCreateInfo				viewInfo		=
	{
		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
		&conversionInfo,
		(VkImageViewCreateFlags)0,
		image,
		(layerCount > 1) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D,
		format,
		{
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
		},
		{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, layerCount },
	};

	return createImageView(vkd, device, &viewInfo);
}

Move<VkDescriptorSetLayout> createDescriptorSetLayout (const DeviceInterface& vkd, VkDevice device, VkSampler sampler)
{
	const VkDescriptorSetLayoutBinding		binding			=
	{
		0u,													// binding
		VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
		1u,													// descriptorCount
		VK_SHADER_STAGE_ALL,
		&sampler
	};
	const VkDescriptorSetLayoutCreateInfo	layoutInfo	=
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
		DE_NULL,
		(VkDescriptorSetLayoutCreateFlags)0u,
		1u,
		&binding,
	};

	return createDescriptorSetLayout(vkd, device, &layoutInfo);
}

Move<VkDescriptorPool> createDescriptorPool (const DeviceInterface& vkd, VkDevice device)
{
	const VkDescriptorPoolSize			poolSizes[]	=
	{
		{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	1u	},
	};
	const VkDescriptorPoolCreateInfo	poolInfo	=
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,
		DE_NULL,
		(VkDescriptorPoolCreateFlags)VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,
		1u,		// maxSets
		DE_LENGTH_OF_ARRAY(poolSizes),
		poolSizes,
	};

	return createDescriptorPool(vkd, device, & poolInfo);
}

Move<VkDescriptorSet> createDescriptorSet (const DeviceInterface&	vkd,
										   VkDevice					device,
										   VkDescriptorPool			descPool,
										   VkDescriptorSetLayout	descLayout,
										   VkImageView				imageView)
{
	Move<VkDescriptorSet>					descSet;

	{
		const VkDescriptorSetAllocateInfo	allocInfo			=
		{
			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
			DE_NULL,
			descPool,
			1u,
			&descLayout,
		};

		descSet = allocateDescriptorSet(vkd, device, &allocInfo);
	}

	{
		const VkDescriptorImageInfo			imageInfo			=
		{
			0xdeadbeef,    // Not required to be valid. Use something invalid and not NULL
			imageView,
			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
		};
		const VkWriteDescriptorSet			descriptorWrite		=
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
			DE_NULL,
			*descSet,
			0u,		// dstBinding
			0u,		// dstArrayElement
			1u,		// descriptorCount
			VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
			&imageInfo,
			(const VkDescriptorBufferInfo*)DE_NULL,
			(const VkBufferView*)DE_NULL,
		};

		vkd.updateDescriptorSets(device, 1u, &descriptorWrite, 0u, DE_NULL);
	}

	return descSet;
}

struct TestParameters
{
	VkFormat			format;
	UVec2				size;
	VkImageCreateFlags	flags;
	VkImageTiling		tiling;
	glu::ShaderType		shaderType;
	bool				useMappedMemory;
	bool				useArrayLayers;

	TestParameters (VkFormat			format_,
					const UVec2&		size_,
					VkImageCreateFlags	flags_,
					VkImageTiling		tiling_,
					glu::ShaderType		shaderType_,
					bool				useMappedMemory_,
					bool				useArrayLayers_)
		: format			(format_)
		, size				(size_)
		, flags				(flags_)
		, tiling			(tiling_)
		, shaderType		(shaderType_)
		, useMappedMemory	(useMappedMemory_)
		, useArrayLayers	(useArrayLayers_)
	{
	}

	TestParameters (void)
		: format			(VK_FORMAT_UNDEFINED)
		, flags				(0u)
		, tiling			(VK_IMAGE_TILING_OPTIMAL)
		, shaderType		(glu::SHADERTYPE_LAST)
		, useMappedMemory	(false)
		, useArrayLayers	(false)
	{
	}
};

ShaderSpec getShaderSpec (const TestParameters& params)
{
	ShaderSpec spec;

	spec.inputs.push_back(Symbol("texCoord", glu::VarType(glu::TYPE_FLOAT_VEC2, glu::PRECISION_HIGHP)));
	spec.outputs.push_back(Symbol("result", glu::VarType(glu::TYPE_FLOAT_VEC4, glu::PRECISION_HIGHP)));

	if (params.useArrayLayers)
	{
		spec.globalDeclarations =
			"layout(binding = 0, set = 1) uniform highp sampler2DArray u_image;\n";
		spec.source =
			"result = texture(u_image, vec3(texCoord, 1u));\n";
	}
	else
	{
		spec.globalDeclarations =
			"layout(binding = 0, set = 1) uniform highp sampler2D u_image;\n";
		spec.source =
			"result = texture(u_image, texCoord);\n";
	}

	return spec;
}

void checkSupport (Context& context, const TestParameters params)
{
	checkImageSupport(context, params.format, params.flags, params.tiling);

	if (params.useArrayLayers)
	{
		if (!context.isDeviceFunctionalitySupported("VK_EXT_ycbcr_image_arrays"))
			TCU_THROW(NotSupportedError, "VK_EXT_ycbcr_image_arrays is not supported");

		VkImageFormatProperties properties = getPhysicalDeviceImageFormatProperties(context.getInstanceInterface(), context.getPhysicalDevice(),
			params.format, VK_IMAGE_TYPE_2D, params.tiling, VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT, params.flags);
		if (properties.maxArrayLayers < 2)
			TCU_THROW(NotSupportedError, "Image format does not support more than 1 maxArrayLayers");
	}
}

void generateLookupCoordinates (const UVec2& imageSize, vector<Vec2>* dst)
{
	dst->resize(imageSize.x() * imageSize.y());

	for (deUint32 texelY = 0; texelY < imageSize.y(); ++texelY)
	for (deUint32 texelX = 0; texelX < imageSize.x(); ++texelX)
	{
		const float		x	= ((float)texelX + 0.5f) / (float)imageSize.x();
		const float		y	= ((float)texelY + 0.5f) / (float)imageSize.y();

		(*dst)[texelY*imageSize.x() + texelX] = Vec2(x, y);
	}
}

tcu::TestStatus testFormat (Context& context, TestParameters params)
{
	const DeviceInterface&					vkd						= context.getDeviceInterface();
	const VkDevice							device					= context.getDevice();

	const VkFormat							format					= params.format;
	const PlanarFormatDescription			formatInfo				= getPlanarFormatDescription(format);
	const UVec2								size					= params.size;
	const VkImageCreateFlags				createFlags				= params.flags;
	const VkImageTiling						tiling					= params.tiling;
	const bool								mappedMemory			= params.useMappedMemory;
	const deUint32							arrayLayers				= (params.useArrayLayers) ? 2u : 1u;
	const deUint32							arrayLayer				= arrayLayers - 1u;

	const Unique<VkImage>					image					(createTestImage(vkd, device, format, size, createFlags, tiling, mappedMemory ? VK_IMAGE_LAYOUT_PREINITIALIZED : VK_IMAGE_LAYOUT_UNDEFINED, arrayLayers));
	const vector<AllocationSp>				allocations				(allocateAndBindImageMemory(vkd, device, context.getDefaultAllocator(), *image, format, createFlags, mappedMemory ? MemoryRequirement::HostVisible : MemoryRequirement::Any));

	const VkSamplerYcbcrConversionCreateInfo
											conversionInfo			=
	{
		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
		DE_NULL,
		format,
		VK_SAMPLER_YCBCR_MODEL_CONVERSION_RGB_IDENTITY,
		VK_SAMPLER_YCBCR_RANGE_ITU_FULL,
		{
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
			VK_COMPONENT_SWIZZLE_IDENTITY,
		},
		VK_CHROMA_LOCATION_MIDPOINT,
		VK_CHROMA_LOCATION_MIDPOINT,
		VK_FILTER_NEAREST,
		VK_FALSE,									// forceExplicitReconstruction
	};
	const Unique<VkSamplerYcbcrConversion>	conversion				(createSamplerYcbcrConversion(vkd, device, &conversionInfo));
	const Unique<VkImageView>				imageView				(createImageView(vkd, device, *image, format, *conversion, arrayLayers));

	const VkSamplerYcbcrConversionInfo		samplerConversionInfo	=
	{
		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO,
		DE_NULL,
		*conversion,
	};

	const VkSamplerCreateInfo				samplerInfo				=
	{
		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
		&samplerConversionInfo,
		0u,
		VK_FILTER_NEAREST,							// magFilter
		VK_FILTER_NEAREST,							// minFilter
		VK_SAMPLER_MIPMAP_MODE_NEAREST,				// mipmapMode
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeU
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeV
		VK_SAMPLER_ADDRESS_MODE_CLAMP_TO_EDGE,		// addressModeW
		0.0f,										// mipLodBias
		VK_FALSE,									// anisotropyEnable
		1.0f,										// maxAnisotropy
		VK_FALSE,									// compareEnable
		VK_COMPARE_OP_ALWAYS,						// compareOp
		0.0f,										// minLod
		0.0f,										// maxLod
		VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// borderColor
		VK_FALSE,									// unnormalizedCoords
	};

	const Unique<VkSampler>					sampler					(createSampler(vkd, device, &samplerInfo));

	const Unique<VkDescriptorSetLayout>		descLayout				(createDescriptorSetLayout(vkd, device, *sampler));
	const Unique<VkDescriptorPool>			descPool				(createDescriptorPool(vkd, device));
	const Unique<VkDescriptorSet>			descSet					(createDescriptorSet(vkd, device, *descPool, *descLayout, *imageView));

	MultiPlaneImageData						imageData				(format, size);

	const VkPhysicalDeviceImageFormatInfo2			imageFormatInfo	=
	{
		VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,
		DE_NULL,
		params.format,
		VK_IMAGE_TYPE_2D,
		params.tiling,
		VK_IMAGE_USAGE_TRANSFER_DST_BIT|VK_IMAGE_USAGE_SAMPLED_BIT,
		params.flags,
	};
	VkSamplerYcbcrConversionImageFormatProperties		ycbcrProperties =
	{
		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES,
		DE_NULL,
		0,
	};
	VkImageFormatProperties2				extProperties =
	{
		VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2,
		&ycbcrProperties,
		{
			{
				0,	// width
				0,	// height
				0,	// depth
			},
			0u,		// maxMipLevels
			0u,		// maxArrayLayers
			0,		// sampleCounts
			0u,		// maxResourceSize
		},
	};
	VkResult				propsResult;
	const CustomInstance			instance	(createCustomInstanceWithExtension(context, "VK_KHR_get_physical_device_properties2"));
	const InstanceDriver&			vki			(instance.getDriver());

	// Verify that a yuv image consumes at least one descriptor
	propsResult = vki.getPhysicalDeviceImageFormatProperties2(context.getPhysicalDevice(), &imageFormatInfo, &extProperties);

	TCU_CHECK(propsResult == VK_SUCCESS);
	TCU_CHECK(ycbcrProperties.combinedImageSamplerDescriptorCount >= 1);

	// Zero fill unused layer
	if (params.useArrayLayers)
	{
		fillZero(&imageData);

		if (mappedMemory)
		{
			fillImageMemory(vkd,
							device,
							context.getUniversalQueueFamilyIndex(),
							*image,
							allocations,
							imageData,
							(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
							VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
							0);
		}
		else
		{
			uploadImage(vkd,
						device,
						context.getUniversalQueueFamilyIndex(),
						context.getDefaultAllocator(),
						*image,
						imageData,
						(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
						VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
						0);
		}
	}

	// Prepare texture data
	fillGradient(&imageData, Vec4(0.0f), Vec4(1.0f));

	if (mappedMemory)
	{
		// Fill and prepare image
		fillImageMemory(vkd,
						device,
						context.getUniversalQueueFamilyIndex(),
						*image,
						allocations,
						imageData,
						(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
						VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
						arrayLayer);
	}
	else
	{
		// Upload and prepare image
		uploadImage(vkd,
					device,
					context.getUniversalQueueFamilyIndex(),
					context.getDefaultAllocator(),
					*image,
					imageData,
					(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
					VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
					arrayLayer);
	}

	{
		vector<Vec2>	texCoord;
		vector<Vec4>	result;
		vector<Vec4>	reference;
		bool			allOk		= true;
		Vec4			threshold	(0.02f);

		generateLookupCoordinates(size, &texCoord);

		result.resize(texCoord.size());
		reference.resize(texCoord.size());

		{
			UniquePtr<ShaderExecutor>	executor	(createExecutor(context, params.shaderType, getShaderSpec(params), *descLayout));
			const void*					inputs[]	= { texCoord[0].getPtr() };
			void*						outputs[]	= { result[0].getPtr() };

			executor->execute((int)texCoord.size(), inputs, outputs, *descSet);
		}

		for (deUint32 channelNdx = 0; channelNdx < 4; channelNdx++)
		{
			if (formatInfo.hasChannelNdx(channelNdx))
			{
				const tcu::ConstPixelBufferAccess	channelAccess	= imageData.getChannelAccess(channelNdx);
				const tcu::Sampler					refSampler		= mapVkSampler(samplerInfo);
				const tcu::Texture2DView			refTexView		(1u, &channelAccess);

				for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
				{
					const Vec2&	coord	= texCoord[ndx];
					reference[ndx][channelNdx] = refTexView.sample(refSampler, coord.x(), coord.y(), 0.0f)[0];
				}
			}
			else
			{
				for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
					reference[ndx][channelNdx] = channelNdx == 3 ? 1.0f : 0.0f;
			}
		}

		for (size_t ndx = 0; ndx < texCoord.size(); ++ndx)
		{
			if (boolAny(greaterThanEqual(abs(result[ndx] - reference[ndx]), threshold)))
			{
				context.getTestContext().getLog()
					<< TestLog::Message << "ERROR: At " << texCoord[ndx]
										<< ": got " << result[ndx]
										<< ", expected " << reference[ndx]
					<< TestLog::EndMessage;
				allOk = false;
			}
		}

		if (allOk)
			return tcu::TestStatus::pass("All samples passed");
		else
		{
			const tcu::ConstPixelBufferAccess	refAccess	(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
															 tcu::IVec3((int)size.x(), (int)size.y(), 1u),
															 reference[0].getPtr());
			const tcu::ConstPixelBufferAccess	resAccess	(tcu::TextureFormat(tcu::TextureFormat::RGBA, tcu::TextureFormat::FLOAT),
															 tcu::IVec3((int)size.x(), (int)size.y(), 1u),
															 result[0].getPtr());

			context.getTestContext().getLog()
				<< TestLog::Image("Result", "Result Image", resAccess, Vec4(1.0f), Vec4(0.0f))
				<< TestLog::Image("Reference", "Reference Image", refAccess, Vec4(1.0f), Vec4(0.0f));

			return tcu::TestStatus::fail("Got invalid results");
		}
	}
}

void initPrograms (SourceCollections& dst, TestParameters params)
{
	const ShaderSpec	spec	= getShaderSpec(params);

	generateSources(params.shaderType, spec, dst);
}

void populatePerFormatGroup (tcu::TestCaseGroup* group, VkFormat format)
{
	const UVec2				size			(66, 32);
	const glu::ShaderType	shaderTypes[]	=
	{
		glu::SHADERTYPE_VERTEX,
		glu::SHADERTYPE_FRAGMENT,
		glu::SHADERTYPE_GEOMETRY,
		glu::SHADERTYPE_TESSELLATION_CONTROL,
		glu::SHADERTYPE_TESSELLATION_EVALUATION,
		glu::SHADERTYPE_COMPUTE
	};
	const struct
	{
		const char*		name;
		VkImageTiling	value;
	} tilings[] =
	{
		{ "optimal",	VK_IMAGE_TILING_OPTIMAL },
		{ "linear",		VK_IMAGE_TILING_LINEAR }
	};

	for (glu::ShaderType shaderType : shaderTypes)
	for (int tilingNdx = 0; tilingNdx < DE_LENGTH_OF_ARRAY(tilings); tilingNdx++)
	for (int useArrayLayers = 0; useArrayLayers < 2; useArrayLayers++)
	{
		const VkImageTiling		tiling			= tilings[tilingNdx].value;
		const char* const		tilingName		= tilings[tilingNdx].name;
		const char* const		shaderTypeName	= glu::getShaderTypeName(shaderType);
		const string			name			= string(shaderTypeName) + "_" + tilingName + ((useArrayLayers) ? "_array" : "");

		addFunctionCaseWithPrograms(group, name, "", checkSupport, initPrograms, testFormat, TestParameters(format, size, 0u, tiling, shaderType, false, useArrayLayers));

		if (getPlaneCount(format) > 1)
			addFunctionCaseWithPrograms(group, name + "_disjoint", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT, tiling, shaderType, false, useArrayLayers));

		if (tiling == VK_IMAGE_TILING_LINEAR)
		{
			addFunctionCaseWithPrograms(group, name + "_mapped", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, 0u, tiling, shaderType, true, useArrayLayers));

			if (getPlaneCount(format) > 1)
				addFunctionCaseWithPrograms(group, name + "_disjoint_mapped", "", checkSupport, initPrograms, testFormat, TestParameters(format, size, (VkImageCreateFlags)VK_IMAGE_CREATE_DISJOINT_BIT, tiling, shaderType, true, useArrayLayers));
		}
	}
}

void populateFormatGroup (tcu::TestCaseGroup* group)
{
	for (int formatNdx = VK_YCBCR_FORMAT_FIRST; formatNdx < VK_YCBCR_FORMAT_LAST; formatNdx++)
	{
		const VkFormat					format			= (VkFormat)formatNdx;
		const string					formatName		= de::toLower(de::toString(format).substr(10));

		group->addChild(createTestGroup<VkFormat>(group->getTestContext(), formatName, "", populatePerFormatGroup, format));
	}
}

} // namespace

tcu::TestCaseGroup* createFormatTests (tcu::TestContext& testCtx)
{
	return createTestGroup(testCtx, "format", "YCbCr Format Tests", populateFormatGroup);
}

} // ycbcr
} // vkt
