/*------------------------------------------------------------------------
 * Vulkan Conformance Tests
 * ------------------------
 *
 * Copyright (c) 2021 The Khronos Group Inc.
 * Copyright (c) 2021 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 load and store op "none"
 *//*--------------------------------------------------------------------*/

#include "vktRenderPassLoadStoreOpNoneTests.hpp"
#include "pipeline/vktPipelineImageUtil.hpp"
#include "vktTestCase.hpp"
#include "vkImageUtil.hpp"
#include "vkMemUtil.hpp"
#include "vkPrograms.hpp"
#include "vkQueryUtil.hpp"
#include "vkCmdUtil.hpp"
#include "vkRef.hpp"
#include "vkRefUtil.hpp"
#include "vkTypeUtil.hpp"
#include "vkObjUtil.hpp"
#include "tcuImageCompare.hpp"
#include "tcuPlatform.hpp"
#include "tcuTestLog.hpp"
#include "deStringUtil.hpp"
#include "deUniquePtr.hpp"
#include "deRandom.hpp"
#include <cstring>
#include <cmath>
#include <vector>

namespace vkt
{
namespace renderpass
{

using namespace vk;

namespace
{

enum AttachmentInit
{
	ATTACHMENT_INIT_PRE = 1,
	ATTACHMENT_INIT_CMD_CLEAR = 2
};

enum AttachmentUsage
{
	ATTACHMENT_USAGE_UNDEFINED = 0,
	ATTACHMENT_USAGE_COLOR = 1,
	ATTACHMENT_USAGE_DEPTH = 2,
	ATTACHMENT_USAGE_STENCIL = 4,
	ATTACHMENT_USAGE_INPUT = 8,
	ATTACHMENT_USAGE_WRITE_OFF = 16,
	ATTACHMENT_USAGE_DEPTH_STENCIL = ATTACHMENT_USAGE_DEPTH | ATTACHMENT_USAGE_STENCIL
};

struct AttachmentParams
{
	deUint32			usage;
	VkAttachmentLoadOp	loadOp;
	VkAttachmentStoreOp	storeOp;
	deUint32			init;
	bool				verifyInner;
	tcu::Vec4			innerRef;
	bool				verifyOuter;
	tcu::Vec4			outerRef;
};

struct AttachmentRef
{
	deUint32	idx;
	deUint32	usage;
};

struct SubpassParams
{
	std::vector<AttachmentRef>	attachmentRefs;
	deUint32					numDraws;
};

struct TestParams
{
	std::vector<AttachmentParams>	attachments;
	std::vector<SubpassParams>		subpasses;
	RenderPassType					renderPassType;
	VkFormat						depthStencilFormat;
	bool							alphaBlend;
};

struct Vertex4RGBA
{
	tcu::Vec4 position;
	tcu::Vec4 color;
};

template<typename T>
inline de::SharedPtr<vk::Move<T> > makeSharedPtr(vk::Move<T> move)
{
	return de::SharedPtr<vk::Move<T> >(new vk::Move<T>(move));
}

std::vector<Vertex4RGBA> createQuad (void)
{
	std::vector<Vertex4RGBA>	vertices;

	const float			size					= 1.0f;
	const tcu::Vec4		red						(1.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4		blue					(0.0f, 0.0f, 1.0f, 1.0f);
	const Vertex4RGBA	lowerLeftVertexRed		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), red};
	const Vertex4RGBA	lowerRightVertexRed		= {tcu::Vec4(size, -size, 0.0f, 1.0f), red};
	const Vertex4RGBA	upperLeftVertexRed		= {tcu::Vec4(-size, size, 0.0f, 1.0f), red};
	const Vertex4RGBA	upperRightVertexRed		= {tcu::Vec4(size, size, 0.0f, 1.0f), red};
	const Vertex4RGBA	lowerLeftVertexBlue		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), blue};
	const Vertex4RGBA	lowerRightVertexBlue	= {tcu::Vec4(size, -size, 0.0f, 1.0f), blue};
	const Vertex4RGBA	upperLeftVertexBlue		= {tcu::Vec4(-size, size, 0.0f, 1.0f), blue};
	const Vertex4RGBA	upperRightVertexBlue	= {tcu::Vec4(size, size, 0.0f, 1.0f), blue};

	vertices.push_back(lowerLeftVertexRed);
	vertices.push_back(lowerRightVertexRed);
	vertices.push_back(upperLeftVertexRed);
	vertices.push_back(upperLeftVertexRed);
	vertices.push_back(lowerRightVertexRed);
	vertices.push_back(upperRightVertexRed);

	vertices.push_back(lowerLeftVertexBlue);
	vertices.push_back(lowerRightVertexBlue);
	vertices.push_back(upperLeftVertexBlue);
	vertices.push_back(upperLeftVertexBlue);
	vertices.push_back(lowerRightVertexBlue);
	vertices.push_back(upperRightVertexBlue);

	return vertices;
}

deUint32 getFirstUsage (deUint32 attachmentIdx, const std::vector<SubpassParams>& subpasses)
{
	for (const auto& subpass : subpasses)
		for (const auto& ref : subpass.attachmentRefs)
			if (ref.idx == attachmentIdx)
				return ref.usage;

	return ATTACHMENT_USAGE_UNDEFINED;
}

std::string getFormatCaseName(VkFormat format)
{
	return de::toLower(de::toString(getFormatStr(format)).substr(10));
}

template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
Move<VkRenderPass> createRenderPass (const DeviceInterface&	vk,
									 VkDevice				vkDevice,
									 const TestParams		testParams)
{
	const VkImageAspectFlags	aspectMask						= testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
	const VkImageAspectFlags	depthStencilAspectMask			= testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
	std::vector<AttachmentDesc>	attachmentDescriptions;
	std::vector<SubpassDesc>	subpassDescriptions;

	struct Refs
	{
		std::vector<AttachmentRef>	colorAttachmentRefs;
		std::vector<AttachmentRef>	depthStencilAttachmentRefs;
		std::vector<AttachmentRef>	inputAttachmentRefs;
	};

	std::vector<Refs>			subpassRefs;
	bool						hasInputAttachment				= false;

	for (size_t i = 0; i < testParams.attachments.size(); i++)
	{
		VkImageLayout	initialLayout;
		VkImageLayout	finalLayout;
		VkFormat		format;

		if (testParams.attachments[i].usage & ATTACHMENT_USAGE_DEPTH_STENCIL)
		{
			format = testParams.depthStencilFormat;
		}
		else
		{
			// Color and input attachments.
			format = VK_FORMAT_R8G8B8A8_UNORM;
		}

		// Search for the first reference to determine the initial layout.
		deUint32 firstUsage = getFirstUsage((deUint32)i, testParams.subpasses);

		// No subpasses using this attachment. Use the usage flags of the attachment.
		if (firstUsage == ATTACHMENT_USAGE_UNDEFINED)
			firstUsage = testParams.attachments[i].usage;

		if (firstUsage & ATTACHMENT_USAGE_COLOR)
			initialLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
		else if (firstUsage & ATTACHMENT_USAGE_DEPTH_STENCIL)
			initialLayout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
		else
		{
			DE_ASSERT(firstUsage & ATTACHMENT_USAGE_INPUT);
			initialLayout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
		}

		// Set final layout to transfer src if it's being verified. Otherwise
		// just use the initial layout as it's known to be supported by
		// the usage flags.
		if (testParams.attachments[i].verifyInner || testParams.attachments[i].verifyOuter)
			finalLayout = VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL;
		else
			finalLayout = initialLayout;

		const AttachmentDesc attachmentDesc =
		{
			DE_NULL,							// const void*						pNext
			(VkAttachmentDescriptionFlags) 0,	// VkAttachmentDescriptionFlags		flags
			format,								// VkFormat							format
			VK_SAMPLE_COUNT_1_BIT,				// VkSampleCountFlagBits			samples
			testParams.attachments[i].loadOp,	// VkAttachmentLoadOp				loadOp
			testParams.attachments[i].storeOp,	// VkAttachmentStoreOp				storeOp
			testParams.attachments[i].loadOp,	// VkAttachmentLoadOp				stencilLoadOp
			testParams.attachments[i].storeOp,	// VkAttachmentStoreOp				stencilStoreOp
			initialLayout,						// VkImageLayout					initialLayout
			finalLayout							// VkImageLayout					finalLayout
		};

		attachmentDescriptions.push_back(attachmentDesc);
	}

	for (const auto& subpass : testParams.subpasses)
	{
		subpassRefs.push_back({});
		auto& refs = subpassRefs.back();

		for (const auto& ref : subpass.attachmentRefs)
		{
			VkImageLayout layout;

			if (ref.usage & ATTACHMENT_USAGE_COLOR)
			{
				layout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
				refs.colorAttachmentRefs.push_back({DE_NULL, ref.idx, layout, aspectMask});
			}
			else if (ref.usage & ATTACHMENT_USAGE_DEPTH_STENCIL)
			{
				layout = VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL;
				refs.depthStencilAttachmentRefs.push_back({DE_NULL, ref.idx, layout, depthStencilAspectMask});
			}
			else
			{
				DE_ASSERT(ref.usage & ATTACHMENT_USAGE_INPUT);
				layout = VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL;
				refs.inputAttachmentRefs.push_back({DE_NULL, ref.idx, layout, aspectMask});
				hasInputAttachment = true;
			}
		}

		const SubpassDesc			subpassDescription			=
		{
			DE_NULL,
			(VkSubpassDescriptionFlags)0,																// VkSubpassDescriptionFlags		flags
			VK_PIPELINE_BIND_POINT_GRAPHICS,															// VkPipelineBindPoint				pipelineBindPoint
			0u,																							// deUint32							viewMask
			(deUint32)refs.inputAttachmentRefs.size(),													// deUint32							inputAttachmentCount
			refs.inputAttachmentRefs.empty() ? DE_NULL : refs.inputAttachmentRefs.data(),				// const VkAttachmentReference*		pInputAttachments
			(deUint32)refs.colorAttachmentRefs.size(),													// deUint32							colorAttachmentCount
			refs.colorAttachmentRefs.empty() ? DE_NULL : refs.colorAttachmentRefs.data(),				// const VkAttachmentReference*		pColorAttachments
			DE_NULL,																					// const VkAttachmentReference*		pResolveAttachments
			refs.depthStencilAttachmentRefs.empty() ? DE_NULL : refs.depthStencilAttachmentRefs.data(),	// const VkAttachmentReference*		pDepthStencilAttachment
			0u,																							// deUint32							preserveAttachmentCount
			DE_NULL																						// const deUint32*					pPreserveAttachments
		};

		subpassDescriptions.push_back(subpassDescription);
	}

	// Dependency of color attachment of subpass 0 to input attachment of subpass 1.
	// Determined later if it's being used.
	const SubpassDep			subpassDependency				=
	{
		DE_NULL,										// const void*				pNext
		0u,												// uint32_t					srcSubpass
		1u,												// uint32_t					dstSubpass
		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		srcStageMask
		VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags		dstStageMask
		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask
		VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// VkAccessFlags			dstAccessMask
		VK_DEPENDENCY_BY_REGION_BIT,					// VkDependencyFlags		dependencyFlags
		0u												// deInt32					viewOffset
	};

	const RenderPassCreateInfo	renderPassInfo					=
	{
		DE_NULL,											// const void*						pNext
		(VkRenderPassCreateFlags)0,							// VkRenderPassCreateFlags			flags
		(deUint32)attachmentDescriptions.size(),			// deUint32							attachmentCount
		attachmentDescriptions.data(),						// const VkAttachmentDescription*	pAttachments
		(deUint32)subpassDescriptions.size(),				// deUint32							subpassCount
		subpassDescriptions.data(),							// const VkSubpassDescription*		pSubpasses
		hasInputAttachment ? 1u : 0u,						// deUint32							dependencyCount
		hasInputAttachment ? &subpassDependency : DE_NULL,	// const VkSubpassDependency*		pDependencies
		0u,													// deUint32							correlatedViewMaskCount
		DE_NULL												// const deUint32*					pCorrelatedViewMasks
	};

	return renderPassInfo.createRenderPass(vk, vkDevice);
}

class LoadStoreOpNoneTest : public vkt::TestCase
{
public:
							LoadStoreOpNoneTest		(tcu::TestContext&	testContext,
													 const std::string&	name,
													 const std::string&	description,
													 const TestParams&	testParams);
	virtual					~LoadStoreOpNoneTest	(void);
	virtual void			initPrograms			(SourceCollections&	sourceCollections) const;
	virtual void			checkSupport			(Context& context) const;
	virtual TestInstance*	createInstance			(Context& context) const;
private:
	const TestParams		m_testParams;
};

class LoadStoreOpNoneTestInstance : public vkt::TestInstance
{
public:
								LoadStoreOpNoneTestInstance		(Context&			context,
																 const TestParams&	testParams);
	virtual						~LoadStoreOpNoneTestInstance	(void);
	virtual tcu::TestStatus		iterate							(void);
	template<typename RenderpassSubpass>
	void						createCommandBuffer				(const DeviceInterface&					vk,
																 VkDevice								vkDevice,
																 std::vector<Move<VkDescriptorSet>>&	descriptorSets,
																 std::vector<Move<VkPipelineLayout>>&	pipelineLayouts,
																 std::vector<Move<VkPipeline>>&			pipelines);
private:
	TestParams					m_testParams;

	const tcu::UVec2			m_imageSize;
	const tcu::UVec2			m_renderSize;

	Move<VkDescriptorPool>		m_descriptorPool;
	Move<VkRenderPass>			m_renderPass;
	Move<VkFramebuffer>			m_framebuffer;

	Move<VkBuffer>				m_vertexBuffer;
	std::vector<Vertex4RGBA>	m_vertices;
	de::MovePtr<Allocation>		m_vertexBufferAlloc;

	Move<VkCommandPool>			m_cmdPool;
	Move<VkCommandBuffer>		m_cmdBuffer;
};

LoadStoreOpNoneTest::LoadStoreOpNoneTest (tcu::TestContext&		testContext,
										  const std::string&	name,
										  const std::string&	description,
										  const TestParams&		testParams)
	: vkt::TestCase	(testContext, name, description)
	, m_testParams(testParams)
{
}

LoadStoreOpNoneTest::~LoadStoreOpNoneTest (void)
{
}

TestInstance* LoadStoreOpNoneTest::createInstance (Context& context) const
{
	return new LoadStoreOpNoneTestInstance(context, m_testParams);
}

void LoadStoreOpNoneTest::checkSupport (Context& ctx) const
{
	// Check for renderpass2 extension if used.
	if (m_testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
		ctx.requireDeviceFunctionality("VK_KHR_create_renderpass2");

	ctx.requireDeviceFunctionality("VK_EXT_load_store_op_none");
}

void LoadStoreOpNoneTest::initPrograms (SourceCollections& sourceCollections) const
{
	std::ostringstream fragmentSource;

	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
		"#version 450\n"
		"layout(location = 0) in highp vec4 position;\n"
		"layout(location = 1) in highp vec4 color;\n"
		"layout(location = 0) out highp vec4 vtxColor;\n"
		"void main (void)\n"
		"{\n"
		"	gl_Position = position;\n"
		"	vtxColor = color;\n"
		"}\n");

	sourceCollections.glslSources.add("color_frag") << glu::FragmentSource(
		"#version 450\n"
		"layout(location = 0) in highp vec4 vtxColor;\n"
		"layout(location = 0) out highp vec4 fragColor;\n"
		"void main (void)\n"
		"{\n"
		"	fragColor = vtxColor;\n"
		"	gl_FragDepth = 1.0;\n"
		"}\n");

	sourceCollections.glslSources.add("color_frag_blend") << glu::FragmentSource(
		"#version 450\n"
		"layout(location = 0) in highp vec4 vtxColor;\n"
		"layout(location = 0) out highp vec4 fragColor;\n"
		"void main (void)\n"
		"{\n"
		"	fragColor = vec4(vtxColor.rgb, 0.5);\n"
		"	gl_FragDepth = 1.0;\n"
		"}\n");

	sourceCollections.glslSources.add("color_frag_input") << glu::FragmentSource(
		"#version 450\n"
		"layout(location = 0) in highp vec4 vtxColor;\n"
		"layout(location = 0) out highp vec4 fragColor;\n"
		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
		"void main (void)\n"
		"{\n"
		"	fragColor = subpassLoad(inputColor) + vtxColor;\n"
		"	gl_FragDepth = 1.0;\n"
		"}\n");
}

LoadStoreOpNoneTestInstance::LoadStoreOpNoneTestInstance	(Context&			context,
															 const TestParams&	testParams)
	: vkt::TestInstance	(context)
	, m_testParams		(testParams)
	, m_imageSize		(32u, 32u)
	, m_renderSize		(27u, 19u)
	, m_vertices		(createQuad())
{
}

LoadStoreOpNoneTestInstance::~LoadStoreOpNoneTestInstance (void)
{
}

template<typename RenderpassSubpass>
void LoadStoreOpNoneTestInstance::createCommandBuffer	(const DeviceInterface&					vk,
														 VkDevice								vkDevice,
														 std::vector<Move<VkDescriptorSet>>&	descriptorSets,
														 std::vector<Move<VkPipelineLayout>>&	pipelineLayouts,
														 std::vector<Move<VkPipeline>>&			pipelines)
{
	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);

	const VkDeviceSize vertexBufferOffset = 0;

	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);

	beginCommandBuffer(vk, *m_cmdBuffer, 0u);

	const VkRenderPassBeginInfo renderPassBeginInfo =
	{
		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType
		DE_NULL,									// const void*			pNext
		*m_renderPass,								// VkRenderPass			renderPass
		*m_framebuffer,								// VkFramebuffer		framebuffer
		makeRect2D(m_renderSize),					// VkRect2D				renderArea
		0u,											// uint32_t				clearValueCount
		DE_NULL										// const VkClearValue*	pClearValues
	};
	RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);

	// Add clear commands for selected attachments
	std::vector<VkClearAttachment> clearAttachments;
	deUint32 colorAttIdx = 0u;
	for (const auto& att : m_testParams.attachments)
	{
		if (att.init & ATTACHMENT_INIT_CMD_CLEAR)
		{
			if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL)
			{
				clearAttachments.push_back({VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT, 0u,
											makeClearValueDepthStencil(0.25, 64)});
			}
			else
			{
				clearAttachments.push_back({VK_IMAGE_ASPECT_COLOR_BIT, colorAttIdx++,
											makeClearValueColorF32(0.0f, 0.0f, 0.5f, 1.0f)});
			}
		}
	}
	if (!clearAttachments.empty())
	{
		VkClearRect rect = { makeRect2D(m_renderSize), 0u, 1u };
		vk.cmdClearAttachments(*m_cmdBuffer, (deUint32) clearAttachments.size(), clearAttachments.data(), 1u, &rect);
	}

	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);

	deUint32	descriptorSetIdx	= 0u;
	deUint32	vertexOffset		= 0u;
	for (size_t i = 0; i < m_testParams.subpasses.size(); i++)
	{
		if (i != 0)
			vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);

		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelines[i]);

		bool hasInput = false;
		for (const auto &ref : m_testParams.subpasses[i].attachmentRefs)
			if (ref.usage & ATTACHMENT_USAGE_INPUT)
				hasInput = true;

		if (hasInput)
			vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipelineLayouts[i], 0, 1,
									 &descriptorSets[descriptorSetIdx++].get(), 0, DE_NULL);

		for (deUint32 d = 0; d < m_testParams.subpasses[i].numDraws; d++)
		{
			vk.cmdDraw(*m_cmdBuffer, 6u, 1, vertexOffset, 0);
			vertexOffset += 6u;
		}
	}
	RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
	endCommandBuffer(vk, *m_cmdBuffer);
}

tcu::TestStatus LoadStoreOpNoneTestInstance::iterate (void)
{
	const DeviceInterface&					vk						= m_context.getDeviceInterface();
	const VkDevice							vkDevice				= m_context.getDevice();
	const VkQueue							queue					= m_context.getUniversalQueue();
	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
	SimpleAllocator							memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
	const VkComponentMapping				componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };

	std::vector<Move<VkImage>>				attachmentImages;
	std::vector<de::MovePtr<Allocation>>	attachmentImageAllocs;
	std::vector<Move<VkImageView>>			imageViews;
	std::vector<Move<VkPipeline>>			pipelines;

	for (const auto& att : m_testParams.attachments)
	{
		VkFormat				format;
		VkImageUsageFlags		usage				= 0;
		VkImageAspectFlags		aspectFlags;

		if (att.verifyInner || att.verifyOuter) usage |= VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
		if (att.init & ATTACHMENT_INIT_PRE) usage |= VK_IMAGE_USAGE_TRANSFER_DST_BIT;

		if (att.usage & ATTACHMENT_USAGE_DEPTH_STENCIL)
		{
			aspectFlags = VK_IMAGE_ASPECT_DEPTH_BIT | VK_IMAGE_ASPECT_STENCIL_BIT;
			usage |= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT;
			format = m_testParams.depthStencilFormat;

			VkImageFormatProperties		properties;
			VkResult result = m_context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
				m_context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0u, &properties);
			if (result != VK_SUCCESS)
			{
				TCU_THROW(NotSupportedError, "Depth-stencil format not supported");
			}
		}
		else
		{
			// Color and input attachments.
			format = VK_FORMAT_R8G8B8A8_UNORM;
			aspectFlags = VK_IMAGE_ASPECT_COLOR_BIT;

			if (att.usage & ATTACHMENT_USAGE_COLOR)
				usage |= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT;
			if (att.usage & ATTACHMENT_USAGE_INPUT)
				usage |= VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
		}

		const VkImageCreateInfo		imageParams		=
		{
			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType
			DE_NULL,									// const void*				pNext
			0u,											// VkImageCreateFlags		flags
			VK_IMAGE_TYPE_2D,							// VkImageType				imageType
			format,										// VkFormat					format
			{ m_imageSize.x(), m_imageSize.y(), 1u },	// VkExtent3D				extent
			1u,											// deUint32					mipLevels
			1u,											// deUint32					arrayLayers
			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples
			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling
			usage,										// VkImageUsageFlags		usage
			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode
			1u,											// deUint32					queueFamilyIndexCount
			&queueFamilyIndex,							// const deUint32*			pQueueFamilyIndices
			VK_IMAGE_LAYOUT_UNDEFINED					// VkImageLayout			initialLayout
		};

		attachmentImages.push_back(createImage(vk, vkDevice, &imageParams));

		// Allocate and bind image memory.
		attachmentImageAllocs.push_back(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *attachmentImages.back()), MemoryRequirement::Any));
		VK_CHECK(vk.bindImageMemory(vkDevice, *attachmentImages.back(), attachmentImageAllocs.back()->getMemory(), attachmentImageAllocs.back()->getOffset()));

		// Create image view.
		const VkImageViewCreateInfo	imageViewParams	=
		{
			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType
			DE_NULL,									// const void*				pNext
			0u,											// VkImageViewCreateFlags	flags
			*attachmentImages.back(),					// VkImage					image
			VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType
			format,										// VkFormat					format
			componentMappingRGBA,						// VkChannelMapping			channels
			{ aspectFlags, 0u, 1u, 0u, 1u }				// VkImageSubresourceRange	subresourceRange
		};

		imageViews.push_back(createImageView(vk, vkDevice, &imageViewParams));

		if (att.init & ATTACHMENT_INIT_PRE)
		{
			// Preinitialize image
			deUint32 firstUsage = getFirstUsage((deUint32)attachmentImages.size() - 1, m_testParams.subpasses);
			if (firstUsage == ATTACHMENT_USAGE_UNDEFINED)
				firstUsage = att.usage;

			if (firstUsage & ATTACHMENT_USAGE_DEPTH_STENCIL)
			{
				clearDepthStencilImage(vk, vkDevice, queue, queueFamilyIndex, *attachmentImages.back(), 0.5f, 128u,
									   VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
									   VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
			}
			else
			{
				clearColorImage(vk, vkDevice, queue, queueFamilyIndex, *attachmentImages.back(), tcu::Vec4(0.0f, 1.0f, 0.0f, 1.0f),
								VK_IMAGE_LAYOUT_UNDEFINED, firstUsage & ATTACHMENT_USAGE_COLOR ? VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,
								VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT);
			}
		}
	}

	// Create render pass.
	if (m_testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, m_testParams);
	else
		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, m_testParams);

	// Create framebuffer.
	{
		std::vector<VkImageView>		views;
		for (const auto& view : imageViews)
			views.push_back(*view);

		const VkFramebufferCreateInfo	framebufferParams	=
		{
			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType
			DE_NULL,									// const void*				pNext
			0u,											// VkFramebufferCreateFlags	flags
			*m_renderPass,								// VkRenderPass				renderPass
			(deUint32)views.size(),						// deUint32					attachmentCount
			views.data(),								// const VkImageView*		pAttachments
			(deUint32)m_imageSize.x(),					// deUint32					width
			(deUint32)m_imageSize.y(),					// deUint32					height
			1u											// deUint32					layers
		};

		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
	}

	// Create shader modules
	Unique<VkShaderModule>		vertexShaderModule			(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0));
	Unique<VkShaderModule>		fragmentShaderModule		(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag"), 0));
	Unique<VkShaderModule>		fragmentShaderModuleBlend	(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_blend"), 0));
	Unique<VkShaderModule>		fragmentShaderModuleInput	(createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_input"), 0));

	// Create descriptor pool. Prepare for using one input attachment at most.
	{
		const VkDescriptorPoolSize			descriptorPoolSize			=
		{
			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		type
			1u										// deUint32				descriptorCount
		};

		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
		{
			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,		// VkStructureType				sType
			DE_NULL,											// const void*					pNext
			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	// VkDescriptorPoolCreateFlags	flags
			1u,													// deUint32						maxSets
			1u,													// deUint32						poolSizeCount
			&descriptorPoolSize									// const VkDescriptorPoolSize*	pPoolSizes
		};

		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
	}

	std::vector<Move<VkDescriptorSetLayout>>		descriptorSetLayouts;
	std::vector<Move<VkDescriptorSet>>				descriptorSets;
	std::vector<Move<VkPipelineLayout>>				pipelineLayouts;

	for (const auto& subpass : m_testParams.subpasses)
	{
		deUint32	numInputAttachments	= 0u;
		bool		noColorWrite		= false;
		bool		depthTest			= false;
		bool		stencilTest			= false;

		// Create pipeline layout.
		{
			std::vector<VkDescriptorSetLayoutBinding>	layoutBindings;

			for (const auto ref : subpass.attachmentRefs)
			{
				if (ref.usage & ATTACHMENT_USAGE_INPUT)
				{
					const VkDescriptorSetLayoutBinding	layoutBinding	=
					{
						0u,										// deUint32				binding
						VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		descriptorType
						1u,										// deUint32				descriptorCount
						VK_SHADER_STAGE_FRAGMENT_BIT,			// VkShaderStageFlags	stageFlags
						DE_NULL									// const VkSampler*		pImmutableSamplers
					};

					layoutBindings.push_back(layoutBinding);
					numInputAttachments++;
				}
				if (ref.usage & ATTACHMENT_USAGE_COLOR)
				{
					if (ref.usage & ATTACHMENT_USAGE_WRITE_OFF)
						noColorWrite = true;
				}
				if (ref.usage & ATTACHMENT_USAGE_DEPTH)
				{
					if (!(ref.usage & ATTACHMENT_USAGE_WRITE_OFF))
						depthTest = true;
				}
				if (ref.usage & ATTACHMENT_USAGE_STENCIL)
				{
					if (!(ref.usage & ATTACHMENT_USAGE_WRITE_OFF))
						stencilTest = true;
				}
			}

			const VkDescriptorSetLayoutCreateInfo		descriptorSetLayoutParams	=
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,		// VkStructureType						sType
				DE_NULL,													// const void*							pNext
				0u,															// VkDescriptorSetLayoutCreateFlags		flags
				(deUint32) layoutBindings.size(),							// deUint32								bindingCount
				layoutBindings.empty() ? DE_NULL : layoutBindings.data()	// const VkDescriptorSetLayoutBinding*	pBindings
			};
			descriptorSetLayouts.push_back(createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams));

			const VkPipelineLayoutCreateInfo			pipelineLayoutParams		=
			{
				VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	// VkStructureType				sType
				DE_NULL,										// const void*					pNext
				0u,												// VkPipelineLayoutCreateFlags	flags
				1u,												// deUint32						setLayoutCount
				&descriptorSetLayouts.back().get(),				// const VkDescriptorSetLayout*	pSetLayouts
				0u,												// deUint32						pushConstantRangeCount
				DE_NULL											// const VkPushConstantRange*	pPushConstantRanges
			};

			pipelineLayouts.push_back(createPipelineLayout(vk, vkDevice, &pipelineLayoutParams));
		}

		// Update descriptor set if needed.
		if (numInputAttachments > 0u)
		{
			// Assuming there's only one input attachment at most.
			DE_ASSERT(numInputAttachments == 1u);


			const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
			{
				VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,	// VkStructureType				sType
				DE_NULL,										// const void*					pNext
				*m_descriptorPool,								// VkDescriptorPool				descriptorPool
				1u,												// deUint32						descriptorSetCount
				&descriptorSetLayouts.back().get(),				// const VkDescriptorSetLayout*	pSetLayouts
			};

			descriptorSets.push_back(allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo));

			for (size_t i = 0; i < imageViews.size(); i++)
			{
				if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_INPUT)
				{
					const VkDescriptorImageInfo	inputImageInfo	=
					{
						DE_NULL,									// VkSampler		sampler
						*imageViews[i],								// VkImageView		imageView
						VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout
					};

					const VkWriteDescriptorSet	descriptorWrite	=
					{
						VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,	// VkStructureType					sType
						DE_NULL,								// const void*						pNext
						*descriptorSets.back(),					// VkDescriptorSet					dstSet
						0u,										// deUint32							dstBinding
						0u,										// deUint32							dstArrayElement
						1u,										// deUint32							descriptorCount
						VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType					descriptorType
						&inputImageInfo,						// const VkDescriptorImageInfo*		pImageInfo
						DE_NULL,								// const VkDescriptorBufferInfo*	pBufferInfo
						DE_NULL									// const VkBufferView*				pTexelBufferView
					};
					vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
				}
			}
		}

		// Create pipeline.
		{
			const VkVertexInputBindingDescription		vertexInputBindingDescription		=
			{
				0u,								// deUint32					binding
				(deUint32)sizeof(Vertex4RGBA),			// deUint32					strideInBytes
				VK_VERTEX_INPUT_RATE_VERTEX		// VkVertexInputStepRate	inputRate
			};

			const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
			{
				{
					0u,								// deUint32	location
					0u,								// deUint32	binding
					VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format
					0u								// deUint32	offset
				},
				{
					1u,								// deUint32	location
					0u,								// deUint32	binding
					VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat	format
					(deUint32)(sizeof(float) * 4),	// deUint32	offset
				}
			};

			const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
			{
				VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType
				DE_NULL,													// const void*								pNext
				0u,															// VkPipelineVertexInputStateCreateFlags	flags
				1u,															// deUint32									vertexBindingDescriptionCount
				&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions
				2u,															// deUint32									vertexAttributeDescriptionCount
				vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions
			};

			const VkColorComponentFlags					writeMask							= noColorWrite ? 0 : VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
																											   | VK_COLOR_COMPONENT_G_BIT
																											   | VK_COLOR_COMPONENT_B_BIT
																											   | VK_COLOR_COMPONENT_A_BIT;

			const VkPipelineColorBlendAttachmentState	colorBlendAttachmentState			=
			{
				m_testParams.alphaBlend,				// VkBool32					blendEnable
				VK_BLEND_FACTOR_SRC_ALPHA,				// VkBlendFactor			srcColorBlendFactor
				VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,	// VkBlendFactor			dstColorBlendFactor
				VK_BLEND_OP_ADD,						// VkBlendOp				colorBlendOp
				VK_BLEND_FACTOR_ONE,					// VkBlendFactor			srcAlphaBlendFactor
				VK_BLEND_FACTOR_ZERO,					// VkBlendFactor			dstAlphaBlendFactor
				VK_BLEND_OP_ADD,						// VkBlendOp				alphaBlendOp
				writeMask								// VkColorComponentFlags	colorWriteMask
			};

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

			const VkStencilOpState							stencilOpState					=
			{
				VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp
				VK_STENCIL_OP_REPLACE,	// VkStencilOp	passOp
				VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp
				VK_COMPARE_OP_GREATER,	// VkCompareOp	compareOp
				0xff,					// deUint32		compareMask
				0xff,					// deUint32		writeMask
				0xff					// deUint32		reference
			};

			const VkPipelineDepthStencilStateCreateInfo		depthStencilStateParams			=
			{
				VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	// VkStructureType							sType
				DE_NULL,													// const void*								pNext
				0u,															// VkPipelineDepthStencilStateCreateFlags	flags
				depthTest,													// VkBool32									depthTestEnable
				VK_TRUE,													// VkBool32									depthWriteEnable
				VK_COMPARE_OP_GREATER,										// VkCompareOp								depthCompareOp
				VK_FALSE,													// VkBool32									depthBoundsTestEnable
				stencilTest,												// VkBool32									stencilTestEnable
				stencilOpState,												// VkStencilOpState							front
				stencilOpState,												// VkStencilOpState							back
				0.0f,														// float									minDepthBounds
				1.0f,														// float									maxDepthBounds
			};

			const std::vector<VkViewport>					viewports						(1, makeViewport(m_imageSize));
			const std::vector<VkRect2D>						scissors						(1, makeRect2D(m_renderSize));
			VkShaderModule									fragShader						= *fragmentShaderModule;

			if (numInputAttachments > 0u)
				fragShader = *fragmentShaderModuleInput;
			else if (m_testParams.alphaBlend)
				fragShader = *fragmentShaderModuleBlend;

			pipelines.push_back(makeGraphicsPipeline(
				vk,										// const DeviceInterface&						vk
				vkDevice,								// const VkDevice								device
				*pipelineLayouts.back(),				// const VkPipelineLayout						pipelineLayout
				*vertexShaderModule,					// const VkShaderModule							vertexShaderModule
				DE_NULL,								// const VkShaderModule							tessellationControlModule
				DE_NULL,								// const VkShaderModule							tessellationEvalModule
				DE_NULL,								// const VkShaderModule							geometryShaderModule
				fragShader,								// const VkShaderModule							fragmentShaderModule
				*m_renderPass,							// const VkRenderPass							renderPass
				viewports,								// const std::vector<VkViewport>&				viewports
				scissors,								// const std::vector<VkRect2D>&					scissors
				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
				(deUint32)pipelines.size(),				// const deUint32								subpass
				0u,										// const deUint32								patchControlPoints
				&vertexInputStateParams,				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
				DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
				DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*	multisampleStateCreateInfo
				&depthStencilStateParams,				// const VkPipelineDepthStencilStateCreateInfo*	depthStencilStateCreateInfo
				&colorBlendStateParams));				// const VkPipelineColorBlendStateCreateInfo*	colorBlendStateCreateInfo
		}
	}

	// Create vertex buffer.
	{
		const VkBufferCreateInfo	vertexBufferParams	=
		{
			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType
			DE_NULL,													// const void*			pNext
			0u,															// VkBufferCreateFlags	flags
			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size
			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage
			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode
			1u,															// deUint32				queueFamilyIndexCount
			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices
		};

		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);

		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));

		// Upload vertex data.
		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
	}

	// Create command pool.
	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);

	// Create command buffer.
	if (m_testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice, descriptorSets, pipelineLayouts, pipelines);
	else
		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice, descriptorSets, pipelineLayouts, pipelines);

	// Submit commands.
	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());

	bool pass = true;

	// Verify selected attachments.
	for (size_t i = 0; i < m_testParams.attachments.size(); i++)
	{
		if (m_testParams.attachments[i].verifyInner || m_testParams.attachments[i].verifyOuter)
		{
			de::MovePtr<tcu::TextureLevel>		textureLevelResult;

			SimpleAllocator						allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));

			if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_DEPTH)
			{
				textureLevelResult = pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], m_testParams.depthStencilFormat, m_imageSize, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
			}
			else if (m_testParams.attachments[i].usage & ATTACHMENT_USAGE_STENCIL)
			{
				textureLevelResult = pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], m_testParams.depthStencilFormat, m_imageSize, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
			}
			else
			{
				textureLevelResult = pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *attachmentImages[i], VK_FORMAT_R8G8B8A8_UNORM, m_imageSize, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
			}

			const tcu::ConstPixelBufferAccess&	access				= textureLevelResult->getAccess();

			// Log attachment contents
			m_context.getTestContext().getLog() << tcu::TestLog::ImageSet("Attachment " + de::toString(i), "")
												<< tcu::TestLog::Image("Attachment " + de::toString(i), "", access)
												<< tcu::TestLog::EndImageSet;

			for (int y = 0; y < access.getHeight(); y++)
				for (int x = 0; x < access.getWidth(); x++)
				{
					const bool		inner	= x < (int)m_renderSize.x() && y < (int)m_renderSize.y();

					if (inner && !m_testParams.attachments[i].verifyInner)
						continue;
					if (!inner && !m_testParams.attachments[i].verifyOuter)
						continue;

					const tcu::Vec4	ref		= inner ? m_testParams.attachments[i].innerRef : m_testParams.attachments[i].outerRef;
					const tcu::Vec4	p		= access.getPixel(x, y);

					for (int c = 0; c < 4; c++)
						if (fabs(p[c] - ref[c]) > 0.01f)
							pass = false;
				}

		}
	}

	if (pass)
		return tcu::TestStatus::pass("Pass");
	else
		return tcu::TestStatus::fail("Fail");
}

} // anonymous

tcu::TestCaseGroup* createRenderPassLoadStoreOpNoneTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
{
	de::MovePtr<tcu::TestCaseGroup>		opNoneTests		(new tcu::TestCaseGroup(testCtx, "load_store_op_none", ""));

	const tcu::Vec4	red			(1.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4	green		(0.0f, 1.0f, 0.0f, 1.0f);
	const tcu::Vec4	magenta		(1.0f, 0.0f, 1.0f, 1.0f);
	const tcu::Vec4	darkBlue	(0.0f, 0.0f, 0.5f, 1.0f);
	const tcu::Vec4	blend		(0.5f, 0.0f, 0.25f, 0.5f);
	const tcu::Vec4	depthInit	(0.5f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4	depthFull	(1.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4	stencilInit	(128.0f, 0.0f, 0.0f, 1.0f);
	const tcu::Vec4	stencilFull	(255.0f, 0.0f, 0.0f, 1.0f);

	// Preinitialize attachments 0 and 1 to green.
	// Subpass 0: draw a red rectangle inside attachment 0.
	// Subpass 1: use the attachment 0 as input and add blue channel to it resulting in magenta. Write the results to
	// attachment 1.
	// After the render pass attachment 0 has undefined values inside the render area because of the shader writes with
	// store op 'none', but outside should still have the preinitialized value of green. Attachment 1 should have the
	// preinitialized green outside the render area and magenta inside.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_INPUT,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_NONE_EXT,
									  ATTACHMENT_INIT_PRE,
									  false, green,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_DONT_CARE,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, magenta,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_INPUT}, {1u, ATTACHMENT_USAGE_COLOR}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_load_store_op_none", "", params));
	}

	// Preinitialize color attachment to green. Use a render pass with load and store ops none, but
	// disable color writes using an empty color mask. The color attachment image should have the original
	// preinitialized value after the render pass.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_NONE_EXT,
									  ATTACHMENT_INIT_PRE,
									  true, green,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_WRITE_OFF}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_none_write_off", "", params));
	}

	// Preinitialize color attachment to green. Use a render pass with load and store ops none, and
	// write a rectange to the color buffer. The render area is undefined, but the outside area should
	// still have the preinitialized color.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_NONE_EXT,
									  ATTACHMENT_INIT_PRE,
									  false, green,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_none", "", params));
	}

	// Preinitialize color attachment to green. Use a subpass with no draw calls but instead
	// do an attachment clear command using dark blue color. Using load op none preserves the preinitialized
	// data and store op store causes the cleared blue render area to be present after the render pass.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
									  true, darkBlue,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 0u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_store", "", params));
	}

	// Preinitialize color attachment to green. Use a subpass with a dark blue attachment clear followed
	// by an alpha blender draw. Load op is none preserves the preinitialized data and store op store
	// keeps the blended color inside the render area after the render pass.
	{
		TestParams params;
		params.alphaBlend = true;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
									  true, blend,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_store_alphablend", "", params));
	}

	// Preinitialize attachments 0 and 1 to green. Attachment 0 contents inside render area is undefined  because load op 'none'.
	// Subpass 0: draw a red rectangle inside attachment 0 overwriting all undefined values.
	// Subpass 1: use the attachment 0 as input and add blue to it resulting in magenta. Write the results to attachment 1.
	// After the render pass attachment 0 contents inside the render area are undefined because of store op 'don't care',
	// but the outside area should still have the preinitialized content.
	// Attachment 1 should have the preinitialized green outside render area and magenta inside.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR | ATTACHMENT_USAGE_INPUT,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_DONT_CARE,
									  ATTACHMENT_INIT_PRE,
									  false, green,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, magenta,
									  true, green});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}}, 1u});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_INPUT}, {1u, ATTACHMENT_USAGE_COLOR}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "color_load_op_none_store_op_dontcare", "", params));
	}

	// Preinitialize attachment 0 (color) to green and attachment 1 (depth) to 0.5.
	// Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update
	// depth buffer to 1.0.
	// This is followed by another draw with a blue rectangle using the same depth of 1.0. This time
	// the depth test fails and nothing is written.
	// After the renderpass the red color should remain inside the render area of the color buffer.
	// Store op 'store' for depth buffer makes the written values undefined, but the pixels outside
	// render area should still contain the original value of 0.5.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, red,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_NONE_EXT,
									  ATTACHMENT_INIT_PRE,
									  false, depthInit,
									  true, depthInit});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 2u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_load_op_load_store_op_none", "", params));
	}

	// Preinitialize depth attachment to 0.5. Use a render pass with load and store ops none for the depth, but
	// disable depth test which also disables depth writes. The depth attachment should have the original
	// preinitialized value after the render pass.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, red,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_NONE_EXT,
									  ATTACHMENT_INIT_PRE,
									  true, depthInit,
									  true, depthInit});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH | ATTACHMENT_USAGE_WRITE_OFF}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_load_op_none_store_op_none_write_off", "", params));
	}

	// Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25
	// using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update
	// depth buffer to 1.0. After the renderpass the color buffer should have red inside the render area and depth should have the
	// shader updated value of 1.0.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, red,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
									  true, depthFull,
									  true, depthInit});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_load_op_none_store_op_store", "", params));
	}

	// Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25
	// using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater' which will pass.
	// After the renderpass the color buffer should have red inside the render area. Depth buffer contents inside render
	// are is undefined because of store op 'don't care', but the outside should have the original value of 0.5.
	{
		TestParams params;
		params.alphaBlend = false;
		params.renderPassType = renderPassType;
		params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
									  VK_ATTACHMENT_LOAD_OP_LOAD,
									  VK_ATTACHMENT_STORE_OP_STORE,
									  ATTACHMENT_INIT_PRE,
									  true, red,
									  true, green});
		params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
									  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
									  VK_ATTACHMENT_STORE_OP_DONT_CARE,
									  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
									  false, depthFull,
									  true, depthInit});
		params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u});

		opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_load_op_none_store_op_dontcare", "", params));
	}

	std::vector<VkFormat>	formats = { VK_FORMAT_D16_UNORM_S8_UINT, VK_FORMAT_D24_UNORM_S8_UINT, VK_FORMAT_D32_SFLOAT_S8_UINT };

	for (deUint32 f = 0; f < formats.size(); ++f)
	{
		const std::string	formatName = getFormatCaseName(formats[f]);

		// Preinitialize attachment 0 (color) to green and attachment 1 (depth) to 0.5.
		// Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update
		// depth buffer to 1.0.
		// This is followed by another draw with a blue rectangle using the same depth of 1.0. This time
		// the depth test fails and nothing is written.
		// After the renderpass the red color should remain inside the render area of the color buffer.
		// Store op 'store' for depth buffer makes the written values undefined, but the pixels outside
		// render area should still contain the original value of 0.5.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_NONE_EXT,
										  ATTACHMENT_INIT_PRE,
										  false, depthInit,
										  true, depthInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 2u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_load_store_op_none", "", params));
		}

		// Preinitialize depth attachment to 0.5. Use a render pass with load and store ops none for the depth, but
		// disable depth test which also disables depth writes. The depth attachment should have the original
		// preinitialized value after the render pass.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_NONE_EXT,
										  ATTACHMENT_INIT_PRE,
										  true, depthInit,
										  true, depthInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH | ATTACHMENT_USAGE_WRITE_OFF}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_none_write_off", "", params));
		}

		// Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25
		// using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater'. Depth test will pass and update
		// depth buffer to 1.0. After the renderpass the color buffer should have red inside the render area and depth should have the
		// shader updated value of 1.0.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
										  true, depthFull,
										  true, depthInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_store", "", params));
		}

		// Preinitialize attachment 0 (color) to green and depth buffer to 0.5. During the render pass initialize attachment 1 (depth) to 0.25
		// using cmdClearAttachments. Draw a red rectangle using depth 1.0 and depth op 'greater' which will pass.
		// After the renderpass the color buffer should have red inside the render area. Depth buffer contents inside render
		// are is undefined because of store op 'don't care', but the outside should have the original value of 0.5.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_DEPTH,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_DONT_CARE,
										  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
										  false, depthFull,
										  true, depthInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_DEPTH}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "depth_" + formatName + "_load_op_none_store_op_dontcare", "", params));
		}

		// Preinitialize attachment 0 (color) to green and attachment 1 (stencil) to 128.
		// Draw a red rectangle using stencil testing with compare op 'greater' and reference of 255. The stencil test
		// will pass. This is followed by another draw with a blue rectangle using the same stencil settings. This time
		// the stencil test fails and nothing is written.
		// After the renderpass the red color should remain inside the render area of the color buffer.
		// Store op 'store' for stencil buffer makes the written values undefined, but the pixels outside
		// render area should still contain the original value of 128.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_STENCIL,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_NONE_EXT,
										  ATTACHMENT_INIT_PRE,
										  false, stencilInit,
										  true, stencilInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 2u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_load_store_op_none", "", params));
		}

		// Preinitialize stencil attachment to 128. Use a render pass with load and store ops none for the stencil, but
		// disable stencil test which also disables stencil writes. The stencil attachment should have the original
		// preinitialized value after the render pass.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_STENCIL,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_NONE_EXT,
										  ATTACHMENT_INIT_PRE,
										  true, stencilInit,
										  true, stencilInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL | ATTACHMENT_USAGE_WRITE_OFF}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_none_write_off", "", params));
		}

		// Preinitialize attachment 0 (color) to green and stencil buffer to 128. During the render pass initialize attachment 1 (stencil) to 64
		// using cmdClearAttachments. Draw a red rectangle using stencil reference of 255 and stencil op 'greater'. Stencil test will pass and update
		// stencil buffer to 255. After the renderpass the color buffer should have red inside the render area and stencil should have the
		// shader updated value of 255.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_STENCIL,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
										  true, stencilFull,
										  true, stencilInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_store", "", params));
		}

		// Preinitialize attachment 0 (color) to green and stencil buffer to 128. During the render pass initialize attachment 1 (stencil) to 64
		// using cmdClearAttachments. Draw a red rectangle using stencil reference 255 and stencil op 'greater' which will pass.
		// After the renderpass the color buffer should have red inside the render area. Stencil buffer contents inside render
		// are is undefined because of store op 'don't care', but the outside should have the original value of 128.
		{
			TestParams params;
			params.alphaBlend = false;
			params.depthStencilFormat = formats[f];
			params.renderPassType = renderPassType;
			params.attachments.push_back({ATTACHMENT_USAGE_COLOR,
										  VK_ATTACHMENT_LOAD_OP_LOAD,
										  VK_ATTACHMENT_STORE_OP_STORE,
										  ATTACHMENT_INIT_PRE,
										  true, red,
										  true, green});
			params.attachments.push_back({ATTACHMENT_USAGE_STENCIL,
										  VK_ATTACHMENT_LOAD_OP_NONE_EXT,
										  VK_ATTACHMENT_STORE_OP_DONT_CARE,
										  ATTACHMENT_INIT_PRE | ATTACHMENT_INIT_CMD_CLEAR,
										  false, stencilFull,
										  true, stencilInit});
			params.subpasses.push_back({{{0u, ATTACHMENT_USAGE_COLOR}, {1u, ATTACHMENT_USAGE_STENCIL}}, 1u});

			opNoneTests->addChild(new LoadStoreOpNoneTest(testCtx, "stencil_" + formatName + "_load_op_none_store_op_dontcare", "", params));
		}
	}

	return opNoneTests.release();
}

} // renderpass
} // vkt
