/*-------------------------------------------------------------------------
 * 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"

#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 <string>
#include <vector>
#include <utility>

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;
};

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=0, binding=0) uniform texture2D img;";
		readOp			= "texelFetch(img, ivec2(0, 0), 0)";
		break;
	case vk::VK_DESCRIPTOR_TYPE_STORAGE_IMAGE:
		descriptorDecl	= "layout(rgba8, set=0, 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=0, 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 layout.
	vk::DescriptorSetLayoutBuilder layoutBuilder;
	layoutBuilder.addSingleBinding(m_params.type, vk::VK_SHADER_STAGE_ALL_GRAPHICS);
	const auto descriptorSetLayout = 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, 1u);

	// Descriptor set.
	const auto descriptorSet = vk::makeDescriptorSet(vkd, device, descriptorPool.get(), descriptorSetLayout.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(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, descriptorSetLayout.get());

	// 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_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, 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(), 0u, 1u, &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);

	// 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)
	{
		const std::string		caseName	= typeCase.second + "_" + pointerCase.second;
		const SamplerlessParams	params		{typeCase.first, pointerCase.first};

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

	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));

	return group.release();
}

} // BindingModel
} // vkt
