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

#include "vktFragmentOperationsTransientAttachmentTests.hpp"
#include "vktTestCaseUtil.hpp"
#include "vktTestGroupUtil.hpp"
#include "vktFragmentOperationsMakeUtil.hpp"

#include "vkDefs.hpp"
#include "vkBuilderUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkBarrierUtil.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTestLog.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVector.hpp"

#include "deUniquePtr.hpp"

namespace vkt
{
namespace FragmentOperations
{
using namespace vk;
using de::UniquePtr;

namespace
{

enum class TestMode
{
	MODE_INVALID	= 1u << 0,
	MODE_COLOR		= 1u << 1,
	MODE_DEPTH		= 1u << 2,
	MODE_STENCIL	= 1u << 3
};

const char* memoryPropertyFlagBitToString(VkMemoryPropertyFlags flagBit)
{
	switch (flagBit)
	{
	case VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT:
		return "VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT";

	case VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT:
		return "VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT";

	case VK_MEMORY_PROPERTY_HOST_COHERENT_BIT:
		return "VK_MEMORY_PROPERTY_HOST_COHERENT_BIT";

	case VK_MEMORY_PROPERTY_HOST_CACHED_BIT:
		return "VK_MEMORY_PROPERTY_HOST_CACHED_BIT";

	case VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT:
		return "VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT";

	case VK_MEMORY_PROPERTY_PROTECTED_BIT:
		return "VK_MEMORY_PROPERTY_PROTECTED_BIT";

	case VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD:
		return "VK_MEMORY_PROPERTY_DEVICE_COHERENT_BIT_AMD";

	case VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD:
		return "VK_MEMORY_PROPERTY_DEVICE_UNCACHED_BIT_AMD";

	case VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV:
		return "VK_MEMORY_PROPERTY_RDMA_CAPABLE_BIT_NV";

	default:
		TCU_THROW(InternalError, "Unknown memory property flag bit");
	}
};

VkFormat getSupportedStencilFormat(const VkPhysicalDevice physDevice, const InstanceInterface& instanceInterface)
{
	static const VkFormat stencilFormats[] =
	{
		VK_FORMAT_D16_UNORM_S8_UINT,
		VK_FORMAT_D24_UNORM_S8_UINT,
		VK_FORMAT_D32_SFLOAT_S8_UINT,
	};

	for (const auto& sFormat : stencilFormats)
	{
		VkFormatProperties formatProps;
		instanceInterface.getPhysicalDeviceFormatProperties(physDevice, sFormat, &formatProps);

		if ((formatProps.optimalTilingFeatures & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT) != 0)
		{
			return sFormat;
		};
	}

	return VK_FORMAT_UNDEFINED;
}

std::vector<deUint32> getMemoryTypeIndices(VkMemoryPropertyFlags propertyFlag, const VkPhysicalDeviceMemoryProperties& pMemoryProperties)
{
	std::vector<deUint32> indices;
	for (deUint32 typeIndex = 0u; typeIndex < pMemoryProperties.memoryTypeCount; ++typeIndex)
	{
		if ((pMemoryProperties.memoryTypes[typeIndex].propertyFlags & propertyFlag) == propertyFlag)
			indices.push_back(typeIndex);
	}
	return indices;
}

VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const tcu::IVec2& size, VkImageUsageFlags usage)
{
	const VkImageCreateInfo imageParams =
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
		DE_NULL,								// const void*				pNext;
		(VkImageCreateFlags)0,					// VkImageCreateFlags		flags;
		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
		format,									// VkFormat					format;
		makeExtent3D(size.x(), size.y(), 1),	// VkExtent3D				extent;
		1u,										// deUint32					mipLevels;
		1u,										// deUint32					arrayLayers;
		VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
		usage,									// VkImageUsageFlags		usage;
		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
		0u,										// deUint32					queueFamilyIndexCount;
		DE_NULL,								// const deUint32*			pQueueFamilyIndices;
		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
	};
	return imageParams;
}

VkAttachmentDescription makeAttachment (
	 const VkFormat				format,
	 const VkAttachmentLoadOp	loadOp,
	 const VkAttachmentStoreOp	storeOp,
	 const VkImageLayout		initialLayout,
	 const VkImageLayout		finalLayout)
{
	const tcu::TextureFormat		tcuFormat		= mapVkFormat(format);
	const bool						hasStencil		= (tcuFormat.order == tcu::TextureFormat::DS
													|| tcuFormat.order == tcu::TextureFormat::S);

	const VkAttachmentDescription	attachmentDesc	=
	{
		VkAttachmentDescriptionFlags(0),							// VkAttachmentDescriptionFlags	flags;
		format,														// VkFormat						format;
		VK_SAMPLE_COUNT_1_BIT,										// VkSampleCountFlagBits		samples;
		loadOp,														// VkAttachmentLoadOp			loadOp;
		storeOp,													// VkAttachmentStoreOp			storeOp;
		hasStencil ? loadOp		: VK_ATTACHMENT_LOAD_OP_DONT_CARE,	// VkAttachmentLoadOp			stencilLoadOp;
		hasStencil ? storeOp	: VK_ATTACHMENT_STORE_OP_DONT_CARE,	// VkAttachmentStoreOp			stencilStoreOp;
		initialLayout,												// VkImageLayout				initialLayout;
		finalLayout													// VkImageLayout				finalLayout;
	};

	return attachmentDesc;
}

Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk, const VkDevice device, const std::vector<VkAttachmentDescription> attachmentDescriptions, const bool hasInputAttachment)
{
	const tcu::TextureFormat					tcuFormat				= mapVkFormat(attachmentDescriptions[0].format);
	const bool									hasDepthStencil			= (tcuFormat.order == tcu::TextureFormat::DS
																		|| tcuFormat.order == tcu::TextureFormat::S
																		|| tcuFormat.order == tcu::TextureFormat::D);

	std::vector< VkAttachmentReference>			testReferences;
	const deUint32								maxAttachmentIndex		= deUint32(attachmentDescriptions.size()) - 1u;

	for (deUint32 ref = 0; ref < attachmentDescriptions.size(); ref++)
	{
		testReferences.push_back({ ref, attachmentDescriptions[ref].finalLayout });
	}

	const VkSubpassDescription					subpassDescription		=
	{
		(VkSubpassDescriptionFlags)0,															// VkSubpassDescriptionFlags		flags
		VK_PIPELINE_BIND_POINT_GRAPHICS,														// VkPipelineBindPoint				pipelineBindPoint
		hasInputAttachment ? 1u :0u,															// deUint32							inputAttachmentCount
		hasInputAttachment ? &testReferences[0] : DE_NULL,										// const VkAttachmentReference*		pInputAttachments
		!hasDepthStencil || hasInputAttachment ? 1u : 0u,										// deUint32							colorAttachmentCount
		!hasDepthStencil || hasInputAttachment ? &testReferences[maxAttachmentIndex] : DE_NULL,	// const VkAttachmentReference*		pColorAttachments
		DE_NULL,																				// const VkAttachmentReference*		pResolveAttachments
		hasDepthStencil && !hasInputAttachment ? &testReferences[0] : DE_NULL,					// const VkAttachmentReference*		pDepthStencilAttachment
		0u,																						// deUint32							preserveAttachmentCount
		DE_NULL																					// const deUint32*					pPreserveAttachments
	};

	const VkRenderPassCreateInfo				renderPassInfo			=
	{
		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
		DE_NULL,									// const void*						pNext
		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
		deUint32(attachmentDescriptions.size()),	// deUint32							attachmentCount
		attachmentDescriptions.data(),				// const VkAttachmentDescription*	pAttachments
		1u,											// deUint32							subpassCount
		&subpassDescription,						// const VkSubpassDescription*		pSubpasses
		0u,											// deUint32							dependencyCount
		DE_NULL																		// const VkSubpassDependency*		pDependencies
	};

	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
}

class TransientAttachmentTest : public TestCase
{
public:
						TransientAttachmentTest	(tcu::TestContext&				testCtx,
												 const std::string				name,
												 const TestMode					testMode,
												 const VkMemoryPropertyFlags	flags,
												 const tcu::IVec2				renderSize);

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

private:
	const TestMode					m_testMode;
	const VkMemoryPropertyFlags		m_flags;
	const tcu::IVec2				m_renderSize;
};

TransientAttachmentTest::TransientAttachmentTest (
	tcu::TestContext&			testCtx,
	const std::string			name,
	const TestMode				testMode,
	const VkMemoryPropertyFlags	flags,
	const tcu::IVec2			renderSize)
	: TestCase		(testCtx, name, "")
	, m_testMode	(testMode)
	, m_flags		(flags)
	, m_renderSize	(renderSize)
{
}

void TransientAttachmentTest::initPrograms (SourceCollections& programCollection) const
{
	// Vertex shader
	{
		std::ostringstream src;

		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(location = 0) in vec4 position;\n"
			<< "\n"
			<< "out gl_PerVertex\n"
			<< "{\n"
			<< "   vec4 gl_Position;\n"
			<< "};\n"
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "    gl_Position = position;\n"
			<< "}\n";

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

	// Fragment shader
	{
		std::ostringstream src;

		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
			<< "\n"
			<< "layout(input_attachment_index = 0, binding = 0) uniform "	<< (m_testMode == TestMode::MODE_STENCIL	? "usubpassInput " : "subpassInput ") << "inputValue;\n"
			<< "\n"
			<< "layout(location = 0) out vec4 fragColor;\n"
			<< "\n"
			<< "void main (void)\n"
			<< "{\n"
			<< "	fragColor = " << (m_testMode == TestMode::MODE_COLOR					? "subpassLoad(inputValue);\n"
													: m_testMode == TestMode::MODE_DEPTH	? "vec4(subpassLoad(inputValue).r, 0.0, 0.0, 1.0);\n"
													: /*			TestMode::MODE_STENCIL	*/"vec4(0.0, 0.0, float(subpassLoad(inputValue).r) / 256.0, 1.0);\n")
			<< "}\n";

		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
	}
}

void TransientAttachmentTest::checkSupport (Context& context) const
{
	const InstanceInterface&				vki					= context.getInstanceInterface();
	const VkPhysicalDevice					physicalDevice		= context.getPhysicalDevice();
	VkImageFormatProperties					formatProperties;
	const VkPhysicalDeviceMemoryProperties	pMemoryProperties	= getPhysicalDeviceMemoryProperties(vki,physicalDevice);
	const std::vector<deUint32>				memoryTypeIndices	= getMemoryTypeIndices(m_flags, pMemoryProperties);

	const VkFormat							testFormat			= m_testMode == TestMode::MODE_DEPTH
																? VK_FORMAT_D16_UNORM
																: m_testMode == TestMode::MODE_STENCIL
																? getSupportedStencilFormat(context.getPhysicalDevice(), context.getInstanceInterface())
																: VK_FORMAT_R8G8B8A8_UNORM;

	if (memoryTypeIndices.empty())
	{
		TCU_THROW(NotSupportedError, std::string(memoryPropertyFlagBitToString(m_flags)) + " is not supported by any memory type");
	}

	vki.getPhysicalDeviceImageFormatProperties	(physicalDevice, testFormat,
												 VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL,
												 (m_testMode == TestMode::MODE_DEPTH || m_testMode == TestMode::MODE_STENCIL)
												? VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT	| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT
												: VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT			| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT,
												 0u, &formatProperties);

	if (formatProperties.sampleCounts == 0 || testFormat == VK_FORMAT_UNDEFINED)
		TCU_THROW(NotSupportedError, de::toString(testFormat) + " not supported");
}

class TransientAttachmentTestInstance : public TestInstance
{
public:
					TransientAttachmentTestInstance	(Context&						context,
													 const TestMode					testMode,
													 const VkMemoryPropertyFlags	flags,
													 const tcu::IVec2				renderSize);

	tcu::TestStatus	iterate							(void);

private:
	const TestMode				m_testMode;
	const tcu::IVec2			m_renderSize;
	const VkImageAspectFlags	m_aspectFlags;
	const VkImageUsageFlags		m_usageFlags;
	const VkFormat				m_testFormat;
	const vk::MemoryRequirement	m_memReq;
};

TransientAttachmentTestInstance::TransientAttachmentTestInstance (Context& context, const TestMode testMode, const VkMemoryPropertyFlags flags, const tcu::IVec2 renderSize)
	: TestInstance	(context)
	, m_testMode	(testMode)
	, m_renderSize	(renderSize)
	, m_aspectFlags	(	testMode	==	TestMode::MODE_DEPTH			?	VkImageAspectFlagBits::VK_IMAGE_ASPECT_DEPTH_BIT
					:	testMode	==	TestMode::MODE_STENCIL			?	VkImageAspectFlagBits::VK_IMAGE_ASPECT_STENCIL_BIT
					:														VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT)
	, m_usageFlags	(	testMode	==	TestMode::MODE_COLOR			?	VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT			| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT
					:														VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT	| VK_IMAGE_USAGE_TRANSIENT_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT)
	, m_testFormat	(	testMode	==	TestMode::MODE_DEPTH			?	VK_FORMAT_D16_UNORM
					:	testMode	==	TestMode::MODE_STENCIL			?	getSupportedStencilFormat(m_context.getPhysicalDevice(), m_context.getInstanceInterface())
					:														VK_FORMAT_R8G8B8A8_UNORM)
	, m_memReq		(flags & VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT
																		?	MemoryRequirement::LazilyAllocated
																		:	MemoryRequirement::Local)
{
	DE_ASSERT(m_testMode != TestMode::MODE_INVALID);
}

tcu::TestStatus	TransientAttachmentTestInstance::iterate (void)
{
	const DeviceInterface&				vk							= m_context.getDeviceInterface();
	const VkDevice						device						= m_context.getDevice();
	const VkQueue						queue						= m_context.getUniversalQueue();
	const deUint32						queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
	Allocator&							allocator					= m_context.getDefaultAllocator();
	const VkImageSubresourceRange		testSubresourceRange		= makeImageSubresourceRange(m_aspectFlags, 0u, 1u, 0u, 1u);
	const VkFormat						outputFormat				= VK_FORMAT_R8G8B8A8_UNORM;
	const VkImageAspectFlags			outputAspectFlags			= VkImageAspectFlagBits::VK_IMAGE_ASPECT_COLOR_BIT;
	const VkImageUsageFlags				outputUsageFlags			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;

	// Test attachment
	const Unique<VkImage>				inputImage					(makeImage(vk, device, makeImageCreateInfo(m_testFormat, m_renderSize, m_usageFlags)));
	const UniquePtr<Allocation>			inputImageAllocator			(bindImage(vk, device, allocator, *inputImage, m_memReq));
	const Unique<VkImageView>			inputImageView				(makeImageView(vk, device, *inputImage, VK_IMAGE_VIEW_TYPE_2D, m_testFormat, testSubresourceRange));
	const VkImageView					firstAttachmentImages[]		= { *inputImageView };

	const VkImageSubresourceRange		outputSubresourceRange		= makeImageSubresourceRange(outputAspectFlags, 0u, 1u, 0u, 1u);
	const Unique<VkImage>				outputImage					(makeImage(vk, device, makeImageCreateInfo(outputFormat, m_renderSize, outputUsageFlags)));
	const UniquePtr<Allocation>			outputImageAllocator		(bindImage(vk, device, allocator, *outputImage, MemoryRequirement::Local));
	const Unique<VkImageView>			outputImageView				(makeImageView(vk, device, *outputImage, VK_IMAGE_VIEW_TYPE_2D, outputFormat, outputSubresourceRange));
	const VkImageView					secondAttachmentImages[]	= { *inputImageView, *outputImageView };

	const VkDeviceSize					resultBufferSizeBytes		= tcu::getPixelSize(mapVkFormat(outputFormat)) * m_renderSize.x() * m_renderSize.y();
	const Unique<VkBuffer>				resultBuffer				(makeBuffer(vk, device, resultBufferSizeBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
	const UniquePtr<Allocation>			resultBufferAlloc			(bindBuffer(vk, device, allocator, *resultBuffer, MemoryRequirement::HostVisible));

	// Main vertex buffer
	const deUint32						numVertices					= 6;
	const VkDeviceSize					vertexBufferSizeBytes		= 256;
	const Unique<VkBuffer>				vertexBuffer				(makeBuffer(vk, device, vertexBufferSizeBytes, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT));
	const UniquePtr<Allocation>			vertexBufferAlloc			(bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));

	{
		tcu::Vec4* const pVertices = reinterpret_cast<tcu::Vec4*>(vertexBufferAlloc->getHostPtr());

		pVertices[0]	= tcu::Vec4( 1.0f, -1.0f, 0.0f, 1.0f);
		pVertices[1]	= tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f);
		pVertices[2]	= tcu::Vec4(-1.0f,  1.0f, 0.0f, 1.0f);
		pVertices[3]	= tcu::Vec4(-1.0f,  1.0f, 1.0f, 1.0f);
		pVertices[4]	= tcu::Vec4( 1.0f,  1.0f, 1.0f, 1.0f);
		pVertices[5]	= tcu::Vec4( 1.0f, -1.0f, 1.0f, 1.0f);

		flushAlloc(vk, device, *vertexBufferAlloc);
	}

	// Shader modules
	const Unique<VkShaderModule>		vertexModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
	const Unique<VkShaderModule>		fragmentModule				(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u));

	// Descriptor pool and descriptor set
	DescriptorPoolBuilder				poolBuilder;
	{
		poolBuilder.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1u);
	}

	const auto							descriptorPool				= poolBuilder.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	DescriptorSetLayoutBuilder			layoutBuilderAttachments;
	{
		layoutBuilderAttachments.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT);
	}

	const auto							inputAttachmentsSetLayout	= layoutBuilderAttachments.build(vk, device);
	const auto							descriptorSetAttachments	= makeDescriptorSet(vk, device, descriptorPool.get(), inputAttachmentsSetLayout.get());
	const std::vector<VkDescriptorSet>	descriptorSets				= { descriptorSetAttachments.get() };

	const VkDescriptorImageInfo			imageInfo					=
	{
		DE_NULL,									// VkSampler		sampler;
		*inputImageView,							// VkImageView		imageView;
		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
	};

	DescriptorSetUpdateBuilder			updater;
	{
		updater.writeSingle(descriptorSetAttachments.get(), DescriptorSetUpdateBuilder::Location::binding(static_cast<deUint32>(0)), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &imageInfo);
		updater.update(vk, device);
	}

	const bool							isDepthStencil				= isDepthStencilFormat(m_testFormat);
	VkImageLayout						inputLayout					= isDepthStencil
																	? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL
																	: VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;

	// Renderpasses
	VkAttachmentDescription				clearPassAttachment			= makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_CLEAR,		VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, inputLayout);
	VkAttachmentDescription				inputPassAttachment			= makeAttachment(m_testFormat, VK_ATTACHMENT_LOAD_OP_LOAD,		VK_ATTACHMENT_STORE_OP_STORE, inputLayout, VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);
	VkAttachmentDescription				outputPassAttachment		= makeAttachment(outputFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE,	VK_ATTACHMENT_STORE_OP_STORE, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL);

	const Unique<VkRenderPass>			renderPassOne				(makeRenderPass(vk, device, { clearPassAttachment }, false));
	const Unique<VkRenderPass>			renderPassTwo				(makeRenderPass(vk, device, { inputPassAttachment, outputPassAttachment }, true));

	const Unique<VkFramebuffer>			framebufferOne				(makeFramebuffer(vk, device, *renderPassOne, 1, firstAttachmentImages, m_renderSize.x(), m_renderSize.y()));
	const Unique<VkFramebuffer>			framebufferTwo				(makeFramebuffer(vk, device, *renderPassTwo, 2, secondAttachmentImages, m_renderSize.x(), m_renderSize.y()));

	// Pipeline
	const std::vector<VkViewport>		viewports					(1, makeViewport(m_renderSize));
	const std::vector<VkRect2D>			scissors					(1, makeRect2D(m_renderSize));
	const Unique<VkPipelineLayout>		pipelineLayout				(makePipelineLayout(vk, device, *inputAttachmentsSetLayout));
	const Unique<VkPipeline>			pipeline					(vk::makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
																							  device,								// const VkDevice								device
																							  *pipelineLayout,						// const VkPipelineLayout						pipelineLayout
																							  *vertexModule,						// const VkShaderModule							vertexShaderModule
																							  DE_NULL,								// const VkShaderModule							essellationControlModule
																							  DE_NULL,								// const VkShaderModule							tessellationEvalModule
																							  DE_NULL,								// const VkShaderModule							geometryShaderModule
																							  *fragmentModule,						// const VkShaderModule							fragmentShaderModule
																							  *renderPassTwo,						// const VkRenderPass							renderPass
																							  viewports,							// const std::vector<VkViewport>&				viewports
																							  scissors,								// const std::vector<VkRect2D>&					scissors
																							  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
																							  0u,									// const deUint32								subpass
																							  0u));									// const VkPipelineDepthStencilStateCreateInfo*	depthStencilStateCreateInfo

	// Command buffer
	const Unique<VkCommandPool>			cmdPool						(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
	const Unique<VkCommandBuffer>		cmdBuffer					(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	{
		const VkDeviceSize	vertexBufferOffset	= 0ull;
		VkClearValue		clearValue;

		if		(m_testMode == TestMode::MODE_COLOR)	clearValue.color				= { { 1.0f, 1.0f, 0.0f, 1.0f } };
		else if	(m_testMode == TestMode::MODE_DEPTH)	clearValue.depthStencil.depth	= 0.5f;
		else if (m_testMode == TestMode::MODE_STENCIL)	clearValue.depthStencil			= { 0.0f, 128u };

		const VkRect2D		renderArea			=
		{
			makeOffset2D(0, 0),
			makeExtent2D(m_renderSize.x(), m_renderSize.y()),
		};

		beginCommandBuffer(vk, *cmdBuffer);

		// Clear attachment
		beginRenderPass(vk, *cmdBuffer, *renderPassOne, *framebufferOne, renderArea, clearValue);
		endRenderPass(vk, *cmdBuffer);

		// Synchronize clear and read operations.
		{
			const auto srcAccess	= isDepthStencil ? VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT;
			const auto dstAccess	= VK_ACCESS_INPUT_ATTACHMENT_READ_BIT;
			const auto srcStage		= isDepthStencil ? (VK_PIPELINE_STAGE_EARLY_FRAGMENT_TESTS_BIT | VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT) : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;
			const auto dstStage		= VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT;
			const auto clearToLoad	= makeMemoryBarrier(srcAccess, dstAccess);
			cmdPipelineMemoryBarrier(vk, *cmdBuffer, srcStage, dstStage, &clearToLoad);
		}

		// Draw with input attachment
		beginRenderPass(vk, *cmdBuffer, *renderPassTwo, *framebufferTwo, renderArea);
		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
		vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, static_cast<deUint32>(descriptorSets.size()), descriptorSets.data(), 0u, nullptr);
		vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
		endRenderPass(vk, *cmdBuffer);

		copyImageToBuffer(vk, *cmdBuffer, *outputImage, *resultBuffer, m_renderSize, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, outputPassAttachment.finalLayout, 1u, outputAspectFlags, outputAspectFlags);

		endCommandBuffer(vk, *cmdBuffer);
		submitCommandsAndWait(vk, device, queue, *cmdBuffer);
	}

	// Verify results
	{
		invalidateAlloc(vk, device, *resultBufferAlloc);

		const tcu::ConstPixelBufferAccess	imagePixelAccess(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y(), 1, resultBufferAlloc->getHostPtr());
		tcu::TextureLevel					referenceImage(mapVkFormat(outputFormat), m_renderSize.x(), m_renderSize.y());
		const tcu::Vec4						clearColor	= m_testMode == TestMode::MODE_COLOR
														? tcu::Vec4(1.0f, 1.0f, 0.0f, 1.0f)
														: m_testMode == TestMode::MODE_DEPTH ? tcu::Vec4(0.5f, 0.0f, 0.0f, 1.0f)
														: tcu::Vec4(0.0f, 0.0f, 0.5f, 1.0f);

		tcu::clear(referenceImage.getAccess(), clearColor);

		if (!tcu::floatThresholdCompare(m_context.getTestContext().getLog(), "Compare", "Result comparison", referenceImage.getAccess(), imagePixelAccess, tcu::Vec4(0.02f), tcu::COMPARE_LOG_RESULT))
		{
			return tcu::TestStatus::fail("Rendered color image is not correct");
		}
	}

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

TestInstance* TransientAttachmentTest::createInstance (Context& context) const
{
	return new TransientAttachmentTestInstance(context, m_testMode, m_flags, m_renderSize);
}

} // anonymous

tcu::TestCaseGroup* createTransientAttachmentTests(tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> testGroup(new tcu::TestCaseGroup(testCtx, "transient_attachment_bit", "image usage transient attachment bit load and store op test"));

	{
		static const struct
		{
			std::string					caseName;
			TestMode					testMode;
			const VkMemoryPropertyFlags	flags;
		} cases[] =
		{
			{ "color_load_store_op_test_lazy_bit",		TestMode::MODE_COLOR	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
			{ "depth_load_store_op_test_lazy_bit",		TestMode::MODE_DEPTH	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
			{ "stencil_load_store_op_test_lazy_bit",	TestMode::MODE_STENCIL	,	VK_MEMORY_PROPERTY_LAZILY_ALLOCATED_BIT},
			{ "color_load_store_op_test_local_bit",		TestMode::MODE_COLOR	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
			{ "depth_load_store_op_test_local_bit",		TestMode::MODE_DEPTH	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT},
			{ "stencil_load_store_op_test_local_bit",	TestMode::MODE_STENCIL	,	VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT}
		};

		for (const auto& testCase: cases)
		{
			testGroup->addChild(new TransientAttachmentTest(testCtx, testCase.caseName, testCase.testMode, testCase.flags, tcu::IVec2(32, 32)));
		}
	}

	return testGroup.release();
}

} // FragmentOperations
} // vkt
