• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 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 TestParams & testParams)297 UnusedAttachmentTest::UnusedAttachmentTest (tcu::TestContext&	testContext,
298 											const std::string&	name,
299 											const TestParams&	testParams)
300 	: vkt::TestCase	(testContext, name)
301 	, m_testParams	(testParams)
302 {
303 }
304 
~UnusedAttachmentTest(void)305 UnusedAttachmentTest::~UnusedAttachmentTest (void)
306 {
307 }
308 
createInstance(Context & context) const309 TestInstance* UnusedAttachmentTest::createInstance (Context& context) const
310 {
311 	return new UnusedAttachmentTestInstance(context, m_testParams);
312 }
313 
initPrograms(SourceCollections & sourceCollections) const314 void UnusedAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
315 {
316 	std::ostringstream fragmentSource;
317 
318 	sourceCollections.glslSources.add("color_vert") << glu::VertexSource(
319 		"#version 450\n"
320 		"layout(location = 0) in highp vec4 position;\n"
321 		"layout(location = 1) in highp vec4 color;\n"
322 		"layout(location = 0) out highp vec4 vtxColor;\n"
323 		"void main (void)\n"
324 		"{\n"
325 		"	gl_Position = position;\n"
326 		"	vtxColor = color;\n"
327 		"}\n");
328 
329 	sourceCollections.glslSources.add("color_frag_sb0") << glu::FragmentSource(
330 		"#version 450\n"
331 		"layout(location = 0) in highp vec4 vtxColor;\n"
332 		"layout(location = 0) out highp vec4 fragColor;\n"
333 		"void main (void)\n"
334 		"{\n"
335 		"	fragColor = vtxColor;\n"
336 		"}\n");
337 
338 	sourceCollections.glslSources.add("color_frag_sb1") << glu::FragmentSource(
339 		"#version 450\n"
340 		"layout(location = 0) in highp vec4 vtxColor;\n"
341 		"layout(location = 0) out highp vec4 fragColor;\n"
342 		"layout(input_attachment_index = 0, set = 0, binding = 0) uniform subpassInput inputColor;"
343 		"void main (void)\n"
344 		"{\n"
345 		"	fragColor = subpassLoad(inputColor) + vtxColor;\n"
346 		"}\n");
347 }
348 
UnusedAttachmentTestInstance(Context & context,const TestParams & testParams)349 UnusedAttachmentTestInstance::UnusedAttachmentTestInstance (Context&			context,
350 															const TestParams&	testParams)
351 	: vkt::TestInstance	(context)
352 	, m_renderSize		(32u, 32u)
353 	, m_vertices		(createQuad())
354 {
355 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
356 	const VkDevice				vkDevice				= m_context.getDevice();
357 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
358 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
359 	const VkComponentMapping	componentMappingRGBA	= { VK_COMPONENT_SWIZZLE_R, VK_COMPONENT_SWIZZLE_G, VK_COMPONENT_SWIZZLE_B, VK_COMPONENT_SWIZZLE_A };
360 
361 	// Check for renderpass2 extension if used
362 	if (testParams.renderingType == RENDERING_TYPE_RENDERPASS2)
363 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
364 
365 	// Create color image
366 	{
367 		const VkImageCreateInfo	colorImageParams =
368 		{
369 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
370 			DE_NULL,																	// const void*				pNext;
371 			0u,																			// VkImageCreateFlags		flags;
372 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
373 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
374 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
375 			1u,																			// deUint32					mipLevels;
376 			1u,																			// deUint32					arrayLayers;
377 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
378 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
379 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT,		// VkImageUsageFlags		usage;
380 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
381 			1u,																			// deUint32					queueFamilyIndexCount;
382 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
383 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
384 		};
385 
386 		m_colorImage			= createImage(vk, vkDevice, &colorImageParams);
387 
388 		// Allocate and bind color image memory
389 		m_colorImageAlloc		= memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImage), MemoryRequirement::Any);
390 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImage, m_colorImageAlloc->getMemory(), m_colorImageAlloc->getOffset()));
391 	}
392 
393 	// Create image which is not used by any subpass
394 	{
395 		const VkImageCreateInfo	unusedImageParams =
396 		{
397 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
398 			DE_NULL,																	// const void*				pNext;
399 			0u,																			// VkImageCreateFlags		flags;
400 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
401 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
402 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
403 			1u,																			// deUint32					mipLevels;
404 			1u,																			// deUint32					arrayLayers;
405 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
406 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
407 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
408 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT,										// VkImageUsageFlags		usage;
409 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
410 			1u,																			// deUint32					queueFamilyIndexCount;
411 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
412 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
413 		};
414 
415 		m_unusedImage			= createImage(vk, vkDevice, &unusedImageParams);
416 
417 		// Allocate and bind unused image memory
418 		VkMemoryRequirements	memoryRequirements	= getImageMemoryRequirements(vk, vkDevice, *m_unusedImage);
419 
420 		m_unusedImageAlloc		= memAlloc.allocate(memoryRequirements, MemoryRequirement::Any);
421 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_unusedImage, m_unusedImageAlloc->getMemory(), m_unusedImageAlloc->getOffset()));
422 
423 		// Clear image with specific value to verify the contents don't change
424 		{
425 			const VkImageAspectFlags		aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
426 			Move<VkCommandPool>				cmdPool;
427 			Move<VkCommandBuffer>			cmdBuffer;
428 
429 			VkClearValue					clearValue;
430 			clearValue.color.float32[0] = 0.1f;
431 			clearValue.color.float32[1] = 0.2f;
432 			clearValue.color.float32[2] = 0.3f;
433 			clearValue.color.float32[3] = 0.4f;
434 
435 			// Create command pool and buffer
436 			cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
437 			cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
438 
439 			const VkImageMemoryBarrier preImageBarrier =
440 			{
441 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
442 				DE_NULL,								// const void*				pNext;
443 				0u,										// VkAccessFlags			srcAccessMask;
444 				VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
445 				VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
446 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
447 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
448 				VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
449 				*m_unusedImage,							// VkImage					image;
450 				{										// VkImageSubresourceRange	subresourceRange;
451 					aspectMask,							// VkImageAspect			aspect;
452 					0u,									// deUint32					baseMipLevel;
453 					1u,									// deUint32					mipLevels;
454 					0u,									// deUint32					baseArraySlice;
455 					1u									// deUint32					arraySize;
456 				}
457 			};
458 
459 			const VkImageMemoryBarrier postImageBarrier =
460 			{
461 				VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
462 				DE_NULL,									// const void*				pNext;
463 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
464 				VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
465 				VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
466 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
467 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
468 				VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
469 				*m_unusedImage,								// VkImage					image;
470 				{											// VkImageSubresourceRange	subresourceRange;
471 					aspectMask,								// VkImageAspect			aspect;
472 					0u,										// deUint32					baseMipLevel;
473 					1u,										// deUint32					mipLevels;
474 					0u,										// deUint32					baseArraySlice;
475 					1u										// deUint32					arraySize;
476 				}
477 			};
478 
479 			const VkImageSubresourceRange clearRange	=
480 			{
481 				aspectMask,	// VkImageAspectFlags	aspectMask;
482 				0u,			// deUint32				baseMipLevel;
483 				1u,			// deUint32				levelCount;
484 				0u,			// deUint32				baseArrayLayer;
485 				1u			// deUint32				layerCount;
486 			};
487 
488 			// Clear image
489 			beginCommandBuffer(vk, *cmdBuffer);
490 			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);
491 			vk.cmdClearColorImage(*cmdBuffer, *m_unusedImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &clearValue.color, 1, &clearRange);
492 			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);
493 			endCommandBuffer(vk, *cmdBuffer);
494 
495 			submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
496 		}
497 	}
498 
499 	// Create input image
500 	{
501 		const VkImageCreateInfo	inputImageParams =
502 		{
503 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,										// VkStructureType			sType;
504 			DE_NULL,																	// const void*				pNext;
505 			0u,																			// VkImageCreateFlags		flags;
506 			VK_IMAGE_TYPE_2D,															// VkImageType				imageType;
507 			VK_FORMAT_R8G8B8A8_UNORM,													// VkFormat					format;
508 			{ m_renderSize.x(), m_renderSize.y(), 1u },									// VkExtent3D				extent;
509 			1u,																			// deUint32					mipLevels;
510 			1u,																			// deUint32					arrayLayers;
511 			VK_SAMPLE_COUNT_1_BIT,														// VkSampleCountFlagBits	samples;
512 			VK_IMAGE_TILING_OPTIMAL,													// VkImageTiling			tiling;
513 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_INPUT_ATTACHMENT_BIT,	// VkImageUsageFlags		usage;
514 			VK_SHARING_MODE_EXCLUSIVE,													// VkSharingMode			sharingMode;
515 			1u,																			// deUint32					queueFamilyIndexCount;
516 			&queueFamilyIndex,															// const deUint32*			pQueueFamilyIndices;
517 			VK_IMAGE_LAYOUT_UNDEFINED													// VkImageLayout			initialLayout;
518 		};
519 
520 		m_inputImage = createImage(vk, vkDevice, &inputImageParams);
521 
522 		// Allocate and bind input image memory
523 		m_inputImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_inputImage), MemoryRequirement::Any);
524 		VK_CHECK(vk.bindImageMemory(vkDevice, *m_inputImage, m_inputImageAlloc->getMemory(), m_inputImageAlloc->getOffset()));
525 	}
526 
527 	// Create color attachment view
528 	{
529 		const VkImageViewCreateInfo colorAttachmentViewParams =
530 		{
531 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
532 			DE_NULL,											// const void*				pNext;
533 			0u,													// VkImageViewCreateFlags	flags;
534 			*m_colorImage,										// VkImage					image;
535 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
536 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
537 			componentMappingRGBA,								// VkChannelMapping			channels;
538 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
539 		};
540 
541 		m_colorAttachmentView = createImageView(vk, vkDevice, &colorAttachmentViewParams);
542 	}
543 
544 	// Create unused attachment view
545 	{
546 		const VkImageViewCreateInfo unusedAttachmentViewParams =
547 		{
548 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
549 			DE_NULL,											// const void*				pNext;
550 			0u,													// VkImageViewCreateFlags	flags;
551 			*m_unusedImage,										// VkImage					image;
552 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
553 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
554 			componentMappingRGBA,								// VkChannelMapping			channels;
555 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
556 		};
557 
558 		m_unusedAttachmentView = createImageView(vk, vkDevice, &unusedAttachmentViewParams);
559 	}
560 
561 	// Create input attachment view
562 	{
563 		const VkImageViewCreateInfo inputAttachmentViewParams =
564 		{
565 			VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
566 			DE_NULL,											// const void*				pNext;
567 			0u,													// VkImageViewCreateFlags	flags;
568 			*m_inputImage,										// VkImage					image;
569 			VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
570 			VK_FORMAT_R8G8B8A8_UNORM,							// VkFormat					format;
571 			componentMappingRGBA,								// VkChannelMapping			channels;
572 			{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
573 		};
574 
575 		m_inputAttachmentView = createImageView(vk, vkDevice, &inputAttachmentViewParams);
576 	}
577 
578 	// Create render pass
579 	if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
580 		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
581 	else
582 		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
583 
584 	// Create framebuffer
585 	{
586 		const VkImageView				imageViews[]		=
587 		{
588 			*m_colorAttachmentView,
589 			*m_unusedAttachmentView,
590 			*m_inputAttachmentView
591 		};
592 
593 		const VkFramebufferCreateInfo	framebufferParams	=
594 		{
595 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,	// VkStructureType			sType;
596 			DE_NULL,									// const void*				pNext;
597 			0u,											// VkFramebufferCreateFlags	flags;
598 			*m_renderPass,								// VkRenderPass				renderPass;
599 			3u,											// deUint32					attachmentCount;
600 			imageViews,									// const VkImageView*		pAttachments;
601 			(deUint32)m_renderSize.x(),					// deUint32					width;
602 			(deUint32)m_renderSize.y(),					// deUint32					height;
603 			1u											// deUint32					layers;
604 		};
605 
606 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
607 	}
608 
609 	// Create pipeline layout for subpass 0
610 	{
611 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
612 		{
613 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
614 			DE_NULL,												// const void*							pNext
615 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
616 			0u,														// deUint32								bindingCount
617 			DE_NULL													// const VkDescriptorSetLayoutBinding*	pBindings
618 		};
619 		m_descriptorSetLayoutSubpass0 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
620 
621 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
622 		{
623 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
624 			DE_NULL,											// const void*						pNext;
625 			0u,													// VkPipelineLayoutCreateFlags		flags;
626 			1u,													// deUint32							setLayoutCount;
627 			&m_descriptorSetLayoutSubpass0.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
628 			0u,													// deUint32							pushConstantRangeCount;
629 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
630 		};
631 
632 		m_pipelineLayoutSubpass0 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
633 	}
634 
635 	// Create pipeline layout for subpass 1
636 	{
637 		const VkDescriptorSetLayoutBinding		layoutBinding				=
638 		{
639 			0u,										// deUint32				binding;
640 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		descriptorType;
641 			1u,										// deUint32				descriptorCount;
642 			VK_SHADER_STAGE_FRAGMENT_BIT,			// VkShaderStageFlags	stageFlags;
643 			DE_NULL									// const VkSampler*		pImmutableSamplers;
644 		};
645 
646 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
647 		{
648 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
649 			DE_NULL,												// const void*							pNext
650 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
651 			1u,														// deUint32								bindingCount
652 			&layoutBinding											// const VkDescriptorSetLayoutBinding*	pBindings
653 		};
654 		m_descriptorSetLayoutSubpass1 = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
655 
656 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
657 		{
658 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
659 			DE_NULL,											// const void*						pNext;
660 			0u,													// VkPipelineLayoutCreateFlags		flags;
661 			1u,													// deUint32							setLayoutCount;
662 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts;
663 			0u,													// deUint32							pushConstantRangeCount;
664 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
665 		};
666 
667 		m_pipelineLayoutSubpass1 = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
668 	}
669 
670 	// Update descriptor set
671 	{
672 		const VkDescriptorPoolSize			descriptorPoolSize			=
673         {
674 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,	// VkDescriptorType		type;
675 			1u										// deUint32				descriptorCount;
676 		};
677 
678 		const VkDescriptorPoolCreateInfo	descriptorPoolCreateInfo	=
679 		{
680 			VK_STRUCTURE_TYPE_DESCRIPTOR_POOL_CREATE_INFO,		// VkStructureType				sType
681 			DE_NULL,											// const void*					pNext
682 			VK_DESCRIPTOR_POOL_CREATE_FREE_DESCRIPTOR_SET_BIT,	// VkDescriptorPoolCreateFlags	flags
683 			1u,                                                 // deUint32						maxSets
684 			1u,													// deUint32						poolSizeCount
685 			&descriptorPoolSize									// const VkDescriptorPoolSize*	pPoolSizes
686 		};
687 
688 		m_descriptorPool = createDescriptorPool(vk, vkDevice, &descriptorPoolCreateInfo);
689 
690 		const VkDescriptorSetAllocateInfo	descriptorSetAllocateInfo	=
691 		{
692 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_ALLOCATE_INFO,		// VkStructureType					sType
693 			DE_NULL,											// const void*						pNext
694 			*m_descriptorPool,									// VkDescriptorPool					descriptorPool
695 			1u,													// deUint32							descriptorSetCount
696 			&m_descriptorSetLayoutSubpass1.get(),				// const VkDescriptorSetLayout*		pSetLayouts
697 		};
698 
699 		m_descriptorSetSubpass1 = allocateDescriptorSet(vk, vkDevice, &descriptorSetAllocateInfo);
700 
701 		const VkDescriptorImageInfo			inputImageInfo				=
702 		{
703 			DE_NULL,									// VkSampleri		sampler;
704 			*m_inputAttachmentView,						// VkImageView		imageView;
705 			VK_IMAGE_LAYOUT_SHADER_READ_ONLY_OPTIMAL	// VkImageLayout	imageLayout;
706 		};
707 
708 		const VkWriteDescriptorSet			descriptorWrite				=
709 		{
710 			VK_STRUCTURE_TYPE_WRITE_DESCRIPTOR_SET,		// VkStructureType					sType;
711 			DE_NULL,									// const void*						pNext;
712 			*m_descriptorSetSubpass1,					// VkDescriptorSet					dstSet;
713 			0u,											// deUint32							dstBinding;
714 			0u,											// deUint32							dstArrayElement;
715 			1u,											// deUint32							descriptorCount;
716 			VK_DESCRIPTOR_TYPE_INPUT_ATTACHMENT,		// VkDescriptorType					descriptorType;
717 			&inputImageInfo,							// const VkDescriptorImageInfo*		pImageInfo;
718 			DE_NULL,									// const VkDescriptorBufferInfo*	pBufferInfo;
719 			DE_NULL										// const VkBufferView*				pTexelBufferView;
720 		};
721 
722 		vk.updateDescriptorSets(vkDevice, 1u, &descriptorWrite, 0u, DE_NULL);
723 	}
724 
725 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_vert"), 0);
726 	m_fragmentShaderModuleSubpass0	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb0"), 0);
727 	m_fragmentShaderModuleSubpass1	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("color_frag_sb1"), 0);
728 
729 	// Create pipelines
730 	{
731 		const VkVertexInputBindingDescription		vertexInputBindingDescription		=
732 		{
733 			0u,									// deUint32					binding;
734 			sizeof(Vertex4RGBA),				// deUint32					strideInBytes;
735 			VK_VERTEX_INPUT_RATE_VERTEX			// VkVertexInputStepRate	inputRate;
736 		};
737 
738 		const VkVertexInputAttributeDescription		vertexInputAttributeDescriptions[2]	=
739 		{
740 			{
741 				0u,								// deUint32		location;
742 				0u,								// deUint32		binding;
743 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
744 				0u								// deUint32		offset;
745 			},
746 			{
747 				1u,								// deUint32		location;
748 				0u,								// deUint32		binding;
749 				VK_FORMAT_R32G32B32A32_SFLOAT,	// VkFormat		format;
750 				(deUint32)(sizeof(float) * 4),	// deUint32		offset;
751 			}
752 		};
753 
754 		const VkPipelineVertexInputStateCreateInfo	vertexInputStateParams				=
755 		{
756 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType;
757 			DE_NULL,													// const void*								pNext;
758 			0u,															// VkPipelineVertexInputStateCreateFlags	flags;
759 			1u,															// deUint32									vertexBindingDescriptionCount;
760 			&vertexInputBindingDescription,								// const VkVertexInputBindingDescription*	pVertexBindingDescriptions;
761 			2u,															// deUint32									vertexAttributeDescriptionCount;
762 			vertexInputAttributeDescriptions							// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions;
763 		};
764 
765 		const std::vector<VkViewport>				viewports							(1, makeViewport(m_renderSize));
766 		const std::vector<VkRect2D>					scissors							(1, makeRect2D(m_renderSize));
767 
768 		{
769 			m_graphicsPipelineSubpass0 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
770 															  vkDevice,								// const VkDevice								device
771 															  *m_pipelineLayoutSubpass0,			// const VkPipelineLayout						pipelineLayout
772 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
773 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
774 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
775 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
776 															  *m_fragmentShaderModuleSubpass0,		// const VkShaderModule							fragmentShaderModule
777 															  *m_renderPass,						// const VkRenderPass							renderPass
778 															  viewports,							// const std::vector<VkViewport>&				viewports
779 															  scissors,								// const std::vector<VkRect2D>&					scissors
780 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
781 															  0u,									// const deUint32								subpass
782 															  0u,									// const deUint32								patchControlPoints
783 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
784 
785 			m_graphicsPipelineSubpass1 = makeGraphicsPipeline(vk,									// const DeviceInterface&						vk
786 															  vkDevice,								// const VkDevice								device
787 															  *m_pipelineLayoutSubpass1,			// const VkPipelineLayout						pipelineLayout
788 															  *m_vertexShaderModule,				// const VkShaderModule							vertexShaderModule
789 															  DE_NULL,								// const VkShaderModule							tessellationControlModule
790 															  DE_NULL,								// const VkShaderModule							tessellationEvalModule
791 															  DE_NULL,								// const VkShaderModule							geometryShaderModule
792 															  *m_fragmentShaderModuleSubpass1,		// const VkShaderModule							fragmentShaderModule
793 															  *m_renderPass,						// const VkRenderPass							renderPass
794 															  viewports,							// const std::vector<VkViewport>&				viewports
795 															  scissors,								// const std::vector<VkRect2D>&					scissors
796 															  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology					topology
797 															  1u,									// const deUint32								subpass
798 															  0u,									// const deUint32								patchControlPoints
799 															  &vertexInputStateParams);				// const VkPipelineVertexInputStateCreateInfo*	vertexInputStateCreateInfo
800 		}
801 	}
802 
803 	// Create vertex buffer
804 	{
805 		const VkBufferCreateInfo vertexBufferParams =
806 		{
807 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,						// VkStructureType		sType;
808 			DE_NULL,													// const void*			pNext;
809 			0u,															// VkBufferCreateFlags	flags;
810 			(VkDeviceSize)(sizeof(Vertex4RGBA) * m_vertices.size()),	// VkDeviceSize			size;
811 			VK_BUFFER_USAGE_VERTEX_BUFFER_BIT,							// VkBufferUsageFlags	usage;
812 			VK_SHARING_MODE_EXCLUSIVE,									// VkSharingMode		sharingMode;
813 			1u,															// deUint32				queueFamilyIndexCount;
814 			&queueFamilyIndex											// const deUint32*		pQueueFamilyIndices;
815 		};
816 
817 		m_vertexBuffer		= createBuffer(vk, vkDevice, &vertexBufferParams);
818 		m_vertexBufferAlloc	= memAlloc.allocate(getBufferMemoryRequirements(vk, vkDevice, *m_vertexBuffer), MemoryRequirement::HostVisible);
819 
820 		VK_CHECK(vk.bindBufferMemory(vkDevice, *m_vertexBuffer, m_vertexBufferAlloc->getMemory(), m_vertexBufferAlloc->getOffset()));
821 
822 		// Upload vertex data
823 		deMemcpy(m_vertexBufferAlloc->getHostPtr(), m_vertices.data(), m_vertices.size() * sizeof(Vertex4RGBA));
824 		flushAlloc(vk, vkDevice, *m_vertexBufferAlloc);
825 	}
826 
827 	// Create command pool
828 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
829 
830 	// Create command buffer
831 	if (testParams.renderingType == RENDERING_TYPE_RENDERPASS_LEGACY)
832 		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
833 	else
834 		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
835 }
836 
~UnusedAttachmentTestInstance(void)837 UnusedAttachmentTestInstance::~UnusedAttachmentTestInstance (void)
838 {
839 }
840 
841 template<typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)842 void UnusedAttachmentTestInstance::createCommandBuffer (const DeviceInterface&	vk,
843 														VkDevice				vkDevice)
844 {
845 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
846 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
847 
848 	const VkClearValue attachmentClearValues[] =
849 	{
850 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// color
851 		makeClearValueColorF32(0.5f, 0.5f, 0.5f, 1.0f),	// unused
852 		makeClearValueColorF32(0.5f, 0.2f, 0.1f, 1.0f)	// input
853 	};
854 
855 	const VkDeviceSize vertexBufferOffset = 0;
856 
857 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
858 
859 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
860 
861 	const VkRenderPassBeginInfo renderPassBeginInfo =
862 	{
863 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
864 		DE_NULL,									// const void*			pNext;
865 		*m_renderPass,								// VkRenderPass			renderPass;
866 		*m_framebuffer,								// VkFramebuffer		framebuffer;
867 		makeRect2D(m_renderSize),					// VkRect2D				renderArea;
868 		3u,											// uint32_t				clearValueCount;
869 		attachmentClearValues						// const VkClearValue*	pClearValues;
870 	};
871 	RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
872 
873 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass0);
874 	vk.cmdBindVertexBuffers(*m_cmdBuffer, 0, 1, &m_vertexBuffer.get(), &vertexBufferOffset);
875 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
876 	vk.cmdNextSubpass(*m_cmdBuffer, VK_SUBPASS_CONTENTS_INLINE);
877 	vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipelineSubpass1);
878 	vk.cmdBindDescriptorSets(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipelineLayoutSubpass1, 0, 1, &m_descriptorSetSubpass1.get(), 0, DE_NULL);
879 	vk.cmdDraw(*m_cmdBuffer, (deUint32)m_vertices.size(), 1, 0, 0);
880 
881 	RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
882 	endCommandBuffer(vk, *m_cmdBuffer);
883 }
884 
iterate(void)885 tcu::TestStatus UnusedAttachmentTestInstance::iterate (void)
886 {
887 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
888 	const VkDevice				vkDevice	= m_context.getDevice();
889 	const VkQueue				queue		= m_context.getUniversalQueue();
890 
891 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
892 
893 	return verifyImage();
894 }
895 
verifyImage(void)896 tcu::TestStatus UnusedAttachmentTestInstance::verifyImage (void)
897 {
898 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
899 	const VkDevice						vkDevice				= m_context.getDevice();
900 	const VkQueue						queue					= m_context.getUniversalQueue();
901 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
902 	SimpleAllocator						allocator				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
903 	de::UniquePtr<tcu::TextureLevel>	textureLevelResult		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
904 	const tcu::ConstPixelBufferAccess&	resultAccess			= textureLevelResult->getAccess();
905 	de::UniquePtr<tcu::TextureLevel>	textureLevelUnused		(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_unusedImage, VK_FORMAT_R8G8B8A8_UNORM, m_renderSize).release());
906 	const tcu::ConstPixelBufferAccess&	unusedAccess			= textureLevelUnused->getAccess();
907 	tcu::TestLog&						log						= m_context.getTestContext().getLog();
908 
909 	// Log images
910 	log << tcu::TestLog::ImageSet("Result", "Result images")
911 		<< tcu::TestLog::Image("Rendered", "Rendered image", resultAccess)
912 		<< tcu::TestLog::Image("Unused", "Unused image", unusedAccess)
913 		<< tcu::TestLog::EndImageSet;
914 
915 	// Check the unused image data hasn't changed.
916 	for (int y = 0; y < unusedAccess.getHeight(); y++)
917 		for (int x = 0; x < unusedAccess.getWidth(); x++)
918 		{
919 			const tcu::Vec4 color = unusedAccess.getPixel(x, y);
920 			const tcu::Vec4 refColor = tcu::Vec4(0.1f, 0.2f, 0.3f, 0.4f);
921 			for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
922 				if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
923 					return tcu::TestStatus::fail("Unused image contents has changed.");
924 		}
925 
926 	// Check for rendered result. Just a quick check to see if correct color is found at the center of the quad.
927 	const tcu::Vec4 resultColor = resultAccess.getPixel(resultAccess.getWidth() / 2, resultAccess.getHeight() / 2);
928 	const tcu::Vec4 refColor = tcu::Vec4(0.4f, 0.6f, 0.2f, 1.0f);
929 	for (deUint32 cpnt = 0; cpnt < 4; cpnt++)
930 		if (de::abs(resultColor[cpnt] - refColor[cpnt]) > 0.01f)
931 			return tcu::TestStatus::fail("Result image mismatch");
932 
933 	return tcu::TestStatus::pass("Pass");
934 }
935 
loadOpToString(VkAttachmentLoadOp loadOp)936 std::string loadOpToString (VkAttachmentLoadOp loadOp)
937 {
938 	switch (loadOp)
939 	{
940 		case VK_ATTACHMENT_LOAD_OP_LOAD:
941 			return "load";
942 		case VK_ATTACHMENT_LOAD_OP_CLEAR:
943 			return "clear";
944 		case VK_ATTACHMENT_LOAD_OP_DONT_CARE:
945 			return "dontcare";
946 		default:
947 			DE_FATAL("unexpected attachment load op");
948 			return "";
949 	}
950 }
951 
storeOpToString(VkAttachmentStoreOp storeOp)952 std::string storeOpToString (VkAttachmentStoreOp storeOp)
953 {
954 	switch (storeOp)
955 	{
956 		case VK_ATTACHMENT_STORE_OP_STORE:
957 			return "store";
958 		case VK_ATTACHMENT_STORE_OP_DONT_CARE:
959 			return "dontcare";
960 		default:
961 			DE_FATAL("unexpected attachment store op");
962 			return "";
963 	}
964 }
965 
966 } // anonymous
967 
createRenderPassUnusedAttachmentTests(tcu::TestContext & testCtx,const RenderingType renderingType)968 tcu::TestCaseGroup* createRenderPassUnusedAttachmentTests (tcu::TestContext& testCtx, const RenderingType renderingType)
969 {
970 	// Unused attachment tests
971 	de::MovePtr<tcu::TestCaseGroup>		unusedAttTests		(new tcu::TestCaseGroup(testCtx, "unused_attachment"));
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.renderingType	= renderingType;
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