/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2020 The Khronos Group 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 filtering tests.
 *//*--------------------------------------------------------------------*/

#include "tcuVectorUtil.hpp"
#include "tcuTexVerifierUtil.hpp"
#include "tcuImageCompare.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPrograms.hpp"
#include "vkRefUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktYCbCrFilteringTests.hpp"
#include "vktDrawUtil.hpp"
#include "vktYCbCrUtil.hpp"
#include "gluTextureTestUtil.hpp"
#include <string>
#include <vector>

using namespace vk;
using namespace vkt::drawutil;

namespace vkt
{
namespace ycbcr
{
namespace
{

using std::vector;
using std::string;
using tcu::TestLog;
using tcu::Sampler;
using namespace glu::TextureTestUtil;

class LinearFilteringTestInstance: public TestInstance
{
public:
	LinearFilteringTestInstance(Context& context, VkFormat format);
	~LinearFilteringTestInstance() = default;

protected:

	VkSamplerCreateInfo				getSamplerInfo				(VkFilter								minMagFilter,
																 const VkSamplerYcbcrConversionInfo*	samplerConversionInfo = DE_NULL);
	Move<VkDescriptorSetLayout>		createDescriptorSetLayout	(VkSampler sampler);
	Move<VkDescriptorPool>			createDescriptorPool		(const deUint32 combinedSamplerDescriptorCount);
	Move<VkDescriptorSet>			createDescriptorSet			(VkDescriptorPool		descPool,
																 VkDescriptorSetLayout	descLayout);
	Move<VkSamplerYcbcrConversion>	createYCbCrConversion		(void);
	Move<VkImage>					createImage					(deUint32 width, deUint32 height);
	Move<VkImageView>				createImageView				(const VkSamplerYcbcrConversionInfo& samplerConversionInfo, VkImage image);
	void							bindImage					(VkDescriptorSet		descriptorSet,
																 VkImageView			imageView,
																 VkSampler				sampler);
	tcu::TestStatus					iterate						(void);
	void							getExplicitFilteringRefData	(const MultiPlaneImageData& imageData, vector<deUint8>& refData);
	void							getImplicitFilteringRefData	(const MultiPlaneImageData& imageData, vector<deUint8>& refData);


private:

	struct FilterCase
	{
		const tcu::UVec2 imageSize;
		const tcu::UVec2 renderSize;
	};

	const VkFormat				m_format;
	const DeviceInterface&		m_vkd;
	const VkDevice				m_device;
	int							m_caseIndex;
	const vector<FilterCase>	m_cases;
};

LinearFilteringTestInstance::LinearFilteringTestInstance(Context& context, VkFormat format)
	: TestInstance	(context)
	, m_format		(format)
	, m_vkd			(m_context.getDeviceInterface())
	, m_device		(m_context.getDevice())
	, m_caseIndex	(0)
	, m_cases		{
		{ { 8,  8}, {64, 64} },
		{ {64, 32}, {32, 64} }
	}
{
}

VkSamplerCreateInfo LinearFilteringTestInstance::getSamplerInfo(VkFilter minMagFilter, const VkSamplerYcbcrConversionInfo* samplerConversionInfo)
{
	return
	{
		VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,
		samplerConversionInfo,
		0u,
		minMagFilter,								// magFilter
		minMagFilter,								// 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
	};
}

Move<VkDescriptorSetLayout> LinearFilteringTestInstance::createDescriptorSetLayout(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(m_vkd, m_device, &layoutInfo);
}

Move<VkDescriptorPool> LinearFilteringTestInstance::createDescriptorPool(const deUint32 combinedSamplerDescriptorCount)
{
	const VkDescriptorPoolSize poolSizes[] =
	{
		{ VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,	combinedSamplerDescriptorCount	},
	};
	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(m_vkd, m_device, &poolInfo);
}

Move<VkDescriptorSet> LinearFilteringTestInstance::createDescriptorSet(VkDescriptorPool			descPool,
																	   VkDescriptorSetLayout	descLayout)
{
	const VkDescriptorSetAllocateInfo allocInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,
		DE_NULL,
		descPool,
		1u,
		&descLayout,
	};

	return allocateDescriptorSet(m_vkd, m_device, &allocInfo);
}

Move<VkSamplerYcbcrConversion> LinearFilteringTestInstance::createYCbCrConversion()
{
	const VkSamplerYcbcrConversionCreateInfo conversionInfo =
	{
		VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_CREATE_INFO,
		DE_NULL,
		m_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,							// chromaFilter
		VK_FALSE,									// forceExplicitReconstruction
	};

	return createSamplerYcbcrConversion(m_vkd, m_device, &conversionInfo);
}

Move<VkImage> LinearFilteringTestInstance::createImage(deUint32 width, deUint32 height)
{
	VkImageCreateFlags			createFlags = 0u;
	const VkImageCreateInfo		createInfo =
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,
		DE_NULL,
		createFlags,
		VK_IMAGE_TYPE_2D,
		m_format,
		makeExtent3D(width, height, 1u),
		1u,		// mipLevels
		1u,		// arrayLayers
		VK_SAMPLE_COUNT_1_BIT,
		VK_IMAGE_TILING_OPTIMAL,
		VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_SAMPLED_BIT,
		VK_SHARING_MODE_EXCLUSIVE,
		0u,
		(const deUint32*)DE_NULL,
		VK_IMAGE_LAYOUT_UNDEFINED,
	};

	return ::createImage(m_vkd, m_device, &createInfo);
}

Move<VkImageView> LinearFilteringTestInstance::createImageView(const VkSamplerYcbcrConversionInfo& samplerConversionInfo, VkImage image)
{
	const VkImageViewCreateInfo	viewInfo =
	{
		VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
		&samplerConversionInfo,
		(VkImageViewCreateFlags)0,
		image,
		VK_IMAGE_VIEW_TYPE_2D,
		m_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, 1u },
	};

	return ::createImageView(m_vkd, m_device, &viewInfo);
}

void LinearFilteringTestInstance::bindImage(VkDescriptorSet	descriptorSet,
											VkImageView		imageView,
											VkSampler		sampler)
{
	const VkDescriptorImageInfo imageInfo =
	{
		sampler,
		imageView,
		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL
	};
	const VkWriteDescriptorSet descriptorWrite =
	{
		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
		DE_NULL,
		descriptorSet,
		0u,		// dstBinding
		0u,		// dstArrayElement
		1u,		// descriptorCount
		VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
		&imageInfo,
		(const VkDescriptorBufferInfo*)DE_NULL,
		(const VkBufferView*)DE_NULL,
	};

	m_vkd.updateDescriptorSets(m_device, 1u, &descriptorWrite, 0u, DE_NULL);
}

void LinearFilteringTestInstance::getExplicitFilteringRefData(const MultiPlaneImageData& imageData, vector<deUint8>& refData)
{
	const tcu::UVec2					imageSize				= m_cases[m_caseIndex].imageSize;
	const vk::PlanarFormatDescription&	planarFormatDescription = imageData.getDescription();
	const deUint8*						lumaData				= static_cast<const deUint8*>(imageData.getPlanePtr(0));
	const deUint8*						chromaBData				= static_cast<const deUint8*>(imageData.getPlanePtr(1));
	const deUint8*						chromaRData				= chromaBData;		// assuming 2 planes
	deUint32							chromaStride			= 2;
	deUint32							chromaOffset			= 1;

	if (planarFormatDescription.numPlanes == 3)
	{
		chromaRData		= static_cast<const deUint8*>(imageData.getPlanePtr(2));
		chromaStride	= 1;
		chromaOffset	= 0;
	}

	// associate nearest chroma sample with each luma sample
	vector<deUint8> intermediateImageData(imageSize.x() * imageSize.y() * 4, 255);
	for (deUint32 y = 0; y < imageSize.y(); ++y)
	{
		for (deUint32 x = 0; x < imageSize.x(); ++x)
		{
			deUint32 component						= x * 4 + imageSize.x() * y * 4;
			deUint32 chromaIndex					= x / 2 + (imageSize.x() / 2) * (y / 2);
			intermediateImageData[component]		= lumaData[x + imageSize.x() * y];
			intermediateImageData[component + 1]	= chromaBData[chromaStride * chromaIndex];
			intermediateImageData[component + 2]	= chromaRData[chromaStride * chromaIndex + chromaOffset];
		}
	}

	tcu::ConstPixelBufferAccess intermediateImage	(vk::mapVkFormat(VK_FORMAT_R8G8B8A8_UNORM), imageSize.x(), imageSize.y(), 1, intermediateImageData.data());
	const tcu::Texture2DView	intermediateTexView	(1u, &intermediateImage);
	const tcu::Sampler			refSampler			(mapVkSampler(getSamplerInfo(VK_FILTER_LINEAR)));
	const tcu::UVec2			renderSize			(m_cases[m_caseIndex].renderSize);

	// sample intermediate image and convert to gbr to generate reference image
	for (deUint32 y = 0; y < renderSize.y(); ++y)
	{
		float yCoord = ((float)y + 0.5f) / (float)renderSize.y();
		for (deUint32 x = 0; x < renderSize.x(); ++x)
		{
			float		xCoord		= ((float)x + 0.5f) / (float)renderSize.x();
			tcu::Vec4	color		= intermediateTexView.sample(refSampler, xCoord, yCoord, 0.0f);
			deUint32	texelIndex	= x * 4 + renderSize.x() * y * 4;
			refData[texelIndex + 1] = static_cast<deUint8>(255 * color[0]);		// g
			refData[texelIndex + 2] = static_cast<deUint8>(255 * color[1]);		// b
			refData[texelIndex]		= static_cast<deUint8>(255 * color[2]);		// r
		}
	}
}

void LinearFilteringTestInstance::getImplicitFilteringRefData(const MultiPlaneImageData& imageData, vector<deUint8>& refData)
{
	const tcu::UVec2			renderSize			(m_cases[m_caseIndex].renderSize);
	const VkSamplerCreateInfo	nSamplerCreateInfo	(getSamplerInfo(VK_FILTER_NEAREST));
	const VkSamplerCreateInfo	lSamplerCreateInfo	(getSamplerInfo(VK_FILTER_LINEAR));
	const tcu::Sampler			refSamplerNearest	(mapVkSampler(nSamplerCreateInfo));
	const tcu::Sampler			refSamplerLinear	(mapVkSampler(lSamplerCreateInfo));
	const deUint32				channelRemap[]		= { 1, 0, 2 };		// remap to have channels in order: Y Cr Cb
	const tcu::Sampler*			refSampler[]		=
	{
		&refSamplerLinear,
		&refSamplerNearest,
		&refSamplerNearest
	};

	for (deUint32 channelNdx = 0; channelNdx < 3; channelNdx++)
	{
		const tcu::ConstPixelBufferAccess	channelAccess		(imageData.getChannelAccess(channelNdx));
		const tcu::Texture2DView			refTexView			(1u, &channelAccess);
		const deUint32						orderedChannelNdx	(channelRemap[channelNdx]);

		for (deUint32 y = 0; y < renderSize.y(); ++y)
		{
			float yCoord = ((float)y + 0.5f) / (float)renderSize.y();
			for (deUint32 x = 0; x < renderSize.x(); ++x)
			{
				deUint32	texelIndex	= x * 4 + renderSize.x() * y * 4 + channelNdx;
				float		xCoord		= ((float)x + 0.5f) / (float)renderSize.x();
				refData[texelIndex]		= static_cast<deUint8>(255.0f * refTexView.sample(*refSampler[orderedChannelNdx], xCoord, yCoord, 0.0f)[0]);
			}
		}
	}
}

tcu::TestStatus LinearFilteringTestInstance::iterate(void)
{
	const tcu::UVec2						imageSize			(m_cases[m_caseIndex].imageSize);
	const tcu::UVec2						renderSize			(m_cases[m_caseIndex].renderSize);
	const auto&								instInt				(m_context.getInstanceInterface());
	auto									physicalDevice		(m_context.getPhysicalDevice());
	const Unique<VkSamplerYcbcrConversion>	conversion			(createYCbCrConversion());
	const VkSamplerYcbcrConversionInfo		samplerConvInfo		{ VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_INFO, DE_NULL, *conversion };
	const VkSamplerCreateInfo				samplerCreateInfo	(getSamplerInfo(VK_FILTER_LINEAR, &samplerConvInfo));
	const Unique<VkSampler>					sampler				(createSampler(m_vkd, m_device, &samplerCreateInfo));

	deUint32								combinedSamplerDescriptorCount = 1;
	{
		const VkPhysicalDeviceImageFormatInfo2			imageFormatInfo				=
		{
			VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_IMAGE_FORMAT_INFO_2,	// sType
			DE_NULL,												// pNext
			m_format,												// format
			VK_IMAGE_TYPE_2D,										// type
			VK_IMAGE_TILING_OPTIMAL,								// tiling
			VK_IMAGE_USAGE_TRANSFER_DST_BIT |
			VK_IMAGE_USAGE_SAMPLED_BIT,								// usage
			(VkImageCreateFlags)0u									// flags
		};

		VkSamplerYcbcrConversionImageFormatProperties	samplerYcbcrConversionImage = {};
		samplerYcbcrConversionImage.sType = VK_STRUCTURE_TYPE_SAMPLER_YCBCR_CONVERSION_IMAGE_FORMAT_PROPERTIES;
		samplerYcbcrConversionImage.pNext = DE_NULL;

		VkImageFormatProperties2						imageFormatProperties		= {};
		imageFormatProperties.sType = VK_STRUCTURE_TYPE_IMAGE_FORMAT_PROPERTIES_2;
		imageFormatProperties.pNext = &samplerYcbcrConversionImage;

		VK_CHECK(instInt.getPhysicalDeviceImageFormatProperties2(physicalDevice, &imageFormatInfo, &imageFormatProperties));
		combinedSamplerDescriptorCount = samplerYcbcrConversionImage.combinedImageSamplerDescriptorCount;
	}

	const Unique<VkDescriptorSetLayout>		descLayout			(createDescriptorSetLayout(*sampler));
	const Unique<VkDescriptorPool>			descPool			(createDescriptorPool(combinedSamplerDescriptorCount));
	const Unique<VkDescriptorSet>			descSet				(createDescriptorSet(*descPool, *descLayout));
	const Unique<VkImage>					testImage			(createImage(imageSize.x(), imageSize.y()));
	const vector<AllocationSp>				allocations			(allocateAndBindImageMemory(m_vkd, m_device, m_context.getDefaultAllocator(), *testImage, m_format, 0u));
	const Unique<VkImageView>				imageView			(createImageView(samplerConvInfo, *testImage));

	// create and bind image with test data
	MultiPlaneImageData imageData(m_format, imageSize);
	fillGradient(&imageData, tcu::Vec4(0.0f), tcu::Vec4(1.0f));
	uploadImage(m_vkd,
				m_device,
				m_context.getUniversalQueueFamilyIndex(),
				m_context.getDefaultAllocator(),
				*testImage,
				imageData,
				(VkAccessFlags)VK_ACCESS_SHADER_READ_BIT,
				VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
				0);
	bindImage(*descSet, *imageView, *sampler);

	const vector<tcu::Vec4> vertices =
	{
		{ -1.0f, -1.0f, 0.0f, 1.0f },
		{ +1.0f, -1.0f, 0.0f, 1.0f },
		{ -1.0f, +1.0f, 0.0f, 1.0f },
		{ +1.0f, +1.0f, 0.0f, 1.0f }
	};
	VulkanProgram program({
		VulkanShader(VK_SHADER_STAGE_VERTEX_BIT,	m_context.getBinaryCollection().get("vert")),
		VulkanShader(VK_SHADER_STAGE_FRAGMENT_BIT,	m_context.getBinaryCollection().get("frag"))
	});
	program.descriptorSet		= *descSet;
	program.descriptorSetLayout = *descLayout;

	PipelineState		pipelineState		(m_context.getDeviceProperties().limits.subPixelPrecisionBits);
	const DrawCallData	drawCallData		(VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, vertices);
	FrameBufferState	frameBufferState	(renderSize.x(), renderSize.y());
	VulkanDrawContext	renderer			(m_context, frameBufferState);

	// render full screen quad
	renderer.registerDrawObject(pipelineState, program, drawCallData);
	renderer.draw();

	// get rendered image
	tcu::ConstPixelBufferAccess resImage(renderer.getColorPixels());

	vector<deUint8>					refData				(renderSize.x() * renderSize.y() * 4, 255);
	const VkFormatProperties		formatProperties	(getPhysicalDeviceFormatProperties(instInt, physicalDevice, m_format));
	const VkFormatFeatureFlags		featureFlags		(formatProperties.optimalTilingFeatures);
	const bool						explicitFiltering	(featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_CHROMA_RECONSTRUCTION_EXPLICIT_BIT);

	// generate reference image data
	if (explicitFiltering)
		getExplicitFilteringRefData(imageData, refData);
	else
		getImplicitFilteringRefData(imageData, refData);

	float							threshold			(0.01f);
	tcu::Vec4						thresholdVec		(threshold, threshold, threshold, 1.0f);
	tcu::TextureFormat				refFormat			(vk::mapVkFormat(frameBufferState.colorFormat));
	tcu::ConstPixelBufferAccess		refImage			(refFormat, renderSize.x(), renderSize.y(), 1, refData.data());

	// compare reference with the rendered image
	if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "", refImage, resImage, thresholdVec, tcu::COMPARE_LOG_RESULT))
		return tcu::TestStatus::fail("Invalid result");

	if (++m_caseIndex < (int)m_cases.size())
		return tcu::TestStatus::incomplete();
	return tcu::TestStatus::pass("Pass");
}

class LinearFilteringTestCase : public vkt::TestCase
{
public:
	LinearFilteringTestCase(tcu::TestContext &context, const char* name, const char* description, VkFormat format);

protected:
	void				checkSupport(Context& context) const;
	vkt::TestInstance*	createInstance(vkt::Context& context) const;
	void				initPrograms(SourceCollections& programCollection) const;

private:
	VkFormat			m_format;
};

LinearFilteringTestCase::LinearFilteringTestCase(tcu::TestContext &context, const char* name, const char* description, VkFormat format)
	: TestCase(context, name, description)
	, m_format(format)
{
}

void LinearFilteringTestCase::checkSupport(Context& context) const
{
	context.requireDeviceFunctionality("VK_KHR_sampler_ycbcr_conversion");

	const auto&					instInt				= context.getInstanceInterface();
	auto						physicalDevice		= context.getPhysicalDevice();
	const VkFormatProperties	formatProperties	= getPhysicalDeviceFormatProperties(instInt, physicalDevice, m_format);
	const VkFormatFeatureFlags	featureFlags		= formatProperties.optimalTilingFeatures;

	if ((featureFlags & VK_FORMAT_FEATURE_MIDPOINT_CHROMA_SAMPLES_BIT) == 0)
		TCU_THROW(NotSupportedError, "YCbCr conversion is not supported for format");

	if ((featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_FILTER_LINEAR_BIT) == 0)
		TCU_THROW(NotSupportedError, "Linear filtering not supported for format");

	if ((featureFlags & VK_FORMAT_FEATURE_SAMPLED_IMAGE_YCBCR_CONVERSION_SEPARATE_RECONSTRUCTION_FILTER_BIT) == 0)
		TCU_THROW(NotSupportedError, "Different chroma, min, and mag filters not supported for format");
}

vkt::TestInstance* LinearFilteringTestCase::createInstance(vkt::Context& context) const
{
	return new LinearFilteringTestInstance(context, m_format);
}

void LinearFilteringTestCase::initPrograms(SourceCollections& programCollection) const
{
	static const char* vertShader =
		"#version 450\n"
		"precision mediump int; precision highp float;\n"
		"layout(location = 0) in vec4 a_position;\n"
		"layout(location = 0) out vec2 v_texCoord;\n"
		"out gl_PerVertex { vec4 gl_Position; };\n"
		"\n"
		"void main (void)\n"
		"{\n"
		"  v_texCoord = a_position.xy * 0.5 + 0.5;\n"
		"  gl_Position = a_position;\n"
		"}\n";

	static const char* fragShader =
		"#version 450\n"
		"precision mediump int; precision highp float;\n"
		"layout(location = 0) in vec2 v_texCoord;\n"
		"layout(location = 0) out mediump vec4 dEQP_FragColor;\n"
		"layout (set=0, binding=0) uniform sampler2D u_sampler;\n"
		"void main (void)\n"
		"{\n"
		"  dEQP_FragColor = vec4(texture(u_sampler, v_texCoord));\n"
		"}\n";

	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
}

} // anonymous

tcu::TestCaseGroup* createFilteringTests (tcu::TestContext& testCtx)
{
	struct YCbCrFormatData
	{
		const char* const	name;
		const VkFormat		format;
	};

	static const std::vector<YCbCrFormatData> ycbcrFormats =
	{
		{ "g8_b8_r8_3plane_420_unorm",	VK_FORMAT_G8_B8_R8_3PLANE_420_UNORM		},
		{ "g8_b8r8_2plane_420_unorm",	VK_FORMAT_G8_B8R8_2PLANE_420_UNORM		},
	};

	de::MovePtr<tcu::TestCaseGroup> filteringTests(new tcu::TestCaseGroup(testCtx, "filtering",	"YCbCr filtering tests"));

	for (const auto& ycbcrFormat : ycbcrFormats)
	{
		const std::string name = std::string("linear_sampler_") + ycbcrFormat.name;
		filteringTests->addChild(new LinearFilteringTestCase(filteringTests->getTestContext(), name.c_str(), "", ycbcrFormat.format));
	}

	return filteringTests.release();
}

} // ycbcr
} // vkt
