• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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>
makeSharedPtr(Move<T> move)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>
sizeInBytes(const vector<T> & vec)90 inline VkDeviceSize sizeInBytes(const vector<T>& vec)
91 {
92 	return vec.size() * sizeof(vec[0]);
93 }
94 
getImageType(const VkImageViewType viewType)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.
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,const deUint32 numLayers,const bool multisample)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 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule fragmentModule,const IVec3 renderSize,const VkPrimitiveTopology topology,const deUint32 subpass,const deUint32 numAttachments,const bool multisample)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 
makeImage(const DeviceInterface & vk,const VkDevice device,const VkImageCreateFlags flags,const VkImageType imageType,const VkFormat format,const IVec3 & size,const deUint32 numLayers,const VkImageUsageFlags usage,const bool multisample)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 
genFullQuadVertices(const int subpassCount)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 
initColorPrograms(SourceCollections & programCollection,const CaseDef caseDef)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 
getExpectedData(tcu::TextureLevel & textureLevel,const CaseDef & caseDef)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 
makeColorSubresourceRange(const deUint32 baseArrayLayer,const deUint32 layerCount)373 inline VkImageSubresourceRange makeColorSubresourceRange (const deUint32 baseArrayLayer, const deUint32 layerCount)
374 {
375 	return makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, baseArrayLayer, layerCount);
376 }
377 
378 // Tests rendering to a a framebuffer with color attachments larger than the
379 // framebuffer dimensions and verifies that rendering does not affect the areas
380 // of the attachment outside the framebuffer dimensions. Tests both single-sample
381 // and multi-sample configurations.
test(Context & context,const CaseDef caseDef)382 tcu::TestStatus test (Context& context, const CaseDef caseDef)
383 {
384 	const DeviceInterface&			vk					= context.getDeviceInterface();
385 	const VkDevice					device				= context.getDevice();
386 	const VkQueue					queue				= context.getUniversalQueue();
387 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
388 	Allocator&						allocator			= context.getDefaultAllocator();
389 
390 	// Color image for rendering in single-sample tests or resolve target for multi-sample tests
391 	Move<VkImage>					colorImage;
392 	MovePtr<Allocation>				colorImageAlloc;
393 
394 	// For multisampled tests, this is the rendering target
395 	Move<VkImage>					msColorImage;
396 	MovePtr<Allocation>				msColorImageAlloc;
397 
398 	// Host memory buffer where we will copy the rendered image for verification
399 	const deUint32					att_size_x			= caseDef.attachmentSize.x();
400 	const deUint32					att_size_y			= caseDef.attachmentSize.y();
401 	const deUint32					att_size_z			= caseDef.attachmentSize.z();
402 	const VkDeviceSize				colorBufferSize		= att_size_x * att_size_y * att_size_z * caseDef.numLayers * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
403 	const Unique<VkBuffer>			colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
404 	const UniquePtr<Allocation>		colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
405 
406 	Move<VkBuffer>					vertexBuffer;
407 	MovePtr<Allocation>				vertexBufferAlloc;
408 
409 	vector<SharedPtrVkImageView>	colorAttachments;
410 	vector<VkImageView>				attachmentHandles;
411 
412 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
413 	vector<SharedPtrVkPipeline>		pipeline;
414 	const Unique<VkRenderPass>		renderPass			(makeRenderPass(vk, device, COLOR_FORMAT, caseDef.numLayers, caseDef.multisample));
415 	Move<VkFramebuffer>				framebuffer;
416 
417 	const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
418 	const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
419 
420 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
421 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
422 
423 	const VkImageViewType			imageViewType		= caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
424 		? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
425 
426 	// create vertexBuffer
427 	{
428 		const vector<tcu::Vec4>	vertices			= genFullQuadVertices(caseDef.numLayers);
429 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
430 
431 		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
432 		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
433 
434 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
435 		flushAlloc(vk, device, *vertexBufferAlloc);
436 	}
437 
438 	// create colorImage (and msColorImage) using the configured attachmentsize
439 	{
440 		const VkImageUsageFlags	colorImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
441 
442 		colorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
443 			caseDef.attachmentSize, caseDef.numLayers, colorImageUsage, false);
444 		colorImageAlloc	= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
445 
446 		if (caseDef.multisample)
447 		{
448 			const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
449 
450 			msColorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
451 				caseDef.attachmentSize, caseDef.numLayers, msImageUsage, true);
452 			msColorImageAlloc	= bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
453 		}
454 	}
455 
456 	// create attachmentHandles and pipelines (one for each layer). We use the renderSize for viewport and scissor
457 	for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
458 	{
459 		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
460 			imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
461 		attachmentHandles.push_back(**colorAttachments.back());
462 
463 		pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
464 			caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample)));
465 	}
466 
467 	// create framebuffer
468 	framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
469 		static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
470 
471 	// record command buffer
472 	beginCommandBuffer(vk, *cmdBuffer);
473 	{
474 		// Clear the entire image attachment to black
475 		{
476 			const VkImageMemoryBarrier	imageLayoutBarriers[]	=
477 			{
478 				{
479 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
480 					DE_NULL,											// const void*				pNext;
481 					0u,													// VkAccessFlags			srcAccessMask;
482 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
483 					VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
484 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
485 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
486 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
487 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
488 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
489 				},
490 			};
491 
492 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
493 				0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
494 
495 			const VkImageSubresourceRange	ranges		= makeColorSubresourceRange(0, caseDef.numLayers);
496 			const VkClearColorValue			clearColor	=
497 	        {
498                 {0.0f, 0.0f, 0.0f, 1.0f}
499 			};
500 			vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
501 
502 			const VkImageMemoryBarrier	imageClearBarriers[]	=
503 			{
504 				{
505 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
506 					DE_NULL,											// const void*				pNext;
507 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
508 					VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,				// VkAccessFlags			dstAccessMask;
509 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
510 					VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
511 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
512 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
513 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
514 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
515 				},
516 			};
517 
518 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
519 				0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
520 		}
521 
522 		// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
523 		{
524 			const VkDeviceSize			vertexBufferOffset	= 0ull;
525 
526 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
527 			{
528 				vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
529 				for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
530 				{
531 					if (layerNdx != 0)
532 						vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
533 
534 					vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[layerNdx]);
535 					vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
536 				}
537 			}
538 			endRenderPass(vk, *cmdBuffer);
539 		}
540 
541 		// If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
542 		if (caseDef.multisample)
543 		{
544 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
545 			const VkImageMemoryBarrier	imageBarriers[]	=
546 			{
547 				{
548 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
549 					DE_NULL,										// const void*				pNext;
550 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask;
551 					VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			dstAccessMask;
552 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
553 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
554 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
555 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
556 					*msColorImage,									// VkImage					image;
557 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
558 				},
559 				{
560 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
561 					DE_NULL,										// const void*				pNext;
562 					(VkAccessFlags)0,								// VkAccessFlags			srcAccessMask;
563 					VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
564 					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
565 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
566 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
567 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
568 					*colorImage,									// VkImage					image;
569 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
570 				}
571 			};
572 
573 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
574 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
575 
576 			const VkImageResolve	region	=
577 			{
578 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    srcSubresource;
579 				makeOffset3D(0, 0, 0),															// VkOffset3D                  srcOffset;
580 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    dstSubresource;
581 				makeOffset3D(0, 0, 0),															// VkOffset3D                  dstOffset;
582 				makeExtent3D(caseDef.attachmentSize)											// VkExtent3D                  extent;
583 			};
584 
585 			vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
586 		}
587 
588 		// copy colorImage to host visible colorBuffer
589 		{
590 			const VkImageMemoryBarrier	imageBarriers[]		=
591 			{
592 				{
593 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
594 					DE_NULL,																					// const void*				pNext;
595 					(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
596 					VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
597 					caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
598 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
599 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
600 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
601 					*colorImage,																				// VkImage					image;
602 					makeColorSubresourceRange(0, caseDef.numLayers)												// VkImageSubresourceRange	subresourceRange;
603 				}
604 			};
605 
606 			vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
607 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
608 
609 			const VkBufferImageCopy		region				=
610 			{
611 				0ull,																				// VkDeviceSize                bufferOffset;
612 				0u,																					// uint32_t                    bufferRowLength;
613 				0u,																					// uint32_t                    bufferImageHeight;
614 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),	// VkImageSubresourceLayers    imageSubresource;
615 				makeOffset3D(0, 0, 0),																// VkOffset3D                  imageOffset;
616 				makeExtent3D(caseDef.attachmentSize),												// VkExtent3D                  imageExtent;
617 			};
618 
619 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
620 
621 			const VkBufferMemoryBarrier	bufferBarriers[]	=
622 			{
623 				{
624 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
625 					DE_NULL,									// const void*        pNext;
626 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
627 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
628 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
629 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
630 					*colorBuffer,								// VkBuffer           buffer;
631 					0ull,										// VkDeviceSize       offset;
632 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
633 				},
634 			};
635 
636 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
637 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
638 		}
639 	} // beginCommandBuffer
640 
641 	endCommandBuffer(vk, *cmdBuffer);
642 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
643 
644 	// Verify results
645 	{
646 		invalidateAlloc(vk, device, *colorBufferAlloc);
647 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
648 		const int							depth			= deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
649 		tcu::TextureLevel					textureLevel	(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
650 		const tcu::PixelBufferAccess		expectedImage	= getExpectedData(textureLevel, caseDef);
651 		const tcu::ConstPixelBufferAccess	resultImage		(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
652 
653 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
654 			return tcu::TestStatus::fail("Fail");
655 	}
656 
657 	return tcu::TestStatus::pass("Pass");
658 }
659 
initImagePrograms(SourceCollections & programCollection,const bool multisample)660 void initImagePrograms (SourceCollections& programCollection, const bool multisample)
661 {
662 	// Vertex shader
663 	{
664 		std::ostringstream src;
665 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
666 			<< "\n"
667 			<< "layout(location = 0) in vec4 in_position;\n"
668 			<< "\n"
669 			<< "out gl_PerVertex {\n"
670 			<< "	vec4 gl_Position;\n"
671 			<< "	float gl_PointSize;\n"
672 			<< "};\n"
673 			<< "\n"
674 			<< "void main(void)\n"
675 			<< "{\n"
676 			<< "	gl_Position	= in_position;\n"
677 			<< "	gl_PointSize = 1.0f;\n"
678 			<< "}\n";
679 
680 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
681 	}
682 
683 	// Fragment shader
684 	{
685 		std::ostringstream src;
686 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
687 			<< "\n"
688 			<< "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
689 			<< "\n"
690 			<< "void main(void)\n"
691 			<< "{\n";
692 			if (!multisample)
693 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
694 			else
695 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
696 			src << "}\n";
697 
698 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
699 	}
700 }
701 
702 //! Make a render pass with no attachments
makeRenderPassNoAtt(const DeviceInterface & vk,const VkDevice device)703 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
704 {
705 	// Create a single subpass with no attachment references
706 	vector<VkSubpassDescription>	subpasses;
707 
708 	const VkSubpassDescription		subpassDescription	=
709 	{
710 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
711 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
712 		0u,									// deUint32							inputAttachmentCount;
713 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
714 		0u,									// deUint32							colorAttachmentCount;
715 		DE_NULL,							// const VkAttachmentReference*		pColorAttachments;
716 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
717 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
718 		0u,									// deUint32							preserveAttachmentCount;
719 		DE_NULL								// const deUint32*					pPreserveAttachments;
720 	};
721 	subpasses.push_back(subpassDescription);
722 
723 	const VkRenderPassCreateInfo	renderPassInfo	=
724 	{
725 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
726 		DE_NULL,									// const void*						pNext;
727 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
728 		0,											// deUint32							attachmentCount;
729 		DE_NULL,									// const VkAttachmentDescription*	pAttachments;
730 		1,											// deUint32							subpassCount;
731 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
732 		0u,											// deUint32							dependencyCount;
733 		DE_NULL										// const VkSubpassDependency*		pDependencies;
734 	};
735 
736 	return createRenderPass(vk, device, &renderPassInfo);
737 }
738 
getExpectedDataNoAtt(tcu::TextureLevel & textureLevel)739 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
740 {
741 	const tcu::PixelBufferAccess	expectedImage	(textureLevel);
742 	for (int z = 0; z < expectedImage.getDepth(); ++z)
743 	{
744 		for (int y = 0; y < expectedImage.getHeight(); ++y)
745 		{
746 			for (int x = 0; x < expectedImage.getWidth(); ++x)
747 			{
748 				expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
749 			}
750 		}
751 	}
752 	return expectedImage;
753 }
754 
genPointVertices(void)755 vector<tcu::Vec4> genPointVertices (void)
756 {
757 	vector<tcu::Vec4>	vectorData;
758 	vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
759 	vectorData.push_back(Vec4(-0.25f,  0.25f, 0, 1));
760 	vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
761 	vectorData.push_back(Vec4(0.25f,  0.25f, 0, 1));
762 	return vectorData;
763 }
764 
765 // Tests rendering to a framebuffer without color attachments, checking that
766 // the fragment shader is run even in the absence of color output. In this case
767 // we render 4 point primitives and we make the fragment shader write to a
768 // different pixel of an image via an imageStore command. For the single-sampled
769 // configuration we use a 4x1 image to record the output and for the
770 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
771 // 4-sample multi-sampling
testNoAtt(Context & context,const bool multisample)772 tcu::TestStatus testNoAtt (Context& context, const bool multisample)
773 {
774 	const DeviceInterface&				vk						= context.getDeviceInterface();
775 	const VkDevice						device					= context.getDevice();
776 	const VkQueue						queue					= context.getUniversalQueue();
777 	const deUint32						queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
778 	Allocator&							allocator				= context.getDefaultAllocator();
779 	const IVec3							renderSize				(32, 32, 1);
780 
781 	Move<VkBuffer>						vertexBuffer;
782 	MovePtr<Allocation>					vertexBufferAlloc;
783 
784 	const Unique<VkShaderModule>		vertexModule			(createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
785 	const Unique<VkShaderModule>		fragmentModule			(createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
786 
787 	// Create image where we will record the writes. For single-sampled cases this is a 4x1 image
788 	// and for multi-sampled cases this is a 4x<num_samples> image.
789 	const deUint8						numSamples				= multisample ? 4 : 1;
790 	const deUint8						imageWidth				= 4;
791 	const deUint8						imageHeight				= numSamples;
792 	const deUint8						imageDepth				= 1;
793 	const deUint8						imageLayers				= 1;
794 	const IVec3							imageDim				= IVec3(imageWidth, imageHeight, imageDepth);
795 	const VkImageUsageFlags				imageUsage				= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
796 	const Move<VkImage>					image					= makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
797 	const VkImageSubresourceRange		imageSubresourceRange	= makeColorSubresourceRange(0u, imageLayers);
798 	const MovePtr<Allocation>			imageAlloc				= bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
799 	const Move<VkImageView>				imageView				= makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
800 
801 	// Create a buffer where we will copy the image for verification
802 	const VkDeviceSize					colorBufferSize		= imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
803 	const Unique<VkBuffer>				colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
804 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
805 
806 	// Create pipeline descriptor set for the image
807 	const Move<VkDescriptorSetLayout>	descriptorSetLayout		= DescriptorSetLayoutBuilder()
808 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
809 		.build(vk, device);
810 
811 	const Move<VkDescriptorPool>		descriptorPool			= DescriptorPoolBuilder()
812 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
813 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
814 
815 	const Move<VkDescriptorSet>			descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
816 	const VkDescriptorImageInfo			descriptorImageInfo		= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
817 	DescriptorSetUpdateBuilder()
818 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
819 		.update(vk, device);
820 
821 	const Unique<VkPipelineLayout>		pipelineLayout			(makePipelineLayout (vk, device, *descriptorSetLayout));
822 	vector<SharedPtrVkPipeline>			pipeline;
823 	const Unique<VkRenderPass>			renderPass				(makeRenderPassNoAtt (vk, device));
824 	Move<VkFramebuffer>					framebuffer;
825 
826 	const Unique<VkCommandPool>			cmdPool					(createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
827 	const Unique<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer (vk, device, *cmdPool));
828 
829 	// create vertexBuffer
830 	{
831 		const vector<tcu::Vec4>	vertices			= genPointVertices();
832 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
833 
834 		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
835 		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
836 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
837 		flushAlloc(vk, device, *vertexBufferAlloc);
838 	}
839 
840 	// Create render pass and pipeline
841 	pipeline.push_back(makeSharedPtr(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
842 		renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, multisample)));
843 	framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
844 
845 	// Record command buffer
846 	beginCommandBuffer(vk, *cmdBuffer);
847 	{
848 		// shader image layout transition undefined -> general
849 		{
850 			const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
851 				0u, VK_ACCESS_SHADER_WRITE_BIT,
852 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
853 				*image, imageSubresourceRange);
854 
855 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
856 				0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
857 		}
858 
859 		// Render pass
860 		{
861 			const VkDeviceSize vertexBufferOffset = 0ull;
862 
863 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
864 
865 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, **pipeline[0]);
866 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
867 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
868 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
869 
870 			endRenderPass(vk, *cmdBuffer);
871 		}
872 
873 		// copy image to host visible colorBuffer
874 		{
875 			const VkImageMemoryBarrier	imageBarriers[]		=
876 			{
877 				{
878 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
879 					DE_NULL,									// const void*				pNext;
880 					VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
881 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
882 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			oldLayout;
883 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
884 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
885 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
886 					*image,										// VkImage					image;
887 					makeColorSubresourceRange(0, 1)				// VkImageSubresourceRange	subresourceRange;
888 				}
889 			};
890 
891 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
892 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
893 
894 			const VkBufferImageCopy		region				=
895 			{
896 				0ull,																// VkDeviceSize                bufferOffset;
897 				0u,																	// uint32_t                    bufferRowLength;
898 				0u,																	// uint32_t                    bufferImageHeight;
899 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1),	// VkImageSubresourceLayers    imageSubresource;
900 				makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
901 				makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)),			// VkExtent3D                  imageExtent;
902 			};
903 
904 			vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
905 
906 			const VkBufferMemoryBarrier	bufferBarriers[]	=
907 			{
908 				{
909 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
910 					DE_NULL,									// const void*        pNext;
911 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
912 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
913 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
914 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
915 					*colorBuffer,								// VkBuffer           buffer;
916 					0ull,										// VkDeviceSize       offset;
917 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
918 				},
919 			};
920 
921 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
922 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
923 		}
924 	} // beginCommandBuffer
925 
926 	endCommandBuffer(vk, *cmdBuffer);
927 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
928 
929 	// Verify results
930 	{
931 		invalidateAlloc(vk, device, *colorBufferAlloc);
932 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
933 		tcu::TextureLevel					textureLevel	(format, imageWidth, imageHeight, imageDepth);
934 		const tcu::PixelBufferAccess		expectedImage	= getExpectedDataNoAtt(textureLevel);
935 		const tcu::ConstPixelBufferAccess	resultImage		(format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
936 
937 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
938 			return tcu::TestStatus::fail("Fail");
939 	}
940 
941 	return tcu::TestStatus::pass("Pass");
942 }
943 
944 //! Make a render pass with three color attachments
makeRenderPassDifferentAttachmentSizes(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,deUint32 numAttachments,const bool multisample)945 Move<VkRenderPass> makeRenderPassDifferentAttachmentSizes	(const DeviceInterface&	vk,
946 															 const VkDevice			device,
947 															 const VkFormat			colorFormat,
948 															 deUint32				numAttachments,
949 															 const bool				multisample)
950 {
951 	vector<VkAttachmentDescription>	attachmentDescriptions		(numAttachments);
952 	vector<VkAttachmentReference>	colorAttachmentReferences	(numAttachments);
953 
954 	for (deUint32 i = 0; i < numAttachments; i++)
955 	{
956 		VkAttachmentDescription colorAttachmentDescription =
957 		{
958 			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
959 			colorFormat,													// VkFormat						format;
960 			!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits		samples;
961 			VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
962 			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
963 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
964 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
965 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				initialLayout;
966 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
967 		};
968 		attachmentDescriptions[i] = colorAttachmentDescription;
969 
970 		const VkAttachmentReference attachmentRef =
971 		{
972 			i,											// deUint32			attachment;
973 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
974 		};
975 		colorAttachmentReferences[i] = attachmentRef;
976 	}
977 
978 	const VkSubpassDescription subpassDescription =
979 	{
980 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
981 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
982 		0u,									// deUint32							inputAttachmentCount;
983 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
984 		numAttachments,						// deUint32							colorAttachmentCount;
985 		&colorAttachmentReferences[0],		// const VkAttachmentReference*		pColorAttachments;
986 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
987 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
988 		0u,									// deUint32							preserveAttachmentCount;
989 		DE_NULL								// const deUint32*					pPreserveAttachments;
990 	};
991 
992 	const VkRenderPassCreateInfo renderPassInfo =
993 	{
994 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
995 		DE_NULL,									// const void*						pNext;
996 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
997 		numAttachments,								// deUint32							attachmentCount;
998 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
999 		1u,											// deUint32							subpassCount;
1000 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
1001 		0u,											// deUint32							dependencyCount;
1002 		DE_NULL										// const VkSubpassDependency*		pDependencies;
1003 	};
1004 
1005 	return createRenderPass(vk, device, &renderPassInfo);
1006 }
1007 
1008 // Tests framebuffer with attachments of different sizes
testDifferentAttachmentSizes(Context & context,const CaseDef caseDef)1009 tcu::TestStatus testDifferentAttachmentSizes (Context& context, const CaseDef caseDef)
1010 {
1011 	const DeviceInterface&			vk					= context.getDeviceInterface();
1012 	const VkDevice					device				= context.getDevice();
1013 	const VkQueue					queue				= context.getUniversalQueue();
1014 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1015 	Allocator&						allocator			= context.getDefaultAllocator();
1016 	const deUint32					numRenderTargets	= 3;
1017 
1018 	// Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1019 	Move<VkImage>					colorImages[numRenderTargets];
1020 	MovePtr<Allocation>				colorImageAllocs[numRenderTargets];
1021 
1022 	// For multisampled tests, these are the rendering targets
1023 	Move<VkImage>					msColorImages[numRenderTargets];
1024 	MovePtr<Allocation>				msColorImageAllocs[numRenderTargets];
1025 
1026 	Move<VkBuffer>					colorBuffers[numRenderTargets];
1027 	MovePtr<Allocation>				colorBufferAllocs[numRenderTargets];
1028 
1029 	// Vary attachment sizes by adding an offset to the base size.
1030 	const IVec3						attachmentSizes[]	=
1031 	{
1032 		caseDef.attachmentSize,
1033 		caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1034 		caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
1035 	};
1036 
1037 	// Use unique clear color for each render target to verify no leaking happens between render target clears.
1038 	const VkClearColorValue			clearColors[]		=
1039 	{
1040 		{{1.0f, 0.0f, 0.0f, 1.0f}},
1041 		{{0.0f, 1.0f, 0.0f, 1.0f}},
1042 		{{0.0f, 0.0f, 1.0f, 1.0f}}
1043 	};
1044 
1045 	Move<VkBuffer>					vertexBuffer;
1046 	MovePtr<Allocation>				vertexBufferAlloc;
1047 
1048 	vector<SharedPtrVkImageView>	colorAttachments;
1049 	vector<VkImageView>				attachmentHandles;
1050 
1051 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
1052 	Move<VkPipeline>				pipeline;
1053 	const Unique<VkRenderPass>		renderPass			(makeRenderPassDifferentAttachmentSizes(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1054 	Move<VkFramebuffer>				framebuffer;
1055 
1056 	const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1057 	const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1058 
1059 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1060 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
1061 
1062 	const VkImageViewType			imageViewType		= caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
1063 		? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
1064 
1065 	const VkImageSubresourceRange	range				= makeColorSubresourceRange(0, 1);
1066 
1067 	// create color buffers
1068 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1069 	{
1070 		// Host memory buffer where we will copy the rendered image for verification
1071 		const deUint32					att_size_x			= attachmentSizes[renderTargetIdx].x();
1072 		const deUint32					att_size_y			= attachmentSizes[renderTargetIdx].y();
1073 		const deUint32					att_size_z			= attachmentSizes[renderTargetIdx].z();
1074 		const VkDeviceSize				colorBufferSize		= att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1075 		colorBuffers[renderTargetIdx]						= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1076 		colorBufferAllocs[renderTargetIdx]					= bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1077 	}
1078 
1079 	// create vertexBuffer
1080 	{
1081 		const vector<tcu::Vec4>	vertices			= genFullQuadVertices(1);
1082 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
1083 
1084 		vertexBuffer								= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1085 		vertexBufferAlloc							= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1086 
1087 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1088 		flushAlloc(vk, device, *vertexBufferAlloc);
1089 	}
1090 
1091 	// create colorImages (and msColorImages) using the configured attachmentsize
1092 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1093 	{
1094 		const VkImageUsageFlags	colorImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
1095 		colorImages[renderTargetIdx]			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1096 			attachmentSizes[renderTargetIdx], 1, colorImageUsage, false);
1097 		colorImageAllocs[renderTargetIdx]		= bindImage(vk, device, allocator, *colorImages[renderTargetIdx], MemoryRequirement::Any);
1098 
1099 		if (caseDef.multisample)
1100 		{
1101 			const VkImageUsageFlags	msImageUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1102 
1103 			msColorImages[renderTargetIdx]			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSizes[renderTargetIdx], 1, msImageUsage, true);
1104 			msColorImageAllocs[renderTargetIdx]		= bindImage(vk, device, allocator, *msColorImages[renderTargetIdx], MemoryRequirement::Any);
1105 		}
1106 	}
1107 
1108 	// create attachmentHandles. We use the renderSize for viewport and scissor
1109 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1110 	{
1111 		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImages[renderTargetIdx] : *msColorImages[renderTargetIdx], imageViewType, COLOR_FORMAT, range)));
1112 		attachmentHandles.push_back(**colorAttachments.back());
1113 	}
1114 
1115 	pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, numRenderTargets, caseDef.multisample);
1116 
1117 	// create framebuffer
1118 	framebuffer = makeFramebuffer(vk, device, *renderPass, numRenderTargets, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1119 
1120 	// record command buffer
1121 	beginCommandBuffer(vk, *cmdBuffer);
1122 
1123 	// Clear image attachments
1124 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1125 	{
1126 		{
1127 			const VkImageMemoryBarrier	imageLayoutBarriers[]	=
1128 			{
1129 				{
1130 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1131 					DE_NULL,																				// const void*				pNext;
1132 					0u,																						// VkAccessFlags			srcAccessMask;
1133 					VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
1134 					VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
1135 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
1136 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1137 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1138 					caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],	// VkImage					image;
1139 					range																					// VkImageSubresourceRange	subresourceRange;
1140 				},
1141 			};
1142 
1143 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1144 				0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
1145 
1146 			vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColors[renderTargetIdx], 1u, &range);
1147 
1148 			const VkImageMemoryBarrier	imageClearBarriers[]	=
1149 			{
1150 				{
1151 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1152 					DE_NULL,																				// const void*				pNext;
1153 					VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
1154 					VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,													// VkAccessFlags			dstAccessMask;
1155 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
1156 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,												// VkImageLayout			newLayout;
1157 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1158 					VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1159 					caseDef.multisample ? *msColorImages[renderTargetIdx] : *colorImages[renderTargetIdx],	// VkImage					image;
1160 					range																					// VkImageSubresourceRange	subresourceRange;
1161 				},
1162 			};
1163 
1164 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
1165 		}
1166 	}
1167 
1168 	// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1169 	{
1170 		const VkDeviceSize			vertexBufferOffset	= 0ull;
1171 
1172 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1173 		{
1174 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1175 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1176 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1177 		}
1178 		endRenderPass(vk, *cmdBuffer);
1179 	}
1180 
1181 	// If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
1182 	if (caseDef.multisample)
1183 	{
1184 		for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1185 		{
1186 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1187 			const VkImageMemoryBarrier	imageBarriers[]	=
1188 			{
1189 				{
1190 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1191 					DE_NULL,									// const void*				pNext;
1192 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
1193 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1194 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
1195 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			newLayout;
1196 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1197 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
1198 					*msColorImages[renderTargetIdx],			// VkImage					image;
1199 					range										// VkImageSubresourceRange	subresourceRange;
1200 				},
1201 				{
1202 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
1203 					DE_NULL,								// const void*				pNext;
1204 					(VkAccessFlags)0,						// VkAccessFlags			srcAccessMask;
1205 					VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1206 					VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
1207 					VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout			newLayout;
1208 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
1209 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					destQueueFamilyIndex;
1210 					*colorImages[renderTargetIdx],			// VkImage					image;
1211 					range									// VkImageSubresourceRange	subresourceRange;
1212 				}
1213 			};
1214 
1215 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1216 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1217 
1218 			const VkImageResolve	region	=
1219 			{
1220 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    srcSubresource;
1221 				makeOffset3D(0, 0, 0),											// VkOffset3D                  srcOffset;
1222 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    dstSubresource;
1223 				makeOffset3D(0, 0, 0),											// VkOffset3D                  dstOffset;
1224 				makeExtent3D(attachmentSizes[renderTargetIdx])					// VkExtent3D                  extent;
1225 			};
1226 
1227 			vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, &region);
1228 		}
1229 	}
1230 
1231 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1232 	{
1233 		// copy colorImage to host visible colorBuffer
1234 		const VkImageMemoryBarrier	imageBarrier		=
1235 		{
1236 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
1237 			DE_NULL,																					// const void*				pNext;
1238 			(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1239 			VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1240 			caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
1241 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
1242 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
1243 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
1244 			*colorImages[renderTargetIdx],																// VkImage					image;
1245 			range																						// VkImageSubresourceRange	subresourceRange;
1246 		};
1247 
1248 		vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1249 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1250 
1251 		const VkBufferImageCopy		region				=
1252 		{
1253 			0ull,																// VkDeviceSize                bufferOffset;
1254 			0u,																	// uint32_t                    bufferRowLength;
1255 			0u,																	// uint32_t                    bufferImageHeight;
1256 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
1257 			makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1258 			makeExtent3D(attachmentSizes[renderTargetIdx]),						// VkExtent3D                  imageExtent;
1259 		};
1260 
1261 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, &region);
1262 
1263 		const VkBufferMemoryBarrier	bufferBarrier		=
1264 		{
1265 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1266 			DE_NULL,									// const void*        pNext;
1267 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1268 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1269 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
1270 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
1271 			*colorBuffers[renderTargetIdx],				// VkBuffer           buffer;
1272 			0ull,										// VkDeviceSize       offset;
1273 			VK_WHOLE_SIZE,								// VkDeviceSize       size;
1274 		};
1275 
1276 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1277 			0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1278 	}
1279 
1280 	endCommandBuffer(vk, *cmdBuffer);
1281 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1282 
1283 	// Verify results
1284 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1285 	{
1286 		const tcu::TextureFormat			format				= mapVkFormat(COLOR_FORMAT);
1287 		const IVec3							size				= attachmentSizes[renderTargetIdx];
1288 		tcu::TextureLevel					textureLevel		(format, size.x(), size.y(), size.z());
1289 		const tcu::PixelBufferAccess		expectedImage		(textureLevel);
1290 
1291 		const tcu::Vec4						expectedColors[]	=
1292 		{
1293 			tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
1294 			tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1295 			tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
1296 		};
1297 
1298 		invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
1299 
1300 		for (int z = 0; z < expectedImage.getDepth(); ++z)
1301 		{
1302 			for (int y = 0; y < expectedImage.getHeight(); ++y)
1303 			{
1304 				for (int x = 0; x < expectedImage.getWidth(); ++x)
1305 				{
1306 					if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1307 						expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1308 					else
1309 						expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1310 				}
1311 			}
1312 		}
1313 		const tcu::ConstPixelBufferAccess	resultImage		(format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
1314 
1315 		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))
1316 			return tcu::TestStatus::fail("Fail");
1317 	}
1318 
1319 	return tcu::TestStatus::pass("Pass");
1320 }
1321 
initInputResolveSameAttachmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)1322 void initInputResolveSameAttachmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1323 {
1324 	DE_UNREF(caseDef);
1325 
1326 	// Vertex shader
1327 	{
1328 		std::ostringstream src;
1329 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1330 			<< "\n"
1331 			<< "layout(location = 0) in vec4 in_position;\n"
1332 			<< "\n"
1333 			<< "out gl_PerVertex {\n"
1334 			<< "	vec4 gl_Position;\n"
1335 			<< "};\n"
1336 			<< "\n"
1337 			<< "void main(void)\n"
1338 			<< "{\n"
1339 			<< "	gl_Position	= in_position;\n"
1340 			<< "}\n";
1341 
1342 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1343 	}
1344 
1345 	// Fragment shader
1346 	{
1347 		std::ostringstream src;
1348 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1349 			<< "\n"
1350 			<< "layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;\n"
1351 			<< "layout(location = 0) out vec4 o_color0;\n"
1352 			<< "\n"
1353 			<< "void main(void)\n"
1354 			<< "{\n"
1355 			<< "    vec4 in_color = subpassLoad(inputColor);\n"
1356 			<< "    o_color0 = vec4(1.0, in_color.y, 0.25, 1.0);\n"
1357 			<< "}\n";
1358 
1359 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1360 	}
1361 }
1362 
makeRenderPassInputResolveSameAttachment(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)1363 Move<VkRenderPass> makeRenderPassInputResolveSameAttachment	(const DeviceInterface&	vk,
1364 															 const VkDevice			device,
1365 															 const VkFormat			colorFormat)
1366 {
1367 	std::vector<VkAttachmentDescription> attachmentDescriptions;
1368 	VkAttachmentDescription colorAttachmentDescription =
1369 	{
1370 		(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
1371 		colorFormat,													// VkFormat						format;
1372 		VK_SAMPLE_COUNT_4_BIT,											// VkSampleCountFlagBits		samples;
1373 		VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
1374 		VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
1375 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
1376 		VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
1377 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				initialLayout;
1378 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
1379 	};
1380 
1381 	attachmentDescriptions.push_back(colorAttachmentDescription);
1382 
1383 	VkAttachmentDescription inputAttachmentDescription =
1384 	{
1385 		(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
1386 		colorFormat,													// VkFormat						format;
1387 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits		samples;
1388 		VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
1389 		VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
1390 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
1391 		VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
1392 		VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				initialLayout;
1393 		VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				finalLayout;
1394 	};
1395 
1396 	attachmentDescriptions.push_back(inputAttachmentDescription);
1397 
1398 	const VkAttachmentReference colorAttachmentRef =
1399 	{
1400 		0u,											// deUint32			attachment;
1401 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
1402 	};
1403 
1404 	const VkAttachmentReference inputAttachmentRef =
1405 	{
1406 		1u,											// deUint32			attachment;
1407 		VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout	layout;
1408 	};
1409 
1410 	const VkSubpassDescription subpassDescription =
1411 	{
1412 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags flags;
1413 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint pipelineBindPoint;
1414 		1u,									// deUint32 inputAttachmentCount;
1415 		&inputAttachmentRef,				// const VkAttachmentReference* pInputAttachments;
1416 		1u,									// deUint32 colorAttachmentCount;
1417 		&colorAttachmentRef,				// const VkAttachmentReference* pColorAttachments;
1418 		&inputAttachmentRef,				// const VkAttachmentReference* pResolveAttachments;
1419 		DE_NULL,							// const VkAttachmentReference* pDepthStencilAttachment;
1420 		0u,									// deUint32 preserveAttachmentCount;
1421 		DE_NULL								// const deUint32* pPreserveAttachments;
1422 	};
1423 
1424 	const VkRenderPassCreateInfo renderPassInfo =
1425 	{
1426 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
1427 		DE_NULL,									// const void*						pNext;
1428 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
1429 		(deUint32)attachmentDescriptions.size(),	// deUint32							attachmentCount;
1430 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
1431 		1u,											// deUint32							subpassCount;
1432 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
1433 		0u,											// deUint32							dependencyCount;
1434 		DE_NULL										// const VkSubpassDependency*		pDependencies;
1435 	};
1436 
1437 	return createRenderPass(vk, device, &renderPassInfo);
1438 }
1439 
testInputResolveSameAttachment(Context & context,const CaseDef caseDef)1440 tcu::TestStatus testInputResolveSameAttachment(Context &context, const CaseDef caseDef)
1441 {
1442 	const DeviceInterface&			vk					= context.getDeviceInterface();
1443 	const VkDevice					device				= context.getDevice();
1444 	const VkQueue					queue				= context.getUniversalQueue();
1445 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1446 	Allocator&						allocator			= context.getDefaultAllocator();
1447 
1448 	// Use unique clear color for each render target to verify no leaking happens between render target clears.
1449 	const VkClearColorValue			clearColor[] =
1450 	{
1451 			{{ 1.0f, 0.0f, 0.0f, 1.0f }},
1452 			{{ 0.0f, 0.5f, 0.0f, 1.0f }}
1453 	};
1454 
1455 	Move<VkBuffer>					vertexBuffer;
1456 	MovePtr<Allocation>				vertexBufferAlloc;
1457 
1458 	vector<SharedPtrVkImageView>	colorAttachments;
1459 	vector<VkImageView>				attachmentHandles;
1460 
1461 	// Create pipeline descriptor set for the image
1462 	const Move<VkDescriptorSetLayout>	descriptorSetLayout		= DescriptorSetLayoutBuilder()
1463 		.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
1464 		.build(vk, device);
1465 
1466 	const Move<VkDescriptorPool>		descriptorPool			= DescriptorPoolBuilder()
1467 		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1)
1468 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1469 
1470 	const Move<VkDescriptorSet>			descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1471 
1472 	const Unique<VkPipelineLayout>		pipelineLayout			(makePipelineLayout (vk, device, *descriptorSetLayout));
1473 	Move<VkPipeline>					pipeline;
1474 	const Unique<VkRenderPass>			renderPass				(makeRenderPassInputResolveSameAttachment(vk, device, COLOR_FORMAT));
1475 	Move<VkFramebuffer>					framebuffer;
1476 
1477 	const Unique<VkShaderModule>		vertexModule			(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1478 	const Unique<VkShaderModule>		fragmentModule			(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1479 
1480 	const Unique<VkCommandPool>			cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1481 	const Unique<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
1482 
1483 	const VkImageViewType				imageViewType			= caseDef.imageType;
1484 
1485 	const VkImageSubresourceRange		range					= makeColorSubresourceRange(0, 1);
1486 
1487 	// create color buffer
1488 	const IVec3							attachmentSize			= caseDef.attachmentSize;
1489 	const VkDeviceSize					colorBufferSize			= attachmentSize.x() * attachmentSize.y() * attachmentSize.z() * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1490 	auto								colorBuffer				= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1491 	MovePtr<Allocation>					colorBufferAlloc		= bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible);
1492 
1493 	// create vertexBuffer
1494 	{
1495 		const vector<tcu::Vec4>			vertices				= genFullQuadVertices(1);
1496 		const VkDeviceSize				vertexBufferSize		= sizeInBytes(vertices);
1497 
1498 		vertexBuffer											= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1499 		vertexBufferAlloc										= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1500 
1501 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1502 		flushAlloc(vk, device, *vertexBufferAlloc);
1503 	}
1504 
1505 	// create colorImages (and msColorImages)
1506 	const VkImageUsageFlags	colorImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT;
1507 	Move<VkImage>			colorImage			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1508 															attachmentSize, 1, colorImageUsage, false);
1509 	MovePtr<Allocation>		colorImageAlloc		= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1510 
1511 	const VkImageUsageFlags	msImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1512 	Move<VkImage>			msColorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSize, 1, msImageUsage, true);
1513 	MovePtr<Allocation>		msColorImageAlloc	= bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
1514 
1515 	// create attachmentHandles. We use the renderSize for viewport and scissor
1516 	colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *msColorImage, imageViewType, COLOR_FORMAT, range)));
1517 	attachmentHandles.push_back(**colorAttachments.back());
1518 
1519 	colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *colorImage, imageViewType, COLOR_FORMAT, range)));
1520 	attachmentHandles.push_back(**colorAttachments.back());
1521 
1522 	const VkDescriptorImageInfo			descriptorImageInfo		= makeDescriptorImageInfo(DE_NULL, attachmentHandles[1], VK_IMAGE_LAYOUT_GENERAL);
1523 	DescriptorSetUpdateBuilder()
1524 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfo)
1525 		.update(vk, device);
1526 
1527 	pipeline = makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1u, true);
1528 
1529 	// create framebuffer
1530 	framebuffer = makeFramebuffer(vk, device, *renderPass, 2u, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1531 
1532 	// record command buffer
1533 	beginCommandBuffer(vk, *cmdBuffer);
1534 
1535 	// Clear image attachments
1536 	{
1537 		const VkImageMemoryBarrier	imageLayoutBarriers[]	=
1538 		{
1539 			{
1540 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1541 				DE_NULL,																				// const void*				pNext;
1542 				0u,																						// VkAccessFlags			srcAccessMask;
1543 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
1544 				VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
1545 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
1546 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1547 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1548 				*msColorImage,																			// VkImage					image;
1549 				range																					// VkImageSubresourceRange	subresourceRange;
1550 			},
1551 			{
1552 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1553 				DE_NULL,																				// const void*				pNext;
1554 				(VkAccessFlags)0,																		// VkAccessFlags			srcAccessMask;
1555 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
1556 				VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
1557 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
1558 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1559 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1560 				*colorImage,																			// VkImage					image;
1561 				range																					// VkImageSubresourceRange	subresourceRange;
1562 			}
1563 		};
1564 
1565 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1566 							  0u, DE_NULL, 0u, DE_NULL, 2u, imageLayoutBarriers);
1567 
1568 		vk.cmdClearColorImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[0], 1u, &range);
1569 		vk.cmdClearColorImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[1], 1u, &range);
1570 
1571 		const VkImageMemoryBarrier	imageClearBarriers[]	=
1572 		{
1573 			{
1574 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1575 				DE_NULL,																				// const void*				pNext;
1576 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
1577 				VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,													// VkAccessFlags			dstAccessMask;
1578 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
1579 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,												// VkImageLayout			newLayout;
1580 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1581 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1582 				*msColorImage,																			// VkImage					image;
1583 				range																					// VkImageSubresourceRange	subresourceRange;
1584 			},
1585 			{
1586 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1587 				DE_NULL,																				// const void*				pNext;
1588 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
1589 				VK_ACCESS_SHADER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1590 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
1591 				VK_IMAGE_LAYOUT_GENERAL,																// VkImageLayout			newLayout;
1592 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1593 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1594 				*colorImage,																			// VkImage					image;
1595 				range																					// VkImageSubresourceRange	subresourceRange;
1596 			}
1597 		};
1598 
1599 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[0]);
1600 
1601 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[1]);
1602 	}
1603 
1604 	// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1605 	{
1606 		const VkDeviceSize			vertexBufferOffset	= 0ull;
1607 
1608 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1609 		{
1610 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1611 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1612 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1613 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1614 		}
1615 		endRenderPass(vk, *cmdBuffer);
1616 	}
1617 
1618 	// copy colorImage to host visible colorBuffer
1619 	const VkImageMemoryBarrier	imageBarrier		=
1620 	{
1621 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
1622 		DE_NULL,																					// const void*				pNext;
1623 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,														// VkAccessFlags			srcAccessMask;
1624 		VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1625 		VK_IMAGE_LAYOUT_GENERAL,																	// VkImageLayout			oldLayout;
1626 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
1627 		VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
1628 		VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
1629 		*colorImage,																				// VkImage					image;
1630 		range																						// VkImageSubresourceRange	subresourceRange;
1631 	};
1632 
1633 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1634 						  0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1635 
1636 	const VkBufferImageCopy		regionBufferImageCopy				=
1637 	{
1638 		0ull,																// VkDeviceSize                bufferOffset;
1639 		0u,																	// uint32_t                    bufferRowLength;
1640 		0u,																	// uint32_t                    bufferImageHeight;
1641 		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
1642 		makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1643 		makeExtent3D(attachmentSize),										// VkExtent3D                  imageExtent;
1644 	};
1645 
1646 	vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &regionBufferImageCopy);
1647 
1648 	const VkBufferMemoryBarrier	bufferBarrier		=
1649 	{
1650 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1651 		DE_NULL,									// const void*        pNext;
1652 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1653 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1654 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
1655 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
1656 		*colorBuffer,								// VkBuffer           buffer;
1657 		0ull,										// VkDeviceSize       offset;
1658 		VK_WHOLE_SIZE,								// VkDeviceSize       size;
1659 	};
1660 
1661 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1662 						  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1663 
1664 	endCommandBuffer(vk, *cmdBuffer);
1665 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1666 
1667 	// Verify results
1668 	const tcu::TextureFormat			format				= mapVkFormat(COLOR_FORMAT);
1669 	tcu::TextureLevel					textureLevel		(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z());
1670 	const tcu::PixelBufferAccess		expectedImage		(textureLevel);
1671 
1672 	const tcu::Vec4						expectedColor		= tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f);
1673 
1674 	invalidateAlloc(vk, device, *colorBufferAlloc);
1675 
1676 	for (int z = 0; z < expectedImage.getDepth(); ++z)
1677 	{
1678 		for (int y = 0; y < expectedImage.getHeight(); ++y)
1679 		{
1680 			for (int x = 0; x < expectedImage.getWidth(); ++x)
1681 			{
1682 				if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1683 					expectedImage.setPixel(expectedColor, x, y, z);
1684 				else
1685 					expectedImage.setPixel(tcu::Vec4(clearColor[0].float32), x, y, z);
1686 			}
1687 		}
1688 	}
1689 	const tcu::ConstPixelBufferAccess	resultImage		(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z(), colorBufferAlloc->getHostPtr());
1690 
1691 	if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1692 		return tcu::TestStatus::fail("Fail");
1693 
1694 	return tcu::TestStatus::pass("Pass");
1695 }
1696 
testUnusedAtt(Context & context)1697 tcu::TestStatus testUnusedAtt (Context& context)
1698 {
1699 	const DeviceInterface&			vk						= context.getDeviceInterface();
1700 	const VkDevice					device					= context.getDevice();
1701 	const Move<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1702 	const Move<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
1703 
1704 	const VkAttachmentReference		attRef					=
1705 	{
1706 		VK_ATTACHMENT_UNUSED,
1707 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
1708 	};
1709 
1710 	const VkSubpassDescription		subpass					=
1711 	{
1712 		0,
1713 		VK_PIPELINE_BIND_POINT_GRAPHICS,
1714 		0,
1715 		DE_NULL,
1716 		1,
1717 		&attRef,
1718 		DE_NULL,
1719 		DE_NULL,
1720 		0,
1721 		DE_NULL
1722 	};
1723 
1724 	const VkRenderPassCreateInfo	renderPassCreateInfo	=
1725 	{
1726 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1727 		DE_NULL,
1728 		0,
1729 		0,
1730 		DE_NULL,
1731 		1,
1732 		&subpass,
1733 		0,
1734 		DE_NULL
1735 	};
1736 
1737 	const Move<VkRenderPass>		renderPass				= createRenderPass(vk, device, &renderPassCreateInfo, DE_NULL);
1738 
1739 	const VkFramebufferCreateInfo	framebufferCreateInfo	=
1740 	{
1741 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1742 		DE_NULL,
1743 		0,
1744 		*renderPass,
1745 		0,
1746 		DE_NULL,
1747 		32,
1748 		32,
1749 		1
1750 	};
1751 
1752 	const Move<VkFramebuffer>		framebuffer				= createFramebuffer(vk, device, &framebufferCreateInfo, DE_NULL);
1753 
1754 	beginCommandBuffer(vk, *cmdBuffer);
1755 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 32u, 32u));
1756 	endRenderPass(vk, *cmdBuffer);
1757 	endCommandBuffer(vk, *cmdBuffer);
1758 
1759 	return tcu::TestStatus::pass("Pass");
1760 }
1761 
initDifferentAttachmentSizesPrograms(SourceCollections & programCollection,const CaseDef caseDef)1762 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1763 {
1764 	DE_UNREF(caseDef);
1765 
1766 	// Vertex shader
1767 	{
1768 		std::ostringstream src;
1769 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1770 			<< "\n"
1771 			<< "layout(location = 0) in vec4 in_position;\n"
1772 			<< "\n"
1773 			<< "out gl_PerVertex {\n"
1774 			<< "	vec4 gl_Position;\n"
1775 			<< "};\n"
1776 			<< "\n"
1777 			<< "void main(void)\n"
1778 			<< "{\n"
1779 			<< "	gl_Position	= in_position;\n"
1780 			<< "}\n";
1781 
1782 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1783 	}
1784 
1785 	// Fragment shader
1786 	{
1787 		std::ostringstream src;
1788 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1789 			<< "\n"
1790 			<< "layout(location = 0) out vec4 o_color0;\n"
1791 			<< "layout(location = 1) out vec4 o_color1;\n"
1792 			<< "layout(location = 2) out vec4 o_color2;\n"
1793 			<< "\n"
1794 			<< "void main(void)\n"
1795 			<< "{\n"
1796 			<< "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1797 			<< "    o_color1 = vec4(0.5,  1.0, 0.25, 1.0);\n"
1798 			<< "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1799 			<< "}\n";
1800 
1801 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1802 	}
1803 }
1804 
getShortImageViewTypeName(const VkImageViewType imageViewType)1805 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1806 {
1807 	std::string	s	(getImageViewTypeName(imageViewType));
1808 	return de::toLower(s.substr(19));
1809 }
1810 
getSizeString(const CaseDef & caseDef)1811 std::string getSizeString (const CaseDef& caseDef)
1812 {
1813 	std::ostringstream	str;
1814 
1815 										str << caseDef.renderSize.x();
1816 	if (caseDef.renderSize.y() > 1)		str << "x" << caseDef.renderSize.y();
1817 	if (caseDef.renderSize.z() > 1)		str << "x" << caseDef.renderSize.z();
1818 
1819 										str << "_" << caseDef.attachmentSize.x();
1820 
1821 	if (caseDef.attachmentSize.y() > 1)	str << "x" << caseDef.attachmentSize.y();
1822 	if (caseDef.attachmentSize.z() > 1)	str << "x" << caseDef.attachmentSize.z();
1823 	if (caseDef.numLayers > 1)			str << "_" << caseDef.numLayers;
1824 
1825 	return str.str();
1826 }
1827 
getTestCaseString(const CaseDef & caseDef)1828 std::string getTestCaseString (const CaseDef& caseDef)
1829 {
1830 	std::ostringstream str;
1831 
1832 	str << getShortImageViewTypeName (caseDef.imageType).c_str();
1833 	str << "_";
1834 	str << getSizeString(caseDef);
1835 
1836 	if (caseDef.multisample)
1837 		str << "_ms";
1838 
1839 	return str.str();
1840 }
1841 
checkSupport(Context & context,const bool multisample)1842 void checkSupport (Context& context, const bool multisample)
1843 {
1844 	const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
1845 
1846 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1847 
1848 	if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
1849 		throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
1850 
1851 	if (multisample)
1852 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); // MS shader uses gl_SampleID
1853 }
1854 
addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup * group)1855 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group)
1856 {
1857 
1858 	// Add test cases for attachment strictly sizes larger than the framebuffer
1859 	const CaseDef	caseDef[]	=
1860 	{
1861 		// Single-sample test cases
1862 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,		false },
1863 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,		false },
1864 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,		false },
1865 		{ VK_IMAGE_VIEW_TYPE_1D,			IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,		false },
1866 
1867 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(64, 1, 1),	4,		false },
1868 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(48, 1, 1),	4,		false },
1869 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(32, 1, 1),	IVec3(39, 1, 1),	4,		false },
1870 		{ VK_IMAGE_VIEW_TYPE_1D_ARRAY,		IVec3(19, 1, 1),	IVec3(32, 1, 1),	4,		false },
1871 
1872 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		false },
1873 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		false },
1874 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		false },
1875 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		false },
1876 
1877 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		false },
1878 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		false },
1879 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		false },
1880 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		false },
1881 
1882 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	6,		false },
1883 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	6,		false },
1884 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	6,		false },
1885 		{ VK_IMAGE_VIEW_TYPE_CUBE,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	6,		false },
1886 
1887 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	6*2,	false },
1888 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	6*2,	false },
1889 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	6*2,	false },
1890 		{ VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	6*2,	false },
1891 
1892 		// Multi-sample test cases
1893 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		true },
1894 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		true },
1895 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		true },
1896 		{ VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		true },
1897 
1898 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		true },
1899 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		true },
1900 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		true },
1901 		{ VK_IMAGE_VIEW_TYPE_2D_ARRAY,		IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		true },
1902 	};
1903 
1904 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1905 		addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", initColorPrograms, test, caseDef[sizeNdx]);
1906 
1907 	// Add tests for the case where there are no color attachments but the
1908 	// fragment shader writes to an image via imageStore().
1909 	addFunctionCaseWithPrograms(group, "no_attachments", "", checkSupport, initImagePrograms, testNoAtt, false);
1910 	addFunctionCaseWithPrograms(group, "no_attachments_ms", "", checkSupport, initImagePrograms, testNoAtt, true);
1911 
1912 	// Test render pass with attachment set as unused.
1913 	addFunctionCase(group, "unused_attachment", "", testUnusedAtt);
1914 
1915 	const CaseDef	differentAttachmentSizesCaseDef[]	=
1916 	{
1917 		// Single-sample test cases
1918 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,	false },
1919 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,	false },
1920 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,	false },
1921 		{ VK_IMAGE_VIEW_TYPE_1D,	IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,	false },
1922 
1923 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	false },
1924 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	false },
1925 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	false },
1926 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	false },
1927 
1928 		// Multi-sample test cases
1929 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	true },
1930 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	true },
1931 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	true },
1932 		{ VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	true }
1933 	};
1934 
1935 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
1936 		addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", initDifferentAttachmentSizesPrograms, testDifferentAttachmentSizes, differentAttachmentSizesCaseDef[sizeNdx]);
1937 
1938 	const CaseDef resolveInputSameAttachmentCaseDef = { VK_IMAGE_VIEW_TYPE_2D,	IVec3(64, 64, 1),	IVec3(64, 64, 1),	1,	true };
1939 	addFunctionCaseWithPrograms(group, "resolve_input_same_attachment" , "", initInputResolveSameAttachmentPrograms, testInputResolveSameAttachment, resolveInputSameAttachmentCaseDef);
1940 }
1941 
1942 } // anonymous ns
1943 
createFramebufferAttachmentTests(tcu::TestContext & testCtx)1944 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx)
1945 {
1946 	return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions);
1947 }
1948 
1949 } // pipeline
1950 } // vkt
1951