1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Valve Corporation.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests vkCmdClearAttachments with unused attachments.
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRenderPassUnusedClearAttachmentTests.hpp"
26 #include "pipeline/vktPipelineImageUtil.hpp"
27 #include "vkQueryUtil.hpp"
28 #include "vkRefUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkImageUtil.hpp"
32 #include "tcuTextureUtil.hpp"
33 #include <sstream>
34 #include <functional>
35 #include <vector>
36 #include <string>
37 #include <memory>
38 
39 namespace vkt
40 {
41 namespace renderpass
42 {
43 
44 namespace
45 {
46 
47 constexpr size_t	COLOR_ATTACHMENTS_NUMBER	= 4; // maxColorAttachments is guaranteed to be at least 4.
48 constexpr VkFormat	FORMAT_COLOR				= VK_FORMAT_R8G8B8A8_UNORM;
49 constexpr VkFormat	FORMAT_DEPTH				= VK_FORMAT_D32_SFLOAT;
50 constexpr VkFormat	FORMAT_STENCIL				= VK_FORMAT_S8_UINT;
51 constexpr VkFormat	FORMAT_DEPTH_STENCIL		= VK_FORMAT_D32_SFLOAT_S8_UINT;
52 const deBool		DE_BOOL_VALUES[]			= { DE_FALSE, DE_TRUE };
53 
54 enum DepthStencilType
55 {
56 	DEPTH_STENCIL_NONE			= 0,
57 	DEPTH_STENCIL_DEPTH_ONLY	= 1,
58 	DEPTH_STENCIL_STENCIL_ONLY	= 2,
59 	DEPTH_STENCIL_BOTH			= 3,
60 	DEPTH_STENCIL_MAX_ENUM		= 4
61 };
62 
getFormatBriefName(VkFormat format)63 std::string getFormatBriefName (VkFormat format)
64 {
65 	switch (format)
66 	{
67 	case VK_FORMAT_D32_SFLOAT:			return "d32";
68 	case VK_FORMAT_S8_UINT:				return "s8";
69 	case VK_FORMAT_D32_SFLOAT_S8_UINT:	return "d32s8";
70 	default:								break;
71 	}
72 
73 	return "";
74 }
75 
depthStencilTypeName(DepthStencilType type,VkFormat format)76 std::string depthStencilTypeName (DepthStencilType type, VkFormat format)
77 {
78 	DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
79 
80 	const std::string formatName = getFormatBriefName(format);
81 
82 	switch (type)
83 	{
84 	case DEPTH_STENCIL_NONE:			return "nods";
85 	case DEPTH_STENCIL_DEPTH_ONLY:		return "depthonly_" + formatName;
86 	case DEPTH_STENCIL_STENCIL_ONLY:	return "stencilonly_" + formatName;
87 	case DEPTH_STENCIL_BOTH:			return "depthstencil_" + formatName;
88 	default:							return "UNKNOWN";		// Unreachable.
89 	}
90 
91 	return "UNKNOWN";											// Unreachable.
92 }
93 
getClearAspectMask(DepthStencilType type)94 VkImageAspectFlags getClearAspectMask (DepthStencilType type)
95 {
96 	VkImageAspectFlags aspectMask = 0u;
97 
98 	if (type == DEPTH_STENCIL_DEPTH_ONLY || type == DEPTH_STENCIL_BOTH)
99 		aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
100 
101 	if (type == DEPTH_STENCIL_STENCIL_ONLY || type == DEPTH_STENCIL_BOTH)
102 		aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
103 
104 	return aspectMask;
105 }
106 
getFormatAspectMask(VkFormat format)107 VkImageAspectFlags getFormatAspectMask (VkFormat format)
108 {
109 	const auto			order		= mapVkFormat(format).order;
110 	VkImageAspectFlags	aspectMask	= 0u;
111 
112 	if (tcu::hasDepthComponent(order))
113 		aspectMask |= VK_IMAGE_ASPECT_DEPTH_BIT;
114 
115 	if (tcu::hasStencilComponent(order))
116 		aspectMask |= VK_IMAGE_ASPECT_STENCIL_BIT;
117 
118 	if (!aspectMask)
119 		aspectMask |= VK_IMAGE_ASPECT_COLOR_BIT;
120 
121 	return aspectMask;
122 }
123 
getFormats(DepthStencilType type)124 std::vector<VkFormat> getFormats (DepthStencilType type)
125 {
126 	DE_ASSERT(type >= DEPTH_STENCIL_NONE && type < DEPTH_STENCIL_MAX_ENUM);
127 
128 	std::vector<VkFormat> formats;
129 
130 	if (type != DEPTH_STENCIL_NONE)
131 		formats.push_back(FORMAT_DEPTH_STENCIL);
132 	else
133 		formats.push_back(VK_FORMAT_UNDEFINED);
134 
135 	if (type == DEPTH_STENCIL_DEPTH_ONLY)
136 		formats.push_back(FORMAT_DEPTH);
137 	else if (type == DEPTH_STENCIL_STENCIL_ONLY)
138 		formats.push_back(FORMAT_STENCIL);
139 
140 	return formats;
141 }
142 
isDepthOnly(DepthStencilType type)143 bool isDepthOnly(DepthStencilType type)
144 {
145 	return (type == DEPTH_STENCIL_DEPTH_ONLY);
146 }
147 
isStencilOnly(DepthStencilType type)148 bool isStencilOnly(DepthStencilType type)
149 {
150 	return (type == DEPTH_STENCIL_STENCIL_ONLY);
151 }
152 
hasDepthStencil(DepthStencilType type)153 bool hasDepthStencil(DepthStencilType type)
154 {
155 	return (type != DEPTH_STENCIL_NONE);
156 }
157 
158 struct TestParams
159 {
TestParamsvkt::renderpass::__anon076e20c80111::TestParams160 	TestParams(size_t numColorAttachments, DepthStencilType depthStencilType_, deBool depthStencilUsed_, VkFormat depthStencilFormat_, RenderPassType renderPassType_)
161 		: colorUsed(numColorAttachments, DE_FALSE)
162 		, depthStencilType(depthStencilType_)
163 		, depthStencilUsed(depthStencilUsed_)
164 		, depthStencilFormat(depthStencilFormat_)
165 		, renderPassType(renderPassType_)
166 		{}
167 
168 	std::vector<deBool>	colorUsed;
169 	DepthStencilType	depthStencilType;
170 	deBool				depthStencilUsed;
171 	VkFormat		depthStencilFormat;
172 	RenderPassType		renderPassType;
173 };
174 
175 class UnusedClearAttachmentTestInstance : public vkt::TestInstance
176 {
177 public:
178 											UnusedClearAttachmentTestInstance	(Context&			context,
179 																				 const TestParams&	testParams);
~UnusedClearAttachmentTestInstance(void)180 	virtual									~UnusedClearAttachmentTestInstance	(void) {}
181 	virtual tcu::TestStatus					iterate								(void);
182 	template<typename RenderpassSubpass>
183 	void									createCommandBuffer					(const DeviceInterface&	vk,
184 																				 VkDevice				vkDevice);
185 private:
186 	static constexpr deUint32				kImageWidth		= 32;
187 	static constexpr deUint32				kImageHeight	= 32;
188 	const tcu::UVec2						m_renderSize	= { kImageWidth, kImageHeight };
189 
190 	VkClearValue							m_initialColor;
191 	VkClearValue							m_initialColorDepth;
192 	VkClearValue							m_clearColor;
193 	VkClearValue							m_clearColorDepth;
194 
195 	const TestParams						m_testParams;
196 
197 	std::vector<Move<VkImage>>				m_colorImages;
198 	std::vector<de::MovePtr<Allocation>>	m_colorImageAllocs;
199 	std::vector<Move<VkImageView>>			m_colorAttachmentViews;
200 
201 	Move<VkImage>							m_depthImage;
202 	de::MovePtr<Allocation>					m_depthImageAlloc;
203 	Move<VkImageView>						m_depthAttachmentView;
204 
205 	Move<VkRenderPass>						m_renderPass;
206 	Move<VkFramebuffer>						m_framebuffer;
207 	Move<VkShaderModule>					m_vertexShaderModule;
208 	Move<VkShaderModule>					m_fragmentShaderModule;
209 	Move<VkDescriptorSetLayout>				m_descriptorSetLayout;
210 	Move<VkPipelineLayout>					m_pipelineLayout;
211 	Move<VkPipeline>						m_graphicsPipeline;
212 	Move<VkCommandPool>						m_cmdPool;
213 	Move<VkCommandBuffer>					m_cmdBuffer;
214 };
215 
216 class UnusedClearAttachmentTest : public vkt::TestCase
217 {
218 public:
UnusedClearAttachmentTest(tcu::TestContext & testContext,const std::string & name,const std::string & description,const TestParams & testParams)219 										UnusedClearAttachmentTest	(tcu::TestContext&	testContext,
220 																	 const std::string&	name,
221 																	 const std::string&	description,
222 																	 const TestParams&	testParams)
223 											: vkt::TestCase(testContext, name, description)
224 											, m_testParams(testParams)
225 											{}
~UnusedClearAttachmentTest(void)226 	virtual								~UnusedClearAttachmentTest	(void) {}
227 	virtual void						initPrograms				(SourceCollections&	sourceCollections) const;
228 	virtual TestInstance*				createInstance				(Context&			context) const;
229 	virtual void						checkSupport				(Context&			context) const;
230 private:
231 	const TestParams					m_testParams;
232 };
233 
checkFormatSupported(Context & context,VkFormat format,VkImageUsageFlags usage)234 void checkFormatSupported(Context& context, VkFormat format, VkImageUsageFlags usage)
235 {
236 	VkResult					result;
237 	VkImageFormatProperties		properties;
238 
239 	result = context.getInstanceInterface().getPhysicalDeviceImageFormatProperties(
240 		context.getPhysicalDevice(), format, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, usage, 0, &properties);
241 
242 	if (result == VK_ERROR_FORMAT_NOT_SUPPORTED)
243 	{
244 		std::ostringstream msg;
245 		msg << "Format " << format << " not supported for usage flags 0x" << std::hex << usage;
246 		TCU_THROW(NotSupportedError, msg.str());
247 	}
248 
249 	VK_CHECK(result);
250 }
251 
checkSupport(Context & context) const252 void UnusedClearAttachmentTest::checkSupport (Context& context) const
253 {
254 	// Check for renderpass2 extension if used
255 	if (m_testParams.renderPassType == RENDERPASS_TYPE_RENDERPASS2)
256 		context.requireDeviceFunctionality("VK_KHR_create_renderpass2");
257 
258 	// Check support for the needed color, depth and stencil formats.
259 	if (!m_testParams.colorUsed.empty())
260 		checkFormatSupported(context, FORMAT_COLOR, VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT);
261 
262 	if (hasDepthStencil(m_testParams.depthStencilType))
263 		checkFormatSupported(context, m_testParams.depthStencilFormat, VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT);
264 }
265 
createInstance(Context & context) const266 TestInstance* UnusedClearAttachmentTest::createInstance (Context& context) const
267 {
268 	return new UnusedClearAttachmentTestInstance(context, m_testParams);
269 }
270 
271 // These shaders are needed to create the graphics pipeline, but they will not be actually used because we will not draw anything.
initPrograms(SourceCollections & sourceCollections) const272 void UnusedClearAttachmentTest::initPrograms (SourceCollections& sourceCollections) const
273 {
274 	// Vertex shader.
275 	sourceCollections.glslSources.add("vert_shader") << glu::VertexSource(
276 		"#version 450\n"
277 		"precision highp float;\n"
278 		"layout(location = 0) in vec4 position;\n"
279 		"layout(location = 0) out vec4 vtxColor;\n"
280 		"void main (void)\n"
281 		"{\n"
282 		"\tgl_Position = position;\n"
283 		"\tvtxColor = vec4(0.5, 0.5, 0.5, 1.0);\n"
284 		"}\n");
285 
286 	// Fragment shader.
287 	std::ostringstream fragmentSource;
288 
289 	fragmentSource	<< "#version 450\n"
290 					<< "precision highp float;\n"
291 					<< "layout(location = 0) in vec4 vtxColor;\n";
292 
293 	for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
294 	{
295 		if (m_testParams.colorUsed[i])
296 			fragmentSource << "layout(location = " << i << ") out vec4 fragColor" << i << ";\n";
297 	}
298 
299 	fragmentSource	<< "void main (void)\n"
300 					<< "{\n";
301 
302 	for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
303 	{
304 		if (m_testParams.colorUsed[i])
305 			fragmentSource << "\tfragColor" << i << " = vtxColor;\n";
306 	}
307 
308 	fragmentSource	<< "}\n";
309 
310 	sourceCollections.glslSources.add("frag_shader") << glu::FragmentSource(fragmentSource.str());
311 }
312 
313 // Create a render pass for this use case.
314 template<typename AttachmentDesc, typename AttachmentRef, typename SubpassDesc, typename SubpassDep, typename RenderPassCreateInfo>
createRenderPass(const DeviceInterface & vk,VkDevice vkDevice,const TestParams testParams)315 Move<VkRenderPass> createRenderPass (const DeviceInterface&	vk,
316 									 VkDevice				vkDevice,
317 									 const TestParams		testParams)
318 {
319 	const VkImageAspectFlags	colorAspectMask					= VK_IMAGE_ASPECT_COLOR_BIT;
320 	const VkImageAspectFlags	dsClearAspectMask				= getClearAspectMask(testParams.depthStencilType);
321 	const bool					isDepthStencil					= hasDepthStencil(testParams.depthStencilType);
322 
323 	// Create attachment descriptions.
324 	const AttachmentDesc		attachmentDescription			(
325 		DE_NULL,									// const void*						pNext
326 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags		flags
327 		FORMAT_COLOR,								// VkFormat							format
328 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples
329 		VK_ATTACHMENT_LOAD_OP_LOAD,					// VkAttachmentLoadOp				loadOp
330 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp
331 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp
332 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp
333 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
334 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
335 	);
336 	std::vector<AttachmentDesc>	attachmentDescriptions			(testParams.colorUsed.size(), attachmentDescription);
337 
338 	if (isDepthStencil)
339 	{
340 		const bool					depthOnly		= isDepthOnly(testParams.depthStencilType);
341 		const bool					stencilOnly		= isStencilOnly(testParams.depthStencilType);
342 		const VkAttachmentLoadOp	depthLoadOp		= (stencilOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
343 		const VkAttachmentStoreOp	depthStoreOp	= (stencilOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
344 		const VkAttachmentLoadOp	stencilLoadOp	= (depthOnly ? VK_ATTACHMENT_LOAD_OP_DONT_CARE : VK_ATTACHMENT_LOAD_OP_LOAD);
345 		const VkAttachmentStoreOp	stencilStoreOp	= (depthOnly ? VK_ATTACHMENT_STORE_OP_DONT_CARE : VK_ATTACHMENT_STORE_OP_STORE);
346 
347 		attachmentDescriptions.emplace_back(
348 			nullptr,											// const void*						pNext
349 			(VkAttachmentDescriptionFlags)0,					// VkAttachmentDescriptionFlags		flags
350 			testParams.depthStencilFormat,						// VkFormat							format
351 			VK_SAMPLE_COUNT_1_BIT,								// VkSampleCountFlagBits			samples
352 			depthLoadOp,										// VkAttachmentLoadOp				loadOp
353 			depthStoreOp,										// VkAttachmentStoreOp				storeOp
354 			stencilLoadOp,										// VkAttachmentLoadOp				stencilLoadOp
355 			stencilStoreOp,										// VkAttachmentStoreOp				stencilStoreOp
356 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout					initialLayout
357 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout
358 		);
359 	}
360 
361 	// Mark attachments as used or not depending on the test parameters.
362 	std::vector<AttachmentRef>		attachmentReferences;
363 	for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
364 	{
365 		attachmentReferences.push_back(AttachmentRef(
366 			DE_NULL,																		// const void*			pNext
367 			(testParams.colorUsed[i] ? static_cast<deUint32>(i) : VK_ATTACHMENT_UNUSED),	// deUint32				attachment
368 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,										// VkImageLayout		layout
369 			colorAspectMask																	// VkImageAspectFlags	aspectMask
370 		));
371 	}
372 
373 	std::unique_ptr<AttachmentRef>	depthAttachmentRef;
374 	if (isDepthStencil)
375 	{
376 		depthAttachmentRef.reset(new AttachmentRef(
377 			DE_NULL,
378 			(testParams.depthStencilUsed ? static_cast<deUint32>(testParams.colorUsed.size()) : VK_ATTACHMENT_UNUSED),
379 			VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,
380 			dsClearAspectMask
381 		));
382 	}
383 
384 	// Create subpass description with the previous color attachment references.
385 	const SubpassDesc			subpassDescription				(
386 		DE_NULL,
387 		(VkSubpassDescriptionFlags)0,											// VkSubpassDescriptionFlags		flags
388 		VK_PIPELINE_BIND_POINT_GRAPHICS,										// VkPipelineBindPoint				pipelineBindPoint
389 		0u,																		// deUint32							viewMask
390 		0u,																		// deUint32							inputAttachmentCount
391 		DE_NULL,																// const VkAttachmentReference*		pInputAttachments
392 		static_cast<deUint32>(attachmentReferences.size()),						// deUint32							colorAttachmentCount
393 		(attachmentReferences.empty() ? DE_NULL : attachmentReferences.data()),	// const VkAttachmentReference*		pColorAttachments
394 		DE_NULL,																// const VkAttachmentReference*		pResolveAttachments
395 		(depthAttachmentRef ? depthAttachmentRef.get() : DE_NULL),				// const VkAttachmentReference*		pDepthStencilAttachment
396 		0u,																		// deUint32							preserveAttachmentCount
397 		DE_NULL																	// const deUint32*					pPreserveAttachments
398 	);
399 
400 	const RenderPassCreateInfo	renderPassInfo					(
401 		DE_NULL,																	// const void*						pNext
402 		(VkRenderPassCreateFlags)0,													// VkRenderPassCreateFlags			flags
403 		static_cast<deUint32>(attachmentDescriptions.size()),						// deUint32							attachmentCount
404 		(attachmentDescriptions.empty() ? DE_NULL : attachmentDescriptions.data()),	// const VkAttachmentDescription*	pAttachments
405 		1u,																			// deUint32							subpassCount
406 		&subpassDescription,														// const VkSubpassDescription*		pSubpasses
407 		0u,																			// deUint32							dependencyCount
408 		DE_NULL,																	// const VkSubpassDependency*		pDependencies
409 		0u,																			// deUint32							correlatedViewMaskCount
410 		DE_NULL																		// const deUint32*					pCorrelatedViewMasks
411 	);
412 
413 	return renderPassInfo.createRenderPass(vk, vkDevice);
414 }
415 
UnusedClearAttachmentTestInstance(Context & context,const TestParams & testParams)416 UnusedClearAttachmentTestInstance::UnusedClearAttachmentTestInstance(Context&			context,
417 																	 const TestParams&	testParams)
418 	: vkt::TestInstance(context)
419 	, m_testParams(testParams)
420 {
421 	// Initial color for all images.
422 	m_initialColor.color.float32[0] = 0.0f;
423 	m_initialColor.color.float32[1] = 0.0f;
424 	m_initialColor.color.float32[2] = 0.0f;
425 	m_initialColor.color.float32[3] = 1.0f;
426 
427 	m_initialColorDepth.depthStencil.depth = 1.0f;
428 	m_initialColorDepth.depthStencil.stencil = 0u;
429 
430 	// Clear color for used attachments.
431 	m_clearColor.color.float32[0] = 1.0f;
432 	m_clearColor.color.float32[1] = 1.0f;
433 	m_clearColor.color.float32[2] = 1.0f;
434 	m_clearColor.color.float32[3] = 1.0f;
435 
436 	m_clearColorDepth.depthStencil.depth = 0.0f;
437 	m_clearColorDepth.depthStencil.stencil = 255u;
438 
439 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
440 	const VkDevice				vkDevice				= m_context.getDevice();
441 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
442 	SimpleAllocator				memAlloc				(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
443 	const VkComponentMapping	componentMapping		= { VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY, VK_COMPONENT_SWIZZLE_IDENTITY };
444 
445 	// Create color images.
446 	{
447 		const VkImageCreateInfo	colorImageParams =
448 		{
449 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,									// VkStructureType			sType;
450 			DE_NULL,																// const void*				pNext;
451 			0u,																		// VkImageCreateFlags		flags;
452 			VK_IMAGE_TYPE_2D,														// VkImageType				imageType;
453 			FORMAT_COLOR,															// VkFormat					format;
454 			{ kImageWidth, kImageHeight, 1u },										// VkExtent3D				extent;
455 			1u,																		// deUint32					mipLevels;
456 			1u,																		// deUint32					arrayLayers;
457 			VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits	samples;
458 			VK_IMAGE_TILING_OPTIMAL,												// VkImageTiling			tiling;
459 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
460 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT,									// VkImageUsageFlags		usage;
461 			VK_SHARING_MODE_EXCLUSIVE,												// VkSharingMode			sharingMode;
462 			1u,																		// deUint32					queueFamilyIndexCount;
463 			&queueFamilyIndex,														// const deUint32*			pQueueFamilyIndices;
464 			VK_IMAGE_LAYOUT_UNDEFINED												// VkImageLayout			initialLayout;
465 		};
466 
467 		const VkImageCreateInfo depthImageParams =
468 		{
469 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,											// VkStructureType			sType;
470 			DE_NULL,																		// const void*				pNext;
471 			0u,																				// VkImageCreateFlags		flags;
472 			VK_IMAGE_TYPE_2D,																// VkImageType				imageType;
473 			m_testParams.depthStencilFormat,												// VkFormat					format;
474 			{ kImageWidth, kImageHeight, 1u },												// VkExtent3D				extent;
475 			1u,																				// deUint32					mipLevels;
476 			1u,																				// deUint32					arrayLayers;
477 			VK_SAMPLE_COUNT_1_BIT,															// VkSampleCountFlagBits	samples;
478 			VK_IMAGE_TILING_OPTIMAL,														// VkImageTiling			tiling;
479 			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT
480 				| VK_IMAGE_USAGE_TRANSFER_DST_BIT,											// VkImageUsageFlags		usage;
481 			VK_SHARING_MODE_EXCLUSIVE,														// VkSharingMode			sharingMode;
482 			1u,																				// deUint32					queueFamilyIndexCount;
483 			&queueFamilyIndex,																// const deUint32*			pQueueFamilyIndices;
484 			VK_IMAGE_LAYOUT_UNDEFINED														// VkImageLayout			initialLayout;
485 		};
486 
487 		for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
488 		{
489 			// Create, allocate and bind image memory.
490 			m_colorImages.emplace_back(createImage(vk, vkDevice, &colorImageParams));
491 			m_colorImageAllocs.emplace_back(memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_colorImages.back()), MemoryRequirement::Any));
492 			VK_CHECK(vk.bindImageMemory(vkDevice, *m_colorImages.back(), m_colorImageAllocs.back()->getMemory(), m_colorImageAllocs.back()->getOffset()));
493 
494 			// Create image view.
495 			{
496 				const VkImageViewCreateInfo colorAttachmentViewParams =
497 				{
498 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,			// VkStructureType			sType;
499 					DE_NULL,											// const void*				pNext;
500 					0u,													// VkImageViewCreateFlags	flags;
501 					*m_colorImages.back(),								// VkImage					image;
502 					VK_IMAGE_VIEW_TYPE_2D,								// VkImageViewType			viewType;
503 					FORMAT_COLOR,										// VkFormat					format;
504 					componentMapping,									// VkChannelMapping			channels;
505 					{ VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u }		// VkImageSubresourceRange	subresourceRange;
506 				};
507 
508 				m_colorAttachmentViews.emplace_back(createImageView(vk, vkDevice, &colorAttachmentViewParams));
509 			}
510 
511 			// Clear image and leave it prepared to be used as a color attachment.
512 			{
513 				const VkImageAspectFlags		aspectMask	= VK_IMAGE_ASPECT_COLOR_BIT;
514 				Move<VkCommandPool>				cmdPool;
515 				Move<VkCommandBuffer>			cmdBuffer;
516 
517 				// Create command pool and buffer
518 				cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
519 				cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
520 
521 				// From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
522 				const VkImageMemoryBarrier preImageBarrier =
523 				{
524 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
525 					DE_NULL,								// const void*				pNext;
526 					0u,										// VkAccessFlags			srcAccessMask;
527 					VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
528 					VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
529 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
530 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
531 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
532 					*m_colorImages.back(),					// VkImage					image;
533 					{										// VkImageSubresourceRange	subresourceRange;
534 						aspectMask,							// VkImageAspect			aspect;
535 						0u,									// deUint32					baseMipLevel;
536 						1u,									// deUint32					mipLevels;
537 						0u,									// deUint32					baseArraySlice;
538 						1u									// deUint32					arraySize;
539 					}
540 				};
541 
542 				// From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
543 				const VkImageMemoryBarrier postImageBarrier =
544 				{
545 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// VkStructureType			sType;
546 					DE_NULL,									// const void*				pNext;
547 					VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags			srcAccessMask;
548 					VK_ACCESS_SHADER_READ_BIT,					// VkAccessFlags			dstAccessMask;
549 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,		// VkImageLayout			oldLayout;
550 					VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
551 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					srcQueueFamilyIndex;
552 					VK_QUEUE_FAMILY_IGNORED,					// deUint32					dstQueueFamilyIndex;
553 					*m_colorImages.back(),						// VkImage					image;
554 					{											// VkImageSubresourceRange	subresourceRange;
555 						aspectMask,								// VkImageAspect			aspect;
556 						0u,										// deUint32					baseMipLevel;
557 						1u,										// deUint32					mipLevels;
558 						0u,										// deUint32					baseArraySlice;
559 						1u										// deUint32					arraySize;
560 					}
561 				};
562 
563 				const VkImageSubresourceRange clearRange	=
564 				{
565 					aspectMask,	// VkImageAspectFlags	aspectMask;
566 					0u,			// deUint32				baseMipLevel;
567 					1u,			// deUint32				levelCount;
568 					0u,			// deUint32				baseArrayLayer;
569 					1u			// deUint32				layerCount;
570 				};
571 
572 				// Clear image and transfer layout.
573 				beginCommandBuffer(vk, *cmdBuffer);
574 					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);
575 					vk.cmdClearColorImage(*cmdBuffer, *m_colorImages.back(), VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColor.color, 1, &clearRange);
576 					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);
577 				endCommandBuffer(vk, *cmdBuffer);
578 
579 				submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
580 			}
581 		}
582 
583 		if (hasDepthStencil(m_testParams.depthStencilType))
584 		{
585 			const VkImageAspectFlags clearAspectMask	= getClearAspectMask(m_testParams.depthStencilType);
586 			const VkImageAspectFlags formatAspectMask	= getFormatAspectMask(m_testParams.depthStencilFormat);
587 
588 			// Create, allocate and bind image memory.
589 			m_depthImage = createImage(vk, vkDevice, &depthImageParams);
590 			m_depthImageAlloc = memAlloc.allocate(getImageMemoryRequirements(vk, vkDevice, *m_depthImage), MemoryRequirement::Any);
591 			VK_CHECK(vk.bindImageMemory(vkDevice, *m_depthImage, m_depthImageAlloc->getMemory(), m_depthImageAlloc->getOffset()));
592 
593 			// Create image view.
594 			{
595 				const VkImageViewCreateInfo depthAttachmentViewParams =
596 				{
597 					VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,	// VkStructureType			sType;
598 					DE_NULL,									// const void*				pNext;
599 					0u,											// VkImageViewCreateFlags	flags;
600 					*m_depthImage,								// VkImage					image;
601 					VK_IMAGE_VIEW_TYPE_2D,						// VkImageViewType			viewType;
602 					m_testParams.depthStencilFormat,			// VkFormat					format;
603 					componentMapping,							// VkChannelMapping			channels;
604 					{ clearAspectMask, 0u, 1u, 0u, 1u }			// VkImageSubresourceRange	subresourceRange;
605 				};
606 
607 				m_depthAttachmentView = createImageView(vk, vkDevice, &depthAttachmentViewParams);
608 			}
609 
610 			// Clear image and leave it prepared to be used as a depth/stencil attachment.
611 			{
612 				Move<VkCommandPool>				cmdPool;
613 				Move<VkCommandBuffer>			cmdBuffer;
614 
615 				// Create command pool and buffer
616 				cmdPool		= createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
617 				cmdBuffer	= allocateCommandBuffer(vk, vkDevice, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
618 
619 				// From undefined layout to VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL.
620 				const VkImageMemoryBarrier		preImageBarrier =
621 				{
622 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,	// VkStructureType			sType;
623 					DE_NULL,								// const void*				pNext;
624 					0u,										// VkAccessFlags			srcAccessMask;
625 					VK_ACCESS_TRANSFER_WRITE_BIT,			// VkAccessFlags			dstAccessMask;
626 					VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			oldLayout;
627 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,	// VkImageLayout			newLayout;
628 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					srcQueueFamilyIndex;
629 					VK_QUEUE_FAMILY_IGNORED,				// deUint32					dstQueueFamilyIndex;
630 					*m_depthImage,							// VkImage					image;
631 					{										// VkImageSubresourceRange	subresourceRange;
632 						formatAspectMask,					// VkImageAspect			aspect;
633 						0u,									// deUint32					baseMipLevel;
634 						1u,									// deUint32					mipLevels;
635 						0u,									// deUint32					baseArraySlice;
636 						1u									// deUint32					arraySize;
637 					}
638 				};
639 
640 				// From VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL to VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL.
641 				const VkImageMemoryBarrier		postImageBarrier =
642 				{
643 					VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,				// VkStructureType			sType;
644 					DE_NULL,											// const void*				pNext;
645 					VK_ACCESS_TRANSFER_WRITE_BIT,						// VkAccessFlags			srcAccessMask;
646 					VK_ACCESS_SHADER_READ_BIT,							// VkAccessFlags			dstAccessMask;
647 					VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL,				// VkImageLayout			oldLayout;
648 					VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout			newLayout;
649 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					srcQueueFamilyIndex;
650 					VK_QUEUE_FAMILY_IGNORED,							// deUint32					dstQueueFamilyIndex;
651 					*m_depthImage,										// VkImage					image;
652 					{													// VkImageSubresourceRange	subresourceRange;
653 						formatAspectMask,								// VkImageAspect			aspect;
654 						0u,												// deUint32					baseMipLevel;
655 						1u,												// deUint32					mipLevels;
656 						0u,												// deUint32					baseArraySlice;
657 						1u												// deUint32					arraySize;
658 					}
659 				};
660 
661 				const VkImageSubresourceRange	clearRange	=
662 				{
663 					clearAspectMask,	// VkImageAspectFlags	aspectMask;
664 					0u,					// deUint32				baseMipLevel;
665 					1u,					// deUint32				levelCount;
666 					0u,					// deUint32				baseArrayLayer;
667 					1u					// deUint32				layerCount;
668 				};
669 
670 				// Clear image and transfer layout.
671 				beginCommandBuffer(vk, *cmdBuffer);
672 					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);
673 					vk.cmdClearDepthStencilImage(*cmdBuffer, *m_depthImage, VK_IMAGE_LAYOUT_TRANSFER_DST_OPTIMAL, &m_initialColorDepth.depthStencil, 1, &clearRange);
674 					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);
675 				endCommandBuffer(vk, *cmdBuffer);
676 
677 				submitCommandsAndWait(vk, vkDevice, m_context.getUniversalQueue(), cmdBuffer.get());
678 			}
679 		}
680 	}
681 
682 	// Create render pass.
683 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
684 		m_renderPass = createRenderPass<AttachmentDescription1, AttachmentReference1, SubpassDescription1, SubpassDependency1, RenderPassCreateInfo1>(vk, vkDevice, testParams);
685 	else
686 		m_renderPass = createRenderPass<AttachmentDescription2, AttachmentReference2, SubpassDescription2, SubpassDependency2, RenderPassCreateInfo2>(vk, vkDevice, testParams);
687 
688 	// Create framebuffer
689 	{
690 		std::vector<VkImageView>		imageViews;
691 
692 		for (auto& movePtr : m_colorAttachmentViews)
693 			imageViews.push_back(movePtr.get());
694 
695 		if (hasDepthStencil(m_testParams.depthStencilType))
696 			imageViews.push_back(m_depthAttachmentView.get());
697 
698 		const VkFramebufferCreateInfo	framebufferParams	=
699 		{
700 			VK_STRUCTURE_TYPE_FRAMEBUFFER_CREATE_INFO,			// VkStructureType			sType;
701 			DE_NULL,											// const void*				pNext;
702 			0u,													// VkFramebufferCreateFlags	flags;
703 			*m_renderPass,										// VkRenderPass				renderPass;
704 			static_cast<deUint32>(imageViews.size()),			// deUint32					attachmentCount;
705 			(imageViews.empty() ? DE_NULL : imageViews.data()),	// const VkImageView*		pAttachments;
706 			kImageWidth,										// deUint32					width;
707 			kImageHeight,										// deUint32					height;
708 			1u													// deUint32					layers;
709 		};
710 
711 		m_framebuffer = createFramebuffer(vk, vkDevice, &framebufferParams);
712 	}
713 
714 	// Create pipeline layout for subpass 0.
715 	{
716 		const VkDescriptorSetLayoutCreateInfo	descriptorSetLayoutParams	=
717 		{
718 			VK_STRUCTURE_TYPE_DESCRIPTOR_SET_LAYOUT_CREATE_INFO,	// VkStructureType						sType
719 			DE_NULL,												// const void*							pNext
720 			0u,														// VkDescriptorSetLayoutCreateFlags		flags
721 			0u,														// deUint32								bindingCount
722 			DE_NULL													// const VkDescriptorSetLayoutBinding*	pBindings
723 		};
724 		m_descriptorSetLayout = createDescriptorSetLayout(vk, vkDevice, &descriptorSetLayoutParams);
725 
726 		const VkPipelineLayoutCreateInfo		pipelineLayoutParams		=
727 		{
728 			VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,		// VkStructureType					sType;
729 			DE_NULL,											// const void*						pNext;
730 			0u,													// VkPipelineLayoutCreateFlags		flags;
731 			1u,													// deUint32							setLayoutCount;
732 			&m_descriptorSetLayout.get(),						// const VkDescriptorSetLayout*		pSetLayouts;
733 			0u,													// deUint32							pushConstantRangeCount;
734 			DE_NULL												// const VkPushConstantRange*		pPushConstantRanges;
735 		};
736 
737 		m_pipelineLayout = createPipelineLayout(vk, vkDevice, &pipelineLayoutParams);
738 	}
739 
740 	m_vertexShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("vert_shader"), 0);
741 	m_fragmentShaderModule	= createShaderModule(vk, vkDevice, m_context.getBinaryCollection().get("frag_shader"), 0);
742 
743 	// Create pipeline.
744 	{
745 		const std::vector<VkViewport>						viewports						(1, makeViewport(m_renderSize));
746 		const std::vector<VkRect2D>							scissors						(1, makeRect2D(m_renderSize));
747 
748 		const VkPipelineColorBlendAttachmentState			colorBlendAttachmentState		=
749 		{
750 			VK_FALSE,					// VkBool32					blendEnable
751 			VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcColorBlendFactor
752 			VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstColorBlendFactor
753 			VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
754 			VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcAlphaBlendFactor
755 			VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstAlphaBlendFactor
756 			VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
757 			VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
758 			| VK_COLOR_COMPONENT_G_BIT
759 			| VK_COLOR_COMPONENT_B_BIT
760 			| VK_COLOR_COMPONENT_A_BIT
761 		};
762 
763 		std::vector<VkPipelineColorBlendAttachmentState>	colorBlendAttachmentStates;
764 		for (size_t i = 0; i < testParams.colorUsed.size(); ++i)
765 			colorBlendAttachmentStates.push_back(colorBlendAttachmentState);
766 
767 		const VkPipelineColorBlendStateCreateInfo			colorBlendStateCreateInfo		=
768 		{
769 			VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,							// VkStructureType								sType
770 			DE_NULL,																			// const void*									pNext
771 			0u,																					// VkPipelineColorBlendStateCreateFlags			flags
772 			VK_FALSE,																			// VkBool32										logicOpEnable
773 			VK_LOGIC_OP_CLEAR,																	// VkLogicOp									logicOp
774 			static_cast<deUint32>(colorBlendAttachmentStates.size()),							// deUint32										attachmentCount
775 			(colorBlendAttachmentStates.empty() ? DE_NULL : colorBlendAttachmentStates.data()),	// const VkPipelineColorBlendAttachmentState*	pAttachments
776 			{ 0.0f, 0.0f, 0.0f, 0.0f }															// float										blendConstants[4]
777 		};
778 
779 		m_graphicsPipeline = makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
780 												  vkDevice,								// const VkDevice									device
781 												  *m_pipelineLayout,					// const VkPipelineLayout							pipelineLayout
782 												  *m_vertexShaderModule,				// const VkShaderModule								vertexShaderModule
783 												  DE_NULL,								// const VkShaderModule								tessellationControlModule
784 												  DE_NULL,								// const VkShaderModule								tessellationEvalModule
785 												  DE_NULL,								// const VkShaderModule								geometryShaderModule
786 												  *m_fragmentShaderModule,				// const VkShaderModule								fragmentShaderModule
787 												  *m_renderPass,						// const VkRenderPass								renderPass
788 												  viewports,							// const std::vector<VkViewport>&					viewports
789 												  scissors,								// const std::vector<VkRect2D>&						scissors
790 												  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	// const VkPrimitiveTopology						topology
791 												  0u,									// const deUint32									subpass
792 												  0u,									// const deUint32									patchControlPoints
793 												  DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
794 												  DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
795 												  DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
796 												  DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
797 												  &colorBlendStateCreateInfo);			// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
798 	}
799 
800 	// Create command pool
801 	m_cmdPool = createCommandPool(vk, vkDevice, VK_COMMAND_POOL_CREATE_TRANSIENT_BIT, queueFamilyIndex);
802 
803 	// Create command buffer
804 	if (testParams.renderPassType == RENDERPASS_TYPE_LEGACY)
805 		createCommandBuffer<RenderpassSubpass1>(vk, vkDevice);
806 	else
807 		createCommandBuffer<RenderpassSubpass2>(vk, vkDevice);
808 }
809 
810 template <typename RenderpassSubpass>
createCommandBuffer(const DeviceInterface & vk,VkDevice vkDevice)811 void UnusedClearAttachmentTestInstance::createCommandBuffer (const DeviceInterface&	vk,
812 															 VkDevice				vkDevice)
813 {
814 	const typename RenderpassSubpass::SubpassBeginInfo	subpassBeginInfo	(DE_NULL, VK_SUBPASS_CONTENTS_INLINE);
815 	const typename RenderpassSubpass::SubpassEndInfo	subpassEndInfo		(DE_NULL);
816 
817 	const VkRenderPassBeginInfo							renderPassBeginInfo	=
818 	{
819 		VK_STRUCTURE_TYPE_RENDER_PASS_BEGIN_INFO,	// VkStructureType		sType;
820 		DE_NULL,									// const void*			pNext;
821 		*m_renderPass,								// VkRenderPass			renderPass;
822 		*m_framebuffer,								// VkFramebuffer		framebuffer;
823 		makeRect2D(m_renderSize),					// VkRect2D				renderArea;
824 		0u,											// uint32_t				clearValueCount;
825 		DE_NULL										// const VkClearValue*	pClearValues;
826 	};
827 
828 	m_cmdBuffer = allocateCommandBuffer(vk, vkDevice, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
829 
830 	const VkClearRect									clearRect			=
831 	{
832 		{												// VkRect2D		rect;
833 			{ 0, 0, },									//	VkOffset2D	offset;
834 			{ kImageWidth, kImageHeight }				//	VkExtent2D	extent;
835 		},
836 		0u,												// uint32_t		baseArrayLayer;
837 		1u												// uint32_t		layerCount;
838 	};
839 
840 	std::vector<VkClearAttachment> clearAttachments;
841 	for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
842 	{
843 		const VkClearAttachment clearAttachment = {
844 			VK_IMAGE_ASPECT_COLOR_BIT,	// VkImageAspectFlags	aspectMask;
845 			static_cast<deUint32>(i),	// uint32_t				colorAttachment;
846 			m_clearColor				// VkClearValue			clearValue;
847 		};
848 		clearAttachments.push_back(clearAttachment);
849 	}
850 
851 	if (hasDepthStencil(m_testParams.depthStencilType))
852 	{
853 		const VkClearAttachment clearAttachment = {
854 			getClearAspectMask(m_testParams.depthStencilType),	// VkImageAspectFlags	aspectMask;
855 			0u,													// uint32_t				colorAttachment;
856 			m_clearColorDepth									// VkClearValue			clearValue;
857 		};
858 		clearAttachments.push_back(clearAttachment);
859 	}
860 
861 	beginCommandBuffer(vk, *m_cmdBuffer, 0u);
862 		RenderpassSubpass::cmdBeginRenderPass(vk, *m_cmdBuffer, &renderPassBeginInfo, &subpassBeginInfo);
863 		vk.cmdBindPipeline(*m_cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_graphicsPipeline);
864 		vk.cmdClearAttachments(*m_cmdBuffer, static_cast<deUint32>(clearAttachments.size()), (clearAttachments.empty() ? DE_NULL : clearAttachments.data()), 1u, &clearRect);
865 		RenderpassSubpass::cmdEndRenderPass(vk, *m_cmdBuffer, &subpassEndInfo);
866 	endCommandBuffer(vk, *m_cmdBuffer);
867 }
868 
iterate(void)869 tcu::TestStatus	UnusedClearAttachmentTestInstance::iterate (void)
870 {
871 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
872 	const VkDevice			vkDevice			= m_context.getDevice();
873 	const VkQueue			queue				= m_context.getUniversalQueue();
874 	const deUint32			queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
875 	SimpleAllocator			allocator			(vk, vkDevice, getPhysicalDeviceMemoryProperties(m_context.getInstanceInterface(), m_context.getPhysicalDevice()));
876 
877 	submitCommandsAndWait(vk, vkDevice, queue, m_cmdBuffer.get());
878 
879 	// Read result images.
880 	std::vector<de::MovePtr<tcu::TextureLevel>> imagePixels;
881 	for (size_t i = 0; i < m_testParams.colorUsed.size(); ++i)
882 		imagePixels.emplace_back(pipeline::readColorAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_colorImages[i], FORMAT_COLOR, m_renderSize).release());
883 
884 	// Verify pixel colors match.
885 	for (size_t i = 0; i < imagePixels.size(); ++i)
886 	{
887 		const tcu::ConstPixelBufferAccess&	imageAccess		= imagePixels[i]->getAccess();
888 		const float*						refColor		= (m_testParams.colorUsed[i] ? m_clearColor.color.float32 : m_initialColor.color.float32);
889 
890 		for (int y = 0; y < imageAccess.getHeight(); ++y)
891 		for (int x = 0; x < imageAccess.getWidth(); ++x)
892 		{
893 			const tcu::Vec4	color = imageAccess.getPixel(x, y);
894 
895 			for (deUint32 cpnt = 0; cpnt < 4; ++cpnt)
896 				if (de::abs(color[cpnt] - refColor[cpnt]) > 0.01f)
897 				{
898 					std::ostringstream msg;
899 
900 					msg << "Attachment " << i << " with mismatched pixel (" << x << ", " << y << "): expecting pixel value [";
901 					for (deUint32 j = 0; j < 4; ++j)
902 						msg << ((j == 0) ? "" : ", ") << refColor[j];
903 					msg << "] and found [";
904 					for (deUint32 j = 0; j < 4; ++j)
905 						msg << ((j == 0) ? "" : ", ") << color[j];
906 					msg << "]";
907 
908 					return tcu::TestStatus::fail(msg.str());
909 				}
910 		}
911 	}
912 
913 	if (hasDepthStencil(m_testParams.depthStencilType))
914 	{
915 		const bool depthOnly	= isDepthOnly(m_testParams.depthStencilType);
916 		const bool stencilOnly	= isStencilOnly(m_testParams.depthStencilType);
917 
918 		if (!stencilOnly)
919 		{
920 			de::MovePtr<tcu::TextureLevel>		depthPixels	= pipeline::readDepthAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize);
921 			const tcu::ConstPixelBufferAccess&	depthAccess	= depthPixels->getAccess();
922 			const float							refDepth	= (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.depth : m_initialColorDepth.depthStencil.depth);
923 
924 			for (int y = 0; y < depthAccess.getHeight(); ++y)
925 			for (int x = 0; x < depthAccess.getWidth(); ++x)
926 			{
927 				const float value = depthAccess.getPixDepth(x, y);
928 				if (de::abs(value - refDepth) > 0.001f)
929 				{
930 					std::ostringstream msg;
931 
932 					msg << "Depth/stencil attachment with mismatched depth value at pixel ("
933 						<< x << ", " << y << "): expected value " << refDepth << " and found " << value;
934 					return tcu::TestStatus::fail(msg.str());
935 				}
936 			}
937 		}
938 
939 		if (!depthOnly)
940 		{
941 			// Note read*Attachment leaves the attachment in the VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL layout, so the current layout
942 			// depends on if we have previously read the depth aspect or not.
943 			const VkImageLayout					currentLayout	= (stencilOnly ? VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL : VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL);
944 			de::MovePtr<tcu::TextureLevel>		stencilPixels	= pipeline::readStencilAttachment(vk, vkDevice, queue, queueFamilyIndex, allocator, *m_depthImage, m_testParams.depthStencilFormat, m_renderSize, currentLayout);
945 			const tcu::ConstPixelBufferAccess&	stencilAccess	= stencilPixels->getAccess();
946 			const deUint32						refStencil		= (m_testParams.depthStencilUsed ? m_clearColorDepth.depthStencil.stencil : m_initialColorDepth.depthStencil.stencil);
947 
948 			for (int y = 0; y < stencilAccess.getHeight(); ++y)
949 			for (int x = 0; x < stencilAccess.getWidth(); ++x)
950 			{
951 				const int value = stencilAccess.getPixStencil(x, y);
952 				if (value < 0 || static_cast<deUint32>(value) != refStencil)
953 				{
954 					std::ostringstream msg;
955 
956 					msg << "Depth/stencil attachment with mismatched stencil value at pixel ("
957 						<< x << ", " << y << "): expected value " << refStencil << " and found " << value;
958 					return tcu::TestStatus::fail(msg.str());
959 				}
960 			}
961 		}
962 	}
963 
964 	return tcu::TestStatus::pass("Pass");
965 }
966 
967 
968 using CallbackFunction = std::function<void(const std::vector<deBool>&)>;
969 
runCallbackOnCombination(std::vector<deBool> & array,size_t current_index,CallbackFunction callback)970 void runCallbackOnCombination(std::vector<deBool>& array, size_t current_index, CallbackFunction callback)
971 {
972 	DE_ASSERT(current_index < array.size());
973 	for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
974 	{
975 		array[current_index] = DE_BOOL_VALUES[i];
976 		if (current_index == array.size() - 1)
977 			callback(array);
978 		else
979 			runCallbackOnCombination(array, current_index + 1, callback);
980 	}
981 }
982 
runCallbackOnCombination(std::vector<deBool> & array,CallbackFunction callback)983 void runCallbackOnCombination(std::vector<deBool>& array, CallbackFunction callback)
984 {
985 	runCallbackOnCombination(array, 0, callback);
986 }
987 
getUsed(deBool value)988 std::string getUsed(deBool value)
989 {
990 	return (value ? "used" : "unused");
991 }
992 
getCombName(const std::vector<deBool> & array)993 std::string getCombName(const std::vector<deBool>& array)
994 {
995 	std::ostringstream name;
996 	for (size_t i = 0; i < array.size(); ++i)
997 		name << ((i == 0)? "" : "_") << "color" << getUsed(array[i]);
998 	return name.str();
999 }
1000 
1001 } // anonymous
1002 
1003 
createRenderPassUnusedClearAttachmentTests(tcu::TestContext & testCtx,const RenderPassType renderPassType)1004 tcu::TestCaseGroup* createRenderPassUnusedClearAttachmentTests (tcu::TestContext& testCtx, const RenderPassType renderPassType)
1005 {
1006 	de::MovePtr<tcu::TestCaseGroup>	testGroup (new tcu::TestCaseGroup(testCtx, "unused_clear_attachments", "Unused attachments with vkCmdClearAttachments"));
1007 
1008 	for (int depthStencilType = 0; depthStencilType < DEPTH_STENCIL_MAX_ENUM; ++depthStencilType)
1009 	{
1010 		const DepthStencilType	dsType		= static_cast<DepthStencilType>(depthStencilType);
1011 		const auto				dsFormats	= getFormats(dsType);
1012 
1013 		for (const auto dsFormat : dsFormats)
1014 		{
1015 			for (size_t i = 0; i < DE_LENGTH_OF_ARRAY(DE_BOOL_VALUES); ++i)
1016 			{
1017 				const deBool			depthStencilUse	= DE_BOOL_VALUES[i];
1018 				const std::string		dsCase			= depthStencilTypeName(dsType, dsFormat);
1019 				std::vector<TestParams>	testTypes;
1020 
1021 				if (hasDepthStencil(dsType))
1022 					testTypes.emplace_back(0, dsType, depthStencilUse, dsFormat, renderPassType);						// No color attachments.
1023 				testTypes.emplace_back(1, dsType, depthStencilUse, dsFormat, renderPassType);							// Single color attachment.
1024 				testTypes.emplace_back(COLOR_ATTACHMENTS_NUMBER, dsType, depthStencilUse, dsFormat, renderPassType);	// Multiple color attachments.
1025 
1026 				for (auto& params : testTypes)
1027 				{
1028 					if (!params.colorUsed.empty())
1029 					{
1030 						runCallbackOnCombination(params.colorUsed, [&](const std::vector<deBool>& array) {
1031 							std::string name = getCombName(array) + "_" + dsCase;
1032 							if (hasDepthStencil(dsType))
1033 								name += std::string("_") + getUsed(depthStencilUse);
1034 							testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
1035 						});
1036 					}
1037 					else
1038 					{
1039 						std::string name = dsCase + "_" + getUsed(depthStencilUse);
1040 						testGroup->addChild(new UnusedClearAttachmentTest(testCtx, name, "", params));
1041 					}
1042 
1043 				}
1044 
1045 				if (!hasDepthStencil(dsType))
1046 					break;
1047 			}
1048 		}
1049 	}
1050 
1051 	return testGroup.release();
1052 }
1053 
1054 } // renderpass
1055 } // vkt
1056