/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2021 The Khronos Group Inc.
 * Copyright (c) 2021 Valve Corporation.
 *
 * 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 Mesh Shader Builtin Tests
 *//*--------------------------------------------------------------------*/

#include "vktMeshShaderBuiltinTests.hpp"
#include "vktTestCase.hpp"

#include "vkTypeUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkImageWithMemory.hpp"
#include "vkBufferWithMemory.hpp"
#include "vkCmdUtil.hpp"
#include "vkBarrierUtil.hpp"

#include "tcuTexture.hpp"
#include "tcuTestLog.hpp"

#include <vector>
#include <algorithm>
#include <sstream>
#include <map>
#include <utility>
#include <sstream>

namespace tcu
{
// Needed for PixelMap below.
bool operator<(const IVec2& a, const IVec2& b)
{
	return (a.x() < b.x() || (a.x() == b.x() && a.y() < b.y()));
}
}

namespace vkt
{
namespace MeshShader
{

namespace
{

using namespace vk;

using GroupPtr				= de::MovePtr<tcu::TestCaseGroup>;
using DrawCommandVec		= std::vector<VkDrawMeshTasksIndirectCommandNV>;
using ImageWithMemoryPtr	= de::MovePtr<ImageWithMemory>;
using BufferWithMemoryPtr	= de::MovePtr<BufferWithMemory>;
using ViewportVec			= std::vector<VkViewport>;
using ColorVec				= std::vector<tcu::Vec4>;
using PixelMap				= std::map<tcu::IVec2, tcu::Vec4>; // Coordinates to color.

VkExtent2D getDefaultExtent ()
{
	return makeExtent2D(8u, 8u);
}

VkExtent2D getLinearExtent ()
{
	return makeExtent2D(8u, 1u);
}

struct JobSize
{
	uint32_t numTasks;
	uint32_t localSize;
};

JobSize getLargeJobSize ()
{
	return JobSize{8u, 8u};
}

// Single draw command with the given number of tasks, 1 by default.
DrawCommandVec getDefaultDrawCommands (uint32_t taskCount = 1u)
{
	return DrawCommandVec(1u, makeDrawMeshTasksIndirectCommandNV(taskCount, 0u));
}

// Basic fragment shader that draws fragments in blue.
std::string getBasicFragShader ()
{
	return
		"#version 460\n"
		"#extension GL_NV_mesh_shader : enable\n"
		"\n"
		"layout (location=0) out vec4 outColor;\n"
		"\n"
		"void main ()\n"
		"{\n"
		"    outColor = vec4(0.0, 0.0, 1.0, 1.0);\n"
		"}\n"
		;
}

struct IterationParams
{
	VkExtent2D		colorExtent;
	uint32_t		numLayers;
	DrawCommandVec	drawArgs;
	bool			indirect;
	ViewportVec		viewports;	// If empty, a single default viewport is used.
};

class MeshShaderBuiltinInstance : public vkt::TestInstance
{
public:
						MeshShaderBuiltinInstance	(Context& context, const IterationParams& params)
							: vkt::TestInstance	(context)
							, m_params			(params)
							{}
	virtual				~MeshShaderBuiltinInstance	(void) {}

	tcu::TestStatus		iterate						() override;
	virtual void		verifyResults				(const tcu::ConstPixelBufferAccess& result) = 0;

protected:
	IterationParams		m_params;
};

tcu::TestStatus MeshShaderBuiltinInstance::iterate ()
{
	const auto&		vkd			= m_context.getDeviceInterface();
	const auto		device		= m_context.getDevice();
	auto&			alloc		= m_context.getDefaultAllocator();
	const auto		queueIndex	= m_context.getUniversalQueueFamilyIndex();
	const auto		queue		= m_context.getUniversalQueue();
	const auto&		binaries	= m_context.getBinaryCollection();

	const auto		useTask		= binaries.contains("task");
	const auto		useFrag		= binaries.contains("frag");
	const auto		extent		= makeExtent3D(m_params.colorExtent.width, m_params.colorExtent.height, 1u);
	const auto		iExtent3D	= tcu::IVec3(static_cast<int>(extent.width), static_cast<int>(extent.height), static_cast<int>(m_params.numLayers));
	const auto		format		= VK_FORMAT_R8G8B8A8_UNORM;
	const auto		tcuFormat	= mapVkFormat(format);
	const auto		colorUsage	= (VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT);
	const auto		viewType	= ((m_params.numLayers > 1u) ? VK_IMAGE_VIEW_TYPE_2D_ARRAY : VK_IMAGE_VIEW_TYPE_2D);
	const auto		colorSRR	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, m_params.numLayers);
	const auto		colorSRL	= makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, m_params.numLayers);
	const tcu::Vec4	clearColor	(0.0f, 0.0f, 0.0f, 1.0f);

	ImageWithMemoryPtr	colorBuffer;
	Move<VkImageView>	colorBufferView;
	{
		const VkImageCreateInfo colorBufferInfo =
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	//	VkStructureType			sType;
			nullptr,								//	const void*				pNext;
			0u,										//	VkImageCreateFlags		flags;
			VK_IMAGE_TYPE_2D,						//	VkImageType				imageType;
			format,									//	VkFormat				format;
			extent,									//	VkExtent3D				extent;
			1u,										//	uint32_t				mipLevels;
			m_params.numLayers,						//	uint32_t				arrayLayers;
			VK_SAMPLE_COUNT_1_BIT,					//	VkSampleCountFlagBits	samples;
			VK_IMAGE_TILING_OPTIMAL,				//	VkImageTiling			tiling;
			colorUsage,								//	VkImageUsageFlags		usage;
			VK_SHARING_MODE_EXCLUSIVE,				//	VkSharingMode			sharingMode;
			0u,										//	uint32_t				queueFamilyIndexCount;
			nullptr,								//	const uint32_t*			pQueueFamilyIndices;
			VK_IMAGE_LAYOUT_UNDEFINED,				//	VkImageLayout			initialLayout;
		};
		colorBuffer = ImageWithMemoryPtr(new ImageWithMemory(vkd, device, alloc, colorBufferInfo, MemoryRequirement::Any));
		colorBufferView = makeImageView(vkd, device, colorBuffer->get(), viewType, format, colorSRR);
	}

	// Empty descriptor set layout.
	DescriptorSetLayoutBuilder layoutBuilder;
	const auto setLayout = layoutBuilder.build(vkd, device);

	// Pipeline layout.
	const auto pipelineLayout = makePipelineLayout(vkd, device, setLayout.get());

	// Render pass and framebuffer.
	const auto renderPass	= makeRenderPass(vkd, device, format);
	const auto framebuffer	= makeFramebuffer(vkd, device, renderPass.get(), colorBufferView.get(), extent.width, extent.height, m_params.numLayers);

	// Pipeline.
	Move<VkShaderModule> taskModule;
	Move<VkShaderModule> meshModule;
	Move<VkShaderModule> fragModule;

	if (useTask)
		taskModule = createShaderModule(vkd, device, binaries.get("task"));
	if (useFrag)
		fragModule = createShaderModule(vkd, device, binaries.get("frag"));
	meshModule = createShaderModule(vkd, device, binaries.get("mesh"));

	std::vector<VkViewport>	viewports;
	std::vector<VkRect2D>	scissors;
	if (m_params.viewports.empty())
	{
		// Default ones.
		viewports.push_back(makeViewport(extent));
		scissors.push_back(makeRect2D(extent));
	}
	else
	{
		// The desired viewports and the same number of default scissors.
		viewports.reserve(m_params.viewports.size());
		std::copy(begin(m_params.viewports), end(m_params.viewports), std::back_inserter(viewports));
		scissors.resize(viewports.size(), makeRect2D(extent));
	}

	const auto pipeline = makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
		taskModule.get(), meshModule.get(), fragModule.get(),
		renderPass.get(), viewports, scissors);

	// Command pool and buffer.
	const auto cmdPool		= makeCommandPool(vkd, device, queueIndex);
	const auto cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto cmdBuffer	= cmdBufferPtr.get();

	// Indirect buffer if needed.
	BufferWithMemoryPtr indirectBuffer;

	DE_ASSERT(!m_params.drawArgs.empty());
	if (m_params.indirect)
	{
		// Indirect draws.
		const auto indirectBufferSize	= static_cast<VkDeviceSize>(de::dataSize(m_params.drawArgs));
		const auto indirectBufferUsage	= (VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
		const auto indirectBufferInfo	= makeBufferCreateInfo(indirectBufferSize, indirectBufferUsage);
		indirectBuffer					= BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, indirectBufferInfo, MemoryRequirement::HostVisible));
		auto& indirectBufferAlloc		= indirectBuffer->getAllocation();
		void* indirectBufferData		= indirectBufferAlloc.getHostPtr();

		deMemcpy(indirectBufferData, m_params.drawArgs.data(), static_cast<size_t>(indirectBufferSize));
		flushAlloc(vkd, device, indirectBufferAlloc);
	}

	// Submit commands.
	beginCommandBuffer(vkd, cmdBuffer);
	beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), scissors.at(0), clearColor);
	vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());

	if (!m_params.indirect)
	{
		for (const auto& command : m_params.drawArgs)
			vkd.cmdDrawMeshTasksNV(cmdBuffer, command.taskCount, command.firstTask);
	}
	else
	{
		const auto numDraws	= static_cast<uint32_t>(m_params.drawArgs.size());
		const auto stride	= static_cast<uint32_t>(sizeof(decltype(m_params.drawArgs)::value_type));
		vkd.cmdDrawMeshTasksIndirectNV(cmdBuffer, indirectBuffer->get(), 0ull, numDraws, stride);
	}

	endRenderPass(vkd, cmdBuffer);

	// Output buffer to extract the color buffer contents.
	BufferWithMemoryPtr	outBuffer;
	void*				outBufferData	= nullptr;
	{
		const auto	layerSize			= static_cast<VkDeviceSize>(static_cast<uint32_t>(tcu::getPixelSize(tcuFormat)) * extent.width * extent.height);
		const auto	outBufferSize		= layerSize * m_params.numLayers;
		const auto	outBufferUsage		= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
		const auto	outBufferInfo		= makeBufferCreateInfo(outBufferSize, outBufferUsage);

		outBuffer						= BufferWithMemoryPtr(new BufferWithMemory(vkd, device, alloc, outBufferInfo, MemoryRequirement::HostVisible));
		outBufferData					= outBuffer->getAllocation().getHostPtr();
	}

	// Transition image layout.
	const auto preTransferBarrier = makeImageMemoryBarrier(
		(VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT), VK_ACCESS_TRANSFER_READ_BIT,
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
		colorBuffer->get(), colorSRR);

	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preTransferBarrier);

	// Copy image to output buffer.
	const std::vector<VkBufferImageCopy> regions (1u, makeBufferImageCopy(extent, colorSRL));
	vkd.cmdCopyImageToBuffer(cmdBuffer, colorBuffer->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, outBuffer->get(), static_cast<uint32_t>(regions.size()), de::dataOrNull(regions));

	// Transfer to host barrier.
	const auto postTransferBarrier = makeMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &postTransferBarrier, 0u, nullptr, 0u, nullptr);

	endCommandBuffer(vkd, cmdBuffer);
	submitCommandsAndWait(vkd, device, queue, cmdBuffer);

	// Invalidate alloc and verify result.
	{
		auto& outBufferAlloc = outBuffer->getAllocation();
		invalidateAlloc(vkd, device, outBufferAlloc);

		tcu::ConstPixelBufferAccess	result (tcuFormat, iExtent3D, outBufferData);
		verifyResults(result);
	}

	return tcu::TestStatus::pass("Pass");
}

// Abstract case that implements the generic checkSupport method.
class MeshShaderBuiltinCase : public vkt::TestCase
{
public:
					MeshShaderBuiltinCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
						: vkt::TestCase	(testCtx, name, description)
						, m_taskNeeded	(taskNeeded)
						{}
	virtual			~MeshShaderBuiltinCase	(void) {}

	void			checkSupport			(Context& context) const override;

protected:
	const bool		m_taskNeeded;
};

void MeshShaderBuiltinCase::checkSupport (Context& context) const
{
	context.requireDeviceFunctionality("VK_NV_mesh_shader");

	const auto& meshFeatures = context.getMeshShaderFeatures();

	if (!meshFeatures.meshShader)
		TCU_THROW(NotSupportedError, "Mesh shader not supported");

	if (m_taskNeeded && !meshFeatures.taskShader)
		TCU_THROW(NotSupportedError, "Task shader not supported");
}

// Instance that verifies color layers.
class FullScreenColorInstance : public MeshShaderBuiltinInstance
{
public:
				FullScreenColorInstance		(Context& context, const IterationParams& params, const ColorVec& expectedColors)
					: MeshShaderBuiltinInstance (context, params)
					, m_expectedColors			(expectedColors)
					{}
	virtual		~FullScreenColorInstance	(void) {}

	void		verifyResults				(const tcu::ConstPixelBufferAccess& result) override;

protected:
	const ColorVec m_expectedColors;
};

void FullScreenColorInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
{
	auto&		log		= m_context.getTestContext().getLog();
	bool		fail	= false;
	const auto	width	= result.getWidth();
	const auto	height	= result.getHeight();
	const auto	depth	= result.getDepth();

	for (int z = 0; z < depth; ++z)
	{
		const auto& expected = m_expectedColors.at(z);

		for (int y = 0; y < height; ++y)
		for (int x = 0; x < width; ++x)
		{
			const auto resultColor = result.getPixel(x, y, z);
			if (resultColor != expected)
			{
				std::ostringstream msg;
				msg << "Pixel (" << x << ", " << y << ", " << z << ") failed: expected " << expected << " and found " << resultColor;
				log << tcu::TestLog::Message << msg.str() << tcu::TestLog::EndMessage;
				fail = true;
			}
		}
	}

	if (fail)
	{
		log << tcu::TestLog::Image("Result", "", result);
		TCU_FAIL("Check log for details");
	}
}

// Instance that verifies single-layer framebuffers divided into 4 quadrants.
class QuadrantsInstance : public MeshShaderBuiltinInstance
{
public:
				QuadrantsInstance	(Context& context, const IterationParams& params,
									 const tcu::Vec4 topLeft,
									 const tcu::Vec4 topRight,
									 const tcu::Vec4 bottomLeft,
									 const tcu::Vec4 bottomRight)
					: MeshShaderBuiltinInstance (context, params)
					, m_topLeft					(topLeft)
					, m_topRight				(topRight)
					, m_bottomLeft				(bottomLeft)
					, m_bottomRight				(bottomRight)
					{}
	virtual		~QuadrantsInstance	(void) {}

	void		verifyResults		(const tcu::ConstPixelBufferAccess& result) override;

protected:
	const tcu::Vec4 m_topLeft;
	const tcu::Vec4 m_topRight;
	const tcu::Vec4 m_bottomLeft;
	const tcu::Vec4 m_bottomRight;
};

void QuadrantsInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
{
	const auto width	= result.getWidth();
	const auto height	= result.getHeight();
	const auto depth	= result.getDepth();

	DE_ASSERT(depth == 1);
	DE_ASSERT(width > 0 && width % 2 == 0);
	DE_ASSERT(height > 0 && height % 2 == 0);
	DE_UNREF(depth); // For release builds.

	const auto	halfWidth	= width / 2;
	const auto	halfHeight	= height / 2;
	tcu::Vec4	expected;

	for (int y = 0; y < height; ++y)
	for (int x = 0; x < width; ++x)
	{
		// Choose the right quadrant
		if (y < halfHeight)
			expected = ((x < halfWidth) ? m_topLeft : m_topRight);
		else
			expected = ((x < halfWidth) ? m_bottomLeft : m_bottomRight);

		const auto resultColor = result.getPixel(x, y);
		if (resultColor != expected)
		{
			std::ostringstream msg;
			msg << "Pixel (" << x << ", " << y  << ") failed: expected " << expected << " and found " << resultColor;
			TCU_FAIL(msg.str());
		}
	}
}

// Instance that verifies single-layer framebuffers with specific pixels set to some color.
struct PixelVerifierParams
{
	const tcu::Vec4		background;
	const PixelMap		pixelMap;
};

class PixelsInstance : public MeshShaderBuiltinInstance
{
public:
				PixelsInstance	(Context& context, const IterationParams& params, const PixelVerifierParams& pixelParams)
					: MeshShaderBuiltinInstance	(context, params)
					, m_pixelParams				(pixelParams)
					{}
	virtual		~PixelsInstance	(void) {}

	void		verifyResults	(const tcu::ConstPixelBufferAccess& result) override;

protected:
	const PixelVerifierParams m_pixelParams;
};

void PixelsInstance::verifyResults (const tcu::ConstPixelBufferAccess& result)
{
	const auto width	= result.getWidth();
	const auto height	= result.getHeight();
	const auto depth	= result.getDepth();

	DE_ASSERT(depth == 1);
	DE_UNREF(depth); // For release builds.

	for (int y = 0; y < height; ++y)
	for (int x = 0; x < width; ++x)
	{
		const tcu::IVec2	coords		(x, y);
		const auto			iter		= m_pixelParams.pixelMap.find(coords);
		const auto			expected	= ((iter == m_pixelParams.pixelMap.end()) ? m_pixelParams.background : iter->second);
		const auto			resultColor	= result.getPixel(x, y);

		if (resultColor != expected)
		{
			std::ostringstream msg;
			msg << "Pixel (" << x << ", " << y << ") failed: expected " << expected << " and found " << resultColor;
			TCU_FAIL(msg.str());
		}
	}
}

// Primitive ID cases.
class PrimitiveIdCase : public MeshShaderBuiltinCase
{
public:
					PrimitiveIdCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool glslFrag)
						: MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
						, m_glslFrag			(glslFrag)
						{}
	virtual			~PrimitiveIdCase	(void) {}

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

protected:
	// Fragment shader in GLSL means glslang will use the Geometry capability due to gl_PrimitiveID.
	const bool		m_glslFrag;
};

void PrimitiveIdCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Mesh shader.
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=1) out;\n"
			<< "\n"
			<< "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
			<< "   int gl_PrimitiveID;\n"
			<< "} gl_MeshPrimitivesNV[];\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 1u;\n"
			<< "\n"
			<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
			<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[2] = 2;\n"
			<< "\n"
			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[1].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
			<< "\n"
			// Sets an arbitrary primitive id.
			<< "    gl_MeshPrimitivesNV[0].gl_PrimitiveID = 1629198956;\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Frag shader.
	if (m_glslFrag)
	{
		std::ostringstream frag;
		frag
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (location=0) out vec4 outColor;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			// Checks the primitive id matches.
			<< "    outColor = ((gl_PrimitiveID == 1629198956) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(0.0, 0.0, 0.0, 1.0));\n"
			<< "}\n"
			;
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
	}
	else
	{
		// This is the same shader as above, but OpCapability Geometry has been replaced by OpCapability MeshShadingNV in order to
		// access gl_PrimitiveID. This also needs the SPV_NV_mesh_shader extension.
		std::ostringstream frag;
		frag
			<< "; Version: 1.0\n"
			<< "; Generator: Khronos Glslang Reference Front End; 10\n"
			<< "; Bound: 24\n"
			<< "; Schema: 0\n"
			<< "      OpCapability Shader\n"

			// Manual change in these lines.
			//<< "      OpCapability Geometry\n"
			<< "      OpCapability MeshShadingNV\n"
			<< "      OpExtension \"SPV_NV_mesh_shader\"\n"

			<< " %1 = OpExtInstImport \"GLSL.std.450\"\n"
			<< "      OpMemoryModel Logical GLSL450\n"
			<< "      OpEntryPoint Fragment %4 \"main\" %9 %12\n"
			<< "      OpExecutionMode %4 OriginUpperLeft\n"
			<< "      OpDecorate %9 Location 0\n"
			<< "      OpDecorate %12 Flat\n"
			<< "      OpDecorate %12 BuiltIn PrimitiveId\n"
			<< " %2 = OpTypeVoid\n"
			<< " %3 = OpTypeFunction %2\n"
			<< " %6 = OpTypeFloat 32\n"
			<< " %7 = OpTypeVector %6 4\n"
			<< " %8 = OpTypePointer Output %7\n"
			<< " %9 = OpVariable %8 Output\n"
			<< "%10 = OpTypeInt 32 1\n"
			<< "%11 = OpTypePointer Input %10\n"
			<< "%12 = OpVariable %11 Input\n"
			<< "%14 = OpConstant %10 1629198956\n"
			<< "%15 = OpTypeBool\n"
			<< "%17 = OpConstant %6 0\n"
			<< "%18 = OpConstant %6 1\n"
			<< "%19 = OpConstantComposite %7 %17 %17 %18 %18\n"
			<< "%20 = OpConstantComposite %7 %17 %17 %17 %18\n"
			<< "%21 = OpTypeVector %15 4\n"
			<< " %4 = OpFunction %2 None %3\n"
			<< " %5 = OpLabel\n"
			<< "%13 = OpLoad %10 %12\n"
			<< "%16 = OpIEqual %15 %13 %14\n"
			<< "%22 = OpCompositeConstruct %21 %16 %16 %16 %16\n"
			<< "%23 = OpSelect %7 %22 %19 %20\n"
			<< "      OpStore %9 %23\n"
			<< "      OpReturn\n"
			<< "      OpFunctionEnd\n"
			;
		programCollection.spirvAsmSources.add("frag") << frag.str();
	}
}

void PrimitiveIdCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);

	// Fragment shader in GLSL means glslang will use the Geometry capability due to gl_PrimitiveID.
	if (m_glslFrag)
		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
}

TestInstance* PrimitiveIdCase::createInstance (Context& context) const
{
	const ColorVec			expectedColors	(1u, tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f));
	const IterationParams	iterationParams	=
	{
		getDefaultExtent(),			//	VkExtent2D		colorExtent;
		1u,							//	uint32_t		numLayers;
		getDefaultDrawCommands(),	//	DrawCommandVec	drawArgs;
		false,						//	bool			indirect;
		{},							//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

// Layer builtin case.
class LayerCase : public MeshShaderBuiltinCase
{
public:
					LayerCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool shareVertices)
						: MeshShaderBuiltinCase	(testCtx, name, description, false/*taskNeeded*/)
						, m_shareVertices		(shareVertices)
						{}
	virtual			~LayerCase	(void) {}

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

	static constexpr uint32_t kNumLayers = 4u;

protected:
	const bool m_shareVertices;
};

void LayerCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const auto localSize		= (m_shareVertices ? kNumLayers : 1u);
	const auto numPrimitives	= (m_shareVertices ? kNumLayers : 1u);
	const auto layerNumber		= (m_shareVertices ? "gl_LocalInvocationIndex" : "gl_WorkGroupID.x");

	// One layer per local invocation or work group (shared vertices or not, respectively).
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << localSize << ") in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=" << numPrimitives << ") out;\n"
			<< "\n"
			<< "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
			<< "   int gl_Layer;\n"
			<< "} gl_MeshPrimitivesNV[];\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = " << numPrimitives << ";\n"
			<< "\n"
			<< "    if (gl_LocalInvocationIndex == 0u)\n"
			<< "    {\n"
			<< "        gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
			<< "        gl_MeshVerticesNV[1].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
			<< "        gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
			<< "    }\n"
			<< "\n"
			<< "    const uint baseIndex = gl_LocalInvocationIndex * 3u;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 0] = 0;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 1] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 2] = 2;\n"
			<< "\n"
			<< "    gl_MeshPrimitivesNV[gl_LocalInvocationIndex].gl_Layer = int(" << layerNumber << ");\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Fragment shader chooses one color per layer.
	{
		std::ostringstream frag;
		frag
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (location=0) out vec4 outColor;\n"
			<< "\n"
			<< "vec4 colors[" << kNumLayers << "] = vec4[](\n"
			<< "    vec4(0.0, 0.0, 1.0, 1.0),\n"
			<< "    vec4(1.0, 0.0, 1.0, 1.0),\n"
			<< "    vec4(0.0, 1.0, 1.0, 1.0),\n"
			<< "    vec4(1.0, 1.0, 0.0, 1.0)\n"
			<< ");\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    outColor = colors[gl_Layer];\n"
			<< "}\n"
			;
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
	}
}

void LayerCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);

	if (!context.contextSupports(vk::ApiVersion(1u, 2u, 0u)))
		context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
	else
	{
		const auto& features = context.getDeviceVulkan12Features();
		if (!features.shaderOutputLayer)
			TCU_THROW(NotSupportedError, "shaderOutputLayer feature not supported");
	}
}

TestInstance* LayerCase::createInstance (Context& context) const
{
	ColorVec expectedColors;

	expectedColors.reserve(kNumLayers);
	expectedColors.push_back(tcu::Vec4(0.0, 0.0, 1.0, 1.0));
	expectedColors.push_back(tcu::Vec4(1.0, 0.0, 1.0, 1.0));
	expectedColors.push_back(tcu::Vec4(0.0, 1.0, 1.0, 1.0));
	expectedColors.push_back(tcu::Vec4(1.0, 1.0, 0.0, 1.0));

	const auto numWorkGroups = (m_shareVertices ? 1u : kNumLayers);
	const IterationParams iterationParams =
	{
		getDefaultExtent(),						//	VkExtent2D		colorExtent;
		kNumLayers,								//	uint32_t		numLayers;
		getDefaultDrawCommands(numWorkGroups),	//	DrawCommandVec	drawArgs;
		false,									//	bool			indirect;
		{},										//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

// ViewportIndex builtin case.
class ViewportIndexCase : public MeshShaderBuiltinCase
{
public:
					ViewportIndexCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool shareVertices)
						: MeshShaderBuiltinCase	(testCtx, name, description, false/*taskNeeded*/)
						, m_shareVertices		(shareVertices)
						{}
	virtual			~ViewportIndexCase	(void) {}

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

	static constexpr uint32_t kQuadrants = 4u;

protected:
	const bool m_shareVertices;
};

void ViewportIndexCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const auto localSize		= (m_shareVertices ? kQuadrants : 1u);
	const auto numPrimitives	= (m_shareVertices ? kQuadrants : 1u);
	const auto viewportIndex	= (m_shareVertices ? "gl_LocalInvocationIndex" : "gl_WorkGroupID.x");

	// One viewport per local invocation or work group (sharing vertices or not, respectively).
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << localSize << ") in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=" << numPrimitives << ") out;\n"
			<< "\n"
			<< "perprimitiveNV out gl_MeshPerPrimitiveNV {\n"
			<< "   int gl_ViewportIndex;\n"
			<< "} gl_MeshPrimitivesNV[];\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = " << numPrimitives << ";\n"
			<< "\n"
			<< "    if (gl_LocalInvocationIndex == 0u)\n"
			<< "    {\n"
			<< "        gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
			<< "        gl_MeshVerticesNV[1].gl_Position = vec4(-1.0,  3.0, 0.0, 1.0);\n"
			<< "        gl_MeshVerticesNV[2].gl_Position = vec4( 3.0, -1.0, 0.0, 1.0);\n"
			<< "    }\n"
			<< "\n"
			<< "    const uint baseIndex = gl_LocalInvocationIndex * 3u;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 0] = 0;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 1] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[baseIndex + 2] = 2;\n"
			<< "\n"
			<< "    gl_MeshPrimitivesNV[gl_LocalInvocationIndex].gl_ViewportIndex = int(" << viewportIndex << ");\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Fragment shader chooses one color per viewport.
	{
		std::ostringstream frag;
		frag
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (location=0) out vec4 outColor;\n"
			<< "\n"
			<< "vec4 colors[" << kQuadrants << "] = vec4[](\n"
			<< "    vec4(0.0, 0.0, 1.0, 1.0),\n"
			<< "    vec4(1.0, 0.0, 1.0, 1.0),\n"
			<< "    vec4(0.0, 1.0, 1.0, 1.0),\n"
			<< "    vec4(1.0, 1.0, 0.0, 1.0)\n"
			<< ");\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    outColor = colors[gl_ViewportIndex];\n"
			<< "}\n"
			;
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
	}
}

void ViewportIndexCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);
	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_MULTI_VIEWPORT);

	if (!context.contextSupports(vk::ApiVersion(1u, 2u, 0u)))
		context.requireDeviceFunctionality("VK_EXT_shader_viewport_index_layer");
	else
	{
		const auto& features = context.getDeviceVulkan12Features();
		if (!features.shaderOutputViewportIndex)
			TCU_THROW(NotSupportedError, "shaderOutputViewportIndex feature not supported");
	}
}

TestInstance* ViewportIndexCase::createInstance (Context& context) const
{
	const auto extent = getDefaultExtent();

	DE_ASSERT(extent.width > 0u && extent.width % 2u == 0u);
	DE_ASSERT(extent.height > 0u && extent.height % 2u == 0u);

	const auto halfWidth	= static_cast<float>(extent.width / 2u);
	const auto halfHeight	= static_cast<float>(extent.height / 2u);

	const auto topLeft		= tcu::Vec4(0.0, 0.0, 1.0, 1.0);
	const auto topRight		= tcu::Vec4(1.0, 0.0, 1.0, 1.0);
	const auto bottomLeft	= tcu::Vec4(0.0, 1.0, 1.0, 1.0);
	const auto bottomRight	= tcu::Vec4(1.0, 1.0, 0.0, 1.0);

	ViewportVec viewports;
	viewports.reserve(kQuadrants);
	viewports.emplace_back(makeViewport(0.0f,		0.0f,		halfWidth, halfHeight, 0.0f, 1.0f));
	viewports.emplace_back(makeViewport(halfWidth,	0.0f,		halfWidth, halfHeight, 0.0f, 1.0f));
	viewports.emplace_back(makeViewport(0.0f,		halfHeight,	halfWidth, halfHeight, 0.0f, 1.0f));
	viewports.emplace_back(makeViewport(halfWidth,	halfHeight,	halfWidth, halfHeight, 0.0f, 1.0f));

	const auto numWorkGroups = (m_shareVertices ? 1u : kQuadrants);
	const IterationParams iterationParams =
	{
		getDefaultExtent(),						//	VkExtent2D		colorExtent;
		1u,										//	uint32_t		numLayers;
		getDefaultDrawCommands(numWorkGroups),	//	DrawCommandVec	drawArgs;
		false,									//	bool			indirect;
		std::move(viewports),					//	ViewportVec		viewports;
	};
	return new QuadrantsInstance(context, iterationParams, topLeft, topRight, bottomLeft, bottomRight);
}

// Position builtin case.
class PositionCase : public MeshShaderBuiltinCase
{
public:
					PositionCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description)
						: MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
						{}
	virtual			~PositionCase	(void) {}

	void			initPrograms		(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance		(Context& context) const override;
};

void PositionCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Mesh shader: emit single triangle around the center of the top left pixel.
	{
		const auto extent	= getDefaultExtent();
		const auto fWidth	= static_cast<float>(extent.width);
		const auto fHeight	= static_cast<float>(extent.height);

		const auto pxWidth	= 2.0f / fWidth;
		const auto pxHeight = 2.0f / fHeight;

		const auto halfXPix	= pxWidth / 2.0f;
		const auto halfYPix	= pxHeight / 2.0f;

		// Center of top left pixel.
		const auto x		= -1.0f + halfXPix;
		const auto y		= -1.0f + halfYPix;

		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=1) out;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 1u;\n"
			<< "\n"
			<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
			<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[2] = 2;\n"
			<< "\n"
			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(" << (x - halfXPix) << ", " << (y + halfYPix) << ", 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[1].gl_Position = vec4(" << (x + halfXPix) << ", " << (y + halfYPix) << ", 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[2].gl_Position = vec4(" << x << ", " << (y - halfYPix) << ", 0.0, 1.0);\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* PositionCase::createInstance (Context& context) const
{
	const IterationParams iterationParams =
	{
		getDefaultExtent(),			//	VkExtent2D		colorExtent;
		1u,							//	uint32_t		numLayers;
		getDefaultDrawCommands(),	//	DrawCommandVec	drawArgs;
		false,						//	bool			indirect;
		{},							//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};

	// Must match the shader.
	PixelMap pixelMap;
	pixelMap[tcu::IVec2(0, 0)] = tcu::Vec4(0.0f, 0.0f, 1.0f, 1.0f);

	const PixelVerifierParams verifierParams =
	{
		tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f),	//	const tcu::Vec4		background;
		std::move(pixelMap),				//	const PixelMap		pixelMap;
	};
	return new PixelsInstance(context, iterationParams, verifierParams);
}

// PointSize builtin case.
class PointSizeCase : public MeshShaderBuiltinCase
{
public:
					PointSizeCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description)
						: MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
						{}
	virtual			~PointSizeCase	(void) {}

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

	static constexpr float kPointSize = 4.0f;
};

void PointSizeCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Mesh shader: large point covering the top left quadrant.
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (points) out;\n"
			<< "layout (max_vertices=1, max_primitives=1) out;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 1u;\n"
			<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-0.5, -0.5, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[0].gl_PointSize = " << kPointSize << ";\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* PointSizeCase::createInstance (Context& context) const
{
	const IterationParams iterationParams =
	{
		getDefaultExtent(),			//	VkExtent2D		colorExtent;
		1u,							//	uint32_t		numLayers;
		getDefaultDrawCommands(),	//	DrawCommandVec	drawArgs;
		false,						//	bool			indirect;
		{},							//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};

	// Must match the shader.
	const tcu::Vec4 black	(0.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4 blue	(0.0f, 0.0f, 1.0f, 1.0f);

	return new QuadrantsInstance(context, iterationParams, blue, black, black, black);
}

void PointSizeCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);
	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_LARGE_POINTS);

	const auto& properties = context.getDeviceProperties();
	if (kPointSize < properties.limits.pointSizeRange[0] || kPointSize > properties.limits.pointSizeRange[1])
		TCU_THROW(NotSupportedError, "Required point size outside point size range");
}

// ClipDistance builtin case.
class ClipDistanceCase : public MeshShaderBuiltinCase
{
public:
					ClipDistanceCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description)
						: MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
						{}
	virtual			~ClipDistanceCase	(void) {}

	void			initPrograms		(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance		(Context& context) const override;
	void			checkSupport		(Context& context) const override;
};

void ClipDistanceCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Mesh shader: full-screen quad using different clip distances.
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=4, max_primitives=2) out;\n"
			<< "\n"
			<< "out gl_MeshPerVertexNV {\n"
			<< "    vec4  gl_Position;\n"
			<< "    float gl_ClipDistance[2];\n"
			<< "} gl_MeshVerticesNV[];\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 2u;\n"
			<< "\n"
			<< "    gl_PrimitiveIndicesNV[0] = 0;\n"
			<< "    gl_PrimitiveIndicesNV[1] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[2] = 2;\n"
			<< "    gl_PrimitiveIndicesNV[3] = 1;\n"
			<< "    gl_PrimitiveIndicesNV[4] = 3;\n"
			<< "    gl_PrimitiveIndicesNV[5] = 2;\n"
			<< "\n"
			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[1].gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[2].gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[3].gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
			<< "\n"
			// The first clip plane keeps the left half of the frame buffer.
			<< "    gl_MeshVerticesNV[0].gl_ClipDistance[0] =  1.0;\n"
			<< "    gl_MeshVerticesNV[1].gl_ClipDistance[0] =  1.0;\n"
			<< "    gl_MeshVerticesNV[2].gl_ClipDistance[0] = -1.0;\n"
			<< "    gl_MeshVerticesNV[3].gl_ClipDistance[0] = -1.0;\n"
			<< "\n"
			// The second clip plane keeps the top half of the frame buffer.
			<< "    gl_MeshVerticesNV[0].gl_ClipDistance[1] =  1.0;\n"
			<< "    gl_MeshVerticesNV[1].gl_ClipDistance[1] = -1.0;\n"
			<< "    gl_MeshVerticesNV[2].gl_ClipDistance[1] =  1.0;\n"
			<< "    gl_MeshVerticesNV[3].gl_ClipDistance[1] = -1.0;\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Fragment shader chooses a constant color.
	{
		std::ostringstream frag;
		frag
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (location=0) out vec4 outColor;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			// White color should not actually be used, as those fragments are supposed to be discarded.
			<< "    outColor = ((gl_ClipDistance[0] >= 0.0 && gl_ClipDistance[1] >= 0.0) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(1.0, 1.0, 1.0, 1.0));\n"
			<< "}\n"
			;
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
	}
}

TestInstance* ClipDistanceCase::createInstance (Context& context) const
{
	const IterationParams iterationParams =
	{
		getDefaultExtent(),			//	VkExtent2D		colorExtent;
		1u,							//	uint32_t		numLayers;
		getDefaultDrawCommands(),	//	DrawCommandVec	drawArgs;
		false,						//	bool			indirect;
		{},							//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};

	// Must match the shader.
	const tcu::Vec4 black	(0.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4 blue	(0.0f, 0.0f, 1.0f, 1.0f);

	return new QuadrantsInstance(context, iterationParams, blue, black, black, black);
}

void ClipDistanceCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);
	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CLIP_DISTANCE);
}

// CullDistance builtin case.
class CullDistanceCase : public MeshShaderBuiltinCase
{
public:
					CullDistanceCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description)
						: MeshShaderBuiltinCase (testCtx, name, description, false/*taskNeeded*/)
						{}
	virtual			~CullDistanceCase	(void) {}

	void			initPrograms		(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance		(Context& context) const override;
	void			checkSupport		(Context& context) const override;
};

void CullDistanceCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Mesh shader: two quads covering the whole screen, one on top of the other.
	// Use cull distances to discard the bottom quad.
	// Use cull distances to paint the top one in two colors: blue on the left, white on the right.
	{
		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=6, max_primitives=4) out;\n"
			<< "\n"
			<< "out gl_MeshPerVertexNV {\n"
			<< "    vec4  gl_Position;\n"
			<< "    float gl_CullDistance[2];\n"
			<< "} gl_MeshVerticesNV[];\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 4u;\n"
			<< "\n"
			<< "    gl_PrimitiveIndicesNV[0]  = 0;\n"
			<< "    gl_PrimitiveIndicesNV[1]  = 1;\n"
			<< "    gl_PrimitiveIndicesNV[2]  = 3;\n"
			<< "    gl_PrimitiveIndicesNV[3]  = 1;\n"
			<< "    gl_PrimitiveIndicesNV[4]  = 4;\n"
			<< "    gl_PrimitiveIndicesNV[5]  = 3;\n"
			<< "    gl_PrimitiveIndicesNV[6]  = 1;\n"
			<< "    gl_PrimitiveIndicesNV[7]  = 2;\n"
			<< "    gl_PrimitiveIndicesNV[8]  = 4;\n"
			<< "    gl_PrimitiveIndicesNV[9]  = 2;\n"
			<< "    gl_PrimitiveIndicesNV[10] = 5;\n"
			<< "    gl_PrimitiveIndicesNV[11] = 4;\n"
			<< "\n"
			<< "    gl_MeshVerticesNV[0].gl_Position = vec4(-1.0, -1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[1].gl_Position = vec4(-1.0,  0.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[2].gl_Position = vec4(-1.0,  1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[3].gl_Position = vec4( 1.0, -1.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[4].gl_Position = vec4( 1.0,  0.0, 0.0, 1.0);\n"
			<< "    gl_MeshVerticesNV[5].gl_Position = vec4( 1.0,  1.0, 0.0, 1.0);\n"
			<< "\n"
			// The first cull plane discards the bottom quad
			<< "    gl_MeshVerticesNV[0].gl_CullDistance[0] =  1.0;\n"
			<< "    gl_MeshVerticesNV[1].gl_CullDistance[0] = -1.0;\n"
			<< "    gl_MeshVerticesNV[2].gl_CullDistance[0] = -2.0;\n"
			<< "    gl_MeshVerticesNV[3].gl_CullDistance[0] =  1.0;\n"
			<< "    gl_MeshVerticesNV[4].gl_CullDistance[0] = -1.0;\n"
			<< "    gl_MeshVerticesNV[5].gl_CullDistance[0] = -2.0;\n"
			<< "\n"
			// The second cull plane helps paint left and right different.
			<< "    gl_MeshVerticesNV[0].gl_CullDistance[1] =  1.0;\n"
			<< "    gl_MeshVerticesNV[1].gl_CullDistance[1] =  1.0;\n"
			<< "    gl_MeshVerticesNV[2].gl_CullDistance[1] =  1.0;\n"
			<< "    gl_MeshVerticesNV[3].gl_CullDistance[1] = -1.0;\n"
			<< "    gl_MeshVerticesNV[4].gl_CullDistance[1] = -1.0;\n"
			<< "    gl_MeshVerticesNV[5].gl_CullDistance[1] = -1.0;\n"
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	// Fragment shader chooses color based on the second cull distance.
	{
		std::ostringstream frag;
		frag
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (location=0) out vec4 outColor;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    outColor = ((gl_CullDistance[1] >= 0.0) ? vec4(0.0, 0.0, 1.0, 1.0) : vec4(1.0, 1.0, 1.0, 1.0));\n"
			<< "}\n"
			;
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag.str());
	}
}

TestInstance* CullDistanceCase::createInstance (Context& context) const
{
	const IterationParams iterationParams =
	{
		getDefaultExtent(),			//	VkExtent2D		colorExtent;
		1u,							//	uint32_t		numLayers;
		getDefaultDrawCommands(),	//	DrawCommandVec	drawArgs;
		false,						//	bool			indirect;
		{},							//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};

	// Must match the shader.
	const tcu::Vec4 black	(0.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4 blue	(0.0f, 0.0f, 1.0f, 1.0f);
	const tcu::Vec4 white	(1.0f, 1.0f, 1.0f, 1.0f);

	return new QuadrantsInstance(context, iterationParams, blue, white, black, black);
}

void CullDistanceCase::checkSupport (Context& context) const
{
	MeshShaderBuiltinCase::checkSupport(context);
	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SHADER_CULL_DISTANCE);
}

// Generates statements to draw a triangle around the given pixel number, knowing the framebuffer width (len).
// Supposes the height of the framebuffer is 1.
std::string triangleForPixel(const std::string& pixel, const std::string& len, const std::string& baseIndex)
{
	std::ostringstream statements;
	statements
		<< "    const float imgWidth = float(" << len << ");\n"
		<< "    const float pixWidth = (2.0 / imgWidth);\n"
		<< "    const float halfPix  = (pixWidth / 2.0);\n"
		<< "    const float xCenter  = (((float(" << pixel << ") + 0.5) / imgWidth) * 2.0 - 1.0);\n"
		<< "    const float xLeft    = (xCenter - halfPix);\n"
		<< "    const float xRight   = (xCenter + halfPix);\n"
		<< "    const uvec3 indices  = uvec3(" << baseIndex << " + 0, " << baseIndex << " + 1, " << baseIndex << " + 2);\n"
		<< "\n"
		<< "    gl_PrimitiveIndicesNV[indices.x] = indices.x;\n"
		<< "    gl_PrimitiveIndicesNV[indices.y] = indices.y;\n"
		<< "    gl_PrimitiveIndicesNV[indices.z] = indices.z;\n"
		<< "\n"
		<< "    gl_MeshVerticesNV[indices.x].gl_Position = vec4(xLeft,    0.5, 0.0, 1.0);\n"
		<< "    gl_MeshVerticesNV[indices.y].gl_Position = vec4(xRight,   0.5, 0.0, 1.0);\n"
		<< "    gl_MeshVerticesNV[indices.z].gl_Position = vec4(xCenter, -0.5, 0.0, 1.0);\n"
		;
	return statements.str();
}

// WorkGroupID builtin case.
class WorkGroupIdCase : public MeshShaderBuiltinCase
{
public:
					WorkGroupIdCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
						: MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
						, m_extent				(getLinearExtent())
						{}
	virtual			~WorkGroupIdCase	(void) {}

	void			initPrograms		(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance		(Context& context) const override;

protected:
	const VkExtent2D m_extent;
};

void WorkGroupIdCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const std::string taskDataDecl =
		"taskNV TaskData {\n"
		"    uint id;\n"
		"    uint size;\n"
		"} td;\n"
		;

	// Mesh shader: each work group fills one pixel.
	{
		const std::string pixel = (m_taskNeeded ? "td.id"   : "gl_WorkGroupID.x"   );
		const std::string len   = (m_taskNeeded ? "td.size" : de::toString(m_extent.width) );

		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=1) out;\n"
			<< "\n"
			<< (m_taskNeeded ? ("in " + taskDataDecl) : "")
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 1u;\n"
			<< "\n"
			<< triangleForPixel(pixel, len, "0")
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	if (m_taskNeeded)
	{
		std::ostringstream task;
		task
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "\n"
			<< "out " << taskDataDecl
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_TaskCountNV = 1u;\n"
			<< "    td.id          = gl_WorkGroupID.x;\n"
			<< "    td.size        = " << m_extent.width << ";\n"
			<< "}\n"
			;
		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* WorkGroupIdCase::createInstance (Context& context) const
{
	// Must match the shader.
	const ColorVec			expectedColors	(1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
	const IterationParams	iterationParams	=
	{
		m_extent,								//	VkExtent2D		colorExtent;
		1u,										//	uint32_t		numLayers;
		getDefaultDrawCommands(m_extent.width),	//	DrawCommandVec	drawArgs;
		false,									//	bool			indirect;
		{},										//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

// Variable to use.
enum class LocalInvocation { ID=0, INDEX };

// LocalInvocationId and LocalInvocationIndex builtin cases. These are also used to test WorkGroupSize.
class LocalInvocationCase : public MeshShaderBuiltinCase
{
public:
					LocalInvocationCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded, LocalInvocation variable)
						: MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
						, m_extent				(getLinearExtent())
						, m_variable			(variable)
						{}
	virtual			~LocalInvocationCase	(void) {}

	void			initPrograms			(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance			(Context& context) const override;

protected:
	const VkExtent2D      m_extent;
	const LocalInvocation m_variable;
};

void LocalInvocationCase::initPrograms (vk::SourceCollections& programCollection) const
{
	// Invocation index to use.
	const std::string localIndex = ((m_variable == LocalInvocation::ID) ? "gl_LocalInvocationID.x" : "gl_LocalInvocationIndex");

	// Task data.
	std::ostringstream taskDataDecl;
	taskDataDecl
		<< "taskNV TaskData {\n"
		// indexNumber[x] == x
		<< "    uint indexNumber[" << m_extent.width << "];\n"
		<< "    uint size;\n"
		<< "} td;\n"
		;
	const auto taskDataDeclStr = taskDataDecl.str();

	// Mesh shader: each work group fills one pixel.
	{
		const std::string pixel     = (m_taskNeeded ? "td.indexNumber[gl_WorkGroupID.x]" : localIndex);
		const std::string len       = (m_taskNeeded ? "td.size" : "gl_WorkGroupSize.x");
		const auto        localSize = (m_taskNeeded ? 1u : m_extent.width);
		const auto        maxVert   = localSize * 3u;
		const std::string baseIndex = (m_taskNeeded ? "0" : "(" + localIndex + " * 3u)");

		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << localSize << ") in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=" << maxVert << ", max_primitives=" << localSize << ") out;\n"
			<< "\n"
			<< (m_taskNeeded ? ("in " + taskDataDeclStr) : "")
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = " << localSize << ";\n"
			<< "\n"
			<< triangleForPixel(pixel, len, baseIndex)
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	if (m_taskNeeded)
	{
		std::ostringstream task;
		task
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << m_extent.width << ") in;\n"
			<< "\n"
			<< "out " << taskDataDeclStr
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_TaskCountNV = " << m_extent.width << ";\n"
			<< "    td.indexNumber[" << localIndex << "] = " << localIndex << ";\n"
			<< "    td.size = gl_WorkGroupSize.x;\n"
			<< "}\n"
			;
		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* LocalInvocationCase::createInstance (Context& context) const
{
	// Must match the shader.
	const ColorVec			expectedColors	(1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
	const IterationParams	iterationParams	=
	{
		m_extent,								//	VkExtent2D		colorExtent;
		1u,										//	uint32_t		numLayers;
		getDefaultDrawCommands(),				//	DrawCommandVec	drawArgs;
		false,									//	bool			indirect;
		{},										//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

// GlobalInvocationId builtin case.
class GlobalInvocationIdCase : public MeshShaderBuiltinCase
{
public:
					GlobalInvocationIdCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
						: MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
						, m_jobSize				(getLargeJobSize())
						, m_extent				{m_jobSize.numTasks * m_jobSize.localSize, 1u}
						{}
	virtual			~GlobalInvocationIdCase		(void) {}

	void			initPrograms				(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance				(Context& context) const override;

protected:
	const JobSize    m_jobSize;
	const VkExtent2D m_extent;
};

void GlobalInvocationIdCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const auto& localSize = m_jobSize.localSize;

	// Task data.
	std::ostringstream taskDataDecl;
	taskDataDecl
		<< "taskNV TaskData {\n"
		<< "    uint pixelId[" << localSize << "];\n"
		<< "    uint size;\n"
		<< "} td;\n"
		;
	const auto taskDataDeclStr = taskDataDecl.str();

	// Mesh shader: each work group fills one pixel.
	{
		const std::string pixel     = (m_taskNeeded ? "td.pixelId[gl_LocalInvocationIndex]" : "gl_GlobalInvocationID.x");
		const std::string len       = (m_taskNeeded ? "td.size" : de::toString(m_extent.width));
		const std::string baseIndex = "(gl_LocalInvocationIndex * 3u)";
		const auto        maxVert   = localSize * 3u;

		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << localSize << ") in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=" << maxVert << ", max_primitives=" << localSize << ") out;\n"
			<< "\n"
			<< (m_taskNeeded ? ("in " + taskDataDeclStr) : "")
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = " << localSize << ";\n"
			<< "\n"
			<< triangleForPixel(pixel, len, baseIndex)
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	if (m_taskNeeded)
	{
		std::ostringstream task;
		task
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=" << localSize << ") in;\n"
			<< "\n"
			<< "out " << taskDataDeclStr
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_TaskCountNV = 1;\n"
			<< "    td.pixelId[gl_LocalInvocationIndex] = gl_GlobalInvocationID.x;\n"
			<< "    td.size = " << m_extent.width << ";\n"
			<< "}\n"
			;
		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* GlobalInvocationIdCase::createInstance (Context& context) const
{
	// Must match the shader.
	const ColorVec			expectedColors	(1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
	const IterationParams	iterationParams	=
	{
		m_extent,									//	VkExtent2D		colorExtent;
		1u,											//	uint32_t		numLayers;
		getDefaultDrawCommands(m_jobSize.numTasks),	//	DrawCommandVec	drawArgs;
		false,										//	bool			indirect;
		{},											//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

// DrawIndex builtin case.
class DrawIndexCase : public MeshShaderBuiltinCase
{
public:
					DrawIndexCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, bool taskNeeded)
						: MeshShaderBuiltinCase (testCtx, name, description, taskNeeded)
						, m_extent				(getLinearExtent())
						{}
	virtual			~DrawIndexCase	(void) {}

	void			initPrograms		(vk::SourceCollections& programCollection) const override;
	TestInstance*	createInstance		(Context& context) const override;

protected:
	const VkExtent2D m_extent;
};

void DrawIndexCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const std::string taskDataDecl =
		"taskNV TaskData {\n"
		"    uint id;\n"
		"    uint size;\n"
		"} td;\n"
		;

	const auto drawIndex = "uint(gl_DrawID)";

	// Mesh shader: each work group fills one pixel.
	{
		const std::string pixel = (m_taskNeeded ? "td.id"   : drawIndex);
		const std::string len   = (m_taskNeeded ? "td.size" : de::toString(m_extent.width));

		std::ostringstream mesh;
		mesh
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "layout (triangles) out;\n"
			<< "layout (max_vertices=3, max_primitives=1) out;\n"
			<< "\n"
			<< (m_taskNeeded ? ("in " + taskDataDecl) : "")
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_PrimitiveCountNV = 1u;\n"
			<< "\n"
			<< triangleForPixel(pixel, len, "0")
			<< "}\n"
			;
		programCollection.glslSources.add("mesh") << glu::MeshSource(mesh.str());
	}

	if (m_taskNeeded)
	{
		std::ostringstream task;
		task
			<< "#version 460\n"
			<< "#extension GL_NV_mesh_shader : enable\n"
			<< "\n"
			<< "layout (local_size_x=1) in;\n"
			<< "\n"
			<< "out " << taskDataDecl
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "    gl_TaskCountNV = 1u;\n"
			<< "    td.id          = " << drawIndex << ";\n"
			<< "    td.size        = " << m_extent.width << ";\n"
			<< "}\n"
			;
		programCollection.glslSources.add("task") << glu::TaskSource(task.str());
	}

	// Basic fragment shader.
	{
		const auto frag = getBasicFragShader();
		programCollection.glslSources.add("frag") << glu::FragmentSource(frag);
	}
}

TestInstance* DrawIndexCase::createInstance (Context& context) const
{
	// Must match the shader.
	const ColorVec			expectedColors	(1u, tcu::Vec4(0.0, 0.0, 1.0, 1.0));
	const DrawCommandVec	commands		(m_extent.width, makeDrawMeshTasksIndirectCommandNV(1u, 0u));
	const IterationParams	iterationParams	=
	{
		m_extent,	//	VkExtent2D		colorExtent;
		1u,			//	uint32_t		numLayers;
		commands,	//	DrawCommandVec	drawArgs;
		true,		//	bool			indirect;
		{},			//	ViewportVec		viewports;	// If empty, a single default viewport is used.
	};
	return new FullScreenColorInstance(context, iterationParams, expectedColors);
}

} // anonymous

tcu::TestCaseGroup* createMeshShaderBuiltinTests (tcu::TestContext& testCtx)
{
	GroupPtr mainGroup (new tcu::TestCaseGroup(testCtx, "builtin", "Mesh Shader Builtin Tests"));

	mainGroup->addChild(new PositionCase				(testCtx, "position", ""));
	mainGroup->addChild(new PointSizeCase				(testCtx, "point_size", ""));
	mainGroup->addChild(new ClipDistanceCase			(testCtx, "clip_distance", ""));
	mainGroup->addChild(new CullDistanceCase			(testCtx, "cull_distance", ""));
	mainGroup->addChild(new PrimitiveIdCase				(testCtx, "primitive_id_glsl", "", true/*glslFrag*/));
	mainGroup->addChild(new PrimitiveIdCase				(testCtx, "primitive_id_spirv", "", false/*glslFrag*/));
	mainGroup->addChild(new LayerCase					(testCtx, "layer", "", false/*shareVertices*/));
	mainGroup->addChild(new LayerCase					(testCtx, "layer_shared", "", true/*shareVertices*/));
	mainGroup->addChild(new ViewportIndexCase			(testCtx, "viewport_index", "", false/*shareVertices*/));
	mainGroup->addChild(new ViewportIndexCase			(testCtx, "viewport_index_shared", "", true/*shareVertices*/));
	mainGroup->addChild(new WorkGroupIdCase				(testCtx, "work_group_id_in_mesh", "", false/*taskNeeded*/));
	mainGroup->addChild(new WorkGroupIdCase				(testCtx, "work_group_id_in_task", "", true/*taskNeeded*/));
	mainGroup->addChild(new LocalInvocationCase			(testCtx, "local_invocation_id_in_mesh", "", false/*taskNeeded*/, LocalInvocation::ID));
	mainGroup->addChild(new LocalInvocationCase			(testCtx, "local_invocation_id_in_task", "", true/*taskNeeded*/, LocalInvocation::ID));
	mainGroup->addChild(new LocalInvocationCase			(testCtx, "local_invocation_index_in_task", "", true/*taskNeeded*/, LocalInvocation::INDEX));
	mainGroup->addChild(new LocalInvocationCase			(testCtx, "local_invocation_index_in_mesh", "", false/*taskNeeded*/, LocalInvocation::INDEX));
	mainGroup->addChild(new GlobalInvocationIdCase		(testCtx, "global_invocation_id_in_mesh", "", false/*taskNeeded*/));
	mainGroup->addChild(new GlobalInvocationIdCase		(testCtx, "global_invocation_id_in_task", "", true/*taskNeeded*/));
	mainGroup->addChild(new DrawIndexCase				(testCtx, "draw_index_in_mesh", "", false/*taskNeeded*/));
	mainGroup->addChild(new DrawIndexCase				(testCtx, "draw_index_in_task", "", true/*taskNeeded*/));

	return mainGroup.release();
}

} // MeshShader
} // vkt
