/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2017 The Khronos Group Inc.
 * Copyright (c) 2017 Samsung Electronics Co., Ltd.
 *
 * 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 Protected memory image access tests
 *//*--------------------------------------------------------------------*/

#include "vktProtectedMemShaderImageAccessTests.hpp"

#include "vktProtectedMemContext.hpp"
#include "vktProtectedMemUtils.hpp"
#include "vktProtectedMemImageValidator.hpp"
#include "vktTestCase.hpp"
#include "vktTestGroupUtil.hpp"

#include "vkPrograms.hpp"
#include "vkTypeUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkObjUtil.hpp"

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

#include "gluTextureTestUtil.hpp"

#include "deRandom.hpp"

namespace vkt
{
namespace ProtectedMem
{

namespace
{

enum
{
	RENDER_WIDTH	= 128,
	RENDER_HEIGHT	= 128,
	IMAGE_WIDTH		= 128,
	IMAGE_HEIGHT	= 128,
};

enum AccessType
{
	ACCESS_TYPE_SAMPLING = 0,
	ACCESS_TYPE_TEXEL_FETCH,
	ACCESS_TYPE_IMAGE_LOAD,
	ACCESS_TYPE_IMAGE_STORE,
	ACCESS_TYPE_IMAGE_ATOMICS,

	ACCESS_TYPE_LAST
};

enum AtomicOperation
{
	ATOMIC_OPERATION_ADD = 0,
	ATOMIC_OPERATION_MIN,
	ATOMIC_OPERATION_MAX,
	ATOMIC_OPERATION_AND,
	ATOMIC_OPERATION_OR,
	ATOMIC_OPERATION_XOR,
	ATOMIC_OPERATION_EXCHANGE,

	ATOMIC_OPERATION_LAST
};

struct Params
{
	glu::ShaderType		shaderType;
	AccessType			accessType;
	vk::VkFormat		imageFormat;
	AtomicOperation		atomicOperation;

	Params (void)
		: shaderType		(glu::SHADERTYPE_LAST)
		, accessType		(ACCESS_TYPE_LAST)
		, imageFormat		(vk::VK_FORMAT_UNDEFINED)
		, atomicOperation	(ATOMIC_OPERATION_LAST)
	{}

	Params (const glu::ShaderType	shaderType_,
			const AccessType		accessType_,
			const vk::VkFormat		imageFormat_,
			const AtomicOperation	atomicOperation_	= ATOMIC_OPERATION_LAST)
		: shaderType		(shaderType_)
		, accessType		(accessType_)
		, imageFormat		(imageFormat_)
		, atomicOperation	(atomicOperation_)
	{}
};

static deUint32 getSeedValue (const Params& params)
{
	return deInt32Hash(params.shaderType) ^ deInt32Hash(params.accessType) ^ deInt32Hash(params.imageFormat) ^ deInt32Hash(params.atomicOperation);
}

static std::string getAtomicOperationCaseName (const AtomicOperation op)
{
	switch (op)
	{
		case ATOMIC_OPERATION_ADD:			return "add";
		case ATOMIC_OPERATION_MIN:			return "min";
		case ATOMIC_OPERATION_MAX:			return "max";
		case ATOMIC_OPERATION_AND:			return "and";
		case ATOMIC_OPERATION_OR:			return "or";
		case ATOMIC_OPERATION_XOR:			return "xor";
		case ATOMIC_OPERATION_EXCHANGE:		return "exchange";
		default:
			DE_FATAL("Impossible");
			return "";
	}
}

static std::string getAtomicOperationShaderFuncName (const AtomicOperation op)
{
	switch (op)
	{
		case ATOMIC_OPERATION_ADD:			return "imageAtomicAdd";
		case ATOMIC_OPERATION_MIN:			return "imageAtomicMin";
		case ATOMIC_OPERATION_MAX:			return "imageAtomicMax";
		case ATOMIC_OPERATION_AND:			return "imageAtomicAnd";
		case ATOMIC_OPERATION_OR:			return "imageAtomicOr";
		case ATOMIC_OPERATION_XOR:			return "imageAtomicXor";
		case ATOMIC_OPERATION_EXCHANGE:		return "imageAtomicExchange";
		default:
			DE_FATAL("Impossible");
			return "";
	}
}

//! Computes the result of an atomic operation where "a" is the data operated on and "b" is the parameter to the atomic function.
static deInt32 computeBinaryAtomicOperationResult (const AtomicOperation op, const deInt32 a, const deInt32 b)
{
	switch (op)
	{
		case ATOMIC_OPERATION_ADD:			return a + b;
		case ATOMIC_OPERATION_MIN:			return de::min(a, b);
		case ATOMIC_OPERATION_MAX:			return de::max(a, b);
		case ATOMIC_OPERATION_AND:			return a & b;
		case ATOMIC_OPERATION_OR:			return a | b;
		case ATOMIC_OPERATION_XOR:			return a ^ b;
		case ATOMIC_OPERATION_EXCHANGE:		return b;
		default:
			DE_FATAL("Impossible");
			return -1;
	}
}

static std::string getShaderImageFormatQualifier (const tcu::TextureFormat& format)
{
	const char* orderPart;
	const char* typePart;

	switch (format.order)
	{
		case tcu::TextureFormat::R:		orderPart = "r";	break;
		case tcu::TextureFormat::RG:	orderPart = "rg";	break;
		case tcu::TextureFormat::RGB:	orderPart = "rgb";	break;
		case tcu::TextureFormat::RGBA:	orderPart = "rgba";	break;

		default:
			DE_FATAL("Impossible");
			orderPart = DE_NULL;
	}

	switch (format.type)
	{
		case tcu::TextureFormat::FLOAT:				typePart = "32f";		break;
		case tcu::TextureFormat::HALF_FLOAT:		typePart = "16f";		break;

		case tcu::TextureFormat::UNSIGNED_INT32:	typePart = "32ui";		break;
		case tcu::TextureFormat::UNSIGNED_INT16:	typePart = "16ui";		break;
		case tcu::TextureFormat::UNSIGNED_INT8:		typePart = "8ui";		break;

		case tcu::TextureFormat::SIGNED_INT32:		typePart = "32i";		break;
		case tcu::TextureFormat::SIGNED_INT16:		typePart = "16i";		break;
		case tcu::TextureFormat::SIGNED_INT8:		typePart = "8i";		break;

		case tcu::TextureFormat::UNORM_INT16:		typePart = "16";		break;
		case tcu::TextureFormat::UNORM_INT8:		typePart = "8";			break;

		case tcu::TextureFormat::SNORM_INT16:		typePart = "16_snorm";	break;
		case tcu::TextureFormat::SNORM_INT8:		typePart = "8_snorm";	break;

		default:
			DE_FATAL("Impossible");
			typePart = DE_NULL;
	}

	return std::string() + orderPart + typePart;
}

static std::string getShaderSamplerOrImageType (const tcu::TextureFormat& format, bool isSampler)
{
	const std::string formatPart = tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_UNSIGNED_INTEGER ? "u" :
								   tcu::getTextureChannelClass(format.type) == tcu::TEXTURECHANNELCLASS_SIGNED_INTEGER   ? "i" : "";

	return formatPart + (isSampler ? "sampler2D" : "image2D");
}

class ImageAccessTestInstance : public ProtectedTestInstance
{
public:
								ImageAccessTestInstance	(Context&				ctx,
														 const ImageValidator&	validator,
														 const Params&			params);
	virtual tcu::TestStatus		iterate					(void);

private:
	de::MovePtr<tcu::Texture2D>	createTestTexture2D		(void);
	void						calculateAtomicRef		(tcu::Texture2D&		texture2D);
	tcu::TestStatus				validateResult			(vk::VkImage			image,
														 vk::VkImageLayout		imageLayout,
														 const tcu::Texture2D&	texture2D,
														 const tcu::Sampler&	refSampler);

	tcu::TestStatus				executeFragmentTest		(void);
	tcu::TestStatus				executeComputeTest		(void);

	const ImageValidator&		m_validator;
	const Params&				m_params;
};

class ImageAccessTestCase : public TestCase
{
public:
								ImageAccessTestCase		(tcu::TestContext&		testCtx,
														 const std::string&		name,
														 const std::string&		description,
														 const Params&			params)
									: TestCase		(testCtx, name, description)
									, m_validator	(params.imageFormat)
									, m_params		(params)
								{
								}

	virtual						~ImageAccessTestCase	(void) {}
	virtual TestInstance*		createInstance			(Context& ctx) const
								{
									return new ImageAccessTestInstance(ctx, m_validator, m_params);
								}
	virtual void				initPrograms			(vk::SourceCollections& programCollection) const;
	virtual void				checkSupport			(Context& context) const
								{
									checkProtectedQueueSupport(context);
								}

private:
	ImageValidator				m_validator;
	Params						m_params;
};

void ImageAccessTestCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const tcu::TextureFormat&	texFormat		= mapVkFormat(m_params.imageFormat);
	const std::string			imageFormat		= getShaderImageFormatQualifier(texFormat);
	const std::string			imageType		= getShaderSamplerOrImageType(texFormat, false);
	const std::string			samplerType		= getShaderSamplerOrImageType(texFormat, true);
	const std::string			colorVecType	= isIntFormat(m_params.imageFormat)		? "ivec4" :
												  isUintFormat(m_params.imageFormat)	? "uvec4" : "vec4";

	m_validator.initPrograms(programCollection);

	if (m_params.shaderType == glu::SHADERTYPE_FRAGMENT)
	{
		{
			// Vertex shader
			const char* vert = "#version 450\n"
							   "layout(location = 0) in mediump vec2 a_position;\n"
							   "layout(location = 1) in mediump vec2 a_texCoord;\n"
							   "layout(location = 0) out mediump vec2 v_texCoord;\n"
							   "\n"
							   "void main() {\n"
							   "    gl_Position = vec4(a_position, 0.0, 1.0);\n"
							   "    v_texCoord = a_texCoord;\n"
							   "}\n";

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

		{
			// Fragment shader
			std::ostringstream frag;
			frag << "#version 450\n"
					"layout(location = 0) in mediump vec2 v_texCoord;\n"
					"layout(location = 0) out highp ${COLOR_VEC_TYPE} o_color;\n";

			switch (m_params.accessType)
			{
				case ACCESS_TYPE_SAMPLING:
				case ACCESS_TYPE_TEXEL_FETCH:
					frag << "layout(set = 0, binding = 0) uniform highp ${SAMPLER_TYPE} u_sampler;\n";
					break;
				case ACCESS_TYPE_IMAGE_LOAD:
					frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_image;\n";
					break;
				case ACCESS_TYPE_IMAGE_STORE:
					frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_imageA;\n";
					frag << "layout(set = 0, binding = 1, ${IMAGE_FORMAT}) writeonly uniform highp ${IMAGE_TYPE} u_imageB;\n";
					break;
				case ACCESS_TYPE_IMAGE_ATOMICS:
					frag << "layout(set = 0, binding = 0, ${IMAGE_FORMAT}) coherent uniform highp ${IMAGE_TYPE} u_image;\n";
					break;
				default:
					DE_FATAL("Impossible");
					break;
			}

			frag << "\n"
					"void main() {\n";

			switch (m_params.accessType)
			{
				case ACCESS_TYPE_SAMPLING:
					frag << "    o_color = texture(u_sampler, v_texCoord);\n";
					break;
				case ACCESS_TYPE_TEXEL_FETCH:
					frag << "    const highp int lod = 0;\n";
					frag << "    o_color = texelFetch(u_sampler, ivec2(v_texCoord), lod);\n";
					break;
				case ACCESS_TYPE_IMAGE_LOAD:
					frag << "    o_color = imageLoad(u_image, ivec2(v_texCoord));\n";
					break;
				case ACCESS_TYPE_IMAGE_STORE:
					frag << "    o_color = imageLoad(u_imageA, ivec2(v_texCoord));\n";
					frag << "    imageStore(u_imageB, ivec2(v_texCoord), o_color);\n";
					break;
				case ACCESS_TYPE_IMAGE_ATOMICS:
					frag << "    int gx = int(v_texCoord.x);\n";
					frag << "    int gy = int(v_texCoord.y);\n";
					frag << "    "
						 << getAtomicOperationShaderFuncName(m_params.atomicOperation)
						 << "(u_image, ivec2(v_texCoord), "
						 << (isUintFormat(m_params.imageFormat) ? "uint" : "int")
						 << "(gx*gx + gy*gy));\n";
					frag << "    o_color = imageLoad(u_image, ivec2(v_texCoord));\n";
					break;
				default:
					DE_FATAL("Impossible");
					break;
			}

			frag << "}\n";

			std::map<std::string, std::string> fragParams;

			fragParams["IMAGE_FORMAT"]		= imageFormat;
			fragParams["IMAGE_TYPE"]		= imageType;
			fragParams["SAMPLER_TYPE"]		= samplerType;
			fragParams["COLOR_VEC_TYPE"]	= colorVecType;

			programCollection.glslSources.add("frag") << glu::FragmentSource(tcu::StringTemplate(frag.str()).specialize(fragParams));
		}
	}
	else if (m_params.shaderType == glu::SHADERTYPE_COMPUTE)
	{
		// Compute shader
		std::ostringstream comp;
		comp << "#version 450\n"
				"layout(local_size_x = 1, local_size_y = 1, local_size_z = 1) in;\n"
				"layout(set = 0, binding = 0, ${IMAGE_FORMAT}) ${RES_MEM_QUALIFIER} uniform highp ${IMAGE_TYPE} u_resultImage;\n";

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
				comp << "layout(set = 0, binding = 1) uniform highp ${SAMPLER_TYPE} u_sampler;\n";
				break;
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
				comp << "layout(set = 0, binding = 1, ${IMAGE_FORMAT}) readonly uniform highp ${IMAGE_TYPE} u_srcImage;\n";
				break;
			case ACCESS_TYPE_IMAGE_ATOMICS:
				break;
			default:
				DE_FATAL("Impossible");
				break;
		}

		comp << "\n"
				"void main() {\n"
				"    int gx = int(gl_GlobalInvocationID.x);\n"
				"    int gy = int(gl_GlobalInvocationID.y);\n";

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
				comp << "    ${COLOR_VEC_TYPE} color = texture(u_sampler, vec2(float(gx)/" << de::toString((int)IMAGE_WIDTH) << ", float(gy)/" << de::toString((int)IMAGE_HEIGHT) << "));\n";
				comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
				break;
			case ACCESS_TYPE_TEXEL_FETCH:
				comp << "    const highp int lod = 0;\n";
				comp << "    ${COLOR_VEC_TYPE} color = texelFetch(u_sampler, ivec2(gx, gy), lod);\n";
				comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
				break;
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
				comp << "    ${COLOR_VEC_TYPE} color = imageLoad(u_srcImage, ivec2(gx, gy));\n";
				comp << "    imageStore(u_resultImage, ivec2(gx, gy), color);\n";
				break;
			case ACCESS_TYPE_IMAGE_ATOMICS:
				comp << "    "
					 << getAtomicOperationShaderFuncName(m_params.atomicOperation)
					 << "(u_resultImage, ivec2(gx, gy), "
					 << (isUintFormat(m_params.imageFormat) ? "uint" : "int")
					 << "(gx*gx + gy*gy));\n";
				break;
			default:
				DE_FATAL("Impossible");
				break;
		}

		comp << "}\n";

		std::map<std::string, std::string> compParams;

		compParams["IMAGE_FORMAT"]		= imageFormat;
		compParams["IMAGE_TYPE"]		= imageType;
		compParams["SAMPLER_TYPE"]		= samplerType;
		compParams["COLOR_VEC_TYPE"]	= colorVecType;
		compParams["RES_MEM_QUALIFIER"]	= m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS ? "coherent" : "writeonly";

		programCollection.glslSources.add("comp") << glu::ComputeSource(tcu::StringTemplate(comp.str()).specialize(compParams));
	}
	else
		DE_FATAL("Impossible");
}

ImageAccessTestInstance::ImageAccessTestInstance (Context&					ctx,
												  const ImageValidator&		validator,
												  const Params&				params)
	: ProtectedTestInstance	(ctx)
	, m_validator			(validator)
	, m_params				(params)
{
}

de::MovePtr<tcu::Texture2D> ImageAccessTestInstance::createTestTexture2D (void)
{
	const tcu::TextureFormat		texFmt		= mapVkFormat(m_params.imageFormat);
	const tcu::TextureFormatInfo	fmtInfo		= tcu::getTextureFormatInfo(texFmt);
	de::MovePtr<tcu::Texture2D>		texture2D	(new tcu::Texture2D(texFmt, IMAGE_WIDTH, IMAGE_HEIGHT));

	// \note generate only the base level
	texture2D->allocLevel(0);

	const tcu::PixelBufferAccess&	level		= texture2D->getLevel(0);

	if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
	{
		// use a smaller range than the format would allow
		const float		cMin	= isIntFormat(m_params.imageFormat) ? -1000.0f : 0.0f;
		const float		cMax	= +1000.0f;

		fillWithRandomColorTiles(level, tcu::Vec4(cMin, 0, 0, 0), tcu::Vec4(cMax, 0, 0, 0), getSeedValue(m_params));
	}
	else
		fillWithRandomColorTiles(level, fmtInfo.valueMin, fmtInfo.valueMax, getSeedValue(m_params));

	return texture2D;
}

tcu::TestStatus ImageAccessTestInstance::iterate (void)
{
	switch (m_params.shaderType)
	{
		case glu::SHADERTYPE_FRAGMENT:	return executeFragmentTest();
		case glu::SHADERTYPE_COMPUTE:	return executeComputeTest();
		default:
			DE_FATAL("Impossible");
			return tcu::TestStatus::fail("");
	}
}

tcu::TestStatus ImageAccessTestInstance::executeComputeTest (void)
{
	ProtectedContext&					ctx					(m_protectedContext);
	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
	const vk::VkDevice					device				= ctx.getDevice();
	const vk::VkQueue					queue				= ctx.getQueue();
	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();

	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));

	de::MovePtr<tcu::Texture2D>			texture2D			= createTestTexture2D();
	const tcu::Sampler					refSampler			= tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
																		   tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);

	vk::Unique<vk::VkShaderModule>		computeShader		(vk::createShaderModule(vk, device, ctx.getBinaryCollection().get("comp"), 0));

	de::MovePtr<vk::ImageWithMemory>	imageSrc;
	de::MovePtr<vk::ImageWithMemory>	imageDst;
	vk::Move<vk::VkSampler>				sampler;
	vk::Move<vk::VkImageView>			imageViewSrc;
	vk::Move<vk::VkImageView>			imageViewDst;

	vk::Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
	vk::Move<vk::VkDescriptorPool>		descriptorPool;
	vk::Move<vk::VkDescriptorSet>		descriptorSet;

	// Create src and dst images
	{
		vk::VkImageUsageFlags imageUsageFlags = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT	|
												vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT	|
												vk::VK_IMAGE_USAGE_SAMPLED_BIT		|
												vk::VK_IMAGE_USAGE_STORAGE_BIT;

		imageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
								 IMAGE_WIDTH, IMAGE_HEIGHT,
								 m_params.imageFormat,
								 imageUsageFlags);

		if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
		{
			imageDst = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
									 IMAGE_WIDTH, IMAGE_HEIGHT,
									 m_params.imageFormat,
									 imageUsageFlags);
		}
	}

	// Upload source image
	{
		de::MovePtr<vk::ImageWithMemory>	unprotectedImage	= createImage2D(ctx, PROTECTION_DISABLED, queueFamilyIndex,
																				IMAGE_WIDTH, IMAGE_HEIGHT,
																				m_params.imageFormat,
																				vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);

		// Upload data to an unprotected image
		uploadImage(m_protectedContext, **unprotectedImage, *texture2D);

		// Select vkImageLayout based upon accessType
		vk::VkImageLayout imageSrcLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
			{
				imageSrcLayout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
				break;
			}
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
			case ACCESS_TYPE_IMAGE_ATOMICS:
			{
				imageSrcLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
				break;
			}
			default:
				DE_FATAL("Impossible");
				break;
		}

		// Copy unprotected image to protected image
		copyToProtectedImage(m_protectedContext, **unprotectedImage, **imageSrc, imageSrcLayout, IMAGE_WIDTH, IMAGE_HEIGHT);
	}

	// Clear dst image
	if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
		clearImage(m_protectedContext, **imageDst);

	// Create descriptors
	{
		vk::DescriptorSetLayoutBuilder	layoutBuilder;
		vk::DescriptorPoolBuilder		poolBuilder;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
				layoutBuilder.addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_COMPUTE_BIT, DE_NULL);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
				break;
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
				break;
			case ACCESS_TYPE_IMAGE_ATOMICS:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_COMPUTE_BIT);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
				break;
			default:
				DE_FATAL("Impossible");
				break;
		}

		descriptorSetLayout		= layoutBuilder.build(vk, device);
		descriptorPool			= poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
		descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
	}

	// Create pipeline layout
	vk::Unique<vk::VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));

	// Create sampler and image views
	{
		if (m_params.accessType == ACCESS_TYPE_SAMPLING || m_params.accessType == ACCESS_TYPE_TEXEL_FETCH)
		{
			const tcu::TextureFormat		texFormat		= mapVkFormat(m_params.imageFormat);
			const vk::VkSamplerCreateInfo	samplerParams	= vk::mapSampler(refSampler, texFormat);

			sampler = createSampler(vk, device, &samplerParams);
		}

		imageViewSrc = createImageView(ctx, **imageSrc, m_params.imageFormat);

		if (m_params.accessType != ACCESS_TYPE_IMAGE_ATOMICS)
			imageViewDst = createImageView(ctx, **imageDst, m_params.imageFormat);
	}

	// Update descriptor set information
	{
		vk::DescriptorSetUpdateBuilder		updateBuilder;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
			{
				vk::VkDescriptorImageInfo	descStorageImgDst	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
				vk::VkDescriptorImageInfo	descSampledImgSrc	= makeDescriptorImageInfo(*sampler, *imageViewSrc, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImgSrc);
				break;
			}
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
			{
				vk::VkDescriptorImageInfo	descStorageImgDst	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);
				vk::VkDescriptorImageInfo	descStorageImgSrc	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgSrc);
				break;
			}
			case ACCESS_TYPE_IMAGE_ATOMICS:
			{
				vk::VkDescriptorImageInfo	descStorageImg		= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
				break;
			}
			default:
				DE_FATAL("Impossible");
				break;
		}

		updateBuilder.update(vk, device);
	}

	// Create validation compute commands & submit
	{
		const vk::Unique<vk::VkFence>		fence		(vk::createFence(vk, device));
		vk::Unique<vk::VkPipeline>			pipeline	(makeComputePipeline(vk, device, *pipelineLayout, *computeShader, DE_NULL));
		vk::Unique<vk::VkCommandBuffer>		cmdBuffer	(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));

		beginCommandBuffer(vk, *cmdBuffer);

		vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipeline);
		vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_COMPUTE, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);
		vk.cmdDispatch(*cmdBuffer, (deUint32)IMAGE_WIDTH, (deUint32)IMAGE_HEIGHT, 1u);
		endCommandBuffer(vk, *cmdBuffer);

		VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
	}

	// Calculate reference image
	if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
		calculateAtomicRef(*texture2D);

	// Validate result
	{
		const vk::VkImage	resultImage		= m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS ? **imageSrc : **imageDst;

		return validateResult(resultImage, vk::VK_IMAGE_LAYOUT_GENERAL, *texture2D, refSampler);
	}
}

tcu::TestStatus ImageAccessTestInstance::executeFragmentTest (void)
{
	ProtectedContext&					ctx					(m_protectedContext);
	const vk::DeviceInterface&			vk					= ctx.getDeviceInterface();
	const vk::VkDevice					device				= ctx.getDevice();
	const vk::VkQueue					queue				= ctx.getQueue();
	const deUint32						queueFamilyIndex	= ctx.getQueueFamilyIndex();

	// Create output image
	de::MovePtr<vk::ImageWithMemory>	colorImage			(createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
																		   RENDER_WIDTH, RENDER_HEIGHT,
																		   m_params.imageFormat,
																		   vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT|vk::VK_IMAGE_USAGE_SAMPLED_BIT));
	vk::Unique<vk::VkImageView>			colorImageView		(createImageView(ctx, **colorImage, m_params.imageFormat));

	vk::Unique<vk::VkRenderPass>		renderPass			(createRenderPass(ctx, m_params.imageFormat));
	vk::Unique<vk::VkFramebuffer>		framebuffer			(createFramebuffer(ctx, RENDER_WIDTH, RENDER_HEIGHT, *renderPass, *colorImageView));

	vk::Unique<vk::VkCommandPool>		cmdPool				(makeCommandPool(vk, device, PROTECTION_ENABLED, queueFamilyIndex));
	vk::Unique<vk::VkCommandBuffer>		cmdBuffer			(vk::allocateCommandBuffer(vk, device, *cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY));

	de::MovePtr<tcu::Texture2D>			texture2D			= createTestTexture2D();
	const tcu::Sampler					refSampler			= tcu::Sampler(tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE, tcu::Sampler::CLAMP_TO_EDGE,
																		   tcu::Sampler::NEAREST, tcu::Sampler::NEAREST);

	vk::Move<vk::VkShaderModule>		vertexShader		= createShaderModule(vk, device, ctx.getBinaryCollection().get("vert"), 0);
	vk::Move<vk::VkShaderModule>		fragmentShader		= createShaderModule(vk, device, ctx.getBinaryCollection().get("frag"), 0);

	de::MovePtr<vk::ImageWithMemory>	imageSrc;
	de::MovePtr<vk::ImageWithMemory>	imageDst;
	vk::Move<vk::VkSampler>				sampler;
	vk::Move<vk::VkImageView>			imageViewSrc;
	vk::Move<vk::VkImageView>			imageViewDst;

	vk::Move<vk::VkPipeline>			graphicsPipeline;
	vk::Move<vk::VkDescriptorSetLayout>	descriptorSetLayout;
	vk::Move<vk::VkDescriptorPool>		descriptorPool;
	vk::Move<vk::VkDescriptorSet>		descriptorSet;

	// Create src and dst images
	{
		vk::VkImageUsageFlags imageUsageFlags = vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT	|
												vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT	|
												vk::VK_IMAGE_USAGE_SAMPLED_BIT;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_IMAGE_LOAD:
			case ACCESS_TYPE_IMAGE_STORE:
			case ACCESS_TYPE_IMAGE_ATOMICS:
				imageUsageFlags |= vk::VK_IMAGE_USAGE_STORAGE_BIT;
				break;
			default:
				break;
		}

		imageSrc = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
								 IMAGE_WIDTH, IMAGE_HEIGHT,
								 m_params.imageFormat,
								 imageUsageFlags);

		if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
		{
			imageDst = createImage2D(ctx, PROTECTION_ENABLED, queueFamilyIndex,
									 IMAGE_WIDTH, IMAGE_HEIGHT,
									 m_params.imageFormat,
									 imageUsageFlags);
		}
	}

	// Select vkImageLayout based upon accessType
	vk::VkImageLayout imageLayout = vk::VK_IMAGE_LAYOUT_UNDEFINED;

	switch (m_params.accessType)
	{
		case ACCESS_TYPE_SAMPLING:
		case ACCESS_TYPE_TEXEL_FETCH:
		{
			imageLayout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
			break;
		}
		case ACCESS_TYPE_IMAGE_LOAD:
		case ACCESS_TYPE_IMAGE_STORE:
		case ACCESS_TYPE_IMAGE_ATOMICS:
		{
			imageLayout = vk::VK_IMAGE_LAYOUT_GENERAL;
			break;
		}
		default:
			DE_FATAL("Impossible");
			break;
	}

	// Upload source image
	{
		de::MovePtr<vk::ImageWithMemory>	unprotectedImage	= createImage2D(ctx, PROTECTION_DISABLED, queueFamilyIndex,
																				IMAGE_WIDTH, IMAGE_HEIGHT,
																				m_params.imageFormat,
																				vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT | vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT);

		// Upload data to an unprotected image
		uploadImage(m_protectedContext, **unprotectedImage, *texture2D);

		// Copy unprotected image to protected image
		copyToProtectedImage(m_protectedContext, **unprotectedImage, **imageSrc, imageLayout, IMAGE_WIDTH, IMAGE_HEIGHT);
	}

	// Clear dst image
	if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
		clearImage(m_protectedContext, **imageDst);

	// Create descriptors
	{
		vk::DescriptorSetLayoutBuilder	layoutBuilder;
		vk::DescriptorPoolBuilder		poolBuilder;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
				layoutBuilder.addSingleSamplerBinding(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, vk::VK_SHADER_STAGE_FRAGMENT_BIT, DE_NULL);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, 1u);
				break;
			case ACCESS_TYPE_IMAGE_LOAD:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
				break;
			case ACCESS_TYPE_IMAGE_STORE:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 2u);
				break;
			case ACCESS_TYPE_IMAGE_ATOMICS:
				layoutBuilder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
				poolBuilder.addType(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1u);
				break;
			default:
				DE_FATAL("Impossible");
				break;
		}

		descriptorSetLayout		= layoutBuilder.build(vk, device);
		descriptorPool			= poolBuilder.build(vk, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);
		descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
	}

	// Create pipeline layout
	vk::Unique<vk::VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device, *descriptorSetLayout));

	// Create sampler and image views
	{
		if (m_params.accessType == ACCESS_TYPE_SAMPLING || m_params.accessType == ACCESS_TYPE_TEXEL_FETCH)
		{
			const tcu::TextureFormat		texFormat		= mapVkFormat(m_params.imageFormat);
			const vk::VkSamplerCreateInfo	samplerParams	= vk::mapSampler(refSampler, texFormat);

			sampler = createSampler(vk, device, &samplerParams);
		}

		imageViewSrc = createImageView(ctx, **imageSrc, m_params.imageFormat);

		if (m_params.accessType == ACCESS_TYPE_IMAGE_STORE)
			imageViewDst = createImageView(ctx, **imageDst, m_params.imageFormat);
	}

	// Update descriptor set information
	{
		vk::DescriptorSetUpdateBuilder		updateBuilder;

		switch (m_params.accessType)
		{
			case ACCESS_TYPE_SAMPLING:
			case ACCESS_TYPE_TEXEL_FETCH:
			{
				vk::VkDescriptorImageInfo	descSampledImg		= makeDescriptorImageInfo(*sampler, *imageViewSrc, vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER, &descSampledImg);
				break;
			}
			case ACCESS_TYPE_IMAGE_LOAD:
			{
				vk::VkDescriptorImageInfo	descStorageImg		= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
				break;
			}
			case ACCESS_TYPE_IMAGE_STORE:
			{
				vk::VkDescriptorImageInfo	descStorageImgSrc	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);
				vk::VkDescriptorImageInfo	descStorageImgDst	= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewDst, vk::VK_IMAGE_LAYOUT_GENERAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgSrc);
				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(1u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImgDst);
				break;
			}
			case ACCESS_TYPE_IMAGE_ATOMICS:
			{
				vk::VkDescriptorImageInfo	descStorageImg		= makeDescriptorImageInfo((vk::VkSampler)0, *imageViewSrc, vk::VK_IMAGE_LAYOUT_GENERAL);

				updateBuilder.writeSingle(*descriptorSet, vk::DescriptorSetUpdateBuilder::Location::binding(0u), vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descStorageImg);
				break;
			}
			default:
				DE_FATAL("Impossible");
				break;
		}

		updateBuilder.update(vk, device);
	}

	// Create vertex buffer and vertex input descriptors
	VertexBindings						vertexBindings;
	VertexAttribs						vertexAttribs;
	de::MovePtr<vk::BufferWithMemory>	vertexBuffer;
	{
		const float			positions[]		=
		{
			-1.0f,	-1.0f,
			-1.0f,	+1.0f,
			+1.0f,	-1.0f,
			+1.0f,	+1.0f,
		};

		std::vector<float>	texCoord;

		{
			const tcu::Vec2		minCoords		(0.0f, 0.0f);
			const tcu::Vec2		maxCoords		= m_params.accessType == ACCESS_TYPE_SAMPLING ?
												  tcu::Vec2(1.0f, 1.0f) :
												  tcu::Vec2((float)IMAGE_WIDTH - 0.1f, (float)IMAGE_HEIGHT - 0.1f);

			glu::TextureTestUtil::computeQuadTexCoord2D(texCoord, minCoords, maxCoords);
		}

		const deUint32		vertexPositionStrideSize	= (deUint32)sizeof(tcu::Vec2);
		const deUint32		vertexTextureStrideSize		= (deUint32)sizeof(tcu::Vec2);
		const deUint32		positionDataSize			= 4 * vertexPositionStrideSize;
		const deUint32		textureCoordDataSize		= 4 * vertexTextureStrideSize;
		const deUint32		vertexBufferSize			= positionDataSize + textureCoordDataSize;

		{
			const vk::VkVertexInputBindingDescription	vertexInputBindingDescriptions[2]	=
			{
				{
					0u,									// deUint32					binding;
					vertexPositionStrideSize,			// deUint32					strideInBytes;
					vk::VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
				},
				{
					1u,									// deUint32					binding;
					vertexTextureStrideSize,			// deUint32					strideInBytes;
					vk::VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate;
				}
			};
			vertexBindings.push_back(vertexInputBindingDescriptions[0]);
			vertexBindings.push_back(vertexInputBindingDescriptions[1]);

			const vk::VkVertexInputAttributeDescription	vertexInputAttributeDescriptions[2]	=
			{
				{
					0u,									// deUint32	location;
					0u,									// deUint32	binding;
					vk::VK_FORMAT_R32G32_SFLOAT,		// VkFormat	format;
					0u									// deUint32	offsetInBytes;
				},
				{
					1u,									// deUint32	location;
					1u,									// deUint32	binding;
					vk::VK_FORMAT_R32G32_SFLOAT,		// VkFormat	format;
					positionDataSize					// deUint32	offsetInBytes;
				}
			};
			vertexAttribs.push_back(vertexInputAttributeDescriptions[0]);
			vertexAttribs.push_back(vertexInputAttributeDescriptions[1]);
		}

		vertexBuffer = makeBuffer(ctx,
								  PROTECTION_DISABLED,
								  queueFamilyIndex,
								  vertexBufferSize,
								  vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,
								  vk::MemoryRequirement::HostVisible);

		deMemcpy(vertexBuffer->getAllocation().getHostPtr(), positions, positionDataSize);
		deMemcpy(reinterpret_cast<deUint8*>(vertexBuffer->getAllocation().getHostPtr()) +  positionDataSize, texCoord.data(), textureCoordDataSize);
		vk::flushMappedMemoryRange(vk, device, vertexBuffer->getAllocation().getMemory(), vertexBuffer->getAllocation().getOffset(), vertexBufferSize);
	}

	// Create pipeline
	graphicsPipeline = makeGraphicsPipeline(vk,
											device,
											*pipelineLayout,
											*renderPass,
											*vertexShader,
											*fragmentShader,
											vertexBindings,
											vertexAttribs,
											tcu::UVec2(RENDER_WIDTH, RENDER_HEIGHT),
											vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP);

	// Begin cmd buffer
	beginCommandBuffer(vk, *cmdBuffer);

	// Start image barrier
	{
		const vk::VkImageMemoryBarrier	startImgBarrier		=
		{
			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
			DE_NULL,											// pNext
			0,													// srcAccessMask
			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// dstAccessMask
			vk::VK_IMAGE_LAYOUT_UNDEFINED,						// oldLayout
			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// newLayout
			queueFamilyIndex,									// srcQueueFamilyIndex
			queueFamilyIndex,									// dstQueueFamilyIndex
			**colorImage,										// image
			{
				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
				0u,												// baseMipLevel
				1u,												// mipLevels
				0u,												// baseArraySlice
				1u,												// subresourceRange
			}
		};

		vk.cmdPipelineBarrier(*cmdBuffer,
							  vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// srcStageMask
							  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// dstStageMask
							  (vk::VkDependencyFlags)0,
							  0, (const vk::VkMemoryBarrier*)DE_NULL,
							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
							  1, &startImgBarrier);
	}

	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, vk::makeRect2D(0, 0, RENDER_WIDTH, RENDER_HEIGHT), tcu::Vec4(0.0f));

	vk.cmdBindPipeline(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *graphicsPipeline);
	vk.cmdBindDescriptorSets(*cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayout, 0u, 1u, &*descriptorSet, 0u, DE_NULL);

	{
		const vk::VkDeviceSize vertexBufferOffset = 0;

		vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer->get(), &vertexBufferOffset);
		vk.cmdBindVertexBuffers(*cmdBuffer, 1u, 1u, &vertexBuffer->get(), &vertexBufferOffset);
	}

	vk.cmdDraw(*cmdBuffer, /*vertexCount*/ 4u, 1u, 0u, 1u);

	endRenderPass(vk, *cmdBuffer);

	{
		const vk::VkImageMemoryBarrier	endImgBarrier		=
		{
			vk::VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType
			DE_NULL,											// pNext
			vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// srcAccessMask
			vk::VK_ACCESS_SHADER_READ_BIT,						// dstAccessMask
			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// oldLayout
			imageLayout,										// newLayout
			queueFamilyIndex,									// srcQueueFamilyIndex
			queueFamilyIndex,									// dstQueueFamilyIndex
			**colorImage,										// image
			{
				vk::VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
				0u,												// baseMipLevel
				1u,												// mipLevels
				0u,												// baseArraySlice
				1u,												// subresourceRange
			}
		};
		vk.cmdPipelineBarrier(*cmdBuffer,
							  vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// srcStageMask
							  vk::VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,				// dstStageMask
							  (vk::VkDependencyFlags)0,
							  0, (const vk::VkMemoryBarrier*)DE_NULL,
							  0, (const vk::VkBufferMemoryBarrier*)DE_NULL,
							  1, &endImgBarrier);
	}

	endCommandBuffer(vk, *cmdBuffer);

	// Submit command buffer
	{
		const vk::Unique<vk::VkFence>	fence		(vk::createFence(vk, device));
		VK_CHECK(queueSubmit(ctx, PROTECTION_ENABLED, queue, *cmdBuffer, *fence, ~0ull));
	}

	// Calculate reference image
	if (m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS)
		calculateAtomicRef(*texture2D);

	// Validate result
	{
		const vk::VkImage	resultImage		= m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS	?	**imageSrc	:
											  m_params.accessType == ACCESS_TYPE_IMAGE_STORE	?	**imageDst	: **colorImage;

		return validateResult(resultImage, imageLayout, *texture2D, refSampler);
	}
}

void ImageAccessTestInstance::calculateAtomicRef (tcu::Texture2D& texture2D)
{
	DE_ASSERT(m_params.accessType == ACCESS_TYPE_IMAGE_ATOMICS);

	const tcu::PixelBufferAccess&	reference	= texture2D.getLevel(0);

	for (int x = 0; x < reference.getWidth(); ++x)
	for (int y = 0; y < reference.getHeight(); ++y)
	{
		const deInt32	oldX		= reference.getPixelInt(x, y).x();
		const deInt32	atomicArg	= x*x + y*y;
		const deInt32	newX		= computeBinaryAtomicOperationResult(m_params.atomicOperation, oldX, atomicArg);

		reference.setPixel(tcu::IVec4(newX, 0, 0, 0), x, y);
	}
}

tcu::TestStatus ImageAccessTestInstance::validateResult (vk::VkImage image, vk::VkImageLayout imageLayout, const tcu::Texture2D& texture2D, const tcu::Sampler& refSampler)
{
	de::Random			rnd			(getSeedValue(m_params));
	ValidationData		refData;

	for (int ndx = 0; ndx < 4; ++ndx)
	{
		const float		lod		= 0.0f;
		const float		cx		= rnd.getFloat(0.0f, 1.0f);
		const float		cy		= rnd.getFloat(0.0f, 1.0f);

		refData.coords[ndx] = tcu::Vec4(cx, cy, 0.0f, 0.0f);
		refData.values[ndx] = texture2D.sample(refSampler, cx, cy, lod);
	}

	if (!m_validator.validateImage(m_protectedContext, refData, image, m_params.imageFormat, imageLayout))
		return tcu::TestStatus::fail("Something went really wrong");
	else
		return tcu::TestStatus::pass("Everything went OK");
}

} // anonymous

tcu::TestCaseGroup*	createShaderImageAccessTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> accessGroup (new tcu::TestCaseGroup(testCtx, "access", "Shader Image Access Tests"));

	static const struct
	{
		glu::ShaderType	type;
		const char*		name;
		const char*		desc;
	} shaderTypes[] =
	{
		{ glu::SHADERTYPE_FRAGMENT,		"fragment",			"Image access from fragment shader"		},
		{ glu::SHADERTYPE_COMPUTE,		"compute",			"Image access from compute shader"		},
	};

	static const struct
	{
		AccessType		type;
		const char*		name;
		const char*		desc;
	} accessTypes[] =
	{
		{ ACCESS_TYPE_SAMPLING,			"sampling",			"Sampling test"			},
		{ ACCESS_TYPE_TEXEL_FETCH,		"texelfetch",		"Texel fetch test"		},
		{ ACCESS_TYPE_IMAGE_LOAD,		"imageload",		"Image load test"		},
		{ ACCESS_TYPE_IMAGE_STORE,		"imagestore",		"Image store test"		},
		{ ACCESS_TYPE_IMAGE_ATOMICS,	"imageatomics",		"Image atomics test"	},
	};

	static const struct
	{
		vk::VkFormat	format;
		const char*		name;
	} formats[] =
	{
		{ vk::VK_FORMAT_R8G8B8A8_UNORM,	"rgba8"	},
		{ vk::VK_FORMAT_R32_SINT,		"r32i"	},
		{ vk::VK_FORMAT_R32_UINT,		"r32ui"	},
	};

	for (int shaderTypeNdx = 0; shaderTypeNdx < DE_LENGTH_OF_ARRAY(shaderTypes); ++shaderTypeNdx)
	{
		const glu::ShaderType				shaderType		= shaderTypes[shaderTypeNdx].type;
		de::MovePtr<tcu::TestCaseGroup>		shaderGroup		(new tcu::TestCaseGroup(testCtx, shaderTypes[shaderTypeNdx].name, shaderTypes[shaderTypeNdx].desc));

		for (int accessNdx = 0; accessNdx < DE_LENGTH_OF_ARRAY(accessTypes); ++accessNdx)
		{
			const AccessType					accessType			= accessTypes[accessNdx].type;

			if (shaderType == glu::SHADERTYPE_COMPUTE && accessType == ACCESS_TYPE_IMAGE_STORE) // \note already tested in other tests
				continue;

			de::MovePtr<tcu::TestCaseGroup>		accessTypeGroup		(new tcu::TestCaseGroup(testCtx, accessTypes[accessNdx].name, accessTypes[accessNdx].desc));

			if (accessType == ACCESS_TYPE_IMAGE_ATOMICS)
			{
				for (deUint32 atomicOpI = 0; atomicOpI < ATOMIC_OPERATION_LAST; ++atomicOpI)
				{
					const AtomicOperation				atomicOp		= (AtomicOperation)atomicOpI;
					de::MovePtr<tcu::TestCaseGroup>		operationGroup	(new tcu::TestCaseGroup(testCtx, getAtomicOperationCaseName(atomicOp).c_str(), ""));

					for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
					{
						const vk::VkFormat		format		= formats[formatNdx].format;

						if (format != vk::VK_FORMAT_R32_UINT && format != vk::VK_FORMAT_R32_SINT)
							continue;

						operationGroup->addChild(new ImageAccessTestCase(testCtx, formats[formatNdx].name, "", Params(shaderType, accessType, format, atomicOp)));
					}

					accessTypeGroup->addChild(operationGroup.release());
				}
			}
			else
			{
				for (deUint32 formatNdx = 0; formatNdx < DE_LENGTH_OF_ARRAY(formats); formatNdx++)
				{
					const vk::VkFormat		format		= formats[formatNdx].format;

					accessTypeGroup->addChild(new ImageAccessTestCase(testCtx, formats[formatNdx].name, "", Params(shaderType, accessType, format)));
				}
			}

			shaderGroup->addChild(accessTypeGroup.release());
		}

		accessGroup->addChild(shaderGroup.release());
	}

	return accessGroup.release();
}

} // ProtectedMem
} // vkt
