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