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