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

#include "vktBindingDescriptorUpdateTests.hpp"
#ifndef CTS_USES_VULKANSC
#include "vktBindingDescriptorUpdateASTests.hpp"
#endif // CTS_USES_VULKANSC

#include "vktTestCase.hpp"
#include "vktTestCaseUtil.hpp"

#include "vkRefUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkBuilderUtil.hpp"
#include "vkQueryUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkObjUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkImageUtil.hpp"
#include "vkBarrierUtil.hpp"
#include "vkImageWithMemory.hpp"
#include "vkBufferWithMemory.hpp"

#include "tcuTexture.hpp"
#include "tcuTestLog.hpp"

#include "deRandom.hpp"

#include <string>
#include <vector>
#include <utility>
#include <memory>
#include <math.h>

namespace vkt
{
namespace BindingModel
{
namespace
{

// Test matches VkPositiveLayerTest.EmptyDescriptorUpdateTest
tcu::TestStatus EmptyDescriptorUpdateCase (Context& context)
{
	const vk::DeviceInterface&				vki					= context.getDeviceInterface();
	const vk::VkDevice						device				= context.getDevice();
	vk::Allocator&							allocator			= context.getDefaultAllocator();

	// Create layout with two uniform buffer descriptors w/ empty binding between them
	vk::DescriptorSetLayoutBuilder			builder;

	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);
	builder.addBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 0, (vk::VkShaderStageFlags)0, DE_NULL);
	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_ALL);

	vk::Unique<vk::VkDescriptorSetLayout>	layout				(builder.build(vki, device, (vk::VkDescriptorSetLayoutCreateFlags)0));

	// Create descriptor pool
	vk::Unique<vk::VkDescriptorPool>		descriptorPool		(vk::DescriptorPoolBuilder().addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 2).build(vki, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));

	// Create descriptor set
	const vk::VkDescriptorSetAllocateInfo	setAllocateInfo		=
	{
		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType
		DE_NULL,											// const void*					pNext
		*descriptorPool,									// VkDescriptorPool				descriptorPool
		1,													// deUint32						descriptorSetCount
		&layout.get()										// const VkDescriptorSetLayout*	pSetLayouts
	};

	vk::Unique<vk::VkDescriptorSet>			descriptorSet		(allocateDescriptorSet(vki, device, &setAllocateInfo));

	// Create a buffer to be used for update
	const vk::VkBufferCreateInfo			bufferCreateInfo	=
	{
		vk::VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,	// VkStructureType		sType
		DE_NULL,									// const void*			pNext
		(vk::VkBufferCreateFlags)DE_NULL,			// VkBufferCreateFlags	flags
		256,										// VkDeviceSize			size
		vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT,		// VkBufferUsageFlags	usage
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode		sharingMode
		0,											// deUint32				queueFamilyIndexCount
		DE_NULL										// const deUint32*		pQueueFamilyIndices
	};

	vk::Unique<vk::VkBuffer>				buffer				(createBuffer(vki, device, &bufferCreateInfo));
	const vk::VkMemoryRequirements			requirements		= vk::getBufferMemoryRequirements(vki, device, *buffer);
	de::MovePtr<vk::Allocation>				allocation			= allocator.allocate(requirements, vk::MemoryRequirement::Any);

	VK_CHECK(vki.bindBufferMemory(device, *buffer, allocation->getMemory(), allocation->getOffset()));

	// Only update the descriptor at binding 2
	const vk::VkDescriptorBufferInfo		descriptorInfo		=
	{
		*buffer,		// VkBuffer		buffer
		0,				// VkDeviceSize	offset
		VK_WHOLE_SIZE	// VkDeviceSize	range
	};

	const vk::VkWriteDescriptorSet			descriptorWrite		=
	{
		vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureTypes					Type
		DE_NULL,									// const void*						pNext
		*descriptorSet,								// VkDescriptorSet					dstSet
		2,											// deUint32							dstBinding
		0,											// deUint32							dstArrayElement
		1,											// deUint32							descriptorCount
		vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,		// VkDescriptorType					descriptorType
		DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo
		&descriptorInfo,							// const VkDescriptorBufferInfo*	pBufferInfo
		DE_NULL										// const VkBufferView*				pTexelBufferView
	};

	vki.updateDescriptorSets(device, 1, &descriptorWrite, 0, DE_NULL);

	// Test should always pass
	return tcu::TestStatus::pass("Pass");
}


tcu::TestCaseGroup* createEmptyDescriptorUpdateTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "empty_descriptor", "Update last descriptor in a set that includes an empty binding"));

	addFunctionCase(group.get(), "uniform_buffer", "", EmptyDescriptorUpdateCase);

	return group.release();
}

enum class PointerCase
{
	ZERO = 0,
	ONE,
	DESTROYED,
};

struct SamplerlessParams
{
	vk::VkDescriptorType	type;
	PointerCase				pointer;
	deUint32				descriptorSet;
};

class SamplerlessDescriptorWriteTestCase : public vkt::TestCase
{
public:
								SamplerlessDescriptorWriteTestCase	(tcu::TestContext& testCtx, const std::string& name, const std::string& description, const SamplerlessParams& params);
	virtual						~SamplerlessDescriptorWriteTestCase	(void) {}

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

	vk::VkFormatFeatureFlagBits	getMainImageFeature					(void) const;

	static const vk::VkFormat	kImageFormat						= vk::VK_FORMAT_R8G8B8A8_UNORM;
private:
	SamplerlessParams			m_params;
};

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

	vk::VkSampler				getSamplerHandle						(void) const;
	virtual tcu::TestStatus		iterate									(void);

	vk::VkExtent3D				getMainImageExtent						(void) const;
	vk::VkImageUsageFlags		getMainImageUsage						(void) const;
	vk::VkImageLayout			getMainImageShaderLayout				(void) const;

	static const vk::VkFormat	kImageFormat							= SamplerlessDescriptorWriteTestCase::kImageFormat;
	static const vk::VkExtent3D	kFramebufferExtent;
	static const vk::VkExtent3D	kMinimumExtent;
	static const tcu::Vec4		kDescriptorColor;
private:
	SamplerlessParams			m_params;
};

const vk::VkExtent3D	SamplerlessDescriptorWriteTestInstance::kFramebufferExtent	= vk::makeExtent3D(64u, 64u, 1u);
const vk::VkExtent3D	SamplerlessDescriptorWriteTestInstance::kMinimumExtent		= vk::makeExtent3D(1u, 1u, 1u);
const tcu::Vec4			SamplerlessDescriptorWriteTestInstance::kDescriptorColor	{0.0f, 1.0f, 0.0f, 1.0f};

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

void SamplerlessDescriptorWriteTestCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const std::string vertexShader =
		"#version 450\n"
		"layout(location=0) in vec4 position;\n"
		"void main() { gl_Position = position; }\n";

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

	std::string descriptorDecl;
	std::string readOp;
	std::string extensions;

	switch (m_params.type)
	{
	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:
		extensions		= "#extension GL_EXT_samplerless_texture_functions : require\n";
		descriptorDecl	= "layout(set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform texture2D img;";
		readOp			= "texelFetch(img, ivec2(0, 0), 0)";
		break;
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		descriptorDecl	= "layout(rgba8, set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform image2D img;";
		readOp			= "imageLoad(img, ivec2(0, 0))";
		break;
	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:
		descriptorDecl	= "layout(input_attachment_index=0, set=" + std::to_string(m_params.descriptorSet) + ", binding=0) uniform subpassInput img;";
		readOp			= "subpassLoad(img)";
		break;
	default:
		DE_ASSERT(false);
		break;
	}

	std::ostringstream fragmentShader;

	fragmentShader
		<< "#version 450\n"
		<< extensions
		<< descriptorDecl << "\n"
		<< "layout(location = 0) out vec4 color_out;\n"
		<< "void main()\n"
		<< "{\n"
		<< "    color_out = " << readOp << ";\n"
		<< "}\n"
		;

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

vk::VkFormatFeatureFlagBits SamplerlessDescriptorWriteTestCase::getMainImageFeature (void) const
{
	vk::VkFormatFeatureFlagBits feature = static_cast<vk::VkFormatFeatureFlagBits>(0);

	switch (m_params.type)
	{
	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		feature = vk::VK_FORMAT_FEATURE_SAMPLED_IMAGE_BIT;		break;
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		feature = vk::VK_FORMAT_FEATURE_STORAGE_IMAGE_BIT;		break;
	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	feature = vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT;	break;
	default:
		DE_ASSERT(false);
		break;
	}

	return feature;
}

void SamplerlessDescriptorWriteTestCase::checkSupport (Context& context) const
{
	const auto&	vki				= context.getInstanceInterface();
	const auto	physicalDevice	= context.getPhysicalDevice();
	const auto	mainFeature		= getMainImageFeature();

	const vk::VkFormatFeatureFlags features =
	(
		vk::VK_FORMAT_FEATURE_TRANSFER_DST_BIT		|	// For color clearing.
		vk::VK_FORMAT_FEATURE_COLOR_ATTACHMENT_BIT	|	// For the separate frame buffer image (uses the same format).
		mainFeature
	);

	const auto props = vk::getPhysicalDeviceFormatProperties(vki, physicalDevice, kImageFormat);
	if ((props.optimalTilingFeatures & features) != features)
		TCU_THROW(NotSupportedError, "Image format does not support the required features");
}

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

SamplerlessDescriptorWriteTestInstance::SamplerlessDescriptorWriteTestInstance (Context& context, const SamplerlessParams& params)
	: vkt::TestInstance{context}
	, m_params(params)
{
}

struct DestroyedSampler
{
	vk::VkSampler sampler;

	DestroyedSampler (Context& context)
		: sampler{DE_NULL}
	{
		const vk::VkSamplerCreateInfo createInfo =
		{
			vk::VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO,		// VkStructureType		sType;
			nullptr,										// const void*			pNext;
			0u,												// VkSamplerCreateFlags	flags;
			vk::VK_FILTER_NEAREST,							// VkFilter				magFilter;
			vk::VK_FILTER_NEAREST,							// VkFilter				minFilter;
			vk::VK_SAMPLER_MIPMAP_MODE_NEAREST,				// VkSamplerMipmapMode	mipmapMode;
			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeU;
			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeV;
			vk::VK_SAMPLER_ADDRESS_MODE_REPEAT,				// VkSamplerAddressMode	addressModeW;
			0.0f,											// float				mipLodBias;
			VK_FALSE,										// VkBool32				anisotropyEnable;
			1.0f,											// float				maxAnisotropy;
			VK_FALSE,										// VkBool32				compareEnable;
			vk::VK_COMPARE_OP_NEVER,						// VkCompareOp			compareOp;
			0.0f,											// float				minLod;
			0.0f,											// float				maxLod;
			vk::VK_BORDER_COLOR_FLOAT_TRANSPARENT_BLACK,	// VkBorderColor		borderColor;
			VK_FALSE,										// VkBool32				unnormalizedCoordinates;
		};
		const auto newSampler = vk::createSampler(context.getDeviceInterface(), context.getDevice(), &createInfo);
		sampler = newSampler.get();
		// newSampler will be destroyed here and sampler will hold the former handle.
	}
};

vk::VkSampler SamplerlessDescriptorWriteTestInstance::getSamplerHandle (void) const
{
	if (m_params.pointer == PointerCase::ZERO)	return vk::VkSampler{DE_NULL};
	if (m_params.pointer == PointerCase::ONE)	return vk::VkSampler{1};
	static const DestroyedSampler destroyedSampler{m_context};
	return destroyedSampler.sampler;
}

vk::VkExtent3D SamplerlessDescriptorWriteTestInstance::getMainImageExtent (void) const
{
	const vk::VkExtent3D* extent = nullptr;

	switch (m_params.type)
	{
	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		// fallthrough
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		extent = &kMinimumExtent;		break;
	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	extent = &kFramebufferExtent;	break;
	default:
		DE_ASSERT(false);
		break;
	}

	return *extent;
}

vk::VkImageUsageFlags SamplerlessDescriptorWriteTestInstance::getMainImageUsage (void) const
{
	vk::VkImageUsageFlags usage = vk::VK_IMAGE_USAGE_TRANSFER_DST_BIT;	// Used when clearing the image.

	switch (m_params.type)
	{
	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		usage |= vk::VK_IMAGE_USAGE_SAMPLED_BIT;			break;
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		usage |= vk::VK_IMAGE_USAGE_STORAGE_BIT;			break;
	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	usage |= vk::VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;	break;
	default:
		DE_ASSERT(false);
		break;
	}

	return usage;
}

vk::VkImageLayout SamplerlessDescriptorWriteTestInstance::getMainImageShaderLayout (void) const
{
	vk::VkImageLayout layout = vk::VK_IMAGE_LAYOUT_UNDEFINED;

	switch (m_params.type)
	{
	case vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE:		// fallthrough
	case vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT:	layout = vk::VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;	break;
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:		layout = vk::VK_IMAGE_LAYOUT_GENERAL;					break;
	default:
		DE_ASSERT(false);
		break;
	}

	return layout;
}


tcu::TestStatus SamplerlessDescriptorWriteTestInstance::iterate (void)
{
	const auto&	vkd			= m_context.getDeviceInterface();
	const auto	device		= m_context.getDevice();
	auto&		allocator	= m_context.getDefaultAllocator();
	const auto	queue		= m_context.getUniversalQueue();
	const auto	queueIndex	= m_context.getUniversalQueueFamilyIndex();
	const auto	tcuFormat	= vk::mapVkFormat(kImageFormat);

	const vk::VkImageCreateInfo mainImgCreateInfo =
	{
		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
		nullptr,									// const void*				pNext;
		0u,											// VkImageCreateFlags		flags;
		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
		kImageFormat,								// VkFormat					format;
		getMainImageExtent(),						// VkExtent3D				extent;
		1u,											// deUint32					mipLevels;
		1u,											// deUint32					arrayLayers;
		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
		getMainImageUsage(),						// VkImageUsageFlags		usage;
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
		1u,											// deUint32					queueFamilyIndexCount;
		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
	};

	const vk::VkImageCreateInfo fbImgCreateInfo =
	{
		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
		nullptr,									// const void*				pNext;
		0u,											// VkImageCreateFlags		flags;
		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
		kImageFormat,								// VkFormat					format;
		kFramebufferExtent,							// VkExtent3D				extent;
		1u,											// deUint32					mipLevels;
		1u,											// deUint32					arrayLayers;
		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples;
		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
		(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |	// VkImageUsageFlags		usage;
		 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT),			// Used when verifying the image.
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
		1u,											// deUint32					queueFamilyIndexCount;
		&queueIndex,								// const deUint32*			pQueueFamilyIndices;
		vk::VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
	};

	// Create main and framebuffer images.
	const vk::ImageWithMemory mainImage	{vkd, device, allocator, mainImgCreateInfo,	vk::MemoryRequirement::Any};
	const vk::ImageWithMemory fbImage	{vkd, device, allocator, fbImgCreateInfo,	vk::MemoryRequirement::Any};

	// Corresponding image views.
	const auto colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
	const auto mainView					= vk::makeImageView(vkd, device, mainImage.get(),	vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);
	const auto fbView					= vk::makeImageView(vkd, device, fbImage.get(),		vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);

	// Buffer to copy rendering result to.
	const vk::VkDeviceSize		resultsBufferSize	= static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * kFramebufferExtent.width * kFramebufferExtent.height * kFramebufferExtent.depth);
	const auto					resultsBufferInfo	= vk::makeBufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
	const vk::BufferWithMemory	resultsBuffer		{vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible};

	const std::vector<tcu::Vec4> fullScreenQuad =
	{
		{ -1.f, -1.f,	0.f, 1.f },
		{  1.f, -1.f,	0.f, 1.f },
		{ -1.f,  1.f,	0.f, 1.f },
		{ -1.f,  1.f,	0.f, 1.f },
		{  1.f, -1.f,	0.f, 1.f },
		{  1.f,  1.f,	0.f, 1.f },
	};

	// Vertex buffer.
	const vk::VkDeviceSize		vertexBufferSize	= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
	const auto					vertexBufferInfo	= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
	const vk::BufferWithMemory	vertexBuffer		{vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible};

	// Copy data to vertex buffer.
	const auto&	vertexAlloc		= vertexBuffer.getAllocation();
	const auto	vertexDataPtr	= reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
	deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
	vk::flushAlloc(vkd, device, vertexAlloc);

	// Descriptor set layouts.
	vk::DescriptorSetLayoutBuilder layoutBuilder;
	std::vector<vk::Move<vk::VkDescriptorSetLayout>> descriptorSetLayouts;
	// Create layouts for required amount of empty descriptor sets before the one that is actually used.
	for (deUint32 descIdx = 0u; descIdx < m_params.descriptorSet; descIdx++)
	{
		descriptorSetLayouts.push_back(layoutBuilder.build(vkd, device));
	}
	// Create a layout for the descriptor set that is actually used.
	layoutBuilder.addSingleBinding(m_params.type, vk::VK_SHADER_STAGE_FRAGMENT_BIT);
	descriptorSetLayouts.push_back(layoutBuilder.build(vkd, device));

	// Descriptor pool.
	vk::DescriptorPoolBuilder poolBuilder;
	poolBuilder.addType(m_params.type);
	const auto descriptorPool = poolBuilder.build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, m_params.descriptorSet + 1);

	// Descriptor sets.
	std::vector<vk::Move<vk::VkDescriptorSet>> descriptorSets;
	for (deUint32 descIdx = 0u; descIdx < m_params.descriptorSet; descIdx++)
	{
		descriptorSets.push_back(vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayouts[descIdx].get()));
	}
	descriptorSets.push_back(vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayouts[m_params.descriptorSet].get()));

	// Update descriptor set with the descriptor.
	// IMPORTANT: the chosen sampler handle is used here.
	vk::DescriptorSetUpdateBuilder updateBuilder;
	const auto descriptorImageInfo = vk::makeDescriptorImageInfo(getSamplerHandle(), mainView.get(), getMainImageShaderLayout());
	updateBuilder.writeSingle(descriptorSets[m_params.descriptorSet].get(), vk::DescriptorSetUpdateBuilder::Location::binding(0u), m_params.type, &descriptorImageInfo);
	updateBuilder.update(vkd, device);

	// Shader modules.
	const auto vertexModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
	const auto fragModule	= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);

	// Render pass.
	const vk::VkAttachmentDescription fbAttachment =
	{
		0u,												// VkAttachmentDescriptionFlags	flags;
		kImageFormat,									// VkFormat						format;
		vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
		vk::VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp			loadOp;
		vk::VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp			storeOp;
		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
		vk::VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout				initialLayout;
		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout				finalLayout;
	};

	std::vector<vk::VkAttachmentDescription> attachmentDescs;
	attachmentDescs.push_back(fbAttachment);

	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
	{
		// Add it as a frame buffer attachment.
		const vk::VkAttachmentDescription inputAttachment =
		{
			0u,												// VkAttachmentDescriptionFlags	flags;
			kImageFormat,									// VkFormat						format;
			vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits		samples;
			vk::VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp			loadOp;
			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			storeOp;
			vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp			stencilLoadOp;
			vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp			stencilStoreOp;
			getMainImageShaderLayout(),						// VkImageLayout				initialLayout;
			getMainImageShaderLayout(),						// VkImageLayout				finalLayout;
		};

		attachmentDescs.push_back(inputAttachment);
	}

	std::vector<vk::VkAttachmentReference> inputAttachments;
	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
	{
		const vk::VkAttachmentReference inputRef =
		{
			1u,												// deUint32			attachment;
			getMainImageShaderLayout(),						// VkImageLayout	layout;
		};

		inputAttachments.push_back(inputRef);
	}

	const vk::VkAttachmentReference colorRef =
	{
			0u,												// deUint32			attachment;
			vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout;
	};
	const std::vector<vk::VkAttachmentReference> colorAttachments(1u, colorRef);

	const vk::VkSubpassDescription subpass =
	{
		0u,																// VkSubpassDescriptionFlags		flags;
		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,							// VkPipelineBindPoint				pipelineBindPoint;
		static_cast<deUint32>(inputAttachments.size()),					// deUint32							inputAttachmentCount;
		(inputAttachments.empty() ? nullptr : inputAttachments.data()),	// const VkAttachmentReference*		pInputAttachments;
		static_cast<deUint32>(colorAttachments.size()),					// deUint32							colorAttachmentCount;
		colorAttachments.data(),										// const VkAttachmentReference*		pColorAttachments;
		0u,																// const VkAttachmentReference*		pResolveAttachments;
		nullptr,														// const VkAttachmentReference*		pDepthStencilAttachment;
		0u,																// deUint32							preserveAttachmentCount;
		nullptr,														// const deUint32*					pPreserveAttachments;
	};
	const std::vector<vk::VkSubpassDescription> subpasses(1u, subpass);

	const vk::VkRenderPassCreateInfo renderPassInfo =
	{
		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
		nullptr,										// const void*						pNext;
		0u,												// VkRenderPassCreateFlags			flags;
		static_cast<deUint32>(attachmentDescs.size()),	// deUint32							attachmentCount;
		attachmentDescs.data(),							// const VkAttachmentDescription*	pAttachments;
		static_cast<deUint32>(subpasses.size()),		// deUint32							subpassCount;
		subpasses.data(),								// const VkSubpassDescription*		pSubpasses;
		0u,												// deUint32							dependencyCount;
		nullptr,										// const VkSubpassDependency*		pDependencies;
	};
	const auto renderPass = vk::createRenderPass(vkd, device, &renderPassInfo);

	// Framebuffer.
	std::vector<vk::VkImageView> attachments;
	attachments.push_back(fbView.get());
	if (m_params.type == vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT)
		attachments.push_back(mainView.get());
	const auto framebuffer = vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(attachments.size()), attachments.data(), kFramebufferExtent.width, kFramebufferExtent.height, kFramebufferExtent.depth);

	// Pipeline layout.
	const auto pipelineLayout = vk::makePipelineLayout(vkd, device, descriptorSetLayouts);

	// Graphics pipeline.
	const std::vector<vk::VkViewport>	viewports(1u, vk::makeViewport(kFramebufferExtent));
	const std::vector<vk::VkRect2D>		scissors(1u, vk::makeRect2D(kFramebufferExtent));

	const auto pipeline = vk::makeGraphicsPipeline(
		vkd, device, pipelineLayout.get(),
		vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
		renderPass.get(), viewports, scissors);

	// Command pool and command buffer.
	const auto cmdPool		= vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
	const auto cmdBufferPtr	= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto cmdBuffer	= cmdBufferPtr.get();

	// Draw quad.
	const vk::VkRect2D		renderArea			= vk::makeRect2D(kFramebufferExtent);
	const tcu::Vec4			clearFbColor		(0.0f, 0.0f, 0.0f, 1.0f);
	const vk::VkDeviceSize	vertexBufferOffset	= 0ull;

	const auto vtxBufferBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
	const auto preClearBarrier	= vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, mainImage.get(), colorSubresourceRange);
	const auto postClearBarrier	= vk::makeImageMemoryBarrier(vk::VK_ACCESS_TRANSFER_WRITE_BIT, vk::VK_ACCESS_SHADER_READ_BIT | vk::VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,
						vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, getMainImageShaderLayout(), mainImage.get(), colorSubresourceRange);
	const auto clearDescColor	= vk::makeClearValueColor(kDescriptorColor);

	vk::beginCommandBuffer(vkd, cmdBuffer);

	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u, 0u, nullptr, 1u, &vtxBufferBarrier, 0u, nullptr);
	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &preClearBarrier);
	vkd.cmdClearColorImage(cmdBuffer, mainImage.get(), vk::VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearDescColor.color, 1u, &colorSubresourceRange);
	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, vk::VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, nullptr, 0u, nullptr, 1u, &postClearBarrier);

	vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea, clearFbColor);
	vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
	vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), m_params.descriptorSet, 1u, &descriptorSets[m_params.descriptorSet].get(), 0u, nullptr);
	vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
	vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);
	vk::endRenderPass(vkd, cmdBuffer);

	const tcu::IVec2 copySize{static_cast<int>(kFramebufferExtent.width), static_cast<int>(kFramebufferExtent.height)};
	vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), copySize);

	vk::endCommandBuffer(vkd, cmdBuffer);
	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
	m_context.resetCommandPoolForVKSC(device, *cmdPool);

	// Check results.
	const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
	vk::invalidateAlloc(vkd, device, resultsBufferAlloc);

	const auto							resultsBufferPtr	= reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
	const tcu::ConstPixelBufferAccess	resultPixels		{tcuFormat, copySize[0], copySize[1], 1, resultsBufferPtr};

	bool pass = true;
	for (int x = 0; pass && x < resultPixels.getWidth(); ++x)
	for (int y = 0; pass && y < resultPixels.getHeight(); ++y)
	for (int z = 0; pass && z < resultPixels.getDepth(); ++z)
	{
		const auto pixel = resultPixels.getPixel(x, y, z);
		pass = (pixel == kDescriptorColor);
	}

	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
	if (!pass)
	{
		auto& log = m_context.getTestContext().getLog();
		log << tcu::TestLog::Image("color", "Rendered image", resultPixels);
		status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
	}

	return status;
}

tcu::TestCaseGroup* createSamplerlessWriteTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "samplerless", "Verify sampler unused with some descriptor image types"));

	const std::vector<std::pair<vk::VkDescriptorType, std::string>> descriptorTypes =
	{
		std::make_pair(vk::VK_DESCRIPTOR_TYPE_SAMPLED_IMAGE,	"sampled_img"),
		std::make_pair(vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE,	"storage_img"),
		std::make_pair(vk::VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	"input_attachment"),
	};

	const std::vector<std::pair<PointerCase, std::string>> pointerCases =
	{
		std::make_pair(PointerCase::ZERO,		"sampler_zero"),
		std::make_pair(PointerCase::ONE,		"sampler_one"),
		std::make_pair(PointerCase::DESTROYED,	"sampler_destroyed"),
	};

	for (const auto& typeCase		: descriptorTypes)
	for (const auto& pointerCase	: pointerCases)
	for (deUint32 descriptorSet = 0u; descriptorSet < 2u; descriptorSet++)
	{
		std::string			caseName	= typeCase.second + "_" + pointerCase.second;
		SamplerlessParams	params		{typeCase.first, pointerCase.first, descriptorSet};
		if (descriptorSet > 0u)
		{
			caseName += "_set_" + std::to_string(descriptorSet);
		}

		group->addChild(new SamplerlessDescriptorWriteTestCase(testCtx, caseName, "", params));
	}

	return group.release();
}

class RandomDescriptorUpdateTestCase : public vkt::TestCase
{
public:
	RandomDescriptorUpdateTestCase				(tcu::TestContext& testCtx, const std::string& name, const std::string& description);
	virtual	~RandomDescriptorUpdateTestCase		(void) {}

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

private:
};

class RandomDescriptorUpdateTestInstance : public vkt::TestInstance
{
public:
	RandomDescriptorUpdateTestInstance			(Context& context);
	virtual	~RandomDescriptorUpdateTestInstance	(void) {}

	virtual tcu::TestStatus		iterate			(void);

	static const vk::VkExtent3D	kFramebufferExtent;
	static const vk::VkFormat	kImageFormat;
	static const deUint32		kNumBuffers;
	static const deUint32		kNumOffsets;
	static const deUint32		kNumIterations;

private:
	deRandom					m_random;
};

const vk::VkExtent3D	RandomDescriptorUpdateTestInstance::kFramebufferExtent	= vk::makeExtent3D(64u, 64u, 1u);
const vk::VkFormat		RandomDescriptorUpdateTestInstance::kImageFormat		= vk::VK_FORMAT_R16G16B16A16_SFLOAT;
const deUint32			RandomDescriptorUpdateTestInstance::kNumBuffers			= 3u;
const deUint32			RandomDescriptorUpdateTestInstance::kNumOffsets			= 5u;
const deUint32			RandomDescriptorUpdateTestInstance::kNumIterations		= 1000u;

RandomDescriptorUpdateTestCase::RandomDescriptorUpdateTestCase (tcu::TestContext& testCtx, const std::string& name, const std::string& description)
: vkt::TestCase(testCtx, name, description)
{
}

void RandomDescriptorUpdateTestCase::initPrograms (vk::SourceCollections& programCollection) const
{
	const std::string vertexShader =
			"#version 450\n"
			"layout(location=0) in vec4 position;\n"
			"void main() { gl_Position = position; }\n";

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

	std::ostringstream fragmentShader;

	fragmentShader
			<< "#version 450\n"
			<< "layout(location = 0) out vec4 color_out;\n"
			<< "layout(set = 0, binding = 0) uniform buf\n"
			<< "{\n"
			<< "    vec4 data0;\n"
			<< "    vec4 data1;\n"
			<< "};\n"
			<< "void main()\n"
			<< "{\n"
			<< "    color_out = data0 + data1;\n"
			<< "}\n"
			;

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

vkt::TestInstance* RandomDescriptorUpdateTestCase::createInstance (Context& context) const
{
	return new RandomDescriptorUpdateTestInstance(context);
}

RandomDescriptorUpdateTestInstance::RandomDescriptorUpdateTestInstance(Context &context)
: vkt::TestInstance(context)
{
	deRandom_init(&m_random, 0);
}

tcu::TestStatus RandomDescriptorUpdateTestInstance::iterate()
{
	const auto&								vkd						= m_context.getDeviceInterface();
	const auto								device					= m_context.getDevice();
	auto&									allocator				= m_context.getDefaultAllocator();
	const auto								queue					= m_context.getUniversalQueue();
	const auto								queueIndex				= m_context.getUniversalQueueFamilyIndex();
	const auto								tcuFormat				= vk::mapVkFormat(kImageFormat);
	vk::DescriptorSetLayoutBuilder			builder;

	builder.addSingleBinding(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, vk::VK_SHADER_STAGE_FRAGMENT_BIT);

	vk::Unique<vk::VkDescriptorSetLayout>	layout					(builder.build(vkd, device, (vk::VkDescriptorSetLayoutCreateFlags)0));

	// Create descriptor pool
	vk::Unique<vk::VkDescriptorPool>		descriptorPool			(vk::DescriptorPoolBuilder().addType(vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER, 1).build(vkd, device, vk::VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1));

	// Create descriptor set
	const vk::VkDescriptorSetAllocateInfo	setAllocateInfo			=
	{
		vk::VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType
		DE_NULL,											// const void*					pNext
		*descriptorPool,									// VkDescriptorPool				descriptorPool
		1u,													// deUint32						descriptorSetCount
		&layout.get()										// const VkDescriptorSetLayout*	pSetLayouts
	};

	vk::Unique<vk::VkDescriptorSet>			descriptorSet			(allocateDescriptorSet(vkd, device, &setAllocateInfo));

	// The maximum allowed buffer offset alignment is 256 bytes. Meaningful data is placed at these offsets.
	const deUint32	bufferSize = 256u * kNumOffsets;

	float									bufferContents[kNumBuffers][bufferSize / 4];
	float									counter				= 1.0f;
	float									sign				= 1.0f;
	deUint32								offset				= 0;
	deUint32								channelSelector		= 0;

	// The buffers are filled with a running counter in one of the channels.
	// Both signed and unsigned values are used for each counter. Two vec4s
	// are initialized at offsets of 256 bytes (the maximum allowed alignment).
	// Everythin else is left as zero.
	for (deUint32 b = 0; b < kNumBuffers; b++)
	{
		deMemset(bufferContents[b], 0, bufferSize);

		for (deUint32 o = 0; o < kNumOffsets; o++)
		{
			offset = o * 64;

			// Two vectors at every offset.
			for (deUint32 v = 0; v < 2; v++)
			{
				// Only RGB channels are being tested.
				for (deUint32 c = 0; c < 3; c++)
				{
					if (c == channelSelector)
					{
						bufferContents[b][offset++] = sign * counter;
					}
					else
					{
						bufferContents[b][offset++] = 0.0f;
					}
				}
				// Keep alpha at one.
				bufferContents[b][offset++] = 1.0f;

				channelSelector = channelSelector + 1;

				// All three channels have been filled in. Switch a sign or increase the counter.
				if (channelSelector == 3)
				{
					channelSelector = 0;
					if (sign == 1.0f)
					{
						sign = -1.0f;
					}
					else
					{
						sign = 1.0f;
						counter += 1.0f;
					}
				}
			}
		}
	}

	const auto								bufferInfo				= vk::makeBufferCreateInfo(bufferSize, vk::VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT);
	std::vector<std::shared_ptr<vk::BufferWithMemory>>	buffers;

	for (const auto& contents : bufferContents)
	{
		buffers.emplace_back(std::make_shared<vk::BufferWithMemory>(vkd, device, allocator, bufferInfo, vk::MemoryRequirement::HostVisible));
		const auto&	bufferAlloc	= buffers.back()->getAllocation();
		const auto	bufferPtr	= reinterpret_cast<char*>(bufferAlloc.getHostPtr()) + bufferAlloc.getOffset();
		deMemcpy(bufferPtr, contents, bufferSize);
		vk::flushAlloc(vkd, device, bufferAlloc);
	}

	// Create framebuffer image and view.
	const vk::VkImageCreateInfo				fbImgCreateInfo			=
	{
		vk::VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType
		DE_NULL,									// const void*				pNext
		0u,											// VkImageCreateFlags		flags
		vk::VK_IMAGE_TYPE_2D,						// VkImageType				imageType
		kImageFormat,								// VkFormat					format
		kFramebufferExtent,							// VkExtent3D				extent
		1u,											// deUint32					mipLevels
		1u,											// deUint32					arrayLayers
		vk::VK_SAMPLE_COUNT_1_BIT,					// VkSampleCountFlagBits	samples
		vk::VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling
		(vk::VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |	// VkImageUsageFlags		usage
		 vk::VK_IMAGE_USAGE_TRANSFER_SRC_BIT),
		vk::VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode
		1u,											// deUint32					queueFamilyIndexCount
		&queueIndex,								// const deUint32*			pQueueFamilyIndices
		vk::VK_IMAGE_LAYOUT_UNDEFINED				// VkImageLayout			initialLayout
	};

	const vk::ImageWithMemory				fbImage					(vkd, device, allocator, fbImgCreateInfo,	vk::MemoryRequirement::Any);
	const auto								colorSubresourceRange	= vk::makeImageSubresourceRange(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
	const auto								fbView					= vk::makeImageView(vkd, device, fbImage.get(),		vk::VK_IMAGE_VIEW_TYPE_2D, kImageFormat, colorSubresourceRange);

	// Buffer to copy rendering result to.
	const vk::VkDeviceSize					resultsBufferSize		= static_cast<vk::VkDeviceSize>(static_cast<deUint32>(tcu::getPixelSize(tcuFormat)) * kFramebufferExtent.width * kFramebufferExtent.height * kFramebufferExtent.depth);
	const auto								resultsBufferInfo		= vk::makeBufferCreateInfo(resultsBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT);
	const vk::BufferWithMemory				resultsBuffer			(vkd, device, allocator, resultsBufferInfo, vk::MemoryRequirement::HostVisible);

	const std::vector<tcu::Vec4>			fullScreenQuad			=
	{
		{ -1.f, -1.f,	0.f, 1.f },
		{  1.f, -1.f,	0.f, 1.f },
		{ -1.f,  1.f,	0.f, 1.f },
		{ -1.f,  1.f,	0.f, 1.f },
		{  1.f, -1.f,	0.f, 1.f },
		{  1.f,  1.f,	0.f, 1.f }
	};

	// Vertex buffer.
	const vk::VkDeviceSize					vertexBufferSize		= static_cast<vk::VkDeviceSize>(fullScreenQuad.size() * sizeof(decltype(fullScreenQuad)::value_type));
	const auto								vertexBufferInfo		= vk::makeBufferCreateInfo(vertexBufferSize, vk::VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
	const vk::BufferWithMemory				vertexBuffer			(vkd, device, allocator, vertexBufferInfo, vk::MemoryRequirement::HostVisible | vk::MemoryRequirement::Coherent);

	// Copy data to vertex buffer.
	const auto&								vertexAlloc				= vertexBuffer.getAllocation();
	const auto								vertexDataPtr			= reinterpret_cast<char*>(vertexAlloc.getHostPtr()) + vertexAlloc.getOffset();
	deMemcpy(vertexDataPtr, fullScreenQuad.data(), static_cast<size_t>(vertexBufferSize));
	vk::flushAlloc(vkd, device, vertexAlloc);

	// Shader modules.
	const auto								vertexModule			= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
	const auto								fragModule				= vk::createShaderModule(vkd, device, m_context.getBinaryCollection().get("frag"), 0u);

	// Render pass.
	const vk::VkAttachmentDescription		fbAttachment			=
	{
		0u,												// VkAttachmentDescriptionFlags		flags
		kImageFormat,									// VkFormat							format
		vk::VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
		vk::VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp
		vk::VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
		vk::VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
		vk::VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
	};

	std::vector<vk::VkAttachmentDescription>	attachmentDescs;
	attachmentDescs.push_back(fbAttachment);

	const vk::VkAttachmentReference			colorRef				=
	{
		0u,												// deUint32			attachment
		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout	layout
	};
	const std::vector<vk::VkAttachmentReference> colorAttachments(1u, colorRef);

	const vk::VkSubpassDescription				subpass				=
	{
		0u,												// VkSubpassDescriptionFlags		flags
		vk::VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint				pipelineBindPoint
		0u,												// deUint32							inputAttachmentCount
		DE_NULL,										// const VkAttachmentReference*		pInputAttachments
		static_cast<deUint32>(colorAttachments.size()),	// deUint32							colorAttachmentCount
		colorAttachments.data(),						// const VkAttachmentReference*		pColorAttachments
		0u,												// const VkAttachmentReference*		pResolveAttachments
		DE_NULL,										// const VkAttachmentReference*		pDepthStencilAttachment
		0u,												// deUint32							preserveAttachmentCount
		DE_NULL											// const deUint32*					pPreserveAttachments
	};
	const std::vector<vk::VkSubpassDescription>	subpasses			(1u, subpass);

	const vk::VkRenderPassCreateInfo renderPassInfo =
	{
		vk::VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType
		DE_NULL,										// const void*						pNext
		0u,												// VkRenderPassCreateFlags			flags
		static_cast<deUint32>(attachmentDescs.size()),	// deUint32							attachmentCount
		attachmentDescs.data(),							// const VkAttachmentDescription*	pAttachments
		static_cast<deUint32>(subpasses.size()),		// deUint32							subpassCount
		subpasses.data(),								// const VkSubpassDescription*		pSubpasses
		0u,												// deUint32							dependencyCount
		DE_NULL,										// const VkSubpassDependency*		pDependencies
	};
	const auto									renderPass			= vk::createRenderPass(vkd, device, &renderPassInfo);

	// Framebuffer.
	std::vector<vk::VkImageView>				attachments;
	attachments.push_back(fbView.get());
	const auto									framebuffer			= vk::makeFramebuffer(vkd, device, renderPass.get(), static_cast<deUint32>(attachments.size()), attachments.data(), kFramebufferExtent.width, kFramebufferExtent.height, kFramebufferExtent.depth);

	// Pipeline layout.
	const auto									pipelineLayout		= vk::makePipelineLayout(vkd, device, layout.get());

	// Graphics pipeline.
	const std::vector<vk::VkViewport>			viewports			(1u, vk::makeViewport(kFramebufferExtent));
	const std::vector<vk::VkRect2D>				scissors			(1u, vk::makeRect2D(kFramebufferExtent));

	// Use additive alpha blending to accumulate results from all iterations.
	const vk::VkPipelineColorBlendAttachmentState	colorBlendAttachmentState	=
	{
		VK_TRUE,						// VkBool32					blendEnable
		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcColorBlendFactor
		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			dstColorBlendFactor
		vk::VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
		vk::VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcAlphaBlendFactor
		vk::VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstAlphaBlendFactor
		vk::VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
		vk::VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
		| vk::VK_COLOR_COMPONENT_G_BIT
		| vk::VK_COLOR_COMPONENT_B_BIT
		| vk::VK_COLOR_COMPONENT_A_BIT
	};

	const vk::VkPipelineColorBlendStateCreateInfo	colorBlendState	=
	{
		vk::VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
		DE_NULL,														// const void*									pNext
		0u,																// VkPipelineColorBlendStateCreateFlags			flags
		VK_FALSE,														// VkBool32										logicOpEnable
		vk::VK_LOGIC_OP_CLEAR,											// VkLogicOp									logicOp
		1u,																// deUint32										attachmentCount
		&colorBlendAttachmentState,										// const VkPipelineColorBlendAttachmentState*	pAttachments
		{ 1.0f, 1.0f, 1.0f, 1.0f }										// float										blendConstants[4]
	};

	const auto									pipeline			= vk::makeGraphicsPipeline(vkd, device, pipelineLayout.get(),
																							   vertexModule.get(), DE_NULL, DE_NULL, DE_NULL, fragModule.get(),
																							   renderPass.get(), viewports, scissors, vk::VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
																							   0u, 0u, DE_NULL, DE_NULL, DE_NULL, DE_NULL, &colorBlendState);

	// Command pool and command buffer.
	const auto									cmdPool				= vk::createCommandPool(vkd, device, vk::VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueIndex);
	const auto									cmdBufferPtr		= vk::allocateCommandBuffer(vkd, device, cmdPool.get(), vk::VK_COMMAND_BUFFER_LEVEL_PRIMARY);
	const auto									cmdBuffer			= cmdBufferPtr.get();

	const vk::VkRect2D							renderArea			= vk::makeRect2D(kFramebufferExtent);
	const vk::VkDeviceSize						vertexBufferOffset	= 0ull;

	const auto									vtxBufferBarrier	= vk::makeBufferMemoryBarrier(vk::VK_ACCESS_HOST_WRITE_BIT, vk::VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, vertexBuffer.get(), 0ull, vertexBufferSize);
	const auto									fbBarrier			= vk::makeImageMemoryBarrier(0u, vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_IMAGE_LAYOUT_UNDEFINED, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, fbImage.get(), colorSubresourceRange);

	vk::VkClearValue							clearValue;
	clearValue.color.float32[0] = 0.0f;
	clearValue.color.float32[1] = 0.0f;
	clearValue.color.float32[2] = 0.0f;
	clearValue.color.float32[3] = 1.0f;

	const vk::VkClearAttachment					clearAttachment		=
	{
		vk::VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask
		0u,								// uint32_t				colorAttachment
		clearValue						// VkClearValue			clearValue
	};

	const vk::VkClearRect						clearRect			=
	{
		vk::makeRect2D(kFramebufferExtent),	// VkRect2D	rect
		0u,									// uint32_t	baseArrayLayer
		1u									// uint32_t	layerCount
	};

	vk::beginCommandBuffer(vkd, cmdBuffer);
	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_HOST_BIT, vk::VK_PIPELINE_STAGE_VERTEX_INPUT_BIT, 0u,
						   0u, DE_NULL, 1u, &vtxBufferBarrier, 0u, DE_NULL);
	vkd.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
						   0u, DE_NULL, 0u, DE_NULL, 1u, &fbBarrier);
	vk::endCommandBuffer(vkd, cmdBuffer);
	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
	m_context.resetCommandPoolForVKSC(device, *cmdPool);

	struct DescriptorWrite
	{
		deUint32			bufferId;	// Which buffer to use for the descriptor update.
		vk::VkDeviceSize	offset;		// The offset for the descriptor update.
		vk::VkDeviceSize	range;		// The range for the descriptor update.
	};

	// Each iteration operates on a descriptor mutation which decides the source of the descriptor update.
	struct DescriptorMutation
	{
		deBool							update;		// Determines if a descriptor update is performed.
		deUint32						numDraws;	// The number of consecutive draw calls in a loop.
		std::vector<DescriptorWrite>	writes;		// Multiple redundant writes can be performed.
		// Other ideas to implement:
		// - Sometimes also update the buffer contents.
		// - Multiple descriptor sets.
	};

	std::vector<DescriptorMutation>				descriptorMutations;

	// Keep track of the expected result while generating the mutations.
	tcu::Vec4									uboValue0;
	tcu::Vec4									uboValue1;
	tcu::Vec4									expectedColor		(0.0f, 0.0f, 0.0f, 1.0f);
	DescriptorWrite								descWrite			= { 0u, 0u, 32u };

	for (deUint32 i = 0; i < kNumIterations; i++)
	{
		while (true)
		{
			tcu::Vec4						val0		= uboValue0;
			tcu::Vec4						val1		= uboValue1;

			deUint32						numWrites	= 1u;

			// Sometimes do redundant descriptor writes.
			if (deRandom_getUint32(&m_random) % 10 == 0)
				numWrites = deRandom_getUint32(&m_random) % 20 + 1;

			std::vector<DescriptorWrite>	writes;

			for (deUint32 w = 0; w < numWrites; w++)
			{
				// The first half: Most of the times change the offset but sometimes the buffer.
				// The second half: Most of the times change the buffer but sometimes change the offset.
				bool	firstHalf	= i < kNumIterations / 2;
				bool	rare		= (deRandom_getUint32(&m_random) % 100u >= (firstHalf ? 98u : 80u));

				// firstHalf     rare      change
				// --------------------------------
				//     1          0        Offset
				//     1          1        Buffer
				//     0          0        Buffer
				//     0          1        Offset
				//
				// This has a XOR pattern

				if (firstHalf ^ rare)
					descWrite.offset = (deRandom_getUint32(&m_random) % kNumOffsets) * 256u;
				else
					descWrite.bufferId = deRandom_getUint32(&m_random) % kNumBuffers;

				writes.push_back(descWrite);
			}

			DescriptorMutation				mutation	= {i == 0 ? true : deRandom_getBool(&m_random),
										deRandom_getUint32(&m_random) % 10u, writes};

			const auto&						lastWrite	= mutation.writes.back();
			if (mutation.update)
			{
				for (int c = 0; c < 3; c++)
				{
					val0[c] = bufferContents[lastWrite.bufferId][lastWrite.offset / 4 + c];
					val1[c] = bufferContents[lastWrite.bufferId][lastWrite.offset / 4 + 4 + c];

					// Sanity check we are reading expected values.
					DE_ASSERT(val0[c] >= -counter && val0[c] <= counter);
					DE_ASSERT(val1[c] >= -counter && val1[c] <= counter);
				}
			}

			tcu::Vec4						color		= expectedColor + (val0 + val1) * tcu::Vec4(static_cast<float>(mutation.numDraws));

			// 16-bit float can precisely present integers from -2048..2048. Continue randomizing the mutation
			// until we stay in this range.
			if (color[0] >= -2048.0f && color[0] <= 2048.0f && color[1] >= -2048.0f && color[1] <= 2048.0f
				&& color[2] >= -2048.0f && color[2] <= 2048.0f)
			{
				descriptorMutations.push_back(mutation);
				uboValue0		= val0;
				uboValue1		= val1;
				expectedColor	= color;
				break;
			}
			else
			{
				// Randomize both buffer and offset for a better chance to hit a
				// mutation that pushes the values back to the desired range.
				descWrite.offset = (deRandom_getUint32(&m_random) % kNumOffsets) * 256u;
				descWrite.bufferId = deRandom_getUint32(&m_random) % kNumBuffers;
			}
		}
	}

	bool first = true;

	for (auto mutation : descriptorMutations)
	{
		if (mutation.update)
		{
			for (const auto &write : mutation.writes)
			{
				const vk::VkDescriptorBufferInfo descriptorInfo =
				{
					buffers[write.bufferId]->get(),	// VkBuffer		buffer
					write.offset,					// VkDeviceSize	offset
					write.range						// VkDeviceSize	range
				};

				const vk::VkWriteDescriptorSet descriptorWrite =
				{
					vk::VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureTypes					Type
					DE_NULL,									// const void*						pNext
					*descriptorSet,								// VkDescriptorSet					dstSet
					0,											// deUint32							dstBinding
					0,											// deUint32							dstArrayElement
					1u,											// deUint32							descriptorCount
					vk::VK_DESCRIPTOR_TYPE_UNIFORM_BUFFER,		// VkDescriptorType					descriptorType
					DE_NULL,									// const VkDescriptorImageInfo*		pImageInfo
					&descriptorInfo,							// const VkDescriptorBufferInfo*	pBufferInfo
					DE_NULL										// const VkBufferView*				pTexelBufferView
				};

				vkd.updateDescriptorSets(device, 1, &descriptorWrite, 0, DE_NULL);
			}
		}

		vk::beginCommandBuffer(vkd, cmdBuffer);

		vk::beginRenderPass(vkd, cmdBuffer, renderPass.get(), framebuffer.get(), renderArea);
		vkd.cmdBindPipeline(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.get());
		// Clear the frame buffer during the first iteration.
		if (first)
		{
			vkd.cmdClearAttachments(cmdBuffer, 1u, &clearAttachment, 1u, &clearRect);
			first = false;
		}
		vkd.cmdBindDescriptorSets(cmdBuffer, vk::VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u,
								  &descriptorSet.get(), 0u, nullptr);
		vkd.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);

		for (deUint32 i = 0u; i < mutation.numDraws; i++)
			vkd.cmdDraw(cmdBuffer, static_cast<deUint32>(fullScreenQuad.size()), 1u, 0u, 0u);

		vk::endRenderPass(vkd, cmdBuffer);
		vk::endCommandBuffer(vkd, cmdBuffer);
		vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
		m_context.resetCommandPoolForVKSC(device, *cmdPool);
	}

	vk::beginCommandBuffer(vkd, cmdBuffer);
	const tcu::IVec2 copySize{static_cast<int>(kFramebufferExtent.width),
							  static_cast<int>(kFramebufferExtent.height)};
	vk::copyImageToBuffer(vkd, cmdBuffer, fbImage.get(), resultsBuffer.get(), copySize);
	vk::endCommandBuffer(vkd, cmdBuffer);
	vk::submitCommandsAndWait(vkd, device, queue, cmdBuffer);
	m_context.resetCommandPoolForVKSC(device, *cmdPool);

	// Check results.
	const auto& resultsBufferAlloc = resultsBuffer.getAllocation();
	vk::invalidateAlloc(vkd, device, resultsBufferAlloc);

	const auto							resultsBufferPtr	= reinterpret_cast<const char*>(resultsBufferAlloc.getHostPtr()) + resultsBufferAlloc.getOffset();
	const tcu::ConstPixelBufferAccess	resultPixels		{tcuFormat, copySize[0], copySize[1], 1, resultsBufferPtr};

	// The test only operates on integers, so a tolerance of 0.5 should work.
	const float							tolerance			= 0.5f;

	bool pass = true;
	for (int x = 0; pass && x < resultPixels.getWidth(); ++x)
		for (int y = 0; pass && y < resultPixels.getHeight(); ++y)
			for (int z = 0; pass && z < resultPixels.getDepth(); ++z)
			{
				const auto pixel = resultPixels.getPixel(x, y, z);
				for (int c = 0; c < 3; c++)
					if (fabs(pixel[c] - expectedColor[c]) > tolerance)
						pass = false;
			}

	tcu::TestStatus status = tcu::TestStatus::pass("Pass");
	if (!pass)
	{
		m_context.getTestContext().getLog() << tcu::TestLog::Image("color", "Rendered image", resultPixels);
		status = tcu::TestStatus::fail("Pixel mismatch; please check the rendered image");
	}

	return status;
}

tcu::TestCaseGroup* createRandomDescriptorUpdateTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "random", "Update descriptors randomly between draws"));

	group->addChild(new RandomDescriptorUpdateTestCase(testCtx, "uniform_buffer", ""));
	return group.release();
}

} // anonymous

tcu::TestCaseGroup* createDescriptorUpdateTests (tcu::TestContext& testCtx)
{
	de::MovePtr<tcu::TestCaseGroup> group(new tcu::TestCaseGroup(testCtx, "descriptor_update", "Update descriptor sets"));

	group->addChild(createEmptyDescriptorUpdateTests(testCtx));
	group->addChild(createSamplerlessWriteTests(testCtx));
	group->addChild(createRandomDescriptorUpdateTests(testCtx));
#ifndef CTS_USES_VULKANSC
	group->addChild(createDescriptorUpdateASTests(testCtx));
#endif // CTS_USES_VULKANSC

	return group.release();
}

} // BindingModel
} // vkt
