1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
6  * Copyright (c) 2018 Google Inc.
7  * Copyright (c) 2015 Imagination Technologies Ltd.
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
23  * \brief Tests attachments unused by subpasses
24  *//*--------------------------------------------------------------------*/
25 
26 #include "vktRenderPassUnusedAttachmentTests.hpp"
27 #include "pipeline/vktPipelineImageUtil.hpp"
28 #include "vktTestCase.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkMemUtil.hpp"
31 #include "vkPlatform.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkCmdUtil.hpp"
35 #include "vkRef.hpp"
36 #include "vkRefUtil.hpp"
37 #include "vkTypeUtil.hpp"
38 #include "vkCmdUtil.hpp"
39 #include "vkObjUtil.hpp"
40 #include "tcuImageCompare.hpp"
41 #include "tcuPlatform.hpp"
42 #include "tcuTextureUtil.hpp"
43 #include "tcuTestLog.hpp"
44 #include "deStringUtil.hpp"
45 #include "deUniquePtr.hpp"
46 #include "deRandom.hpp"
47 #include <cstring>
48 #include <set>
49 #include <sstream>
50 #include <vector>
51 
52 namespace vkt
53 {
54 namespace renderpass
55 {
56 
57 using namespace vk;
58 
59 namespace
60 {
61 
62 struct TestParams
63 {
64 	VkAttachmentLoadOp	loadOp;
65 	VkAttachmentStoreOp	storeOp;
66 	VkAttachmentLoadOp	stencilLoadOp;
67 	VkAttachmentStoreOp	stencilStoreOp;
68 	RenderPassType		renderPassType;
69 };
70 
71 struct Vertex4RGBA
72 {
73 	tcu::Vec4 position;
74 	tcu::Vec4 color;
75 };
76 
createQuad(void)77 std::vector<Vertex4RGBA> createQuad (void)
78 {
79 	std::vector<Vertex4RGBA>	vertices;
80 
81 	const float			size				= 0.8f;
82 	const tcu::Vec4		color				(0.2f, 0.3f, 0.1f, 1.0f);
83 	const Vertex4RGBA	lowerLeftVertex		= {tcu::Vec4(-size, -size, 0.0f, 1.0f), color};
84 	const Vertex4RGBA	lowerRightVertex	= {tcu::Vec4(size, -size, 0.0f, 1.0f), color};
85 	const Vertex4RGBA	upperLeftVertex		= {tcu::Vec4(-size, size, 0.0f, 1.0f), color};
86 	const Vertex4RGBA	upperRightVertex	= {tcu::Vec4(size, size, 0.0f, 1.0f), color};
87 
88 	vertices.push_back(lowerLeftVertex);
89 	vertices.push_back(lowerRightVertex);
90 	vertices.push_back(upperLeftVertex);
91 	vertices.push_back(upperLeftVertex);
92 	vertices.push_back(lowerRightVertex);
93 	vertices.push_back(upperRightVertex);
94 
95 	return vertices;
96 }
97 
98 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)99 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vk,
100 									 VkDevice				vkDevice,
101 									 const TestParams		testParams)
102 {
103 	const VkImageAspectFlags	aspectMask						= testParams.renderPassType == RENDERPASS_TYPE_LEGACY ? 0 : VK_IMAGE_ASPECT_COLOR_BIT;
104 	const AttachmentDesc		attachmentDescriptions[]		=
105 	{
106 		// Result attachment
107 		AttachmentDesc (
108 			DE_NULL,									// const void*						pNext
109 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
110 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
111 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
112 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
113 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
114 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
115 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
116 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
117 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
118 		),
119 		// Unused attachment
120 		AttachmentDesc (
121 			DE_NULL,									// const void*						pNext
122 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
123 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
124 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
125 			testParams.loadOp,							// VkAttachmentLoadOp				loadOp
126 			testParams.storeOp,							// VkAttachmentStoreOp				storeOp
127 			testParams.stencilLoadOp,					// VkAttachmentLoadOp				stencilLoadOp
128 			testParams.stencilStoreOp,					// VkAttachmentStoreOp				stencilStoreOp
129 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
130 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
131 		),
132 		// Input attachment
133 		AttachmentDesc (
134 			DE_NULL,									// const void*						pNext
135 			(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
136 			VK_FORMAT_R8G8B8A8_UNORM,					// VkFormat							format
137 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
138 			VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp
139 			VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
140 			VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
141 			VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
142 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout
143 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
144 		)
145 	};
146 
147 	// Note: Attachment 1 is not referenced by any subpass.
148 	const AttachmentRef			resultAttachmentRefSubpass0		(
149 		DE_NULL,									// const void*			pNext
150 		2u,											// deUint32				attachment
151 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
152 		aspectMask									// VkImageAspectFlags	aspectMask
153 	);
154 
155 	const AttachmentRef			resultAttachmentRefSubpass1		(
156 		DE_NULL,									// const void*			pNext
157 		0u,											// deUint32				attachment
158 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout		layout
159 		aspectMask									// VkImageAspectFlags	aspectMask
160 	);
161 
162 	const AttachmentRef			inputAttachmentRefSubpass1		(
163 		DE_NULL,									// const void*			pNext
164 		2u,											// deUint32				attachment
165 		VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL,	// VkImageLayout		layout
166 		aspectMask									// VkImageAspectFlags	aspectMask
167 	);
168 
169 	const SubpassDesc			subpassDescriptions[]			=
170 	{
171 		SubpassDesc (
172 			DE_NULL,
173 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
174 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
175 			0u,									// deUint32							viewMask
176 			0u,									// deUint32							inputAttachmentCount
177 			DE_NULL,							// const VkAttachmentReference*		pInputAttachments
178 			1u,									// deUint32							colorAttachmentCount
179 			&resultAttachmentRefSubpass0,		// const VkAttachmentReference*		pColorAttachments
180 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments
181 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment
182 			0u,									// deUint32							preserveAttachmentCount
183 			DE_NULL								// const deUint32*					pPreserveAttachments
184 		),
185 		SubpassDesc (
186 			DE_NULL,
187 			(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags		flags
188 			VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint				pipelineBindPoint
189 			0u,									// deUint32							viewMask
190 			1u,									// deUint32							inputAttachmentCount
191 			&inputAttachmentRefSubpass1,		// const VkAttachmentReference*		pInputAttachments
192 			1u,									// deUint32							colorAttachmentCount
193 			&resultAttachmentRefSubpass1,		// const VkAttachmentReference*		pColorAttachments
194 			DE_NULL,							// const VkAttachmentReference*		pResolveAttachments
195 			DE_NULL,							// const VkAttachmentReference*		pDepthStencilAttachment
196 			0u,									// deUint32							preserveAttachmentCount
197 			DE_NULL								// const deUint32*					pPreserveAttachments
198 		)
199 	};
200 
201 	const SubpassDep			subpassDependency				(
202 		DE_NULL,										// const void*				pNext
203 		0u,												// uint32_t					srcSubpass
204 		1u,												// uint32_t					dstSubpass
205 		VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT,	// VkPipelineStageFlags		srcStageMask
206 		VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT,			// VkPipelineStageFlags		dstStageMask
207 		VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,			// VkAccessFlags			srcAccessMask
208 		VK_ACCESS_INPUT_ATTACHMENT_READ_BIT,			// VkAccessFlags			dstAccessMask
209 		VK_DEPENDENCY_BY_REGION_BIT,					// VkDependencyFlags		dependencyFlags
210 		0u												// deInt32					viewOffset
211 	);
212 
213 	const RenderPassCreateInfo	renderPassInfo					(
214 		DE_NULL,									// const void*						pNext
215 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags			flags
216 		3u,											// deUint32							attachmentCount
217 		attachmentDescriptions,						// const VkAttachmentDescription*	pAttachments
218 		2u,											// deUint32							subpassCount
219 		subpassDescriptions,						// const VkSubpassDescription*		pSubpasses
220 		1u,											// deUint32							dependencyCount
221 		&subpassDependency,							// const VkSubpassDependency*		pDependencies
222 		0u,											// deUint32							correlatedViewMaskCount
223 		DE_NULL										// const deUint32*					pCorrelatedViewMasks
224 	);
225 
226 	return renderPassInfo.createRenderPass(vk, vkDevice);
227 }
228 
229 class UnusedAttachmentTest : public vkt::TestCase
230 {
231 public:
232 										UnusedAttachmentTest	(tcu::TestContext&	testContext,
233 																 const std::string&	name,
234 																 const std::string&	description,
235 																 const TestParams&	testParams);
236 	virtual								~UnusedAttachmentTest	(void);
237 	virtual void						initPrograms			(SourceCollections&	sourceCollections) const;
238 	virtual TestInstance*				createInstance			(Context&			context) const;
239 private:
240 	const TestParams					m_testParams;
241 };
242 
243 class UnusedAttachmentTestInstance : public vkt::TestInstance
244 {
245 public:
246 										UnusedAttachmentTestInstance	(Context&				context,
247 																		 const TestParams&		testParams);
248 	virtual								~UnusedAttachmentTestInstance	(void);
249 	virtual tcu::TestStatus				iterate							(void);
250 	template<typename RenderpassSubpass>
251 	void								createCommandBuffer				(const DeviceInterface&	vk,
252 																		 VkDevice				vkDevice);
253 private:
254 	tcu::TestStatus						verifyImage						(void);
255 
256 	const tcu::UVec2					m_renderSize;
257 
258 	Move<VkImage>						m_colorImage;
259 	de::MovePtr<Allocation>				m_colorImageAlloc;
260 	Move<VkImageView>					m_colorAttachmentView;
261 
262 	Move<VkImage>						m_unusedImage;
263 	de::MovePtr<Allocation>				m_unusedImageAlloc;
264 	Move<VkImageView>					m_unusedAttachmentView;
265 
266 	Move<VkImage>						m_inputImage;
267 	de::MovePtr<Allocation>				m_inputImageAlloc;
268 	Move<VkImageView>					m_inputAttachmentView;
269 
270 	Move<VkDescriptorSetLayout>			m_descriptorSetLayoutSubpass0;
271 	Move<VkDescriptorSetLayout>			m_descriptorSetLayoutSubpass1;
272 	Move<VkDescriptorPool>				m_descriptorPool;
273 	Move<VkDescriptorSet>				m_descriptorSetSubpass1;
274 	Move<VkRenderPass>					m_renderPass;
275 	Move<VkFramebuffer>					m_framebuffer;
276 
277 	Move<VkShaderModule>				m_vertexShaderModule;
278 	Move<VkShaderModule>				m_fragmentShaderModuleSubpass0;
279 	Move<VkShaderModule>				m_fragmentShaderModuleSubpass1;
280 
281 	Move<VkBuffer>						m_vertexBuffer;
282 	std::vector<Vertex4RGBA>			m_vertices;
283 	de::MovePtr<Allocation>				m_vertexBufferAlloc;
284 
285 	Move<VkBuffer>						m_backingBuffer;
286 	de::MovePtr<Allocation>				m_backingBufferAlloc;
287 
288 	Move<VkPipelineLayout>				m_pipelineLayoutSubpass0;
289 	Move<VkPipelineLayout>				m_pipelineLayoutSubpass1;
290 	Move<VkPipeline>					m_graphicsPipelineSubpass0;
291 	Move<VkPipeline>					m_graphicsPipelineSubpass1;
292 
293 	Move<VkCommandPool>					m_cmdPool;
294 	Move<VkCommandBuffer>				m_cmdBuffer;
295 };
296 
UnusedAttachmentTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)297 UnusedAttachmentTest::UnusedAttachmentTest (tcu::TestContext&	testContext,
298 											const std::string&	name,
299 											const std::string&	description,
300 											const TestParams&	testParams)
301 	: vkt::TestCase	(testContext, name, description)
302 	, m_testParams	(testParams)
303 {
304 }
305 
~UnusedAttachmentTest(void)306 UnusedAttachmentTest::~UnusedAttachmentTest (void)
307 {
308 }
309 
createInstance(Context & context) const310 TestInstance* UnusedAttachmentTest::createInstance (Context& context) const
311 {
312 	return new UnusedAttachmentTestInstance(context, m_testParams);
313 }
314 
initPrograms(SourceCollections & sourceCollections) const315 void UnusedAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
316 {
317 	std::ostringstream fragmentSource;
318 
319 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
320 		"#version 450\n"
321 		"layout(location = 0) in highp vec4 position;\n"
322 		"layout(location = 1) in highp vec4 color;\n"
323 		"layout(location = 0) out highp vec4 vtxColor;\n"
324 		"void main (void)\n"
325 		"{\n"
326 		"	gl_Position = position;\n"
327 		"	vtxColor = color;\n"
328 		"}\n");
329 
330 	sourceCollections.glslSources.add("color_frag_sb0") << glu::FragmentSource(
331 		"#version 450\n"
332 		"layout(location = 0) in highp vec4 vtxColor;\n"
333 		"layout(location = 0) out highp vec4 fragColor;\n"
334 		"void main (void)\n"
335 		"{\n"
336 		"	fragColor = vtxColor;\n"
337 		"}\n");
338 
339 	sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
340 		"#version 450\n"
341 		"layout(location = 0) in highp vec4 vtxColor;\n"
342 		"layout(location = 0) out highp vec4 fragColor;\n"
343 		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
344 		"void main (void)\n"
345 		"{\n"
346 		"	fragColor = subpassLoad(inputColor) + vtxColor;\n"
347 		"}\n");
348 }
349 
UnusedAttachmentTestInstance(Context & context,const TestParams & testParams)350 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance (Context&			context,
351 															const TestParams&	testParams)
352 	: vkt::TestInstance	(context)
353 	, m_renderSize		(32u, 32u)
354 	, m_vertices		(createQuad())
355 {
356 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
357 	const VkDevice				vkDevice				= m_context.getDevice();
358 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
359 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
360 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
361 
362 	// Check for renderpass2 extension if used
363 	if (testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
364 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
365 
366 	// Create color image
367 	{
368 		const VkImageCreateInfo	colorImageParams =
369 		{
370 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
371 			DE_NULL,																	// const void*				pNext;
372 			0u,																			// VkImageCreateFlags		flags;
373 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
374 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
375 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
376 			1u,																			// deUint32					mipLevels;
377 			1u,																			// deUint32					arrayLayers;
378 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
379 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
380 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
381 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
382 			1u,																			// deUint32					queueFamilyIndexCount;
383 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
384 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
385 		};
386 
387 		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
388 
389 		// Allocate and bind color image memory
390 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
391 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
392 	}
393 
394 	// Create image which is not used by any subpass
395 	{
396 		const VkImageCreateInfo	unusedImageParams =
397 		{
398 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
399 			DE_NULL,																	// const void*				pNext;
400 			0u,																			// VkImageCreateFlags		flags;
401 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
402 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
403 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
404 			1u,																			// deUint32					mipLevels;
405 			1u,																			// deUint32					arrayLayers;
406 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
407 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
408 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
409 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT,										// VkImageUsageFlags		usage;
410 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
411 			1u,																			// deUint32					queueFamilyIndexCount;
412 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
413 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
414 		};
415 
416 		m_unusedImage			= createImage(vk, vkDevice, &unusedImageParams);
417 
418 		// Allocate and bind unused image memory
419 		VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
420 
421 		m_unusedImageAlloc		= memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
422 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(), m_unusedImageAlloc->getOffset()));
423 
424 		// Clear image with specific value to verify the contents don't change
425 		{
426 			const VkImageAspectFlags		aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
427 			Move<VkCommandPool>				cmdPool;
428 			Move<VkCommandBuffer>			cmdBuffer;
429 
430 			VkClearValue					clearValue;
431 			clearValue.color.float32[0] = 0.1f;
432 			clearValue.color.float32[1] = 0.2f;
433 			clearValue.color.float32[2] = 0.3f;
434 			clearValue.color.float32[3] = 0.4f;
435 
436 			// Create command pool and buffer
437 			cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
438 			cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
439 
440 			const VkImageMemoryBarrier preImageBarrier =
441 			{
442 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
443 				DE_NULL,								// const void*				pNext;
444 				0u,										// VkAccessFlags			srcAccessMask;
445 				VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
446 				VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
447 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
448 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
449 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
450 				*m_unusedImage,							// VkImage					image;
451 				{										// VkImageSubresourceRange	subresourceRange;
452 					aspectMask,							// VkImageAspect			aspect;
453 					0u,									// deUint32					baseMipLevel;
454 					1u,									// deUint32					mipLevels;
455 					0u,									// deUint32					baseArraySlice;
456 					1u									// deUint32					arraySize;
457 				}
458 			};
459 
460 			const VkImageMemoryBarrier postImageBarrier =
461 			{
462 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
463 				DE_NULL,									// const void*				pNext;
464 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
465 				VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
466 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
467 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
468 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
469 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
470 				*m_unusedImage,								// VkImage					image;
471 				{											// VkImageSubresourceRange	subresourceRange;
472 					aspectMask,								// VkImageAspect			aspect;
473 					0u,										// deUint32					baseMipLevel;
474 					1u,										// deUint32					mipLevels;
475 					0u,										// deUint32					baseArraySlice;
476 					1u										// deUint32					arraySize;
477 				}
478 			};
479 
480 			const VkImageSubresourceRange clearRange	=
481 			{
482 				aspectMask,	// VkImageAspectFlags	aspectMask;
483 				0u,			// deUint32				baseMipLevel;
484 				1u,			// deUint32				levelCount;
485 				0u,			// deUint32				baseArrayLayer;
486 				1u			// deUint32				layerCount;
487 			};
488 
489 			// Clear image
490 			beginCommandBuffer(vk, *cmdBuffer);
491 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_HOST_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &preImageBarrier);
492 			vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange);
493 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_ALL_GRAPHICS_BIT, (VkDependencyFlags)0, 0, (const VkMemoryBarrier*)DE_NULL, 0, (const VkBufferMemoryBarrier*)DE_NULL, 1, &postImageBarrier);
494 			endCommandBuffer(vk, *cmdBuffer);
495 
496 			submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
497 		}
498 	}
499 
500 	// Create input image
501 	{
502 		const VkImageCreateInfo	inputImageParams =
503 		{
504 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
505 			DE_NULL,																	// const void*				pNext;
506 			0u,																			// VkImageCreateFlags		flags;
507 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
508 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
509 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
510 			1u,																			// deUint32					mipLevels;
511 			1u,																			// deUint32					arrayLayers;
512 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
513 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
514 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,	// VkImageUsageFlags		usage;
515 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
516 			1u,																			// deUint32					queueFamilyIndexCount;
517 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
518 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
519 		};
520 
521 		m_inputImage = createImage(vk, vkDevice, &inputImageParams);
522 
523 		// Allocate and bind input image memory
524 		m_inputImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
525 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(), m_inputImageAlloc->getOffset()));
526 	}
527 
528 	// Create color attachment view
529 	{
530 		const VkImageViewCreateInfo colorAttachmentViewParams =
531 		{
532 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
533 			DE_NULL,											// const void*				pNext;
534 			0u,													// VkImageViewCreateFlags	flags;
535 			*m_colorImage,										// VkImage					image;
536 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
537 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
538 			componentMappingRGBA,								// VkChannelMapping			channels;
539 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
540 		};
541 
542 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
543 	}
544 
545 	// Create unused attachment view
546 	{
547 		const VkImageViewCreateInfo unusedAttachmentViewParams =
548 		{
549 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
550 			DE_NULL,											// const void*				pNext;
551 			0u,													// VkImageViewCreateFlags	flags;
552 			*m_unusedImage,										// VkImage					image;
553 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
554 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
555 			componentMappingRGBA,								// VkChannelMapping			channels;
556 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
557 		};
558 
559 		m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
560 	}
561 
562 	// Create input attachment view
563 	{
564 		const VkImageViewCreateInfo inputAttachmentViewParams =
565 		{
566 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
567 			DE_NULL,											// const void*				pNext;
568 			0u,													// VkImageViewCreateFlags	flags;
569 			*m_inputImage,										// VkImage					image;
570 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
571 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
572 			componentMappingRGBA,								// VkChannelMapping			channels;
573 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
574 		};
575 
576 		m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
577 	}
578 
579 	// Create render pass
580 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
581 		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
582 	else
583 		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
584 
585 	// Create framebuffer
586 	{
587 		const VkImageView				imageViews[]		=
588 		{
589 			*m_colorAttachmentView,
590 			*m_unusedAttachmentView,
591 			*m_inputAttachmentView
592 		};
593 
594 		const VkFramebufferCreateInfo	framebufferParams	=
595 		{
596 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
597 			DE_NULL,									// const void*				pNext;
598 			0u,											// VkFramebufferCreateFlags	flags;
599 			*m_renderPass,								// VkRenderPass				renderPass;
600 			3u,											// deUint32					attachmentCount;
601 			imageViews,									// const VkImageView*		pAttachments;
602 			(deUint32)m_renderSize.x(),					// deUint32					width;
603 			(deUint32)m_renderSize.y(),					// deUint32					height;
604 			1u											// deUint32					layers;
605 		};
606 
607 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
608 	}
609 
610 	// Create pipeline layout for subpass 0
611 	{
612 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
613 		{
614 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
615 			DE_NULL,												// const void*							pNext
616 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
617 			0u,														// deUint32								bindingCount
618 			DE_NULL													// const VkDescriptorSetLayoutBinding*	pBindings
619 		};
620 		m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
621 
622 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
623 		{
624 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
625 			DE_NULL,											// const void*						pNext;
626 			0u,													// VkPipelineLayoutCreateFlags		flags;
627 			1u,													// deUint32							setLayoutCount;
628 			&m_descriptorSetLayoutSubpass0.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
629 			0u,													// deUint32							pushConstantRangeCount;
630 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
631 		};
632 
633 		m_pipelineLayoutSubpass0 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
634 	}
635 
636 	// Create pipeline layout for subpass 1
637 	{
638 		const VkDescriptorSetLayoutBinding		layoutBinding				=
639 		{
640 			0u,										// deUint32				binding;
641 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		descriptorType;
642 			1u,										// deUint32				descriptorCount;
643 			VK_SHADER_STAGE_FRAGMENT_BIT,			// VkShaderStageFlags	stageFlags;
644 			DE_NULL									// const VkSampler*		pImmutableSamplers;
645 		};
646 
647 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
648 		{
649 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
650 			DE_NULL,												// const void*							pNext
651 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
652 			1u,														// deUint32								bindingCount
653 			&layoutBinding											// const VkDescriptorSetLayoutBinding*	pBindings
654 		};
655 		m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
656 
657 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
658 		{
659 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
660 			DE_NULL,											// const void*						pNext;
661 			0u,													// VkPipelineLayoutCreateFlags		flags;
662 			1u,													// deUint32							setLayoutCount;
663 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
664 			0u,													// deUint32							pushConstantRangeCount;
665 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
666 		};
667 
668 		m_pipelineLayoutSubpass1 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
669 	}
670 
671 	// Update descriptor set
672 	{
673 		const VkDescriptorPoolSize			descriptorPoolSize			=
674         {
675 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		type;
676 			1u										// deUint32				descriptorCount;
677 		};
678 
679 		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
680 		{
681 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,		// VkStructureType				sType
682 			DE_NULL,											// const void*					pNext
683 			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	// VkDescriptorPoolCreateFlags	flags
684 			1u,                                                 // deUint32						maxSets
685 			1u,													// deUint32						poolSizeCount
686 			&descriptorPoolSize									// const VkDescriptorPoolSize*	pPoolSizes
687 		};
688 
689 		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
690 
691 		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
692 		{
693 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType
694 			DE_NULL,											// const void*						pNext
695 			*m_descriptorPool,									// VkDescriptorPool					descriptorPool
696 			1u,													// deUint32							descriptorSetCount
697 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts
698 		};
699 
700 		m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
701 
702 		const VkDescriptorImageInfo			inputImageInfo				=
703 		{
704 			DE_NULL,									// VkSampleri		sampler;
705 			*m_inputAttachmentView,						// VkImageView		imageView;
706 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
707 		};
708 
709 		const VkWriteDescriptorSet			descriptorWrite				=
710 		{
711 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
712 			DE_NULL,									// const void*						pNext;
713 			*m_descriptorSetSubpass1,					// VkDescriptorSet					dstSet;
714 			0u,											// deUint32							dstBinding;
715 			0u,											// deUint32							dstArrayElement;
716 			1u,											// deUint32							descriptorCount;
717 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		// VkDescriptorType					descriptorType;
718 			&inputImageInfo,							// const VkDescriptorImageInfo*		pImageInfo;
719 			DE_NULL,									// const VkDescriptorBufferInfo*	pBufferInfo;
720 			DE_NULL										// const VkBufferView*				pTexelBufferView;
721 		};
722 
723 		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
724 	}
725 
726 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
727 	m_fragmentShaderModuleSubpass0	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
728 	m_fragmentShaderModuleSubpass1	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
729 
730 	// Create pipelines
731 	{
732 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
733 		{
734 			0u,									// deUint32					binding;
735 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
736 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
737 		};
738 
739 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
740 		{
741 			{
742 				0u,								// deUint32		location;
743 				0u,								// deUint32		binding;
744 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
745 				0u								// deUint32		offset;
746 			},
747 			{
748 				1u,								// deUint32		location;
749 				0u,								// deUint32		binding;
750 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
751 				(deUint32)(sizeof(float) * 4),	// deUint32		offset;
752 			}
753 		};
754 
755 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
756 		{
757 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
758 			DE_NULL,													// const void*								pNext;
759 			0u,															// VkPipelineVertexInputStateCreateFlags	flags;
760 			1u,															// deUint32									vertexBindingDescriptionCount;
761 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
762 			2u,															// deUint32									vertexAttributeDescriptionCount;
763 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
764 		};
765 
766 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
767 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
768 
769 		{
770 			m_graphicsPipelineSubpass0 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
771 															  vkDevice,								// const VkDevice								device
772 															  *m_pipelineLayoutSubpass0,			// const VkPipelineLayout						pipelineLayout
773 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
774 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
775 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
776 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
777 															  *m_fragmentShaderModuleSubpass0,		// const VkShaderModule							fragmentShaderModule
778 															  *m_renderPass,						// const VkRenderPass							renderPass
779 															  viewports,							// const std::vector<VkViewport>&				viewports
780 															  scissors,								// const std::vector<VkRect2D>&					scissors
781 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
782 															  0u,									// const deUint32								subpass
783 															  0u,									// const deUint32								patchControlPoints
784 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
785 
786 			m_graphicsPipelineSubpass1 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
787 															  vkDevice,								// const VkDevice								device
788 															  *m_pipelineLayoutSubpass1,			// const VkPipelineLayout						pipelineLayout
789 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
790 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
791 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
792 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
793 															  *m_fragmentShaderModuleSubpass1,		// const VkShaderModule							fragmentShaderModule
794 															  *m_renderPass,						// const VkRenderPass							renderPass
795 															  viewports,							// const std::vector<VkViewport>&				viewports
796 															  scissors,								// const std::vector<VkRect2D>&					scissors
797 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
798 															  1u,									// const deUint32								subpass
799 															  0u,									// const deUint32								patchControlPoints
800 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
801 		}
802 	}
803 
804 	// Create vertex buffer
805 	{
806 		const VkBufferCreateInfo vertexBufferParams =
807 		{
808 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
809 			DE_NULL,													// const void*			pNext;
810 			0u,															// VkBufferCreateFlags	flags;
811 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
812 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
813 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
814 			1u,															// deUint32				queueFamilyIndexCount;
815 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
816 		};
817 
818 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
819 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
820 
821 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
822 
823 		// Upload vertex data
824 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
825 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
826 	}
827 
828 	// Create command pool
829 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
830 
831 	// Create command buffer
832 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
833 		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
834 	else
835 		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
836 }
837 
~UnusedAttachmentTestInstance(void)838 UnusedAttachmentTestInstance::~UnusedAttachmentTestInstance (void)
839 {
840 }
841 
842 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)843 void UnusedAttachmentTestInstance::createCommandBuffer (const DeviceInterface&	vk,
844 														VkDevice				vkDevice)
845 {
846 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
847 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
848 
849 	const VkClearValue attachmentClearValues[] =
850 	{
851 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// color
852 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// unused
853 		makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f)	// input
854 	};
855 
856 	const VkDeviceSize vertexBufferOffset = 0;
857 
858 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
859 
860 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
861 
862 	const VkRenderPassBeginInfo renderPassBeginInfo =
863 	{
864 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
865 		DE_NULL,									// const void*			pNext;
866 		*m_renderPass,								// VkRenderPass			renderPass;
867 		*m_framebuffer,								// VkFramebuffer		framebuffer;
868 		makeRect2D(m_renderSize),					// VkRect2D				renderArea;
869 		3u,											// uint32_t				clearValueCount;
870 		attachmentClearValues						// const VkClearValue*	pClearValues;
871 	};
872 	RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
873 
874 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass0);
875 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
876 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
877 	vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
878 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass1);
879 	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1, &m_descriptorSetSubpass1.get(), 0, DE_NULL);
880 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
881 
882 	RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
883 	endCommandBuffer(vk, *m_cmdBuffer);
884 }
885 
iterate(void)886 tcu::TestStatus UnusedAttachmentTestInstance::iterate (void)
887 {
888 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
889 	const VkDevice				vkDevice	= m_context.getDevice();
890 	const VkQueue				queue		= m_context.getUniversalQueue();
891 
892 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
893 
894 	return verifyImage();
895 }
896 
verifyImage(void)897 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage (void)
898 {
899 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
900 	const VkDevice						vkDevice				= m_context.getDevice();
901 	const VkQueue						queue					= m_context.getUniversalQueue();
902 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
903 	SimpleAllocator						allocator				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
904 	de::UniquePtr<tcu::TextureLevel>	textureLevelResult		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
905 	const tcu::ConstPixelBufferAccess&	resultAccess			= textureLevelResult->getAccess();
906 	de::UniquePtr<tcu::TextureLevel>	textureLevelUnused		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
907 	const tcu::ConstPixelBufferAccess&	unusedAccess			= textureLevelUnused->getAccess();
908 	tcu::TestLog&						log						= m_context.getTestContext().getLog();
909 
910 	// Log images
911 	log << tcu::TestLog::ImageSet("Result", "Result images")
912 		<< tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
913 		<< tcu::TestLog::Image("Unused", "Unused image", unusedAccess)
914 		<< tcu::TestLog::EndImageSet;
915 
916 	// Check the unused image data hasn't changed.
917 	for (int y = 0; y < unusedAccess.getHeight(); y++)
918 		for (int x = 0; x < unusedAccess.getWidth(); x++)
919 		{
920 			const tcu::Vec4 color = unusedAccess.getPixel(x, y);
921 			const tcu::Vec4 refColor = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
922 			for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
923 				if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
924 					return tcu::TestStatus::fail("Unused image contents has changed.");
925 		}
926 
927 	// Check for rendered result. Just a quick sanity check to see if correct color is found at the center of the quad.
928 	const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
929 	const tcu::Vec4 refColor = tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f);
930 	for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
931 		if (de::abs(resultColor[cpnt] - refColor[cpnt]) > 0.01f)
932 			return tcu::TestStatus::fail("Result image mismatch");
933 
934 	return tcu::TestStatus::pass("Pass");
935 }
936 
loadOpToString(VkAttachmentLoadOp loadOp)937 std::string loadOpToString (VkAttachmentLoadOp loadOp)
938 {
939 	switch (loadOp)
940 	{
941 		case VK_ATTACHMENT_LOAD_OP_LOAD:
942 			return "load";
943 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
944 			return "clear";
945 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
946 			return "dontcare";
947 		default:
948 			DE_FATAL("unexpected attachment load op");
949 			return "";
950 	};
951 }
952 
storeOpToString(VkAttachmentStoreOp storeOp)953 std::string storeOpToString (VkAttachmentStoreOp storeOp)
954 {
955 	switch (storeOp)
956 	{
957 		case VK_ATTACHMENT_STORE_OP_STORE:
958 			return "store";
959 		case VK_ATTACHMENT_STORE_OP_DONT_CARE:
960 			return "dontcare";
961 		default:
962 			DE_FATAL("unexpected attachment store op");
963 			return "";
964 	};
965 }
966 
967 } // anonymous
968 
createRenderPassUnusedAttachmentTests(tcu::TestContext & testCtx,const RenderPassType renderPassType)969 tcu::TestCaseGroup* createRenderPassUnusedAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
970 {
971 	de::MovePtr<tcu::TestCaseGroup>		unusedAttTests		(new tcu::TestCaseGroup(testCtx, "unused_attachment", "Unused attachment tests"));
972 
973 	const VkAttachmentLoadOp			loadOps[]			=
974 	{
975 		VK_ATTACHMENT_LOAD_OP_LOAD,
976 		VK_ATTACHMENT_LOAD_OP_CLEAR,
977 		VK_ATTACHMENT_LOAD_OP_DONT_CARE
978 	};
979 
980 	const VkAttachmentStoreOp			storeOps[]			=
981 	{
982 		VK_ATTACHMENT_STORE_OP_STORE,
983 		VK_ATTACHMENT_STORE_OP_DONT_CARE
984 	};
985 
986 	for (deUint32 loadOpIdx = 0; loadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); loadOpIdx++)
987 	{
988 		de::MovePtr<tcu::TestCaseGroup>	loadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("loadop") + loadOpToString(loadOps[loadOpIdx])).c_str(), ""));
989 
990 		for (deUint32 storeOpIdx = 0; storeOpIdx < DE_LENGTH_OF_ARRAY(storeOps); storeOpIdx++)
991 		{
992 			de::MovePtr<tcu::TestCaseGroup>	storeOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("storeop") + storeOpToString(storeOps[storeOpIdx])).c_str(), ""));
993 
994 			for (deUint32 stencilLoadOpIdx = 0; stencilLoadOpIdx < DE_LENGTH_OF_ARRAY(loadOps); stencilLoadOpIdx++)
995 			{
996 				de::MovePtr<tcu::TestCaseGroup>	stencilLoadOpGroup(new tcu::TestCaseGroup(testCtx, (std::string("stencilloadop") + loadOpToString(loadOps[stencilLoadOpIdx])).c_str(), ""));
997 
998 				for (deUint32 stencilStoreOpIdx = 0; stencilStoreOpIdx < DE_LENGTH_OF_ARRAY(storeOps); stencilStoreOpIdx++)
999 				{
1000 					TestParams			params;
1001 					const std::string	testName = std::string("stencilstoreop") + storeOpToString(storeOps[stencilStoreOpIdx]);
1002 
1003 					params.loadOp			= loadOps[loadOpIdx];
1004 					params.storeOp			= storeOps[storeOpIdx];
1005 					params.stencilLoadOp	= loadOps[stencilLoadOpIdx];
1006 					params.stencilStoreOp	= storeOps[stencilStoreOpIdx];
1007 					params.renderPassType	= renderPassType;
1008 
1009 					stencilLoadOpGroup->addChild(new UnusedAttachmentTest(testCtx, testName, "", params));
1010 				}
1011 				storeOpGroup->addChild(stencilLoadOpGroup.release());
1012 			}
1013 			loadOpGroup->addChild(storeOpGroup.release());
1014 		}
1015 		unusedAttTests->addChild(loadOpGroup.release());
1016 	}
1017 
1018 	return unusedAttTests.release();
1019 }
1020 
1021 } // renderpass
1022 } // vkt
1023