/*------------------------------------------------------------------------
 * 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 Dynamic State tests mixing it with compute and transfer.
 *//*--------------------------------------------------------------------*/
#include "vktDynamicStateComputeTests.hpp"

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

#include "tcuVector.hpp"

#include <vector>
#include <string>
#include <functional>
#include <map>
#include <sstream>
#include <cstring>
#include <iterator>
#include <numeric>

namespace vkt
{
namespace DynamicState
{

namespace
{

using namespace vk;

// Additional objects needed to set a given dynamic state that need to exist beyond the state-setting call. Empty by default.
struct DynamicStateData
{
	virtual ~DynamicStateData() {}
};

// A vertex buffer and graphics pipeline are needed for vkCmdBindVertexBuffers2EXT().
struct BindVertexBuffersData : public DynamicStateData
{
private:
	using BufferPtr			= de::MovePtr<BufferWithMemory>;
	using RenderPassPtr		= Move<VkRenderPass>;
	using LayoutPtr			= Move<VkPipelineLayout>;
	using ModulePtr			= Move<VkShaderModule>;
	using PipelinePtr		= Move<VkPipeline>;

	static constexpr deUint32 kWidth	= 16u;
	static constexpr deUint32 kHeight	= 16u;

	VkExtent3D getExtent (void)
	{
		return makeExtent3D(kWidth, kHeight, 1u);
	}

public:
	BindVertexBuffersData(Context& ctx)
		: m_vertexBuffer		()
		, m_dataSize			(0u)
		, m_vertexBufferSize	(0ull)
		, m_renderPass			()
		, m_pipelineLayout		()
		, m_vertexShader		()
		, m_graphicsPipeline	()
	{
		const auto&	vki			= ctx.getInstanceInterface();
		const auto	phyDev		= ctx.getPhysicalDevice();
		const auto&	vkd			= ctx.getDeviceInterface();
		const auto	device		= ctx.getDevice();
		auto&		alloc		= ctx.getDefaultAllocator();

		// Vertex buffer.
		tcu::Vec4	vertex		(0.f, 0.f, 0.f, 1.f);
		m_dataSize				= sizeof(vertex);
		m_vertexBufferSize		= de::roundUp(static_cast<VkDeviceSize>(m_dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
		const auto	bufferInfo	= makeBufferCreateInfo(m_vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);

		m_vertexBuffer			= BufferPtr(new BufferWithMemory(vkd, device, alloc, bufferInfo, MemoryRequirement::HostVisible));
		auto&	bufferAlloc		= m_vertexBuffer->getAllocation();

		deMemcpy(bufferAlloc.getHostPtr(), &vertex, m_dataSize);
		flushAlloc(vkd, device, bufferAlloc);

		// Empty render pass.
		m_renderPass = makeRenderPass(vkd, device);

		// Empty pipeline layout.
		m_pipelineLayout = makePipelineLayout(vkd, device);

		// Passthrough vertex shader.
		m_vertexShader = createShaderModule(vkd, device, ctx.getBinaryCollection().get("vert"), 0u);

		const auto						extent		= getExtent();
		const std::vector<VkViewport>	viewports	(1, makeViewport(extent));
		const std::vector<VkRect2D>		scissors	(1, makeRect2D(extent));
		const VkDynamicState			state		= VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT;

		const VkPipelineDynamicStateCreateInfo dynamicStateInfo =
		{
			VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//	VkStructureType						sType;
			nullptr,												//	const void*							pNext;
			0u,														//	VkPipelineDynamicStateCreateFlags	flags;
			1u,														//	deUint32							dynamicStateCount;
			&state,													//	const VkDynamicState*				pDynamicStates;
		};

		// Graphics pipeline.
		m_graphicsPipeline = makeGraphicsPipeline(vkd, device, m_pipelineLayout.get(),
			m_vertexShader.get(), DE_NULL, DE_NULL, DE_NULL, DE_NULL,
			m_renderPass.get(), viewports, scissors, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, 0u, 0u,
			nullptr, nullptr, nullptr, nullptr, nullptr, &dynamicStateInfo);
	}

	const BufferWithMemory*	getVertexBuffer () const
	{
		return m_vertexBuffer.get();
	}

	size_t getDataSize () const
	{
		return m_dataSize;
	}

	VkPipeline getPipeline () const
	{
		return m_graphicsPipeline.get();
	}

	virtual ~BindVertexBuffersData() {}

private:
	BufferPtr		m_vertexBuffer;
	size_t			m_dataSize;
	VkDeviceSize	m_vertexBufferSize;
	RenderPassPtr	m_renderPass;
	LayoutPtr		m_pipelineLayout;
	ModulePtr		m_vertexShader;
	PipelinePtr		m_graphicsPipeline;
};

// Function that records a state-setting command in the given command buffer.
using RecordStateFunction = std::function<void(const DeviceInterface*, VkCommandBuffer, const DynamicStateData*)>;

// State-setting functions
void setViewport (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkViewport viewport =
	{
		0.0f,	//	float	x;
		0.0f,	//	float	y;
		1.0f,	//	float	width;
		1.0f,	//	float	height;
		0.0f,	//	float	minDepth;
		1.0f,	//	float	maxDepth;
	};
	vkd->cmdSetViewport(cmdBuffer, 0u, 1u, &viewport);
}

void setScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkRect2D scissor =
	{
		{ 0, 0 },	//	VkOffset2D	offset;
		{ 1u, 1u },	//	VkExtent2D	extent;
	};
	vkd->cmdSetScissor(cmdBuffer, 0u, 1u, &scissor);
}

void setLineWidth (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetLineWidth(cmdBuffer, 1.0f);
}

void setDepthBias (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthBias(cmdBuffer, 0.0f, 0.0f, 0.0f);
}

void setBlendConstants (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const float blendConstants[4] = { 0.0f, 0.0f, 0.0f, 0.0f };
	vkd->cmdSetBlendConstants(cmdBuffer, blendConstants);
}

void setDepthBounds (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthBounds(cmdBuffer, 0.0f, 1.0f);
}

void setStencilCompareMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetStencilCompareMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
}

void setStencilWriteMask (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetStencilWriteMask(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
}

void setStencilReference (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetStencilReference(cmdBuffer, VK_STENCIL_FACE_FRONT_AND_BACK, 0xFFu);
}

void setDiscardRectangle (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkRect2D rectangle =
	{
		{ 0, 0 },	//	VkOffset2D	offset;
		{ 1u, 1u },	//	VkExtent2D	extent;
	};
	vkd->cmdSetDiscardRectangleEXT(cmdBuffer, 0u, 1u, &rectangle);
}

void setSampleLocations (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkSampleLocationEXT locations[] =
	{
		{ 0.5f, 0.5f },
		{ 0.5f, 1.5f },
		{ 1.5f, 0.5f },
		{ 1.5f, 1.5f },
	};
	const VkSampleLocationsInfoEXT info =
	{
		VK_STRUCTURE_TYPE_SAMPLE_LOCATIONS_INFO_EXT,	//	VkStructureType				sType;
		nullptr,										//	const void*					pNext;
		VK_SAMPLE_COUNT_4_BIT,							//	VkSampleCountFlagBits		sampleLocationsPerPixel;
		{ 1u, 1u },										//	VkExtent2D					sampleLocationGridSize;
		4u,												//	deUint32					sampleLocationsCount;
		locations,										//	const VkSampleLocationEXT*	pSampleLocations;
	};
	vkd->cmdSetSampleLocationsEXT(cmdBuffer, &info);
}

void setRTPipelineStatckSize (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetRayTracingPipelineStackSizeKHR(cmdBuffer, 4096u);
}

void setFragmentShadingRage (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkExtent2D							fragmentSize	= { 1u, 1u };
	const VkFragmentShadingRateCombinerOpKHR	combinerOps[2]	=
	{
		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
		VK_FRAGMENT_SHADING_RATE_COMBINER_OP_KEEP_KHR,
	};
	vkd->cmdSetFragmentShadingRateKHR(cmdBuffer, &fragmentSize, combinerOps);
}

void setLineStipple (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetLineStippleEXT(cmdBuffer, 1u, 1u);
}

void setCullMode (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetCullModeEXT(cmdBuffer, VK_CULL_MODE_FRONT_AND_BACK);
}

void setFrontFace (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetFrontFaceEXT(cmdBuffer, VK_FRONT_FACE_COUNTER_CLOCKWISE);
}

void setPrimitiveTopology (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetPrimitiveTopologyEXT(cmdBuffer, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);
}

void setViewportWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkViewport viewport =
	{
		0.0f,	//	float	x;
		0.0f,	//	float	y;
		1.0f,	//	float	width;
		1.0f,	//	float	height;
		0.0f,	//	float	minDepth;
		1.0f,	//	float	maxDepth;
	};
	vkd->cmdSetViewportWithCountEXT(cmdBuffer, 1u, &viewport);
}

void setScissorWithCount (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkRect2D scissor =
	{
		{ 0, 0 },	//	VkOffset2D	offset;
		{ 1u, 1u },	//	VkExtent2D	extent;
	};
	vkd->cmdSetScissorWithCountEXT(cmdBuffer, 1u, &scissor);
}

void bindVertexBuffers (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData* data)
{
	const auto bindData			= dynamic_cast<const BindVertexBuffersData*>(data);
	DE_ASSERT(bindData != nullptr);
	const auto vertexBuffer		= bindData->getVertexBuffer();
	const auto dataSize			= static_cast<VkDeviceSize>(bindData->getDataSize());
	const auto bufferOffset		= vertexBuffer->getAllocation().getOffset();
	const auto stride			= static_cast<VkDeviceSize>(0);
	const auto pipeline			= bindData->getPipeline();

	vkd->cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
	vkd->cmdBindVertexBuffers2EXT(cmdBuffer, 0u, 1u, &vertexBuffer->get(), &bufferOffset, &dataSize, &stride);
}

void setDepthTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthTestEnableEXT(cmdBuffer, VK_TRUE);
}

void setDepthWriteEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthWriteEnableEXT(cmdBuffer, VK_TRUE);
}

void setDepthCompareOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthCompareOpEXT(cmdBuffer, VK_COMPARE_OP_LESS);
}

void setDepthBoundsTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetDepthBoundsTestEnableEXT(cmdBuffer, VK_TRUE);
}

void setStencilTestEnable (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetStencilTestEnableEXT(cmdBuffer, VK_TRUE);
}

void setStencilOp (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	vkd->cmdSetStencilOpEXT(cmdBuffer, VK_STENCIL_FRONT_AND_BACK, VK_STENCIL_OP_ZERO, VK_STENCIL_OP_INCREMENT_AND_CLAMP, VK_STENCIL_OP_KEEP, VK_COMPARE_OP_ALWAYS);
}

void setViewportWScaling (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkViewportWScalingNV viewport =
	{
		1.0f,	//	float	xcoeff;
		1.0f,	//	float	ycoeff;
	};
	vkd->cmdSetViewportWScalingNV(cmdBuffer, 0u, 1u, &viewport);
}

void setViewportShadingRatePalette (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkShadingRatePaletteEntryNV	entry	= VK_SHADING_RATE_PALETTE_ENTRY_NO_INVOCATIONS_NV;
	const VkShadingRatePaletteNV		palette	=
	{
		1u,		//	deUint32							shadingRatePaletteEntryCount;
		&entry,	//	const VkShadingRatePaletteEntryNV*	pShadingRatePaletteEntries;
	};
	vkd->cmdSetViewportShadingRatePaletteNV(cmdBuffer, 0u, 1u, &palette);
}

void setCoarseSamplingOrder (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkCoarseSampleLocationNV location =
	{
		0u,	//	deUint32	pixelX;
		0u,	//	deUint32	pixelY;
		0u,	//	deUint32	sample;
	};
	const VkCoarseSampleOrderCustomNV order =
	{
		VK_SHADING_RATE_PALETTE_ENTRY_1_INVOCATION_PER_PIXEL_NV,	//	VkShadingRatePaletteEntryNV		shadingRate;
		1u,															//	deUint32						sampleCount;
		1u,															//	deUint32						sampleLocationCount;
		&location													//	const VkCoarseSampleLocationNV*	pSampleLocations;
	};
	vkd->cmdSetCoarseSampleOrderNV(cmdBuffer, VK_COARSE_SAMPLE_ORDER_TYPE_CUSTOM_NV, 1u, &order);
}

void setExclusiveScissor (const DeviceInterface* vkd, VkCommandBuffer cmdBuffer, const DynamicStateData*)
{
	const VkRect2D scissor =
	{
		{ 0, 0 },	//	VkOffset2D	offset;
		{ 1u, 1u },	//	VkExtent2D	extent;
	};
	vkd->cmdSetExclusiveScissorNV(cmdBuffer, 0u, 1u, &scissor);
}

const VkDynamicState dynamicStateList[] =
{
	VK_DYNAMIC_STATE_VIEWPORT,
	VK_DYNAMIC_STATE_SCISSOR,
	VK_DYNAMIC_STATE_LINE_WIDTH,
	VK_DYNAMIC_STATE_DEPTH_BIAS,
	VK_DYNAMIC_STATE_BLEND_CONSTANTS,
	VK_DYNAMIC_STATE_DEPTH_BOUNDS,
	VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,
	VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,
	VK_DYNAMIC_STATE_STENCIL_REFERENCE,
	VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,
	VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,
	VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR,
	VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,
	VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,
	VK_DYNAMIC_STATE_CULL_MODE_EXT,
	VK_DYNAMIC_STATE_FRONT_FACE_EXT,
	VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,
	VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,
	VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,
	VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,
	VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,
	VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,
	VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,
	VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,
	VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,
	VK_DYNAMIC_STATE_STENCIL_OP_EXT,
	VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,
	VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,
	VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,
	VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,
};

// Information about a dynamic state.
struct StateInfo
{
	std::vector<std::string>	requirements;	// List of required functionalities.
	RecordStateFunction			recorder;		// Function that records the state to the command buffer being used.
};

// Returns the state info for a given dynamic state.
const StateInfo& getDynamicStateInfo (VkDynamicState state)
{
	// Maps a given state to its state info structure.
	using StateInfoMap = std::map<VkDynamicState, StateInfo>;

	static const StateInfoMap result =
	{
		{	VK_DYNAMIC_STATE_VIEWPORT,								{	{},										setViewport						}	},
		{	VK_DYNAMIC_STATE_SCISSOR,								{	{},										setScissor						}	},
		{	VK_DYNAMIC_STATE_LINE_WIDTH,							{	{},										setLineWidth					}	},
		{	VK_DYNAMIC_STATE_DEPTH_BIAS,							{	{},										setDepthBias					}	},
		{	VK_DYNAMIC_STATE_BLEND_CONSTANTS,						{	{},										setBlendConstants				}	},
		{	VK_DYNAMIC_STATE_DEPTH_BOUNDS,							{	{},										setDepthBounds					}	},
		{	VK_DYNAMIC_STATE_STENCIL_COMPARE_MASK,					{	{},										setStencilCompareMask			}	},
		{	VK_DYNAMIC_STATE_STENCIL_WRITE_MASK,					{	{},										setStencilWriteMask				}	},
		{	VK_DYNAMIC_STATE_STENCIL_REFERENCE,						{	{},										setStencilReference				}	},
		{	VK_DYNAMIC_STATE_DISCARD_RECTANGLE_EXT,					{	{ "VK_EXT_discard_rectangles" },		setDiscardRectangle				}	},
		{	VK_DYNAMIC_STATE_SAMPLE_LOCATIONS_EXT,					{	{ "VK_EXT_sample_locations" },			setSampleLocations				}	},
		{	VK_DYNAMIC_STATE_RAY_TRACING_PIPELINE_STACK_SIZE_KHR,	{	{ "VK_KHR_ray_tracing_pipeline" },		setRTPipelineStatckSize			}	},
		{	VK_DYNAMIC_STATE_FRAGMENT_SHADING_RATE_KHR,				{	{ "VK_KHR_fragment_shading_rate" },		setFragmentShadingRage			}	},
		{	VK_DYNAMIC_STATE_LINE_STIPPLE_EXT,						{	{ "VK_EXT_line_rasterization" },		setLineStipple					}	},
		{	VK_DYNAMIC_STATE_CULL_MODE_EXT,							{	{ "VK_EXT_extended_dynamic_state" },	setCullMode						}	},
		{	VK_DYNAMIC_STATE_FRONT_FACE_EXT,						{	{ "VK_EXT_extended_dynamic_state" },	setFrontFace					}	},
		{	VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setPrimitiveTopology			}	},
		{	VK_DYNAMIC_STATE_VIEWPORT_WITH_COUNT_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setViewportWithCount			}	},
		{	VK_DYNAMIC_STATE_SCISSOR_WITH_COUNT_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setScissorWithCount				}	},
		{	VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT,		{	{ "VK_EXT_extended_dynamic_state" },	bindVertexBuffers				}	},
		{	VK_DYNAMIC_STATE_DEPTH_TEST_ENABLE_EXT,					{	{ "VK_EXT_extended_dynamic_state" },	setDepthTestEnable				}	},
		{	VK_DYNAMIC_STATE_DEPTH_WRITE_ENABLE_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setDepthWriteEnable				}	},
		{	VK_DYNAMIC_STATE_DEPTH_COMPARE_OP_EXT,					{	{ "VK_EXT_extended_dynamic_state" },	setDepthCompareOp				}	},
		{	VK_DYNAMIC_STATE_DEPTH_BOUNDS_TEST_ENABLE_EXT,			{	{ "VK_EXT_extended_dynamic_state" },	setDepthBoundsTestEnable		}	},
		{	VK_DYNAMIC_STATE_STENCIL_TEST_ENABLE_EXT,				{	{ "VK_EXT_extended_dynamic_state" },	setStencilTestEnable			}	},
		{	VK_DYNAMIC_STATE_STENCIL_OP_EXT,						{	{ "VK_EXT_extended_dynamic_state" },	setStencilOp					}	},
		{	VK_DYNAMIC_STATE_VIEWPORT_W_SCALING_NV,					{	{ "VK_NV_clip_space_w_scaling" },		setViewportWScaling				}	},
		{	VK_DYNAMIC_STATE_VIEWPORT_SHADING_RATE_PALETTE_NV,		{	{ "VK_NV_shading_rate_image"},			setViewportShadingRatePalette	}	},
		{	VK_DYNAMIC_STATE_VIEWPORT_COARSE_SAMPLE_ORDER_NV,		{	{ "VK_NV_shading_rate_image"},			setCoarseSamplingOrder			}	},
		{	VK_DYNAMIC_STATE_EXCLUSIVE_SCISSOR_NV,					{	{ "VK_NV_scissor_exclusive"},			setExclusiveScissor				}	},
	};

	const auto itr = result.find(state);
	DE_ASSERT(itr != result.end());

	return itr->second;
}

// Returns the set of auxiliary data needed to set a given state.
de::MovePtr<DynamicStateData> getDynamicStateData (Context& ctx, VkDynamicState state)
{
	// Create vertex buffer for VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT.
	if (state == VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT)
		return de::MovePtr<DynamicStateData>(new BindVertexBuffersData(ctx));

	// null pointer normally.
	return de::MovePtr<DynamicStateData>();
}

enum class OperType		{ COMPUTE = 0,	TRANSFER	};
enum class WhenToSet	{ BEFORE = 0,	AFTER		};

// Set dynamic state before or after attempting to run a compute or transfer operation.
struct TestParams
{
	OperType					operationType;
	WhenToSet					whenToSet;
	std::vector<VkDynamicState>	states;
};

class DynamicStateComputeCase : public vkt::TestCase
{
public:

							DynamicStateComputeCase		(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params);
	virtual					~DynamicStateComputeCase	(void) {}

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

protected:
	TestParams				m_params;
};

class DynamicStateComputeInstance : public vkt::TestInstance
{
public:
								DynamicStateComputeInstance		(Context& context, const TestParams& params);
	virtual						~DynamicStateComputeInstance	(void) {}

	virtual tcu::TestStatus		iterate							(void);

protected:
	tcu::TestStatus				iterateTransfer					(void);
	tcu::TestStatus				iterateCompute					(void);

	TestParams					m_params;
};

DynamicStateComputeCase::DynamicStateComputeCase(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const TestParams& params)
	: vkt::TestCase	(testCtx, name, description)
	, m_params		(params)
{}

DynamicStateComputeInstance::DynamicStateComputeInstance (Context& context, const TestParams& params)
	: vkt::TestInstance (context)
	, m_params			(params)
{}

void DynamicStateComputeCase::checkSupport (Context& context) const
{
	// Check required functionalities.
	for (const auto& state : m_params.states)
	{
		const auto stateInfo = getDynamicStateInfo(state);
		for (const auto& functionality : stateInfo.requirements)
			context.requireDeviceFunctionality(functionality);
	}
}

void DynamicStateComputeCase::initPrograms (vk::SourceCollections& programCollection) const
{
	if (m_params.operationType == OperType::COMPUTE)
	{
		std::ostringstream comp;
		comp
			<< "#version 450\n"
			<< "\n"
			<< "layout (local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
			<< "\n"
			<< "layout (push_constant, std430) uniform PushConstants {\n"
			<< "	uint valueIndex;\n"
			<< "} pc;\n"
			<< "\n"
			<< "layout (set=0, binding=0, std430) buffer OutputBlock {\n"
			<< "	uint value[];\n"
			<< "} ob;\n"
			<< "\n"
			<< "void main ()\n"
			<< "{\n"
			<< "	ob.value[pc.valueIndex] = 1u;\n"
			<< "}\n"
			;

		programCollection.glslSources.add("comp") << glu::ComputeSource(comp.str());
	}

	if (de::contains(begin(m_params.states), end(m_params.states), VK_DYNAMIC_STATE_VERTEX_INPUT_BINDING_STRIDE_EXT))
	{
		// Passthrough vertex shader for stand-in graphics pipeline.
		std::ostringstream vert;
		vert
			<< "#version 450\n"
			<< "layout (location=0) in vec4 inVertex;\n"
			<< "void main() {\n"
			<< "    gl_Position = inVertex;\n"
			<< "}\n"
			;

		programCollection.glslSources.add("vert") << glu::VertexSource(vert.str());
	}
}

vkt::TestInstance* DynamicStateComputeCase::createInstance (Context& context) const
{
	return new DynamicStateComputeInstance(context, m_params);
}

tcu::TestStatus DynamicStateComputeInstance::iterate (void)
{
	if (m_params.operationType == OperType::COMPUTE)
		return iterateCompute();
	else
		return iterateTransfer();
}

void fillBuffer(const DeviceInterface& vkd, VkDevice device, BufferWithMemory& buffer, const std::vector<deUint32> &values)
{
	auto& alloc = buffer.getAllocation();

	deMemcpy(alloc.getHostPtr(), values.data(), de::dataSize(values));
	flushAlloc(vkd, device, alloc);
}

tcu::TestStatus DynamicStateComputeInstance::iterateTransfer (void)
{
	const auto&	vki		= m_context.getInstanceInterface();
	const auto	phyDev	= m_context.getPhysicalDevice();
	const auto&	vkd		= m_context.getDeviceInterface();
	const auto	device	= m_context.getDevice();
	auto&		alloc	= m_context.getDefaultAllocator();
	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
	const auto	queue	= m_context.getUniversalQueue();

	const auto	cmdPool			= makeCommandPool(vkd, device, qIndex);
	const auto	cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto	cmdBuffer		= cmdBufferPtr.get();

	// Prepare two host-visible buffers for a transfer operation, with one element per dynamic state.
	const deUint32		seqStart	= 1611747605u;

	DE_ASSERT(!m_params.states.empty());
	std::vector<deUint32>		srcValues(m_params.states.size());
	const decltype(srcValues)	dstValues(srcValues.size(), 0u);
	std::iota(begin(srcValues), end(srcValues), seqStart);

	const auto			elemSize	= static_cast<VkDeviceSize>(sizeof(decltype(srcValues)::value_type));
	const auto			dataSize	= static_cast<VkDeviceSize>(de::dataSize(srcValues));
	const auto			bufferSize	= de::roundUp(dataSize, getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
	const auto			srcInfo		= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT);
	const auto			dstInfo		= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
	BufferWithMemory	srcBuffer	(vkd, device, alloc, srcInfo, MemoryRequirement::HostVisible);
	BufferWithMemory	dstBuffer	(vkd, device, alloc, dstInfo, MemoryRequirement::HostVisible);

	// Fill source and destination buffer.
	fillBuffer(vkd, device, srcBuffer, srcValues);
	fillBuffer(vkd, device, dstBuffer, dstValues);

	beginCommandBuffer(vkd, cmdBuffer);

	// We need to preserve dynamic state data until the command buffer has run.
	std::vector<de::MovePtr<DynamicStateData>> statesData;

	for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
	{
		// Get extra data needed for using the dynamic state.
		const auto	offset		= elemSize * stateIdx;
		const auto&	state		= m_params.states[stateIdx];
		const auto	stateInfo	= getDynamicStateInfo(state);
		statesData.push_back(getDynamicStateData(m_context, state));

		// Record command if before.
		if (m_params.whenToSet == WhenToSet::BEFORE)
			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());

		// Transfer op (copy one buffer element per dynamic state).
		const VkBufferCopy region = { offset, offset, elemSize };
		vkd.cmdCopyBuffer(cmdBuffer, srcBuffer.get(), dstBuffer.get(), 1u, &region);

		// Record command if after.
		if (m_params.whenToSet == WhenToSet::AFTER)
			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
	}

	const auto barrier = 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, &barrier, 0u, nullptr, 0u, nullptr);

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

	// Invalidate alloc and check destination buffer.
	auto& dstBufferAlloc = dstBuffer.getAllocation();
	invalidateAlloc(vkd, device, dstBufferAlloc);

	decltype(srcValues) results (srcValues.size());
	deMemcpy(results.data(), dstBufferAlloc.getHostPtr(), de::dataSize(srcValues));

	for (size_t valueIdx = 0; valueIdx < srcValues.size(); ++valueIdx)
	{
		const auto& orig	= srcValues[valueIdx];
		const auto& res		= results[valueIdx];

		if (orig != res)
		{
			std::ostringstream msg;
			msg << "Unexpected value found in destination buffer at position " << valueIdx << " (found=" << res << " expected=" << orig << ")";
			TCU_FAIL(msg.str());
		}
	}

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

tcu::TestStatus DynamicStateComputeInstance::iterateCompute (void)
{
	const auto&	vki		= m_context.getInstanceInterface();
	const auto	phyDev	= m_context.getPhysicalDevice();
	const auto&	vkd		= m_context.getDeviceInterface();
	const auto	device	= m_context.getDevice();
	auto&		alloc	= m_context.getDefaultAllocator();
	const auto	qIndex	= m_context.getUniversalQueueFamilyIndex();
	const auto	queue	= m_context.getUniversalQueue();

	const auto	cmdPool			= makeCommandPool(vkd, device, qIndex);
	const auto	cmdBufferPtr	= allocateCommandBuffer(vkd, device, cmdPool.get(), VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto	cmdBuffer		= cmdBufferPtr.get();

	DescriptorSetLayoutBuilder setLayoutBuilder;
	setLayoutBuilder.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT);
	const auto	setLayout		= setLayoutBuilder.build(vkd, device);

	// Push constants.
	const deUint32	pcSize		= static_cast<deUint32>(sizeof(deUint32));
	const auto		pcRange		= makePushConstantRange(VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize);

	// Pipeline.
	const VkPipelineLayoutCreateInfo layoutInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//	VkStructureType					sType;
		nullptr,										//	const void*						pNext;
		0u,												//	VkPipelineLayoutCreateFlags		flags;
		1u,												//	deUint32						setLayoutCount;
		&setLayout.get(),								//	const VkDescriptorSetLayout*	pSetLayouts;
		1u,												//	deUint32						pushConstantRangeCount;
		&pcRange,										//	const VkPushConstantRange*		pPushConstantRanges;
	};
	const auto pipelineLayout = createPipelineLayout(vkd, device, &layoutInfo);

	const auto shaderModule = createShaderModule(vkd, device, m_context.getBinaryCollection().get("comp"), 0u);

	const VkPipelineShaderStageCreateInfo shaderStageInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,	//	VkStructureType						sType;
		nullptr,												//	const void*							pNext;
		0u,														//	VkPipelineShaderStageCreateFlags	flags;
		VK_SHADER_STAGE_COMPUTE_BIT,							//	VkShaderStageFlagBits				stage;
		shaderModule.get(),										//	VkShaderModule						module;
		"main",													//	const char*							pName;
		nullptr,												//	const VkSpecializationInfo*			pSpecializationInfo;
	};

	const VkComputePipelineCreateInfo pipelineInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,	//	VkStructureType					sType;
		nullptr,										//	const void*						pNext;
		0u,												//	VkPipelineCreateFlags			flags;
		shaderStageInfo,								//	VkPipelineShaderStageCreateInfo	stage;
		pipelineLayout.get(),							//	VkPipelineLayout				layout;
		DE_NULL,										//	VkPipeline						basePipelineHandle;
		0,												//	deInt32							basePipelineIndex;
	};
	const auto pipeline = createComputePipeline(vkd, device, DE_NULL, &pipelineInfo);

	DE_ASSERT(!m_params.states.empty());

	// Output buffer with one value per state.
	std::vector<deUint32>	bufferData			(m_params.states.size(), 0u);
	const auto				dataSize			(de::dataSize(bufferData));
	const auto				outputBufferSize	= de::roundUp(static_cast<VkDeviceSize>(dataSize), getPhysicalDeviceProperties(vki, phyDev).limits.nonCoherentAtomSize);
	const auto				bufferCreateInfo	= makeBufferCreateInfo(outputBufferSize, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);

	BufferWithMemory		outputBuffer		(vkd, device, alloc, bufferCreateInfo, MemoryRequirement::HostVisible);
	auto&					outputBufferAlloc	= outputBuffer.getAllocation();
	auto					outputBufferPtr		= outputBufferAlloc.getHostPtr();

	deMemcpy(outputBufferPtr, bufferData.data(), dataSize);
	flushAlloc(vkd, device, outputBufferAlloc);

	// Descriptor set.
	DescriptorPoolBuilder poolBuilder;
	poolBuilder.addType(VK_DESCRIPTOR_TYPE_STORAGE_BUFFER);
	const auto descriptorPool = poolBuilder.build(vkd, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	const auto descriptorSet = makeDescriptorSet(vkd, device, descriptorPool.get(), setLayout.get());

	const auto bufferInfo = makeDescriptorBufferInfo(outputBuffer.get(), 0ull, outputBufferSize);
	DescriptorSetUpdateBuilder updateBuilder;
	updateBuilder.writeSingle(descriptorSet.get(), DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_BUFFER, &bufferInfo);
	updateBuilder.update(vkd, device);

	// Record and submit.
	beginCommandBuffer(vkd, cmdBuffer);

	// We need to preserve dynamic state data until the command buffer has run.
	std::vector<de::MovePtr<DynamicStateData>> statesData;

	for (size_t stateIdx = 0; stateIdx < m_params.states.size(); ++stateIdx)
	{
		// Objects needed to set the dynamic state.
		const auto&	state		= m_params.states[stateIdx];
		const auto	stateInfo	= getDynamicStateInfo(state);
		statesData.push_back(getDynamicStateData(m_context, state));

		if (m_params.whenToSet == WhenToSet::BEFORE)
			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());

		vkd.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipeline.get());
		vkd.cmdBindDescriptorSets(cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, nullptr);
		{
			// Each state will write to a different buffer position.
			const deUint32 pcData = static_cast<deUint32>(stateIdx);
			vkd.cmdPushConstants(cmdBuffer, pipelineLayout.get(), VK_SHADER_STAGE_COMPUTE_BIT, 0u, pcSize, &pcData);
		}
		vkd.cmdDispatch(cmdBuffer, 1u, 1u, 1u);

		if (m_params.whenToSet == WhenToSet::AFTER)
			stateInfo.recorder(&vkd, cmdBuffer, statesData.back().get());
	}

	// Barrier to read buffer contents.
	const auto barrier = makeMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT);
	vkd.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &barrier, 0u, nullptr, 0u, nullptr);

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

	// Read and verify buffer contents.
	invalidateAlloc(vkd, device, outputBufferAlloc);
	deMemcpy(bufferData.data(), outputBufferPtr, dataSize);

	for (size_t idx = 0u; idx < bufferData.size(); ++idx)
	{
		if (bufferData[idx] != 1u)
		{
			std::ostringstream msg;
			msg << "Unexpected value found at buffer position " << idx << ": " << bufferData[idx];
			TCU_FAIL(msg.str());
		}
	}

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

std::string getDynamicStateBriefName (VkDynamicState state)
{
	const auto fullName		= de::toString(state);
	const auto prefixLen	= strlen("VK_DYNAMIC_STATE_");

	return de::toLower(fullName.substr(prefixLen));
}

} // anonymous

tcu::TestCaseGroup* createDynamicStateComputeTests (tcu::TestContext& testCtx)
{
	using GroupPtr = de::MovePtr<tcu::TestCaseGroup>;

	GroupPtr mainGroup(new tcu::TestCaseGroup(testCtx, "compute_transfer", "Dynamic state mixed with compute and transfer operations"));

	const struct
	{
		OperType	operationType;
		const char*	name;
	} operations[] =
	{
		{	OperType::COMPUTE,	"compute"	},
		{	OperType::TRANSFER,	"transfer"	},
	};

	const struct
	{
		WhenToSet	when;
		const char*	name;
	} moments[] =
	{
		{	WhenToSet::BEFORE,	"before"	},
		{	WhenToSet::AFTER,	"after"		},
	};

	// Tests with a single dynamic state.
	{
		GroupPtr singleStateGroup(new tcu::TestCaseGroup(testCtx, "single", "Tests using a single dynamic state"));

		for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
		{
			GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));

			for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
			{
				const auto	state		= dynamicStateList[stateIdx];
				const auto	stateName	= getDynamicStateBriefName(state);

				GroupPtr stateGroup(new tcu::TestCaseGroup(testCtx, stateName.c_str(), ""));

				for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
				{
					const TestParams testParams =
					{
						operations[operIdx].operationType,		//	OperType					operationType;
						moments[momentIdx].when,				//	WhenToSet					whenToSet;
						std::vector<VkDynamicState>(1, state),	//	std::vector<VkDynamicState>	state;
					};

					stateGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
				}

				operationGroup->addChild(stateGroup.release());
			}

			singleStateGroup->addChild(operationGroup.release());
		}

		mainGroup->addChild(singleStateGroup.release());
	}

	// A few tests with several dynamic states.
	{
		GroupPtr multiStateGroup(new tcu::TestCaseGroup(testCtx, "multi", "Tests using multiple dynamic states"));

		for (int operIdx = 0; operIdx < DE_LENGTH_OF_ARRAY(operations); ++operIdx)
		{
			GroupPtr operationGroup(new tcu::TestCaseGroup(testCtx, operations[operIdx].name, ""));

			for (int momentIdx = 0; momentIdx < DE_LENGTH_OF_ARRAY(moments); ++momentIdx)
			{
				TestParams testParams =
				{
					operations[operIdx].operationType,	//	OperType					operationType;
					moments[momentIdx].when,			//	WhenToSet					whenToSet;
					std::vector<VkDynamicState>(),		//	std::vector<VkDynamicState>	states;
				};

				// Use the basic states so as not to introduce extra requirements.
				for (int stateIdx = 0; stateIdx < DE_LENGTH_OF_ARRAY(dynamicStateList); ++stateIdx)
				{
					testParams.states.push_back(dynamicStateList[stateIdx]);
					if (dynamicStateList[stateIdx] == VK_DYNAMIC_STATE_STENCIL_REFERENCE)
						break;
				}

				operationGroup->addChild(new DynamicStateComputeCase(testCtx, moments[momentIdx].name, "", testParams));
			}

			multiStateGroup->addChild(operationGroup.release());
		}

		mainGroup->addChild(multiStateGroup.release());
	}

	return mainGroup.release();
}

} // DynamicState
} // vkt
