Home | History | Annotate | Download | only in renderpass
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2018 The Khronos Group Inc.
      6  * Copyright (c) 2018 Google Inc.
      7  * Copyright (c) 2015 Imagination Technologies Ltd.
      8  *
      9  * Licensed under the Apache License, Version 2.0 (the "License");
     10  * you may not use this file except in compliance with the License.
     11  * You may obtain a copy of the License at
     12  *
     13  *      http://www.apache.org/licenses/LICENSE-2.0
     14  *
     15  * Unless required by applicable law or agreed to in writing, software
     16  * distributed under the License is distributed on an "AS IS" BASIS,
     17  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     18  * See the License for the specific language governing permissions and
     19  * limitations under the License.
     20  *
     21  *//*!
     22  * \file
     23  * \brief Tests attachments unused by subpasses
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "vktRenderPassUnusedAttachmentTests.hpp"
     27 #include "pipeline/vktPipelineImageUtil.hpp"
     28 #include "vktTestCase.hpp"
     29 #include "vkImageUtil.hpp"
     30 #include "vkMemUtil.hpp"
     31 #include "vkPlatform.hpp"
     32 #include "vkPrograms.hpp"
     33 #include "vkQueryUtil.hpp"
     34 #include "vkCmdUtil.hpp"
     35 #include "vkRef.hpp"
     36 #include "vkRefUtil.hpp"
     37 #include "vkTypeUtil.hpp"
     38 #include "vkCmdUtil.hpp"
     39 #include "vkObjUtil.hpp"
     40 #include "tcuImageCompare.hpp"
     41 #include "tcuPlatform.hpp"
     42 #include "tcuTextureUtil.hpp"
     43 #include "tcuTestLog.hpp"
     44 #include "deStringUtil.hpp"
     45 #include "deUniquePtr.hpp"
     46 #include "deRandom.hpp"
     47 #include <cstring>
     48 #include <set>
     49 #include <sstream>
     50 #include <vector>
     51 
     52 namespace vkt
     53 {
     54 namespace renderpass
     55 {
     56 
     57 using namespace vk;
     58 
     59 namespace
     60 {
     61 
     62 struct TestParams
     63 {
     64 	VkAttachmentLoadOp	loadOp;
     65 	VkAttachmentStoreOp	storeOp;
     66 	VkAttachmentLoadOp	stencilLoadOp;
     67 	VkAttachmentStoreOp	stencilStoreOp;
     68 	RenderPassType		renderPassType;
     69 };
     70 
     71 struct Vertex4RGBA
     72 {
     73 	tcu::Vec4 position;
     74 	tcu::Vec4 color;
     75 };
     76 
     77 std::vector<Vertex4RGBA> createQuad (void)
     78 {
     79 	std::vector<Vertex4RGBA>	vertices;
     80 
     81 	const float			size				= 0.8f;
     82 	const tcu::Vec4		color				(0.2f, 0.3f, 0.1f, 1.0f);
     83 	const Vertex4RGBA	lowerLeftVertex		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
     84 	const Vertex4RGBA	lowerRightVertex	= {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
     85 	const Vertex4RGBA	upperLeftVertex		= {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
     86 	const Vertex4RGBA	upperRightVertex	= {tcu::Vec4(size, size, 0.0f, 1.0f), color};
     87 
     88 	vertices.push_back(lowerLeftVertex);
     89 	vertices.push_back(lowerRightVertex);
     90 	vertices.push_back(upperLeftVertex);
     91 	vertices.push_back(upperLeftVertex);
     92 	vertices.push_back(lowerRightVertex);
     93 	vertices.push_back(upperRightVertex);
     94 
     95 	return vertices;
     96 }
     97 
     98 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
     99 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vk,
    100 									 VkDevice				vkDevice,
    101 									 const TestParams		testParams)
    102 {
    103 	const VkImageAspectFlags	aspectMask						= testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
    104 	const AttachmentDesc		attachmentDescriptions[]		=
    105 	{
    106 		// Result attachment
    107 		AttachmentDesc (
    108 			DE_NULL,									// const void*						pNext
    109 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
    110 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
    111 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
    112 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
    113 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
    114 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
    115 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
    116 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
    117 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
    118 		),
    119 		// Unused attachment
    120 		AttachmentDesc (
    121 			DE_NULL,									// const void*						pNext
    122 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
    123 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
    124 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
    125 			testParams.loadOp,							// VkAttachmentLoadOp				loadOp
    126 			testParams.storeOp,							// VkAttachmentStoreOp				storeOp
    127 			testParams.stencilLoadOp,					// VkAttachmentLoadOp				stencilLoadOp
    128 			testParams.stencilStoreOp,					// VkAttachmentStoreOp				stencilStoreOp
    129 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
    130 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
    131 		),
    132 		// Input attachment
    133 		AttachmentDesc (
    134 			DE_NULL,									// const void*						pNext
    135 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
    136 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
    137 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
    138 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
    139 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
    140 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
    141 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
    142 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
    143 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
    144 		)
    145 	};
    146 
    147 	// Note: Attachment 1 is not referenced by any subpass.
    148 	const AttachmentRef			resultAttachmentRefSubpass0		(
    149 		DE_NULL,									// const void*			pNext
    150 		2u,											// deUint32				attachment
    151 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
    152 		aspectMask									// VkImageAspectFlags	aspectMask
    153 	);
    154 
    155 	const AttachmentRef			resultAttachmentRefSubpass1		(
    156 		DE_NULL,									// const void*			pNext
    157 		0u,											// deUint32				attachment
    158 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
    159 		aspectMask									// VkImageAspectFlags	aspectMask
    160 	);
    161 
    162 	const AttachmentRef			inputAttachmentRefSubpass1		(
    163 		DE_NULL,									// const void*			pNext
    164 		2u,											// deUint32				attachment
    165 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout		layout
    166 		aspectMask									// VkImageAspectFlags	aspectMask
    167 	);
    168 
    169 	const SubpassDesc			subpassDescriptions[]			=
    170 	{
    171 		SubpassDesc (
    172 			DE_NULL,
    173 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
    174 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
    175 			0u,									// deUint32							viewMask
    176 			0u,									// deUint32							inputAttachmentCount
    177 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments
    178 			1u,									// deUint32							colorAttachmentCount
    179 			&resultAttachmentRefSubpass0,		// const VkAttachmentReference*		pColorAttachments
    180 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments
    181 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment
    182 			0u,									// deUint32							preserveAttachmentCount
    183 			DE_NULL								// const deUint32*					pPreserveAttachments
    184 		),
    185 		SubpassDesc (
    186 			DE_NULL,
    187 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
    188 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
    189 			0u,									// deUint32							viewMask
    190 			1u,									// deUint32							inputAttachmentCount
    191 			&inputAttachmentRefSubpass1,		// const VkAttachmentReference*		pInputAttachments
    192 			1u,									// deUint32							colorAttachmentCount
    193 			&resultAttachmentRefSubpass1,		// const VkAttachmentReference*		pColorAttachments
    194 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments
    195 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment
    196 			0u,									// deUint32							preserveAttachmentCount
    197 			DE_NULL								// const deUint32*					pPreserveAttachments
    198 		)
    199 	};
    200 
    201 	const SubpassDep			subpassDependency				(
    202 		DE_NULL,										// const void*				pNext
    203 		0u,												// uint32_t					srcSubpass
    204 		1u,												// uint32_t					dstSubpass
    205 		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		srcStageMask
    206 		VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags		dstStageMask
    207 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask
    208 		VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// VkAccessFlags			dstAccessMask
    209 		VK_DEPENDENCY_BY_REGION_BIT,					// VkDependencyFlags		dependencyFlags
    210 		0u												// deInt32					viewOffset
    211 	);
    212 
    213 	const RenderPassCreateInfo	renderPassInfo					(
    214 		DE_NULL,									// const void*						pNext
    215 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
    216 		3u,											// deUint32							attachmentCount
    217 		attachmentDescriptions,						// const VkAttachmentDescription*	pAttachments
    218 		2u,											// deUint32							subpassCount
    219 		subpassDescriptions,						// const VkSubpassDescription*		pSubpasses
    220 		1u,											// deUint32							dependencyCount
    221 		&subpassDependency,							// const VkSubpassDependency*		pDependencies
    222 		0u,											// deUint32							correlatedViewMaskCount
    223 		DE_NULL										// const deUint32*					pCorrelatedViewMasks
    224 	);
    225 
    226 	return renderPassInfo.createRenderPass(vk, vkDevice);
    227 }
    228 
    229 class UnusedAttachmentTest : public vkt::TestCase
    230 {
    231 public:
    232 										UnusedAttachmentTest	(tcu::TestContext&	testContext,
    233 																 const std::string&	name,
    234 																 const std::string&	description,
    235 																 const TestParams&	testParams);
    236 	virtual								~UnusedAttachmentTest	(void);
    237 	virtual void						initPrograms			(SourceCollections&	sourceCollections) const;
    238 	virtual TestInstance*				createInstance			(Context&			context) const;
    239 private:
    240 	const TestParams					m_testParams;
    241 };
    242 
    243 class UnusedAttachmentTestInstance : public vkt::TestInstance
    244 {
    245 public:
    246 										UnusedAttachmentTestInstance	(Context&				context,
    247 																		 const TestParams&		testParams);
    248 	virtual								~UnusedAttachmentTestInstance	(void);
    249 	virtual tcu::TestStatus				iterate							(void);
    250 	template<typename RenderpassSubpass>
    251 	void								createCommandBuffer				(const DeviceInterface&	vk,
    252 																		 VkDevice				vkDevice);
    253 private:
    254 	tcu::TestStatus						verifyImage						(void);
    255 
    256 	const tcu::UVec2					m_renderSize;
    257 
    258 	Move<VkImage>						m_colorImage;
    259 	de::MovePtr<Allocation>				m_colorImageAlloc;
    260 	Move<VkImageView>					m_colorAttachmentView;
    261 
    262 	Move<VkImage>						m_unusedImage;
    263 	de::MovePtr<Allocation>				m_unusedImageAlloc;
    264 	Move<VkImageView>					m_unusedAttachmentView;
    265 
    266 	Move<VkImage>						m_inputImage;
    267 	de::MovePtr<Allocation>				m_inputImageAlloc;
    268 	Move<VkImageView>					m_inputAttachmentView;
    269 
    270 	Move<VkDescriptorSetLayout>			m_descriptorSetLayoutSubpass0;
    271 	Move<VkDescriptorSetLayout>			m_descriptorSetLayoutSubpass1;
    272 	Move<VkDescriptorPool>				m_descriptorPool;
    273 	Move<VkDescriptorSet>				m_descriptorSetSubpass1;
    274 	Move<VkRenderPass>					m_renderPass;
    275 	Move<VkFramebuffer>					m_framebuffer;
    276 
    277 	Move<VkShaderModule>				m_vertexShaderModule;
    278 	Move<VkShaderModule>				m_fragmentShaderModuleSubpass0;
    279 	Move<VkShaderModule>				m_fragmentShaderModuleSubpass1;
    280 
    281 	Move<VkBuffer>						m_vertexBuffer;
    282 	std::vector<Vertex4RGBA>			m_vertices;
    283 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
    284 
    285 	Move<VkBuffer>						m_backingBuffer;
    286 	de::MovePtr<Allocation>				m_backingBufferAlloc;
    287 
    288 	Move<VkPipelineLayout>				m_pipelineLayoutSubpass0;
    289 	Move<VkPipelineLayout>				m_pipelineLayoutSubpass1;
    290 	Move<VkPipeline>					m_graphicsPipelineSubpass0;
    291 	Move<VkPipeline>					m_graphicsPipelineSubpass1;
    292 
    293 	Move<VkCommandPool>					m_cmdPool;
    294 	Move<VkCommandBuffer>				m_cmdBuffer;
    295 };
    296 
    297 UnusedAttachmentTest::UnusedAttachmentTest (tcu::TestContext&	testContext,
    298 											const std::string&	name,
    299 											const std::string&	description,
    300 											const TestParams&	testParams)
    301 	: vkt::TestCase	(testContext, name, description)
    302 	, m_testParams	(testParams)
    303 {
    304 }
    305 
    306 UnusedAttachmentTest::~UnusedAttachmentTest (void)
    307 {
    308 }
    309 
    310 TestInstance* UnusedAttachmentTest::createInstance (Context& context) const
    311 {
    312 	return new UnusedAttachmentTestInstance(context, m_testParams);
    313 }
    314 
    315 void UnusedAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
    316 {
    317 	std::ostringstream fragmentSource;
    318 
    319 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
    320 		"#version 450\n"
    321 		"layout(location = 0) in highp vec4 position;\n"
    322 		"layout(location = 1) in highp vec4 color;\n"
    323 		"layout(location = 0) out highp vec4 vtxColor;\n"
    324 		"void main (void)\n"
    325 		"{\n"
    326 		"	gl_Position = position;\n"
    327 		"	vtxColor = color;\n"
    328 		"}\n");
    329 
    330 	sourceCollections.glslSources.add("color_frag_sb0") << glu::FragmentSource(
    331 		"#version 450\n"
    332 		"layout(location = 0) in highp vec4 vtxColor;\n"
    333 		"layout(location = 0) out highp vec4 fragColor;\n"
    334 		"void main (void)\n"
    335 		"{\n"
    336 		"	fragColor = vtxColor;\n"
    337 		"}\n");
    338 
    339 	sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
    340 		"#version 450\n"
    341 		"layout(location = 0) in highp vec4 vtxColor;\n"
    342 		"layout(location = 0) out highp vec4 fragColor;\n"
    343 		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
    344 		"void main (void)\n"
    345 		"{\n"
    346 		"	fragColor = subpassLoad(inputColor) + vtxColor;\n"
    347 		"}\n");
    348 }
    349 
    350 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance (Context&			context,
    351 															const TestParams&	testParams)
    352 	: vkt::TestInstance	(context)
    353 	, m_renderSize		(32u, 32u)
    354 	, m_vertices		(createQuad())
    355 {
    356 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
    357 	const VkDevice				vkDevice				= m_context.getDevice();
    358 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
    359 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    360 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
    361 
    362 	// Check for renderpass2 extension if used
    363 	if (testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
    364 		context.requireDeviceExtension("VK_KHR_create_renderpass2");
    365 
    366 	// Create color image
    367 	{
    368 		const VkImageCreateInfo	colorImageParams =
    369 		{
    370 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    371 			DE_NULL,																	// const void*				pNext;
    372 			0u,																			// VkImageCreateFlags		flags;
    373 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    374 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
    375 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    376 			1u,																			// deUint32					mipLevels;
    377 			1u,																			// deUint32					arrayLayers;
    378 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    379 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    380 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
    381 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    382 			1u,																			// deUint32					queueFamilyIndexCount;
    383 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    384 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    385 		};
    386 
    387 		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
    388 
    389 		// Allocate and bind color image memory
    390 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
    391 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
    392 	}
    393 
    394 	// Create image which is not used by any subpass
    395 	{
    396 		const VkImageCreateInfo	unusedImageParams =
    397 		{
    398 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    399 			DE_NULL,																	// const void*				pNext;
    400 			0u,																			// VkImageCreateFlags		flags;
    401 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    402 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
    403 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    404 			1u,																			// deUint32					mipLevels;
    405 			1u,																			// deUint32					arrayLayers;
    406 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    407 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    408 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
    409 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT,										// VkImageUsageFlags		usage;
    410 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    411 			1u,																			// deUint32					queueFamilyIndexCount;
    412 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    413 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    414 		};
    415 
    416 		m_unusedImage			= createImage(vk, vkDevice, &unusedImageParams);
    417 
    418 		// Allocate and bind unused image memory
    419 		VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
    420 
    421 		m_unusedImageAlloc		= memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
    422 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(), m_unusedImageAlloc->getOffset()));
    423 
    424 		// Clear image with specific value to verify the contents don't change
    425 		{
    426 			const VkImageAspectFlags		aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
    427 			Move<VkCommandPool>				cmdPool;
    428 			Move<VkCommandBuffer>			cmdBuffer;
    429 
    430 			VkClearValue					clearValue;
    431 			clearValue.color.float32[0] = 0.1f;
    432 			clearValue.color.float32[1] = 0.2f;
    433 			clearValue.color.float32[2] = 0.3f;
    434 			clearValue.color.float32[3] = 0.4f;
    435 
    436 			// Create command pool and buffer
    437 			cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
    438 			cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    439 
    440 			const VkImageMemoryBarrier preImageBarrier =
    441 			{
    442 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
    443 				DE_NULL,								// const void*				pNext;
    444 				0u,										// VkAccessFlags			srcAccessMask;
    445 				VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
    446 				VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
    447 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
    448 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
    449 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
    450 				*m_unusedImage,							// VkImage					image;
    451 				{										// VkImageSubresourceRange	subresourceRange;
    452 					aspectMask,							// VkImageAspect			aspect;
    453 					0u,									// deUint32					baseMipLevel;
    454 					1u,									// deUint32					mipLevels;
    455 					0u,									// deUint32					baseArraySlice;
    456 					1u									// deUint32					arraySize;
    457 				}
    458 			};
    459 
    460 			const VkImageMemoryBarrier postImageBarrier =
    461 			{
    462 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
    463 				DE_NULL,									// const void*				pNext;
    464 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
    465 				VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
    466 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
    467 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
    468 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
    469 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
    470 				*m_unusedImage,								// VkImage					image;
    471 				{											// VkImageSubresourceRange	subresourceRange;
    472 					aspectMask,								// VkImageAspect			aspect;
    473 					0u,										// deUint32					baseMipLevel;
    474 					1u,										// deUint32					mipLevels;
    475 					0u,										// deUint32					baseArraySlice;
    476 					1u										// deUint32					arraySize;
    477 				}
    478 			};
    479 
    480 			const VkImageSubresourceRange clearRange	=
    481 			{
    482 				aspectMask,	// VkImageAspectFlags	aspectMask;
    483 				0u,			// deUint32				baseMipLevel;
    484 				1u,			// deUint32				levelCount;
    485 				0u,			// deUint32				baseArrayLayer;
    486 				1u			// deUint32				layerCount;
    487 			};
    488 
    489 			// Clear image
    490 			beginCommandBuffer(vk, *cmdBuffer);
    491 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
    492 			vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange);
    493 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
    494 			endCommandBuffer(vk, *cmdBuffer);
    495 
    496 			submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
    497 		}
    498 	}
    499 
    500 	// Create input image
    501 	{
    502 		const VkImageCreateInfo	inputImageParams =
    503 		{
    504 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
    505 			DE_NULL,																	// const void*				pNext;
    506 			0u,																			// VkImageCreateFlags		flags;
    507 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
    508 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
    509 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
    510 			1u,																			// deUint32					mipLevels;
    511 			1u,																			// deUint32					arrayLayers;
    512 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
    513 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
    514 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,	// VkImageUsageFlags		usage;
    515 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
    516 			1u,																			// deUint32					queueFamilyIndexCount;
    517 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
    518 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
    519 		};
    520 
    521 		m_inputImage = createImage(vk, vkDevice, &inputImageParams);
    522 
    523 		// Allocate and bind input image memory
    524 		m_inputImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
    525 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(), m_inputImageAlloc->getOffset()));
    526 	}
    527 
    528 	// Create color attachment view
    529 	{
    530 		const VkImageViewCreateInfo colorAttachmentViewParams =
    531 		{
    532 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    533 			DE_NULL,											// const void*				pNext;
    534 			0u,													// VkImageViewCreateFlags	flags;
    535 			*m_colorImage,										// VkImage					image;
    536 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    537 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
    538 			componentMappingRGBA,								// VkChannelMapping			channels;
    539 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    540 		};
    541 
    542 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
    543 	}
    544 
    545 	// Create unused attachment view
    546 	{
    547 		const VkImageViewCreateInfo unusedAttachmentViewParams =
    548 		{
    549 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    550 			DE_NULL,											// const void*				pNext;
    551 			0u,													// VkImageViewCreateFlags	flags;
    552 			*m_unusedImage,										// VkImage					image;
    553 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    554 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
    555 			componentMappingRGBA,								// VkChannelMapping			channels;
    556 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    557 		};
    558 
    559 		m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
    560 	}
    561 
    562 	// Create input attachment view
    563 	{
    564 		const VkImageViewCreateInfo inputAttachmentViewParams =
    565 		{
    566 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
    567 			DE_NULL,											// const void*				pNext;
    568 			0u,													// VkImageViewCreateFlags	flags;
    569 			*m_inputImage,										// VkImage					image;
    570 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
    571 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
    572 			componentMappingRGBA,								// VkChannelMapping			channels;
    573 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
    574 		};
    575 
    576 		m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
    577 	}
    578 
    579 	// Create render pass
    580 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
    581 		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
    582 	else
    583 		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
    584 
    585 	// Create framebuffer
    586 	{
    587 		const VkImageView				imageViews[]		=
    588 		{
    589 			*m_colorAttachmentView,
    590 			*m_unusedAttachmentView,
    591 			*m_inputAttachmentView
    592 		};
    593 
    594 		const VkFramebufferCreateInfo	framebufferParams	=
    595 		{
    596 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
    597 			DE_NULL,									// const void*				pNext;
    598 			0u,											// VkFramebufferCreateFlags	flags;
    599 			*m_renderPass,								// VkRenderPass				renderPass;
    600 			3u,											// deUint32					attachmentCount;
    601 			imageViews,									// const VkImageView*		pAttachments;
    602 			(deUint32)m_renderSize.x(),					// deUint32					width;
    603 			(deUint32)m_renderSize.y(),					// deUint32					height;
    604 			1u											// deUint32					layers;
    605 		};
    606 
    607 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
    608 	}
    609 
    610 	// Create pipeline layout for subpass 0
    611 	{
    612 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
    613 		{
    614 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
    615 			DE_NULL,												// const void*							pNext
    616 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
    617 			0u,														// deUint32								bindingCount
    618 			DE_NULL													// const VkDescriptorSetLayoutBinding*	pBindings
    619 		};
    620 		m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
    621 
    622 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
    623 		{
    624 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
    625 			DE_NULL,											// const void*						pNext;
    626 			0u,													// VkPipelineLayoutCreateFlags		flags;
    627 			1u,													// deUint32							setLayoutCount;
    628 			&m_descriptorSetLayoutSubpass0.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
    629 			0u,													// deUint32							pushConstantRangeCount;
    630 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
    631 		};
    632 
    633 		m_pipelineLayoutSubpass0 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
    634 	}
    635 
    636 	// Create pipeline layout for subpass 1
    637 	{
    638 		const VkDescriptorSetLayoutBinding		layoutBinding				=
    639 		{
    640 			0u,										// deUint32				binding;
    641 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		descriptorType;
    642 			1u,										// deUint32				descriptorCount;
    643 			VK_SHADER_STAGE_FRAGMENT_BIT,			// VkShaderStageFlags	stageFlags;
    644 			DE_NULL									// const VkSampler*		pImmutableSamplers;
    645 		};
    646 
    647 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
    648 		{
    649 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
    650 			DE_NULL,												// const void*							pNext
    651 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
    652 			1u,														// deUint32								bindingCount
    653 			&layoutBinding											// const VkDescriptorSetLayoutBinding*	pBindings
    654 		};
    655 		m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
    656 
    657 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
    658 		{
    659 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
    660 			DE_NULL,											// const void*						pNext;
    661 			0u,													// VkPipelineLayoutCreateFlags		flags;
    662 			1u,													// deUint32							setLayoutCount;
    663 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
    664 			0u,													// deUint32							pushConstantRangeCount;
    665 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
    666 		};
    667 
    668 		m_pipelineLayoutSubpass1 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
    669 	}
    670 
    671 	// Update descriptor set
    672 	{
    673 		const VkDescriptorPoolSize			descriptorPoolSize			=
    674         {
    675 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		type;
    676 			1u										// deUint32				descriptorCount;
    677 		};
    678 
    679 		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
    680 		{
    681 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,		// VkStructureType				sType
    682 			DE_NULL,											// const void*					pNext
    683 			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	// VkDescriptorPoolCreateFlags	flags
    684 			1u,                                                 // deUint32						maxSets
    685 			1u,													// deUint32						poolSizeCount
    686 			&descriptorPoolSize									// const VkDescriptorPoolSize*	pPoolSizes
    687 		};
    688 
    689 		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
    690 
    691 		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
    692 		{
    693 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType
    694 			DE_NULL,											// const void*						pNext
    695 			*m_descriptorPool,									// VkDescriptorPool					descriptorPool
    696 			1u,													// deUint32							descriptorSetCount
    697 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts
    698 		};
    699 
    700 		m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
    701 
    702 		const VkDescriptorImageInfo			inputImageInfo				=
    703 		{
    704 			DE_NULL,									// VkSampleri		sampler;
    705 			*m_inputAttachmentView,						// VkImageView		imageView;
    706 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
    707 		};
    708 
    709 		const VkWriteDescriptorSet			descriptorWrite				=
    710 		{
    711 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
    712 			DE_NULL,									// const void*						pNext;
    713 			*m_descriptorSetSubpass1,					// VkDescriptorSet					dstSet;
    714 			0u,											// deUint32							dstBinding;
    715 			0u,											// deUint32							dstArrayElement;
    716 			1u,											// deUint32							descriptorCount;
    717 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		// VkDescriptorType					descriptorType;
    718 			&inputImageInfo,							// const VkDescriptorImageInfo*		pImageInfo;
    719 			DE_NULL,									// const VkDescriptorBufferInfo*	pBufferInfo;
    720 			DE_NULL										// const VkBufferView*				pTexelBufferView;
    721 		};
    722 
    723 		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
    724 	}
    725 
    726 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
    727 	m_fragmentShaderModuleSubpass0	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
    728 	m_fragmentShaderModuleSubpass1	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
    729 
    730 	// Create pipelines
    731 	{
    732 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
    733 		{
    734 			0u,									// deUint32					binding;
    735 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
    736 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
    737 		};
    738 
    739 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
    740 		{
    741 			{
    742 				0u,								// deUint32		location;
    743 				0u,								// deUint32		binding;
    744 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
    745 				0u								// deUint32		offset;
    746 			},
    747 			{
    748 				1u,								// deUint32		location;
    749 				0u,								// deUint32		binding;
    750 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
    751 				(deUint32)(sizeof(float) * 4),	// deUint32		offset;
    752 			}
    753 		};
    754 
    755 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
    756 		{
    757 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
    758 			DE_NULL,													// const void*								pNext;
    759 			0u,															// VkPipelineVertexInputStateCreateFlags	flags;
    760 			1u,															// deUint32									vertexBindingDescriptionCount;
    761 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
    762 			2u,															// deUint32									vertexAttributeDescriptionCount;
    763 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
    764 		};
    765 
    766 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
    767 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
    768 
    769 		{
    770 			m_graphicsPipelineSubpass0 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
    771 															  vkDevice,								// const VkDevice								device
    772 															  *m_pipelineLayoutSubpass0,			// const VkPipelineLayout						pipelineLayout
    773 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
    774 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
    775 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
    776 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
    777 															  *m_fragmentShaderModuleSubpass0,		// const VkShaderModule							fragmentShaderModule
    778 															  *m_renderPass,						// const VkRenderPass							renderPass
    779 															  viewports,							// const std::vector<VkViewport>&				viewports
    780 															  scissors,								// const std::vector<VkRect2D>&					scissors
    781 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
    782 															  0u,									// const deUint32								subpass
    783 															  0u,									// const deUint32								patchControlPoints
    784 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
    785 
    786 			m_graphicsPipelineSubpass1 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
    787 															  vkDevice,								// const VkDevice								device
    788 															  *m_pipelineLayoutSubpass1,			// const VkPipelineLayout						pipelineLayout
    789 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
    790 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
    791 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
    792 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
    793 															  *m_fragmentShaderModuleSubpass1,		// const VkShaderModule							fragmentShaderModule
    794 															  *m_renderPass,						// const VkRenderPass							renderPass
    795 															  viewports,							// const std::vector<VkViewport>&				viewports
    796 															  scissors,								// const std::vector<VkRect2D>&					scissors
    797 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
    798 															  1u,									// const deUint32								subpass
    799 															  0u,									// const deUint32								patchControlPoints
    800 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
    801 		}
    802 	}
    803 
    804 	// Create vertex buffer
    805 	{
    806 		const VkBufferCreateInfo vertexBufferParams =
    807 		{
    808 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
    809 			DE_NULL,													// const void*			pNext;
    810 			0u,															// VkBufferCreateFlags	flags;
    811 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
    812 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
    813 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
    814 			1u,															// deUint32				queueFamilyIndexCount;
    815 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
    816 		};
    817 
    818 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
    819 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
    820 
    821 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
    822 
    823 		// Upload vertex data
    824 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
    825 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
    826 	}
    827 
    828 	// Create command pool
    829 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
    830 
    831 	// Create command buffer
    832 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
    833 		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
    834 	else
    835 		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
    836 }
    837 
    838 UnusedAttachmentTestInstance::~UnusedAttachmentTestInstance (void)
    839 {
    840 }
    841 
    842 template<typename RenderpassSubpass>
    843 void UnusedAttachmentTestInstance::createCommandBuffer (const DeviceInterface&	vk,
    844 														VkDevice				vkDevice)
    845 {
    846 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
    847 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
    848 
    849 	const VkClearValue attachmentClearValues[] =
    850 	{
    851 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// color
    852 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// unused
    853 		makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f)	// input
    854 	};
    855 
    856 	const VkDeviceSize vertexBufferOffset = 0;
    857 
    858 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
    859 
    860 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
    861 
    862 	const VkRenderPassBeginInfo renderPassBeginInfo =
    863 	{
    864 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
    865 		DE_NULL,									// const void*			pNext;
    866 		*m_renderPass,								// VkRenderPass			renderPass;
    867 		*m_framebuffer,								// VkFramebuffer		framebuffer;
    868 		makeRect2D(m_renderSize),					// VkRect2D				renderArea;
    869 		3u,											// uint32_t				clearValueCount;
    870 		attachmentClearValues						// const VkClearValue*	pClearValues;
    871 	};
    872 	RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
    873 
    874 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass0);
    875 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
    876 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
    877 	vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
    878 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass1);
    879 	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1, &m_descriptorSetSubpass1.get(), 0, DE_NULL);
    880 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
    881 
    882 	RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
    883 	endCommandBuffer(vk, *m_cmdBuffer);
    884 }
    885 
    886 tcu::TestStatus UnusedAttachmentTestInstance::iterate (void)
    887 {
    888 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
    889 	const VkDevice				vkDevice	= m_context.getDevice();
    890 	const VkQueue				queue		= m_context.getUniversalQueue();
    891 
    892 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
    893 
    894 	return verifyImage();
    895 }
    896 
    897 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage (void)
    898 {
    899 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
    900 	const VkDevice						vkDevice				= m_context.getDevice();
    901 	const VkQueue						queue					= m_context.getUniversalQueue();
    902 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
    903 	SimpleAllocator						allocator				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
    904 	de::UniquePtr<tcu::TextureLevel>	textureLevelResult		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
    905 	const tcu::ConstPixelBufferAccess&	resultAccess			= textureLevelResult->getAccess();
    906 	de::UniquePtr<tcu::TextureLevel>	textureLevelUnused		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
    907 	const tcu::ConstPixelBufferAccess&	unusedAccess			= textureLevelUnused->getAccess();
    908 	tcu::TestLog&						log						= m_context.getTestContext().getLog();
    909 
    910 	// Log images
    911 	log << tcu::TestLog::ImageSet("Result", "Result images")
    912 		<< tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
    913 		<< tcu::TestLog::Image("Unused", "Unused image", unusedAccess)
    914 		<< tcu::TestLog::EndImageSet;
    915 
    916 	// Check the unused image data hasn't changed.
    917 	for (int y = 0; y < unusedAccess.getHeight(); y++)
    918 		for (int x = 0; x < unusedAccess.getWidth(); x++)
    919 		{
    920 			const tcu::Vec4 color = unusedAccess.getPixel(x, y);
    921 			const tcu::Vec4 refColor = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
    922 			for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
    923 				if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
    924 					return tcu::TestStatus::fail("Unused image contents has changed.");
    925 		}
    926 
    927 	// Check for rendered result. Just a quick sanity check to see if correct color is found at the center of the quad.
    928 	const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
    929 	const tcu::Vec4 refColor = tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f);
    930 	for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
    931 		if (de::abs(resultColor[cpnt] - refColor[cpnt]) > 0.01f)
    932 			return tcu::TestStatus::fail("Result image mismatch");
    933 
    934 	return tcu::TestStatus::pass("Pass");
    935 }
    936 
    937 std::string loadOpToString (VkAttachmentLoadOp loadOp)
    938 {
    939 	switch (loadOp)
    940 	{
    941 		case VK_ATTACHMENT_LOAD_OP_LOAD:
    942 			return "load";
    943 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
    944 			return "clear";
    945 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
    946 			return "dontcare";
    947 		default:
    948 			DE_FATAL("unexpected attachment load op");
    949 			return "";
    950 	};
    951 }
    952 
    953 std::string storeOpToString (VkAttachmentStoreOp storeOp)
    954 {
    955 	switch (storeOp)
    956 	{
    957 		case VK_ATTACHMENT_STORE_OP_STORE:
    958 			return "store";
    959 		case VK_ATTACHMENT_STORE_OP_DONT_CARE:
    960 			return "dontcare";
    961 		default:
    962 			DE_FATAL("unexpected attachment store op");
    963 			return "";
    964 	};
    965 }
    966 
    967 } // anonymous
    968 
    969 tcu::TestCaseGroup* createRenderPassUnusedAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
    970 {
    971 	de::MovePtr<tcu::TestCaseGroup>		unusedAttTests		(new tcu::TestCaseGroup(testCtx, "unused_attachment", "Unused attachment tests"));
    972 
    973 	const VkAttachmentLoadOp			loadOps[]			=
    974 	{
    975 		VK_ATTACHMENT_LOAD_OP_LOAD,
    976 		VK_ATTACHMENT_LOAD_OP_CLEAR,
    977 		VK_ATTACHMENT_LOAD_OP_DONT_CARE
    978 	};
    979 
    980 	const VkAttachmentStoreOp			storeOps[]			=
    981 	{
    982 		VK_ATTACHMENT_STORE_OP_STORE,
    983 		VK_ATTACHMENT_STORE_OP_DONT_CARE
    984 	};
    985 
    986 	for (deUint32 loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++)
    987 	{
    988 		de::MovePtr<tcu::TestCaseGroup>	loadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str(), ""));
    989 
    990 		for (deUint32 storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++)
    991 		{
    992 			de::MovePtr<tcu::TestCaseGroup>	storeOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str(), ""));
    993 
    994 			for (deUint32 stencilLoadOpIdx = 0; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); stencilLoadOpIdx++)
    995 			{
    996 				de::MovePtr<tcu::TestCaseGroup>	stencilLoadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str(), ""));
    997 
    998 				for (deUint32 stencilStoreOpIdx = 0; stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++)
    999 				{
   1000 					TestParams			params;
   1001 					const std::string	testName = std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]);
   1002 
   1003 					params.loadOp			= loadOps[loadOpIdx];
   1004 					params.storeOp			= storeOps[storeOpIdx];
   1005 					params.stencilLoadOp	= loadOps[stencilLoadOpIdx];
   1006 					params.stencilStoreOp	= storeOps[stencilStoreOpIdx];
   1007 					params.renderPassType	= renderPassType;
   1008 
   1009 					stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, "", params));
   1010 				}
   1011 				storeOpGroup->addChild(stencilLoadOpGroup.release());
   1012 			}
   1013 			loadOpGroup->addChild(storeOpGroup.release());
   1014 		}
   1015 		unusedAttTests->addChild(loadOpGroup.release());
   1016 	}
   1017 
   1018 	return unusedAttTests.release();
   1019 }
   1020 
   1021 } // renderpass
   1022 } // vkt
   1023