/*------------------------------------------------------------------------
* Vulkan Conformance Tests
* ------------------------
*
* Copyright (c) 2019 The Khronos Group 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 Vulkan Decriptor Indexing Tests
*//*--------------------------------------------------------------------*/

#include <algorithm>
#include <iostream>
#include <iterator>
#include <functional>
#include <sstream>
#include <utility>
#include <vector>

#include "vktDescriptorSetsIndexingTests.hpp"

#include "vkBuilderUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkDefs.hpp"
#include "vkObjUtil.hpp"
#include "vkPlatform.hpp"
#include "vkPrograms.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"

#include "tcuTestLog.hpp"
#include "tcuResource.hpp"
#include "tcuImageCompare.hpp"
#include "tcuCommandLine.hpp"
#include "tcuStringTemplate.hpp"
#include "tcuSurface.hpp"
#include "tcuVectorUtil.hpp"

#include "deRandom.hpp"
#include "deMath.h"
#include "deStringUtil.hpp"

namespace vkt
{
namespace DescriptorIndexing
{
namespace
{
using namespace vk;
using tcu::UVec2;
using tcu::Vec4;
using tcu::TestStatus;
using tcu::PixelBufferAccess;
using tcu::Texture2D;

#define RESOLUTION_width	64
#define RESOLUTION_height	64
static const VkExtent3D RESOLUTION = { RESOLUTION_width, RESOLUTION_height, 1 };

#define MAX_DESCRIPTORS		4200
#define FUZZY_COMPARE		DE_FALSE
#define	CMP_THRESHOLD		0.02f

#define BINDING_Undefined				0
#define BINDING_UniformBuffer			1
#define BINDING_StorageBuffer			2
#define BINDING_UniformTexelBuffer		3
#define BINDING_StorageTexelBuffer		4
#define BINDING_Sampler					5
#define BINDING_SampledImage			6
#define BINDING_CombinedImageSampler	7
#define BINDING_UniformBufferDynamic	8
#define BINDING_StorageBufferDynamic	9
#define BINDING_InputAttachment			10
#define BINDING_StorageImage			11
#define BINDING_DescriptorEnumerator	12

static const VkExtent3D			smallImageExtent				= { 4, 4, 1 };
static const VkExtent3D			bigImageExtent					= { 32, 32, 1 };
static const VkDescriptorType	VK_DESCRIPTOR_TYPE_UNDEFINED = VK_DESCRIPTOR_TYPE_INLINE_UNIFORM_BLOCK_EXT;

template<deUint32 BindingNumber>
struct Binding
{
	static const deUint32	binding	= BindingNumber;
};

struct BindingUniformBuffer : Binding<BINDING_UniformBuffer>
{
	typedef struct
	{
		tcu::Vec4 c;
	} Data;
};

struct BindingStorageBuffer : Binding<BINDING_StorageBuffer>
{
	typedef struct
	{
		tcu::Vec4 cnew;
		tcu::Vec4 cold;
	} Data;
};

struct TestCaseParams
{
	VkDescriptorType	descriptorType;		// used only to distinguish test class instance
	VkShaderStageFlags	stageFlags;			// used only to build a proper program
	VkExtent3D			frameResolution;	// target frame buffer resolution
	bool				updateAfterBind;	// whether a test will use update after bind feature
	bool				calculateInLoop;	// perform calculation in a loop
	bool				usesMipMaps;		// this makes a sense and affects in image test cases only
	deBool				fuzzyComparison;	// if true then a test will use fuzzy comparison, otherwise float threshold
	float				thresholdValue;		// a threshold that will be used for both, float and fuzzy comparisons
};

struct TestParams
{
	VkShaderStageFlags	stageFlags;
	VkDescriptorType	descriptorType;
	deUint32			descriptorBinding;
	VkDescriptorType	additionalDescriptorType;
	deUint32			additionalDescriptorBinding;
	bool				copyBuffersToImages;
	bool				allowVertexStoring;
	VkExtent3D			frameResolution;
	bool				updateAfterBind;
	bool				calculateInLoop;
	bool				usesMipMaps;
	deBool				fuzzyComparison;
	float				thresholdValue;

	TestParams			(VkShaderStageFlags		stageFlags_,
						VkDescriptorType		descriptorType_,
						deUint32				descriptorBinding_,
						VkDescriptorType		additionalDescriptorType_,
						deUint32				additionalDescriptorBinding_,
						bool					copyBuffersToImages_,
						bool					allowVertexStoring_,
						const TestCaseParams&	caseParams)
		: stageFlags							(stageFlags_)
		, descriptorType						(descriptorType_)
		, descriptorBinding						(descriptorBinding_)
		, additionalDescriptorType				(additionalDescriptorType_)
		, additionalDescriptorBinding			(additionalDescriptorBinding_)
		, copyBuffersToImages					(copyBuffersToImages_)
		, allowVertexStoring					(allowVertexStoring_)
		, frameResolution						(caseParams.frameResolution)
		, updateAfterBind						(caseParams.updateAfterBind)
		, calculateInLoop						(caseParams.calculateInLoop)
		, usesMipMaps							(caseParams.usesMipMaps)
		, fuzzyComparison						(caseParams.fuzzyComparison ? true : false)
		, thresholdValue						(caseParams.thresholdValue)
	{
	}
};

struct DescriptorEnumerator
{
	ut::BufferHandleAllocSp							buffer;
	ut::BufferViewSp								bufferView;
	VkDeviceSize									bufferSize;

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

	void init(const vkt::Context& context, deUint32 vertexCount, deUint32 availableDescriptorCount);
	void update(const vkt::Context& context);
};

struct IterateCommonVariables
{
	// An amount of descriptors of a given type available on the platform
	deUint32										availableDescriptorCount;
	// An amount of valid descriptors that have connected a buffers to them
	deUint32										validDescriptorCount;
	// As the name suggests, sometimes it is used as invocationCount
	deUint32										vertexCount;
	VkRect2D										renderArea;
	VkDeviceSize									dataAlignment;
	deUint32										lowerBound;
	deUint32										upperBound;

	DescriptorEnumerator							descriptorEnumerator;

	ut::BufferHandleAllocSp							vertexAttributesBuffer;
	ut::BufferHandleAllocSp							descriptorsBuffer;
	std::vector<VkDescriptorBufferInfo>				descriptorsBufferInfos;
	std::vector<ut::BufferViewSp>					descriptorsBufferViews;
	std::vector<ut::ImageViewSp>					descriptorImageViews;
	std::vector<ut::SamplerSp>						descriptorSamplers;
	std::vector<ut::ImageHandleAllocSp>				descriptorsImages;
	ut::FrameBufferSp								frameBuffer;

	Move<VkDescriptorSetLayout>						descriptorSetLayout;
	Move<VkDescriptorPool>							descriptorPool;
	Move<VkDescriptorSet>							descriptorSet;
	Move<VkPipelineLayout>							pipelineLayout;
	Move<VkRenderPass>								renderPass;
	Move<VkPipeline>								pipeline;
	Move<VkCommandBuffer>							commandBuffer;
};

class CommonDescriptorInstance : public TestInstance
{
public:
								CommonDescriptorInstance		(Context&									context,
																const TestParams&							testParams);

	deUint32					computeAvailableDescriptorCount	(VkDescriptorType							descriptorType) const;

	Move<VkDescriptorSetLayout>	createDescriptorSetLayout		(deUint32&									descriptorCount) const;

	Move<VkDescriptorPool>		createDescriptorPool			(deUint32									descriptorCount) const;

	Move<VkDescriptorSet>		createDescriptorSet				(VkDescriptorPool							dsPool,
																 VkDescriptorSetLayout						dsLayout) const;

	struct attributes
	{
		typedef tcu::Vec4	vec4;
		typedef tcu::Vec2	vec2;
		typedef tcu::IVec4	ivec4;
		vec4			position;
		vec2			normalpos;
		ivec4			index;
		attributes& operator()(const vec4& pos)
		{
			position = pos;

			normalpos.x() = (pos.x() + 1.0f) / 2.0f;
			normalpos.y() = (pos.y() + 1.0f) / 2.0f;

			return *this;
		}
	};
	void						createVertexAttributeBuffer		(ut::BufferHandleAllocSp&					buffer,
																 deUint32									availableDescriptorCount) const;

	static std::string			substBinding					(deUint32									binding,
																 const char*								str,
																 deUint32									count = 0,
																 const char*								name = DE_NULL);

	static const char*			getVertexShaderProlog			(void);

	static const char*			getFragmentShaderProlog			(void);

	static const char*			getShaderEpilog					(void);

	static bool					performWritesInVertex			(VkDescriptorType							descriptorType);

	static std::string			getShaderSource					(VkShaderStageFlagBits						shaderType,
																 const TestCaseParams&						testCaseParams,
																 bool										allowVertexStoring);

	static std::string			getColorAccess					(VkDescriptorType							descriptorType,
																 const char*								indexVariableName,
																 bool										usesMipMaps);

	static std::string			getFragmentReturnSource			(const std::string&							colorAccess);

	static std::string			getFragmentLoopSource			(const std::string&							colorAccess1,
																 const std::string&							colorAccess2);

	virtual Move<VkRenderPass>	createRenderPass				(const IterateCommonVariables&				variables);

	struct push_constant
	{
		deInt32	lowerBound;
		deInt32	upperBound;
	};
	VkPushConstantRange			makePushConstantRange			(void) const;

	Move<VkPipelineLayout>		createPipelineLayout			(const std::vector<VkDescriptorSetLayout>&	descriptorSetLayouts) const;

	// Creates graphics or compute pipeline and appropriate shaders' modules according the testCaseParams.stageFlags
	// In the case of compute pipeline renderPass parameter is ignored.
	// Viewport will be created with a width and a height taken from testCaseParam.fragResolution.
	Move<VkPipeline>			createPipeline					(VkPipelineLayout							pipelineLayout,
																 VkRenderPass								renderPass);

	virtual void				createFramebuffer				(ut::FrameBufferSp&							frameBuffer,
																 VkRenderPass								renderPass,
																 const IterateCommonVariables&				variables);

	// Creates one big stagging buffer cutted out on chunks that can accomodate an element of elementSize size
	VkDeviceSize				createBuffers					(std::vector<VkDescriptorBufferInfo>&		bufferInfos,
																 ut::BufferHandleAllocSp&					buffer,
																 deUint32									elementCount,
																 deUint32									elementSize,
																 VkDeviceSize								alignment,
																 VkBufferUsageFlags							bufferUsage);

	// Creates and binds an imagesCount of images with given parameters.
	// Additionally creates stagging buffer for their data and PixelBufferAccess for particular images.
	VkDeviceSize				createImages					(std::vector<ut::ImageHandleAllocSp>&		images,
																 std::vector<VkDescriptorBufferInfo>&		bufferInfos,
																 ut::BufferHandleAllocSp&					buffer,
																 VkBufferUsageFlags							bufferUsage,
																 const VkExtent3D&							imageExtent,
																 VkFormat									imageFormat,
																 VkImageLayout								imageLayout,
																 deUint32									imageCount,
																 bool										withMipMaps = false);

	void						createBuffersViews				(std::vector<ut::BufferViewSp>&				views,
																 const std::vector<VkDescriptorBufferInfo>&	bufferInfos,
																 VkFormat									format);

	void						createImagesViews				(std::vector<ut::ImageViewSp>&				views,
																 const std::vector<ut::ImageHandleAllocSp>&	images,
																 VkFormat									format);

	virtual void				copyBuffersToImages				(IterateCommonVariables&					variables);

	virtual void				copyImagesToBuffers				(IterateCommonVariables&					variables);

	PixelBufferAccess			getPixelAccess					(deUint32									imageIndex,
																 const VkExtent3D&							imageExtent,
																 VkFormat									imageFormat,
																 const std::vector<VkDescriptorBufferInfo>&	bufferInfos,
																 const ut::BufferHandleAllocSp&				buffer,
																 deUint32									mipLevel = 0u) const;

	virtual void				createAndPopulateDescriptors	(IterateCommonVariables&					variables) = 0;

	virtual void				updateDescriptors				(IterateCommonVariables&					variables);

	virtual void				iterateCollectResults			(ut::UpdatablePixelBufferAccessPtr&			result,
																 const IterateCommonVariables&				variables,
																 bool										fromTest);


	void						iterateCommandBegin				(IterateCommonVariables&					variables);

	bool						iterateCommandEnd				(IterateCommonVariables&					variables,
																 bool										collectBeforeSubmit = true);

	Move<VkCommandBuffer>		createCmdBuffer					(void);

	void						commandBindPipeline				(VkCommandBuffer							commandBuffer,
																 VkPipeline									pipeline);

	void						commandBindVertexAttributes		(VkCommandBuffer							commandBuffer,
																 const ut::BufferHandleAllocSp&				vertexAttributesBuffer);

	void						commandBindDescriptorSets		(VkCommandBuffer							commandBuffer,
																 VkPipelineLayout							pipelineLayout,
																 VkDescriptorSet							descriptorSet,
																 deUint32									descriptorSetIndex);

	void						commandReadFrameBuffer			(ut::BufferHandleAllocSp&					content,
																 VkCommandBuffer							commandBuffer,
																 const ut::FrameBufferSp&					frameBuffer);
	ut::UpdatablePixelBufferAccessPtr
								commandReadFrameBuffer			(VkCommandBuffer							commandBuffer,
																 const ut::FrameBufferSp&					frameBuffer);

	Move<VkFence>				commandSubmit					(VkCommandBuffer							commandBuffer);

	virtual bool				verifyVertexWriteResults		(IterateCommonVariables&					variables);

protected:
	virtual tcu::TestStatus		iterate							(void);

protected:
	const VkDevice				m_vkd;
	const DeviceInterface&		m_vki;
	Allocator&					m_allocator;
	const VkQueue				m_queue;
	const deUint32				m_queueFamilyIndex;
	const Move<VkCommandPool>	m_commandPool;
	const VkFormat				m_colorFormat;
	const TestParams			m_testParams;
	static const tcu::Vec4		m_clearColor;
	const std::vector<float>	m_colorScheme;
	const deUint32				m_schemeSize;

private:

	Move<VkPipeline>			createGraphicsPipeline			(VkPipelineLayout							pipelineLayout,
																 VkRenderPass								renderPass);

	Move<VkPipeline>			createComputePipeline			(VkPipelineLayout							pipelineLayout);

	int							constructShaderModules			(void);

	static std::vector<float>	createColorScheme();

	Move<VkShaderModule>		m_vertexModule;
	Move<VkShaderModule>		m_fragmentModule;
	Move<VkShaderModule>		m_computeModule;
};
const tcu::Vec4 CommonDescriptorInstance::m_clearColor = tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);

void DescriptorEnumerator::init (const vkt::Context& context, deUint32 vertexCount, deUint32 availableDescriptorCount)
{
	const VkDevice					device = context.getDevice();
	const DeviceInterface&			deviceInterface = context.getDeviceInterface();

	const VkFormat					imageFormat = VK_FORMAT_R32G32B32A32_SINT;
	typedef ut::mapVkFormat2Type<imageFormat>::type pixelType;
	const VkDeviceSize				dataSize = vertexCount * sizeof(pixelType);
	const std::vector<deUint32>		primes = ut::generatePrimes(availableDescriptorCount);
	const deUint32					primeCount = static_cast<deUint32>(primes.size());

	std::vector<pixelType>	data(vertexCount);
	// e.g. 2,3,5,7,11,13,2,3,5,7,...
	for (deUint32 idx = 0; idx < vertexCount; ++idx)
	{
		data[idx].x() = static_cast<pixelType::Element>(primes[idx % primeCount]);
		data[idx].y() = static_cast<pixelType::Element>(idx);
	}

	bufferSize = ut::createBufferAndBind(buffer, context, VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT, dataSize);
	deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast<size_t>(dataSize));

	const VkBufferViewCreateInfo bufferViewCreateInfo =
	{
		VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,		// sType
		DE_NULL,										// pNext
		0u,												// flags
		*(buffer.get()->buffer),						// buffer
		imageFormat,									// format
		0u,												// offset
		bufferSize,										// range
	};

	bufferView = ut::BufferViewSp(new Move<VkBufferView>(vk::createBufferView(deviceInterface, device, &bufferViewCreateInfo)));

	const VkDescriptorSetLayoutBinding	binding =
	{
		BINDING_DescriptorEnumerator,					// binding
		VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,		// descriptorType
		1u,												// descriptorCount
		VK_SHADER_STAGE_ALL,							// stageFlags
		DE_NULL,										// pImmutableSamplers
	};

	const VkDescriptorSetLayoutCreateInfo	layoutCreateInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
		DE_NULL,										// pNext
		0u,												// flags
		1u,												// bindingCount
		&binding,										// pBindings
	};

	descriptorSetLayout = vk::createDescriptorSetLayout(deviceInterface, device, &layoutCreateInfo);
	descriptorPool = DescriptorPoolBuilder().addType(binding.descriptorType)
		.build(deviceInterface, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1u);

	const VkDescriptorSetAllocateInfo	dsAllocInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// sType
		DE_NULL,										// pNext
		*descriptorPool,								// descriptorPool
		1u,												// descriptorSetCount
		&(*descriptorSetLayout)							// pSetLayouts
	};

	descriptorSet = vk::allocateDescriptorSet(deviceInterface, device, &dsAllocInfo);
}

void DescriptorEnumerator::update (const vkt::Context& context)
{
	const VkDescriptorBufferInfo bufferInfo =
	{
		*(buffer.get()->buffer),					// buffer
		0u,											// offset
		bufferSize,									// range
	};

	const VkWriteDescriptorSet writeInfo =
	{
		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,
		DE_NULL,									// pNext
		*descriptorSet,								// dstSet
		BINDING_DescriptorEnumerator,				// dstBinding
		0u,											// dstArrayElement
		1u,											// descriptorCount
		VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,	// descriptorType
		DE_NULL,									// pImageInfo
		&bufferInfo,								// pBufferInfo
		&(**bufferView),							// pTexelBufferView
	};

	context.getDeviceInterface().updateDescriptorSets(context.getDevice(), 1u, &writeInfo, 0u, DE_NULL);
}

CommonDescriptorInstance::CommonDescriptorInstance					(Context&								context,
																	const TestParams&						testParams)
	: TestInstance		(context)
	, m_vkd				(context.getDevice())
	, m_vki				(context.getDeviceInterface())
	, m_allocator		(context.getDefaultAllocator())
	, m_queue			(context.getUniversalQueue())
	, m_queueFamilyIndex(context.getUniversalQueueFamilyIndex())
	, m_commandPool		(vk::createCommandPool(m_vki, m_vkd, (VK_COMMAND_POOL_CREATE_TRANSIENT_BIT | VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT), m_queueFamilyIndex))
	, m_colorFormat		(VK_FORMAT_R32G32B32A32_SFLOAT)
	, m_testParams		(testParams)
	, m_colorScheme		(createColorScheme())
	, m_schemeSize		(static_cast<deUint32>(m_colorScheme.size()))
{
}

deUint32 CommonDescriptorInstance::computeAvailableDescriptorCount	(VkDescriptorType						descriptorType) const
{
	DE_UNREF(descriptorType);
	const deUint32 vertexCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height;
	const deUint32 availableDescriptorsOnDevice = ut::DeviceProperties(m_context).computeMaxPerStageDescriptorCount(m_testParams.descriptorType, m_testParams.updateAfterBind);
	return deMinu32(deMinu32(vertexCount, availableDescriptorsOnDevice), MAX_DESCRIPTORS);
}

Move<VkDescriptorSetLayout>	CommonDescriptorInstance::createDescriptorSetLayout (deUint32&					descriptorCount) const
{
	descriptorCount = computeAvailableDescriptorCount(m_testParams.descriptorType);

	bool optional = (m_testParams.additionalDescriptorBinding != BINDING_Undefined) && (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED);

	const VkDescriptorSetLayoutBinding	bindings[] =
	{
		{
			m_testParams.descriptorBinding,				// binding
			m_testParams.descriptorType,				// descriptorType
			descriptorCount,							// descriptorCount
			m_testParams.stageFlags,					// stageFlags
			DE_NULL,									// pImmutableSamplers
		},
		{
			m_testParams.additionalDescriptorBinding,	// binding
			m_testParams.additionalDescriptorType,		// descriptorType
			1,											// descriptorCount
			m_testParams.stageFlags,					// stageFlags
			DE_NULL,									// pImmutableSamplers
		}
	};

	const VkDescriptorBindingFlagsEXT	bindingFlagUpdateAfterBind =
		m_testParams.updateAfterBind ? VK_DESCRIPTOR_BINDING_UPDATE_AFTER_BIND_BIT_EXT : 0;

	const VkDescriptorBindingFlagsEXT bindingFlagsExt[] =
	{
		VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | bindingFlagUpdateAfterBind,
		VK_DESCRIPTOR_BINDING_PARTIALLY_BOUND_BIT_EXT | bindingFlagUpdateAfterBind
	};

	const VkDescriptorSetLayoutBindingFlagsCreateInfoEXT	bindingCreateInfoExt =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_BINDING_FLAGS_CREATE_INFO_EXT,
		DE_NULL,
		optional ? 2u : 1u,	// bindingCount
		bindingFlagsExt,	// pBindingFlags
	};

	const VkDescriptorSetLayoutCreateFlags	layoutCreateFlags =
		m_testParams.updateAfterBind ? VK_DESCRIPTOR_SET_LAYOUT_CREATE_UPDATE_AFTER_BIND_POOL_BIT_EXT : 0;

	const VkDescriptorSetLayoutCreateInfo	layoutCreateInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,
		&bindingCreateInfoExt,	// pNext
		layoutCreateFlags,		// flags
		optional ? 2u : 1u,		// bindingCount
		bindings,				// pBindings
	};

	return vk::createDescriptorSetLayout(m_vki, m_vkd, &layoutCreateInfo);
}

Move<VkDescriptorPool>	CommonDescriptorInstance::createDescriptorPool (deUint32							descriptorCount) const
{
	const VkDescriptorPoolCreateFlags pcf = m_testParams.updateAfterBind ? VK_DESCRIPTOR_POOL_CREATE_UPDATE_AFTER_BIND_BIT_EXT : 0;

	DescriptorPoolBuilder builder;

	builder.addType(m_testParams.descriptorType, descriptorCount);

	if (m_testParams.additionalDescriptorType != VK_DESCRIPTOR_TYPE_UNDEFINED && m_testParams.additionalDescriptorBinding != BINDING_Undefined)
	{
		builder.addType(m_testParams.additionalDescriptorType, 1);
	}

	return builder.build(m_vki, m_vkd, (VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT | pcf), 1u);
}

Move<VkDescriptorSet> CommonDescriptorInstance::createDescriptorSet	(VkDescriptorPool						dsPool,
																	 VkDescriptorSetLayout					dsLayout) const
{
	const VkDescriptorSetAllocateInfo	dsAllocInfo =
	{
		VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// sType;
		DE_NULL,											// pNext;
		dsPool,												// descriptorPool;
		1u,													// descriptorSetCount
		&dsLayout											// pSetLayouts
	};

	return vk::allocateDescriptorSet(m_vki, m_vkd, &dsAllocInfo);
}

void CommonDescriptorInstance::createVertexAttributeBuffer			(ut::BufferHandleAllocSp&				buffer,
																	 deUint32								availableDescriptorCount) const
{
	float						xSize			= 0.0f;
	float						ySize			= 0.0f;

	const deUint32				invocationCount = m_testParams.frameResolution.width * m_testParams.frameResolution.height;
	const std::vector<Vec4>		vertices		= ut::createVertices(m_testParams.frameResolution.width, m_testParams.frameResolution.height, xSize, ySize);
	const std::vector<deUint32>	primes			= ut::generatePrimes(availableDescriptorCount);
	const deUint32				primeCount		= static_cast<deUint32>(primes.size());

	std::vector<attributes> data(vertices.size());
	std::transform(vertices.begin(), vertices.end(), data.begin(), attributes());

	for (deUint32 invIdx = 0; invIdx < invocationCount; ++invIdx)
	{
		// r: 2,3,5,7,11,13,2,3,5,7,...
		data[invIdx].index.x() = primes[invIdx % primeCount];

		// b: x index in texel coordinate
		data[invIdx].index.z() = invIdx % m_testParams.frameResolution.width;

		//a: y index in texel coordinate
		data[invIdx].index.w() = invIdx / m_testParams.frameResolution.width;
	}

	// g: 0,0,2,3,0,5,0,7,0,0,0,11,0,13,...
	for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx)
	{
		const deUint32 prime = primes[primeIdx];
		DE_ASSERT(prime < invocationCount);
		data[prime].index.y() = prime;
	}

	const VkDeviceSize		dataSize = data.size() * sizeof(attributes);

	VkDeviceSize			deviceSize = ut::createBufferAndBind(buffer, m_context, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT, dataSize);

	deMemcpy(buffer->alloc->getHostPtr(), data.data(), static_cast<size_t>(deviceSize));

	vk::flushAlloc(m_vki, m_vkd, *buffer->alloc);
}

std::string CommonDescriptorInstance::substBinding					(deUint32								binding,
																	 const char*							str,
																	 deUint32								count,
																	 const char*							name)
{
	std::map<std::string, std::string> vars;
	vars["?"]	= de::toString(binding);
	vars["*"]	= (0 == count)		? ""		: de::toString(count);
	vars["VAR"]	= (DE_NULL == name)	? "data"	: name;
	return tcu::StringTemplate(str).specialize(vars);
}

const char* CommonDescriptorInstance::getVertexShaderProlog			(void)
{
	return
		"layout(location = 0) in  vec4  in_position;	\n"
		"layout(location = 1) in  vec2  in_normalpos;	\n"
		"layout(location = 2) in  ivec4 index;			\n"
		"layout(location = 0) out vec4  position;	\n"
		"layout(location = 1) out vec2  normalpos;	\n"
		"layout(location = 2) out int   vIndex;		\n"
		"layout(location = 3) out int   rIndex;		\n"
		"layout(location = 4) out int   gIndex;		\n"
		"layout(location = 5) out int   bIndex;		\n"
		"layout(location = 6) out int   aIndex;		\n"
		"void main()							\n"
		"{										\n"
		"    gl_PointSize = 0.2f;				\n"
		"    position = in_position;			\n"
		"    normalpos = in_normalpos;			\n"
		"    gl_Position = position;			\n"
		"    vIndex = gl_VertexIndex;			\n"
		"    rIndex = index.x;					\n"
		"    gIndex = index.y;					\n"
		"    bIndex = index.z;					\n"
		"    aIndex = index.w;					\n";
}

const char* CommonDescriptorInstance::getFragmentShaderProlog		(void)
{
	return
		"layout(location = 0) out vec4     FragColor;	\n"
		"layout(location = 0) in flat vec4 position;	\n"
		"layout(location = 1) in flat vec2 normalpos;	\n"
		"layout(location = 2) in flat int  vIndex;		\n"
		"layout(location = 3) in flat int  rIndex;		\n"
		"layout(location = 4) in flat int  gIndex;		\n"
		"layout(location = 5) in flat int  bIndex;		\n"
		"layout(location = 6) in flat int  aIndex;		\n"
		"void main()									\n"
		"{												\n";
}

const char* CommonDescriptorInstance::getShaderEpilog				(void)
{
	return "}											\n";
}

int	CommonDescriptorInstance::constructShaderModules				(void)
{
	int								result	= 0;
	ut::DeviceProperties			dp		(m_context);
	const VkPhysicalDeviceFeatures&	feats	= dp.physicalDeviceFeatures();
	tcu::TestLog&					log		= m_context.getTestContext().getLog();

	if (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
	{
		++result;
		const std::string name = ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, false);
		m_computeModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0);
	}
	if (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT)
	{
		++result;
		const std::string name = ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, (feats.vertexPipelineStoresAndAtomics != DE_FALSE && m_testParams.allowVertexStoring));
		m_fragmentModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0);
		log << tcu::TestLog::Message << "Finally used fragment shader: " << name << '\n' << tcu::TestLog::EndMessage;
	}
	if (m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT)
	{
		++result;
		const std::string name = ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testParams.descriptorType, m_testParams.updateAfterBind, m_testParams.calculateInLoop, (feats.vertexPipelineStoresAndAtomics != DE_FALSE && m_testParams.allowVertexStoring));
		m_vertexModule = vk::createShaderModule(m_vki, m_vkd, m_context.getBinaryCollection().get(name), (VkShaderModuleCreateFlags)0);
		log << tcu::TestLog::Message << "Finally used vertex shader: " << name << '\n' << tcu::TestLog::EndMessage;
	}

	DE_ASSERT(result > 0);

	return result;
}

Move<VkRenderPass> CommonDescriptorInstance::createRenderPass		(const IterateCommonVariables&			variables)
{
	DE_UNREF(variables);
	if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
	{
		return vk::makeRenderPass(m_vki, m_vkd, m_colorFormat);
	}
	return Move<VkRenderPass>();
}

VkPushConstantRange CommonDescriptorInstance::makePushConstantRange	(void) const
{
	const VkPushConstantRange pcr =
	{
		m_testParams.stageFlags,							// stageFlags
		0u,													// offset
		static_cast<deUint32>(sizeof(push_constant))		// size
	};
	return pcr;
}

Move<VkPipelineLayout> CommonDescriptorInstance::createPipelineLayout (const std::vector<VkDescriptorSetLayout>&	descriptorSetLayouts) const
{
	const VkPushConstantRange pcr = makePushConstantRange();

	const VkPipelineLayoutCreateInfo createInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// sType
		DE_NULL,											// pNext
		(VkPipelineLayoutCreateFlags)0,						// flags
		static_cast<deUint32>(descriptorSetLayouts.size()),	// setLayoutCount
		descriptorSetLayouts.data(),						// pSetLayouts;
		m_testParams.calculateInLoop ? 1u : 0u,				// pushConstantRangeCount
		m_testParams.calculateInLoop ? &pcr : DE_NULL,		// pPushConstantRanges
	};

	return vk::createPipelineLayout(m_vki, m_vkd, &createInfo);
}

void CommonDescriptorInstance::createFramebuffer					(ut::FrameBufferSp&							frameBuffer,
																	 VkRenderPass								renderPass,
																	 const IterateCommonVariables&				variables)
{
	DE_UNREF(variables);
	ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass);
}

Move<VkPipeline> CommonDescriptorInstance::createPipeline			(VkPipelineLayout							pipelineLayout,
																	 VkRenderPass								renderPass)
{	DE_ASSERT(VK_SHADER_STAGE_ALL != m_testParams.stageFlags);

	constructShaderModules();

	return (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
		? createComputePipeline(pipelineLayout)
		: createGraphicsPipeline(pipelineLayout, renderPass);
}

Move<VkPipeline> CommonDescriptorInstance::createComputePipeline	(VkPipelineLayout							pipelineLayout)
{
	const VkPipelineShaderStageCreateInfo	shaderStaegCreateInfo =
	{
		VK_STRUCTURE_TYPE_PIPELINE_SHADER_STAGE_CREATE_INFO,
		DE_NULL,								// pNext
		(VkPipelineShaderStageCreateFlags)0,	// flags
		VK_SHADER_STAGE_COMPUTE_BIT,			// stage
		*m_computeModule,						// module
		"main",									// pName
		(VkSpecializationInfo*)DE_NULL			// pSpecializationInfo
	};

	const VkComputePipelineCreateInfo		pipelineCreateInfo =
	{
		VK_STRUCTURE_TYPE_COMPUTE_PIPELINE_CREATE_INFO,
		DE_NULL,								// pNext
		0u,										// flags
		shaderStaegCreateInfo,					// stage
		pipelineLayout,							// layout
		(VkPipeline)0,							// basePipelineHandle
		0u,										// basePipelineIndex
	};
	return vk::createComputePipeline(m_vki, m_vkd, (VkPipelineCache)0u, &pipelineCreateInfo);
}

Move<VkPipeline> CommonDescriptorInstance::createGraphicsPipeline	(VkPipelineLayout							pipelineLayout,
																	 VkRenderPass								renderPass)
{
	const VkVertexInputBindingDescription			bindingDescriptions[] =
	{
		{
			0u,													// binding
			sizeof(attributes),									// stride
			VK_VERTEX_INPUT_RATE_VERTEX,						// inputRate
		},
	};

	const VkVertexInputAttributeDescription			attributeDescriptions[] =
	{
		{
			0u,													// location
			0u,													// binding
			ut::mapType2vkFormat<attributes::vec4>::value,		// format
			0u													// offset
		},														// @in_position
		{
			1u,													// location
			0u,													// binding
			ut::mapType2vkFormat<attributes::vec2>::value,		// format
			static_cast<deUint32>(sizeof(attributes::vec4))		// offset
		},														// @normalpos
		{
			2u,													// location
			0u,													// binding
			ut::mapType2vkFormat<attributes::ivec4>::value,		// format
			static_cast<deUint32>(sizeof(attributes::vec2)
								+ sizeof(attributes::vec4))		// offset
		},														// @index
	};

	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo	=
	{
		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
		DE_NULL,
		(VkPipelineVertexInputStateCreateFlags)0,	// flags
		DE_LENGTH_OF_ARRAY(bindingDescriptions),	// vertexBindingDescriptionCount
		bindingDescriptions,						// pVertexBindingDescriptions
		DE_LENGTH_OF_ARRAY(attributeDescriptions),	// vertexAttributeDescriptionCount
		attributeDescriptions						// pVertexAttributeDescriptions
	};

	const std::vector<VkViewport>	viewports	(1, makeViewport(m_testParams.frameResolution.width, m_testParams.frameResolution.height));
	const std::vector<VkRect2D>		scissors	(1, makeRect2D(m_testParams.frameResolution.width, m_testParams.frameResolution.height));

	DE_ASSERT(m_vertexModule && m_fragmentModule);

	return vk::makeGraphicsPipeline(
		m_vki,											// vk
		m_vkd,											// device
		pipelineLayout,									// pipelineLayout
		*m_vertexModule,								// vertexShaderModule
		DE_NULL,										// tessellationControlModule
		DE_NULL,										// tessellationEvalModule
		DE_NULL,										// geometryShaderModule
		*m_fragmentModule,								// fragmentShaderModule
		renderPass,										// renderPass
		viewports,										// viewports
		scissors,										// scissors
		VK_PRIMITIVE_TOPOLOGY_POINT_LIST,				// topology
		0U,												// subpass
		0U,												// patchControlPoints
		&vertexInputStateCreateInfo);					// vertexInputStateCreateInfo
}

VkDeviceSize CommonDescriptorInstance::createBuffers				(std::vector<VkDescriptorBufferInfo>&		bufferInfos,
																	 ut::BufferHandleAllocSp&					buffer,
																	 deUint32									elementCount,
																	 deUint32									elementSize,
																	 VkDeviceSize								alignment,
																	 VkBufferUsageFlags							bufferUsage)
{
	const VkDeviceSize	roundedSize = deAlign64(elementSize, alignment);
	VkDeviceSize		bufferSize	= ut::createBufferAndBind(buffer, m_context, bufferUsage, (roundedSize * elementCount));

	for (deUint32 elementIdx = 0; elementIdx < elementCount; ++elementIdx)
	{
		const VkDescriptorBufferInfo bufferInfo =
		{
			*buffer.get()->buffer,		//buffer;
			elementIdx * roundedSize,	//offset;
			elementSize,				// range;

		};
		bufferInfos.push_back(bufferInfo);
	}

	return bufferSize;
}

VkDeviceSize CommonDescriptorInstance::createImages					(std::vector<ut::ImageHandleAllocSp>&		images,
																	 std::vector<VkDescriptorBufferInfo>&		bufferInfos,
																	 ut::BufferHandleAllocSp&					buffer,
																	 VkBufferUsageFlags							bufferUsage,
																	 const VkExtent3D&							imageExtent,
																	 VkFormat									imageFormat,
																	 VkImageLayout								imageLayout,
																	 deUint32									imageCount,
																	 bool										withMipMaps)

{
	const deUint32		imageSize	= ut::computeImageSize(imageExtent, imageFormat, withMipMaps);

	const VkDeviceSize	bufferSize	= createBuffers(bufferInfos, buffer, imageCount, imageSize, sizeof(tcu::Vec4), bufferUsage);

	for (deUint32 imageIdx = 0; imageIdx < imageCount; ++imageIdx)
	{
		ut::ImageHandleAllocSp image;
		ut::createImageAndBind(image, m_context, imageFormat, imageExtent, imageLayout, withMipMaps);
		images.push_back(image);
	}

	return bufferSize;
}

void CommonDescriptorInstance::createBuffersViews					(std::vector<ut::BufferViewSp>&				views,
																	 const std::vector<VkDescriptorBufferInfo>&	bufferInfos,
																	 VkFormat									format)
{
	const deUint32 infoCount = static_cast<deUint32>(bufferInfos.size());
	for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx)
	{
		const VkDescriptorBufferInfo&	bufferInfo = bufferInfos[infoIdx];
		const VkBufferViewCreateInfo	bufferViewInfo =
		{
			VK_STRUCTURE_TYPE_BUFFER_VIEW_CREATE_INFO,	// sType
			DE_NULL,									// pNext
			(VkBufferViewCreateFlags)0,					// flags
			bufferInfo.buffer,							// buffer
			format,										// format
			bufferInfo.offset,							// offset
			bufferInfo.range							// range;
		};
		views.push_back(ut::BufferViewSp(new Move<VkBufferView>(vk::createBufferView(m_vki, m_vkd, &bufferViewInfo))));
	}
}

void CommonDescriptorInstance::createImagesViews					(std::vector<ut::ImageViewSp>&				views,
																	 const std::vector<ut::ImageHandleAllocSp>&	images,
																	 VkFormat									format)
{
	const deUint32 imageCount = static_cast<deUint32>(images.size());
	for (deUint32 imageIdx = 0; imageIdx < imageCount; ++imageIdx)
	{
		const VkImageViewCreateInfo createInfo =
		{
			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// sType
			DE_NULL,									// pNext
			(VkImageViewCreateFlags)0,					// flags
			*images[imageIdx]->image,					// image
			VK_IMAGE_VIEW_TYPE_2D,						// viewType
			format,										// format
			vk::makeComponentMappingRGBA(),				// components
			{
				VK_IMAGE_ASPECT_COLOR_BIT,				// aspectMask
				(deUint32)0,							// baseMipLevel
				images[imageIdx]->levels,				// mipLevels
				(deUint32)0,							// baseArrayLayer
				(deUint32)1u,							// arraySize
			},
		};
		views.push_back(ut::ImageViewSp(new Move<VkImageView>(vk::createImageView(m_vki, m_vkd, &createInfo))));
	}
}

void CommonDescriptorInstance::copyBuffersToImages					(IterateCommonVariables&					variables)
{
	const deUint32 infoCount = static_cast<deUint32>(variables.descriptorsBufferInfos.size());
	DE_ASSERT(variables.descriptorsImages.size() == infoCount);
	const VkPipelineStageFlagBits dstStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
		? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
		: VK_PIPELINE_STAGE_VERTEX_INPUT_BIT;
	for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx)
	{
		ut::recordCopyBufferToImage(
			*variables.commandBuffer,						// commandBuffer
			m_vki,											// interface
			VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT,				// srcStageMask
			dstStageMask,									// dstStageMask
			variables.descriptorsBufferInfos[infoIdx],		// bufferInfo
			*(variables.descriptorsImages[infoIdx]->image),	// image
			variables.descriptorsImages[infoIdx]->extent,	// imageExtent
			variables.descriptorsImages[infoIdx]->format,	// imageFormat
			VK_IMAGE_LAYOUT_UNDEFINED,						// oldImageLayout
			VK_IMAGE_LAYOUT_GENERAL,						// newImageLayout
			variables.descriptorsImages[infoIdx]->levels);	// mipLevelCount
	}
}

void CommonDescriptorInstance::copyImagesToBuffers					(IterateCommonVariables&					variables)
{
	const deUint32 infoCount = static_cast<deUint32>(variables.descriptorsBufferInfos.size());
	DE_ASSERT(variables.descriptorsImages.size() == infoCount);
	const VkPipelineStageFlagBits srcStageMask = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT)
		? VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT
		: VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT;

	for (deUint32 infoIdx = 0; infoIdx < infoCount; ++infoIdx)
	{
		ut::recordCopyImageToBuffer(
			*variables.commandBuffer,						// commandBuffer
			m_vki,											// interface
			srcStageMask,									// srcStageMask
			VK_PIPELINE_STAGE_HOST_BIT,						// dstStageMask
			*(variables.descriptorsImages[infoIdx]->image),	// image
			variables.descriptorsImages[infoIdx]->extent,	// imageExtent
			variables.descriptorsImages[infoIdx]->format,	// imageFormat
			VK_IMAGE_LAYOUT_GENERAL,						// oldImageLayout
			VK_IMAGE_LAYOUT_GENERAL,						// newImageLayout
			variables.descriptorsBufferInfos[infoIdx]);		// bufferInfo
	}
}

PixelBufferAccess CommonDescriptorInstance::getPixelAccess			(deUint32									imageIndex,
																	 const VkExtent3D&							imageExtent,
																	 VkFormat									imageFormat,
																	 const std::vector<VkDescriptorBufferInfo>&	bufferInfos,
																	 const ut::BufferHandleAllocSp&				buffer,
																	 deUint32									mipLevel) const
{
	DE_ASSERT(bufferInfos[imageIndex].buffer == *buffer.get()->buffer);
	DE_ASSERT(ut::computeImageSize(imageExtent, imageFormat, true, (mipLevel ? ut::maxDeUint32 : 0)) <= bufferInfos[imageIndex].range);
	DE_ASSERT(imageExtent.width		>> mipLevel);
	DE_ASSERT(imageExtent.height	>> mipLevel);

	deUint32 mipOffset = 0;

	for (deUint32 level = 0; mipLevel && level < mipLevel; ++level)
	{
		mipOffset += ut::computeImageSize(imageExtent, imageFormat, true, level);
	}

	unsigned char* hostPtr	= static_cast<unsigned char*>(buffer->alloc->getHostPtr());
	unsigned char* data = hostPtr + bufferInfos[imageIndex].offset + mipOffset;
	return tcu::PixelBufferAccess(vk::mapVkFormat(imageFormat), (imageExtent.width >> mipLevel), (imageExtent.height >> mipLevel), imageExtent.depth, data);
}


void CommonDescriptorInstance::updateDescriptors					(IterateCommonVariables&					variables)
{
	const std::vector<deUint32>	primes = ut::generatePrimes(variables.availableDescriptorCount);
	const deUint32				primeCount = static_cast<deUint32>(primes.size());

	for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx)
	{
		const VkDescriptorBufferInfo*	pBufferInfo			= DE_NULL;
		const VkDescriptorImageInfo*	pImageInfo			= DE_NULL;
		const VkBufferView*				pTexelBufferView	= DE_NULL;


		VkDescriptorImageInfo		imageInfo =
		{
			static_cast<VkSampler>(0),
			static_cast<VkImageView>(0),
			VK_IMAGE_LAYOUT_GENERAL
		};

		switch (m_testParams.descriptorType)
		{
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			{
				pBufferInfo = &variables.descriptorsBufferInfos[primeIdx];
				switch (m_testParams.descriptorType)
				{
				case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
				case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
					pTexelBufferView = &(**variables.descriptorsBufferViews[primeIdx]);
					break;
				default:
					break;
				}
			}
			break;

		case VK_DESCRIPTOR_TYPE_SAMPLER:
			imageInfo.sampler = **variables.descriptorSamplers[primeIdx];
			pImageInfo = &imageInfo;
			break;

		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			imageInfo.imageView = **variables.descriptorImageViews[primeIdx];
			pImageInfo = &imageInfo;
			break;

		default:	break;
		}

		const VkWriteDescriptorSet writeInfo =
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// sType
			DE_NULL,										// pNext
			*variables.descriptorSet,						// descriptorSet
			m_testParams.descriptorBinding,					// descriptorBinding;
			primes[primeIdx],								// elementIndex
			1u,												// descriptorCount
			m_testParams.descriptorType,					// descriptorType
			pImageInfo,										// pImageInfo
			pBufferInfo,									// pBufferInfo
			pTexelBufferView								// pTexelBufferView
		};

		m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
	}
}

void CommonDescriptorInstance::iterateCommandBegin					(IterateCommonVariables&					variables)
{
	variables.dataAlignment				= 0;

	variables.renderArea.offset.x		= 0;
	variables.renderArea.offset.y		= 0;
	variables.renderArea.extent.width	= m_testParams.frameResolution.width;
	variables.renderArea.extent.height	= m_testParams.frameResolution.height;

	variables.vertexCount				= m_testParams.frameResolution.width * m_testParams.frameResolution.height;

	variables.lowerBound				= 0;
	variables.upperBound				= variables.vertexCount;

	variables.descriptorSetLayout		= createDescriptorSetLayout(variables.availableDescriptorCount);
	variables.validDescriptorCount		= ut::computePrimeCount(variables.availableDescriptorCount);
	variables.descriptorPool			= createDescriptorPool(variables.availableDescriptorCount);
	variables.descriptorSet				= createDescriptorSet(*variables.descriptorPool, *variables.descriptorSetLayout);

	std::vector<VkDescriptorSetLayout>	descriptorSetLayouts;
	descriptorSetLayouts.push_back(*variables.descriptorSetLayout);
	if (m_testParams.calculateInLoop)
	{
		variables.descriptorEnumerator.init(m_context, variables.vertexCount, variables.availableDescriptorCount);
		descriptorSetLayouts.push_back(*variables.descriptorEnumerator.descriptorSetLayout);
	}

	variables.pipelineLayout			= createPipelineLayout(descriptorSetLayouts);

	createAndPopulateDescriptors		(variables);

	variables.renderPass				= createRenderPass(variables);
	variables.pipeline					= createPipeline(*variables.pipelineLayout, *variables.renderPass);

	variables.commandBuffer				= createCmdBuffer();

	if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
	{
		createVertexAttributeBuffer		(variables.vertexAttributesBuffer, variables.availableDescriptorCount);
		createFramebuffer				(variables.frameBuffer, *variables.renderPass, variables);
	}

	if (m_testParams.calculateInLoop)
	{
		variables.descriptorEnumerator.update(m_context);
	}

	if (!m_testParams.updateAfterBind)
	{
		updateDescriptors				(variables);
	}

	vk::beginCommandBuffer				(m_vki, *variables.commandBuffer);

	if (m_testParams.calculateInLoop)
	{
		deRandom rnd;
		deRandom_init(&rnd, static_cast<deUint32>(m_testParams.descriptorType));
		const deUint32 quarter = variables.vertexCount / 4;

		variables.lowerBound			= deRandom_getUint32(&rnd) % quarter;
		variables.upperBound			= (deRandom_getUint32(&rnd) % quarter) + (3 * quarter);

		const push_constant pc =
		{
			static_cast<deInt32>(variables.lowerBound),
			static_cast<deInt32>(variables.upperBound)
		};

		m_vki.cmdPushConstants(*variables.commandBuffer, *variables.pipelineLayout, m_testParams.stageFlags, 0u, static_cast<deUint32>(sizeof(pc)), &pc);
	}

	if ((m_testParams.stageFlags & VK_SHADER_STAGE_VERTEX_BIT) || (m_testParams.stageFlags & VK_SHADER_STAGE_FRAGMENT_BIT))
	{
		commandBindVertexAttributes		(*variables.commandBuffer, variables.vertexAttributesBuffer);
	}

	if (m_testParams.calculateInLoop)
	{
		commandBindDescriptorSets(*variables.commandBuffer, *variables.pipelineLayout, *variables.descriptorEnumerator.descriptorSet, 1);
	}

	if (!ut::isDynamicDescriptor(m_testParams.descriptorType))
	{
		commandBindDescriptorSets		(*variables.commandBuffer, *variables.pipelineLayout, *variables.descriptorSet, 0);
	}

	commandBindPipeline					(*variables.commandBuffer, *variables.pipeline);
}

tcu::TestStatus	CommonDescriptorInstance::iterate					(void)
{
	IterateCommonVariables	v;
	iterateCommandBegin		(v);

	if (true == m_testParams.copyBuffersToImages)
	{
		copyBuffersToImages	(v);
	}

	if (true == m_testParams.updateAfterBind)
	{
		updateDescriptors	(v);
	}

	vk::beginRenderPass		(m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea, m_clearColor);
	m_vki.cmdDraw			(*v.commandBuffer, v.vertexCount, 1u, 0u, 0u);
	vk::endRenderPass		(m_vki, *v.commandBuffer);

	return (iterateCommandEnd(v) ? tcu::TestStatus::pass : tcu::TestStatus::fail)("");
}

std::vector<float> CommonDescriptorInstance::createColorScheme		(void)
{
	std::vector<float> cs;
	int divider = 2;
	for (int i = 0; i < 10; ++i)
	{
		cs.push_back(1.0f / float(divider));
		divider *= 2;
	}
	return cs;
}

bool CommonDescriptorInstance::iterateCommandEnd					(IterateCommonVariables&					variables,
																	 bool										collectBeforeSubmit)
{
	ut::UpdatablePixelBufferAccessPtr	programResult;
	ut::UpdatablePixelBufferAccessPtr	referenceResult;

	if (collectBeforeSubmit)
	{
		iterateCollectResults(programResult, variables, true);
		iterateCollectResults(referenceResult, variables, false);
	}

	VK_CHECK(m_vki.endCommandBuffer(*variables.commandBuffer));
	Move<VkFence> fence = commandSubmit(*variables.commandBuffer);
	m_vki.waitForFences(m_vkd, 1, &(*fence), DE_TRUE, ~0ull);

	if (false == collectBeforeSubmit)
	{
		iterateCollectResults(programResult, variables, true);
		iterateCollectResults(referenceResult, variables, false);
	}

	bool result = false;
	if (m_testParams.fuzzyComparison)
	{
		result = tcu::fuzzyCompare(m_context.getTestContext().getLog(),
			"Fuzzy Compare", "Comparison result", *referenceResult.get(), *programResult.get(), 0.02f, tcu::COMPARE_LOG_EVERYTHING);
	}
	else
	{
		result = tcu::floatThresholdCompare(m_context.getTestContext().getLog(),
			"Float Threshold Compare", "Comparison result", *referenceResult.get(), *programResult.get(), tcu::Vec4(0.02f, 0.02f, 0.02f, 0.02f), tcu::COMPARE_LOG_EVERYTHING);
	}

	if (m_testParams.allowVertexStoring)
	{
		result = verifyVertexWriteResults(variables);
	}

	return result;
}

void CommonDescriptorInstance::iterateCollectResults				(ut::UpdatablePixelBufferAccessPtr&			result,
																	 const IterateCommonVariables&				variables,
																	 bool										fromTest)
{
	if (fromTest)
	{
		result = commandReadFrameBuffer(*variables.commandBuffer, variables.frameBuffer);
	}
	else
	{
		result = ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessAllocation(vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution));

		for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
		{
			for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
			{
				const float component = m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize];
				result->setPixel(tcu::Vec4(component, component, component, 1.0f), x, y);
			}
		}
	}
}

Move<VkCommandBuffer> CommonDescriptorInstance::createCmdBuffer		(void)
{
	return vk::allocateCommandBuffer(m_vki, m_vkd, *m_commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
}

Move<VkFence> CommonDescriptorInstance::commandSubmit				(VkCommandBuffer							cmd)
{
	Move<VkFence>	fence(vk::createFence(m_vki, m_vkd));

	const VkSubmitInfo	submitInfo =
	{
		VK_STRUCTURE_TYPE_SUBMIT_INFO,						// sType
		DE_NULL,											// pNext
		0u,													// waitSemaphoreCount
		static_cast<VkSemaphore*>(DE_NULL),					// pWaitSemaphores
		static_cast<const VkPipelineStageFlags*>(DE_NULL),	// pWaitDstStageMask
		1u,													// commandBufferCount
		&cmd,												// pCommandBuffers
		0u,													// signalSemaphoreCount
		static_cast<VkSemaphore*>(DE_NULL)					// pSignalSemaphores
	};

	VK_CHECK(m_vki.queueSubmit(m_queue, 1u, &submitInfo, *fence));

	return fence;
}

bool CommonDescriptorInstance::verifyVertexWriteResults(IterateCommonVariables&					variables)
{
	DE_UNREF(variables);
	return true;
}

void CommonDescriptorInstance::commandBindPipeline					(VkCommandBuffer							commandBuffer,
																	 VkPipeline									pipeline)
{
	const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
	m_vki.cmdBindPipeline(commandBuffer, pipelineBindingPoint, pipeline);
}

void CommonDescriptorInstance::commandBindVertexAttributes			(VkCommandBuffer							commandBuffer,
																	 const ut::BufferHandleAllocSp&				vertexAttributesBuffer)
{
	const VkDeviceSize	offsets[] = { 0u };
	const VkBuffer		buffers[] = { *vertexAttributesBuffer->buffer };
	m_vki.cmdBindVertexBuffers(commandBuffer, 0u, 1u, buffers, offsets);
}

void CommonDescriptorInstance::commandBindDescriptorSets			(VkCommandBuffer							commandBuffer,
																	 VkPipelineLayout							pipelineLayout,
																	 VkDescriptorSet							descriptorSet,
																	 deUint32									descriptorSetIndex)
{
	const VkPipelineBindPoint pipelineBindingPoint = (m_testParams.stageFlags & VK_SHADER_STAGE_COMPUTE_BIT) ? VK_PIPELINE_BIND_POINT_COMPUTE : VK_PIPELINE_BIND_POINT_GRAPHICS;
	m_vki.cmdBindDescriptorSets(commandBuffer, pipelineBindingPoint, pipelineLayout, descriptorSetIndex, 1u, &descriptorSet, 0u, static_cast<deUint32*>(DE_NULL));
}

ut::UpdatablePixelBufferAccessPtr
CommonDescriptorInstance::commandReadFrameBuffer					(VkCommandBuffer							commandBuffer,
																	 const ut::FrameBufferSp&					frameBuffer)
{
	ut::BufferHandleAllocSp frameBufferContent;
	commandReadFrameBuffer(frameBufferContent, commandBuffer, frameBuffer);
	return ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessBuffer(
		m_vkd, m_vki, vk::mapVkFormat(m_colorFormat), m_testParams.frameResolution,
		de::SharedPtr< Move<VkBuffer> >(new Move<VkBuffer>(frameBufferContent->buffer)),
		de::SharedPtr< de::MovePtr<Allocation> >(new de::MovePtr<Allocation>(frameBufferContent->alloc))));
}

void CommonDescriptorInstance::commandReadFrameBuffer				(ut::BufferHandleAllocSp&					content,
																	 VkCommandBuffer							commandBuffer,
																	 const ut::FrameBufferSp&					frameBuffer)
{
	Move<VkBuffer>			buffer;
	de::MovePtr<Allocation>	allocation;

	const VkDeviceSize bufferSize = ut::computeImageSize(frameBuffer->image);

	// create a buffer and an host allocation for it
	{
		const VkBufferCreateInfo bufferCreateInfo =
		{
			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,		// sType
			DE_NULL,									// pNext
			0u,											// flags
			bufferSize,									// size
			VK_BUFFER_USAGE_TRANSFER_DST_BIT,			// usage
			VK_SHARING_MODE_EXCLUSIVE,					// sharingMode
			1u,											// queueFamilyIndexCoun
			&m_queueFamilyIndex							// pQueueFamilyIndices
		};

		buffer = vk::createBuffer(m_vki, m_vkd, &bufferCreateInfo);
		const VkMemoryRequirements	memRequirements(vk::getBufferMemoryRequirements(m_vki, m_vkd, *buffer));
		allocation = m_allocator.allocate(memRequirements, MemoryRequirement::HostVisible);

		VK_CHECK(m_vki.bindBufferMemory(m_vkd, *buffer, allocation->getMemory(), allocation->getOffset()));
	}

	const VkImage& image = *frameBuffer->image->image;

	VkImageSubresourceRange		subresourceRange =
	{
		VK_IMAGE_ASPECT_COLOR_BIT,					// aspectMask
		0u,											// baseMipLevel
		1u,											// levelCount
		0u,											// baseArrayLayer
		1u											// layerCount
	};

	const VkImageMemoryBarrier	barrierBefore =
	{
		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType;
		DE_NULL,									// pNext;
		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// srcAccessMask;
		VK_ACCESS_TRANSFER_READ_BIT,				// dstAccessMask;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// oldLayout
		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// newLayout;
		VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex;
		VK_QUEUE_FAMILY_IGNORED,					// dstQueueFamilyIndex;
		image,										// image;
		subresourceRange							// subresourceRange;
	};

	const VkBufferImageCopy		copyRegion =
	{
		0u,											// bufferOffset
		frameBuffer->image->extent.width,				// bufferRowLength
		frameBuffer->image->extent.height,			// bufferImageHeight
		{											// VkImageSubresourceLayers
			VK_IMAGE_ASPECT_COLOR_BIT,				// aspect
			0u,										// mipLevel
			0u,										// baseArrayLayer
			1u,										// layerCount
		},
		{ 0, 0, 0 },								// imageOffset
		frameBuffer->image->extent					// imageExtent
	};

	const VkBufferMemoryBarrier	bufferBarrier =
	{
		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// sType;
		DE_NULL,									// pNext;
		VK_ACCESS_TRANSFER_WRITE_BIT,				// srcAccessMask;
		VK_ACCESS_HOST_READ_BIT,					// dstAccessMask;
		VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex;
		VK_QUEUE_FAMILY_IGNORED,					// dstQueueFamilyIndex;
		*buffer,									// buffer;
		0u,											// offset;
		bufferSize									// size;
	};

	const VkImageMemoryBarrier	barrierAfter =
	{
		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// sType;
		DE_NULL,										// pNext;
		VK_ACCESS_TRANSFER_READ_BIT,					// srcAccessMask;
		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// dstAccessMask;
		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,			// oldLayout;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// newLayout;
		VK_QUEUE_FAMILY_IGNORED,						// srcQueueFamilyIndex;
		VK_QUEUE_FAMILY_IGNORED,						// dstQueueFamilyIndex;
		image,											// image
		subresourceRange								// subresourceRange
	};


	m_vki.cmdPipelineBarrier(commandBuffer,												// commandBuffer
		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT,	// srcStageMask, dstStageMask
		(VkDependencyFlags)0,															// dependencyFlags
		0u, DE_NULL,																	// memoryBarrierCount, pMemoryBarriers
		0u, DE_NULL,																	// bufferBarrierCount, pBufferBarriers
		1u, &barrierBefore);																// imageBarrierCount, pImageBarriers

	m_vki.cmdCopyImageToBuffer(commandBuffer, image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *buffer, 1u, &copyRegion);

	m_vki.cmdPipelineBarrier(commandBuffer,
		VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT | VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT,
		(VkDependencyFlags)0,
		0u, DE_NULL,
		1u, &bufferBarrier,
		1u, &barrierAfter);

	content = ut::BufferHandleAllocSp(new ut::BufferHandleAlloc(buffer, allocation));
}

std::string CommonDescriptorInstance::getColorAccess				(VkDescriptorType							descriptorType,
																	 const char*								indexVariableName,
																	 bool										usesMipMaps)
{
	std::string text;
	std::map<std::string, std::string> vars;
	vars["INDEX"] = indexVariableName;

	switch (descriptorType)
	{
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
	case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
		text = "data[nonuniformEXT(${INDEX})].c";
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
		text = "data[nonuniformEXT(${INDEX})].cold";
		break;
	case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
		text = "subpassLoad(data[nonuniformEXT(${INDEX})]).rgba";
		break;
	case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
		text = "texelFetch(data[nonuniformEXT(${INDEX})], 0)";
		break;
	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		text = "imageLoad(data[nonuniformEXT(${INDEX})], 0)";
		break;
	case VK_DESCRIPTOR_TYPE_SAMPLER:
		text = usesMipMaps
			? "textureLod(sampler2D(tex[0], data[nonuniformEXT(${INDEX})]), normalpos, 1)"
			: "texture(   sampler2D(tex[0], data[nonuniformEXT(${INDEX})]), normalpos   )";
		break;
	case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		text = usesMipMaps
			? "textureLod( sampler2D(data[nonuniformEXT(${INDEX})], samp[0]), vec2(0,0), textureQueryLevels(sampler2D(data[nonuniformEXT(${INDEX})], samp[0]))-1)"
			: "texture(    sampler2D(data[nonuniformEXT(${INDEX})], samp[0]), vec2(0,0)   )";
		break;
	case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
		text = usesMipMaps
			? "textureLod( data[nonuniformEXT(${INDEX})], uvec2(0,0), textureQueryLevels(data[nonuniformEXT(${INDEX})])-1)"
			: "texture(    data[nonuniformEXT(${INDEX})], uvec2(0,0)   )";
		break;
	default:
		TCU_THROW(InternalError, "Not implemented descriptor type");
	}

	return tcu::StringTemplate(text).specialize(vars);
}

std::string CommonDescriptorInstance::getFragmentReturnSource		(const std::string&							colorAccess)
{
	return "  FragColor = " + colorAccess + ";\n";
}

std::string CommonDescriptorInstance::getFragmentLoopSource			(const std::string&							colorAccess1,
																	 const std::string&							colorAccess2)
{
	std::map < std::string, std::string > vars;
	vars["COLOR_ACCESS_1"] = colorAccess1;
	vars["COLOR_ACCESS_2"] = colorAccess2;

	const char* s =
		"  vec4 sumClr1 = vec4(0,0,0,0);		\n"
		"  vec4 sumClr2 = vec4(0,0,0,0);		\n"
		"  for (int i = pc.lowerBound; i < pc.upperBound; ++i)	\n"
		"  {\n"
		"    int loopIdx = texelFetch(iter, i).x;				\n"
		"    sumClr1 += ${COLOR_ACCESS_2} + ${COLOR_ACCESS_1};	\n"
		"    sumClr2 += ${COLOR_ACCESS_2};						\n"
		"  }\n"
		"  FragColor = vec4(((sumClr1 - sumClr2) / float(pc.upperBound - pc.lowerBound)).rgb, 1);	\n";

	return tcu::StringTemplate(s).specialize(vars);
}

bool CommonDescriptorInstance::performWritesInVertex				(VkDescriptorType							descriptorType)
{
	bool result = false;

	switch (descriptorType)
	{
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
	case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
	case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
		result = true;
		break;
	default:
		result = false;
		break;
	}

	return result;
}

std::string CommonDescriptorInstance::getShaderSource				(VkShaderStageFlagBits						shaderType,
																	 const TestCaseParams&						testCaseParams,
																	 bool										allowVertexStoring)
{
	std::stringstream	s;

	s << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << '\n';
	s << "#extension GL_EXT_nonuniform_qualifier : require	\n";

	if (testCaseParams.calculateInLoop)
	{
		s << "layout(push_constant)     uniform Block { int lowerBound, upperBound; } pc;\n";
		s << substBinding(BINDING_DescriptorEnumerator,
			"layout(set=1,binding=${?}) uniform isamplerBuffer iter;	\n");
	}

	switch (testCaseParams.descriptorType)
	{
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
			s << substBinding(BINDING_StorageBuffer,
				"layout(set=0,binding=${?}) buffer Data { vec4 cnew, cold; } data[]; \n");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			s << substBinding(BINDING_StorageBufferDynamic,
				"layout(set=0,binding=${?}) buffer Data { vec4 cnew, cold; } data[]; \n");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
			s << substBinding(BINDING_UniformBuffer,
				"layout(set=0,binding=${?}) uniform Data { vec4 c; } data[]; \n");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
			s << substBinding(BINDING_UniformBufferDynamic,
				"layout(set=0,binding=${?}) uniform Data { vec4 c; } data[]; \n");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
			s << substBinding(BINDING_StorageTexelBuffer,
				"layout(set=0,binding=${?},rgba32f) uniform imageBuffer data[];\n");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			s << "#extension GL_EXT_texture_buffer : require	\n";
			s << substBinding(BINDING_UniformTexelBuffer,
				"layout(set=0,binding=${?}) uniform samplerBuffer data[];\n");
			break;
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			// Left for the consistent of code.
			// Header is set one swicth below
			break;
		case VK_DESCRIPTOR_TYPE_SAMPLER:
			s << "#extension GL_EXT_texture_buffer : require	\n";
			s << substBinding(BINDING_SampledImage,
				"layout(set=0,binding=${?}) uniform texture2D ${VAR}[${*}];\n", 1, "tex");
			s << substBinding(BINDING_Sampler,
				"layout(set=0,binding=${?}) uniform sampler ${VAR}[${*}];\n");
			break;
		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
			s << "#extension GL_EXT_texture_buffer : require	\n";
			s << substBinding(BINDING_Sampler,
				"layout(set=0,binding=${?}) uniform sampler ${VAR}[${*}];\n", 1, "samp");
			s << substBinding(BINDING_SampledImage,
				"layout(set=0,binding=${?}) uniform texture2D ${VAR}[${*}];\n");
			break;
		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
			s << "#extension GL_EXT_texture_buffer : require	\n";
			s << substBinding(BINDING_CombinedImageSampler,
				"layout(set=0,binding=${?}) uniform sampler2D data[];\n");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
			s << "layout(local_size_x=1,local_size_y=1,local_size_z=1) in;	\n";
			s << substBinding(BINDING_StorageImage + 1,
				"layout(r32ui,set=0,binding=${?}) uniform uimage2D idxs;	\n");
			s << substBinding(BINDING_StorageImage,
				"layout(r32ui,set=0,binding=${?}) uniform uimage2D data[];	\n");
			break;
		default:
			TCU_THROW(InternalError, "Not implemented descriptor type");
	}

	switch (shaderType)
	{
		case VK_SHADER_STAGE_VERTEX_BIT:	s << getVertexShaderProlog();	break;
		case VK_SHADER_STAGE_FRAGMENT_BIT:
			{
				if (testCaseParams.descriptorType == VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
				{
					s << substBinding(BINDING_InputAttachment,
						"layout(input_attachment_index=1,set=0,binding=${?}) uniform subpassInput data[];	\n");
				}
				s << getFragmentShaderProlog();
			}
			break;
		case VK_SHADER_STAGE_COMPUTE_BIT:
			break;
		default:
			TCU_THROW(InternalError, "Not implemented shader stage");
	}

	switch (shaderType)
	{
		case VK_SHADER_STAGE_VERTEX_BIT:
		{
			switch (testCaseParams.descriptorType)
			{
			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
				if (allowVertexStoring)
					s << "  if (gIndex != 0) data[nonuniformEXT(gIndex)].cnew = data[nonuniformEXT(rIndex)].cold;	\n";
				break;
			case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
				if (allowVertexStoring)
					s << "  if (gIndex != 0) imageStore(data[nonuniformEXT(gIndex)], 1, imageLoad(data[nonuniformEXT(rIndex)], 0));	\n";
				break;
			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
			case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			case VK_DESCRIPTOR_TYPE_SAMPLER:
			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
				break;

			default:
				TCU_THROW(InternalError, "Not implemented descriptor type");
			}
		}
		break;

		case VK_SHADER_STAGE_FRAGMENT_BIT:
		{
			switch (testCaseParams.descriptorType)
			{
			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
			case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
				{
					if (testCaseParams.calculateInLoop)
						s << getFragmentLoopSource(
							getColorAccess(testCaseParams.descriptorType, "rIndex", false),
							getColorAccess(testCaseParams.descriptorType, "loopIdx", false));
					else
						s << getFragmentReturnSource(getColorAccess(testCaseParams.descriptorType, "rIndex", false));
				}
				break;
			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
			case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
			case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			case VK_DESCRIPTOR_TYPE_SAMPLER:
			case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
			case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
				if (testCaseParams.calculateInLoop)
					s << getFragmentLoopSource(
						getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps),
						getColorAccess(testCaseParams.descriptorType, "loopIdx", testCaseParams.usesMipMaps));
				else
					s << getFragmentReturnSource(getColorAccess(testCaseParams.descriptorType, "rIndex", testCaseParams.usesMipMaps));
				break;
			default:	TCU_THROW(InternalError, "Not implemented descriptor type");
			}
		}
		break;

		case VK_SHADER_STAGE_COMPUTE_BIT: // VK_DESCRIPTOR_TYPE_STORAGE_IMAGE
			s << "void main(void)\n{\n";
			if (testCaseParams.calculateInLoop)
				s << "  for (int i = pc.lowerBound; i < pc.upperBound; ++i)	\n"
					"    imageAtomicAdd(data[nonuniformEXT(texelFetch(iter, i).x)], ivec2(0, 0), 1);			\n";
			else
				s << "  uvec4 c = imageLoad(idxs, ivec2(gl_WorkGroupID.x, gl_WorkGroupID.y));	\n"
					"  imageAtomicAdd( data[nonuniformEXT(c.r)], ivec2(0, 0), 1);								\n";
			break;

		default:	TCU_THROW(InternalError, "Not implemented shader stage");
	}

	s << getShaderEpilog();

	return s.str();
}

class StorageBufferInstance : virtual public CommonDescriptorInstance
{
public:
								StorageBufferInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
protected:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);

	virtual bool				verifyVertexWriteResults			(IterateCommonVariables&					variables);
};

StorageBufferInstance::StorageBufferInstance						(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
			BINDING_StorageBuffer,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void StorageBufferInstance::createAndPopulateDescriptors			(IterateCommonVariables&					variables)
{
	BindingStorageBuffer::Data	data;

	bool						vertexStores = false;
	{
		ut::DeviceProperties dp(m_context);
		vertexStores = dp.physicalDeviceFeatures().vertexPipelineStoresAndAtomics != DE_FALSE;
	}
	const deUint32				alignment	= static_cast<deUint32>(ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minStorageBufferOffsetAlignment);
	createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, sizeof(data), alignment, VK_BUFFER_USAGE_STORAGE_BUFFER_BIT);

	unsigned char*				buffer		= static_cast<unsigned char*>(variables.descriptorsBuffer->alloc->getHostPtr());
	for (deUint32 infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx)
	{
		const float				component	= m_colorScheme[infoIdx % m_schemeSize];
		const tcu::Vec4			color		(component, component, component, 1.0f);
		VkDescriptorBufferInfo& info		= variables.descriptorsBufferInfos[infoIdx];
		data.cnew							= vertexStores ? m_clearColor : color;
		data.cold							= color;

		deMemcpy(buffer + info.offset, &data, sizeof(data));
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);

	variables.dataAlignment = deAlign64(sizeof(data), alignment);
}

bool StorageBufferInstance::verifyVertexWriteResults				(IterateCommonVariables&					variables)
{
	const tcu::Vec4				threshold		(0.002f, 0.002f, 0.002f, 0.002f);
	const std::vector<deUint32>	primes			= ut::generatePrimes(variables.availableDescriptorCount);

	unsigned char*				buffer = static_cast<unsigned char*>(variables.descriptorsBuffer->alloc->getHostPtr());
	BindingStorageBuffer::Data	data;
	for (deUint32 primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx)
	{
		const deUint32			prime		= primes[primeIdx];
		const float				component	= m_colorScheme[(prime % variables.validDescriptorCount) % m_schemeSize];
		const tcu::Vec4			referenceValue(component, component, component, 1.0f);

		VkDescriptorBufferInfo& info = variables.descriptorsBufferInfos[primeIdx];
		deMemcpy(&data, buffer + info.offset, sizeof(data));
		const tcu::Vec4			realValue = data.cnew;

		const tcu::Vec4			diff = tcu::absDiff(referenceValue, realValue);
		if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold)))
			return false;
	}
	return true;
}

class UniformBufferInstance : virtual public CommonDescriptorInstance
{
public:
								UniformBufferInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
protected:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
};

UniformBufferInstance::UniformBufferInstance						(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
			BINDING_UniformBuffer,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void UniformBufferInstance::createAndPopulateDescriptors			(IterateCommonVariables&					variables)
{
	BindingUniformBuffer::Data data;

	const deUint32				alignment	= static_cast<deUint32>(ut::DeviceProperties(m_context).physicalDeviceProperties().limits.minUniformBufferOffsetAlignment);
	createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, sizeof(data), alignment, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);

	unsigned char*				buffer		= static_cast<unsigned char*>(variables.descriptorsBuffer->alloc->getHostPtr());
	for (deUint32 infoIdx = 0; infoIdx < variables.validDescriptorCount; ++infoIdx)
	{
		const float				component	= m_colorScheme[infoIdx % m_schemeSize];
		VkDescriptorBufferInfo& info		= variables.descriptorsBufferInfos[infoIdx];
		data.c								= tcu::Vec4(component, component, component, 1.0f);
		deMemcpy(buffer + info.offset, &data, sizeof(data));
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);

	variables.dataAlignment = deAlign64(sizeof(data), alignment);
}

class StorageTexelInstance : public CommonDescriptorInstance
{
public:
								StorageTexelInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);

	virtual bool				verifyVertexWriteResults			(IterateCommonVariables&					variables);
};

StorageTexelInstance::StorageTexelInstance							(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
			BINDING_StorageTexelBuffer,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void StorageTexelInstance::createAndPopulateDescriptors			(IterateCommonVariables&					variables)
{
	const VkExtent3D			imageExtent			= { 4, 4, 1 };
	const deUint32				imageSize			= ut::computeImageSize(imageExtent, m_colorFormat);

	createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_STORAGE_TEXEL_BUFFER_BIT);
	createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat);

	for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
	{
		const float				component			= m_colorScheme[imageIdx % m_schemeSize];
		const PixelBufferAccess pa					= getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer);

		tcu::clear(pa, m_clearColor);
		pa.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
}

bool StorageTexelInstance::verifyVertexWriteResults(IterateCommonVariables&					variables)
{
	const VkExtent3D			imageExtent		= { 4, 4, 1 };
	const tcu::Vec4				threshold		(0.002f, 0.002f, 0.002f, 0.002f);
	const std::vector<deUint32>	primes			= ut::generatePrimes(variables.availableDescriptorCount);

	for (deUint32 primeIdx = 0; primeIdx < variables.validDescriptorCount; ++primeIdx)
	{
		const deUint32			prime		= primes[primeIdx];
		const float				component	= m_colorScheme[( prime % variables.validDescriptorCount ) % m_schemeSize];
		const tcu::Vec4			referenceValue(component, component, component, 1.0f);

		const PixelBufferAccess pa			= getPixelAccess(primeIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer);
		const tcu::Vec4			realValue	= pa.getPixel(1, 0);

		const tcu::Vec4			diff		= tcu::absDiff(referenceValue, realValue);
		if (!tcu::boolAll(tcu::lessThanEqual(diff, threshold)))
			return false;
	}
	return true;
}

class UniformTexelInstance : public CommonDescriptorInstance
{
public:
								UniformTexelInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
};

UniformTexelInstance::UniformTexelInstance							(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
			BINDING_UniformTexelBuffer,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void UniformTexelInstance::createAndPopulateDescriptors				(IterateCommonVariables&					variables)
{
	const VkExtent3D			imageExtent	= { 4, 4, 1 };
	const deUint32				imageSize	= ut::computeImageSize(imageExtent, m_colorFormat);

	createBuffers(variables.descriptorsBufferInfos, variables.descriptorsBuffer, variables.validDescriptorCount, imageSize, sizeof(tcu::Vec4), VK_BUFFER_USAGE_UNIFORM_TEXEL_BUFFER_BIT);
	createBuffersViews(variables.descriptorsBufferViews, variables.descriptorsBufferInfos, m_colorFormat);

	for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
	{
		const float				component	= m_colorScheme[imageIdx % m_schemeSize];
		const PixelBufferAccess	pa			= getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer);

		tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f));
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
}

class DynamicBuffersInstance : virtual public CommonDescriptorInstance
{
public:
	DynamicBuffersInstance											(Context&									context,
																	 const TestParams&							testParams)
		: CommonDescriptorInstance(context, testParams) {}

protected:
	virtual tcu::TestStatus		iterate								(void);
	virtual void				updateDescriptors					(IterateCommonVariables&					variables);
};

void DynamicBuffersInstance::updateDescriptors						(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.dataAlignment);

	VkDescriptorBufferInfo	bufferInfo =
	{
		*variables.descriptorsBuffer.get()->buffer,
		0,	// always 0, it will be taken from pDynamicOffsets
		variables.dataAlignment
	};

	VkWriteDescriptorSet updateInfo =
	{
		VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// sType
		DE_NULL,										// pNext
		*variables.descriptorSet,						// descriptorSet
		m_testParams.descriptorBinding,					// descriptorBinding;
		0,	// to be set in below loop					// dstArrayElement
		1u,												// descriptorCount
		m_testParams.descriptorType,					// descriptorType
		DE_NULL,										// pImageInfo
		&bufferInfo,									// pBufferInfo
		DE_NULL											// pTexelBufferView
	};

	deUint32 descIdx = 0;
	const std::vector<deUint32> primes = ut::generatePrimes(variables.availableDescriptorCount);
	for (deUint32 validIdx = 0; validIdx < variables.validDescriptorCount; ++validIdx)
	{
		for (; descIdx < primes[validIdx]; ++descIdx)
		{
			updateInfo.dstArrayElement			= descIdx;
			m_vki.updateDescriptorSets	(m_vkd, 1u, &updateInfo, 0u, DE_NULL);
		}

		updateInfo.dstArrayElement				= primes[validIdx];
		m_vki.updateDescriptorSets		(m_vkd, 1u, &updateInfo, 0u, DE_NULL);

		++descIdx;
	}
	for (; descIdx < variables.availableDescriptorCount; ++descIdx)
	{
		updateInfo.dstArrayElement = descIdx;
		m_vki.updateDescriptorSets(m_vkd, 1u, &updateInfo, 0u, DE_NULL);
	}
}

tcu::TestStatus	DynamicBuffersInstance::iterate						(void)
{
	IterateCommonVariables	v;
	iterateCommandBegin		(v);

	DE_ASSERT(v.dataAlignment);

	std::vector<deUint32> dynamicOffsets;

	deUint32 descIdx = 0;
	const std::vector<deUint32> primes = ut::generatePrimes(v.availableDescriptorCount);
	for (deUint32 validIdx = 0; validIdx < v.validDescriptorCount; ++validIdx)
	{
		for (; descIdx < primes[validIdx]; ++descIdx)
		{
			dynamicOffsets.push_back(0);
		}

		dynamicOffsets.push_back(static_cast<deUint32>(validIdx * v.dataAlignment));

		++descIdx;
	}
	for (; descIdx < v.availableDescriptorCount; ++descIdx)
	{
		dynamicOffsets.push_back(0);
	}

	// Unfortunatelly not lees and not more, only exactly
	DE_ASSERT(dynamicOffsets.size() == v.availableDescriptorCount);

	const VkDescriptorSet	descriptorSets[] = { *v.descriptorSet };

	m_vki.cmdBindDescriptorSets(
		*v.commandBuffer,						// commandBuffer
		VK_PIPELINE_BIND_POINT_GRAPHICS,		// pipelineBindPoint
		*v.pipelineLayout,						// layout
		0u,										// firstSet
		DE_LENGTH_OF_ARRAY(descriptorSets),		// descriptorSetCount
		descriptorSets,							// pDescriptorSets
		v.availableDescriptorCount,				// dynamicOffsetCount
		dynamicOffsets.data());					// pDynamicOffsets

	vk::beginRenderPass	(m_vki, *v.commandBuffer, *v.renderPass, *v.frameBuffer->buffer, v.renderArea, m_clearColor);
	m_vki.cmdDraw		(*v.commandBuffer, v.vertexCount, 1, 0, 0);
	vk::endRenderPass	(m_vki, *v.commandBuffer);

	return (iterateCommandEnd(v) ? tcu::TestStatus::pass : tcu::TestStatus::fail)("");
}

class DynamicStorageBufferInstance : public DynamicBuffersInstance, public StorageBufferInstance
{
public:
	DynamicStorageBufferInstance									(Context&					context,
																	 const TestCaseParams&		testCaseParams);
	tcu::TestStatus		iterate										(void);
	void				createAndPopulateDescriptors				(IterateCommonVariables&	variables);
	void				updateDescriptors							(IterateCommonVariables&	variables);
	bool				verifyVertexWriteResults					(IterateCommonVariables&	variables);
};

DynamicStorageBufferInstance::DynamicStorageBufferInstance			(Context&					context,
																	 const TestCaseParams&		testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
			BINDING_StorageBufferDynamic,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams)),
			DynamicBuffersInstance(context, m_testParams), StorageBufferInstance(context, testCaseParams)
{
}

tcu::TestStatus	DynamicStorageBufferInstance::iterate(void)
{
	return DynamicBuffersInstance::iterate();
}

void DynamicStorageBufferInstance::createAndPopulateDescriptors(IterateCommonVariables&			variables)
{
	StorageBufferInstance::createAndPopulateDescriptors(variables);
}

void DynamicStorageBufferInstance::updateDescriptors(IterateCommonVariables&					variables)
{
	DynamicBuffersInstance::updateDescriptors(variables);
}

bool DynamicStorageBufferInstance::verifyVertexWriteResults(IterateCommonVariables&				variables)
{
	return StorageBufferInstance::verifyVertexWriteResults(variables);
}

class DynamicUniformBufferInstance : public DynamicBuffersInstance, public UniformBufferInstance
{
public:
	DynamicUniformBufferInstance									(Context&					context,
																	 const TestCaseParams&		testCaseParams);
	tcu::TestStatus		iterate(void);
	void				createAndPopulateDescriptors(IterateCommonVariables&					variables);
	void				updateDescriptors(IterateCommonVariables&								variables);
};

DynamicUniformBufferInstance::DynamicUniformBufferInstance			(Context&					context,
																	 const TestCaseParams&		testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
			BINDING_UniformBufferDynamic,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			false,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams)),
			DynamicBuffersInstance(context, m_testParams), UniformBufferInstance(context, testCaseParams)
{
}

tcu::TestStatus DynamicUniformBufferInstance::iterate(void)
{
	return DynamicBuffersInstance::iterate();
}

void DynamicUniformBufferInstance::createAndPopulateDescriptors(IterateCommonVariables&			variables)
{
	UniformBufferInstance::createAndPopulateDescriptors(variables);
}

void DynamicUniformBufferInstance::updateDescriptors(IterateCommonVariables&					variables)
{
	DynamicBuffersInstance::updateDescriptors(variables);
}

class InputAttachmentInstance : public CommonDescriptorInstance
{
public:
								InputAttachmentInstance				(Context&									context,
																	const TestCaseParams&						testCaseParams);
private:
	virtual Move<VkRenderPass>	createRenderPass					(const IterateCommonVariables&				variables);
	virtual void				createFramebuffer					(ut::FrameBufferSp&							frameBuffer,
																	 VkRenderPass								renderPass,
																	 const IterateCommonVariables&				variables);
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
};

InputAttachmentInstance::InputAttachmentInstance					(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
			BINDING_InputAttachment,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			true,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void InputAttachmentInstance::createAndPopulateDescriptors			(IterateCommonVariables&					variables)
{
	createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
		VK_BUFFER_USAGE_TRANSFER_SRC_BIT, m_testParams.frameResolution, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount);
	createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);

	for (deUint32 descriptorIdx = 0; descriptorIdx < variables.validDescriptorCount; ++descriptorIdx)
	{
		const float						component	= m_colorScheme[descriptorIdx % m_schemeSize];
		const tcu::PixelBufferAccess	pa			= getPixelAccess(descriptorIdx, m_testParams.frameResolution, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer);
		tcu::clear(pa, tcu::Vec4(component, component, component, 1.0f));
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
}

Move<VkRenderPass> InputAttachmentInstance::createRenderPass		(const IterateCommonVariables&				variables)
{
	std::vector<VkAttachmentDescription>	attachmentDescriptions;
	std::vector<VkAttachmentReference>		inputAttachmentRefs;

	const VkAttachmentDescription	colorAttachmentDescription =
	{
		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags;
		m_colorFormat,								// VkFormat							format;
		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					finalLayout;
	};
	const VkAttachmentReference		colorAttachmentRef =
	{
		0u,												// deUint32							attachment;
		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL		// VkImageLayout					layout;
	};
	attachmentDescriptions.push_back(colorAttachmentDescription);

	// build input atachments
	{
		const deUint32 inputCount = static_cast<deUint32>(variables.descriptorImageViews.size());
		for (deUint32 inputIdx = 0; inputIdx < inputCount; ++inputIdx)
		{
			const VkAttachmentDescription	inputAttachmentDescription =
			{
				VK_ATTACHMENT_DESCRIPTION_MAY_ALIAS_BIT,		// VkAttachmentDescriptionFlags		flags;
				variables.descriptorsImages[inputIdx]->format,	// VkFormat							format;
				VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits			samples;
				VK_ATTACHMENT_LOAD_OP_LOAD,						// VkAttachmentLoadOp				loadOp;
				VK_ATTACHMENT_STORE_OP_STORE,					// VkAttachmentStoreOp				storeOp;
				VK_ATTACHMENT_LOAD_OP_DONT_CARE,				// VkAttachmentLoadOp				stencilLoadOp;
				VK_ATTACHMENT_STORE_OP_DONT_CARE,				// VkAttachmentStoreOp				stencilStoreOp;
				VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout					initialLayout;
				VK_IMAGE_LAYOUT_GENERAL							// VkImageLayout					finalLayout;
			};

			const VkAttachmentReference		inputAttachmentRef =
			{
				inputIdx + 1,								// deUint32							attachment;
				VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout					layout;
			};

			inputAttachmentRefs.push_back(inputAttachmentRef);
			attachmentDescriptions.push_back(inputAttachmentDescription);
		}
	}

	const VkSubpassDescription		subpassDescription =
	{
		(VkSubpassDescriptionFlags)0,						// VkSubpassDescriptionFlags		flags;
		VK_PIPELINE_BIND_POINT_GRAPHICS,					// VkPipelineBindPoint				pipelineBindPoint;
		static_cast<deUint32>(inputAttachmentRefs.size()),	// deUint32							inputAttachmentCount;
		inputAttachmentRefs.data(),							// const VkAttachmentReference*		pInputAttachments;
		1u,													// deUint32							colorAttachmentCount;
		&colorAttachmentRef,								// const VkAttachmentReference*		pColorAttachments;
		DE_NULL,											// const VkAttachmentReference*		pResolveAttachments;
		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;
		static_cast<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 vk::createRenderPass(m_vki, m_vkd, &renderPassInfo);
}

void InputAttachmentInstance::createFramebuffer						(ut::FrameBufferSp&							frameBuffer,
																	 VkRenderPass								renderPass,
																	 const IterateCommonVariables&				variables)
{
	std::vector<VkImageView>			inputAttachments;
	const deUint32 viewCount = static_cast<deUint32>(variables.descriptorImageViews.size());
	inputAttachments.resize(viewCount);
	for (deUint32 viewIdx = 0; viewIdx < viewCount; ++viewIdx)
	{
		inputAttachments[viewIdx] = **variables.descriptorImageViews[viewIdx];
	}
	ut::createFrameBuffer(frameBuffer, m_context, m_testParams.frameResolution, m_colorFormat, renderPass, viewCount, inputAttachments.data());
}

class SamplerInstance : public CommonDescriptorInstance
{
public:
								SamplerInstance						(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
	virtual void				updateDescriptors					(IterateCommonVariables&					variables);
};

SamplerInstance::SamplerInstance									(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_SAMPLER,
			BINDING_Sampler,
			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
			BINDING_SampledImage,
			true,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void SamplerInstance::updateDescriptors								(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.descriptorsImages.size()		== 1);
	DE_ASSERT(variables.descriptorImageViews.size()		== 1);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== 1);
	DE_ASSERT(m_testParams.additionalDescriptorType		== VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE);
	DE_ASSERT(variables.descriptorSamplers.size()		== variables.validDescriptorCount);

	// update an image
	{
		const VkDescriptorImageInfo imageInfo =
		{
			static_cast<VkSampler>(0),
			**variables.descriptorImageViews[0],
			VK_IMAGE_LAYOUT_GENERAL
		};

		const VkWriteDescriptorSet writeInfo =
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// sType
			DE_NULL,										// pNext
			*variables.descriptorSet,						// descriptorSet
			BINDING_SampledImage,							// descriptorBinding;
			0,												// elementIndex
			1u,												// descriptorCount
			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,				// descriptorType
			&imageInfo,										// pImageInfo
			DE_NULL,										// pBufferInfo
			DE_NULL											// pTexelBufferView
		};

		m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
	}

	// update samplers
	CommonDescriptorInstance::updateDescriptors(variables);
}

void SamplerInstance::createAndPopulateDescriptors					(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.descriptorsImages.size()		== 0);
	DE_ASSERT(variables.descriptorImageViews.size()		== 0);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== 0);
	DE_ASSERT(variables.descriptorSamplers.size()		== 0);

	// create and populate an image
	{
		VkExtent3D imageExtent = m_testParams.frameResolution;
		if (m_testParams.usesMipMaps)
		{
			imageExtent.width *= 2;
			imageExtent.height *= 2;
		};

		createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
			VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1, m_testParams.usesMipMaps);
		createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);

		PixelBufferAccess pa = getPixelAccess(0, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, m_testParams.usesMipMaps ? 1 : 0);

		for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
		{
			for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
			{
				const float		component	= m_colorScheme[(pixelNum % variables.validDescriptorCount) % m_schemeSize];
				pa.setPixel(tcu::Vec4(component, component, component, 1.0f), x, y);
			}
		}

		vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
	}

	const tcu::Sampler sampler(
		tcu::Sampler::CLAMP_TO_BORDER,															// wrapS
		tcu::Sampler::CLAMP_TO_BORDER,															// wrapT
		tcu::Sampler::CLAMP_TO_BORDER,															// wrapR
		m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// minFilter
		m_testParams.usesMipMaps ? tcu::Sampler::LINEAR_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// magFilter
		0.0f,																					// lodTreshold
		true);																					// normalizeCoords
	const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
	variables.descriptorSamplers.resize(variables.validDescriptorCount);

	for (deUint32 samplerIdx = 0; samplerIdx < variables.validDescriptorCount; ++samplerIdx)
	{
		variables.descriptorSamplers[samplerIdx] = ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo)));
	}
}

class SampledImageInstance : public CommonDescriptorInstance
{
public:
								SampledImageInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
	virtual void				updateDescriptors					(IterateCommonVariables&					variables);
};

SampledImageInstance::SampledImageInstance							(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
			BINDING_SampledImage,
			VK_DESCRIPTOR_TYPE_SAMPLER,
			BINDING_Sampler,
			true,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void SampledImageInstance::updateDescriptors						(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.descriptorSamplers.size()		== 1);
	DE_ASSERT(variables.descriptorsImages.size()		== variables.validDescriptorCount);
	DE_ASSERT(variables.descriptorImageViews.size()		== variables.validDescriptorCount);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== variables.validDescriptorCount);

	// update a sampler
	{
		const VkDescriptorImageInfo samplerInfo =
		{
			**variables.descriptorSamplers[0],
			static_cast<VkImageView>(0),
			static_cast<VkImageLayout>(0)
		};

		const VkWriteDescriptorSet writeInfo =
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// sType
			DE_NULL,										// pNext
			*variables.descriptorSet,						// descriptorSet
			BINDING_Sampler,								// descriptorBinding;
			0,												// elementIndex
			1u,												// descriptorCount
			VK_DESCRIPTOR_TYPE_SAMPLER,						// descriptorType
			&samplerInfo,									// pImageInfo
			DE_NULL,										// pBufferInfo
			DE_NULL											// pTexelBufferView
		};

		m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
	}

	// update images
	CommonDescriptorInstance::updateDescriptors(variables);
}

void SampledImageInstance::createAndPopulateDescriptors				(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.descriptorSamplers.size()		== 0);
	DE_ASSERT(variables.descriptorsImages.size()		== 0);
	DE_ASSERT(variables.descriptorImageViews.size()		== 0);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== 0);

	// create an only one sampler for all images
	{
		const tcu::Sampler sampler(
			tcu::Sampler::CLAMP_TO_BORDER,																// wrapS
			tcu::Sampler::CLAMP_TO_BORDER,																// wrapT
			tcu::Sampler::CLAMP_TO_BORDER,																// wrapR
			m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// minFilter
			m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// magFilter
			0.0f,																						// lodTreshold
			true);																						// normalizeCoords
		const VkSamplerCreateInfo createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
		variables.descriptorSamplers.push_back(ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));
	}

	const VkExtent3D&			imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;

	createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
		VK_BUFFER_USAGE_TRANSFER_SRC_BIT, imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount, m_testParams.usesMipMaps);
	createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);

	PixelBufferAccess			pixelAccess;
	for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
	{
		const float				component	= m_colorScheme[imageIdx % m_schemeSize];

		if (m_testParams.usesMipMaps)
		{
			const deUint32 mipCount = ut::computeMipMapCount(imageExtent);
			DE_ASSERT(mipCount >= 2);
			for (deUint32 mipIdx = 0; mipIdx < mipCount; ++mipIdx)
			{
				pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipIdx);
				tcu::clear(pixelAccess, m_clearColor);
			}

			pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipCount-1);
			pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
		}
		else
		{
			pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, 0);
			pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
		}
	}
	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
}

class CombinedImageInstance : public CommonDescriptorInstance
{
public:
								CombinedImageInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
	virtual void				updateDescriptors					(IterateCommonVariables&					variables);
};

CombinedImageInstance::CombinedImageInstance						(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams(VK_SHADER_STAGE_ALL_GRAPHICS,
			testCaseParams.descriptorType,
			BINDING_CombinedImageSampler,
			VK_DESCRIPTOR_TYPE_UNDEFINED,
			BINDING_Undefined,
			true,
			performWritesInVertex(testCaseParams.descriptorType),
			testCaseParams))
{
}

void CombinedImageInstance::updateDescriptors						(IterateCommonVariables&					variables)
{
	const std::vector<deUint32>	primes = ut::generatePrimes(variables.availableDescriptorCount);
	const deUint32				primeCount = static_cast<deUint32>(primes.size());

	DE_ASSERT(variables.descriptorSamplers.size()		== 1);
	DE_ASSERT(variables.descriptorsImages.size()		== primeCount);
	DE_ASSERT(variables.descriptorImageViews.size()		== primeCount);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== primeCount);

	for (deUint32 primeIdx = 0; primeIdx < primeCount; ++primeIdx)
	{
		const VkDescriptorImageInfo imageInfo =
		{
			**variables.descriptorSamplers[0],
			**variables.descriptorImageViews[primeIdx],
			VK_IMAGE_LAYOUT_GENERAL
		};

		const VkWriteDescriptorSet writeInfo =
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,			// sType
			DE_NULL,										// pNext
			*variables.descriptorSet,						// descriptorSet
			BINDING_CombinedImageSampler,					// descriptorBinding;
			primes[primeIdx],								// elementIndex
			1u,												// descriptorCount
			m_testParams.descriptorType,					// descriptorType
			&imageInfo,										// pImageInfo
			DE_NULL,										// pBufferInfo
			DE_NULL											// pTexelBufferView
		};

		m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
	}
}

void CombinedImageInstance::createAndPopulateDescriptors			(IterateCommonVariables&					variables)
{
	DE_ASSERT(variables.descriptorSamplers.size()		== 0);
	DE_ASSERT(variables.descriptorsImages.size()		== 0);
	DE_ASSERT(variables.descriptorImageViews.size()		== 0);
	DE_ASSERT(variables.descriptorsBufferInfos.size()	== 0);
	DE_ASSERT(variables.descriptorSamplers.size()		== 0);

	const tcu::Sampler sampler(
		tcu::Sampler::CLAMP_TO_BORDER,																// wrapS
		tcu::Sampler::CLAMP_TO_BORDER,																// wrapT
		tcu::Sampler::CLAMP_TO_BORDER,																// wrapR
		m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// minFilter
		m_testParams.usesMipMaps ? tcu::Sampler::NEAREST_MIPMAP_NEAREST : tcu::Sampler::NEAREST,	// magFilter
		0.0f,																						// lodTreshold
		true);																						// normalizeCoords
	const VkSamplerCreateInfo	createInfo = vk::mapSampler(sampler, vk::mapVkFormat(m_colorFormat));
	variables.descriptorSamplers.push_back(ut::SamplerSp(new Move<VkSampler>(vk::createSampler(m_vki, m_vkd, &createInfo))));

	const VkExtent3D&			imageExtent = m_testParams.usesMipMaps ? bigImageExtent : smallImageExtent;
	createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer, VK_BUFFER_USAGE_TRANSFER_SRC_BIT,
		imageExtent, m_colorFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount, m_testParams.usesMipMaps);
	createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, m_colorFormat);

	PixelBufferAccess			pixelAccess;
	for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
	{
		const float				component = m_colorScheme[imageIdx % m_schemeSize];

		if (m_testParams.usesMipMaps)
		{
			const deUint32	mipCount = ut::computeMipMapCount(imageExtent);
			DE_ASSERT(mipCount >= 2);
			for (deUint32 mipIdx = 0; mipIdx < mipCount; ++mipIdx)
			{
				pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipIdx);
				tcu::clear(pixelAccess, m_clearColor);
			}

			pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, mipCount-1);
			pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
		}
		else
		{
			pixelAccess = getPixelAccess(imageIdx, imageExtent, m_colorFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer, 0);
			pixelAccess.setPixel(tcu::Vec4(component, component, component, 1.0f), 0, 0);
		}
	}

	vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
}

class StorageImageInstance : public CommonDescriptorInstance
{
public:
								StorageImageInstance				(Context&									context,
																	 const TestCaseParams&						testCaseParams);
private:
	virtual tcu::TestStatus		iterate								(void);
	virtual void				createAndPopulateDescriptors		(IterateCommonVariables&					variables);
	virtual void				updateDescriptors					(IterateCommonVariables&					variables);
	virtual void				iterateCollectResults				(ut::UpdatablePixelBufferAccessPtr&			result,
																	 const IterateCommonVariables&				variables,
																	 bool										fromTest);
	ut::BufferHandleAllocSp		m_buffer;
	const deUint32				m_fillColor;
	typedef deUint32			m_imageFormat_t;
};

StorageImageInstance::StorageImageInstance							(Context&									context,
																	 const TestCaseParams&						testCaseParams)
	: CommonDescriptorInstance(context,
		TestParams	(VK_SHADER_STAGE_COMPUTE_BIT,
					VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
					BINDING_StorageImage,
					VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
					(BINDING_StorageImage + 1),
					true,
					performWritesInVertex(testCaseParams.descriptorType),
					testCaseParams))
	, m_buffer		()
	, m_fillColor	(10)
{
}

void StorageImageInstance::updateDescriptors						(IterateCommonVariables&					variables)
{
	// update image at last index
	{
		VkDescriptorImageInfo		imageInfo =
		{
			static_cast<VkSampler>(0),
			**variables.descriptorImageViews[variables.validDescriptorCount],
			VK_IMAGE_LAYOUT_GENERAL
		};

		const VkWriteDescriptorSet writeInfo =
		{
			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// sType
			DE_NULL,									// pNext
			*variables.descriptorSet,					// descriptorSet
			m_testParams.additionalDescriptorBinding,	// descriptorBinding;
			0,											// elementIndex
			1u,											// descriptorCount
			m_testParams.additionalDescriptorType,		// descriptorType
			&imageInfo,									// pImageInfo
			DE_NULL,									// pBufferInfo
			DE_NULL										// pTexelBufferView
		};

		m_vki.updateDescriptorSets(m_vkd, 1u, &writeInfo, 0u, DE_NULL);
	}

	// update rest images
	CommonDescriptorInstance::updateDescriptors(variables);
}

void StorageImageInstance::createAndPopulateDescriptors				(IterateCommonVariables&					variables)
{
	const VkFormat				imageFormat = ut::mapType2vkFormat<m_imageFormat_t>::value;
	const VkBufferUsageFlags	bufferUsage = VK_BUFFER_USAGE_STORAGE_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;

	// create descriptor buffer, images and views
	{
		const VkExtent3D			imageExtent = { 4, 4, 1 };

		createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, variables.descriptorsBuffer,
			bufferUsage, imageExtent, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, variables.validDescriptorCount);

		for (deUint32 imageIdx = 0; imageIdx < variables.validDescriptorCount; ++imageIdx)
		{
			const PixelBufferAccess pa = getPixelAccess(imageIdx, imageExtent, imageFormat, variables.descriptorsBufferInfos, variables.descriptorsBuffer);
			tcu::clear(pa, tcu::UVec4(m_fillColor));
		}
		vk::flushAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
	}

	// create additional image that will be used as index container
	{
		createImages(variables.descriptorsImages, variables.descriptorsBufferInfos, m_buffer,
			bufferUsage, m_testParams.frameResolution, imageFormat, VK_IMAGE_LAYOUT_UNDEFINED, 1);

		// populate buffer
		const std::vector<deUint32>	primes = ut::generatePrimes(variables.availableDescriptorCount);
		const PixelBufferAccess pa = getPixelAccess(variables.validDescriptorCount, m_testParams.frameResolution, imageFormat, variables.descriptorsBufferInfos, m_buffer);
		for (deUint32 y = 0, pixel = 0; y < m_testParams.frameResolution.height; ++y)
		{
			for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixel)
			{
				const deUint32 component = primes[pixel % variables.validDescriptorCount];
				pa.setPixel(tcu::UVec4(component), x, y);
			}
		}

		// save changes
		vk::flushAlloc(m_vki, m_vkd, *m_buffer->alloc);
	}

	// create views for all previously created images
	createImagesViews(variables.descriptorImageViews, variables.descriptorsImages, imageFormat);
}

tcu::TestStatus StorageImageInstance::iterate						(void)
{
	IterateCommonVariables	v;
	iterateCommandBegin		(v);

	if (m_testParams.updateAfterBind)
	{
		updateDescriptors	(v);
	}

	copyBuffersToImages		(v);

	m_vki.cmdDispatch		(*v.commandBuffer,
							m_testParams.calculateInLoop ? 1 : v.renderArea.extent.width,
							m_testParams.calculateInLoop ? 1 : v.renderArea.extent.height,
							1);

	copyImagesToBuffers		(v);

	return (iterateCommandEnd(v, false) ? tcu::TestStatus::pass : tcu::TestStatus::fail)("");
}

void StorageImageInstance::iterateCollectResults					(ut::UpdatablePixelBufferAccessPtr&			result,
																	 const IterateCommonVariables&				variables,
																	 bool										fromTest)
{
	result = ut::UpdatablePixelBufferAccessPtr(new ut::PixelBufferAccessAllocation(
		vk::mapVkFormat(ut::mapType2vkFormat<m_imageFormat_t>::value), m_testParams.frameResolution));
	const PixelBufferAccess& dst = *result.get();

	if (fromTest)
	{
		vk::invalidateAlloc(m_vki, m_vkd, *variables.descriptorsBuffer->alloc);
		for (deUint32 y = 0, pixelNum = 0; y < m_testParams.frameResolution.height; ++y)
		{
			for (deUint32 x = 0; x < m_testParams.frameResolution.width; ++x, ++pixelNum)
			{
				const deUint32 imageIdx = pixelNum % variables.validDescriptorCount;
				const PixelBufferAccess src = getPixelAccess(imageIdx,
					variables.descriptorsImages[imageIdx]->extent, variables.descriptorsImages[imageIdx]->format,
					variables.descriptorsBufferInfos, variables.descriptorsBuffer);
				dst.setPixel(tcu::Vector<m_imageFormat_t, 4>(src.getPixelT<m_imageFormat_t>(0, 0).x()), x, y);
			}
		}
	}
	else
	{
		std::vector<m_imageFormat_t> inc(variables.validDescriptorCount, m_fillColor);

		for (deUint32 invIdx = variables.lowerBound; invIdx < variables.upperBound; ++invIdx)
		{
			++inc[invIdx % variables.validDescriptorCount];
		}

		for (deUint32 invIdx = 0; invIdx < variables.vertexCount; ++invIdx)
		{
			const deUint32 row = invIdx / m_testParams.frameResolution.width;
			const deUint32 col = invIdx % m_testParams.frameResolution.width;
			const m_imageFormat_t color = inc[invIdx % variables.validDescriptorCount];
			dst.setPixel(tcu::Vector<m_imageFormat_t, 4>(color), col, row);
		}
	}
}

class DescriptorIndexingTestCase : public TestCase
{
	const TestCaseParams m_testCaseParams;
public:
	DescriptorIndexingTestCase (tcu::TestContext &context, const char *name, const char *description, const TestCaseParams& testCaseParams)
		: TestCase(context, name, description)
		, m_testCaseParams(testCaseParams)
	{
	}

	vkt::TestInstance* createInstance (vkt::Context& context) const // override
	{
		switch (m_testCaseParams.descriptorType)
		{
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
			return new StorageBufferInstance		(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
			return new UniformBufferInstance		(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
			return new StorageTexelInstance			(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			return new UniformTexelInstance			(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			return new DynamicStorageBufferInstance	(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
			return new DynamicUniformBufferInstance	(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			return new InputAttachmentInstance		(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_SAMPLER:
			return new SamplerInstance				(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
			return new SampledImageInstance			(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
			return new CombinedImageInstance		(context, m_testCaseParams);
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
			return new StorageImageInstance			(context, m_testCaseParams);
		default:
			TCU_THROW(InternalError, "Unknown Descriptor Type");
		}
		return DE_NULL;
	}

	virtual void checkSupport (vkt::Context& context) const
	{
		context.requireDeviceExtension("VK_EXT_descriptor_indexing");

		const vk::VkPhysicalDeviceDescriptorIndexingFeaturesEXT& feats = context.getDescriptorIndexingFeatures();

		switch (m_testCaseParams.descriptorType)
		{
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER:
			if (!(feats.shaderStorageBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over storage buffer descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageBufferUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for storage buffer descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER:
			if (!(feats.shaderUniformBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing for uniform buffer descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingUniformBufferUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for uniform buffer descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER:
			if (!(feats.shaderStorageTexelBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing for storage texel buffer descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageTexelBufferUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for storage texel buffer descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER:
			if (!(feats.shaderUniformTexelBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing for uniform texel buffer descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingUniformTexelBufferUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for uniform texel buffer descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC:
			if (!(feats.shaderStorageBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over storage buffer dynamic descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for storage buffer dynamic descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC:
			if (!(feats.shaderUniformBufferArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over uniform buffer dynamic descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for uniform buffer dynamic descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
			if (!(feats.shaderInputAttachmentArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over input attachment descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for input attachment descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_SAMPLER:
			if (!(feats.shaderSampledImageArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over sampler descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for sampler descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
			if (!(feats.shaderSampledImageArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over sampled image descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for sampled image descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER:
			if (!(feats.shaderSampledImageArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over combined image sampler descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingSampledImageUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for combined image sampler descriptors is not supported.");
			break;
		case VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
			if (!(feats.shaderStorageImageArrayNonUniformIndexing))
				TCU_THROW(NotSupportedError, "Non-uniform indexing over storage image descriptor arrays is not supported.");

			if (m_testCaseParams.updateAfterBind && !feats.descriptorBindingStorageImageUpdateAfterBind)
				TCU_THROW(NotSupportedError, "Update after bind for storage image descriptors is not supported.");
			break;
		default:
			DE_FATAL("Unknown Descriptor Type");
			break;
		}
	}

	virtual void initPrograms (SourceCollections& programCollection) const
	{
		std::string(*genShaderSource)(VkShaderStageFlagBits, const TestCaseParams&, bool) = &CommonDescriptorInstance::getShaderSource;

		if (VK_SHADER_STAGE_VERTEX_BIT & m_testCaseParams.stageFlags)
		{
			programCollection.glslSources.add(
				ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false))
				<< glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, false));

			if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
			{
				programCollection.glslSources.add(
					ut::buildShaderName(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, true))
					<< glu::VertexSource((*genShaderSource)(VK_SHADER_STAGE_VERTEX_BIT, m_testCaseParams, true));
			}
		}
		if (VK_SHADER_STAGE_FRAGMENT_BIT & m_testCaseParams.stageFlags)
		{
			programCollection.glslSources.add(
				ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false))
				<< glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, false));

			if (CommonDescriptorInstance::performWritesInVertex(m_testCaseParams.descriptorType))
			{
				programCollection.glslSources.add(
					ut::buildShaderName(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, true))
					<< glu::FragmentSource((*genShaderSource)(VK_SHADER_STAGE_FRAGMENT_BIT, m_testCaseParams, true));
			}
		}
		if (VK_SHADER_STAGE_COMPUTE_BIT & m_testCaseParams.stageFlags)
		{
			programCollection.glslSources.add(
				ut::buildShaderName(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams.descriptorType, m_testCaseParams.updateAfterBind, m_testCaseParams.calculateInLoop, false))
				<< glu::ComputeSource((*genShaderSource)(VK_SHADER_STAGE_COMPUTE_BIT, m_testCaseParams, false));
		}
	}
};

} // - unnamed namespace

void descriptorIndexingDescriptorSetsCreateTests (tcu::TestCaseGroup* group)
{
	struct TestCaseInfo
	{
		const char*		name;
		const char*		description;
		TestCaseParams	params;
	};

	tcu::TestContext&				context(group->getTestContext());

	TestCaseInfo casesAfterBindAndLoop[] =
	{
		{
			"storage_buffer", "Regular Storage Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"storage_texel_buffer", "Storage Texel Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_STORAGE_TEXEL_BUFFER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"uniform_texel_buffer", "Uniform Texel Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_UNIFORM_TEXEL_BUFFER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind,
				false,	// calculateInLoop
				false,	// usesMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"storage_image", "Storage Image Descriptors",
			{
				VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,
				VK_SHADER_STAGE_COMPUTE_BIT,
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
	};

	for (int updateAfterBind = 0; updateAfterBind < 2; ++updateAfterBind)
	{
		for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop)
		{
			for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesAfterBindAndLoop); ++caseIdx)
			{
				TestCaseInfo&	info			(casesAfterBindAndLoop[caseIdx]);
				std::string		caseName		(info.name);
				std::string		caseDescription	(info.description);
				TestCaseParams	params			(info.params);

				caseName				+= (updateAfterBind	? "_after_bind"	: "");
				caseName				+= (calculateInLoop	? "_in_loop"	: "");

				caseDescription			+= (updateAfterBind	? " After Bind"	: "");
				caseDescription			+= (calculateInLoop ? " In Loop"	: "");

				params.updateAfterBind	= updateAfterBind	? true			: false;
				params.calculateInLoop	= calculateInLoop	? true			: false;

				group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params));
			}
		}
	}

	TestCaseInfo casesAfterBindAndLoopAndLOD[] =
	{
		{
			"sampler", "Sampler Descriptors",
			{
				VK_DESCRIPTOR_TYPE_SAMPLER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// usesMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"sampled_image", "Sampled Image Descriptors",
			{
				VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// usesMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"combined_image_sampler", "Combined Image Sampler Descriptors",
			{
				VK_DESCRIPTOR_TYPE_COMBINED_IMAGE_SAMPLER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// usesMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
	};

	for (int updateAfterBind = 0; updateAfterBind < 2; ++updateAfterBind)
	{
		for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop)
		{
			for (int usesMipMaps = 0; usesMipMaps < 2; ++usesMipMaps)
			{
				for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesAfterBindAndLoopAndLOD); ++caseIdx)
				{
					TestCaseInfo&	info			(casesAfterBindAndLoopAndLOD[caseIdx]);
					std::string		caseName		(info.name);
					std::string		caseDescription	(info.description);
					TestCaseParams	params			(info.params);

					caseName				+= (updateAfterBind	? "_after_bind"	: "");
					caseName				+= (calculateInLoop ? "_in_loop"	: "");
					caseName				+= (usesMipMaps		? "_with_lod"	: "");

					caseDescription			+= (updateAfterBind	? " After Bind"	: "");
					caseDescription			+= (calculateInLoop	? " In Loop"	: "");
					caseDescription			+= (usesMipMaps		? " Use LOD"	: "");

					params.updateAfterBind	= updateAfterBind	? true			: false;
					params.calculateInLoop	= calculateInLoop	? true			: false;
					params.usesMipMaps		= usesMipMaps		? true			: false;

					group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params));
				}
			}
		}
	}

	TestCaseInfo casesNonAfterBindAndLoop[] =
	{
		{
			"uniform_buffer", "Regular Uniform Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// usesMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"storage_buffer_dynamic", "Dynamic Storage Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_STORAGE_BUFFER_DYNAMIC,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"uniform_buffer_dynamic", "Dynamic Uniform Buffer Descriptors",
			{
				VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER_DYNAMIC,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
		{
			"input_attachment", "Input Attachment Descriptors",
			{
				VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,
				(VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_FRAGMENT_BIT),
				RESOLUTION,
				false,	// updateAfterBind
				false,	// calculateInLoop
				false,	// useMipMaps
				FUZZY_COMPARE, CMP_THRESHOLD
			}
		},
	};

	for (int calculateInLoop = 0; calculateInLoop < 2; ++calculateInLoop)
	{
		for (deUint32 caseIdx = 0; caseIdx < DE_LENGTH_OF_ARRAY(casesNonAfterBindAndLoop); ++caseIdx)
		{
			TestCaseInfo&	info(casesNonAfterBindAndLoop[caseIdx]);
			std::string		caseName(info.name);
			std::string		caseDescription(info.description);
			TestCaseParams	params(info.params);

			caseName				+= (calculateInLoop	? "_in_loop"	: "");

			caseDescription			+= (calculateInLoop ? " In Loop"	: "");

			params.calculateInLoop	= calculateInLoop	? true			: false;

			group->addChild(new DescriptorIndexingTestCase(context, caseName.c_str(), caseDescription.c_str(), params));
		}
	}
}

} // - DescriptorIndexing
} // - vkt
