/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2016 The Khronos Group Inc.
 * Copyright (c) 2016 The Android Open Source Project
 *
 * 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 Memory qualifiers tests
 *//*--------------------------------------------------------------------*/

#include "vktImageQualifiersTests.hpp"
#include "vktImageLoadStoreTests.hpp"
#include "vktImageTestsUtil.hpp"

#include "vkDefs.hpp"
#include "vkImageUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vktTestCase.hpp"
#include "vktTestCaseUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkMemUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

#include "deDefs.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"

#include "tcuImageCompare.hpp"
#include "tcuTexture.hpp"
#include "tcuTextureUtil.hpp"
#include "tcuVectorType.hpp"

using namespace vk;

namespace vkt
{
namespace image
{
namespace
{

static const tcu::UVec3		g_localWorkGroupSizeBase	= tcu::UVec3(8, 8, 2);
static const deInt32		g_ShaderReadOffsetsX[4]		= { 1, 4, 7, 10 };
static const deInt32		g_ShaderReadOffsetsY[4]		= { 2, 5, 8, 11 };
static const deInt32		g_ShaderReadOffsetsZ[4]		= { 3, 6, 9, 12 };
static const char* const	g_ShaderReadOffsetsXStr		= "int[]( 1, 4, 7, 10 )";
static const char* const	g_ShaderReadOffsetsYStr		= "int[]( 2, 5, 8, 11 )";
static const char* const	g_ShaderReadOffsetsZStr		= "int[]( 3, 6, 9, 12 )";

const tcu::UVec3 getLocalWorkGroupSize (const ImageType imageType, const tcu::UVec3& imageSize)
{
	const tcu::UVec3 computeGridSize	= getShaderGridSize(imageType, imageSize);

	const tcu::UVec3 localWorkGroupSize = tcu::UVec3(de::min(g_localWorkGroupSizeBase.x(), computeGridSize.x()),
													 de::min(g_localWorkGroupSizeBase.y(), computeGridSize.y()),
													 de::min(g_localWorkGroupSizeBase.z(), computeGridSize.z()));
	return localWorkGroupSize;
}

const tcu::UVec3 getNumWorkGroups (const ImageType imageType, const tcu::UVec3& imageSize)
{
	const tcu::UVec3 computeGridSize	= getShaderGridSize(imageType, imageSize);
	const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(imageType, imageSize);

	return computeGridSize / localWorkGroupSize;
}

tcu::ConstPixelBufferAccess getLayerOrSlice (const ImageType					imageType,
											 const tcu::ConstPixelBufferAccess&	access,
											 const deUint32						layer)
{
	switch (imageType)
	{
		case IMAGE_TYPE_1D:
		case IMAGE_TYPE_2D:
		case IMAGE_TYPE_BUFFER:
			DE_ASSERT(layer == 0);
			return access;

		case IMAGE_TYPE_1D_ARRAY:
			return tcu::getSubregion(access, 0, layer, access.getWidth(), 1);

		case IMAGE_TYPE_2D_ARRAY:
		case IMAGE_TYPE_3D:
		case IMAGE_TYPE_CUBE:
		case IMAGE_TYPE_CUBE_ARRAY:
			return tcu::getSubregion(access, 0, 0, layer, access.getWidth(), access.getHeight(), 1);

		default:
			DE_FATAL("Unknown image type");
			return tcu::ConstPixelBufferAccess();
	}
}

bool comparePixelBuffers (tcu::TestContext&						testCtx,
						  const ImageType						imageType,
						  const tcu::UVec3&						imageSize,
						  const tcu::TextureFormat&				format,
						  const tcu::ConstPixelBufferAccess&	reference,
						  const tcu::ConstPixelBufferAccess&	result)
{
	DE_ASSERT(reference.getFormat() == result.getFormat());
	DE_ASSERT(reference.getSize() == result.getSize());

	const bool		 intFormat			= isIntFormat(mapTextureFormat(format)) || isUintFormat(mapTextureFormat(format));
	deUint32		 passedLayers		= 0;

	for (deUint32 layerNdx = 0; layerNdx < getNumLayers(imageType, imageSize); ++layerNdx)
	{
		const std::string comparisonName = "Comparison" + de::toString(layerNdx);

		std::string comparisonDesc = "Image Comparison, ";
		switch (imageType)
		{
			case IMAGE_TYPE_3D:
				comparisonDesc = comparisonDesc + "slice " + de::toString(layerNdx);
				break;

			case IMAGE_TYPE_CUBE:
			case IMAGE_TYPE_CUBE_ARRAY:
				comparisonDesc = comparisonDesc + "face " + de::toString(layerNdx % 6) + ", cube " + de::toString(layerNdx / 6);
				break;

			default:
				comparisonDesc = comparisonDesc + "layer " + de::toString(layerNdx);
				break;
		}

		const tcu::ConstPixelBufferAccess refLayer		= getLayerOrSlice(imageType, reference, layerNdx);
		const tcu::ConstPixelBufferAccess resultLayer	= getLayerOrSlice(imageType, result, layerNdx);

		bool ok = false;
		if (intFormat)
			ok = tcu::intThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::UVec4(0), tcu::COMPARE_LOG_RESULT);
		else
			ok = tcu::floatThresholdCompare(testCtx.getLog(), comparisonName.c_str(), comparisonDesc.c_str(), refLayer, resultLayer, tcu::Vec4(0.01f), tcu::COMPARE_LOG_RESULT);

		if (ok)
			++passedLayers;
	}

	return passedLayers == getNumLayers(imageType, imageSize);
}

const std::string getCoordStr (const ImageType		imageType,
							   const std::string&	x,
							   const std::string&	y,
							   const std::string&	z)
{
	switch (imageType)
	{
		case IMAGE_TYPE_1D:
		case IMAGE_TYPE_BUFFER:
			return x;

		case IMAGE_TYPE_1D_ARRAY:
		case IMAGE_TYPE_2D:
			return "ivec2(" + x + "," + y + ")";

		case IMAGE_TYPE_2D_ARRAY:
		case IMAGE_TYPE_3D:
		case IMAGE_TYPE_CUBE:
		case IMAGE_TYPE_CUBE_ARRAY:
			return "ivec3(" + x + "," + y + "," + z + ")";

		default:
			DE_ASSERT(false);
			return "";
	}
}

class MemoryQualifierTestCase : public vkt::TestCase
{
public:

	enum Qualifier
	{
		QUALIFIER_COHERENT = 0,
		QUALIFIER_VOLATILE,
		QUALIFIER_RESTRICT,
		QUALIFIER_LAST
	};

								MemoryQualifierTestCase		(tcu::TestContext&			testCtx,
															 const std::string&			name,
															 const std::string&			description,
															 const Qualifier			qualifier,
															 const ImageType			imageType,
															 const tcu::UVec3&			imageSize,
															 const tcu::TextureFormat&	format,
															 const glu::GLSLVersion		glslVersion);

	virtual						~MemoryQualifierTestCase	(void) {}

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

protected:

	const Qualifier				m_qualifier;
	const ImageType				m_imageType;
	const tcu::UVec3			m_imageSize;
	const tcu::TextureFormat	m_format;
	const glu::GLSLVersion		m_glslVersion;
};

MemoryQualifierTestCase::MemoryQualifierTestCase (tcu::TestContext&			testCtx,
												  const std::string&		name,
												  const std::string&		description,
												  const Qualifier			qualifier,
												  const ImageType			imageType,
												  const tcu::UVec3&			imageSize,
												  const tcu::TextureFormat&	format,
												  const glu::GLSLVersion	glslVersion)
	: vkt::TestCase(testCtx, name, description)
	, m_qualifier(qualifier)
	, m_imageType(imageType)
	, m_imageSize(imageSize)
	, m_format(format)
	, m_glslVersion(glslVersion)
{
}

void MemoryQualifierTestCase::initPrograms (SourceCollections& programCollection) const
{
	const char* const	versionDecl			= glu::getGLSLVersionDeclaration(m_glslVersion);

	const char* const	qualifierName		= m_qualifier == QUALIFIER_COHERENT ? "coherent"
											: m_qualifier == QUALIFIER_VOLATILE ? "volatile"
											: DE_NULL;

	const bool			uintFormat			= isUintFormat(mapTextureFormat(m_format));
	const bool			intFormat			= isIntFormat(mapTextureFormat(m_format));
	const std::string	colorVecTypeName	= std::string(uintFormat ? "u"	: intFormat ? "i" : "") + "vec4";
	const std::string	colorScalarTypeName = std::string(uintFormat ? "uint" : intFormat ? "int" : "float");
	const std::string	invocationCoord		= getCoordStr(m_imageType, "gx", "gy", "gz");
	const std::string	shaderImageFormat	= getShaderImageFormatQualifier(m_format);
	const std::string	shaderImageType		= getShaderImageType(m_format, m_imageType);

	const tcu::UVec3	localWorkGroupSize	= getLocalWorkGroupSize(m_imageType, m_imageSize);
	const std::string	localSizeX			= de::toString(localWorkGroupSize.x());
	const std::string	localSizeY			= de::toString(localWorkGroupSize.y());
	const std::string	localSizeZ			= de::toString(localWorkGroupSize.z());

	std::ostringstream	programBuffer;

	programBuffer
		<< versionDecl << "\n"
		<< "\n"
		<< "precision highp " << shaderImageType << ";\n"
		<< "\n"
		<< "layout (local_size_x = " << localSizeX << ", local_size_y = " << localSizeY << ", local_size_z = " + localSizeZ << ") in;\n"
		<< "layout (" << shaderImageFormat << ", binding=0) " << qualifierName << " uniform " << shaderImageType << " u_image;\n"
		<< "void main (void)\n"
		<< "{\n"
		<< "	int gx = int(gl_GlobalInvocationID.x);\n"
		<< "	int gy = int(gl_GlobalInvocationID.y);\n"
		<< "	int gz = int(gl_GlobalInvocationID.z);\n"
		<< "	imageStore(u_image, " << invocationCoord << ", " << colorVecTypeName << "(gx^gy^gz));\n"
		<< "\n"
		<< "	memoryBarrier();\n"
		<< "	barrier();\n"
		<< "\n"
		<< "	" << colorScalarTypeName << " sum = " << colorScalarTypeName << "(0);\n"
		<< "	int groupBaseX = gx/" << localSizeX << "*" << localSizeX << ";\n"
		<< "	int groupBaseY = gy/" << localSizeY << "*" << localSizeY << ";\n"
		<< "	int groupBaseZ = gz/" << localSizeZ << "*" << localSizeZ << ";\n"
		<< "	int xOffsets[] = " << g_ShaderReadOffsetsXStr << ";\n"
		<< "	int yOffsets[] = " << g_ShaderReadOffsetsYStr << ";\n"
		<< "	int zOffsets[] = " << g_ShaderReadOffsetsZStr << ";\n"
		<< "	for (int i = 0; i < " << de::toString(DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX)) << "; i++)\n"
		<< "	{\n"
		<< "		int readX = groupBaseX + (gx + xOffsets[i]) % " + localSizeX + ";\n"
		<< "		int readY = groupBaseY + (gy + yOffsets[i]) % " + localSizeY + ";\n"
		<< "		int readZ = groupBaseZ + (gz + zOffsets[i]) % " + localSizeZ + ";\n"
		<< "		sum += imageLoad(u_image, " << getCoordStr(m_imageType, "readX", "readY", "readZ") << ").x;\n"
		<< "	}\n"
		<< "\n"
		<< "	memoryBarrier();\n"
		<< "	barrier();\n"
		<< "\n"
		<< "	imageStore(u_image, " + invocationCoord + ", " + colorVecTypeName + "(sum));\n"
		<< "}\n";

	programCollection.glslSources.add(m_name) << glu::ComputeSource(programBuffer.str());
}

class MemoryQualifierInstanceBase : public vkt::TestInstance
{
public:
									MemoryQualifierInstanceBase		(Context&					context,
																	 const std::string&			name,
																	 const ImageType			imageType,
																	 const tcu::UVec3&			imageSize,
																	 const tcu::TextureFormat&	format);

	virtual							~MemoryQualifierInstanceBase	(void) {};

	virtual tcu::TestStatus			iterate							(void);

	virtual void					prepareResources				(const VkDeviceSize			bufferSizeInBytes) = 0;

	virtual void					prepareDescriptors				(void) = 0;

	virtual void					commandsBeforeCompute			(const VkCommandBuffer		cmdBuffer,
																	 const VkDeviceSize			bufferSizeInBytes) const = 0;

	virtual void					commandsAfterCompute			(const VkCommandBuffer		cmdBuffer,
																	 const VkDeviceSize			bufferSizeInBytes) const = 0;

	virtual void					checkRequirements				(void) const;
protected:

	tcu::TextureLevel				generateReferenceImage			(void) const;

	const std::string				m_name;
	const ImageType					m_imageType;
	const tcu::UVec3				m_imageSize;
	const tcu::TextureFormat		m_format;

	de::MovePtr<Buffer>				m_buffer;
	Move<VkDescriptorPool>			m_descriptorPool;
	Move<VkDescriptorSetLayout>		m_descriptorSetLayout;
	Move<VkDescriptorSet>			m_descriptorSet;
};

MemoryQualifierInstanceBase::MemoryQualifierInstanceBase (Context&					context,
														  const std::string&		name,
														  const ImageType			imageType,
														  const tcu::UVec3&			imageSize,
														  const tcu::TextureFormat&	format)
	: vkt::TestInstance(context)
	, m_name(name)
	, m_imageType(imageType)
	, m_imageSize(imageSize)
	, m_format(format)
{
}

void MemoryQualifierInstanceBase::checkRequirements (void) const
{
	if (m_imageType == IMAGE_TYPE_CUBE_ARRAY && !m_context.getDeviceFeatures().imageCubeArray)
	{
		TCU_THROW(NotSupportedError, "imageCubeArray feature not supported");
	}
}

tcu::TestStatus	MemoryQualifierInstanceBase::iterate (void)
{
	const VkDevice			device				= m_context.getDevice();
	const DeviceInterface&	deviceInterface		= m_context.getDeviceInterface();
	const VkQueue			queue				= m_context.getUniversalQueue();
	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();

	const VkDeviceSize	bufferSizeInBytes = getNumPixels(m_imageType, m_imageSize) * tcu::getPixelSize(m_format);

	checkRequirements();

	// Prepare resources for the test
	prepareResources(bufferSizeInBytes);

	// Prepare descriptor sets
	prepareDescriptors();

	// Create compute shader
	const vk::Unique<VkShaderModule> shaderModule(createShaderModule(deviceInterface, device, m_context.getBinaryCollection().get(m_name), 0u));

	// Create compute pipeline
	const vk::Unique<VkPipelineLayout> pipelineLayout(makePipelineLayout(deviceInterface, device, *m_descriptorSetLayout));
	const vk::Unique<VkPipeline> pipeline(makeComputePipeline(deviceInterface, device, *pipelineLayout, *shaderModule));

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

	// Start recording commands
	beginCommandBuffer(deviceInterface, *cmdBuffer);

	deviceInterface.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
	deviceInterface.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &m_descriptorSet.get(), 0u, DE_NULL);

	commandsBeforeCompute(*cmdBuffer, bufferSizeInBytes);

	const tcu::UVec3 numGroups = getNumWorkGroups(m_imageType, m_imageSize);
	deviceInterface.cmdDispatch(*cmdBuffer, numGroups.x(), numGroups.y(), numGroups.z());

	commandsAfterCompute(*cmdBuffer, bufferSizeInBytes);

	endCommandBuffer(deviceInterface, *cmdBuffer);

	// Submit and wait for completion
	submitCommandsAndWait(deviceInterface, device, queue, *cmdBuffer);

	// Retrieve data from buffer to host memory
	const Allocation& allocation = m_buffer->getAllocation();
	invalidateMappedMemoryRange(deviceInterface, device, allocation.getMemory(), allocation.getOffset(), bufferSizeInBytes);

	const tcu::UVec3 computeGridSize = getShaderGridSize(m_imageType, m_imageSize);
	tcu::ConstPixelBufferAccess resultPixelBuffer(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z(), allocation.getHostPtr());

	// Create a reference image
	tcu::TextureLevel referenceImage = generateReferenceImage();
	tcu::ConstPixelBufferAccess referencePixelBuffer = referenceImage.getAccess();

	// Validate the result
	if (comparePixelBuffers(m_context.getTestContext(), m_imageType, m_imageSize, m_format, referencePixelBuffer, resultPixelBuffer))
		return tcu::TestStatus::pass("Passed");
	else
		return tcu::TestStatus::fail("Image comparison failed");
}

tcu::TextureLevel MemoryQualifierInstanceBase::generateReferenceImage (void) const
{
	// Generate a reference image data using the storage format
	const tcu::UVec3 computeGridSize = getShaderGridSize(m_imageType, m_imageSize);

	tcu::TextureLevel base(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
	tcu::PixelBufferAccess baseAccess = base.getAccess();

	tcu::TextureLevel reference(m_format, computeGridSize.x(), computeGridSize.y(), computeGridSize.z());
	tcu::PixelBufferAccess referenceAccess = reference.getAccess();

	for (deInt32 z = 0; z < baseAccess.getDepth(); ++z)
		for (deInt32 y = 0; y < baseAccess.getHeight(); ++y)
			for (deInt32 x = 0; x < baseAccess.getWidth(); ++x)
			{
				baseAccess.setPixel(tcu::IVec4(x^y^z), x, y, z);
			}

	const tcu::UVec3 localWorkGroupSize = getLocalWorkGroupSize(m_imageType, m_imageSize);

	for (deInt32 z = 0; z < referenceAccess.getDepth(); ++z)
		for (deInt32 y = 0; y < referenceAccess.getHeight(); ++y)
			for (deInt32 x = 0; x < referenceAccess.getWidth(); ++x)
			{
				const deInt32	groupBaseX	= x / localWorkGroupSize.x() * localWorkGroupSize.x();
				const deInt32	groupBaseY	= y / localWorkGroupSize.y() * localWorkGroupSize.y();
				const deInt32	groupBaseZ	= z / localWorkGroupSize.z() * localWorkGroupSize.z();
				deInt32			sum			= 0;

				for (deInt32 i = 0; i < DE_LENGTH_OF_ARRAY(g_ShaderReadOffsetsX); i++)
				{
					sum += baseAccess.getPixelInt(
						groupBaseX + (x + g_ShaderReadOffsetsX[i]) % localWorkGroupSize.x(),
						groupBaseY + (y + g_ShaderReadOffsetsY[i]) % localWorkGroupSize.y(),
						groupBaseZ + (z + g_ShaderReadOffsetsZ[i]) % localWorkGroupSize.z()).x();
				}

				referenceAccess.setPixel(tcu::IVec4(sum), x, y, z);
			}

	return reference;
}

class MemoryQualifierInstanceImage : public MemoryQualifierInstanceBase
{
public:
						MemoryQualifierInstanceImage	(Context&					context,
														 const std::string&			name,
														 const ImageType			imageType,
														 const tcu::UVec3&			imageSize,
														 const tcu::TextureFormat&	format)
							: MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}

	virtual				~MemoryQualifierInstanceImage	(void) {};

	virtual void		prepareResources				(const VkDeviceSize			bufferSizeInBytes);

	virtual void		prepareDescriptors				(void);

	virtual void		commandsBeforeCompute			(const VkCommandBuffer		cmdBuffer,
														 const VkDeviceSize			bufferSizeInBytes) const;

	virtual void		commandsAfterCompute			(const VkCommandBuffer		cmdBuffer,
														 const VkDeviceSize			bufferSizeInBytes) const;
protected:

	de::MovePtr<Image>	m_image;
	Move<VkImageView>	m_imageView;
};

void MemoryQualifierInstanceImage::prepareResources (const VkDeviceSize bufferSizeInBytes)
{
	const VkDevice			device			= m_context.getDevice();
	const DeviceInterface&	deviceInterface = m_context.getDeviceInterface();
	Allocator&				allocator		= m_context.getDefaultAllocator();

	// Create image
	const VkImageCreateInfo imageCreateInfo =
	{
		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
		DE_NULL,														// const void*				pNext;
		m_imageType == IMAGE_TYPE_CUBE ||
		m_imageType	== IMAGE_TYPE_CUBE_ARRAY
		? (VkImageCreateFlags)VK_IMAGE_CREATE_CUBE_COMPATIBLE_BIT : 0u,	// VkImageCreateFlags		flags;
		mapImageType(m_imageType),										// VkImageType				imageType;
		mapTextureFormat(m_format),										// VkFormat					format;
		makeExtent3D(getLayerSize(m_imageType, m_imageSize)),			// VkExtent3D				extent;
		1u,																// deUint32					mipLevels;
		getNumLayers(m_imageType, m_imageSize),							// deUint32					arrayLayers;
		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits	samples;
		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
		VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT,	// VkImageUsageFlags		usage;
		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
		0u,																// deUint32					queueFamilyIndexCount;
		DE_NULL,														// const deUint32*			pQueueFamilyIndices;
		VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout			initialLayout;
	};

	m_image = de::MovePtr<Image>(new Image(deviceInterface, device, allocator, imageCreateInfo, MemoryRequirement::Any));

	// Create imageView
	const VkImageSubresourceRange subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, getNumLayers(m_imageType, m_imageSize));
	m_imageView = makeImageView(deviceInterface, device, m_image->get(), mapImageViewType(m_imageType), mapTextureFormat(m_format), subresourceRange);

	// Create a buffer to store shader output (copied from image data)
	const VkBufferCreateInfo	bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
	m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
}

void MemoryQualifierInstanceImage::prepareDescriptors (void)
{
	const VkDevice			device			= m_context.getDevice();
	const DeviceInterface&	deviceInterface = m_context.getDeviceInterface();

	// Create descriptor pool
	m_descriptorPool =
		DescriptorPoolBuilder()
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE)
		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	// Create descriptor set layout
	m_descriptorSetLayout =
		DescriptorSetLayoutBuilder()
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(deviceInterface, device);

	// Allocate descriptor set
	m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);

	// Set the bindings
	const VkDescriptorImageInfo descriptorImageInfo = makeDescriptorImageInfo(DE_NULL, *m_imageView, VK_IMAGE_LAYOUT_GENERAL);

	DescriptorSetUpdateBuilder()
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
		.update(deviceInterface, device);
}

void MemoryQualifierInstanceImage::commandsBeforeCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
{
	DE_UNREF(bufferSizeInBytes);

	const DeviceInterface&			deviceInterface	 = m_context.getDeviceInterface();
	const VkImageSubresourceRange	subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, getNumLayers(m_imageType, m_imageSize));

	const VkImageMemoryBarrier imageLayoutBarrier
		= makeImageMemoryBarrier(0u,
								 VK_ACCESS_SHADER_READ_BIT,
								 VK_IMAGE_LAYOUT_UNDEFINED,
								 VK_IMAGE_LAYOUT_GENERAL,
								 m_image->get(),
								 subresourceRange);

	deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageLayoutBarrier);
}

void MemoryQualifierInstanceImage::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
{
	const DeviceInterface&			deviceInterface	 = m_context.getDeviceInterface();
	const VkImageSubresourceRange	subresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, getNumLayers(m_imageType, m_imageSize));

	const VkImageMemoryBarrier imagePreCopyBarrier
		= makeImageMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
								 VK_ACCESS_TRANSFER_READ_BIT,
								 VK_IMAGE_LAYOUT_GENERAL,
								 VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
								 m_image->get(),
								 subresourceRange);

	deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imagePreCopyBarrier);

	const VkBufferImageCopy copyParams = makeBufferImageCopy(makeExtent3D(getLayerSize(m_imageType, m_imageSize)), getNumLayers(m_imageType, m_imageSize));
	deviceInterface.cmdCopyImageToBuffer(cmdBuffer, m_image->get(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, m_buffer->get(), 1u, &copyParams);

	const VkBufferMemoryBarrier bufferPostCopyBarrier
		= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT,
								  VK_ACCESS_HOST_READ_BIT,
								  m_buffer->get(),
								  0ull,
								  bufferSizeInBytes);

	deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferPostCopyBarrier, 0u, DE_NULL);
}

class MemoryQualifierInstanceBuffer : public MemoryQualifierInstanceBase
{
public:
						MemoryQualifierInstanceBuffer	(Context&					context,
														 const std::string&			name,
														 const ImageType			imageType,
														 const tcu::UVec3&			imageSize,
														 const tcu::TextureFormat&	format)
							: MemoryQualifierInstanceBase(context, name, imageType, imageSize, format) {}

	virtual				~MemoryQualifierInstanceBuffer	(void) {};

	virtual void		prepareResources				(const VkDeviceSize			bufferSizeInBytes);

	virtual void		prepareDescriptors				(void);

	virtual void		commandsBeforeCompute			(const VkCommandBuffer,
														 const VkDeviceSize) const {}

	virtual void		commandsAfterCompute			(const VkCommandBuffer		cmdBuffer,
														 const VkDeviceSize			bufferSizeInBytes) const;
protected:

	Move<VkBufferView>	m_bufferView;
};

void MemoryQualifierInstanceBuffer::prepareResources (const VkDeviceSize bufferSizeInBytes)
{
	const VkDevice			device			= m_context.getDevice();
	const DeviceInterface&	deviceInterface = m_context.getDeviceInterface();
	Allocator&				allocator		= m_context.getDefaultAllocator();

	// Create a buffer to store shader output
	const VkBufferCreateInfo bufferCreateInfo = makeBufferCreateInfo(bufferSizeInBytes, VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
	m_buffer = de::MovePtr<Buffer>(new Buffer(deviceInterface, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));

	m_bufferView = makeBufferView(deviceInterface, device, m_buffer->get(), mapTextureFormat(m_format), 0ull, bufferSizeInBytes);
}

void MemoryQualifierInstanceBuffer::prepareDescriptors (void)
{
	const VkDevice			device			= m_context.getDevice();
	const DeviceInterface&	deviceInterface = m_context.getDeviceInterface();

	// Create descriptor pool
	m_descriptorPool =
		DescriptorPoolBuilder()
		.addType(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER)
		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	// Create descriptor set layout
	m_descriptorSetLayout =
		DescriptorSetLayoutBuilder()
		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, VK_SHADER_STAGE_COMPUTE_BIT)
		.build(deviceInterface, device);

	// Allocate descriptor set
	m_descriptorSet = makeDescriptorSet(deviceInterface, device, *m_descriptorPool, *m_descriptorSetLayout);

	// Set the bindings
	DescriptorSetUpdateBuilder()
		.writeSingle(*m_descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER, &m_bufferView.get())
		.update(deviceInterface, device);
}

void MemoryQualifierInstanceBuffer::commandsAfterCompute (const VkCommandBuffer cmdBuffer, const VkDeviceSize bufferSizeInBytes) const
{
	const DeviceInterface&	deviceInterface = m_context.getDeviceInterface();

	const VkBufferMemoryBarrier shaderWriteBarrier
		= makeBufferMemoryBarrier(VK_ACCESS_SHADER_WRITE_BIT,
								  VK_ACCESS_HOST_READ_BIT,
								  m_buffer->get(),
								  0ull,
								  bufferSizeInBytes);

	deviceInterface.cmdPipelineBarrier(cmdBuffer, VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &shaderWriteBarrier, 0u, DE_NULL);
}

TestInstance* MemoryQualifierTestCase::createInstance (Context& context) const
{
	if ( m_imageType == IMAGE_TYPE_BUFFER )
		return new MemoryQualifierInstanceBuffer(context, m_name, m_imageType, m_imageSize, m_format);
	else
		return new MemoryQualifierInstanceImage(context, m_name, m_imageType, m_imageSize, m_format);
}

} // anonymous ns

tcu::TestCaseGroup* createImageQualifiersTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> imageQualifiersTests(new tcu::TestCaseGroup(testCtx, "qualifiers", "Coherent, volatile and restrict"));

	struct ImageParams
	{
		ImageParams(const ImageType imageType, const tcu::UVec3& imageSize)
			: m_imageType	(imageType)
			, m_imageSize	(imageSize)
		{
		}
		ImageType	m_imageType;
		tcu::UVec3	m_imageSize;
	};

	static const ImageParams imageParamsArray[] =
	{
		ImageParams(IMAGE_TYPE_1D,			tcu::UVec3(64u, 1u,  1u)),
		ImageParams(IMAGE_TYPE_1D_ARRAY,	tcu::UVec3(64u, 1u,  8u)),
		ImageParams(IMAGE_TYPE_2D,			tcu::UVec3(64u, 64u, 1u)),
		ImageParams(IMAGE_TYPE_2D_ARRAY,	tcu::UVec3(64u, 64u, 8u)),
		ImageParams(IMAGE_TYPE_3D,			tcu::UVec3(64u, 64u, 8u)),
		ImageParams(IMAGE_TYPE_CUBE,		tcu::UVec3(64u, 64u, 1u)),
		ImageParams(IMAGE_TYPE_CUBE_ARRAY,	tcu::UVec3(64u, 64u, 2u)),
		ImageParams(IMAGE_TYPE_BUFFER,		tcu::UVec3(64u, 1u,  1u))
	};

	static const tcu::TextureFormat formats[] =
	{
		tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::FLOAT),
		tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::UNSIGNED_INT32),
		tcu::TextureFormat(tcu::TextureFormat::R, tcu::TextureFormat::SIGNED_INT32),
	};

	for (deUint32 qualifierI = 0; qualifierI < MemoryQualifierTestCase::QUALIFIER_LAST; ++qualifierI)
	{
		const MemoryQualifierTestCase::Qualifier	memoryQualifier		= (MemoryQualifierTestCase::Qualifier)qualifierI;
		const char* const							memoryQualifierName =
			memoryQualifier == MemoryQualifierTestCase::QUALIFIER_COHERENT ? "coherent" :
			memoryQualifier == MemoryQualifierTestCase::QUALIFIER_VOLATILE ? "volatile" :
			memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT ? "restrict" :
			DE_NULL;

		de::MovePtr<tcu::TestCaseGroup> qualifierGroup(new tcu::TestCaseGroup(testCtx, memoryQualifierName, ""));

		for (deInt32 imageTypeNdx = 0; imageTypeNdx < DE_LENGTH_OF_ARRAY(imageParamsArray); imageTypeNdx++)
		{
			const ImageType		imageType = imageParamsArray[imageTypeNdx].m_imageType;
			const tcu::UVec3	imageSize = imageParamsArray[imageTypeNdx].m_imageSize;

			if (memoryQualifier == MemoryQualifierTestCase::QUALIFIER_RESTRICT)
			{
				de::MovePtr<TestCase> restrictCase = createImageQualifierRestrictCase(testCtx, imageType, getImageTypeName(imageType));
				qualifierGroup->addChild(restrictCase.release());
			}
			else
			{
				de::MovePtr<tcu::TestCaseGroup> imageTypeGroup(new tcu::TestCaseGroup(testCtx, getImageTypeName(imageType).c_str(), ""));

				for (deInt32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
				{
					const tcu::TextureFormat&	format		= formats[formatNdx];
					const std::string			formatName	= getShaderImageFormatQualifier(formats[formatNdx]);

					imageTypeGroup->addChild(
						new MemoryQualifierTestCase(testCtx, formatName, "", memoryQualifier, imageType, imageSize, format, glu::GLSL_VERSION_440));
				}

				qualifierGroup->addChild(imageTypeGroup.release());
			}
		}

		imageQualifiersTests->addChild(qualifierGroup.release());
	}

	return imageQualifiersTests.release();
}

} // image
} // vkt
