• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2022 Google LLC
6  * Copyright (c) 2022 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 Vulkan Dynamic Rendering Random Tests
23  *//*--------------------------------------------------------------------*/
24 
25 #include "deRandom.hpp"
26 
27 #include "tcuImageCompare.hpp"
28 #include "tcuTestLog.hpp"
29 
30 #include "vkBarrierUtil.hpp"
31 #include "vkCmdUtil.hpp"
32 #include "vktDrawBufferObjectUtil.hpp"
33 #include "vktDynamicRenderingRandomTests.hpp"
34 #include "vkImageUtil.hpp"
35 #include "vkObjUtil.hpp"
36 #include "vktTestCase.hpp"
37 #include "vkTypeUtil.hpp"
38 
39 #include <iostream>
40 
41 namespace vkt
42 {
43 namespace renderpass
44 {
45 namespace
46 {
47 
48 using namespace vk;
49 
50 using tcu::UVec2;
51 using tcu::Vec4;
52 
53 const deUint32	maxQueries		= 50u * 3u; // multiview with 3 bits can be used
54 const deUint32	numLayers		= 4u;
55 
56 struct TestParameters
57 {
58 	VkFormat	imageFormat;
59 	UVec2		renderSize;
60 	bool		enableGeometry;
61 	bool		enableTessellation;
62 	deUint32	randomSeed;
63 };
64 
65 struct PushConstantData
66 {
67 	Vec4	scale;
68 	Vec4	offset;
69 	Vec4	color;
70 	deInt32	layer;
71 };
72 
73 class DynamicRenderingTestInstance : public TestInstance
74 {
75 public:
76 								DynamicRenderingTestInstance	(Context&				context,
77 																 const TestParameters&	parameters);
78 protected:
79 	virtual tcu::TestStatus		iterate							(void);
80 
81 	TestParameters				m_parameters;
82 	Move<VkImage>				m_imageColor;
83 	Move<VkImageView>			m_colorAttachmentView;
84 	de::MovePtr<Allocation>		m_imageColorAlloc;
85 	de::SharedPtr<Draw::Buffer>	m_imageBuffer;
86 	deUint32					m_layerSizeBytes;
87 	Move<VkShaderModule>		m_vertexModule;
88 	Move<VkShaderModule>		m_vertexPassthroughModule;
89 	Move<VkShaderModule>		m_vertexLayerModule;
90 	Move<VkShaderModule>		m_geometryModule;
91 	Move<VkShaderModule>		m_geometryLayerModule;
92 	Move<VkShaderModule>		m_tscModule;
93 	Move<VkShaderModule>		m_tseModule;
94 	Move<VkShaderModule>		m_fragmentModule;
95 	de::SharedPtr<Draw::Buffer>	m_vertexBuffer;
96 	Move<VkPipelineLayout>		m_pipelineLayout;
97 	de::SharedPtr<Draw::Buffer>	m_queryResults;
98 	Move<VkQueryPool>			m_queryPool;
99 	Move<VkCommandPool>			m_cmdPool;
100 	de::Random					m_random;
101 	Move<VkPipeline>			m_pipelineBasic;
102 	Move<VkPipeline>			m_pipelineGeom;
103 	Move<VkPipeline>			m_pipelineTess;
104 	Move<VkPipeline>			m_pipelineLayer;
105 	Move<VkPipeline>			m_pipelineMultiview;
106 };
107 
DynamicRenderingTestInstance(Context & context,const TestParameters & parameters)108 DynamicRenderingTestInstance::DynamicRenderingTestInstance (Context&				context,
109 															const TestParameters&	parameters)
110 : TestInstance	(context)
111 , m_parameters	(parameters)
112 , m_random		(parameters.randomSeed)
113 {
114 	const DeviceInterface&		vk			= m_context.getDeviceInterface();
115 	const VkDevice				device		= m_context.getDevice();
116 	Allocator&					allocator	= m_context.getDefaultAllocator();
117 
118 	m_cmdPool = createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, m_context.getUniversalQueueFamilyIndex());
119 
120 	// Vertices.
121 	{
122 		std::vector<Vec4>			vertices	=
123 		{
124 			Vec4(-0.5f,  0.5f, 0.0f, 1.0f),
125 			Vec4(-0.5f, -0.5f, 0.0f, 1.0f),
126 			Vec4( 0.5f,  0.5f, 0.0f, 1.0f),
127 			Vec4( 0.5f, -0.5f, 0.0f, 1.0f)
128 		};
129 
130 		const VkDeviceSize			bufferSize	= vertices.size() * sizeof(vertices[0]);
131 		const VkBufferCreateInfo	bufferInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
132 
133 		m_vertexBuffer	= Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
134 
135 		deMemcpy(m_vertexBuffer->getBoundMemory().getHostPtr(), vertices.data(), static_cast<std::size_t>(bufferSize));
136 		flushAlloc(vk, device, m_vertexBuffer->getBoundMemory());
137 	}
138 
139 	// Create color image.
140 	{
141 		const VkImageUsageFlags			imageUsage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
142 															  VK_IMAGE_USAGE_TRANSFER_SRC_BIT |
143 															  VK_IMAGE_USAGE_TRANSFER_DST_BIT;
144 		m_layerSizeBytes									= m_parameters.renderSize.x() *
145 															  m_parameters.renderSize.y() *
146 															  tcu::getPixelSize(mapVkFormat(m_parameters.imageFormat));
147 		const VkDeviceSize				imageBufferSize		= m_layerSizeBytes * numLayers;
148 
149 		const VkImageCreateInfo			imageInfo			=
150 		{
151 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType
152 			DE_NULL,										// const void*				pNext
153 			(VkImageCreateFlags)0,							// VkImageCreateFlags		flags
154 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType
155 			m_parameters.imageFormat,						// VkFormat					format
156 			makeExtent3D(m_parameters.renderSize.x(),
157 						 m_parameters.renderSize.y(), 1),	// VkExtent3D				extent
158 			1u,												// deUint32					mipLevels
159 			numLayers,										// deUint32					arrayLayers
160 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples
161 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling
162 			imageUsage,										// VkImageUsageFlags		usage
163 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
164 			0u,												// deUint32					queueFamilyIndexCount
165 			DE_NULL,										// const deUint32*			pQueueFamilyIndices
166 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout
167 		};
168 
169 		const VkBufferCreateInfo		bufferInfo			= makeBufferCreateInfo(imageBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
170 
171 		m_imageColor		= makeImage(vk, device, imageInfo);
172 		m_imageColorAlloc	= bindImage(vk, device, allocator, *m_imageColor, MemoryRequirement::Any);
173 		m_imageBuffer		= Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
174 
175 		const VkImageSubresourceRange	imageSubresource	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, numLayers);
176 
177 		m_colorAttachmentView	= makeImageView(vk, device, *m_imageColor, VK_IMAGE_VIEW_TYPE_2D_ARRAY, m_parameters.imageFormat, imageSubresource);
178 
179 		const Allocation				alloc				= m_imageBuffer->getBoundMemory();
180 		deMemset(alloc.getHostPtr(), 0, static_cast<std::size_t>(imageBufferSize));
181 		flushAlloc(vk, device, alloc);
182 	}
183 
184 	// Pipeline layout.
185 	{
186 		const auto	pcStages	= VK_SHADER_STAGE_VERTEX_BIT | vk::VK_SHADER_STAGE_GEOMETRY_BIT;
187 		const auto	pcSize		= static_cast<uint32_t>(sizeof(PushConstantData));
188 		const auto	pcRange		= makePushConstantRange(pcStages, 0u, pcSize);
189 
190 		m_pipelineLayout = makePipelineLayout(vk, device, 0u, DE_NULL, 1u, &pcRange);
191 	}
192 
193 	// Shader modules.
194 	{
195 		m_vertexModule				= createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u);
196 		m_fragmentModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
197 		if (m_parameters.enableGeometry)
198 		{
199 			m_vertexPassthroughModule	= createShaderModule(vk, device, m_context.getBinaryCollection().get("vertPassthrough"), 0u);
200 			m_vertexLayerModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("vertLayer"), 0u);
201 			m_geometryModule			= createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
202 			m_geometryLayerModule		= createShaderModule(vk, device, m_context.getBinaryCollection().get("geomLayer"), 0u);
203 		}
204 		if (m_parameters.enableTessellation)
205 		{
206 			m_tscModule					= createShaderModule(vk, device, m_context.getBinaryCollection().get("tsc"), 0u);
207 			m_tseModule					= createShaderModule(vk, device, m_context.getBinaryCollection().get("tse"), 0u);
208 		}
209 	}
210 
211 	// Pipelines.
212 	{
213 		const std::vector<vk::VkViewport>	viewports			(1u, vk::makeViewport(m_parameters.renderSize));
214 		const std::vector<vk::VkRect2D>		scissors			(1u, vk::makeRect2D(m_parameters.renderSize));
215 
216 		VkPipelineRenderingCreateInfoKHR	renderingCreateInfo	=
217 		{
218 			VK_STRUCTURE_TYPE_PIPELINE_RENDERING_CREATE_INFO_KHR,	// VkStructureType	sType
219 			DE_NULL,												// const void*		pNext
220 			0u,														// deUint32			viewMask
221 			1u,														// deUint32			colorAttachmentCount
222 			&m_parameters.imageFormat,								// const VkFormat*	pColorAttachmentFormats
223 			VK_FORMAT_UNDEFINED,									// VkFormat			depthAttachmentFormat
224 			VK_FORMAT_UNDEFINED,									// VkFormat			stencilAttachmentFormat
225 		};
226 
227 		m_pipelineBasic		= makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
228 												   device,									// const VkDevice									device
229 												   *m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
230 												   *m_vertexModule,							// const VkShaderModule								vertexShaderModule
231 												   DE_NULL,									// const VkShaderModule								tessellationControlShaderModule
232 												   DE_NULL,									// const VkShaderModule								tessellationEvalShaderModule
233 												   DE_NULL,									// const VkShaderModule								geometryShaderModule
234 												   *m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
235 												   DE_NULL,									// const VkRenderPass								renderPass
236 												   viewports,								// const std::vector<VkViewport>&					viewports
237 												   scissors,								// const std::vector<VkRect2D>&						scissors
238 												   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
239 												   0u,										// const deUint32									subpass
240 												   0u,										// const deUint32									patchControlPoints
241 												   DE_NULL,									// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
242 												   DE_NULL,									// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
243 												   DE_NULL,									// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
244 												   DE_NULL,									// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
245 												   DE_NULL,									// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
246 												   DE_NULL,									// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
247 												   &renderingCreateInfo);					// const void*										pNext
248 
249 		if (m_parameters.enableGeometry)
250 		{
251 			m_pipelineGeom = makeGraphicsPipeline(
252 					vk,									// const DeviceInterface&							vk
253 					device,								// const VkDevice									device
254 					*m_pipelineLayout,					// const VkPipelineLayout							pipelineLayout
255 					*m_vertexPassthroughModule,			// const VkShaderModule								vertexShaderModule
256 					DE_NULL,							// const VkShaderModule								tessellationControlShaderModule
257 					DE_NULL,							// const VkShaderModule								tessellationEvalShaderModule
258 					*m_geometryModule,					// const VkShaderModule								geometryShaderModule
259 					*m_fragmentModule,					// const VkShaderModule								fragmentShaderModule
260 					DE_NULL,							// const VkRenderPass								renderPass
261 					viewports,							// const std::vector<VkViewport>&					viewports
262 					scissors,							// const std::vector<VkRect2D>&						scissors
263 					VK_PRIMITIVE_TOPOLOGY_POINT_LIST,	// const VkPrimitiveTopology						topology
264 					0u,									// const deUint32									subpass
265 					0u,									// const deUint32									patchControlPoints
266 					DE_NULL,							// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
267 					DE_NULL,							// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
268 					DE_NULL,							// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
269 					DE_NULL,							// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
270 					DE_NULL,							// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
271 					DE_NULL,							// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
272 					&renderingCreateInfo);				// const void*										pNext
273 
274 			m_pipelineLayer = makeGraphicsPipeline(
275 					vk,										// const DeviceInterface&							vk
276 					device,									// const VkDevice									device
277 					*m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
278 					*m_vertexLayerModule,					// const VkShaderModule								vertexShaderModule
279 					DE_NULL,								// const VkShaderModule								tessellationControlShaderModule
280 					DE_NULL,								// const VkShaderModule								tessellationEvalShaderModule
281 					*m_geometryLayerModule,					// const VkShaderModule								geometryShaderModule
282 					*m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
283 					DE_NULL,								// const VkRenderPass								renderPass
284 					viewports,								// const std::vector<VkViewport>&					viewports
285 					scissors,								// const std::vector<VkRect2D>&						scissors
286 					VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
287 					0u,										// const deUint32									subpass
288 					0u,										// const deUint32									patchControlPoints
289 					DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
290 					DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
291 					DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
292 					DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
293 					DE_NULL,								// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
294 					DE_NULL,								// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
295 					&renderingCreateInfo);					// const void*										pNext
296 		}
297 
298 		if (m_parameters.enableTessellation)
299 		{
300 			m_pipelineTess = makeGraphicsPipeline(
301 					vk,										// const DeviceInterface&							vk
302 					device,									// const VkDevice									device
303 					*m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
304 					*m_vertexModule,						// const VkShaderModule								vertexShaderModule
305 					*m_tscModule,							// const VkShaderModule								tessellationControlShaderModule
306 					*m_tseModule,							// const VkShaderModule								tessellationEvalShaderModule
307 					DE_NULL,								// const VkShaderModule								geometryShaderModule
308 					*m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
309 					DE_NULL,								// const VkRenderPass								renderPass
310 					viewports,								// const std::vector<VkViewport>&					viewports
311 					scissors,								// const std::vector<VkRect2D>&						scissors
312 					vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,	// const VkPrimitiveTopology						topology
313 					0u,										// const deUint32									subpass
314 					4u,										// const deUint32									patchControlPoints
315 					DE_NULL,								// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
316 					DE_NULL,								// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
317 					DE_NULL,								// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
318 					DE_NULL,								// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
319 					DE_NULL,								// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
320 					DE_NULL,								// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
321 					&renderingCreateInfo);					// const void*										pNext
322 		}
323 
324 		renderingCreateInfo.viewMask = 0xb; // 1011b
325 		m_pipelineMultiview	= makeGraphicsPipeline(vk,										// const DeviceInterface&							vk
326 												   device,									// const VkDevice									device
327 												   *m_pipelineLayout,						// const VkPipelineLayout							pipelineLayout
328 												   *m_vertexModule,							// const VkShaderModule								vertexShaderModule
329 												   DE_NULL,									// const VkShaderModule								tessellationControlShaderModule
330 												   DE_NULL,									// const VkShaderModule								tessellationEvalShaderModule
331 												   DE_NULL,									// const VkShaderModule								geometryShaderModule
332 												   *m_fragmentModule,						// const VkShaderModule								fragmentShaderModule
333 												   DE_NULL,									// const VkRenderPass								renderPass
334 												   viewports,								// const std::vector<VkViewport>&					viewports
335 												   scissors,								// const std::vector<VkRect2D>&						scissors
336 												   VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,	// const VkPrimitiveTopology						topology
337 												   0u,										// const deUint32									subpass
338 												   0u,										// const deUint32									patchControlPoints
339 												   DE_NULL,									// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
340 												   DE_NULL,									// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
341 												   DE_NULL,									// const VkPipelineMultisampleStateCreateInfo*		multisampleStateCreateInfo
342 												   DE_NULL,									// const VkPipelineDepthStencilStateCreateInfo*		depthStencilStateCreateInfo
343 												   DE_NULL,									// const VkPipelineColorBlendStateCreateInfo*		colorBlendStateCreateInfo
344 												   DE_NULL,									// const VkPipelineDynamicStateCreateInfo*			dynamicStateCreateInfo
345 												   &renderingCreateInfo);					// const void*										pNext
346 	}
347 
348 	// Query result buffer.
349 	{
350 		const VkDeviceSize			bufferSize = 1024u;
351 		const VkBufferCreateInfo	bufferInfo = makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFER_DST_BIT);
352 
353 		m_queryResults = Draw::Buffer::createAndAlloc(vk, device, bufferInfo, allocator, MemoryRequirement::HostVisible);
354 	}
355 
356 	// Query pool.
357 	{
358 		VkQueryPoolCreateInfo	queryPoolInfo	=
359 		{
360 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType
361 			DE_NULL,									// const void*						pNext
362 			0,											// VkQueryPoolCreateFlags			flags
363 			vk::VK_QUERY_TYPE_OCCLUSION,				// VkQueryType						queryType
364 			maxQueries,									// uint32_t							queryCount
365 			0											// VkQueryPipelineStatisticFlags	pipelineStatistics
366 		};
367 
368 		m_queryPool	= createQueryPool(vk, device, &queryPoolInfo);
369 	}
370 }
371 
372 
iterate(void)373 tcu::TestStatus DynamicRenderingTestInstance::iterate (void)
374 {
375 	const DeviceInterface&				vk				= m_context.getDeviceInterface();
376 	const VkDevice						device			= m_context.getDevice();
377 	const VkQueue						queue			= m_context.getUniversalQueue();
378 	const deUint32						queueFamily		= m_context.getUniversalQueueFamilyIndex();
379 	tcu::TestLog&						log				= m_context.getTestContext().getLog();
380 
381 	std::vector<Move<VkCommandBuffer>>	cmdBuffers;
382 	std::vector<Move<VkCommandBuffer>>	secondaryCmdBuffers;
383 	std::vector<tcu::TextureLevel>		ref;
384 
385 	for (deUint32 i = 0; i < numLayers; i++)
386 	{
387 		ref.emplace_back(mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(), m_parameters.renderSize.y(), 1u);
388 
389 		tcu::PixelBufferAccess	access = ref[i].getAccess();
390 
391 		for (deUint32 y = 0; y < m_parameters.renderSize.x(); y++)
392 			for (deUint32 x = 0; x < m_parameters.renderSize.x(); x++)
393 				access.setPixel(Vec4(0.0f), x, y);
394 	}
395 
396 	cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
397 	beginCommandBuffer(vk, *cmdBuffers.back());
398 	vk.cmdResetQueryPool(*cmdBuffers.back(), *m_queryPool, 0, maxQueries);
399 
400 	clearColorImage(vk, device, queue, queueFamily, *m_imageColor, Vec4(0.0),
401 					VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,
402 					VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT, 0u, numLayers);
403 
404 	VkRenderingFlagsKHR					prevFlags		= 0;
405 	Vec4								clearColor		= Vec4(0.0f);
406 	VkRect2D							renderArea		= makeRect2D(0, 0, 0, 0);
407 	VkAttachmentLoadOp					loadOp			= VK_ATTACHMENT_LOAD_OP_CLEAR;
408 	deUint32							renderWidth		= 0u;
409 	deUint32							renderHeight	= 0u;
410 	deUint32							renderX			= 0u;
411 	deUint32							renderY			= 0u;
412 	deUint32							quadShrink		= 0u;
413 	deUint32							queryIndex		= 0u;
414 	std::vector<uint32_t>				queryMultiviewCount;
415 
416 	enum PipelineType
417 	{
418 		PIPELINE_TYPE_VERTEX_FRAGMENT = 0,
419 		PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT = 1,
420 		PIPELINE_TYPE_VERTEX_TESS_FRAGMENT = 2,
421 		PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER = 3,
422 		PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW = 4,
423 		PIPELINE_TYPE_ATTACHMENT_CLEAR = 5,
424 		PIPELINE_TYPE_MAX = 6
425 	} pipelineType = PIPELINE_TYPE_VERTEX_FRAGMENT;
426 
427 	std::vector<VkPipeline>				pipelines		= {*m_pipelineBasic, *m_pipelineGeom, *m_pipelineTess, *m_pipelineLayer, *m_pipelineMultiview, *m_pipelineBasic};
428 
429 	deUint32							validPipelines	= (1 << PIPELINE_TYPE_VERTEX_FRAGMENT) | (1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);
430 
431 	if (m_parameters.enableGeometry)
432 		validPipelines |= (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT) | (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER);
433 
434 	if (m_parameters.enableTessellation)
435 		validPipelines |= (1 << PIPELINE_TYPE_VERTEX_TESS_FRAGMENT);
436 
437 	const int							numIterations	= 50;
438 
439 	for (int i = 0; i < numIterations; i++)
440 	{
441 		VkRenderingFlagsKHR		flags								= 0;
442 		bool					useSecondaryCmdBuffer				= m_random.getUint32() % 5 == 0;
443 		bool					bindPipelineBeforeBeginRendering	= m_random.getBool();
444 
445 		if (useSecondaryCmdBuffer)
446 		{
447 			flags |= VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR;
448 			// Pipeline bind needs to go to the same command buffer that has the draw call.
449 			bindPipelineBeforeBeginRendering = false;
450 		}
451 
452 		if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
453 		{
454 			// Resuming: Don't touch the beginRendering parameters as they need to
455 			// match with the previous command buffer.
456 
457 			flags |= VK_RENDERING_RESUMING_BIT_KHR;
458 
459 			// Use a new command buffer.
460 			VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));
461 
462 			cmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
463 			beginCommandBuffer(vk, *cmdBuffers.back());
464 
465 			// Make the drawn quad smaller so the previous quad is still visible.
466 			quadShrink++;
467 
468 			// Pipeline bind is not allowed between suspend and resume.
469 			bindPipelineBeforeBeginRendering = false;
470 		}
471 		else
472 		{
473 			// Not resuming: we can randomize new beginRendering parameters.
474 			clearColor		= Vec4(m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f);
475 
476 			const deUint32 minAreaSize = 32u;
477 			// Use a render area with an even size to make the margin around the quad symmetrical.
478 			renderWidth		= (m_random.getUint32() % (m_parameters.renderSize.x() / 2 - minAreaSize) + minAreaSize) & (~1u);
479 			renderHeight	= (m_random.getUint32() % (m_parameters.renderSize.y() / 2 - minAreaSize) + minAreaSize) & (~1u);
480 			renderX			= m_random.getUint32() % (m_parameters.renderSize.x() - renderWidth);
481 			renderY			= m_random.getUint32() % (m_parameters.renderSize.y() - renderHeight);
482 			renderArea		= { makeOffset2D(renderX, renderY), makeExtent2D(renderWidth, renderHeight) };
483 			loadOp			= m_random.getBool() ? vk::VK_ATTACHMENT_LOAD_OP_CLEAR : VK_ATTACHMENT_LOAD_OP_LOAD;
484 			quadShrink		= 0u;
485 		}
486 
487 		// Randomize pipeline type on every round. Multiview pipeline is an exception: the view mask cannot change
488 		// between suspend and resume.
489 		if (!(prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR) || pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
490 		{
491 			deUint32 pipelineMask = validPipelines;
492 
493 			if (prevFlags & VK_RENDERING_SUSPENDING_BIT_KHR)
494 			{
495 				// If resuming from non-multiview pipeline the new pipeline must also be non-multiview to keep the view mask.
496 				if (pipelineType != PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
497 					pipelineMask &= ~(1 << PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW);
498 
499 				// The number of layers need to match too.
500 				const deUint32	layeredPipelines = (1 << PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER) | (1 << PIPELINE_TYPE_ATTACHMENT_CLEAR);
501 				if ((1 << pipelineType) & layeredPipelines)
502 				{
503 					// Filter out all non-layered pipelines.
504 					pipelineMask &= layeredPipelines;
505 				}
506 				else
507 				{
508 					// Filter out all layered pipelines.
509 					pipelineMask &= ~layeredPipelines;
510 				}
511 			}
512 
513 			do
514 			{
515 				pipelineType = static_cast<PipelineType>(m_random.getUint32() % PIPELINE_TYPE_MAX);
516 			} while (((1 << pipelineType) & pipelineMask) == 0);
517 		}
518 
519 		const bool				occlusionQuery						= m_random.getBool() && pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR;
520 		const deUint32			viewMask							= pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW ? 0xb /* 1011b */ : 0;
521 		const bool				useLayers							= pipelineType == PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER || pipelineType == PIPELINE_TYPE_ATTACHMENT_CLEAR;
522 		const bool				suspend								= m_random.getUint32() % 5 == 0 && i != numIterations - 1;
523 
524 		if (suspend)
525 		{
526 			flags |= VK_RENDERING_SUSPENDING_BIT_KHR;
527 		}
528 
529 		const VkClearValue	clearValue								= makeClearValueColor(clearColor);
530 
531 		if (bindPipelineBeforeBeginRendering)
532 			vk.cmdBindPipeline(*cmdBuffers.back(), VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);
533 
534 		// Begin rendering
535 		{
536 			const VkRenderingAttachmentInfoKHR	renderingAttachmentInfo	=
537 			{
538 				VK_STRUCTURE_TYPE_RENDERING_ATTACHMENT_INFO_KHR,	// VkStructureType			sType
539 				DE_NULL,											// const void*				pNext
540 				*m_colorAttachmentView,								// VkImageView				imageView
541 				VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,			// VkImageLayout			imageLayout
542 				VK_RESOLVE_MODE_NONE,								// VkResolveModeFlagBits	resolveMode
543 				DE_NULL,											// VkImageView				resolveImageView
544 				VK_IMAGE_LAYOUT_UNDEFINED,							// VkImageLayout			resolveImageLayout
545 				loadOp,												// VkAttachmentLoadOp		loadOp
546 				VK_ATTACHMENT_STORE_OP_STORE,						// VkAttachmentStoreOp		storeOp
547 				clearValue											// VkClearValue				clearValue
548 			};
549 
550 			const VkRenderingInfoKHR			renderingInfo			=
551 			{
552 				VK_STRUCTURE_TYPE_RENDERING_INFO_KHR,				// VkStructureType						sType
553 				DE_NULL,											// const void*							pNext
554 				flags,												// VkRenderingFlagsKHR					flags
555 				renderArea,											// VkRect2D								renderArea
556 				useLayers ? numLayers : 1u,							// deUint32								layerCount
557 				viewMask,											// deUint32								viewMask
558 				1u,													// deUint32								colorAttachmentCount
559 				&renderingAttachmentInfo,							// const VkRenderingAttachmentInfoKHR*	pColorAttachments
560 				DE_NULL,											// const VkRenderingAttachmentInfoKHR*	pDepthAttachment
561 				DE_NULL												// const VkRenderingAttachmentInfoKHR*	pStencilAttachment
562 			};
563 
564 			vk.cmdBeginRendering(*cmdBuffers.back(), &renderingInfo);
565 		}
566 
567 		if (useSecondaryCmdBuffer)
568 		{
569 			secondaryCmdBuffers.push_back(allocateCommandBuffer(vk, device, *m_cmdPool, vk::VK_COMMAND_BUFFER_LEVEL_SECONDARY));
570 
571 			const VkCommandBufferInheritanceRenderingInfoKHR	inheritanceRenderingInfo	=
572 			{
573 					VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_RENDERING_INFO_KHR,	// VkStructureType			sType
574 					DE_NULL,															// const void*				pNext
575 					flags & ~VK_RENDERING_CONTENTS_SECONDARY_COMMAND_BUFFERS_BIT_KHR,	// VkRenderingFlagsKHR		flags
576 					viewMask,															// uint32_t					viewMask
577 					1u,																	// uint32_t					colorAttachmentCount
578 					&m_parameters.imageFormat,											// const VkFormat*			pColorAttachmentFormats
579 					VK_FORMAT_UNDEFINED,												// VkFormat					depthAttachmentFormat
580 					VK_FORMAT_UNDEFINED,												// VkFormat					stencilAttachmentFormat
581 					VK_SAMPLE_COUNT_1_BIT,												// VkSampleCountFlagBits	rasterizationSamples
582 			};
583 
584 			const VkCommandBufferInheritanceInfo				bufferInheritanceInfo		=
585 			{
586 					vk::VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,				// VkStructureType					sType
587 					&inheritanceRenderingInfo,											// const void*						pNext
588 					DE_NULL,															// VkRenderPass						renderPass
589 					0u,																	// deUint32							subpass
590 					DE_NULL,															// VkFramebuffer					framebuffer
591 					VK_FALSE,															// VkBool32							occlusionQueryEnable
592 					(VkQueryControlFlags)0u,											// VkQueryControlFlags				queryFlags
593 					(VkQueryPipelineStatisticFlags)0u									// VkQueryPipelineStatisticFlags	pipelineStatistics
594 			};
595 
596 			const VkCommandBufferBeginInfo						commandBufBeginParams		=
597 			{
598 					VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,						// VkStructureType				sType
599 					DE_NULL,															// const void*					pNext
600 					VK_COMMAND_BUFFER_USAGE_ONE_TIME_SUBMIT_BIT |
601 					VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,					// VkCommandBufferUsageFlags	flags
602 					&bufferInheritanceInfo
603 			};
604 
605 			VK_CHECK(vk.beginCommandBuffer(*secondaryCmdBuffers.back(), &commandBufBeginParams));
606 		}
607 
608 		const VkCommandBuffer&	cmdBuffer							= useSecondaryCmdBuffer ? *secondaryCmdBuffers.back() : *cmdBuffers.back();
609 
610 		if (!bindPipelineBeforeBeginRendering)
611 			vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipelines[pipelineType]);
612 
613 		// Calculate push constant data.
614 		const float				scaleX								= static_cast<float>(renderArea.extent.width - quadShrink * 4) / static_cast<float>(m_parameters.renderSize.x());
615 		const float				scaleY								= static_cast<float>(renderArea.extent.height - quadShrink * 4) / static_cast<float>(m_parameters.renderSize.y());
616 
617 		DE_ASSERT(scaleX > 0.0f);
618 		DE_ASSERT(scaleY > 0.0f);
619 
620 		const float				pixelSizeX							= 2.0f / static_cast<float>(m_parameters.renderSize.x());
621 		const float				pixelSizeY							= 2.0f / static_cast<float>(m_parameters.renderSize.y());
622 		const Vec4				scale								= {scaleX + pixelSizeX * 0.5f, scaleY + pixelSizeY * 0.5f, 1.0f, 1.0f};
623 		const float				offsetX								= static_cast<float>(renderArea.offset.x - static_cast<int>(m_parameters.renderSize.x() - renderArea.extent.width) / 2) * pixelSizeX;
624 		const float				offsetY								= static_cast<float>(renderArea.offset.y - static_cast<int>(m_parameters.renderSize.y() - renderArea.extent.height) / 2) * pixelSizeY;
625 		const Vec4				offset								= {offsetX, offsetY, 0.0f, 0.0f};
626 		const deUint32			quadMarginX							= renderWidth / 4 + quadShrink;
627 		const deUint32			quadMarginY							= renderHeight / 4 + quadShrink;
628 		const deUint32			quadTop								= renderY + quadMarginY;
629 		const deUint32			quadBottom							= renderY + renderHeight - quadMarginY;
630 		const deUint32			quadLeft							= renderX + quadMarginX;
631 		const deUint32			quadRight							= renderX + renderWidth - quadMarginX;
632 
633 		const Vec4				color								= {m_random.getFloat(), m_random.getFloat(), m_random.getFloat(), 1.0f};
634 		const deInt32			layer								= useLayers ? m_random.getUint32() % numLayers : 0;
635 
636 		PushConstantData		pcd									= {scale, offset, color, layer};
637 
638 		// Bind vertex buffer.
639 		{
640 			const VkBuffer		vertexBuffer		= m_vertexBuffer->object();
641 			const VkDeviceSize	vertexBufferOffset	= 0ull;
642 
643 			vk.cmdBindVertexBuffers(cmdBuffer, 0u, 1u, &vertexBuffer, &vertexBufferOffset);
644 		}
645 
646 		if (occlusionQuery)
647 			vk.cmdBeginQuery(cmdBuffer, *m_queryPool, queryIndex, 0);
648 
649 		vk.cmdPushConstants(cmdBuffer, *m_pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT | VK_SHADER_STAGE_GEOMETRY_BIT, 0, sizeof(pcd), &pcd);
650 
651 		// Draw or clear a quad inside the render area.
652 		switch (pipelineType)
653 		{
654 			case PIPELINE_TYPE_VERTEX_FRAGMENT: // A quad using triangle strip.
655 			case PIPELINE_TYPE_VERTEX_TESS_FRAGMENT: // A quad using a tessellated patch.
656 			case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT_LAYER: // A quad using triangle strip drawn to a chosen layer.
657 			case PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW: // A quad using triangle strip drawn to layers 0, 1, and 3.
658 			{
659 				vk.cmdDraw(cmdBuffer, 4u, 1u, 0u, 0u);
660 			}
661 			break;
662 			case PIPELINE_TYPE_VERTEX_GEOM_FRAGMENT: // A single point turned into a quad by geometry shader.
663 			{
664 				vk.cmdDraw(cmdBuffer, 1u, 1u, 0u, 0u);
665 			}
666 			break;
667 			case PIPELINE_TYPE_ATTACHMENT_CLEAR: // A quad using vkCmdClearAttachments
668 			{
669 				VkClearAttachment	clearAttachment	= { VK_IMAGE_ASPECT_COLOR_BIT, 0u, makeClearValueColor(color) };
670 				VkClearRect			rect			= { makeRect2D(quadLeft, quadTop, quadRight - quadLeft, quadBottom - quadTop), static_cast<deUint32>(layer), 1u };
671 
672 				vk.cmdClearAttachments(cmdBuffer, 1u, &clearAttachment, 1u, &rect);
673 			}
674 			break;
675 			default:
676 			{
677 				DE_ASSERT(0 && "Unexpected pipeline type.");
678 			}
679 			break;
680 		}
681 
682 		if (occlusionQuery)
683 		{
684 			vk.cmdEndQuery(cmdBuffer, *m_queryPool, queryIndex);
685 			if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW) {
686 				queryIndex += 3;
687 				queryMultiviewCount.push_back(3);
688 				queryMultiviewCount.push_back(0);
689 				queryMultiviewCount.push_back(0);
690 			}
691 			else
692 			{
693 				queryIndex++;
694 				queryMultiviewCount.push_back(1);
695 			}
696 		}
697 
698 		deUint32				activeLayersClear					= 0x1;
699 		deUint32				activeLayersQuad					= 0x1;
700 
701 		if (useLayers)
702 		{
703 			activeLayersClear	= (1 << numLayers) - 1;
704 			activeLayersQuad	= 1 << layer;
705 		}
706 		else if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
707 		{
708 			activeLayersClear = activeLayersQuad = viewMask;
709 		}
710 
711 		// Update reference image.
712 		for (deUint32 l = 0; l < numLayers; l++)
713 		{
714 			tcu::PixelBufferAccess access = ref[l].getAccess();
715 			for (deUint32 y = renderY; y < renderY + renderHeight; y++)
716 				for (deUint32 x = renderX; x < renderX + renderWidth; x++)
717 				{
718 					if (loadOp == VK_ATTACHMENT_LOAD_OP_CLEAR && !(flags & VK_RENDERING_RESUMING_BIT_KHR) && (activeLayersClear & (1 <<l)))
719 					{
720 						access.setPixel(clearColor, x, y);
721 					}
722 
723 					if (x >= quadLeft && x < quadRight && y >= quadTop && y < quadBottom && (activeLayersQuad & (1 << l)))
724 					{
725 						// Inside the drawn quad.
726 						Vec4 refColor = color;
727 
728 						if (pipelineType == PIPELINE_TYPE_VERTEX_FRAGMENT_MULTIVIEW)
729 							refColor.z() = 0.15f * static_cast<float>(l);
730 						else if (pipelineType != PIPELINE_TYPE_ATTACHMENT_CLEAR)
731 							refColor.z() = 0.0f;
732 
733 						access.setPixel(refColor, x, y);
734 					}
735 				}
736 		}
737 
738 		if (useSecondaryCmdBuffer)
739 		{
740 			// End the secondary buffer
741 			VK_CHECK(vk.endCommandBuffer(cmdBuffer));
742 
743 			// Call the secondary buffer
744 			vk.cmdExecuteCommands(*cmdBuffers.back(), 1u, &cmdBuffer);
745 		}
746 
747 		vk.cmdEndRendering(*cmdBuffers.back());
748 
749 		// Insert a pipeline barrier if not suspending.
750 		if (!suspend)
751 		{
752 			VkMemoryBarrier	barrier	=
753 			{
754 					VK_STRUCTURE_TYPE_MEMORY_BARRIER,		// VkStructureType	sType
755 					DE_NULL,								// const void*		pNext
756 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,	// VkAccessFlags	srcAccessMask
757 					VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT	// VkAccessFlags	dstAccessMask
758 			};
759 
760 			vk.cmdPipelineBarrier(*cmdBuffers.back(), VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, 0u,
761 								  1u, &barrier, 0u, DE_NULL, 0u, DE_NULL);
762 		}
763 
764 		prevFlags = flags;
765 	}
766 
767 	vk.cmdCopyQueryPoolResults(*cmdBuffers.back(), *m_queryPool, 0, queryIndex, m_queryResults->object(), 0, sizeof(deUint32), VK_QUERY_RESULT_WAIT_BIT);
768 	copyImageToBuffer(vk, *cmdBuffers.back(), *m_imageColor, m_imageBuffer->object(),
769 					  tcu::IVec2(m_parameters.renderSize.x(), m_parameters.renderSize.y()),
770 					  VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, numLayers,
771 					  VK_IMAGE_ASPECT_COLOR_BIT, VK_IMAGE_ASPECT_COLOR_BIT);
772 
773 	VK_CHECK(vk.endCommandBuffer(*cmdBuffers.back()));
774 
775 	// Submit commands and wait.
776 	{
777 		const Unique<VkFence>			fence				(createFence(vk, device));
778 		std::vector<VkCommandBuffer>	cmdBufferHandles;
779 
780 		for (const auto& cmdBuffer : cmdBuffers)
781 			cmdBufferHandles.push_back(*cmdBuffer);
782 
783 		const VkSubmitInfo				submitInfo			=
784 		{
785 			VK_STRUCTURE_TYPE_SUBMIT_INFO,					// VkStructureType				sType
786 			DE_NULL,										// const void*					pNext
787 			0u,												// deUint32						waitSemaphoreCount
788 			DE_NULL,										// const VkSemaphore*			pWaitSemaphores
789 			DE_NULL,										// const VkPipelineStageFlags*	pWaitDstStageMask
790 			static_cast<deUint32>(cmdBufferHandles.size()),	// deUint32						commandBufferCount
791 			cmdBufferHandles.data(),						// const VkCommandBuffer*		pCommandBuffers
792 			0u,												// deUint32						signalSemaphoreCount
793 			DE_NULL,										// const VkSemaphore*			pSignalSemaphores
794 		};
795 
796 		VK_CHECK(vk.queueSubmit(queue, 1u, &submitInfo, *fence));
797 		VK_CHECK(vk.waitForFences(device, 1u, &fence.get(), DE_TRUE, ~0ull));
798 	}
799 
800 	// Verify result image.
801 	for (deUint32 i = 0; i < numLayers; i++)
802 	{
803 		const Allocation					allocColor			= m_imageBuffer->getBoundMemory();
804 		invalidateAlloc(vk, device, allocColor);
805 
806 		const tcu::ConstPixelBufferAccess	resultColorImage	(mapVkFormat(m_parameters.imageFormat), m_parameters.renderSize.x(),
807 																 m_parameters.renderSize.y(), 1u, static_cast<deUint8*>(allocColor.getHostPtr()) + m_layerSizeBytes * i);
808 
809 		if (!tcu::floatThresholdCompare(log, "Compare Color Image", "Result comparison", ref[i].getAccess(), resultColorImage, Vec4(0.02f), tcu::COMPARE_LOG_ON_ERROR))
810 		{
811 			return tcu::TestStatus::fail("Rendered color image is not correct");
812 		}
813 	}
814 
815 	// Verify query pool results.
816 	{
817 		deUint32* queryPtr = static_cast<deUint32*>(m_queryResults->getBoundMemory().getHostPtr());
818 		invalidateAlloc(vk, device, m_queryResults->getBoundMemory());
819 
820 		deUint32 i = 0;
821 		while (i < queryIndex)
822 		{
823 			uint32_t querySum = 0;
824 			for (uint32_t j = 0; j < queryMultiviewCount[i]; j++) {
825 				querySum += queryPtr[i];
826 			}
827 			if (querySum == 0)
828 			{
829 				return tcu::TestStatus::fail("Expected nonzero occlusion query results.");
830 			}
831 			i += queryMultiviewCount[i];
832 		}
833 	}
834 
835 	return tcu::TestStatus::pass("Pass");
836 }
837 
838 class RandomTestCase : public TestCase
839 {
840 public:
841 							RandomTestCase	(tcu::TestContext&		context,
842 											 const std::string&		name,
843 											 const std::string&		description,
844 											 const TestParameters&	parameters);
845 	virtual					~RandomTestCase	(void);
846 
847 protected:
848 	virtual void			checkSupport	(Context&				context) const;
849 	virtual void			initPrograms	(SourceCollections&		programCollection) const;
850 	virtual TestInstance*	createInstance	(Context&				context) const;
851 
852 	const TestParameters	m_parameters;
853 };
854 
RandomTestCase(tcu::TestContext & context,const std::string & name,const std::string & description,const TestParameters & parameters)855 RandomTestCase::RandomTestCase (tcu::TestContext&		context,
856 								const std::string&		name,
857 								const std::string&		description,
858 								const TestParameters&	parameters)
859 : TestCase		(context, name, description)
860 , m_parameters	(parameters)
861 {
862 }
863 
~RandomTestCase()864 RandomTestCase::~RandomTestCase ()
865 {
866 }
867 
checkSupport(Context & context) const868 void RandomTestCase::checkSupport (Context& context) const
869 {
870 	if (!context.requireDeviceFunctionality("VK_KHR_dynamic_rendering"))
871 		TCU_THROW(NotSupportedError, "VK_KHR_dynamic_rendering is not supported");
872 
873 	const VkPhysicalDeviceDynamicRenderingFeaturesKHR& dynamicRenderingFeatures(context.getDynamicRenderingFeatures());
874 
875 	if (dynamicRenderingFeatures.dynamicRendering == DE_FALSE)
876 		TCU_THROW(NotSupportedError, "dynamicRendering feature is not supported");
877 
878 	if (m_parameters.enableGeometry)
879 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
880 	if (m_parameters.enableTessellation)
881 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
882 }
883 
initPrograms(SourceCollections & programCollection) const884 void RandomTestCase::initPrograms (SourceCollections& programCollection) const
885 {
886 	const std::string pushConstant =
887 		"layout( push_constant ) uniform constants\n"
888 		"{\n"
889 		"	vec4 scale;\n"
890 		"	vec4 offset;\n"
891 		"	vec4 color;\n"
892 		"	int layer;\n"
893 		"} pc;\n";
894 
895 	// Vertex
896 	{
897 		std::ostringstream src;
898 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
899 			<< "\n"
900 			<< "layout(location = 0) in vec4 position;\n"
901 			<< "layout(location = 0) out vec4 vsColor;\n"
902 			<< "\n"
903 			<< pushConstant
904 			<< "\n"
905 			<< "void main (void)\n"
906 			<< "{\n"
907 			<< "    gl_Position = position * pc.scale + pc.offset;\n"
908 			<< "    vsColor     = pc.color;\n"
909 			<< "}\n";
910 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
911 	}
912 
913 	// Passthrough vertex
914     if (m_parameters.enableGeometry)
915 	{
916 		std::ostringstream src;
917 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
918 			<< "\n"
919 			<< "layout(location = 0) in vec4 position;\n"
920 			<< "\n"
921 			<< "void main (void)\n"
922 			<< "{\n"
923 			<< "    gl_Position = position;\n"
924 			<< "}\n";
925 		programCollection.glslSources.add("vertPassthrough") << glu::VertexSource(src.str());
926 	}
927 
928 	// Vertex layered
929 	if (m_parameters.enableGeometry)
930 	{
931 		std::ostringstream src;
932 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
933 			<< "layout(location = 0) in vec4 position;\n"
934 			<< "layout(location = 0) out vec4 positionOut;\n"
935 			<< "\n"
936 			<< pushConstant
937 			<< "\n"
938 			<< "void main (void)\n"
939 			<< "{\n"
940 			<< "    positionOut = position * pc.scale + pc.offset;\n"
941 			<< "}\n";
942 		programCollection.glslSources.add("vertLayer") << glu::VertexSource(src.str());
943 	}
944 
945 	// Geometry
946 	if (m_parameters.enableGeometry)
947 	{
948 		std::ostringstream src;
949 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
950 			<< "\n"
951 			<< "layout(points) in;\n"
952 			<< "layout(triangle_strip, max_vertices = 4) out;\n"
953 			<< "layout(location = 0) out vec4 vsColor;\n"
954 			<< "\n"
955 			<< pushConstant
956 			<< "\n"
957 			<< "void main (void)\n"
958 			<< "{\n"
959 			<< "    vec4 quad[4] = vec4[4](vec4(-0.5, 0.5, 0, 1), vec4(-0.5, -0.5, 0, 1), vec4(0.5, 0.5, 0, 1), vec4(0.5, -0.5, 0, 1));\n"
960 			<< "    for (int i = 0; i < 4; i++)\n"
961 			<< "    {\n"
962 			<< "        gl_Position = quad[i] * pc.scale + pc.offset;\n"
963 			<< "        vsColor     = pc.color;\n"
964 			<< "        EmitVertex();\n"
965 			<< "    }\n"
966 			<< "    EndPrimitive();\n"
967 			<< "}\n";
968 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
969 	}
970 
971 	// Geometry passthrough with layer
972 	if (m_parameters.enableGeometry)
973 	{
974 		std::ostringstream src;
975 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
976 			<< "\n"
977 			<< "layout(triangles) in;\n"
978 			<< "layout(triangle_strip, max_vertices = 3) out;\n"
979 			<< "layout(location = 0) in vec4 position[];\n"
980 			<< "layout(location = 0) out vec4 vsColor;\n"
981 			<< "\n"
982 			<< pushConstant
983 			<< "\n"
984 			<< "void main (void)\n"
985 			<< "{\n"
986 			<< "    for (int i = 0; i < 3; i++)\n"
987 			<< "    {\n"
988 			<< "        gl_Position = position[i];\n"
989 			<< "        vsColor     = pc.color;\n"
990 			<< "        gl_Layer    = pc.layer;\n"
991 			<< "        EmitVertex();\n"
992 			<< "    }\n"
993 			<< "    EndPrimitive();\n"
994 			<< "}\n";
995 		programCollection.glslSources.add("geomLayer") << glu::GeometrySource(src.str());
996 	}
997 
998 	// Tessellation control
999 	if (m_parameters.enableTessellation)
1000 	{
1001 		std::ostringstream src;
1002 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1003 			<< "\n"
1004 			<< "layout(vertices = 4) out;\n"
1005 			<< "layout(location = 0) in vec4 in_color[];\n"
1006 			<< "layout(location = 0) out vec4 out_color[];\n"
1007 			<< "\n"
1008 			<< "void main (void)\n"
1009 			<< "{\n"
1010 			<< "    if (gl_InvocationID == 0)\n"
1011 			<< "    {\n"
1012 			<< "        gl_TessLevelInner[0] = 2.0f;\n"
1013 			<< "        gl_TessLevelInner[1] = 2.0f;\n"
1014 			<< "        gl_TessLevelOuter[0] = 2.0f;\n"
1015 			<< "        gl_TessLevelOuter[1] = 2.0f;\n"
1016 			<< "        gl_TessLevelOuter[2] = 2.0f;\n"
1017 			<< "        gl_TessLevelOuter[3] = 2.0f;\n"
1018 			<< "    }\n"
1019 			<< "    out_color[gl_InvocationID] = in_color[gl_InvocationID];\n"
1020 			<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1021 			<< "}\n";
1022 		programCollection.glslSources.add("tsc") << glu::TessellationControlSource(src.str());
1023 	}
1024 
1025 	// Tessellation evaluation
1026 	if (m_parameters.enableTessellation)
1027 	{
1028 		std::ostringstream src;
1029 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1030 			<< "\n"
1031 			<< "layout(quads, equal_spacing, ccw) in;\n"
1032 			<< "layout(location = 0) in vec4 in_color[];\n"
1033 			<< "layout(location = 0) out vec4 out_color;\n"
1034 			<< "void main (void)\n"
1035 			<< "{\n"
1036 			<< "    const float u = gl_TessCoord.x;\n"
1037 			<< "    const float v = gl_TessCoord.y;\n"
1038 			<< "    gl_Position = (1 - u) * (1 - v) * gl_in[0].gl_Position + (1 - u) * v * gl_in[1].gl_Position + u * (1 - v) * gl_in[2].gl_Position + u * v * gl_in[3].gl_Position;\n"
1039 			<< "    out_color = in_color[0];\n"
1040 			<< "}\n";
1041 		programCollection.glslSources.add("tse") << glu::TessellationEvaluationSource(src.str());
1042 	}
1043 
1044 	// Fragment
1045 	{
1046 		std::ostringstream src;
1047 		src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
1048 			<< "#extension GL_EXT_multiview : require\n"
1049 			<< "\n"
1050 			<< "layout(location = 0) in vec4 vsColor;\n"
1051 			<< "layout(location = 0) out vec4 fsColor;\n"
1052 			<< "\n"
1053 			<< "void main (void)\n"
1054 			<< "{\n"
1055 			<< "    fsColor   = vsColor;\n"
1056 			<< "    fsColor.z = 0.15f * gl_ViewIndex;\n"
1057 			<< "}\n";
1058 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1059 	}
1060 }
1061 
createInstance(Context & context) const1062 TestInstance*	RandomTestCase::createInstance (Context& context) const
1063 {
1064 	return new DynamicRenderingTestInstance(context, m_parameters);
1065 }
1066 
addDynamicRenderingTest(tcu::TestContext & testCtx,TestParameters & parameters)1067 tcu::TestNode* addDynamicRenderingTest (tcu::TestContext& testCtx, TestParameters& parameters)
1068 {
1069 	const std::string testName = "seed" + de::toString(parameters.randomSeed) + (parameters.enableGeometry ? "_geometry" : "") + (parameters.enableTessellation ? "_tessellation" : "");
1070 
1071 	return new RandomTestCase(testCtx, testName, "", parameters);
1072 }
1073 
1074 } // anonymous
1075 
createDynamicRenderingRandomTests(tcu::TestContext & testCtx)1076 tcu::TestCaseGroup* createDynamicRenderingRandomTests(tcu::TestContext& testCtx)
1077 {
1078 	de::MovePtr<tcu::TestCaseGroup> dynamicRenderingGroup (new tcu::TestCaseGroup(testCtx, "random", "Random dynamic rendering tests"));
1079 
1080 	for (auto geometry : {true, false})
1081 		for (auto tessellation : {true, false})
1082 		{
1083 			TestParameters parameters =
1084 			{
1085 				VK_FORMAT_R8G8B8A8_UNORM,
1086 				(UVec2(256, 256)),
1087 				geometry,
1088 				tessellation,
1089 				0u
1090 			};
1091 
1092 			for (deUint32 i = 0; i < 100u; i++)
1093 			{
1094 				parameters.randomSeed = i;
1095 				dynamicRenderingGroup->addChild(addDynamicRenderingTest(testCtx, parameters));
1096 			}
1097 		}
1098 
1099 	return dynamicRenderingGroup.release();
1100 }
1101 
1102 } // renderpass
1103 } // vkt
1104