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