• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*-------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * -----------------------------
4  *
5  * Copyright (c) 2020 Google Inc.
6  * Copyright (c) 2020 The Khronos Group Inc.
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 for multiple color or depth clears within a render pass
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktDrawMultipleClearsWithinRenderPass.hpp"
26 
27 #include "vktTestGroupUtil.hpp"
28 #include "vktTestCaseUtil.hpp"
29 #include "vktDrawCreateInfoUtil.hpp"
30 #include "vktDrawBufferObjectUtil.hpp"
31 #include "vktDrawImageObjectUtil.hpp"
32 #include "vkPrograms.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vkRefUtil.hpp"
35 #include "vkCmdUtil.hpp"
36 #include "vkBuilderUtil.hpp"
37 #include "vkImageUtil.hpp"
38 #include "vkQueryUtil.hpp"
39 #include "tcuTextureUtil.hpp"
40 #include "tcuCommandLine.hpp"
41 #include "vktDrawTestCaseUtil.hpp"
42 
43 #include "deStringUtil.hpp"
44 
45 #include <cmath>
46 #include <vector>
47 #include <string>
48 #include <sstream>
49 
50 namespace vkt
51 {
52 namespace Draw
53 {
54 namespace
55 {
56 using namespace vk;
57 using tcu::Vec4;
58 using de::SharedPtr;
59 using std::string;
60 using std::abs;
61 using std::vector;
62 using std::ostringstream;
63 
64 const deUint32						WIDTH					= 400;
65 const deUint32						HEIGHT					= 300;
66 
67 enum struct Topology
68 {
69 	TRIANGLE_STRIP = 0,
70 	TRIANGLES,
71 	TRIANGLE
72 };
73 
74 const Topology						topologiesToTest[]		=
75 {
76 	Topology::TRIANGLE_STRIP,
77 	Topology::TRIANGLES,
78 	Topology::TRIANGLE
79 };
80 
81 struct FormatPair
82 {
83 	VkFormat colorFormat;
84 	VkFormat depthFormat;
85 };
86 
87 const FormatPair					formatsToTest[]			=
88 {
89 	{ VK_FORMAT_R8G8B8A8_UNORM	, VK_FORMAT_UNDEFINED	},
90 	{ VK_FORMAT_R8G8B8A8_SNORM	, VK_FORMAT_UNDEFINED	},
91 	{ VK_FORMAT_UNDEFINED		, VK_FORMAT_D32_SFLOAT	},
92 	{ VK_FORMAT_UNDEFINED		, VK_FORMAT_D16_UNORM	},
93 	{ VK_FORMAT_R8G8B8A8_UNORM	, VK_FORMAT_D32_SFLOAT	},
94 	{ VK_FORMAT_R8G8B8A8_UNORM	, VK_FORMAT_D16_UNORM	},
95 	{ VK_FORMAT_R8G8B8A8_SNORM	, VK_FORMAT_D32_SFLOAT	},
96 	{ VK_FORMAT_R8G8B8A8_SNORM	, VK_FORMAT_D16_UNORM	},
97 };
98 
99 const Vec4							verticesTriangleStrip[]	=
100 {
101 	Vec4(-1.0f, -1.0f,	0.0f, 1.0f),	// 0 -- 2
102 	Vec4(-1.0f,	 1.0f,	0.0f, 1.0f),	// |  / |
103 	Vec4( 1.0f, -1.0f,	0.0f, 1.0f),	// | /	|
104 	Vec4( 1.0f,	 1.0f,	0.0f, 1.0f)		// 1 -- 3
105 };
106 const Vec4							verticesTriangles[]		=
107 {
108 	Vec4(-1.0f, -1.0f,	0.0f, 1.0f),	// 0 - 1
109 	Vec4(-1.0f,	 1.0f,	0.0f, 1.0f),	// | /
110 	Vec4( 1.0f, -1.0f,	0.0f, 1.0f),	// 2
111 	Vec4( 1.0f, -1.0f,	0.0f, 1.0f),	//	   4
112 	Vec4(-1.0f,	 1.0f,	0.0f, 1.0f),	//	 / |
113 	Vec4( 1.0f,	 1.0f,	0.0f, 1.0f)		// 3 - 5
114 };
115 const Vec4							verticesBigTriangle[]	=
116 {
117 	Vec4(-1.0f, -1.0f,	0.0f, 1.0f),	// 0 - 2
118 	Vec4(-1.0f,	 3.0f,	0.0f, 1.0f),	// | /
119 	Vec4( 3.0f, -1.0f,	0.0f, 1.0f),	// 1
120 };
121 
122 const deUint32			TOPOLOGY_MAX_VERTICES_COUNT			= 6;
123 const deUint32			TEST_MAX_STEPS_COUNT				= 3;
124 
125 struct Vertices
126 {
127 	const char*			testNameSuffix;
128 	VkPrimitiveTopology	topology;
129 	deUint32			verticesCount;
130 	const Vec4*			vertices;
131 };
132 
133 const Vertices			verticesByTopology[]				=
134 {
135 	{
136 		"_triangle_strip",
137 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
138 		DE_LENGTH_OF_ARRAY(verticesTriangleStrip),
139 		verticesTriangleStrip
140 	},
141 	{
142 		"_triangles",
143 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
144 		DE_LENGTH_OF_ARRAY(verticesTriangles),
145 		verticesTriangles
146 	},
147 	{
148 		"_big_triangle",
149 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
150 		DE_LENGTH_OF_ARRAY(verticesBigTriangle),
151 		verticesBigTriangle
152 	}
153 };
154 
155 enum struct ClearOp
156 {
157 	LOAD = 0,
158 	DRAW,
159 	CLEAR
160 };
161 
162 struct ClearStep
163 {
164 	ClearOp					clearOp;
165 	Vec4					color;
166 	float					depth;
167 };
168 
169 struct TestParams
170 {
171 	VkFormat				colorFormat;
172 	VkFormat				depthFormat;
173 	Topology				topology;
174 	Vec4					expectedColor;
175 	float					colorEpsilon;
176 	float					expectedDepth;
177 	float					depthEpsilon;
178 	deUint32				repeatCount;
179 	bool					enableBlend;
180 	const SharedGroupParams	groupParams;
181 	vector<ClearStep>		steps;
182 };
183 
184 class MultipleClearsTest : public TestInstance
185 {
186 public:
187 							MultipleClearsTest		(Context& context, const TestParams& params);
188 	virtual tcu::TestStatus	iterate					(void);
189 
190 private:
191 	void					preRenderCommands		(VkCommandBuffer cmdBuffer) const;
192 	void					beginLegacyRender		(VkCommandBuffer cmdBuffer) const;
193 	void					drawCommands			(VkCommandBuffer cmdBuffer) const;
194 
195 #ifndef CTS_USES_VULKANSC
196 	void					beginSecondaryCmdBuffer	(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
197 	void					beginDynamicRender		(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags = 0u) const;
198 #endif // CTS_USES_VULKANSC
199 
200 	SharedPtr<Image>		m_colorTargetImage;
201 	SharedPtr<Image>		m_depthTargetImage;
202 	Move<VkImageView>		m_colorTargetView;
203 	Move<VkImageView>		m_depthTargetView;
204 	SharedPtr<Buffer>		m_vertexBuffer;
205 	Move<VkRenderPass>		m_renderPass;
206 	Move<VkFramebuffer>		m_framebuffer;
207 	Move<VkPipelineLayout>	m_pipelineLayout;
208 	Move<VkPipeline>		m_pipeline;
209 
210 	const TestParams		m_params;
211 	Vec4					m_vertices[TOPOLOGY_MAX_VERTICES_COUNT * TEST_MAX_STEPS_COUNT];
212 };
213 
MultipleClearsTest(Context & context,const TestParams & params)214 MultipleClearsTest::MultipleClearsTest (Context &context, const TestParams& params)
215 	: TestInstance(context)
216 	, m_params(params)
217 {
218 	const DeviceInterface&		vk					= m_context.getDeviceInterface();
219 	const VkDevice				device				= m_context.getDevice();
220 	const deUint32				queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
221 	const bool					hasColor			= m_params.colorFormat != VK_FORMAT_UNDEFINED;
222 	const bool					hasDepth			= m_params.depthFormat != VK_FORMAT_UNDEFINED;
223 
224 	DescriptorSetLayoutBuilder	descriptorSetLayoutBuilder;
225 	// Vertex data
226 	const auto&					vertexData			= verticesByTopology[(size_t)m_params.topology];
227 	{
228 		DE_ASSERT(vertexData.verticesCount <= TOPOLOGY_MAX_VERTICES_COUNT);
229 		const size_t			verticesCount		= vertexData.verticesCount;
230 		const VkDeviceSize		dataSize			= verticesCount * sizeof(Vec4);
231 		const VkDeviceSize		totalDataSize		= m_params.steps.size() * dataSize;
232 		DE_ASSERT(totalDataSize <= sizeof(m_vertices));
233 
234 		for(size_t i = 0; i < m_params.steps.size(); ++i)
235 		{
236 			const size_t start = i * verticesCount;
237 			deMemcpy(&m_vertices[start], vertexData.vertices, static_cast<size_t>(dataSize));
238 			for(size_t j = 0; j < verticesCount; ++j)
239 				m_vertices[start + j][2] = m_params.steps[i].depth;
240 		}
241 		m_vertexBuffer								= Buffer::createAndAlloc(vk, device, BufferCreateInfo(totalDataSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT),
242 																			 m_context.getDefaultAllocator(), MemoryRequirement::HostVisible);
243 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), m_vertices, static_cast<std::size_t>(totalDataSize));
244 		flushMappedMemoryRange(vk, device, m_vertexBuffer->getBoundMemory().getMemory(), m_vertexBuffer->getBoundMemory().getOffset(), VK_WHOLE_SIZE);
245 	}
246 
247 	if (hasColor)
248 	{
249 		const VkImageUsageFlags		targetImageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
250 		const ImageCreateInfo		targetImageCreateInfo		(VK_IMAGE_TYPE_2D, m_params.colorFormat, { WIDTH, HEIGHT, 1u }, 1u,	1u,	VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, targetImageUsageFlags);
251 		m_colorTargetImage										= Image::createAndAlloc(vk, device, targetImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
252 		const ImageViewCreateInfo	colorTargetViewInfo			(m_colorTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.colorFormat);
253 		m_colorTargetView										= createImageView(vk, device, &colorTargetViewInfo);
254 	}
255 
256 	if (hasDepth)
257 	{
258 		const VkImageUsageFlags		depthImageUsageFlags		= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
259 		const ImageCreateInfo		depthImageCreateInfo		(VK_IMAGE_TYPE_2D, m_params.depthFormat, { WIDTH, HEIGHT, 1u }, 1u,	1u,	VK_SAMPLE_COUNT_1_BIT, VK_IMAGE_TILING_OPTIMAL, depthImageUsageFlags);
260 		m_depthTargetImage										= Image::createAndAlloc(vk, device, depthImageCreateInfo, m_context.getDefaultAllocator(), queueFamilyIndex);
261 		const ImageViewCreateInfo	depthTargetViewInfo			(m_depthTargetImage->object(), VK_IMAGE_VIEW_TYPE_2D, m_params.depthFormat);
262 		m_depthTargetView										= createImageView(vk, device, &depthTargetViewInfo);
263 	}
264 
265 	// Render pass
266 	if (!m_params.groupParams->useDynamicRendering)
267 	{
268 		RenderPassCreateInfo			renderPassCreateInfo;
269 		if (hasColor)
270 		{
271 			renderPassCreateInfo.addAttachment(AttachmentDescription(
272 				 m_params.colorFormat,								// format
273 				 VK_SAMPLE_COUNT_1_BIT,								// samples
274 				 VK_ATTACHMENT_LOAD_OP_LOAD,						// loadOp
275 				 VK_ATTACHMENT_STORE_OP_STORE,						// storeOp
276 				 VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// stencilLoadOp
277 				 VK_ATTACHMENT_STORE_OP_DONT_CARE,					// stencilStoreOp
278 				 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// initialLayout
279 				 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL));		// finalLayout
280 		}
281 		if (hasDepth)
282 		{
283 			renderPassCreateInfo.addAttachment(AttachmentDescription(
284 				m_params.depthFormat,								// format
285 				VK_SAMPLE_COUNT_1_BIT,								// samples
286 				VK_ATTACHMENT_LOAD_OP_LOAD,							// loadOp
287 				VK_ATTACHMENT_STORE_OP_STORE,						// storeOp
288 				VK_ATTACHMENT_LOAD_OP_DONT_CARE,					// stencilLoadOp
289 				VK_ATTACHMENT_STORE_OP_DONT_CARE,					// stencilStoreOp
290 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// initialLayout
291 				VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL));	// finalLayout
292 		}
293 		const VkAttachmentReference colorAttachmentReference		= hasColor ? makeAttachmentReference(0u, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL) : AttachmentReference();
294 		const VkAttachmentReference depthAttachmentReference		= hasDepth ? makeAttachmentReference(hasColor ? 1u : 0u, VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL) : AttachmentReference();
295 		renderPassCreateInfo.addSubpass(SubpassDescription(
296 			VK_PIPELINE_BIND_POINT_GRAPHICS,						// pipelineBindPoint
297 			(VkSubpassDescriptionFlags)0,							// flags
298 			0u,														// inputAttachmentCount
299 			DE_NULL,												// inputAttachments
300 			hasColor ? 1 : 0,										// colorAttachmentCount
301 			hasColor ? &colorAttachmentReference : DE_NULL,			// colorAttachments
302 			DE_NULL,												// resolveAttachments
303 			depthAttachmentReference,								// depthStencilAttachment
304 			0u,														// preserveAttachmentCount
305 			DE_NULL));												// preserveAttachments
306 		m_renderPass												= createRenderPass(vk, device, &renderPassCreateInfo);
307 
308 		std::vector<VkImageView> attachments;
309 		if (hasColor)
310 			attachments.push_back(*m_colorTargetView);
311 		if (hasDepth)
312 			attachments.push_back(*m_depthTargetView);
313 		const FramebufferCreateInfo framebufferCreateInfo(*m_renderPass, attachments, WIDTH, HEIGHT, 1);
314 		m_framebuffer = createFramebuffer(vk, device, &framebufferCreateInfo);
315 	}
316 
317 	// Vertex input
318 	const VkVertexInputBindingDescription		vertexInputBindingDescription	=
319 	{
320 		0u,										// uint32_t				binding;
321 		sizeof(Vec4),							// uint32_t				stride;
322 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate	inputRate;
323 	};
324 
325 	const VkVertexInputAttributeDescription		vertexInputAttributeDescription =
326 	{
327 		0u,										// uint32_t		location;
328 		0u,										// uint32_t		binding;
329 		VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat		format;
330 		0u										// uint32_t		offset;
331 	};
332 
333 	const PipelineCreateInfo::VertexInputState	vertexInputState				= PipelineCreateInfo::VertexInputState(1, &vertexInputBindingDescription,
334 																													   1, &vertexInputAttributeDescription);
335 
336 	// Graphics pipeline
337 	const Unique<VkShaderModule>				vertexModule					(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
338 	const Unique<VkShaderModule>				fragmentModule					(createShaderModule(vk, device, m_context.getBinaryCollection().get(hasColor ? "frag" : "frag_depthonly"), 0));
339 
340 	const VkPushConstantRange					pcRange							= vk::VkPushConstantRange { VkShaderStageFlagBits::VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(ClearStep::color) };
341 	const PipelineLayoutCreateInfo				pipelineLayoutCreateInfo		(0u, DE_NULL, 1u, &pcRange);
342 	m_pipelineLayout															= createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
343 
344 	const VkRect2D								scissor							= makeRect2D(WIDTH, HEIGHT);
345 	const VkViewport							viewport						= makeViewport(WIDTH, HEIGHT);
346 
347 	const auto									vkCbAttachmentState				= makePipelineColorBlendAttachmentState(
348 		m_params.enableBlend ? VK_TRUE : VK_FALSE,	// VkBool32					blendEnable
349 		VK_BLEND_FACTOR_SRC_ALPHA,					// VkBlendFactor			srcColorBlendFactor
350 		VK_BLEND_FACTOR_ONE_MINUS_SRC_ALPHA,		// VkBlendFactor			dstColorBlendFactor
351 		VK_BLEND_OP_ADD,							// VkBlendOp				colorBlendOp
352 		VK_BLEND_FACTOR_ZERO,						// VkBlendFactor			srcAlphaBlendFactor
353 		VK_BLEND_FACTOR_ONE,						// VkBlendFactor			dstAlphaBlendFactor
354 		VK_BLEND_OP_ADD,							// VkBlendOp				alphaBlendOp
355 		VK_COLOR_COMPONENT_R_BIT |					// VkColorComponentFlags	colorWriteMask
356 		VK_COLOR_COMPONENT_G_BIT |
357 		VK_COLOR_COMPONENT_B_BIT |
358 		VK_COLOR_COMPONENT_A_BIT);
359 	PipelineCreateInfo pipelineCreateInfo(*m_pipelineLayout, *m_renderPass, 0, (VkPipelineCreateFlags)0);
360 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*vertexModule,	  "main", VK_SHADER_STAGE_VERTEX_BIT));
361 	pipelineCreateInfo.addShader(PipelineCreateInfo::PipelineShaderStage(*fragmentModule, "main", VK_SHADER_STAGE_FRAGMENT_BIT));
362 	pipelineCreateInfo.addState (PipelineCreateInfo::VertexInputState	(vertexInputState));
363 	pipelineCreateInfo.addState (PipelineCreateInfo::InputAssemblerState(vertexData.topology));
364 	pipelineCreateInfo.addState (PipelineCreateInfo::ColorBlendState	(1, &vkCbAttachmentState));
365 	pipelineCreateInfo.addState (PipelineCreateInfo::ViewportState		(1, std::vector<VkViewport>(1, viewport), std::vector<VkRect2D>(1, scissor)));
366 	pipelineCreateInfo.addState (PipelineCreateInfo::DepthStencilState	(hasDepth, hasDepth, VK_COMPARE_OP_ALWAYS, VK_FALSE, VK_FALSE));
367 	pipelineCreateInfo.addState (PipelineCreateInfo::RasterizerState	());
368 	pipelineCreateInfo.addState (PipelineCreateInfo::MultiSampleState	());
369 
370 #ifndef CTS_USES_VULKANSC
371 	vk::VkPipelineRenderingCreateInfoKHR renderingCreateInfo
372 	{
373 		VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,
374 		DE_NULL,
375 		0u,
376 		hasColor,
377 		(hasColor ? &m_params.colorFormat : DE_NULL),
378 		m_params.depthFormat,
379 		VK_FORMAT_UNDEFINED
380 	};
381 
382 	if (m_params.groupParams->useDynamicRendering)
383 		pipelineCreateInfo.pNext = &renderingCreateInfo;
384 #endif // CTS_USES_VULKANSC
385 
386 	m_pipeline = createGraphicsPipeline(vk, device, DE_NULL, &pipelineCreateInfo);
387 }
388 
preRenderCommands(VkCommandBuffer cmdBuffer) const389 void MultipleClearsTest::preRenderCommands(VkCommandBuffer cmdBuffer) const
390 {
391 	const DeviceInterface& vk = m_context.getDeviceInterface();
392 	if (m_params.colorFormat)
393 		initialTransitionColor2DImage(vk, cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT);
394 	if (m_params.depthFormat)
395 		initialTransitionDepth2DImage(vk, cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT);
396 }
397 
beginLegacyRender(VkCommandBuffer cmdBuffer) const398 void MultipleClearsTest::beginLegacyRender(VkCommandBuffer cmdBuffer) const
399 {
400 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
401 	const VkRect2D			renderArea	= makeRect2D(0, 0, WIDTH, HEIGHT);
402 
403 	if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
404 		beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea, m_params.steps[0].color, m_params.steps[0].depth, 0);
405 	else
406 		beginRenderPass(vk, cmdBuffer, *m_renderPass, *m_framebuffer, renderArea);
407 }
408 
drawCommands(vk::VkCommandBuffer cmdBuffer) const409 void MultipleClearsTest::drawCommands(vk::VkCommandBuffer cmdBuffer) const
410 {
411 	const DeviceInterface&	vk		= m_context.getDeviceInterface();
412 
413 	vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *m_pipeline);
414 	{
415 		const VkDeviceSize	offset = 0;
416 		const VkBuffer		buffer = m_vertexBuffer->object();
417 		vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &buffer, &offset);
418 	}
419 
420 	for (deUint32 i = 0; i < m_params.repeatCount; ++i)
421 	for (size_t stepIndex = 0; stepIndex < m_params.steps.size(); ++stepIndex)
422 	{
423 		const auto& step = m_params.steps[stepIndex];
424 
425 		// ClearOp::LOAD only supported for first step
426 		DE_ASSERT(stepIndex == 0 || step.clearOp != ClearOp::LOAD);
427 
428 		const Vec4& color = step.color;
429 		const float depth = step.depth;
430 
431 		switch(step.clearOp)
432 		{
433 		case ClearOp::LOAD:
434 			break;
435 		case ClearOp::DRAW:
436 			{
437 				const auto&		vertexData		= verticesByTopology[(size_t)m_params.topology];
438 				const deUint32	verticesCount	= vertexData.verticesCount;
439 				vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(color), color.getPtr());
440 				vk.cmdDraw(cmdBuffer, verticesCount, 1, static_cast<deUint32>(verticesCount * stepIndex), 0);
441 			}
442 			break;
443 		case ClearOp::CLEAR:
444 			{
445 				vector<VkClearAttachment>	clearAttachments;
446 				if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
447 				{
448 					const VkClearAttachment	clearAttachment
449 					{
450 						VK_IMAGE_ASPECT_COLOR_BIT,						// VkImageAspectFlags	 aspectMask
451 						static_cast<deUint32>(clearAttachments.size()),	// uint32_t				 colorAttachment
452 						makeClearValueColor(color)						// VkClearValue			 clearValue
453 					};
454 					clearAttachments.push_back(clearAttachment);
455 				}
456 				if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
457 				{
458 					const VkClearAttachment	clearAttachment
459 					{
460 						VK_IMAGE_ASPECT_DEPTH_BIT,						// VkImageAspectFlags	 aspectMask
461 						static_cast<deUint32>(clearAttachments.size()),	// uint32_t				 colorAttachment
462 						makeClearValueDepthStencil(depth, 0)			// VkClearValue			 clearValue
463 					};
464 					clearAttachments.push_back(clearAttachment);
465 				}
466 				const VkClearRect clearRect
467 				{
468 					makeRect2D(WIDTH, HEIGHT),							// VkRect2D	   rect
469 					0,													// uint32_t	   baseArrayLayer
470 					1													// uint32_t	   layerCount
471 				};
472 				vk.cmdClearAttachments(cmdBuffer, static_cast<deUint32>(clearAttachments.size()), clearAttachments.data(), 1, &clearRect);
473 			}
474 			break;
475 		default:
476 			break;
477 		}
478 	}
479 }
480 
481 #ifndef CTS_USES_VULKANSC
beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const482 void MultipleClearsTest::beginSecondaryCmdBuffer(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
483 {
484 	VkCommandBufferInheritanceRenderingInfoKHR inheritanceRenderingInfo
485 	{
486 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,		// VkStructureType					sType;
487 		DE_NULL,																// const void*						pNext;
488 		renderingFlags,															// VkRenderingFlagsKHR				flags;
489 		0u,																		// uint32_t							viewMask;
490 		(m_params.colorFormat != VK_FORMAT_UNDEFINED),							// uint32_t							colorAttachmentCount;
491 		&m_params.colorFormat,													// const VkFormat*					pColorAttachmentFormats;
492 		m_params.depthFormat,													// VkFormat							depthAttachmentFormat;
493 		VK_FORMAT_UNDEFINED,													// VkFormat							stencilAttachmentFormat;
494 		VK_SAMPLE_COUNT_1_BIT,													// VkSampleCountFlagBits			rasterizationSamples;
495 	};
496 
497 	const VkCommandBufferInheritanceInfo bufferInheritanceInfo = initVulkanStructure(&inheritanceRenderingInfo);
498 
499 	VkCommandBufferUsageFlags usageFlags = VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT;
500 	if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
501 		usageFlags |= VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT;
502 
503 	const VkCommandBufferBeginInfo commandBufBeginParams
504 	{
505 		VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,							// VkStructureType					sType;
506 		DE_NULL,																// const void*						pNext;
507 		usageFlags,																// VkCommandBufferUsageFlags		flags;
508 		&bufferInheritanceInfo
509 	};
510 
511 	const DeviceInterface& vk = m_context.getDeviceInterface();
512 	VK_CHECK(vk.beginCommandBuffer(cmdBuffer, &commandBufBeginParams));
513 }
514 
beginDynamicRender(VkCommandBuffer cmdBuffer,VkRenderingFlagsKHR renderingFlags) const515 void MultipleClearsTest::beginDynamicRender(VkCommandBuffer cmdBuffer, VkRenderingFlagsKHR renderingFlags) const
516 {
517 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
518 	const VkRect2D			renderArea	= makeRect2D(0, 0, WIDTH, HEIGHT);
519 
520 	VkClearValue clearColorValue = makeClearValueColor(tcu::Vec4(0.0f));
521 	VkClearValue clearDepthValue = makeClearValueDepthStencil(0.0f, 0u);
522 	if (!m_params.steps.empty() && m_params.steps[0].clearOp == ClearOp::LOAD)
523 	{
524 		clearColorValue = makeClearValueColor(m_params.steps[0].color);
525 		clearDepthValue = makeClearValueDepthStencil(m_params.steps[0].depth, 0u);
526 	}
527 
528 	vk::VkRenderingAttachmentInfoKHR colorAttachment
529 	{
530 		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
531 		DE_NULL,												// const void*							pNext;
532 		*m_colorTargetView,										// VkImageView							imageView;
533 		vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout						imageLayout;
534 		vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
535 		DE_NULL,												// VkImageView							resolveImageView;
536 		vk::VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout						resolveImageLayout;
537 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,							// VkAttachmentLoadOp					loadOp;
538 		vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
539 		clearColorValue											// VkClearValue							clearValue;
540 	};
541 
542 	vk::VkRenderingAttachmentInfoKHR depthAttachment
543 	{
544 		vk::VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType						sType;
545 		DE_NULL,												// const void*							pNext;
546 		*m_depthTargetView,										// VkImageView							imageView;
547 		vk::VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL,	// VkImageLayout						imageLayout;
548 		vk::VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits				resolveMode;
549 		DE_NULL,												// VkImageView							resolveImageView;
550 		vk::VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout						resolveImageLayout;
551 		vk::VK_ATTACHMENT_LOAD_OP_LOAD,							// VkAttachmentLoadOp					loadOp;
552 		vk::VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp					storeOp;
553 		clearDepthValue											// VkClearValue							clearValue;
554 	};
555 
556 	const bool hasColor = m_params.colorFormat != VK_FORMAT_UNDEFINED;
557 	const bool hasDepth = m_params.depthFormat != VK_FORMAT_UNDEFINED;
558 
559 	vk::VkRenderingInfoKHR renderingInfo
560 	{
561 		vk::VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,
562 		DE_NULL,
563 		renderingFlags,											// VkRenderingFlagsKHR					flags;
564 		renderArea,												// VkRect2D								renderArea;
565 		1u,														// deUint32								layerCount;
566 		0u,														// deUint32								viewMask;
567 		hasColor,												// deUint32								colorAttachmentCount;
568 		(hasColor ? &colorAttachment : DE_NULL),				// const VkRenderingAttachmentInfoKHR*	pColorAttachments;
569 		(hasDepth ? &depthAttachment : DE_NULL),				// const VkRenderingAttachmentInfoKHR*	pDepthAttachment;
570 		DE_NULL,												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment;
571 	};
572 
573 	vk.cmdBeginRendering(cmdBuffer, &renderingInfo);
574 }
575 #endif // CTS_USES_VULKANSC
576 
iterate(void)577 tcu::TestStatus MultipleClearsTest::iterate (void)
578 {
579 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
580 	const VkDevice					device				= m_context.getDevice();
581 	const VkQueue					queue				= m_context.getUniversalQueue();
582 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
583 
584 	const CmdPoolCreateInfo			cmdPoolCreateInfo	(queueFamilyIndex);
585 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, &cmdPoolCreateInfo));
586 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
587 	Move<VkCommandBuffer>			secCmdBuffer;
588 
589 	const bool						hasColor			= m_params.colorFormat != VK_FORMAT_UNDEFINED;
590 	const bool						hasDepth			= m_params.depthFormat != VK_FORMAT_UNDEFINED;
591 
592 #ifndef CTS_USES_VULKANSC
593 	if (m_params.groupParams->useSecondaryCmdBuffer)
594 	{
595 		secCmdBuffer = allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY);
596 
597 		// record secondary command buffer
598 		if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
599 		{
600 			beginSecondaryCmdBuffer(*secCmdBuffer, VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT);
601 			beginDynamicRender(*secCmdBuffer);
602 		}
603 		else
604 			beginSecondaryCmdBuffer(*secCmdBuffer);
605 
606 		drawCommands(*secCmdBuffer);
607 
608 		if (m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
609 			endRendering(vk, *secCmdBuffer);
610 
611 		endCommandBuffer(vk, *secCmdBuffer);
612 
613 		// record primary command buffer
614 		beginCommandBuffer(vk, *cmdBuffer, 0u);
615 		preRenderCommands(*cmdBuffer);
616 
617 		if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
618 			beginDynamicRender(*cmdBuffer, VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
619 
620 		vk.cmdExecuteCommands(*cmdBuffer, 1u, &*secCmdBuffer);
621 
622 		if (!m_params.groupParams->secondaryCmdBufferCompletelyContainsDynamicRenderpass)
623 			endRendering(vk, *cmdBuffer);
624 	}
625 	else if (m_params.groupParams->useDynamicRendering)
626 	{
627 		beginCommandBuffer(vk, *cmdBuffer);
628 		preRenderCommands(*cmdBuffer);
629 		beginDynamicRender(*cmdBuffer);
630 		drawCommands(*cmdBuffer);
631 		endRendering(vk, *cmdBuffer);
632 	}
633 #endif // CTS_USES_VULKANSC
634 
635 	if (!m_params.groupParams->useDynamicRendering)
636 	{
637 		beginCommandBuffer(vk, *cmdBuffer);
638 		preRenderCommands(*cmdBuffer);
639 		beginLegacyRender(*cmdBuffer);
640 		drawCommands(*cmdBuffer);
641 		endRenderPass(vk, *cmdBuffer);
642 	}
643 
644 	if (hasDepth)
645 	{
646 		const VkMemoryBarrier	memBarrier	= { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_READ_BIT | VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT };
647 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
648 	}
649 	if (hasColor)
650 	{
651 		const VkMemoryBarrier	memBarrier	= { VK_STRUCTURE_TYPE_MEMORY_BARRIER, DE_NULL, VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT };
652 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0, 1, &memBarrier, 0, DE_NULL, 0, DE_NULL);
653 	}
654 
655 	if (hasColor)
656 		transition2DImage(vk, *cmdBuffer, m_colorTargetImage->object(), VK_IMAGE_ASPECT_COLOR_BIT,
657 						  VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
658 						  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
659 						  VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_HOST_BIT);
660 	if (hasDepth)
661 		transition2DImage(vk, *cmdBuffer, m_depthTargetImage->object(), VK_IMAGE_ASPECT_DEPTH_BIT,
662 						  VK_IMAGE_LAYOUT_DEPTH_STENCIL_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
663 						  VK_ACCESS_DEPTH_STENCIL_ATTACHMENT_WRITE_BIT, VK_ACCESS_MEMORY_READ_BIT,
664 						  VK_PIPELINE_STAGE_LATE_FRAGMENT_TESTS_BIT, VK_PIPELINE_STAGE_HOST_BIT);
665 
666 	endCommandBuffer(vk, *cmdBuffer);
667 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
668 
669 	VK_CHECK(vk.queueWaitIdle(queue));
670 
671 	if (hasColor)
672 	{
673 		const auto		resultImage	= m_colorTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_COLOR_BIT);
674 
675 #ifdef CTS_USES_VULKANSC
676 		if (m_context.getTestContext().getCommandLine().isSubProcess())
677 #endif // CTS_USES_VULKANSC
678 		{
679 			for(int z = 0; z < resultImage.getDepth(); ++z)
680 			for(int y = 0; y < resultImage.getHeight(); ++y)
681 			for(int x = 0; x < resultImage.getWidth(); ++x)
682 			{
683 				const Vec4	difference	= m_params.expectedColor - resultImage.getPixel(x,y,z);
684 				if (abs(difference.x()) >= m_params.colorEpsilon || abs(difference.y()) >= m_params.colorEpsilon || abs(difference.z()) >= m_params.colorEpsilon)
685 				{
686 					ostringstream msg;
687 					msg << "Color value mismatch, expected: " << m_params.expectedColor << ", got: " << resultImage.getPixel(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
688 					return tcu::TestStatus::fail(msg.str());
689 				}
690 			}
691 		}
692 	}
693 	if (hasDepth)
694 	{
695 		const auto		resultImage	= m_depthTargetImage->readSurface(queue, m_context.getDefaultAllocator(), VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, { 0, 0, 0 }, WIDTH, HEIGHT, VK_IMAGE_ASPECT_DEPTH_BIT);
696 
697 #ifdef CTS_USES_VULKANSC
698 		if (m_context.getTestContext().getCommandLine().isSubProcess())
699 #endif // CTS_USES_VULKANSC
700 		{
701 			for(int z = 0; z < resultImage.getDepth(); ++z)
702 			for(int y = 0; y < resultImage.getHeight(); ++y)
703 			for(int x = 0; x < resultImage.getWidth(); ++x)
704 			{
705 				const float	difference	= m_params.expectedDepth - resultImage.getPixDepth(x,y,z);
706 				if (abs(difference) >= m_params.depthEpsilon)
707 				{
708 					ostringstream msg;
709 					msg << "Depth value mismatch, expected: " << m_params.expectedDepth << ", got: " << resultImage.getPixDepth(x,y,z) << " at " << "(" << x << ", " << y << ", " << z << ")";
710 					return tcu::TestStatus::fail(msg.str());
711 				}
712 			}
713 		}
714 	}
715 	return tcu::TestStatus::pass("Pass");
716 }
717 
718 class MultipleClearsWithinRenderPassTest : public TestCase
719 {
720 public:
MultipleClearsWithinRenderPassTest(tcu::TestContext & testCtx,const string & name,const string & description,const TestParams & params)721 	MultipleClearsWithinRenderPassTest (tcu::TestContext& testCtx, const string& name, const string& description, const TestParams& params)
722 		: TestCase(testCtx, name, description)
723 		, m_params(params)
724 	{
725 		DE_ASSERT(m_params.steps.size() <= static_cast<size_t>(TEST_MAX_STEPS_COUNT));
726 	}
727 
initPrograms(SourceCollections & programCollection) const728 	virtual void initPrograms (SourceCollections& programCollection) const
729 	{
730 		{
731 			ostringstream src;
732 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
733 				<< "\n"
734 				<< "layout(location = 0) in vec4 in_position;\n"
735 				<< "\n"
736 				<< "out gl_PerVertex {\n"
737 				<< "    vec4  gl_Position;\n"
738 				<< "};\n"
739 				<< "\n"
740 				<< "void main(void)\n"
741 				<< "{\n"
742 				<< "    gl_Position = in_position;\n"
743 				<< "}\n";
744 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
745 		}
746 		{
747 			ostringstream src;
748 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
749 				<< "\n"
750 				<< "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
751 				<< "layout(location = 0) out vec4 out_color;\n"
752 				<< "\n"
753 				<< "void main(void)\n"
754 				<< "{\n"
755 				<< "    out_color = u_color.color;\n"
756 				<< "}\n";
757 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
758 		}
759 		{
760 			ostringstream src;
761 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
762 				<< "\n"
763 				<< "layout(push_constant) uniform Color { vec4 color; } u_color;\n"
764 				<< "\n"
765 				<< "void main(void)\n"
766 				<< "{\n"
767 				<< "}\n";
768 			programCollection.glslSources.add("frag_depthonly") << glu::FragmentSource(src.str());
769 		}
770 	}
771 
checkSupport(Context & context) const772 	virtual void checkSupport (Context& context) const
773 	{
774 		VkImageFormatProperties imageFormatProperties;
775 		const auto&	vki	= context.getInstanceInterface();
776 		const auto&	vkd	= context.getPhysicalDevice();
777 		if (m_params.colorFormat != VK_FORMAT_UNDEFINED)
778 		{
779 			const auto	colorUsage	= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
780 			if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.colorFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, colorUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
781 				TCU_THROW(NotSupportedError, "Color format not supported");
782 		}
783 		if (m_params.depthFormat != VK_FORMAT_UNDEFINED)
784 		{
785 			const auto	depthUsage	= VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
786 			if (vki.getPhysicalDeviceImageFormatProperties(vkd, m_params.depthFormat, VK_IMAGE_TYPE_2D, VK_IMAGE_TILING_OPTIMAL, depthUsage, 0u, &imageFormatProperties) != VK_SUCCESS)
787 				TCU_THROW(NotSupportedError, "Depth format not supported");
788 		}
789 
790 		if (m_params.groupParams->useDynamicRendering)
791 			context.requireDeviceFunctionality("VK_KHR_dynamic_rendering");
792 	}
793 
createInstance(Context & context) const794 	virtual TestInstance* createInstance (Context& context) const
795 	{
796 		return new MultipleClearsTest(context, m_params);
797 	}
798 
799 private:
800 	const TestParams	m_params;
801 };
802 
803 }	// anonymous
804 
MultipleClearsWithinRenderPassTests(tcu::TestContext & testCtx,const SharedGroupParams groupParams)805 MultipleClearsWithinRenderPassTests::MultipleClearsWithinRenderPassTests (tcu::TestContext &testCtx, const SharedGroupParams groupParams)
806 	: TestCaseGroup	(testCtx, "multiple_clears_within_render_pass", "Tests for multiple clears within render pass")
807 	, m_groupParams	(groupParams)
808 {
809 }
810 
~MultipleClearsWithinRenderPassTests()811 MultipleClearsWithinRenderPassTests::~MultipleClearsWithinRenderPassTests ()
812 {
813 }
814 
init()815 void MultipleClearsWithinRenderPassTests::init ()
816 {
817 	for(const auto &formatPair : formatsToTest)
818 	{
819 		ostringstream			formatSuffix;
820 		if (formatPair.colorFormat != VK_FORMAT_UNDEFINED)
821 			formatSuffix << "_c" << de::toLower(string(getFormatName(formatPair.colorFormat)).substr(9));
822 		if (formatPair.depthFormat != VK_FORMAT_UNDEFINED)
823 			formatSuffix << "_d" << de::toLower(string(getFormatName(formatPair.depthFormat)).substr(9));
824 		for(const auto &topology : topologiesToTest)
825 		{
826 			// reduce number of tests for dynamic rendering cases where secondary command buffer is used
827 			if (m_groupParams->useSecondaryCmdBuffer && (topology != Topology::TRIANGLE_STRIP))
828 				continue;
829 
830 			const string	testNameSuffix	= formatSuffix.str() + verticesByTopology[(deUint32)topology].testNameSuffix;
831 			{
832 				const TestParams params
833 				{
834 					formatPair.colorFormat,			// VkFormat				colorFormat;
835 					formatPair.depthFormat,			// VkFormat				depthFormat;
836 					topology,						// Topology				topology;
837 					Vec4(0.0f, 0.5f, 0.5f, 1.0f),	// Vec4					expectedColor;
838 					0.01f,							// float				colorEpsilon;
839 					0.9f,							// float				expectedDepth;
840 					0.01f,							// float				depthEpsilon;
841 					1u,								// deUint32				repeatCount;
842 					true,							// bool					enableBlend;
843 					m_groupParams,					// SharedGroupParams	groupParams;
844 					{								// vector<ClearStep>	steps;
845 						{ ClearOp::LOAD		, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.7f },
846 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.3f },
847 						{ ClearOp::DRAW		, Vec4(0.0f, 0.0f, 1.0f, 0.5f)	, 0.9f }
848 					}
849 				};
850 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear, draw", params));
851 			}
852 			{
853 				const TestParams params
854 				{
855 					formatPair.colorFormat,			// VkFormat				format;
856 					formatPair.depthFormat,			// VkFormat				depthFormat;
857 					topology,						// Topology				topology;
858 					Vec4(0.0f, 0.5f, 0.5f, 1.0f),	// Vec4					expectedColor;
859 					0.01f,							// float				colorEpsilon;
860 					0.9f,							// float				expectedDepth;
861 					0.01f,							// float				depthEpsilon;
862 					1u,								// deUint32				repeatCount;
863 					true,							// bool					enableBlend;
864 					m_groupParams,					// SharedGroupParams	groupParams;
865 					{								// vector<ClearStep>	steps;
866 						{ ClearOp::DRAW		, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.7f },
867 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.3f },
868 						{ ClearOp::DRAW		, Vec4(0.0f, 0.0f, 1.0f, 0.5f)	, 0.9f }
869 					}
870 				};
871 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear, draw", params));
872 			}
873 			{
874 				const TestParams params
875 				{
876 					formatPair.colorFormat,			// VkFormat				format;
877 					formatPair.depthFormat,			// VkFormat				depthFormat;
878 					topology,						// Topology				topology;
879 					Vec4(0.0f, 0.5f, 0.5f, 1.0f),	// Vec4					expectedColor;
880 					0.01f,							// float				colorEpsilon;
881 					0.9f,							// float				expectedDepth;
882 					0.01f,							// float				depthEpsilon;
883 					1u,								// deUint32				repeatCount;
884 					true,							// bool					enableBlend;
885 					m_groupParams,					// SharedGroupParams	groupParams;
886 					{								// vector<ClearStep>	steps;
887 						{ ClearOp::CLEAR	, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.7f },
888 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.3f },
889 						{ ClearOp::DRAW		, Vec4(0.0f, 0.0f, 1.0f, 0.5f)	, 0.9f }
890 					}
891 				};
892 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear_draw" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear, draw", params));
893 			}
894 			{
895 				const TestParams params
896 				{
897 					formatPair.colorFormat,			// VkFormat				format;
898 					formatPair.depthFormat,			// VkFormat				depthFormat;
899 					topology,						// Topology				topology;
900 					Vec4(0.0f, 1.0f, 0.0f, 1.0f),	// Vec4					expectedColor;
901 					0.01f,							// float				colorEpsilon;
902 					0.9f,							// float				expectedDepth;
903 					0.01f,							// float				depthEpsilon;
904 					1u,								// deUint32				repeatCount;
905 					false,							// bool					enableBlend;
906 					m_groupParams,					// SharedGroupParams	groupParams;
907 					{								// vector<ClearStep>	steps;
908 						{ ClearOp::LOAD		, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.3f },
909 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.9f }
910 					}
911 				};
912 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "load_clear" + testNameSuffix, "Multiple clears within same render pass, methods: load, clear", params));
913 			}
914 			{
915 				const TestParams params
916 				{
917 					formatPair.colorFormat,			// VkFormat				format;
918 					formatPair.depthFormat,			// VkFormat				depthFormat;
919 					topology,						// Topology				topology;
920 					Vec4(0.0f, 1.0f, 0.0f, 1.0f),	// Vec4					expectedColor;
921 					0.01f,							// float				colorEpsilon;
922 					0.9f,							// float				expectedDepth;
923 					0.01f,							// float				depthEpsilon;
924 					1u,								// deUint32				repeatCount;
925 					false,							// bool					enableBlend;
926 					m_groupParams,					// SharedGroupParams	groupParams;
927 					{								// vector<ClearStep>	steps;
928 						{ ClearOp::DRAW		, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.3f },
929 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.9f }
930 					}
931 				};
932 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "draw_clear" + testNameSuffix, "Multiple clears within same render pass, methods: draw, clear", params));
933 			}
934 			{
935 				const TestParams params
936 				{
937 					formatPair.colorFormat,			// VkFormat				format;
938 					formatPair.depthFormat,			// VkFormat				depthFormat;
939 					topology,						// Topology				topology;
940 					Vec4(0.0f, 1.0f, 0.0f, 1.0f),	// Vec4					expectedColor;
941 					0.01f,							// float				colorEpsilon;
942 					0.9f,							// float				expectedDepth;
943 					0.01f,							// float				depthEpsilon;
944 					1u,								// deUint32				repeatCount;
945 					false,							// bool					enableBlend;
946 					m_groupParams,					// SharedGroupParams	groupParams;
947 					{								// vector<ClearStep>	steps;
948 						{ ClearOp::CLEAR	, Vec4(1.0f, 0.0f, 0.0f, 1.0f)	, 0.3f },
949 						{ ClearOp::CLEAR	, Vec4(0.0f, 1.0f, 0.0f, 1.0f)	, 0.9f }
950 					}
951 				};
952 				addChild(new MultipleClearsWithinRenderPassTest(m_testCtx, "clear_clear" + testNameSuffix, "Multiple clears within same render pass, methods: clear, clear", params));
953 			}
954 		}
955 	}
956 }
957 }	// Draw
958 }	// vkt
959