• 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 
73 enum MultiAttachmentsTestType
74 {
75 	MULTI_ATTACHMENTS_NONE,
76 	MULTI_ATTACHMENTS_DIFFERENT_SIZES,
77 	MULTI_ATTACHMENTS_NOT_EXPORTED,
78 };
79 
80 struct CaseDef
81 {
82 	PipelineConstructionType	pipelineConstructionType;
83 	VkImageViewType				imageType;
84 	IVec3						renderSize;
85 	IVec3						attachmentSize;
86 	deUint32					numLayers;
87 	bool						multisample;
88 	MultiAttachmentsTestType	multiAttachmentsTestType;
89 };
90 
91 template<typename T>
makeSharedPtr(Move<T> move)92 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
93 {
94 	return SharedPtr<Unique<T> >(new Unique<T>(move));
95 }
96 
97 template<typename T>
sizeInBytes(const vector<T> & vec)98 inline VkDeviceSize sizeInBytes(const vector<T>& vec)
99 {
100 	return vec.size() * sizeof(vec[0]);
101 }
102 
getImageType(const VkImageViewType viewType)103 VkImageType getImageType(const VkImageViewType viewType)
104 {
105 	switch (viewType)
106 	{
107 		case VK_IMAGE_VIEW_TYPE_1D:
108 		case VK_IMAGE_VIEW_TYPE_1D_ARRAY:
109 			return VK_IMAGE_TYPE_1D;
110 
111 		case VK_IMAGE_VIEW_TYPE_2D:
112 		case VK_IMAGE_VIEW_TYPE_2D_ARRAY:
113 		case VK_IMAGE_VIEW_TYPE_CUBE:
114 		case VK_IMAGE_VIEW_TYPE_CUBE_ARRAY:
115 			return VK_IMAGE_TYPE_2D;
116 
117 		case VK_IMAGE_VIEW_TYPE_3D:
118 			return VK_IMAGE_TYPE_3D;
119 
120 		default:
121 			DE_ASSERT(0);
122 			return VK_IMAGE_TYPE_LAST;
123 	}
124 }
125 
126 //! 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)127 Move<VkRenderPass> makeRenderPass (const DeviceInterface& vk,
128 								   const VkDevice		  device,
129 								   const VkFormat		  colorFormat,
130 								   const deUint32		  numLayers,
131 								   const bool			  multisample)
132 {
133 	vector<VkAttachmentDescription>	attachmentDescriptions		(numLayers);
134 	deUint32						attachmentIndex				= 0;
135 	vector<VkAttachmentReference>	colorAttachmentReferences	(numLayers);
136 	vector<VkSubpassDescription>	subpasses;
137 
138 	for (deUint32 i = 0; i < numLayers; i++)
139 	{
140 		VkAttachmentDescription colorAttachmentDescription =
141 		{
142 			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
143 			colorFormat,													// VkFormat						format;
144 			!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits		samples;
145 			VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
146 			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
147 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
148 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
149 			VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				initialLayout;
150 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
151 		};
152 		attachmentDescriptions[attachmentIndex++] = colorAttachmentDescription;
153 	}
154 
155 	// Create a subpass for each attachment (each attachment is a layer of an arrayed image).
156 	for (deUint32 i = 0; i < numLayers; ++i)
157 	{
158 		const VkAttachmentReference attachmentRef =
159 		{
160 			i,											// deUint32			attachment;
161 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
162 		};
163 		colorAttachmentReferences[i] = attachmentRef;
164 
165 		const VkSubpassDescription subpassDescription =
166 		{
167 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
168 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
169 			0u,									// deUint32							inputAttachmentCount;
170 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
171 			1u,									// deUint32							colorAttachmentCount;
172 			&colorAttachmentReferences[i],		// const VkAttachmentReference*		pColorAttachments;
173 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
174 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
175 			0u,									// deUint32							preserveAttachmentCount;
176 			DE_NULL								// const deUint32*					pPreserveAttachments;
177 		};
178 		subpasses.push_back(subpassDescription);
179 	}
180 
181 	const VkRenderPassCreateInfo renderPassInfo =
182 	{
183 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
184 		DE_NULL,									// const void*						pNext;
185 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
186 		numLayers,									// deUint32							attachmentCount;
187 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
188 		static_cast<deUint32>(subpasses.size()),	// deUint32							subpassCount;
189 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
190 		0u,											// deUint32							dependencyCount;
191 		DE_NULL										// const VkSubpassDependency*		pDependencies;
192 	};
193 
194 	return createRenderPass(vk, device, &renderPassInfo);
195 }
196 
preparePipelineWrapper(GraphicsPipelineWrapper & gpw,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)197 void preparePipelineWrapper(GraphicsPipelineWrapper&	gpw,
198 							const VkPipelineLayout		pipelineLayout,
199 							const VkRenderPass			renderPass,
200 							const VkShaderModule		vertexModule,
201 							const VkShaderModule		fragmentModule,
202 							const IVec3					renderSize,
203 							const VkPrimitiveTopology	topology,
204 							const deUint32				subpass,
205 							const deUint32				numAttachments,
206 							const bool					multisample)
207 {
208 	const std::vector<VkViewport>				viewports							{ makeViewport(renderSize) };
209 	const std::vector<VkRect2D>					scissors							{ makeRect2D(renderSize) };
210 
211 	const VkColorComponentFlags					colorComponentsAll					= VK_COLOR_COMPONENT_R_BIT | VK_COLOR_COMPONENT_G_BIT | VK_COLOR_COMPONENT_B_BIT | VK_COLOR_COMPONENT_A_BIT;
212 
213 	const VkPipelineMultisampleStateCreateInfo	pipelineMultisampleStateInfo
214 	{
215 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,		// VkStructureType                          sType;
216 		DE_NULL,														// const void*                              pNext;
217 		(VkPipelineMultisampleStateCreateFlags)0,						// VkPipelineMultisampleStateCreateFlags    flags;
218 		multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT,	// VkSampleCountFlagBits                    rasterizationSamples;
219 		VK_FALSE,														// VkBool32                                 sampleShadingEnable;
220 		1.0f,															// float                                    minSampleShading;
221 		DE_NULL,														// const VkSampleMask*                      pSampleMask;
222 		VK_FALSE,														// VkBool32                                 alphaToCoverageEnable;
223 		VK_FALSE														// VkBool32                                 alphaToOneEnable;
224 	};
225 
226 	const VkPipelineColorBlendAttachmentState	pipelineColorBlendAttachmentState
227 	{
228 		VK_FALSE,				// VkBool32                 blendEnable;
229 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor            srcColorBlendFactor;
230 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor            dstColorBlendFactor;
231 		VK_BLEND_OP_ADD,		// VkBlendOp                colorBlendOp;
232 		VK_BLEND_FACTOR_ONE,	// VkBlendFactor            srcAlphaBlendFactor;
233 		VK_BLEND_FACTOR_ZERO,	// VkBlendFactor            dstAlphaBlendFactor;
234 		VK_BLEND_OP_ADD,		// VkBlendOp                alphaBlendOp;
235 		colorComponentsAll		// VkColorComponentFlags    colorWriteMask;
236 	};
237 
238 	std::vector<VkPipelineColorBlendAttachmentState> colorBlendAttachmentStates;
239 	for (deUint32 attachmentIdx = 0; attachmentIdx < numAttachments; attachmentIdx++)
240 		colorBlendAttachmentStates.push_back(pipelineColorBlendAttachmentState);
241 
242 	const VkPipelineColorBlendStateCreateInfo	pipelineColorBlendStateInfo
243 	{
244 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,		// VkStructureType                              sType;
245 		DE_NULL,														// const void*                                  pNext;
246 		(VkPipelineColorBlendStateCreateFlags)0,						// VkPipelineColorBlendStateCreateFlags         flags;
247 		VK_FALSE,														// VkBool32                                     logicOpEnable;
248 		VK_LOGIC_OP_COPY,												// VkLogicOp                                    logicOp;
249 		numAttachments,													// deUint32                                     attachmentCount;
250 		numAttachments == 0 ? DE_NULL : &colorBlendAttachmentStates[0],	// const VkPipelineColorBlendAttachmentState*   pAttachments;
251 		{ 0.0f, 0.0f, 0.0f, 0.0f }										// float                                        blendConstants[4];
252 	};
253 
254 	gpw.setDefaultTopology(topology)
255 	   .setDefaultRasterizationState()
256 	   .setDefaultDepthStencilState()
257 	   .setupVertexInputState()
258 	   .setupPreRasterizationShaderState(viewports,
259 										 scissors,
260 										 pipelineLayout,
261 										 renderPass,
262 										 subpass,
263 										 vertexModule)
264 	   .setupFragmentShaderState(pipelineLayout, renderPass, subpass, fragmentModule, DE_NULL, &pipelineMultisampleStateInfo)
265 	   .setupFragmentOutputState(renderPass, subpass, &pipelineColorBlendStateInfo, &pipelineMultisampleStateInfo)
266 	   .setMonolithicPipelineLayout(pipelineLayout)
267 	   .buildPipeline();
268 }
269 
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)270 Move<VkImage> makeImage (const DeviceInterface&		vk,
271 						 const VkDevice				device,
272 						 const VkImageCreateFlags	flags,
273 						 const VkImageType			imageType,
274 						 const VkFormat				format,
275 						 const IVec3&				size,
276 						 const deUint32				numLayers,
277 						 const VkImageUsageFlags	usage,
278 						 const bool					multisample)
279 {
280 	const VkImageCreateInfo imageParams =
281 	{
282 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,							// VkStructureType			sType;
283 		DE_NULL,														// const void*				pNext;
284 		flags,															// VkImageCreateFlags		flags;
285 		imageType,														// VkImageType				imageType;
286 		format,															// VkFormat					format;
287 		makeExtent3D(size),												// VkExtent3D				extent;
288 		1u,																// deUint32					mipLevels;
289 		numLayers,														// deUint32					arrayLayers;
290 		multisample ? VK_SAMPLE_COUNT_4_BIT : VK_SAMPLE_COUNT_1_BIT,	// VkSampleCountFlagBits	samples;
291 		VK_IMAGE_TILING_OPTIMAL,										// VkImageTiling			tiling;
292 		usage,															// VkImageUsageFlags		usage;
293 		VK_SHARING_MODE_EXCLUSIVE,										// VkSharingMode			sharingMode;
294 		0u,																// deUint32					queueFamilyIndexCount;
295 		DE_NULL,														// const deUint32*			pQueueFamilyIndices;
296 		VK_IMAGE_LAYOUT_UNDEFINED,										// VkImageLayout			initialLayout;
297 	};
298 
299 	return createImage(vk, device, &imageParams);
300 }
301 
genFullQuadVertices(const int subpassCount)302 vector<tcu::Vec4> genFullQuadVertices (const int subpassCount)
303 {
304 	vector<tcu::Vec4>	vectorData;
305 	for (int subpassNdx = 0; subpassNdx < subpassCount; ++subpassNdx)
306 	{
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 		vectorData.push_back(Vec4(1.0f, -1.0f, 0.0f, 1.0f));
310 		vectorData.push_back(Vec4(1.0f,  1.0f, 0.0f, 1.0f));
311 	}
312 	return vectorData;
313 }
314 
initColorPrograms(SourceCollections & programCollection,const CaseDef)315 void initColorPrograms (SourceCollections& programCollection, const 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<GraphicsPipelineWrapper>	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 	pipeline.reserve(caseDef.numLayers);
458 	for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
459 	{
460 		colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, ! caseDef.multisample ? *colorImage : *msColorImage,
461 			imageViewType, COLOR_FORMAT, makeColorSubresourceRange(layerNdx, 1))));
462 		attachmentHandles.push_back(**colorAttachments.back());
463 
464 		pipeline.emplace_back(vk, device, caseDef.pipelineConstructionType);
465 		preparePipelineWrapper(pipeline.back(), *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
466 							   caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, layerNdx, 1u, caseDef.multisample);
467 	}
468 
469 	// create framebuffer
470 	framebuffer = makeFramebuffer(vk, device, *renderPass, caseDef.numLayers, &attachmentHandles[0],
471 		static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
472 
473 	// record command buffer
474 	beginCommandBuffer(vk, *cmdBuffer);
475 	{
476 		// Clear the entire image attachment to black
477 		{
478 			const VkImageMemoryBarrier	imageLayoutBarriers[]	=
479 			{
480 				{
481 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
482 					DE_NULL,											// const void*				pNext;
483 					0u,													// VkAccessFlags			srcAccessMask;
484 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			dstAccessMask;
485 					VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			oldLayout;
486 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			newLayout;
487 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
488 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
489 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
490 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
491 				},
492 			};
493 
494 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
495 				0u, DE_NULL, 0u, DE_NULL, 1u, imageLayoutBarriers);
496 
497 			const VkImageSubresourceRange	ranges		= makeColorSubresourceRange(0, caseDef.numLayers);
498 			const VkClearColorValue			clearColor	=
499 			{
500 				{0.0f, 0.0f, 0.0f, 1.0f}
501 			};
502 			vk.cmdClearColorImage(*cmdBuffer, caseDef.multisample ? *msColorImage : *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor, 1u, &ranges);
503 
504 			const VkImageMemoryBarrier	imageClearBarriers[]	=
505 			{
506 				{
507 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
508 					DE_NULL,											// const void*				pNext;
509 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
510 					VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,				// VkAccessFlags			dstAccessMask;
511 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
512 					VK_IMAGE_LAYOUT_GENERAL,							// VkImageLayout			newLayout;
513 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
514 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					destQueueFamilyIndex;
515 					caseDef.multisample ? *msColorImage : *colorImage,	// VkImage					image;
516 					makeColorSubresourceRange(0, caseDef.numLayers)		// VkImageSubresourceRange	subresourceRange;
517 				},
518 			};
519 
520 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
521 				0u, DE_NULL, 0u, DE_NULL, 1u, imageClearBarriers);
522 		}
523 
524 		// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
525 		{
526 			const VkDeviceSize			vertexBufferOffset	= 0ull;
527 
528 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
529 			{
530 				vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
531 				for (deUint32 layerNdx = 0; layerNdx < caseDef.numLayers; ++layerNdx)
532 				{
533 					if (layerNdx != 0)
534 						vk.cmdNextSubpass(*cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
535 
536 					vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline[layerNdx].getPipeline());
537 					vk.cmdDraw(*cmdBuffer, 4u, 1u, layerNdx*4u, 0u);
538 				}
539 			}
540 			endRenderPass(vk, *cmdBuffer);
541 		}
542 
543 		// If we are using a multi-sampled render target (msColorImage), resolve it now (to colorImage)
544 		if (caseDef.multisample)
545 		{
546 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
547 			const VkImageMemoryBarrier	imageBarriers[]	=
548 			{
549 				{
550 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
551 					DE_NULL,										// const void*				pNext;
552 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask;
553 					VK_ACCESS_TRANSFER_READ_BIT,					// VkAccessFlags			dstAccessMask;
554 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,		// VkImageLayout			oldLayout;
555 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
556 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
557 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
558 					*msColorImage,									// VkImage					image;
559 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
560 				},
561 				{
562 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
563 					DE_NULL,										// const void*				pNext;
564 					(VkAccessFlags)0,								// VkAccessFlags			srcAccessMask;
565 					VK_ACCESS_TRANSFER_WRITE_BIT,					// VkAccessFlags			dstAccessMask;
566 					VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			oldLayout;
567 					VK_IMAGE_LAYOUT_GENERAL,						// VkImageLayout			newLayout;
568 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
569 					VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
570 					*colorImage,									// VkImage					image;
571 					makeColorSubresourceRange(0, caseDef.numLayers)	// VkImageSubresourceRange	subresourceRange;
572 				}
573 			};
574 
575 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
576 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
577 
578 			const VkImageResolve	region	=
579 			{
580 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    srcSubresource;
581 				makeOffset3D(0, 0, 0),															// VkOffset3D                  srcOffset;
582 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, caseDef.numLayers),	// VkImageSubresourceLayers    dstSubresource;
583 				makeOffset3D(0, 0, 0),															// VkOffset3D                  dstOffset;
584 				makeExtent3D(caseDef.attachmentSize)											// VkExtent3D                  extent;
585 			};
586 
587 			vk.cmdResolveImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_GENERAL, *colorImage, VK_IMAGE_LAYOUT_GENERAL, 1, &region);
588 		}
589 
590 		// copy colorImage to host visible colorBuffer
591 		{
592 			const VkImageMemoryBarrier	imageBarriers[]		=
593 			{
594 				{
595 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
596 					DE_NULL,																					// const void*				pNext;
597 					(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
598 					VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
599 					caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
600 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
601 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
602 					VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
603 					*colorImage,																				// VkImage					image;
604 					makeColorSubresourceRange(0, caseDef.numLayers)												// VkImageSubresourceRange	subresourceRange;
605 				}
606 			};
607 
608 			vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
609 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
610 
611 			const VkBufferImageCopy		region				=
612 			{
613 				0ull,																				// VkDeviceSize                bufferOffset;
614 				0u,																					// uint32_t                    bufferRowLength;
615 				0u,																					// uint32_t                    bufferImageHeight;
616 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, caseDef.numLayers),	// VkImageSubresourceLayers    imageSubresource;
617 				makeOffset3D(0, 0, 0),																// VkOffset3D                  imageOffset;
618 				makeExtent3D(caseDef.attachmentSize),												// VkExtent3D                  imageExtent;
619 			};
620 
621 			vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
622 
623 			const VkBufferMemoryBarrier	bufferBarriers[]	=
624 			{
625 				{
626 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
627 					DE_NULL,									// const void*        pNext;
628 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
629 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
630 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
631 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
632 					*colorBuffer,								// VkBuffer           buffer;
633 					0ull,										// VkDeviceSize       offset;
634 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
635 				},
636 			};
637 
638 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
639 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
640 		}
641 	} // beginCommandBuffer
642 
643 	endCommandBuffer(vk, *cmdBuffer);
644 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
645 
646 	// Verify results
647 	{
648 		invalidateAlloc(vk, device, *colorBufferAlloc);
649 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
650 		const int							depth			= deMax32(caseDef.attachmentSize.z(), caseDef.numLayers);
651 		tcu::TextureLevel					textureLevel	(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth);
652 		const tcu::PixelBufferAccess		expectedImage	= getExpectedData(textureLevel, caseDef);
653 		const tcu::ConstPixelBufferAccess	resultImage		(format, caseDef.attachmentSize.x(), caseDef.attachmentSize.y(), depth, colorBufferAlloc->getHostPtr());
654 
655 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
656 			return tcu::TestStatus::fail("Fail");
657 	}
658 
659 	return tcu::TestStatus::pass("Pass");
660 }
661 
662 struct NoAttCaseDef
663 {
664 	PipelineConstructionType	pipelineConstructionType;
665 	bool						multisample;
666 };
667 
initImagePrograms(SourceCollections & programCollection,const NoAttCaseDef caseDef)668 void initImagePrograms (SourceCollections& programCollection, const NoAttCaseDef caseDef)
669 {
670 	// Vertex shader
671 	{
672 		std::ostringstream src;
673 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
674 			<< "\n"
675 			<< "layout(location = 0) in vec4 in_position;\n"
676 			<< "\n"
677 			<< "out gl_PerVertex {\n"
678 			<< "	vec4 gl_Position;\n"
679 			<< "	float gl_PointSize;\n"
680 			<< "};\n"
681 			<< "\n"
682 			<< "void main(void)\n"
683 			<< "{\n"
684 			<< "	gl_Position	= in_position;\n"
685 			<< "	gl_PointSize = 1.0f;\n"
686 			<< "}\n";
687 
688 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
689 	}
690 
691 	// Fragment shader
692 	{
693 		std::ostringstream src;
694 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
695 			<< "\n"
696 			<< "layout(binding = 0, rgba8) writeonly uniform image2D image;\n"
697 			<< "\n"
698 			<< "void main(void)\n"
699 			<< "{\n";
700 			if (!caseDef.multisample)
701 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, 0), vec4(1.0, 0.5, 0.25, 1.0));\n";
702 			else
703 				src << "    imageStore(image, ivec2(gl_PrimitiveID % 4, gl_SampleID % 4), vec4(1.0, 0.5, 0.25, 1.0));\n";
704 			src << "}\n";
705 
706 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
707 	}
708 }
709 
710 //! Make a render pass with no attachments
makeRenderPassNoAtt(const DeviceInterface & vk,const VkDevice device)711 Move<VkRenderPass> makeRenderPassNoAtt (const DeviceInterface& vk, const VkDevice device)
712 {
713 	// Create a single subpass with no attachment references
714 	vector<VkSubpassDescription>	subpasses;
715 
716 	const VkSubpassDescription		subpassDescription	=
717 	{
718 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
719 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
720 		0u,									// deUint32							inputAttachmentCount;
721 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
722 		0u,									// deUint32							colorAttachmentCount;
723 		DE_NULL,							// const VkAttachmentReference*		pColorAttachments;
724 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
725 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
726 		0u,									// deUint32							preserveAttachmentCount;
727 		DE_NULL								// const deUint32*					pPreserveAttachments;
728 	};
729 	subpasses.push_back(subpassDescription);
730 
731 	const VkRenderPassCreateInfo	renderPassInfo	=
732 	{
733 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
734 		DE_NULL,									// const void*						pNext;
735 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
736 		0,											// deUint32							attachmentCount;
737 		DE_NULL,									// const VkAttachmentDescription*	pAttachments;
738 		1,											// deUint32							subpassCount;
739 		&subpasses[0],								// const VkSubpassDescription*		pSubpasses;
740 		0u,											// deUint32							dependencyCount;
741 		DE_NULL										// const VkSubpassDependency*		pDependencies;
742 	};
743 
744 	return createRenderPass(vk, device, &renderPassInfo);
745 }
746 
getExpectedDataNoAtt(tcu::TextureLevel & textureLevel)747 tcu::PixelBufferAccess getExpectedDataNoAtt (tcu::TextureLevel& textureLevel)
748 {
749 	const tcu::PixelBufferAccess	expectedImage	(textureLevel);
750 	for (int z = 0; z < expectedImage.getDepth(); ++z)
751 	{
752 		for (int y = 0; y < expectedImage.getHeight(); ++y)
753 		{
754 			for (int x = 0; x < expectedImage.getWidth(); ++x)
755 			{
756 				expectedImage.setPixel(tcu::Vec4(1.0, 0.5, 0.25, 1.0), x, y, z);
757 			}
758 		}
759 	}
760 	return expectedImage;
761 }
762 
genPointVertices(void)763 vector<tcu::Vec4> genPointVertices (void)
764 {
765 	vector<tcu::Vec4>	vectorData;
766 	vectorData.push_back(Vec4(-0.25f, -0.25f, 0, 1));
767 	vectorData.push_back(Vec4(-0.25f,  0.25f, 0, 1));
768 	vectorData.push_back(Vec4(0.25f, -0.25f, 0, 1));
769 	vectorData.push_back(Vec4(0.25f,  0.25f, 0, 1));
770 	return vectorData;
771 }
772 
773 // Tests rendering to a framebuffer without color attachments, checking that
774 // the fragment shader is run even in the absence of color output. In this case
775 // we render 4 point primitives and we make the fragment shader write to a
776 // different pixel of an image via an imageStore command. For the single-sampled
777 // configuration we use a 4x1 image to record the output and for the
778 // multi-sampled case we use a 4x4 image to record all 16 samples produced by
779 // 4-sample multi-sampling
testNoAtt(Context & context,const NoAttCaseDef caseDef)780 tcu::TestStatus testNoAtt (Context& context, const NoAttCaseDef caseDef)
781 {
782 	const DeviceInterface&				vk						= context.getDeviceInterface();
783 	const VkDevice						device					= context.getDevice();
784 	const VkQueue						queue					= context.getUniversalQueue();
785 	const deUint32						queueFamilyIndex		= context.getUniversalQueueFamilyIndex();
786 	Allocator&							allocator				= context.getDefaultAllocator();
787 	const IVec3							renderSize				(32, 32, 1);
788 
789 	Move<VkBuffer>						vertexBuffer;
790 	MovePtr<Allocation>					vertexBufferAlloc;
791 
792 	const Unique<VkShaderModule>		vertexModule			(createShaderModule (vk, device, context.getBinaryCollection().get("vert"), 0u));
793 	const Unique<VkShaderModule>		fragmentModule			(createShaderModule (vk, device, context.getBinaryCollection().get("frag"), 0u));
794 
795 	// Create image where we will record the writes. For single-sampled cases this is a 4x1 image
796 	// and for multi-sampled cases this is a 4x<num_samples> image.
797 	const deUint8						numSamples				= caseDef.multisample ? 4 : 1;
798 	const deUint8						imageWidth				= 4;
799 	const deUint8						imageHeight				= numSamples;
800 	const deUint8						imageDepth				= 1;
801 	const deUint8						imageLayers				= 1;
802 	const IVec3							imageDim				= IVec3(imageWidth, imageHeight, imageDepth);
803 	const VkImageUsageFlags				imageUsage				= VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_STORAGE_BIT;
804 	const Move<VkImage>					image					= makeImage(vk, device, VkImageViewCreateFlags(0), VK_IMAGE_TYPE_2D, COLOR_FORMAT, imageDim, imageLayers, imageUsage, false);
805 	const VkImageSubresourceRange		imageSubresourceRange	= makeColorSubresourceRange(0u, imageLayers);
806 	const MovePtr<Allocation>			imageAlloc				= bindImage(vk, device, allocator, *image, MemoryRequirement::Any);
807 	const Move<VkImageView>				imageView				= makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, COLOR_FORMAT, imageSubresourceRange);
808 
809 	// Create a buffer where we will copy the image for verification
810 	const VkDeviceSize					colorBufferSize		= imageWidth * imageHeight * imageDepth * numSamples * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
811 	const Unique<VkBuffer>				colorBuffer			(makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
812 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
813 
814 	// Create pipeline descriptor set for the image
815 	const Move<VkDescriptorSetLayout>	descriptorSetLayout		= DescriptorSetLayoutBuilder()
816 		.addSingleBinding(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, VK_SHADER_STAGE_FRAGMENT_BIT)
817 		.build(vk, device);
818 
819 	const Move<VkDescriptorPool>		descriptorPool			= DescriptorPoolBuilder()
820 		.addType(VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, 1)
821 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
822 
823 	const Move<VkDescriptorSet>			descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
824 	const VkDescriptorImageInfo			descriptorImageInfo		= makeDescriptorImageInfo(DE_NULL, *imageView, VK_IMAGE_LAYOUT_GENERAL);
825 	DescriptorSetUpdateBuilder()
826 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_STORAGE_IMAGE, &descriptorImageInfo)
827 		.update(vk, device);
828 
829 	const Unique<VkPipelineLayout>		pipelineLayout			(makePipelineLayout (vk, device, *descriptorSetLayout));
830 	GraphicsPipelineWrapper				pipeline				(vk, device, caseDef.pipelineConstructionType);
831 	const Unique<VkRenderPass>			renderPass				(makeRenderPassNoAtt (vk, device));
832 	Move<VkFramebuffer>					framebuffer;
833 
834 	const Unique<VkCommandPool>			cmdPool					(createCommandPool (vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
835 	const Unique<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer (vk, device, *cmdPool));
836 
837 	// create vertexBuffer
838 	{
839 		const vector<tcu::Vec4>	vertices			= genPointVertices();
840 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
841 
842 		vertexBuffer		= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
843 		vertexBufferAlloc	= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
844 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
845 		flushAlloc(vk, device, *vertexBufferAlloc);
846 	}
847 
848 	// Create pipeline
849 	preparePipelineWrapper(pipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule,
850 						   renderSize, VK_PRIMITIVE_TOPOLOGY_POINT_LIST, 0, 0u, caseDef.multisample);
851 	framebuffer = makeFramebuffer(vk, device, *renderPass, 0, DE_NULL, renderSize.x(), renderSize.y());
852 
853 	// Record command buffer
854 	beginCommandBuffer(vk, *cmdBuffer);
855 	{
856 		// shader image layout transition undefined -> general
857 		{
858 			const VkImageMemoryBarrier setImageLayoutBarrier = makeImageMemoryBarrier(
859 				0u, VK_ACCESS_SHADER_WRITE_BIT,
860 				VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL,
861 				*image, imageSubresourceRange);
862 
863 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0,
864 				0, DE_NULL, 0, DE_NULL, 1, &setImageLayoutBarrier);
865 		}
866 
867 		// Render pass
868 		{
869 			const VkDeviceSize vertexBufferOffset = 0ull;
870 
871 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, renderSize.x(), renderSize.y()));
872 
873 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
874 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
875 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
876 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
877 
878 			endRenderPass(vk, *cmdBuffer);
879 		}
880 
881 		// copy image to host visible colorBuffer
882 		{
883 			const VkImageMemoryBarrier	imageBarriers[]		=
884 			{
885 				{
886 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
887 					DE_NULL,									// const void*				pNext;
888 					VK_ACCESS_SHADER_WRITE_BIT,					// VkAccessFlags			srcAccessMask;
889 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
890 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			oldLayout;
891 					VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,		// VkImageLayout			newLayout;
892 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
893 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
894 					*image,										// VkImage					image;
895 					makeColorSubresourceRange(0, 1)				// VkImageSubresourceRange	subresourceRange;
896 				}
897 			};
898 
899 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
900 				0u, DE_NULL, 0u, DE_NULL, 1u, imageBarriers);
901 
902 			const VkBufferImageCopy		region				=
903 			{
904 				0ull,																// VkDeviceSize                bufferOffset;
905 				0u,																	// uint32_t                    bufferRowLength;
906 				0u,																	// uint32_t                    bufferImageHeight;
907 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1),	// VkImageSubresourceLayers    imageSubresource;
908 				makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
909 				makeExtent3D(IVec3(imageWidth, imageHeight, imageDepth)),			// VkExtent3D                  imageExtent;
910 			};
911 
912 			vk.cmdCopyImageToBuffer(*cmdBuffer, *image, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
913 
914 			const VkBufferMemoryBarrier	bufferBarriers[]	=
915 			{
916 				{
917 					VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
918 					DE_NULL,									// const void*        pNext;
919 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
920 					VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
921 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
922 					VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
923 					*colorBuffer,								// VkBuffer           buffer;
924 					0ull,										// VkDeviceSize       offset;
925 					VK_WHOLE_SIZE,								// VkDeviceSize       size;
926 				},
927 			};
928 
929 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
930 				0u, DE_NULL, DE_LENGTH_OF_ARRAY(bufferBarriers), bufferBarriers, 0u, DE_NULL);
931 		}
932 	} // beginCommandBuffer
933 
934 	endCommandBuffer(vk, *cmdBuffer);
935 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
936 
937 	// Verify results
938 	{
939 		invalidateAlloc(vk, device, *colorBufferAlloc);
940 		const tcu::TextureFormat			format			= mapVkFormat(COLOR_FORMAT);
941 		tcu::TextureLevel					textureLevel	(format, imageWidth, imageHeight, imageDepth);
942 		const tcu::PixelBufferAccess		expectedImage	= getExpectedDataNoAtt(textureLevel);
943 		const tcu::ConstPixelBufferAccess	resultImage		(format, imageWidth, imageHeight, imageDepth, colorBufferAlloc->getHostPtr());
944 
945 		if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
946 			return tcu::TestStatus::fail("Fail");
947 	}
948 
949 	return tcu::TestStatus::pass("Pass");
950 }
951 
952 //! Make a render pass with three color attachments
makeRenderPassMultiAttachments(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat,deUint32 numAttachments,const bool multisample)953 Move<VkRenderPass> makeRenderPassMultiAttachments	(const DeviceInterface&	vk,
954 													 const VkDevice			device,
955 													 const VkFormat			colorFormat,
956 													 deUint32				numAttachments,
957 													 const bool				multisample)
958 {
959 	vector<VkAttachmentDescription>	attachmentDescriptions		(numAttachments);
960 	vector<VkAttachmentReference>	colorAttachmentReferences	(numAttachments);
961 
962 	for (deUint32 i = 0; i < numAttachments; i++)
963 	{
964 		VkAttachmentDescription colorAttachmentDescription =
965 		{
966 			(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
967 			colorFormat,													// VkFormat						format;
968 			!multisample ? VK_SAMPLE_COUNT_1_BIT : VK_SAMPLE_COUNT_4_BIT,	// VkSampleCountFlagBits		samples;
969 			VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
970 			VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
971 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
972 			VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
973 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				initialLayout;
974 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
975 		};
976 		attachmentDescriptions[i] = colorAttachmentDescription;
977 
978 		const VkAttachmentReference attachmentRef =
979 		{
980 			i,											// deUint32			attachment;
981 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
982 		};
983 		colorAttachmentReferences[i] = attachmentRef;
984 	}
985 
986 	const VkSubpassDescription subpassDescription =
987 	{
988 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags;
989 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint;
990 		0u,									// deUint32							inputAttachmentCount;
991 		DE_NULL,							// const VkAttachmentReference*		pInputAttachments;
992 		numAttachments,						// deUint32							colorAttachmentCount;
993 		&colorAttachmentReferences[0],		// const VkAttachmentReference*		pColorAttachments;
994 		DE_NULL,							// const VkAttachmentReference*		pResolveAttachments;
995 		DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment;
996 		0u,									// deUint32							preserveAttachmentCount;
997 		DE_NULL								// const deUint32*					pPreserveAttachments;
998 	};
999 
1000 	const VkRenderPassCreateInfo renderPassInfo =
1001 	{
1002 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
1003 		DE_NULL,									// const void*						pNext;
1004 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
1005 		numAttachments,								// deUint32							attachmentCount;
1006 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
1007 		1u,											// deUint32							subpassCount;
1008 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
1009 		0u,											// deUint32							dependencyCount;
1010 		DE_NULL										// const VkSubpassDependency*		pDependencies;
1011 	};
1012 
1013 	return createRenderPass(vk, device, &renderPassInfo);
1014 }
1015 
1016 // Tests framebuffer with attachments of different sizes
testMultiAttachments(Context & context,const CaseDef caseDef)1017 tcu::TestStatus testMultiAttachments (Context& context, const CaseDef caseDef)
1018 {
1019 	const DeviceInterface&			vk					= context.getDeviceInterface();
1020 	const VkDevice					device				= context.getDevice();
1021 	const VkQueue					queue				= context.getUniversalQueue();
1022 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1023 	Allocator&						allocator			= context.getDefaultAllocator();
1024 	const deUint32					numRenderTargets	= 3;
1025 	const deBool					differentSizeTest	= caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_DIFFERENT_SIZES;
1026 	const deBool					notExportTest		= caseDef.multiAttachmentsTestType == MULTI_ATTACHMENTS_NOT_EXPORTED;
1027 
1028 	// Color images for rendering in single-sample tests or resolve targets for multi-sample tests
1029 	Move<VkImage>					colorImages[numRenderTargets];
1030 	MovePtr<Allocation>				colorImageAllocs[numRenderTargets];
1031 
1032 	// For multisampled tests, these are the rendering targets
1033 	Move<VkImage>					msColorImages[numRenderTargets];
1034 	MovePtr<Allocation>				msColorImageAllocs[numRenderTargets];
1035 
1036 	Move<VkBuffer>					colorBuffers[numRenderTargets];
1037 	MovePtr<Allocation>				colorBufferAllocs[numRenderTargets];
1038 
1039 	// Vary attachment sizes by adding an offset to the base size.
1040 	const IVec3						attachmentSizes[]	=
1041 	{
1042 		caseDef.attachmentSize,
1043 		caseDef.attachmentSize + IVec3(10, caseDef.attachmentSize.y() == 1 ? 0 : 15, 0),
1044 		caseDef.attachmentSize + IVec3(27, caseDef.attachmentSize.y() == 1 ? 0 : 4, 0)
1045 	};
1046 
1047 	// Use unique clear color for each render target to verify no leaking happens between render target clears.
1048 	const VkClearColorValue			clearColors[]		=
1049 	{
1050 		{{1.0f, 0.0f, 0.0f, 1.0f}},
1051 		{{0.0f, 1.0f, 0.0f, 1.0f}},
1052 		{{0.0f, 0.0f, 1.0f, 1.0f}}
1053 	};
1054 
1055 	Move<VkBuffer>					vertexBuffer;
1056 	MovePtr<Allocation>				vertexBufferAlloc;
1057 
1058 	vector<SharedPtrVkImageView>	colorAttachments;
1059 	vector<VkImageView>				attachmentHandles;
1060 
1061 	const Unique<VkPipelineLayout>	pipelineLayout		(makePipelineLayout(vk, device));
1062 	GraphicsPipelineWrapper			pipeline			(vk, device, caseDef.pipelineConstructionType);
1063 	const Unique<VkRenderPass>		renderPass			(makeRenderPassMultiAttachments(vk, device, COLOR_FORMAT, numRenderTargets, caseDef.multisample));
1064 	Move<VkFramebuffer>				framebuffer;
1065 
1066 	const Unique<VkShaderModule>	vertexModule		(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1067 	const Unique<VkShaderModule>	fragmentModule		(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1068 
1069 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1070 	const Unique<VkCommandBuffer>	cmdBuffer			(makeCommandBuffer(vk, device, *cmdPool));
1071 
1072 	const VkImageViewType			imageViewType		= caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE || caseDef.imageType == VK_IMAGE_VIEW_TYPE_CUBE_ARRAY
1073 		? VK_IMAGE_VIEW_TYPE_2D : caseDef.imageType;
1074 
1075 	const VkImageSubresourceRange	range				= makeColorSubresourceRange(0, 1);
1076 
1077 	// create color buffers
1078 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1079 	{
1080 		const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1081 
1082 		// Host memory buffer where we will copy the rendered image for verification
1083 		const deUint32					att_size_x			= attachmentSize.x();
1084 		const deUint32					att_size_y			= attachmentSize.y();
1085 		const deUint32					att_size_z			= attachmentSize.z();
1086 		const VkDeviceSize				colorBufferSize		= att_size_x * att_size_y * att_size_z * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1087 		colorBuffers[renderTargetIdx]						= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1088 		colorBufferAllocs[renderTargetIdx]					= bindBuffer(vk, device, allocator, *colorBuffers[renderTargetIdx], MemoryRequirement::HostVisible);
1089 	}
1090 
1091 	// create vertexBuffer
1092 	{
1093 		const vector<tcu::Vec4>	vertices			= genFullQuadVertices(1);
1094 		const VkDeviceSize		vertexBufferSize	= sizeInBytes(vertices);
1095 
1096 		vertexBuffer								= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1097 		vertexBufferAlloc							= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1098 
1099 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1100 		flushAlloc(vk, device, *vertexBufferAlloc);
1101 	}
1102 
1103 	// create colorImages (and msColorImages) using the configured attachmentsize
1104 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1105 	{
1106 		const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
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 			attachmentSize, 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, attachmentSize, 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 	preparePipelineWrapper(pipeline, *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_COLOR_ATTACHMENT_OPTIMAL,												// 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.getPipeline());
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 			const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1201 
1202 			// Transition msColorImage (from layout COLOR_ATTACHMENT_OPTIMAL) and colorImage (from layout UNDEFINED) to layout GENERAL before resolving
1203 			const VkImageMemoryBarrier	imageBarriers[]	=
1204 			{
1205 				{
1206 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
1207 					DE_NULL,									// const void*				pNext;
1208 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// VkAccessFlags			srcAccessMask;
1209 					VK_ACCESS_TRANSFER_READ_BIT,				// VkAccessFlags			dstAccessMask;
1210 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
1211 					VK_IMAGE_LAYOUT_GENERAL,					// VkImageLayout			newLayout;
1212 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
1213 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					destQueueFamilyIndex;
1214 					*msColorImages[renderTargetIdx],			// VkImage					image;
1215 					range										// VkImageSubresourceRange	subresourceRange;
1216 				},
1217 				{
1218 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
1219 					DE_NULL,								// const void*				pNext;
1220 					(VkAccessFlags)0,						// VkAccessFlags			srcAccessMask;
1221 					VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
1222 					VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
1223 					VK_IMAGE_LAYOUT_GENERAL,				// VkImageLayout			newLayout;
1224 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
1225 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					destQueueFamilyIndex;
1226 					*colorImages[renderTargetIdx],			// VkImage					image;
1227 					range									// VkImageSubresourceRange	subresourceRange;
1228 				}
1229 			};
1230 
1231 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1232 				0u, DE_NULL, 0u, DE_NULL, 2u, imageBarriers);
1233 
1234 			const VkImageResolve	region	=
1235 			{
1236 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    srcSubresource;
1237 				makeOffset3D(0, 0, 0),											// VkOffset3D                  srcOffset;
1238 				makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0, 0, 1),	// VkImageSubresourceLayers    dstSubresource;
1239 				makeOffset3D(0, 0, 0),											// VkOffset3D                  dstOffset;
1240 				makeExtent3D(attachmentSize)									// VkExtent3D                  extent;
1241 			};
1242 
1243 			vk.cmdResolveImage(*cmdBuffer, *msColorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_GENERAL, 1, &region);
1244 		}
1245 	}
1246 
1247 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1248 	{
1249 		const IVec3 attachmentSize = differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1250 
1251 		// copy colorImage to host visible colorBuffer
1252 		const VkImageMemoryBarrier	imageBarrier		=
1253 		{
1254 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
1255 			DE_NULL,																					// const void*				pNext;
1256 			(vk::VkAccessFlags)(caseDef.multisample ? VK_ACCESS_TRANSFER_WRITE_BIT : VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT),
1257 			VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1258 			caseDef.multisample ? VK_IMAGE_LAYOUT_GENERAL : VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			oldLayout;
1259 			VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
1260 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
1261 			VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
1262 			*colorImages[renderTargetIdx],																// VkImage					image;
1263 			range																						// VkImageSubresourceRange	subresourceRange;
1264 		};
1265 
1266 		vk.cmdPipelineBarrier(*cmdBuffer, caseDef.multisample ? VK_PIPELINE_STAGE_TRANSFER_BIT : VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1267 			0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1268 
1269 		const VkBufferImageCopy		region				=
1270 		{
1271 			0ull,																// VkDeviceSize                bufferOffset;
1272 			0u,																	// uint32_t                    bufferRowLength;
1273 			0u,																	// uint32_t                    bufferImageHeight;
1274 			makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
1275 			makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1276 			makeExtent3D(attachmentSize),										// VkExtent3D                  imageExtent;
1277 		};
1278 
1279 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImages[renderTargetIdx], VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffers[renderTargetIdx], 1u, &region);
1280 
1281 		const VkBufferMemoryBarrier	bufferBarrier		=
1282 		{
1283 			VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1284 			DE_NULL,									// const void*        pNext;
1285 			VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1286 			VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1287 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
1288 			VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
1289 			*colorBuffers[renderTargetIdx],				// VkBuffer           buffer;
1290 			0ull,										// VkDeviceSize       offset;
1291 			VK_WHOLE_SIZE,								// VkDeviceSize       size;
1292 		};
1293 
1294 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1295 			0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1296 	}
1297 
1298 	endCommandBuffer(vk, *cmdBuffer);
1299 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1300 
1301 	// Verify results
1302 	const deUint32						skippedRenderTarget	= notExportTest ? 1 : numRenderTargets;
1303 	const tcu::Vec4						expectedColors[]	=
1304 	{
1305 		tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f),
1306 		tcu::Vec4(0.5f, 1.0f, 0.25f, 1.0f),
1307 		tcu::Vec4(0.25f, 0.5f, 1.0, 1.0f)
1308 	};
1309 
1310 	for (deUint32 renderTargetIdx = 0; renderTargetIdx < numRenderTargets; renderTargetIdx++)
1311 	{
1312 		const tcu::TextureFormat			format				= mapVkFormat(COLOR_FORMAT);
1313 		const IVec3							size				= differentSizeTest ? attachmentSizes[renderTargetIdx] : caseDef.attachmentSize;
1314 		tcu::TextureLevel					textureLevel		(format, size.x(), size.y(), size.z());
1315 		const tcu::PixelBufferAccess		expectedImage		(textureLevel);
1316 
1317 		// Doesn't need to check the output of unused MRT, that may be undefined.
1318 		if (notExportTest && (renderTargetIdx==skippedRenderTarget))
1319 			continue;
1320 
1321 		invalidateAlloc(vk, device, *colorBufferAllocs[renderTargetIdx]);
1322 
1323 		for (int z = 0; z < expectedImage.getDepth(); ++z)
1324 		{
1325 			for (int y = 0; y < expectedImage.getHeight(); ++y)
1326 			{
1327 				for (int x = 0; x < expectedImage.getWidth(); ++x)
1328 				{
1329 					if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1330 						expectedImage.setPixel(expectedColors[renderTargetIdx], x, y, z);
1331 					else
1332 						expectedImage.setPixel(tcu::Vec4(clearColors[renderTargetIdx].float32), x, y, z);
1333 				}
1334 			}
1335 		}
1336 		const tcu::ConstPixelBufferAccess	resultImage		(format, size.x(), size.y(), size.z(), colorBufferAllocs[renderTargetIdx]->getHostPtr());
1337 
1338 		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))
1339 			return tcu::TestStatus::fail("Fail");
1340 	}
1341 
1342 	return tcu::TestStatus::pass("Pass");
1343 }
1344 
initInputResolveSameAttachmentPrograms(SourceCollections & programCollection,const CaseDef caseDef)1345 void initInputResolveSameAttachmentPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1346 {
1347 	DE_UNREF(caseDef);
1348 
1349 	// Vertex shader
1350 	{
1351 		std::ostringstream src;
1352 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1353 			<< "\n"
1354 			<< "layout(location = 0) in vec4 in_position;\n"
1355 			<< "\n"
1356 			<< "out gl_PerVertex {\n"
1357 			<< "	vec4 gl_Position;\n"
1358 			<< "};\n"
1359 			<< "\n"
1360 			<< "void main(void)\n"
1361 			<< "{\n"
1362 			<< "	gl_Position	= in_position;\n"
1363 			<< "}\n";
1364 
1365 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1366 	}
1367 
1368 	// Fragment shader
1369 	{
1370 		std::ostringstream src;
1371 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1372 			<< "\n"
1373 			<< "layout (input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;\n"
1374 			<< "layout(location = 0) out vec4 o_color0;\n"
1375 			<< "\n"
1376 			<< "void main(void)\n"
1377 			<< "{\n"
1378 			<< "    vec4 in_color = subpassLoad(inputColor);\n"
1379 			<< "    o_color0 = vec4(1.0, in_color.y, 0.25, 1.0);\n"
1380 			<< "}\n";
1381 
1382 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1383 	}
1384 }
1385 
makeRenderPassInputResolveSameAttachment(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)1386 Move<VkRenderPass> makeRenderPassInputResolveSameAttachment	(const DeviceInterface&	vk,
1387 															 const VkDevice			device,
1388 															 const VkFormat			colorFormat)
1389 {
1390 	std::vector<VkAttachmentDescription> attachmentDescriptions;
1391 	VkAttachmentDescription colorAttachmentDescription =
1392 	{
1393 		(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
1394 		colorFormat,													// VkFormat						format;
1395 		VK_SAMPLE_COUNT_4_BIT,											// VkSampleCountFlagBits		samples;
1396 		VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
1397 		VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
1398 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
1399 		VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
1400 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				initialLayout;
1401 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,						// VkImageLayout				finalLayout;
1402 	};
1403 
1404 	attachmentDescriptions.push_back(colorAttachmentDescription);
1405 
1406 	VkAttachmentDescription inputAttachmentDescription =
1407 	{
1408 		(VkAttachmentDescriptionFlags)0,								// VkAttachmentDescriptionFla	flags;
1409 		colorFormat,													// VkFormat						format;
1410 		VK_SAMPLE_COUNT_1_BIT,											// VkSampleCountFlagBits		samples;
1411 		VK_ATTACHMENT_LOAD_OP_LOAD,										// VkAttachmentLoadOp			loadOp;
1412 		VK_ATTACHMENT_STORE_OP_STORE,									// VkAttachmentStoreOp			storeOp;
1413 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,								// VkAttachmentLoadOp			stencilLoadOp;
1414 		VK_ATTACHMENT_STORE_OP_DONT_CARE,								// VkAttachmentStoreOp			stencilStoreOp;
1415 		VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				initialLayout;
1416 		VK_IMAGE_LAYOUT_GENERAL,										// VkImageLayout				finalLayout;
1417 	};
1418 
1419 	attachmentDescriptions.push_back(inputAttachmentDescription);
1420 
1421 	const VkAttachmentReference colorAttachmentRef =
1422 	{
1423 		0u,											// deUint32			attachment;
1424 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
1425 	};
1426 
1427 	const VkAttachmentReference inputAttachmentRef =
1428 	{
1429 		1u,											// deUint32			attachment;
1430 		VK_IMAGE_LAYOUT_GENERAL						// VkImageLayout	layout;
1431 	};
1432 
1433 	const VkSubpassDescription subpassDescription =
1434 	{
1435 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags flags;
1436 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint pipelineBindPoint;
1437 		1u,									// deUint32 inputAttachmentCount;
1438 		&inputAttachmentRef,				// const VkAttachmentReference* pInputAttachments;
1439 		1u,									// deUint32 colorAttachmentCount;
1440 		&colorAttachmentRef,				// const VkAttachmentReference* pColorAttachments;
1441 		&inputAttachmentRef,				// const VkAttachmentReference* pResolveAttachments;
1442 		DE_NULL,							// const VkAttachmentReference* pDepthStencilAttachment;
1443 		0u,									// deUint32 preserveAttachmentCount;
1444 		DE_NULL								// const deUint32* pPreserveAttachments;
1445 	};
1446 
1447 	const VkRenderPassCreateInfo renderPassInfo =
1448 	{
1449 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType					sType;
1450 		DE_NULL,									// const void*						pNext;
1451 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags;
1452 		(deUint32)attachmentDescriptions.size(),	// deUint32							attachmentCount;
1453 		&attachmentDescriptions[0],					// const VkAttachmentDescription*	pAttachments;
1454 		1u,											// deUint32							subpassCount;
1455 		&subpassDescription,						// const VkSubpassDescription*		pSubpasses;
1456 		0u,											// deUint32							dependencyCount;
1457 		DE_NULL										// const VkSubpassDependency*		pDependencies;
1458 	};
1459 
1460 	return createRenderPass(vk, device, &renderPassInfo);
1461 }
1462 
testInputResolveSameAttachment(Context & context,const CaseDef caseDef)1463 tcu::TestStatus testInputResolveSameAttachment(Context &context, const CaseDef caseDef)
1464 {
1465 	const DeviceInterface&			vk					= context.getDeviceInterface();
1466 	const VkDevice					device				= context.getDevice();
1467 	const VkQueue					queue				= context.getUniversalQueue();
1468 	const deUint32					queueFamilyIndex	= context.getUniversalQueueFamilyIndex();
1469 	Allocator&						allocator			= context.getDefaultAllocator();
1470 
1471 	// Use unique clear color for each render target to verify no leaking happens between render target clears.
1472 	const VkClearColorValue			clearColor[] =
1473 	{
1474 			{{ 1.0f, 0.0f, 0.0f, 1.0f }},
1475 			{{ 0.0f, 0.5f, 0.0f, 1.0f }}
1476 	};
1477 
1478 	Move<VkBuffer>					vertexBuffer;
1479 	MovePtr<Allocation>				vertexBufferAlloc;
1480 
1481 	vector<SharedPtrVkImageView>	colorAttachments;
1482 	vector<VkImageView>				attachmentHandles;
1483 
1484 	// Create pipeline descriptor set for the image
1485 	const Move<VkDescriptorSetLayout>	descriptorSetLayout		= DescriptorSetLayoutBuilder()
1486 		.addSingleBinding(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, VK_SHADER_STAGE_FRAGMENT_BIT)
1487 		.build(vk, device);
1488 
1489 	const Move<VkDescriptorPool>		descriptorPool			= DescriptorPoolBuilder()
1490 		.addType(VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, 1)
1491 		.build(vk, device, VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT, 1);
1492 
1493 	const Move<VkDescriptorSet>			descriptorSet			= makeDescriptorSet(vk, device, *descriptorPool, *descriptorSetLayout);
1494 
1495 	const Unique<VkPipelineLayout>		pipelineLayout			(makePipelineLayout (vk, device, *descriptorSetLayout));
1496 	GraphicsPipelineWrapper				pipeline				(vk, device, caseDef.pipelineConstructionType);
1497 	const Unique<VkRenderPass>			renderPass				(makeRenderPassInputResolveSameAttachment(vk, device, COLOR_FORMAT));
1498 	Move<VkFramebuffer>					framebuffer;
1499 
1500 	const Unique<VkShaderModule>		vertexModule			(createShaderModule(vk, device, context.getBinaryCollection().get("vert"), 0u));
1501 	const Unique<VkShaderModule>		fragmentModule			(createShaderModule(vk, device, context.getBinaryCollection().get("frag"), 0u));
1502 
1503 	const Unique<VkCommandPool>			cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1504 	const Unique<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
1505 
1506 	const VkImageViewType				imageViewType			= caseDef.imageType;
1507 
1508 	const VkImageSubresourceRange		range					= makeColorSubresourceRange(0, 1);
1509 
1510 	// create color buffer
1511 	const IVec3							attachmentSize			= caseDef.attachmentSize;
1512 	const VkDeviceSize					colorBufferSize			= attachmentSize.x() * attachmentSize.y() * attachmentSize.z() * tcu::getPixelSize(mapVkFormat(COLOR_FORMAT));
1513 	auto								colorBuffer				= makeBuffer(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1514 	MovePtr<Allocation>					colorBufferAlloc		= bindBuffer(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible);
1515 
1516 	// create vertexBuffer
1517 	{
1518 		const vector<tcu::Vec4>			vertices				= genFullQuadVertices(1);
1519 		const VkDeviceSize				vertexBufferSize		= sizeInBytes(vertices);
1520 
1521 		vertexBuffer											= makeBuffer(vk, device, vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1522 		vertexBufferAlloc										= bindBuffer(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible);
1523 
1524 		deMemcpy(vertexBufferAlloc->getHostPtr(), &vertices[0], static_cast<std::size_t>(vertexBufferSize));
1525 		flushAlloc(vk, device, *vertexBufferAlloc);
1526 	}
1527 
1528 	// create colorImages (and msColorImages)
1529 	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;
1530 	Move<VkImage>			colorImage			= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT,
1531 															attachmentSize, 1, colorImageUsage, false);
1532 	MovePtr<Allocation>		colorImageAlloc		= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1533 
1534 	const VkImageUsageFlags	msImageUsage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1535 	Move<VkImage>			msColorImage		= makeImage(vk, device, VkImageViewCreateFlags(0), getImageType(caseDef.imageType), COLOR_FORMAT, attachmentSize, 1, msImageUsage, true);
1536 	MovePtr<Allocation>		msColorImageAlloc	= bindImage(vk, device, allocator, *msColorImage, MemoryRequirement::Any);
1537 
1538 	// create attachmentHandles. We use the renderSize for viewport and scissor
1539 	colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *msColorImage, imageViewType, COLOR_FORMAT, range)));
1540 	attachmentHandles.push_back(**colorAttachments.back());
1541 
1542 	colorAttachments.push_back(makeSharedPtr(makeImageView(vk, device, *colorImage, imageViewType, COLOR_FORMAT, range)));
1543 	attachmentHandles.push_back(**colorAttachments.back());
1544 
1545 	const VkDescriptorImageInfo			descriptorImageInfo		= makeDescriptorImageInfo(DE_NULL, attachmentHandles[1], VK_IMAGE_LAYOUT_GENERAL);
1546 	DescriptorSetUpdateBuilder()
1547 		.writeSingle(*descriptorSet, DescriptorSetUpdateBuilder::Location::binding(0u), VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT, &descriptorImageInfo)
1548 		.update(vk, device);
1549 
1550 	preparePipelineWrapper(pipeline, *pipelineLayout, *renderPass, *vertexModule, *fragmentModule, caseDef.renderSize, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP, 0, 1u, true);
1551 
1552 	// create framebuffer
1553 	framebuffer = makeFramebuffer(vk, device, *renderPass, 2u, &attachmentHandles[0], static_cast<deUint32>(caseDef.renderSize.x()), static_cast<deUint32>(caseDef.renderSize.y()));
1554 
1555 	// record command buffer
1556 	beginCommandBuffer(vk, *cmdBuffer);
1557 
1558 	// Clear image attachments
1559 	{
1560 		const VkImageMemoryBarrier	imageLayoutBarriers[]	=
1561 		{
1562 			{
1563 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1564 				DE_NULL,																				// const void*				pNext;
1565 				0u,																						// VkAccessFlags			srcAccessMask;
1566 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
1567 				VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
1568 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
1569 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1570 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1571 				*msColorImage,																			// VkImage					image;
1572 				range																					// VkImageSubresourceRange	subresourceRange;
1573 			},
1574 			{
1575 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1576 				DE_NULL,																				// const void*				pNext;
1577 				(VkAccessFlags)0,																		// VkAccessFlags			srcAccessMask;
1578 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			dstAccessMask;
1579 				VK_IMAGE_LAYOUT_UNDEFINED,																// VkImageLayout			oldLayout;
1580 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			newLayout;
1581 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1582 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1583 				*colorImage,																			// VkImage					image;
1584 				range																					// VkImageSubresourceRange	subresourceRange;
1585 			}
1586 		};
1587 
1588 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1589 							  0u, DE_NULL, 0u, DE_NULL, 2u, imageLayoutBarriers);
1590 
1591 		vk.cmdClearColorImage(*cmdBuffer, *msColorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[0], 1u, &range);
1592 		vk.cmdClearColorImage(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearColor[1], 1u, &range);
1593 
1594 		const VkImageMemoryBarrier	imageClearBarriers[]	=
1595 		{
1596 			{
1597 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1598 				DE_NULL,																				// const void*				pNext;
1599 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
1600 				VK_ACCESS_COLOR_ATTACHMENT_READ_BIT,													// VkAccessFlags			dstAccessMask;
1601 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
1602 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,												// VkImageLayout			newLayout;
1603 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1604 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1605 				*msColorImage,																			// VkImage					image;
1606 				range																					// VkImageSubresourceRange	subresourceRange;
1607 			},
1608 			{
1609 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,													// VkStructureType			sType;
1610 				DE_NULL,																				// const void*				pNext;
1611 				VK_ACCESS_TRANSFER_WRITE_BIT,															// VkAccessFlags			srcAccessMask;
1612 				VK_ACCESS_SHADER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1613 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,													// VkImageLayout			oldLayout;
1614 				VK_IMAGE_LAYOUT_GENERAL,																// VkImageLayout			newLayout;
1615 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					srcQueueFamilyIndex;
1616 				VK_QUEUE_FAMILY_IGNORED,																// deUint32					destQueueFamilyIndex;
1617 				*colorImage,																			// VkImage					image;
1618 				range																					// VkImageSubresourceRange	subresourceRange;
1619 			}
1620 		};
1621 
1622 		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]);
1623 
1624 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &imageClearBarriers[1]);
1625 	}
1626 
1627 	// Render pass: this should render only to the area defined by renderSize (smaller than the size of the attachment)
1628 	{
1629 		const VkDeviceSize			vertexBufferOffset	= 0ull;
1630 
1631 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, caseDef.renderSize.x(), caseDef.renderSize.y()));
1632 		{
1633 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &vertexBuffer.get(), &vertexBufferOffset);
1634 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline.getPipeline());
1635 			vk.cmdBindDescriptorSets(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelineLayout.get(), 0u, 1u, &descriptorSet.get(), 0u, DE_NULL);
1636 			vk.cmdDraw(*cmdBuffer, 4u, 1u, 0u, 0u);
1637 		}
1638 		endRenderPass(vk, *cmdBuffer);
1639 	}
1640 
1641 	// copy colorImage to host visible colorBuffer
1642 	const VkImageMemoryBarrier	imageBarrier		=
1643 	{
1644 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,														// VkStructureType			sType;
1645 		DE_NULL,																					// const void*				pNext;
1646 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,														// VkAccessFlags			srcAccessMask;
1647 		VK_ACCESS_TRANSFER_READ_BIT,																// VkAccessFlags			dstAccessMask;
1648 		VK_IMAGE_LAYOUT_GENERAL,																	// VkImageLayout			oldLayout;
1649 		VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,														// VkImageLayout			newLayout;
1650 		VK_QUEUE_FAMILY_IGNORED,																	// deUint32					srcQueueFamilyIndex;
1651 		VK_QUEUE_FAMILY_IGNORED,																	// deUint32					destQueueFamilyIndex;
1652 		*colorImage,																				// VkImage					image;
1653 		range																						// VkImageSubresourceRange	subresourceRange;
1654 	};
1655 
1656 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u,
1657 						  0u, DE_NULL, 0u, DE_NULL, 1u, &imageBarrier);
1658 
1659 	const VkBufferImageCopy		regionBufferImageCopy				=
1660 	{
1661 		0ull,																// VkDeviceSize                bufferOffset;
1662 		0u,																	// uint32_t                    bufferRowLength;
1663 		0u,																	// uint32_t                    bufferImageHeight;
1664 		makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u),	// VkImageSubresourceLayers    imageSubresource;
1665 		makeOffset3D(0, 0, 0),												// VkOffset3D                  imageOffset;
1666 		makeExtent3D(attachmentSize),										// VkExtent3D                  imageExtent;
1667 	};
1668 
1669 	vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &regionBufferImageCopy);
1670 
1671 	const VkBufferMemoryBarrier	bufferBarrier		=
1672 	{
1673 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType    sType;
1674 		DE_NULL,									// const void*        pNext;
1675 		VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags      srcAccessMask;
1676 		VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags      dstAccessMask;
1677 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t           srcQueueFamilyIndex;
1678 		VK_QUEUE_FAMILY_IGNORED,					// uint32_t           dstQueueFamilyIndex;
1679 		*colorBuffer,								// VkBuffer           buffer;
1680 		0ull,										// VkDeviceSize       offset;
1681 		VK_WHOLE_SIZE,								// VkDeviceSize       size;
1682 	};
1683 
1684 	vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u,
1685 						  0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
1686 
1687 	endCommandBuffer(vk, *cmdBuffer);
1688 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1689 
1690 	// Verify results
1691 	const tcu::TextureFormat			format				= mapVkFormat(COLOR_FORMAT);
1692 	tcu::TextureLevel					textureLevel		(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z());
1693 	const tcu::PixelBufferAccess		expectedImage		(textureLevel);
1694 
1695 	const tcu::Vec4						expectedColor		= tcu::Vec4(1.0f, 0.5f, 0.25f, 1.0f);
1696 
1697 	invalidateAlloc(vk, device, *colorBufferAlloc);
1698 
1699 	for (int z = 0; z < expectedImage.getDepth(); ++z)
1700 	{
1701 		for (int y = 0; y < expectedImage.getHeight(); ++y)
1702 		{
1703 			for (int x = 0; x < expectedImage.getWidth(); ++x)
1704 			{
1705 				if (x < caseDef.renderSize.x() && y < caseDef.renderSize.y() && z < caseDef.renderSize.z())
1706 					expectedImage.setPixel(expectedColor, x, y, z);
1707 				else
1708 					expectedImage.setPixel(tcu::Vec4(clearColor[0].float32), x, y, z);
1709 			}
1710 		}
1711 	}
1712 	const tcu::ConstPixelBufferAccess	resultImage		(format, attachmentSize.x(), attachmentSize.y(), attachmentSize.z(), colorBufferAlloc->getHostPtr());
1713 
1714 	if (!tcu::intThresholdCompare(context.getTestContext().getLog(), "Image Comparison", "", expectedImage, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT))
1715 		return tcu::TestStatus::fail("Fail");
1716 
1717 	return tcu::TestStatus::pass("Pass");
1718 }
1719 
testUnusedAtt(Context & context)1720 tcu::TestStatus testUnusedAtt (Context& context)
1721 {
1722 	const DeviceInterface&			vk						= context.getDeviceInterface();
1723 	const VkDevice					device					= context.getDevice();
1724 	const Move<VkCommandPool>		cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, context.getUniversalQueueFamilyIndex()));
1725 	const Move<VkCommandBuffer>		cmdBuffer				(makeCommandBuffer(vk, device, *cmdPool));
1726 
1727 	const VkAttachmentReference		attRef					=
1728 	{
1729 		VK_ATTACHMENT_UNUSED,
1730 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL
1731 	};
1732 
1733 	const VkSubpassDescription		subpass					=
1734 	{
1735 		0,
1736 		VK_PIPELINE_BIND_POINT_GRAPHICS,
1737 		0,
1738 		DE_NULL,
1739 		1,
1740 		&attRef,
1741 		DE_NULL,
1742 		DE_NULL,
1743 		0,
1744 		DE_NULL
1745 	};
1746 
1747 	const VkRenderPassCreateInfo	renderPassCreateInfo	=
1748 	{
1749 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,
1750 		DE_NULL,
1751 		0,
1752 		0,
1753 		DE_NULL,
1754 		1,
1755 		&subpass,
1756 		0,
1757 		DE_NULL
1758 	};
1759 
1760 	const Move<VkRenderPass>		renderPass				= createRenderPass(vk, device, &renderPassCreateInfo, DE_NULL);
1761 
1762 	const VkFramebufferCreateInfo	framebufferCreateInfo	=
1763 	{
1764 		VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,
1765 		DE_NULL,
1766 		0,
1767 		*renderPass,
1768 		0,
1769 		DE_NULL,
1770 		32,
1771 		32,
1772 		1
1773 	};
1774 
1775 	const Move<VkFramebuffer>		framebuffer				= createFramebuffer(vk, device, &framebufferCreateInfo, DE_NULL);
1776 
1777 	beginCommandBuffer(vk, *cmdBuffer);
1778 	beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(0, 0, 32u, 32u));
1779 	endRenderPass(vk, *cmdBuffer);
1780 	endCommandBuffer(vk, *cmdBuffer);
1781 
1782 	return tcu::TestStatus::pass("Pass");
1783 }
1784 
initDifferentAttachmentSizesPrograms(SourceCollections & programCollection,const CaseDef caseDef)1785 void initDifferentAttachmentSizesPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1786 {
1787 	DE_UNREF(caseDef);
1788 
1789 	// Vertex shader
1790 	{
1791 		std::ostringstream src;
1792 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1793 			<< "\n"
1794 			<< "layout(location = 0) in vec4 in_position;\n"
1795 			<< "\n"
1796 			<< "out gl_PerVertex {\n"
1797 			<< "	vec4 gl_Position;\n"
1798 			<< "};\n"
1799 			<< "\n"
1800 			<< "void main(void)\n"
1801 			<< "{\n"
1802 			<< "	gl_Position	= in_position;\n"
1803 			<< "}\n";
1804 
1805 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1806 	}
1807 
1808 	// Fragment shader
1809 	{
1810 		std::ostringstream src;
1811 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1812 			<< "\n"
1813 			<< "layout(location = 0) out vec4 o_color0;\n"
1814 			<< "layout(location = 1) out vec4 o_color1;\n"
1815 			<< "layout(location = 2) out vec4 o_color2;\n"
1816 			<< "\n"
1817 			<< "void main(void)\n"
1818 			<< "{\n"
1819 			<< "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1820 			<< "    o_color1 = vec4(0.5,  1.0, 0.25, 1.0);\n"
1821 			<< "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1822 			<< "}\n";
1823 
1824 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1825 	}
1826 }
1827 
initMultiAttachmentsNotExportPrograms(SourceCollections & programCollection,const CaseDef caseDef)1828 void initMultiAttachmentsNotExportPrograms (SourceCollections& programCollection, const CaseDef caseDef)
1829 {
1830 	DE_UNREF(caseDef);
1831 
1832 	// Vertex shader
1833 	{
1834 		std::ostringstream src;
1835 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1836 			<< "\n"
1837 			<< "layout(location = 0) in vec4 in_position;\n"
1838 			<< "\n"
1839 			<< "out gl_PerVertex {\n"
1840 			<< "	vec4 gl_Position;\n"
1841 			<< "};\n"
1842 			<< "\n"
1843 			<< "void main(void)\n"
1844 			<< "{\n"
1845 			<< "	gl_Position	= in_position;\n"
1846 			<< "}\n";
1847 
1848 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1849 	}
1850 
1851 	// Fragment shader
1852 	{
1853 		std::ostringstream src;
1854 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1855 			<< "\n"
1856 			<< "layout(location = 0) out vec4 o_color0;\n"
1857 			<< "layout(location = 1) out vec4 o_color1;\n"
1858 			<< "layout(location = 2) out vec4 o_color2;\n"
1859 			<< "\n"
1860 			<< "void main(void)\n"
1861 			<< "{\n"
1862 			<< "    o_color0 = vec4(1.0,  0.5, 0.25, 1.0);\n"
1863 			<< "    o_color2 = vec4(0.25, 0.5, 1.0,  1.0);\n"
1864 			<< "}\n";
1865 
1866 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1867 	}
1868 }
1869 
getShortImageViewTypeName(const VkImageViewType imageViewType)1870 std::string getShortImageViewTypeName (const VkImageViewType imageViewType)
1871 {
1872 	std::string	s	(getImageViewTypeName(imageViewType));
1873 	return de::toLower(s.substr(19));
1874 }
1875 
getSizeString(const CaseDef & caseDef)1876 std::string getSizeString (const CaseDef& caseDef)
1877 {
1878 	std::ostringstream	str;
1879 
1880 										str << caseDef.renderSize.x();
1881 	if (caseDef.renderSize.y() > 1)		str << "x" << caseDef.renderSize.y();
1882 	if (caseDef.renderSize.z() > 1)		str << "x" << caseDef.renderSize.z();
1883 
1884 										str << "_" << caseDef.attachmentSize.x();
1885 
1886 	if (caseDef.attachmentSize.y() > 1)	str << "x" << caseDef.attachmentSize.y();
1887 	if (caseDef.attachmentSize.z() > 1)	str << "x" << caseDef.attachmentSize.z();
1888 	if (caseDef.numLayers > 1)			str << "_" << caseDef.numLayers;
1889 
1890 	return str.str();
1891 }
1892 
getTestCaseString(const CaseDef & caseDef)1893 std::string getTestCaseString (const CaseDef& caseDef)
1894 {
1895 	std::ostringstream str;
1896 
1897 	str << getShortImageViewTypeName (caseDef.imageType).c_str();
1898 	str << "_";
1899 	str << getSizeString(caseDef);
1900 
1901 	if (caseDef.multisample)
1902 		str << "_ms";
1903 
1904 	return str.str();
1905 }
1906 
checkSupport(Context & context,const CaseDef caseDef)1907 void checkSupport (Context& context, const CaseDef caseDef)
1908 {
1909 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1910 }
1911 
checkSupportNoAtt(Context & context,const NoAttCaseDef caseDef)1912 void checkSupportNoAtt (Context& context, const NoAttCaseDef caseDef)
1913 {
1914 	const VkPhysicalDeviceFeatures features = context.getDeviceFeatures();
1915 
1916 	context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_FRAGMENT_STORES_AND_ATOMICS);
1917 
1918 	if (!features.geometryShader && !features.tessellationShader) // Shader uses gl_PrimitiveID
1919 		throw tcu::NotSupportedError("geometryShader or tessellationShader feature not supported");
1920 
1921 	if (caseDef.multisample)
1922 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_SAMPLE_RATE_SHADING); // MS shader uses gl_SampleID
1923 
1924 	checkPipelineLibraryRequirements(context.getInstanceInterface(), context.getPhysicalDevice(), caseDef.pipelineConstructionType);
1925 }
1926 
addAttachmentTestCasesWithFunctions(tcu::TestCaseGroup * group,PipelineConstructionType pipelineConstructionType)1927 void addAttachmentTestCasesWithFunctions (tcu::TestCaseGroup* group, PipelineConstructionType pipelineConstructionType)
1928 {
1929 	// Add test cases for attachment strictly sizes larger than the framebuffer
1930 	const CaseDef	caseDef[]	=
1931 	{
1932 		// Single-sample test cases
1933 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1934 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1935 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,			IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1936 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,			IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1937 
1938 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D_ARRAY,	IVec3(32, 1, 1),	IVec3(64, 1, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1939 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D_ARRAY,	IVec3(32, 1, 1),	IVec3(48, 1, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1940 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D_ARRAY,	IVec3(32, 1, 1),	IVec3(39, 1, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1941 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D_ARRAY,	IVec3(19, 1, 1),	IVec3(32, 1, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1942 
1943 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1944 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1945 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1946 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		false,	MULTI_ATTACHMENTS_NONE },
1947 
1948 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1949 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1950 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1951 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		false,	MULTI_ATTACHMENTS_NONE },
1952 
1953 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE,		IVec3(32, 32, 1),	IVec3(64, 64, 1),	6,		false,	MULTI_ATTACHMENTS_NONE },
1954 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE,		IVec3(32, 32, 1),	IVec3(48, 48, 1),	6,		false,	MULTI_ATTACHMENTS_NONE },
1955 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE,		IVec3(32, 32, 1),	IVec3(39, 41, 1),	6,		false,	MULTI_ATTACHMENTS_NONE },
1956 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE,		IVec3(19, 27, 1),	IVec3(32, 32, 1),	6,		false,	MULTI_ATTACHMENTS_NONE },
1957 
1958 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	6*2,	false,	MULTI_ATTACHMENTS_NONE },
1959 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	6*2,	false,	MULTI_ATTACHMENTS_NONE },
1960 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	6*2,	false,	MULTI_ATTACHMENTS_NONE },
1961 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_CUBE_ARRAY,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	6*2,	false,	MULTI_ATTACHMENTS_NONE },
1962 
1963 		// Multi-sample test cases
1964 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,		true,	MULTI_ATTACHMENTS_NONE },
1965 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,		true,	MULTI_ATTACHMENTS_NONE },
1966 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,		true,	MULTI_ATTACHMENTS_NONE },
1967 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,			IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,		true,	MULTI_ATTACHMENTS_NONE },
1968 
1969 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	4,		true,	MULTI_ATTACHMENTS_NONE },
1970 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	4,		true,	MULTI_ATTACHMENTS_NONE },
1971 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	4,		true,	MULTI_ATTACHMENTS_NONE },
1972 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D_ARRAY,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	4,		true,	MULTI_ATTACHMENTS_NONE },
1973 	};
1974 
1975 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(caseDef); ++sizeNdx)
1976 		addFunctionCaseWithPrograms(group, getTestCaseString(caseDef[sizeNdx]).c_str(), "", checkSupport, initColorPrograms, test, caseDef[sizeNdx]);
1977 
1978 	// Add tests for the case where there are no color attachments but the
1979 	// fragment shader writes to an image via imageStore().
1980 	NoAttCaseDef noAttCaseDef { pipelineConstructionType, false };
1981 	addFunctionCaseWithPrograms(group, "no_attachments",    "", checkSupportNoAtt, initImagePrograms, testNoAtt, noAttCaseDef);
1982 	noAttCaseDef.multisample = true;
1983 	addFunctionCaseWithPrograms(group, "no_attachments_ms", "", checkSupportNoAtt, initImagePrograms, testNoAtt, noAttCaseDef);
1984 
1985 	// Test render pass with attachment set as unused.
1986 	if (pipelineConstructionType == PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC)
1987 		addFunctionCase(group, "unused_attachment", "", testUnusedAtt);
1988 
1989 	// Tests with multiple attachments that have different sizes.
1990 	const CaseDef	differentAttachmentSizesCaseDef[]	=
1991 	{
1992 		// Single-sample test cases
1993 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(64, 1, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
1994 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(48, 1, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
1995 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,	IVec3(32, 1, 1),	IVec3(39, 1, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
1996 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_1D,	IVec3(19, 1, 1),	IVec3(32, 1, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
1997 
1998 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
1999 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2000 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2001 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	false,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2002 
2003 		// Multi-sample test cases
2004 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(64, 64, 1),	1,	true,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2005 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(48, 48, 1),	1,	true,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2006 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(32, 32, 1),	IVec3(39, 41, 1),	1,	true,	MULTI_ATTACHMENTS_DIFFERENT_SIZES },
2007 		{ pipelineConstructionType,		VK_IMAGE_VIEW_TYPE_2D,	IVec3(19, 27, 1),	IVec3(32, 32, 1),	1,	true,	MULTI_ATTACHMENTS_DIFFERENT_SIZES }
2008 	};
2009 
2010 	for (int sizeNdx = 0; sizeNdx < DE_LENGTH_OF_ARRAY(differentAttachmentSizesCaseDef); ++sizeNdx)
2011 		addFunctionCaseWithPrograms(group, (std::string("diff_attachments_") + getTestCaseString(differentAttachmentSizesCaseDef[sizeNdx])).c_str(), "", checkSupport, initDifferentAttachmentSizesPrograms, testMultiAttachments, differentAttachmentSizesCaseDef[sizeNdx]);
2012 
2013 	// Tests with same attachment for input and resolving.
2014 	const CaseDef resolveInputSameAttachmentCaseDef = { pipelineConstructionType,	VK_IMAGE_VIEW_TYPE_2D,	IVec3(64, 64, 1),	IVec3(64, 64, 1),	1,	true,	MULTI_ATTACHMENTS_NONE };
2015 	addFunctionCaseWithPrograms(group, "resolve_input_same_attachment" , "", checkSupport, initInputResolveSameAttachmentPrograms, testInputResolveSameAttachment, resolveInputSameAttachmentCaseDef);
2016 
2017 	// Tests with multiple attachments, which some of them are not used in FS.
2018 	const CaseDef AttachmentCaseDef[] = {
2019 		// Single-sample test case
2020 		{ pipelineConstructionType,	VK_IMAGE_VIEW_TYPE_2D,	IVec3(64, 64, 1),	IVec3(64, 64, 1),	1,	false,	MULTI_ATTACHMENTS_NOT_EXPORTED },
2021 		// Multi-sample test case
2022 		{ pipelineConstructionType,	VK_IMAGE_VIEW_TYPE_2D,	IVec3(64, 64, 1),	IVec3(64, 64, 1),	1,	true,	MULTI_ATTACHMENTS_NOT_EXPORTED }
2023 	};
2024 
2025 	for (int Ndx = 0; Ndx < DE_LENGTH_OF_ARRAY(AttachmentCaseDef); ++Ndx)
2026 		addFunctionCaseWithPrograms(group, (std::string("multi_attachments_not_exported_") + getTestCaseString(AttachmentCaseDef[Ndx])).c_str(), "", checkSupport, initMultiAttachmentsNotExportPrograms, testMultiAttachments, AttachmentCaseDef[Ndx]);
2027 }
2028 
2029 } // anonymous ns
2030 
createFramebufferAttachmentTests(tcu::TestContext & testCtx,PipelineConstructionType pipelineConstructionType)2031 tcu::TestCaseGroup* createFramebufferAttachmentTests (tcu::TestContext& testCtx, PipelineConstructionType pipelineConstructionType)
2032 {
2033 	return createTestGroup(testCtx, "framebuffer_attachment", "Framebuffer attachment tests", addAttachmentTestCasesWithFunctions, pipelineConstructionType);
2034 }
2035 
2036 } // pipeline
2037 } // vkt
2038