Home | History | Annotate | Download | only in pipeline
      1 /*------------------------------------------------------------------------
      2  * Vulkan Conformance Tests
      3  * ------------------------
      4  *
      5  * Copyright (c) 2017 The Khronos Group Inc.
      6  *
      7  * Licensed under the Apache License, Version 2.0 (the "License");
      8  * you may not use this file except in compliance with the License.
      9  * You may obtain a copy of the License at
     10  *
     11  *      http://www.apache.org/licenses/LICENSE-2.0
     12  *
     13  * Unless required by applicable law or agreed to in writing, software
     14  * distributed under the License is distributed on an "AS IS" BASIS,
     15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
     16  * See the License for the specific language governing permissions and
     17  * limitations under the License.
     18  *
     19  *//*!
     20  * \file vktPipelineFramebuferAttachmentTests.cpp
     21  * \brief Render to a framebuffer with attachments of different sizes and with
     22  *        no attachments at all
     23  *
     24  *//*--------------------------------------------------------------------*/
     25 
     26 #include "vktPipelineFramebufferAttachmentTests.hpp"
     27 #include "vktPipelineMakeUtil.hpp"
     28 #include "vktTestCase.hpp"
     29 #include "vktTestCaseUtil.hpp"
     30 #include "vktPipelineVertexUtil.hpp"
     31 #include "vktTestGroupUtil.hpp"
     32 
     33 #include "vkMemUtil.hpp"
     34 #include "vkBarrierUtil.hpp"
     35 #include "vkQueryUtil.hpp"
     36 #include "vkTypeUtil.hpp"
     37 #include "vkRefUtil.hpp"
     38 #include "vkBuilderUtil.hpp"
     39 #include "vkPrograms.hpp"
     40 #include "vkImageUtil.hpp"
     41 #include "vkCmdUtil.hpp"
     42 #include "vkObjUtil.hpp"
     43 
     44 #include "tcuTextureUtil.hpp"
     45 #include "tcuImageCompare.hpp"
     46 
     47 #include "deUniquePtr.hpp"
     48 #include "deSharedPtr.hpp"
     49 
     50 #include <string>
     51 #include <vector>
     52 
     53 namespace vkt
     54 {
     55 namespace pipeline
     56 {
     57 namespace
     58 {
     59 using namespace vk;
     60 using de::UniquePtr;
     61 using de::MovePtr;
     62 using de::SharedPtr;
     63 using tcu::IVec3;
     64 using tcu::Vec4;
     65 using tcu::UVec4;
     66 using tcu::IVec4;
     67 using std::vector;
     68 
     69 static const VkFormat COLOR_FORMAT	=		VK_FORMAT_R8G8B8A8_UNORM;
     70 
     71 typedef SharedPtr<Unique<VkImageView> >	SharedPtrVkImageView;
     72 typedef SharedPtr<Unique<VkPipeline> >	SharedPtrVkPipeline;
     73 
     74 struct CaseDef
     75 {
     76 	VkImageViewType	imageType;
     77 	IVec3			renderSize;
     78 	IVec3			attachmentSize;
     79 	deUint32		numLayers;
     80 	bool			multisample;
     81 };
     82 
     83 template<typename T>
     84 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
     85 {
     86 	return SharedPtr<Unique<T> >(new Unique<T>(move));
     87 }
     88 
     89 template<typename T>
     90 inline VkDeviceSize sizeInBytes(const vector<T>& vec)
     91 {
     92 	return vec.size() * sizeof(vec[0]);
     93 }
     94 
     95 VkImageType getImageType(const VkImageViewType viewType)
     96 {
     97 	switch (viewType)
     98 	{
     99 		case VK_IMAGE_VIEW_TYPE_1D:
    100 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
    101 			return VK_IMAGE_TYPE_1D;
    102 
    103 		case VK_IMAGE_VIEW_TYPE_2D:
    104 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
    105 		case VK_IMAGE_VIEW_TYPE_CUBE:
    106 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
    107 			return VK_IMAGE_TYPE_2D;
    108 
    109 		case VK_IMAGE_VIEW_TYPE_3D:
    110 			return VK_IMAGE_TYPE_3D;
    111 
    112 		default:
    113 			DE_ASSERT(0);
    114 			return VK_IMAGE_TYPE_LAST;
    115 	}
    116 }
    117 
    118 //! Make a render pass with one subpass per color attachment and one attachment per image layer.
    119 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
    120 								   const VkDevice		  device,
    121 								   const VkFormat		  colorFormat,
    122 								   const deUint32		  numLayers,
    123 								   const bool			  multisample)
    124 {
    125 	vector<VkAttachmentDescription>	attachmentDescriptions		(numLayers);
    126 	deUint32						attachmentIndex				= 0;
    127 	vector<VkAttachmentReference>	colorAttachmentReferences	(numLayers);
    128 	vector<VkSubpassDescription>	subpasses;
    129 
    130 	for (deUint32 i = 0; i < numLayers; i++)
    131 	{
    132 		VkAttachmentDescription colorAttachmentDescription =
    133 		{
    134 			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
    135 			colorFormat,													// VkFormat						format;
    136 			!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits		samples;
    137 			VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
    138 			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
    139 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
    140 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
    141 			VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				initialLayout;
    142 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
    143 		};
    144 		attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
    145 	}
    146 
    147 	// Create a subpass for each attachment (each attachment is a layer of an arrayed image).
    148 	for (deUint32 i = 0; i < numLayers; ++i)
    149 	{
    150 		const VkAttachmentReference attachmentRef =
    151 		{
    152 			i,											// deUint32			attachment;
    153 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
    154 		};
    155 		colorAttachmentReferences[i] = attachmentRef;
    156 
    157 		const VkSubpassDescription subpassDescription =
    158 		{
    159 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
    160 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
    161 			0u,									// deUint32							inputAttachmentCount;
    162 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
    163 			1u,									// deUint32							colorAttachmentCount;
    164 			&colorAttachmentReferences[i],		// const VkAttachmentReference*		pColorAttachments;
    165 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
    166 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
    167 			0u,									// deUint32							preserveAttachmentCount;
    168 			DE_NULL								// const deUint32*					pPreserveAttachments;
    169 		};
    170 		subpasses.push_back(subpassDescription);
    171 	}
    172 
    173 	const VkRenderPassCreateInfo renderPassInfo =
    174 	{
    175 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
    176 		DE_NULL,									// const void*						pNext;
    177 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
    178 		numLayers,									// deUint32							attachmentCount;
    179 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
    180 		static_cast<deUint32>(subpasses.size()),	// deUint32							subpassCount;
    181 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
    182 		0u,											// deUint32							dependencyCount;
    183 		DE_NULL										// const VkSubpassDependency*		pDependencies;
    184 	};
    185 
    186 	return createRenderPass(vk, device, &renderPassInfo);
    187 }
    188 
    189 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
    190 									   const VkDevice				device,
    191 									   const VkPipelineLayout		pipelineLayout,
    192 									   const VkRenderPass			renderPass,
    193 									   const VkShaderModule			vertexModule,
    194 									   const VkShaderModule			fragmentModule,
    195 									   const IVec3					renderSize,
    196 									   const VkPrimitiveTopology	topology,
    197 									   const deUint32				subpass,
    198 									   const deUint32				numAttachments,
    199 									   const bool					multisample)
    200 {
    201 	const std::vector<VkViewport>				viewports							(1, makeViewport(renderSize));
    202 	const std::vector<VkRect2D>					scissors							(1, makeRect2D(renderSize));
    203 
    204 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
    205 
    206 	const VkPipelineMultisampleStateCreateInfo	pipelineMultisampleStateInfo		=
    207 	{
    208 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType                          sType;
    209 		DE_NULL,														// const void*                              pNext;
    210 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags    flags;
    211 		!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits                    rasterizationSamples;
    212 		VK_FALSE,														// VkBool32                                 sampleShadingEnable;
    213 		1.0f,															// float                                    minSampleShading;
    214 		DE_NULL,														// const VkSampleMask*                      pSampleMask;
    215 		VK_FALSE,														// VkBool32                                 alphaToCoverageEnable;
    216 		VK_FALSE														// VkBool32                                 alphaToOneEnable;
    217 	};
    218 
    219 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState	=
    220 	{
    221 		VK_FALSE,				// VkBool32                 blendEnable;
    222 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor            srcColorBlendFactor;
    223 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor            dstColorBlendFactor;
    224 		VK_BLEND_OP_ADD,		// VkBlendOp                colorBlendOp;
    225 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor            srcAlphaBlendFactor;
    226 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor            dstAlphaBlendFactor;
    227 		VK_BLEND_OP_ADD,		// VkBlendOp                alphaBlendOp;
    228 		colorComponentsAll		// VkColorComponentFlags    colorWriteMask;
    229 	};
    230 
    231 	std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
    232 	for (deUint32 attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
    233 		colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
    234 
    235 	const VkPipelineColorBlendStateCreateInfo	pipelineColorBlendStateInfo			=
    236 	{
    237 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType                              sType;
    238 		DE_NULL,														// const void*                                  pNext;
    239 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags         flags;
    240 		VK_FALSE,														// VkBool32                                     logicOpEnable;
    241 		VK_LOGIC_OP_COPY,												// VkLogicOp                                    logicOp;
    242 		numAttachments,													// deUint32                                     attachmentCount;
    243 		numAttachments == 0 ? DE_NULL : &colorBlendAttachmentStates[0],	// const VkPipelineColorBlendAttachmentState*   pAttachments;
    244 		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float                                        blendConstants[4];
    245 	};
    246 
    247 	return vk::makeGraphicsPipeline(vk,								// const DeviceInterface&                        vk
    248 									device,							// const VkDevice                                device
    249 									pipelineLayout,					// const VkPipelineLayout                        pipelineLayout
    250 									vertexModule,					// const VkShaderModule                          vertexShaderModule
    251 									DE_NULL,						// const VkShaderModule                          tessellationControlModule
    252 									DE_NULL,						// const VkShaderModule                          tessellationEvalModule
    253 									DE_NULL,						// const VkShaderModule                          geometryShaderModule
    254 									fragmentModule,					// const VkShaderModule                          fragmentShaderModule
    255 									renderPass,						// const VkRenderPass                            renderPass
    256 									viewports,						// const std::vector<VkViewport>&                viewports
    257 									scissors,						// const std::vector<VkRect2D>&                  scissors
    258 									topology,						// const VkPrimitiveTopology                     topology
    259 									subpass,						// const deUint32                                subpass
    260 									0u,								// const deUint32                                patchControlPoints
    261 									DE_NULL,						// const VkPipelineVertexInputStateCreateInfo*   vertexInputStateCreateInfo
    262 									DE_NULL,						// const VkPipelineRasterizationStateCreateInfo* rasterizationStateCreateInfo
    263 									&pipelineMultisampleStateInfo,	// const VkPipelineMultisampleStateCreateInfo*   multisampleStateCreateInfo
    264 									DE_NULL,						// const VkPipelineDepthStencilStateCreateInfo*  depthStencilStateCreateInfo
    265 									&pipelineColorBlendStateInfo);	// const VkPipelineColorBlendStateCreateInfo*    colorBlendStateCreateInfo
    266 }
    267 
    268 Move<VkImage> makeImage (const DeviceInterface&		vk,
    269 						 const VkDevice				device,
    270 						 const VkImageCreateFlags	flags,
    271 						 const VkImageType			imageType,
    272 						 const VkFormat				format,
    273 						 const IVec3&				size,
    274 						 const deUint32				numLayers,
    275 						 const VkImageUsageFlags	usage,
    276 						 const bool					multisample)
    277 {
    278 	const VkImageCreateInfo imageParams =
    279 	{
    280 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
    281 		DE_NULL,														// const void*				pNext;
    282 		flags,															// VkImageCreateFlags		flags;
    283 		imageType,														// VkImageType				imageType;
    284 		format,															// VkFormat					format;
    285 		makeExtent3D(size),												// VkExtent3D				extent;
    286 		1u,																// deUint32					mipLevels;
    287 		numLayers,														// deUint32					arrayLayers;
    288 		multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT,	// VkSampleCountFlagBits	samples;
    289 		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
    290 		usage,															// VkImageUsageFlags		usage;
    291 		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
    292 		0u,																// deUint32					queueFamilyIndexCount;
    293 		DE_NULL,														// const deUint32*			pQueueFamilyIndices;
    294 		VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout			initialLayout;
    295 	};
    296 
    297 	return createImage(vk, device, &imageParams);
    298 }
    299 
    300 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
    301 {
    302 	vector<tcu::Vec4>	vectorData;
    303 	for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
    304 	{
    305 		vectorData.push_back(Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
    306 		vectorData.push_back(Vec4(-1.0f,  1.0f, 0.0f, 1.0f));
    307 		vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
    308 		vectorData.push_back(Vec4(1.0f,  1.0f, 0.0f, 1.0f));
    309 	}
    310 	return vectorData;
    311 }
    312 
    313 void initColorPrograms (SourceCollections& programCollection, const CaseDef caseDef)
    314 {
    315 	(void)caseDef;
    316 
    317 	// Vertex shader
    318 	{
    319 		std::ostringstream src;
    320 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    321 			<< "\n"
    322 			<< "layout(location = 0) in vec4 in_position;\n"
    323 			<< "\n"
    324 			<< "out gl_PerVertex {\n"
    325 			<< "	vec4 gl_Position;\n"
    326 			<< "};\n"
    327 			<< "\n"
    328 			<< "void main(void)\n"
    329 			<< "{\n"
    330 			<< "	gl_Position	= in_position;\n"
    331 			<< "}\n";
    332 
    333 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    334 	}
    335 
    336 	// Fragment shader
    337 	{
    338 		std::ostringstream src;
    339 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    340 			<< "\n"
    341 			<< "layout(location = 0) out vec4 o_color;\n"
    342 			<< "\n"
    343 			<< "void main(void)\n"
    344 			<< "{\n"
    345 			<< "    o_color = vec4(1.0, 0.5, 0.25, 1.0);\n"
    346 			<< "}\n";
    347 
    348 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    349 	}
    350 }
    351 
    352 tcu::PixelBufferAccess getExpectedData (tcu::TextureLevel& textureLevel, const CaseDef& caseDef)
    353 {
    354 	const tcu::PixelBufferAccess	expectedImage	(textureLevel);
    355 	const int						renderDepth		= deMax32(caseDef.renderSize.z(), caseDef.numLayers);
    356 
    357 	for (int z = 0; z < expectedImage.getDepth(); ++z)
    358 	{
    359 		for (int y = 0; y < expectedImage.getHeight(); ++y)
    360 		{
    361 			for (int x = 0; x < expectedImage.getWidth(); ++x)
    362 			{
    363 				if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < renderDepth)
    364 					expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
    365 				else
    366 					expectedImage.setPixel(tcu::Vec4(0.0, 0.0, 0.0, 1.0), x, y, z);
    367 			}
    368 		}
    369 	}
    370 	return expectedImage;
    371 }
    372 
    373 inline Move<VkBuffer> makeBuffer (const DeviceInterface& vk, const VkDevice device, const VkDeviceSize bufferSize, const VkBufferUsageFlags usage)
    374 {
    375 	const VkBufferCreateInfo	bufferCreateInfo	= makeBufferCreateInfo(bufferSize, usage);
    376 	return createBuffer(vk, device, &bufferCreateInfo);
    377 }
    378 
    379 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
    380 {
    381 	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
    382 }
    383 
    384 // Tests rendering to a a framebuffer with color attachments larger than the
    385 // framebuffer dimensions and verifies that rendering does not affect the areas
    386 // of the attachment outside the framebuffer dimensions. Tests both single-sample
    387 // and multi-sample configurations.
    388 tcu::TestStatus test (Context& context, const CaseDef caseDef)
    389 {
    390 	const DeviceInterface&			vk					= context.getDeviceInterface();
    391 	const VkDevice					device				= context.getDevice();
    392 	const VkQueue					queue				= context.getUniversalQueue();
    393 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
    394 	Allocator&						allocator			= context.getDefaultAllocator();
    395 
    396 	// Color image for rendering in single-sample tests or resolve target for multi-sample tests
    397 	Move<VkImage>					colorImage;
    398 	MovePtr<Allocation>				colorImageAlloc;
    399 
    400 	// For multisampled tests, this is the rendering target
    401 	Move<VkImage>					msColorImage;
    402 	MovePtr<Allocation>				msColorImageAlloc;
    403 
    404 	// Host memory buffer where we will copy the rendered image for verification
    405 	const deUint32					att_size_x			= caseDef.attachmentSize.x();
    406 	const deUint32					att_size_y			= caseDef.attachmentSize.y();
    407 	const deUint32					att_size_z			= caseDef.attachmentSize.z();
    408 	const VkDeviceSize				colorBufferSize		= att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
    409 	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
    410 	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
    411 
    412 	Move<VkBuffer>					vertexBuffer;
    413 	MovePtr<Allocation>				vertexBufferAlloc;
    414 
    415 	vector<SharedPtrVkImageView>	colorAttachments;
    416 	vector<VkImageView>				attachmentHandles;
    417 
    418 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
    419 	vector<SharedPtrVkPipeline>		pipeline;
    420 	const Unique<VkRenderPass>		renderPass			(makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
    421 	Move<VkFramebuffer>				framebuffer;
    422 
    423 	const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
    424 	const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
    425 
    426 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
    427 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
    428 
    429 	const VkImageViewType			imageViewType		= caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
    430 		? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
    431 
    432 	// create vertexBuffer
    433 	{
    434 		const vector<tcu::Vec4>	vertices			= genFullQuadVertices(caseDef.numLayers);
    435 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
    436 
    437 		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
    438 		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
    439 
    440 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
    441 		flushAlloc(vk, device, *vertexBufferAlloc);
    442 	}
    443 
    444 	// create colorImage (and msColorImage) using the configured attachmentsize
    445 	{
    446 		const VkImageUsageFlags	colorImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
    447 
    448 		colorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
    449 			caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
    450 		colorImageAlloc	= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
    451 
    452 		if (caseDef.multisample)
    453 		{
    454 			const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
    455 
    456 			msColorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
    457 				caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
    458 			msColorImageAlloc	= bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
    459 		}
    460 	}
    461 
    462 	// create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
    463 	for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
    464 	{
    465 		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
    466 			imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
    467 		attachmentHandles.push_back(**colorAttachments.back());
    468 
    469 		pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
    470 			caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample)));
    471 	}
    472 
    473 	// create framebuffer
    474 	framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
    475 		static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
    476 
    477 	// record command buffer
    478 	beginCommandBuffer(vk, *cmdBuffer);
    479 	{
    480 		// Clear the entire image attachment to black
    481 		{
    482 			const VkImageMemoryBarrier	imageLayoutBarriers[]	=
    483 			{
    484 				{
    485 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
    486 					DE_NULL,											// const void*				pNext;
    487 					0u,													// VkAccessFlags			srcAccessMask;
    488 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
    489 					VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
    490 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
    491 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
    492 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
    493 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
    494 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
    495 				},
    496 			};
    497 
    498 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
    499 				0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
    500 
    501 			const VkImageSubresourceRange	ranges		= makeColorSubresourceRange(0, caseDef.numLayers);
    502 			const VkClearColorValue			clearColor	=
    503 	        {
    504                 {0.0f, 0.0f, 0.0f, 1.0f}
    505 			};
    506 			vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
    507 
    508 			const VkImageMemoryBarrier	imageClearBarriers[]	=
    509 			{
    510 				{
    511 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
    512 					DE_NULL,											// const void*				pNext;
    513 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
    514 					VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,				// VkAccessFlags			dstAccessMask;
    515 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
    516 					VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
    517 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
    518 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
    519 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
    520 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
    521 				},
    522 			};
    523 
    524 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
    525 				0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
    526 		}
    527 
    528 		// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
    529 		{
    530 			const VkDeviceSize			vertexBufferOffset	= 0ull;
    531 
    532 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
    533 			{
    534 				vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
    535 				for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
    536 				{
    537 					if (layerNdx != 0)
    538 						vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
    539 
    540 					vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
    541 					vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
    542 				}
    543 			}
    544 			endRenderPass(vk, *cmdBuffer);
    545 		}
    546 
    547 		// If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
    548 		if (caseDef.multisample)
    549 		{
    550 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
    551 			const VkImageMemoryBarrier	imageBarriers[]	=
    552 			{
    553 				{
    554 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
    555 					DE_NULL,										// const void*				pNext;
    556 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask;
    557 					VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			dstAccessMask;
    558 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
    559 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
    560 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
    561 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
    562 					*msColorImage,									// VkImage					image;
    563 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
    564 				},
    565 				{
    566 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
    567 					DE_NULL,										// const void*				pNext;
    568 					(VkAccessFlags)0,								// VkAccessFlags			srcAccessMask;
    569 					VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
    570 					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
    571 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
    572 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
    573 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
    574 					*colorImage,									// VkImage					image;
    575 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
    576 				}
    577 			};
    578 
    579 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
    580 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
    581 
    582 			const VkImageResolve	region	=
    583 			{
    584 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    srcSubresource;
    585 				makeOffset3D(0, 0, 0),															// VkOffset3D                  srcOffset;
    586 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    dstSubresource;
    587 				makeOffset3D(0, 0, 0),															// VkOffset3D                  dstOffset;
    588 				makeExtent3D(caseDef.attachmentSize)											// VkExtent3D                  extent;
    589 			};
    590 
    591 			vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
    592 		}
    593 
    594 		// copy colorImage to host visible colorBuffer
    595 		{
    596 			const VkImageMemoryBarrier	imageBarriers[]		=
    597 			{
    598 				{
    599 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
    600 					DE_NULL,																					// const void*				pNext;
    601 					(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
    602 					VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
    603 					caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
    604 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
    605 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
    606 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
    607 					*colorImage,																				// VkImage					image;
    608 					makeColorSubresourceRange(0, caseDef.numLayers)												// VkImageSubresourceRange	subresourceRange;
    609 				}
    610 			};
    611 
    612 			vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
    613 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
    614 
    615 			const VkBufferImageCopy		region				=
    616 			{
    617 				0ull,																				// VkDeviceSize                bufferOffset;
    618 				0u,																					// uint32_t                    bufferRowLength;
    619 				0u,																					// uint32_t                    bufferImageHeight;
    620 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),	// VkImageSubresourceLayers    imageSubresource;
    621 				makeOffset3D(0, 0, 0),																// VkOffset3D                  imageOffset;
    622 				makeExtent3D(caseDef.attachmentSize),												// VkExtent3D                  imageExtent;
    623 			};
    624 
    625 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
    626 
    627 			const VkBufferMemoryBarrier	bufferBarriers[]	=
    628 			{
    629 				{
    630 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
    631 					DE_NULL,									// const void*        pNext;
    632 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
    633 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
    634 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
    635 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
    636 					*colorBuffer,								// VkBuffer           buffer;
    637 					0ull,										// VkDeviceSize       offset;
    638 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
    639 				},
    640 			};
    641 
    642 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
    643 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
    644 		}
    645 	} // beginCommandBuffer
    646 
    647 	endCommandBuffer(vk, *cmdBuffer);
    648 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
    649 
    650 	// Verify results
    651 	{
    652 		invalidateAlloc(vk, device, *colorBufferAlloc);
    653 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
    654 		const int							depth			= deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
    655 		tcu::TextureLevel					textureLevel	(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
    656 		const tcu::PixelBufferAccess		expectedImage	= getExpectedData(textureLevel, caseDef);
    657 		const tcu::ConstPixelBufferAccess	resultImage		(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
    658 
    659 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
    660 			return tcu::TestStatus::fail("Fail");
    661 	}
    662 
    663 	return tcu::TestStatus::pass("Pass");
    664 }
    665 
    666 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
    667 {
    668 	// Vertex shader
    669 	{
    670 		std::ostringstream src;
    671 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    672 			<< "\n"
    673 			<< "layout(location = 0) in vec4 in_position;\n"
    674 			<< "\n"
    675 			<< "out gl_PerVertex {\n"
    676 			<< "	vec4 gl_Position;\n"
    677 			<< "	float gl_PointSize;\n"
    678 			<< "};\n"
    679 			<< "\n"
    680 			<< "void main(void)\n"
    681 			<< "{\n"
    682 			<< "	gl_Position	= in_position;\n"
    683 			<< "	gl_PointSize = 1.0f;\n"
    684 			<< "}\n";
    685 
    686 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
    687 	}
    688 
    689 	// Fragment shader
    690 	{
    691 		std::ostringstream src;
    692 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
    693 			<< "\n"
    694 			<< "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
    695 			<< "\n"
    696 			<< "void main(void)\n"
    697 			<< "{\n";
    698 			if (!multisample)
    699 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
    700 			else
    701 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
    702 			src << "}\n";
    703 
    704 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
    705 	}
    706 }
    707 
    708 //! Make a render pass with no attachments
    709 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
    710 {
    711 	// Create a single subpass with no attachment references
    712 	vector<VkSubpassDescription>	subpasses;
    713 
    714 	const VkSubpassDescription		subpassDescription	=
    715 	{
    716 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
    717 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
    718 		0u,									// deUint32							inputAttachmentCount;
    719 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
    720 		0u,									// deUint32							colorAttachmentCount;
    721 		DE_NULL,							// const VkAttachmentReference*		pColorAttachments;
    722 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
    723 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
    724 		0u,									// deUint32							preserveAttachmentCount;
    725 		DE_NULL								// const deUint32*					pPreserveAttachments;
    726 	};
    727 	subpasses.push_back(subpassDescription);
    728 
    729 	const VkRenderPassCreateInfo	renderPassInfo	=
    730 	{
    731 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
    732 		DE_NULL,									// const void*						pNext;
    733 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
    734 		0,											// deUint32							attachmentCount;
    735 		DE_NULL,									// const VkAttachmentDescription*	pAttachments;
    736 		1,											// deUint32							subpassCount;
    737 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
    738 		0u,											// deUint32							dependencyCount;
    739 		DE_NULL										// const VkSubpassDependency*		pDependencies;
    740 	};
    741 
    742 	return createRenderPass(vk, device, &renderPassInfo);
    743 }
    744 
    745 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
    746 {
    747 	const tcu::PixelBufferAccess	expectedImage	(textureLevel);
    748 	for (int z = 0; z < expectedImage.getDepth(); ++z)
    749 	{
    750 		for (int y = 0; y < expectedImage.getHeight(); ++y)
    751 		{
    752 			for (int x = 0; x < expectedImage.getWidth(); ++x)
    753 			{
    754 				expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
    755 			}
    756 		}
    757 	}
    758 	return expectedImage;
    759 }
    760 
    761 vector<tcu::Vec4> genPointVertices (void)
    762 {
    763 	vector<tcu::Vec4>	vectorData;
    764 	vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
    765 	vectorData.push_back(Vec4(-0.25f,  0.25f, 0, 1));
    766 	vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
    767 	vectorData.push_back(Vec4(0.25f,  0.25f, 0, 1));
    768 	return vectorData;
    769 }
    770 
    771 // Tests rendering to a framebuffer without color attachments, checking that
    772 // the fragment shader is run even in the absence of color output. In this case
    773 // we render 4 point primitives and we make the fragment shader write to a
    774 // different pixel of an image via an imageStore command. For the single-sampled
    775 // configuration we use a 4x1 image to record the output and for the
    776 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
    777 // 4-sample multi-sampling
    778 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
    779 {
    780 	const VkPhysicalDeviceFeatures		features				= context.getDeviceFeatures();
    781 	if (!features.fragmentStoresAndAtomics)
    782 		throw tcu::NotSupportedError("fragmentStoresAndAtomics feature not supported");
    783 	if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
    784 		throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
    785 	if (multisample && !features.sampleRateShading) // MS shader uses gl_SampleID
    786 		throw tcu::NotSupportedError("sampleRateShading feature not supported");
    787 
    788 	const DeviceInterface&				vk						= context.getDeviceInterface();
    789 	const VkDevice						device					= context.getDevice();
    790 	const VkQueue						queue					= context.getUniversalQueue();
    791 	const deUint32						queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
    792 	Allocator&							allocator				= context.getDefaultAllocator();
    793 	const IVec3							renderSize				(32, 32, 1);
    794 
    795 	Move<VkBuffer>						vertexBuffer;
    796 	MovePtr<Allocation>					vertexBufferAlloc;
    797 
    798 	const Unique<VkShaderModule>		vertexModule			(createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
    799 	const Unique<VkShaderModule>		fragmentModule			(createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
    800 
    801 	// Create image where we will record the writes. For single-sampled cases this is a 4x1 image
    802 	// and for multi-sampled cases this is a 4x<num_samples> image.
    803 	const deUint8						numSamples				= multisample ? 4 : 1;
    804 	const deUint8						imageWidth				= 4;
    805 	const deUint8						imageHeight				= numSamples;
    806 	const deUint8						imageDepth				= 1;
    807 	const deUint8						imageLayers				= 1;
    808 	const IVec3							imageDim				= IVec3(imageWidth, imageHeight, imageDepth);
    809 	const VkImageUsageFlags				imageUsage				= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
    810 	const Move<VkImage>					image					= makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
    811 	const VkImageSubresourceRange		imageSubresourceRange	= makeColorSubresourceRange(0u, imageLayers);
    812 	const MovePtr<Allocation>			imageAlloc				= bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
    813 	const Move<VkImageView>				imageView				= makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
    814 
    815 	// Create a buffer where we will copy the image for verification
    816 	const VkDeviceSize					colorBufferSize		= imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
    817 	const Unique<VkBuffer>				colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
    818 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
    819 
    820 	// Create pipeline descriptor set for the image
    821 	const Move<VkDescriptorSetLayout>	descriptorSetLayout		= DescriptorSetLayoutBuilder()
    822 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
    823 		.build(vk, device);
    824 
    825 	const Move<VkDescriptorPool>		descriptorPool			= DescriptorPoolBuilder()
    826 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
    827 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
    828 
    829 	const Move<VkDescriptorSet>			descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
    830 	const VkDescriptorImageInfo			descriptorImageInfo		= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
    831 	DescriptorSetUpdateBuilder()
    832 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
    833 		.update(vk, device);
    834 
    835 	const Unique<VkPipelineLayout>		pipelineLayout			(makePipelineLayout (vk, device, *descriptorSetLayout));
    836 	vector<SharedPtrVkPipeline>			pipeline;
    837 	const Unique<VkRenderPass>			renderPass				(makeRenderPassNoAtt (vk, device));
    838 	Move<VkFramebuffer>					framebuffer;
    839 
    840 	const Unique<VkCommandPool>			cmdPool					(createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
    841 	const Unique<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer (vk, device, *cmdPool));
    842 
    843 	// create vertexBuffer
    844 	{
    845 		const vector<tcu::Vec4>	vertices			= genPointVertices();
    846 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
    847 
    848 		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
    849 		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
    850 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
    851 		flushAlloc(vk, device, *vertexBufferAlloc);
    852 	}
    853 
    854 	// Create render pass and pipeline
    855 	pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
    856 		renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample)));
    857 	framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
    858 
    859 	// Record command buffer
    860 	beginCommandBuffer(vk, *cmdBuffer);
    861 	{
    862 		// shader image layout transition undefined -> general
    863 		{
    864 			const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
    865 				0u, VK_ACCESS_SHADER_WRITE_BIT,
    866 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
    867 				*image, imageSubresourceRange);
    868 
    869 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
    870 				0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
    871 		}
    872 
    873 		// Render pass
    874 		{
    875 			const VkDeviceSize vertexBufferOffset = 0ull;
    876 
    877 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
    878 
    879 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
    880 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
    881 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
    882 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
    883 
    884 			endRenderPass(vk, *cmdBuffer);
    885 		}
    886 
    887 		// copy image to host visible colorBuffer
    888 		{
    889 			const VkImageMemoryBarrier	imageBarriers[]		=
    890 			{
    891 				{
    892 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
    893 					DE_NULL,									// const void*				pNext;
    894 					VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
    895 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
    896 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			oldLayout;
    897 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
    898 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
    899 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
    900 					*image,										// VkImage					image;
    901 					makeColorSubresourceRange(0, 1)				// VkImageSubresourceRange	subresourceRange;
    902 				}
    903 			};
    904 
    905 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
    906 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
    907 
    908 			const VkBufferImageCopy		region				=
    909 			{
    910 				0ull,																// VkDeviceSize                bufferOffset;
    911 				0u,																	// uint32_t                    bufferRowLength;
    912 				0u,																	// uint32_t                    bufferImageHeight;
    913 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1),	// VkImageSubresourceLayers    imageSubresource;
    914 				makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
    915 				makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)),			// VkExtent3D                  imageExtent;
    916 			};
    917 
    918 			vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
    919 
    920 			const VkBufferMemoryBarrier	bufferBarriers[]	=
    921 			{
    922 				{
    923 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
    924 					DE_NULL,									// const void*        pNext;
    925 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
    926 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
    927 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
    928 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
    929 					*colorBuffer,								// VkBuffer           buffer;
    930 					0ull,										// VkDeviceSize       offset;
    931 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
    932 				},
    933 			};
    934 
    935 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
    936 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
    937 		}
    938 	} // beginCommandBuffer
    939 
    940 	endCommandBuffer(vk, *cmdBuffer);
    941 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
    942 
    943 	// Verify results
    944 	{
    945 		invalidateAlloc(vk, device, *colorBufferAlloc);
    946 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
    947 		tcu::TextureLevel					textureLevel	(format, imageWidth, imageHeight, imageDepth);
    948 		const tcu::PixelBufferAccess		expectedImage	= getExpectedDataNoAtt(textureLevel);
    949 		const tcu::ConstPixelBufferAccess	resultImage		(format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
    950 
    951 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
    952 			return tcu::TestStatus::fail("Fail");
    953 	}
    954 
    955 	return tcu::TestStatus::pass("Pass");
    956 }
    957 
    958 //! Make a render pass with three color attachments
    959 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes	(const DeviceInterface&	vk,
    960 															 const VkDevice			device,
    961 															 const VkFormat			colorFormat,
    962 															 deUint32				numAttachments,
    963 															 const bool				multisample)
    964 {
    965 	vector<VkAttachmentDescription>	attachmentDescriptions		(numAttachments);
    966 	vector<VkAttachmentReference>	colorAttachmentReferences	(numAttachments);
    967 
    968 	for (deUint32 i = 0; i < numAttachments; i++)
    969 	{
    970 		VkAttachmentDescription colorAttachmentDescription =
    971 		{
    972 			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
    973 			colorFormat,													// VkFormat						format;
    974 			!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits		samples;
    975 			VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
    976 			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
    977 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
    978 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
    979 			VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				initialLayout;
    980 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
    981 		};
    982 		attachmentDescriptions[i] = colorAttachmentDescription;
    983 
    984 		const VkAttachmentReference attachmentRef =
    985 		{
    986 			i,											// deUint32			attachment;
    987 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
    988 		};
    989 		colorAttachmentReferences[i] = attachmentRef;
    990 	}
    991 
    992 	const VkSubpassDescription subpassDescription =
    993 	{
    994 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
    995 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
    996 		0u,									// deUint32							inputAttachmentCount;
    997 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
    998 		numAttachments,						// deUint32							colorAttachmentCount;
    999 		&colorAttachmentReferences[0],		// const VkAttachmentReference*		pColorAttachments;
   1000 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
   1001 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
   1002 		0u,									// deUint32							preserveAttachmentCount;
   1003 		DE_NULL								// const deUint32*					pPreserveAttachments;
   1004 	};
   1005 
   1006 	const VkRenderPassCreateInfo renderPassInfo =
   1007 	{
   1008 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
   1009 		DE_NULL,									// const void*						pNext;
   1010 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
   1011 		numAttachments,								// deUint32							attachmentCount;
   1012 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
   1013 		1u,											// deUint32							subpassCount;
   1014 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
   1015 		0u,											// deUint32							dependencyCount;
   1016 		DE_NULL										// const VkSubpassDependency*		pDependencies;
   1017 	};
   1018 
   1019 	return createRenderPass(vk, device, &renderPassInfo);
   1020 }
   1021 
   1022 // Tests framebuffer with attachments of different sizes
   1023 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef)
   1024 {
   1025 	const DeviceInterface&			vk					= context.getDeviceInterface();
   1026 	const VkDevice					device				= context.getDevice();
   1027 	const VkQueue					queue				= context.getUniversalQueue();
   1028 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
   1029 	Allocator&						allocator			= context.getDefaultAllocator();
   1030 	const deUint32					numRenderTargets	= 3;
   1031 
   1032 	// Color images for rendering in single-sample tests or resolve targets for multi-sample tests
   1033 	Move<VkImage>					colorImages[numRenderTargets];
   1034 	MovePtr<Allocation>				colorImageAllocs[numRenderTargets];
   1035 
   1036 	// For multisampled tests, these are the rendering targets
   1037 	Move<VkImage>					msColorImages[numRenderTargets];
   1038 	MovePtr<Allocation>				msColorImageAllocs[numRenderTargets];
   1039 
   1040 	Move<VkBuffer>					colorBuffers[numRenderTargets];
   1041 	MovePtr<Allocation>				colorBufferAllocs[numRenderTargets];
   1042 
   1043 	// Vary attachment sizes by adding an offset to the base size.
   1044 	const IVec3						attachmentSizes[]	=
   1045 	{
   1046 		caseDef.attachmentSize,
   1047 		caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
   1048 		caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
   1049 	};
   1050 
   1051 	// Use unique clear color for each render target to verify no leaking happens between render target clears.
   1052 	const VkClearColorValue			clearColors[]		=
   1053 	{
   1054 		{{1.0f, 0.0f, 0.0f, 1.0f}},
   1055 		{{0.0f, 1.0f, 0.0f, 1.0f}},
   1056 		{{0.0f, 0.0f, 1.0f, 1.0f}}
   1057 	};
   1058 
   1059 	Move<VkBuffer>					vertexBuffer;
   1060 	MovePtr<Allocation>				vertexBufferAlloc;
   1061 
   1062 	vector<SharedPtrVkImageView>	colorAttachments;
   1063 	vector<VkImageView>				attachmentHandles;
   1064 
   1065 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
   1066 	Move<VkPipeline>				pipeline;
   1067 	const Unique<VkRenderPass>		renderPass			(makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
   1068 	Move<VkFramebuffer>				framebuffer;
   1069 
   1070 	const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
   1071 	const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
   1072 
   1073 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
   1074 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
   1075 
   1076 	const VkImageViewType			imageViewType		= caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
   1077 		? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
   1078 
   1079 	const VkImageSubresourceRange	range				= makeColorSubresourceRange(0, 1);
   1080 
   1081 	// create color buffers
   1082 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1083 	{
   1084 		// Host memory buffer where we will copy the rendered image for verification
   1085 		const deUint32					att_size_x			= attachmentSizes[renderTargetIdx].x();
   1086 		const deUint32					att_size_y			= attachmentSizes[renderTargetIdx].y();
   1087 		const deUint32					att_size_z			= attachmentSizes[renderTargetIdx].z();
   1088 		const VkDeviceSize				colorBufferSize		= att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
   1089 		colorBuffers[renderTargetIdx]						= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
   1090 		colorBufferAllocs[renderTargetIdx]					= bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
   1091 	}
   1092 
   1093 	// create vertexBuffer
   1094 	{
   1095 		const vector<tcu::Vec4>	vertices			= genFullQuadVertices(1);
   1096 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
   1097 
   1098 		vertexBuffer								= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
   1099 		vertexBufferAlloc							= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
   1100 
   1101 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
   1102 		flushAlloc(vk, device, *vertexBufferAlloc);
   1103 	}
   1104 
   1105 	// create colorImages (and msColorImages) using the configured attachmentsize
   1106 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1107 	{
   1108 		const VkImageUsageFlags	colorImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
   1109 		colorImages[renderTargetIdx]			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
   1110 			attachmentSizes[renderTargetIdx], 1, colorImageUsage, false);
   1111 		colorImageAllocs[renderTargetIdx]		= bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
   1112 
   1113 		if (caseDef.multisample)
   1114 		{
   1115 			const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
   1116 
   1117 			msColorImages[renderTargetIdx]			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSizes[renderTargetIdx], 1, msImageUsage, true);
   1118 			msColorImageAllocs[renderTargetIdx]		= bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
   1119 		}
   1120 	}
   1121 
   1122 	// create attachmentHandles. We use the renderSize for viewport and scissor
   1123 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1124 	{
   1125 		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx], imageViewType, COLOR_FORMAT, range)));
   1126 		attachmentHandles.push_back(**colorAttachments.back());
   1127 	}
   1128 
   1129 	pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
   1130 
   1131 	// create framebuffer
   1132 	framebuffer = makeFramebuffer(vk, device, *renderPass, numRenderTargets, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
   1133 
   1134 	// record command buffer
   1135 	beginCommandBuffer(vk, *cmdBuffer);
   1136 
   1137 	// Clear image attachments
   1138 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1139 	{
   1140 		{
   1141 			const VkImageMemoryBarrier	imageLayoutBarriers[]	=
   1142 			{
   1143 				{
   1144 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
   1145 					DE_NULL,																				// const void*				pNext;
   1146 					0u,																						// VkAccessFlags			srcAccessMask;
   1147 					VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
   1148 					VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
   1149 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
   1150 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
   1151 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
   1152 					caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],	// VkImage					image;
   1153 					range																					// VkImageSubresourceRange	subresourceRange;
   1154 				},
   1155 			};
   1156 
   1157 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
   1158 				0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
   1159 
   1160 			vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
   1161 
   1162 			const VkImageMemoryBarrier	imageClearBarriers[]	=
   1163 			{
   1164 				{
   1165 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
   1166 					DE_NULL,																				// const void*				pNext;
   1167 					VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
   1168 					VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,													// VkAccessFlags			dstAccessMask;
   1169 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
   1170 					VK_IMAGE_LAYOUT_GENERAL,																// VkImageLayout			newLayout;
   1171 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
   1172 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
   1173 					caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],	// VkImage					image;
   1174 					range																					// VkImageSubresourceRange	subresourceRange;
   1175 				},
   1176 			};
   1177 
   1178 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
   1179 		}
   1180 	}
   1181 
   1182 	// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
   1183 	{
   1184 		const VkDeviceSize			vertexBufferOffset	= 0ull;
   1185 
   1186 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
   1187 		{
   1188 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
   1189 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
   1190 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
   1191 		}
   1192 		endRenderPass(vk, *cmdBuffer);
   1193 	}
   1194 
   1195 	// If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
   1196 	if (caseDef.multisample)
   1197 	{
   1198 		for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1199 		{
   1200 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
   1201 			const VkImageMemoryBarrier	imageBarriers[]	=
   1202 			{
   1203 				{
   1204 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
   1205 					DE_NULL,									// const void*				pNext;
   1206 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
   1207 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
   1208 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
   1209 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			newLayout;
   1210 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
   1211 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
   1212 					*msColorImages[renderTargetIdx],			// VkImage					image;
   1213 					range										// VkImageSubresourceRange	subresourceRange;
   1214 				},
   1215 				{
   1216 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
   1217 					DE_NULL,								// const void*				pNext;
   1218 					(VkAccessFlags)0,						// VkAccessFlags			srcAccessMask;
   1219 					VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
   1220 					VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
   1221 					VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout			newLayout;
   1222 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
   1223 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					destQueueFamilyIndex;
   1224 					*colorImages[renderTargetIdx],			// VkImage					image;
   1225 					range									// VkImageSubresourceRange	subresourceRange;
   1226 				}
   1227 			};
   1228 
   1229 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
   1230 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
   1231 
   1232 			const VkImageResolve	region	=
   1233 			{
   1234 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    srcSubresource;
   1235 				makeOffset3D(0, 0, 0),											// VkOffset3D                  srcOffset;
   1236 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    dstSubresource;
   1237 				makeOffset3D(0, 0, 0),											// VkOffset3D                  dstOffset;
   1238 				makeExtent3D(attachmentSizes[renderTargetIdx])					// VkExtent3D                  extent;
   1239 			};
   1240 
   1241 			vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, &region);
   1242 		}
   1243 	}
   1244 
   1245 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1246 	{
   1247 		// copy colorImage to host visible colorBuffer
   1248 		const VkImageMemoryBarrier	imageBarrier		=
   1249 		{
   1250 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
   1251 			DE_NULL,																					// const void*				pNext;
   1252 			(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
   1253 			VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
   1254 			caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
   1255 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
   1256 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
   1257 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
   1258 			*colorImages[renderTargetIdx],																// VkImage					image;
   1259 			range																						// VkImageSubresourceRange	subresourceRange;
   1260 		};
   1261 
   1262 		vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
   1263 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
   1264 
   1265 		const VkBufferImageCopy		region				=
   1266 		{
   1267 			0ull,																// VkDeviceSize                bufferOffset;
   1268 			0u,																	// uint32_t                    bufferRowLength;
   1269 			0u,																	// uint32_t                    bufferImageHeight;
   1270 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
   1271 			makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
   1272 			makeExtent3D(attachmentSizes[renderTargetIdx]),						// VkExtent3D                  imageExtent;
   1273 		};
   1274 
   1275 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, &region);
   1276 
   1277 		const VkBufferMemoryBarrier	bufferBarrier		=
   1278 		{
   1279 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
   1280 			DE_NULL,									// const void*        pNext;
   1281 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
   1282 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
   1283 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
   1284 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
   1285 			*colorBuffers[renderTargetIdx],				// VkBuffer           buffer;
   1286 			0ull,										// VkDeviceSize       offset;
   1287 			VK_WHOLE_SIZE,								// VkDeviceSize       size;
   1288 		};
   1289 
   1290 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
   1291 			0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
   1292 	}
   1293 
   1294 	endCommandBuffer(vk, *cmdBuffer);
   1295 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
   1296 
   1297 	// Verify results
   1298 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
   1299 	{
   1300 		const tcu::TextureFormat			format				= mapVkFormat(COLOR_FORMAT);
   1301 		const IVec3							size				= attachmentSizes[renderTargetIdx];
   1302 		tcu::TextureLevel					textureLevel		(format, size.x(), size.y(), size.z());
   1303 		const tcu::PixelBufferAccess		expectedImage		(textureLevel);
   1304 
   1305 		const tcu::Vec4						expectedColors[]	=
   1306 		{
   1307 			tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
   1308 			tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
   1309 			tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
   1310 		};
   1311 
   1312 		invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
   1313 
   1314 		for (int z = 0; z < expectedImage.getDepth(); ++z)
   1315 		{
   1316 			for (int y = 0; y < expectedImage.getHeight(); ++y)
   1317 			{
   1318 				for (int x = 0; x < expectedImage.getWidth(); ++x)
   1319 				{
   1320 					if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
   1321 						expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
   1322 					else
   1323 						expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
   1324 				}
   1325 			}
   1326 		}
   1327 		const tcu::ConstPixelBufferAccess	resultImage		(format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
   1328 
   1329 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), (std::string("Image Comparison of render target ") + de::toString(renderTargetIdx)).c_str(), "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
   1330 			return tcu::TestStatus::fail("Fail");
   1331 	}
   1332 
   1333 	return tcu::TestStatus::pass("Pass");
   1334 }
   1335 
   1336 tcu::TestStatus testUnusedAtt (Context& context)
   1337 {
   1338 	const DeviceInterface&			vk						= context.getDeviceInterface();
   1339 	const VkDevice					device					= context.getDevice();
   1340 	const Move<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
   1341 	const Move<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
   1342 
   1343 	const VkAttachmentReference		attRef					=
   1344 	{
   1345 		VK_ATTACHMENT_UNUSED,
   1346 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
   1347 	};
   1348 
   1349 	const VkSubpassDescription		subpass					=
   1350 	{
   1351 		0,
   1352 		VK_PIPELINE_BIND_POINT_GRAPHICS,
   1353 		0,
   1354 		DE_NULL,
   1355 		1,
   1356 		&attRef,
   1357 		DE_NULL,
   1358 		DE_NULL,
   1359 		0,
   1360 		DE_NULL
   1361 	};
   1362 
   1363 	const VkRenderPassCreateInfo	renderPassCreateInfo	=
   1364 	{
   1365 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
   1366 		DE_NULL,
   1367 		0,
   1368 		0,
   1369 		DE_NULL,
   1370 		1,
   1371 		&subpass,
   1372 		0,
   1373 		DE_NULL
   1374 	};
   1375 
   1376 	const Move<VkRenderPass>		renderPass				= createRenderPass(vk, device, &renderPassCreateInfo, DE_NULL);
   1377 
   1378 	const VkFramebufferCreateInfo	framebufferCreateInfo	=
   1379 	{
   1380 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
   1381 		DE_NULL,
   1382 		0,
   1383 		*renderPass,
   1384 		0,
   1385 		DE_NULL,
   1386 		32,
   1387 		32,
   1388 		1
   1389 	};
   1390 
   1391 	const Move<VkFramebuffer>		framebuffer				= createFramebuffer(vk, device, &framebufferCreateInfo, DE_NULL);
   1392 
   1393 	beginCommandBuffer(vk, *cmdBuffer);
   1394 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 32u, 32u));
   1395 	endRenderPass(vk, *cmdBuffer);
   1396 	endCommandBuffer(vk, *cmdBuffer);
   1397 
   1398 	return tcu::TestStatus::pass("Pass");
   1399 }
   1400 
   1401 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
   1402 {
   1403 	DE_UNREF(caseDef);
   1404 
   1405 	// Vertex shader
   1406 	{
   1407 		std::ostringstream src;
   1408 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
   1409 			<< "\n"
   1410 			<< "layout(location = 0) in vec4 in_position;\n"
   1411 			<< "\n"
   1412 			<< "out gl_PerVertex {\n"
   1413 			<< "	vec4 gl_Position;\n"
   1414 			<< "};\n"
   1415 			<< "\n"
   1416 			<< "void main(void)\n"
   1417 			<< "{\n"
   1418 			<< "	gl_Position	= in_position;\n"
   1419 			<< "}\n";
   1420 
   1421 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
   1422 	}
   1423 
   1424 	// Fragment shader
   1425 	{
   1426 		std::ostringstream src;
   1427 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
   1428 			<< "\n"
   1429 			<< "layout(location = 0) out vec4 o_color0;\n"
   1430 			<< "layout(location = 1) out vec4 o_color1;\n"
   1431 			<< "layout(location = 2) out vec4 o_color2;\n"
   1432 			<< "\n"
   1433 			<< "void main(void)\n"
   1434 			<< "{\n"
   1435 			<< "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
   1436 			<< "    o_color1 = vec4(0.5,  1.0, 0.25, 1.0);\n"
   1437 			<< "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
   1438 			<< "}\n";
   1439 
   1440 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
   1441 	}
   1442 }
   1443 
   1444 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
   1445 {
   1446 	std::string	s	(getImageViewTypeName(imageViewType));
   1447 	return de::toLower(s.substr(19));
   1448 }
   1449 
   1450 std::string getSizeString (const CaseDef& caseDef)
   1451 {
   1452 	std::ostringstream	str;
   1453 
   1454 										str << caseDef.renderSize.x();
   1455 	if (caseDef.renderSize.y() > 1)		str << "x" << caseDef.renderSize.y();
   1456 	if (caseDef.renderSize.z() > 1)		str << "x" << caseDef.renderSize.z();
   1457 
   1458 										str << "_" << caseDef.attachmentSize.x();
   1459 
   1460 	if (caseDef.attachmentSize.y() > 1)	str << "x" << caseDef.attachmentSize.y();
   1461 	if (caseDef.attachmentSize.z() > 1)	str << "x" << caseDef.attachmentSize.z();
   1462 	if (caseDef.numLayers > 1)			str << "_" << caseDef.numLayers;
   1463 
   1464 	return str.str();
   1465 }
   1466 
   1467 std::string getTestCaseString (const CaseDef& caseDef)
   1468 {
   1469 	std::ostringstream str;
   1470 
   1471 	str << getShortImageViewTypeName (caseDef.imageType).c_str();
   1472 	str << "_";
   1473 	str << getSizeString(caseDef);
   1474 
   1475 	if (caseDef.multisample)
   1476 		str << "_ms";
   1477 
   1478 	return str.str();
   1479 }
   1480 
   1481 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
   1482 {
   1483 
   1484 	// Add test cases for attachment strictly sizes larger than the framebuffer
   1485 	const CaseDef	caseDef[]	=
   1486 	{
   1487 		// Single-sample test cases
   1488 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,		false },
   1489 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,		false },
   1490 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,		false },
   1491 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,		false },
   1492 
   1493 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(64, 1, 1),	4,		false },
   1494 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(48, 1, 1),	4,		false },
   1495 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(39, 1, 1),	4,		false },
   1496 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(19, 1, 1),	IVec3(32, 1, 1),	4,		false },
   1497 
   1498 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		false },
   1499 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		false },
   1500 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		false },
   1501 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		false },
   1502 
   1503 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		false },
   1504 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		false },
   1505 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		false },
   1506 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		false },
   1507 
   1508 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	6,		false },
   1509 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	6,		false },
   1510 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	6,		false },
   1511 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	6,		false },
   1512 
   1513 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	6*2,	false },
   1514 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	6*2,	false },
   1515 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	6*2,	false },
   1516 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	6*2,	false },
   1517 
   1518 		// Multi-sample test cases
   1519 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		true },
   1520 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		true },
   1521 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		true },
   1522 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		true },
   1523 
   1524 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		true },
   1525 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		true },
   1526 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		true },
   1527 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		true },
   1528 	};
   1529 
   1530 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
   1531 		addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
   1532 
   1533 	// Add tests for the case where there are no color attachments but the
   1534 	// fragment shader writes to an image via imageStore().
   1535 	addFunctionCaseWithPrograms(group, "no_attachments", "", initImagePrograms, testNoAtt, false);
   1536 	addFunctionCaseWithPrograms(group, "no_attachments_ms", "", initImagePrograms, testNoAtt, true);
   1537 
   1538 	// Test render pass with attachment set as unused.
   1539 	addFunctionCase(group, "unused_attachment", "", testUnusedAtt);
   1540 
   1541 	const CaseDef	differentAttachmentSizesCaseDef[]	=
   1542 	{
   1543 		// Single-sample test cases
   1544 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,	false },
   1545 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,	false },
   1546 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,	false },
   1547 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,	false },
   1548 
   1549 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	false },
   1550 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	false },
   1551 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	false },
   1552 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	false },
   1553 
   1554 		// Multi-sample test cases
   1555 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	true },
   1556 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	true },
   1557 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	true },
   1558 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	true }
   1559 	};
   1560 
   1561 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
   1562 		addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]);
   1563 }
   1564 
   1565 } // anonymous ns
   1566 
   1567 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
   1568 {
   1569 	return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);
   1570 }
   1571 
   1572 } // pipeline
   1573 } // vkt
   1574