• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 Google LLC
6  *
7  * Licensed under the Apache License, Version 2.0 (the "License");
8  * you may not use this file except in compliance with the License.
9  * You may obtain a copy of the License at
10  *
11  *      http://www.apache.org/licenses/LICENSE-2.0
12  *
13  * Unless required by applicable law or agreed to in writing, software
14  * distributed under the License is distributed on an "AS IS" BASIS,
15  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
16  * See the License for the specific language governing permissions and
17  * limitations under the License.
18  *
19  *//*!
20  * \file
21  * \brief VK_EXT_primitives_generated_query Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktPrimitivesGeneratedQueryTests.hpp"
25 
26 #include "vktTestCase.hpp"
27 #include "vktTestGroupUtil.hpp"
28 
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkMemUtil.hpp"
32 #include "vkObjUtil.hpp"
33 #include "vkQueryUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 #include "vkBarrierUtil.hpp"
36 
37 #include "tcuTestLog.hpp"
38 #include "tcuTextureUtil.hpp"
39 #include "tcuImageCompare.hpp"
40 
41 #include <functional>
42 #include <map>
43 #include <set>
44 
45 namespace vkt
46 {
47 namespace TransformFeedback
48 {
49 namespace
50 {
51 using namespace vk;
52 
53 enum
54 {
55 	IMAGE_WIDTH		= 64,
56 	IMAGE_HEIGHT	= IMAGE_WIDTH,
57 };
58 
59 enum QueryReadType
60 {
61 	QUERY_READ_TYPE_GET,
62 	QUERY_READ_TYPE_COPY,
63 
64 	QUERY_READ_TYPE_LAST
65 };
66 
67 enum QueryResetType
68 {
69 	QUERY_RESET_TYPE_QUEUE,
70 	QUERY_RESET_TYPE_HOST,
71 
72 	QUERY_RESET_TYPE_LAST
73 };
74 
75 enum QueryResultType
76 {
77 	QUERY_RESULT_TYPE_32_BIT,
78 	QUERY_RESULT_TYPE_64_BIT,
79 	QUERY_RESULT_TYPE_PGQ_32_XFB_64,
80 	QUERY_RESULT_TYPE_PGQ_64_XFB_32,
81 
82 	QUERY_RESULT_TYPE_LAST
83 };
84 
85 enum ShaderStage
86 {
87 	SHADER_STAGE_VERTEX,
88 	SHADER_STAGE_TESSELLATION_EVALUATION,
89 	SHADER_STAGE_GEOMETRY,
90 
91 	SHADER_STAGE_LAST
92 };
93 
94 enum RasterizationCase
95 {
96 	RAST_CASE_DEFAULT,
97 	RAST_CASE_DISCARD,
98 	RAST_CASE_EMPTY_FRAG,
99 	RAST_CASE_NO_ATTACHMENT,
100 	RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
101 	RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
102 
103 	RAST_CASE_LAST
104 };
105 
106 enum VertexStream
107 {
108 	VERTEX_STREAM_DEFAULT	= -1,
109 	VERTEX_STREAM_0			= 0,
110 	VERTEX_STREAM_1			= 1,
111 	VERTEX_STREAM_NONE		= 2,
112 };
113 
114 enum CommandBufferCase
115 {
116 	CMD_BUF_CASE_SINGLE_DRAW,
117 	CMD_BUF_CASE_TWO_DRAWS,
118 
119 	CMD_BUF_CASE_LAST
120 };
121 
122 enum QueryOrder
123 {
124 	QUERY_ORDER_PGQ_FIRST,
125 	QUERY_ORDER_XFBQ_FIRST,
126 
127 	QUERY_ORDER_LAST
128 };
129 
130 enum OutsideDraw
131 {
132 	OUTSIDE_DRAW_NONE,
133 	OUTSIDE_DRAW_BEFORE,
134 	OUTSIDE_DRAW_AFTER,
135 
136 	OUTSIDE_DRAW_LAST
137 };
138 
139 struct TestParameters
140 {
141 	QueryReadType		queryReadType;
142 	QueryResetType		queryResetType;
143 	QueryResultType		queryResultType;
144 	ShaderStage			shaderStage;
145 	deBool				transformFeedback;
146 	RasterizationCase	rastCase;
147 	deBool				depthStencilAttachment;
148 	VkPrimitiveTopology	primitiveTopology;
149 	VertexStream		pgqStream;
150 	VertexStream		xfbStream;
151 	CommandBufferCase	cmdBufCase;
152 	const uint32_t		queryCount;
153 	QueryOrder			queryOrder;
154 	OutsideDraw			outsideDraw;
155 	const bool			availabilityBit;
156 
pgqDefaultvkt::TransformFeedback::__anonaeb873c60111::TestParameters157 	bool		pgqDefault					(void)	const	{ return pgqStream == VERTEX_STREAM_DEFAULT;						}
xfbDefaultvkt::TransformFeedback::__anonaeb873c60111::TestParameters158 	bool		xfbDefault					(void)	const	{ return xfbStream == VERTEX_STREAM_DEFAULT;						}
pgqStreamIndexvkt::TransformFeedback::__anonaeb873c60111::TestParameters159 	deUint32	pgqStreamIndex				(void)	const	{ return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream);		}
xfbStreamIndexvkt::TransformFeedback::__anonaeb873c60111::TestParameters160 	deUint32	xfbStreamIndex				(void)	const	{ return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream);		}
multipleStreamsvkt::TransformFeedback::__anonaeb873c60111::TestParameters161 	bool		multipleStreams				(void)	const	{ return pgqStreamIndex() != xfbStreamIndex();						}
nonZeroStreamsvkt::TransformFeedback::__anonaeb873c60111::TestParameters162 	bool		nonZeroStreams				(void)	const	{ return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);		}
rastDiscardvkt::TransformFeedback::__anonaeb873c60111::TestParameters163 	bool		rastDiscard					(void)	const	{ return rastCase == RAST_CASE_DISCARD;								}
colorAttachmentvkt::TransformFeedback::__anonaeb873c60111::TestParameters164 	bool		colorAttachment				(void)	const	{ return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT;		}
staticColorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters165 	bool		staticColorWriteDisable		(void)	const	{ return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC;			}
dynamicColorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters166 	bool		dynamicColorWriteDisable	(void)	const	{ return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC;			}
colorWriteDisablevkt::TransformFeedback::__anonaeb873c60111::TestParameters167 	bool		colorWriteDisable			(void)	const	{ return staticColorWriteDisable() || dynamicColorWriteDisable();	}
168 };
169 
170 enum ConcurrentTestType
171 {
172 	CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ,
173 	CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER,
174 	CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1,
175 	CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2,
176 	CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3,
177 
178 	CONCURRENT_TEST_TYPE_LAST
179 };
180 
181 struct ConcurrentTestParameters
182 {
183 	ConcurrentTestType	concurrentTestType;
184 	QueryResultType		queryResultType;
185 	ShaderStage			shaderStage;
186 	VkPrimitiveTopology	primitiveTopology;
187 	VertexStream		pgqStream;
188 	VertexStream		xfbStream;
189 	bool				indirect;
190 
pgqDefaultvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters191 	bool		pgqDefault					(void)	const	{ return pgqStream == VERTEX_STREAM_DEFAULT;						}
xfbDefaultvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters192 	bool		xfbDefault					(void)	const	{ return xfbStream == VERTEX_STREAM_DEFAULT;						}
pgqStreamIndexvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters193 	deUint32	pgqStreamIndex				(void)	const	{ return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream);		}
xfbStreamIndexvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters194 	deUint32	xfbStreamIndex				(void)	const	{ return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream);		}
multipleStreamsvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters195 	bool		multipleStreams				(void)	const	{ return pgqStreamIndex() != xfbStreamIndex();						}
nonZeroStreamsvkt::TransformFeedback::__anonaeb873c60111::ConcurrentTestParameters196 	bool		nonZeroStreams				(void)	const	{ return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);		}
197 };
198 
199 struct TopologyInfo
200 {
201 	deUint32							primitiveSize;		// Size of the primitive.
202 	deBool								hasAdjacency;		// True if topology has adjacency.
203 	const char*							inputString;		// Layout qualifier identifier for geometry shader input.
204 	const char*							outputString;		// Layout qualifier identifier for geometry shader output.
205 	std::function<deUint64(deUint64)>	getNumPrimitives;	// Number of primitives generated.
206 	std::function<deUint64(deUint64)>	getNumVertices;		// Number of vertices generated.
207 };
208 
209 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
210 {
__anonaeb873c60402() 211 	{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,						{ 1, DE_FALSE,	"points",				"points",			[](deUint64 vtxCount) { return vtxCount;				}, [](deUint64 primCount) {	return primCount;			} } },
__anonaeb873c60602() 212 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						{ 2, DE_FALSE,	"lines",				"line_strip",		[](deUint64 vtxCount) { return vtxCount / 2u;			}, [](deUint64 primCount) {	return primCount * 2u;		} } },
__anonaeb873c60802() 213 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						{ 2, DE_FALSE,	"lines",				"line_strip",		[](deUint64 vtxCount) { return vtxCount - 1u;			}, [](deUint64 primCount) {	return primCount + 1u;		} } },
__anonaeb873c60a02() 214 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount / 3u;			}, [](deUint64 primCount) {	return primCount * 3u;		} } },
__anonaeb873c60c02() 215 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount - 2u;			}, [](deUint64 primCount) {	return primCount + 2u;		} } },
__anonaeb873c60e02() 216 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount - 2u;			}, [](deUint64 primCount) {	return primCount + 2u;		} } },
__anonaeb873c60f02() 217 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,		{ 2, DE_TRUE,	"lines_adjacency",		"line_strip",		[](deUint64 vtxCount) { return vtxCount / 4u;			}, [](deUint64 primCount) {	return primCount * 4u;		} } },
__anonaeb873c61202() 218 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		{ 2, DE_TRUE,	"lines_adjacency",		"line_strip",		[](deUint64 vtxCount) { return vtxCount - 3u;			}, [](deUint64 primCount) {	return primCount + 3u;		} } },
__anonaeb873c61402() 219 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,	{ 3, DE_TRUE,	"triangles_adjacency",	"triangle_strip",	[](deUint64 vtxCount) { return vtxCount / 6u;			}, [](deUint64 primCount) {	return primCount * 6u;		} } },
__anonaeb873c61602() 220 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,	{ 3, DE_TRUE,	"triangles_adjacency",	"triangle_strip",	[](deUint64 vtxCount) { return (vtxCount - 4u) / 2u;	}, [](deUint64 primCount) {	return primCount * 2u + 4;	} } },
__anonaeb873c61802() 221 	{ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,						{ 3, DE_FALSE,	"ERROR",				"ERROR",			[](deUint64 vtxCount) { return vtxCount / 3u;			}, [](deUint64 primCount) {	return primCount * 3u;		} } },
222 };
223 
224 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
225 {
226 public:
PrimitivesGeneratedQueryTestInstance(vkt::Context & context,const TestParameters & parameters)227 							PrimitivesGeneratedQueryTestInstance	(vkt::Context &context, const TestParameters& parameters)
228 								: vkt::TestInstance	(context)
229 								, m_parameters		(parameters)
230 							{
231 							}
232 
233 private:
234 	tcu::TestStatus			iterate									(void);
235 	VkFormat				selectDepthStencilFormat				(void);
236 	Move<VkPipeline>		makeGraphicsPipeline					(const DeviceInterface&	vk,
237 																	 const VkDevice device,
238 																	 const VkRenderPass renderPass);
239 	void					fillVertexBuffer						(tcu::Vec2* vertices,
240 																	 const deUint64 primitivesGenerated);
241 	const TestParameters	m_parameters;
242 };
243 
iterate(void)244 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
245 {
246 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
247 	const VkDevice					device				= m_context.getDevice();
248 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
249 	const VkQueue					queue				= m_context.getUniversalQueue();
250 	Allocator&						allocator			= m_context.getDefaultAllocator();
251 
252 	using ImageVec = std::vector<Move<VkImage>>;
253 	using AllocVec = std::vector<de::MovePtr<Allocation>>;
254 
255 	const VkFormat					colorFormat			= m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
256 	ImageVec						colorImages;
257 	AllocVec						colorImageAllocations;
258 
259 	if (m_parameters.colorAttachment())
260 	{
261 		const VkImageCreateInfo colorImageCreateInfo =
262 		{
263 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType
264 			DE_NULL,									// const void*				pNext
265 			0u,											// VkImageCreateFlags		flags
266 			VK_IMAGE_TYPE_2D,							// VkImageType				imageType
267 			colorFormat,								// VkFormat					format
268 			makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),	// VkExtent3D				extent
269 			1u,											// deUint32					mipLevels
270 			1u,											// deUint32					arrayLayers
271 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples
272 			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling
273 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,		// VkImageUsageFlags		usage
274 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode
275 			0u,											// deUint32					queueFamilyIndexCount
276 			DE_NULL,									// const deUint32*			pQueueFamilyIndices
277 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			initialLayout
278 		};
279 
280 		for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
281 		{
282 			auto colorImage				= makeImage(vk, device, colorImageCreateInfo);
283 			auto colorImageAllocation	= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
284 
285 			colorImages.emplace_back(colorImage);
286 			colorImageAllocations.emplace_back(colorImageAllocation);
287 		}
288 	}
289 
290 	const VkFormat					dsFormat			= m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
291 
292 	if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
293 		return tcu::TestStatus::fail("VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT feature must be supported for at least one of VK_FORMAT_D24_UNORM_S8_UINT and VK_FORMAT_D32_SFLOAT_S8_UINT.");
294 
295 	ImageVec						dsImages;
296 	AllocVec						dsImageAllocations;
297 
298 	if (m_parameters.depthStencilAttachment)
299 	{
300 		const VkImageCreateInfo dsImageCreateInfo =
301 		{
302 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType
303 			DE_NULL,										// const void*				pNext
304 			0u,												// VkImageCreateFlags		flags
305 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType
306 			dsFormat,										// VkFormat					format
307 			makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),		// VkExtent3D				extent
308 			1u,												// deUint32					mipLevels
309 			1u,												// deUint32					arrayLayers
310 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples
311 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling
312 			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,	// VkImageUsageFlags		usage
313 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
314 			0u,												// deUint32					queueFamilyIndexCount
315 			DE_NULL,										// const deUint32*			pQueueFamilyIndices
316 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout
317 		};
318 
319 		for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
320 		{
321 			auto dsImage			= makeImage(vk, device, dsImageCreateInfo);
322 			auto dsImageAllocation	= bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
323 
324 			dsImages.emplace_back(dsImage);
325 			dsImageAllocations.emplace_back(dsImageAllocation);
326 		}
327 	}
328 
329 	const VkDeviceSize				primitivesGenerated = 32;
330 	const deUint32					baseMipLevel		= 0;
331 	const deUint32					levelCount			= 1;
332 	const deUint32					baseArrayLayer		= 0;
333 	const deUint32					layerCount			= 1;
334 
335 	using ImageViewVec = std::vector<Move<VkImageView>>;
336 
337 	ImageViewVec					colorImageViews;
338 	ImageViewVec					dsImageViews;
339 
340 	for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
341 	{
342 		if (m_parameters.colorAttachment())
343 		{
344 			const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
345 			auto colorImageView = makeImageView(vk, device, *colorImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
346 			colorImageViews.emplace_back(colorImageView);
347 		}
348 
349 		if (m_parameters.depthStencilAttachment)
350 		{
351 			const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
352 			auto dsImageView = makeImageView(vk, device, *dsImages.at(queryIdx), VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
353 			dsImageViews.emplace_back(dsImageView);
354 		}
355 	}
356 
357 	using FramebufferVec = std::vector<Move<VkFramebuffer>>;
358 
359 	const Unique<VkRenderPass>		renderPass			(makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
360 	const Unique<VkPipeline>		pipeline			(PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
361 	FramebufferVec					framebuffers;
362 
363 	for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
364 	{
365 		std::vector<VkImageView> imageViews;
366 
367 		if (m_parameters.colorAttachment())
368 			imageViews.push_back(*colorImageViews.at(queryIdx));
369 
370 		if (m_parameters.depthStencilAttachment)
371 			imageViews.push_back(*dsImageViews.at(queryIdx));
372 
373 		auto framebuffer = makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT);
374 		framebuffers.emplace_back(framebuffer);
375 	}
376 
377 	Move<VkBuffer>					vtxBuffer;
378 	de::MovePtr<Allocation>			vtxBufferAlloc;
379 
380 	{
381 		const VkBufferUsageFlags		usage				= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
382 		const std::vector<deUint32>		queueFamilyIndices	(1, queueFamilyIndex);
383 		const VkDeviceSize				vtxBufferSize		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
384 		const VkBufferCreateInfo		createInfo			= makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
385 
386 		vtxBuffer			= createBuffer(vk, device, &createInfo);
387 		vtxBufferAlloc		= allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
388 	}
389 
390 	const VkCommandPoolCreateFlags	cmdPoolCreateFlags	= VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
391 	const VkCommandBufferLevel		cmdBufferLevel		= VK_COMMAND_BUFFER_LEVEL_PRIMARY;
392 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
393 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
394 	const auto						resetCmdBuffer		= allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel);
395 
396 	const bool						pgq64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
397 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
398 	const bool						xfb64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
399 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
400 	const VkQueryResultFlags		availabilityFlags	= (m_parameters.availabilityBit ? VK_QUERY_RESULT_WITH_AVAILABILITY_BIT : 0);
401 	const size_t					pgqValuesPerQuery	= (m_parameters.availabilityBit ? 2 : 1);
402 	const size_t					xfbValuesPerQuery	= (m_parameters.availabilityBit ? 3 : 2);
403 	const size_t					pgqResultSize		= (pgq64 ? sizeof(deUint64) : sizeof(deUint32)) * pgqValuesPerQuery;
404 	const size_t					xfbResultSize		= (xfb64 ? sizeof(deUint64) : sizeof(deUint32)) * xfbValuesPerQuery;
405 	const size_t					pgqResultBufferSize	= pgqResultSize * m_parameters.queryCount;
406 	const size_t					xfbResultBufferSize	= xfbResultSize * m_parameters.queryCount;
407 	const VkQueryResultFlags		pgqResultWidthBit	= pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
408 	const VkQueryResultFlags		xfbResultWidthBit	= xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
409 	const VkQueryResultFlags		pgqResultFlags		= VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit | availabilityFlags;
410 	const VkQueryResultFlags		xfbResultFlags		= VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit | availabilityFlags;
411 
412 	std::vector<deUint8>			pgqResults			(pgqResultBufferSize, 255u);
413 	std::vector<deUint8>			xfbResults			(xfbResultBufferSize, 255u);
414 
415 	const VkQueryPoolCreateInfo		pgqCreateInfo		=
416 	{
417 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType
418 		DE_NULL,									// const void*						pNext
419 		0u,											// VkQueryPoolCreateFlags			flags
420 		VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,		// VkQueryType						queryType
421 		m_parameters.queryCount,					// deUint32							queryCount
422 		0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics
423 	};
424 
425 	const Unique<VkQueryPool>		pgqPool				(createQueryPool(vk, device, &pgqCreateInfo));
426 	Move<VkQueryPool>				xfbPool;
427 
428 	if (m_parameters.transformFeedback)
429 	{
430 		const VkQueryPoolCreateInfo xfbCreateInfo =
431 		{
432 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// VkStructureType					sType
433 			DE_NULL,										// const void*						pNext
434 			0u,												// VkQueryPoolCreateFlags			flags
435 			VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,	// VkQueryType						queryType
436 			m_parameters.queryCount,						// deUint32							queryCount
437 			0u,												// VkQueryPipelineStatisticFlags	pipelineStatistics
438 		};
439 
440 		xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
441 	}
442 
443 	Move<VkBuffer>					pgqResultsBuffer;
444 	Move<VkBuffer>					xfbResultsBuffer;
445 	de::MovePtr<Allocation>			pgqResultsBufferAlloc;
446 	de::MovePtr<Allocation>			xfbResultsBufferAlloc;
447 
448 	if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
449 	{
450 		const VkBufferUsageFlags	usage				= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
451 		const std::vector<deUint32>	queueFamilyIndices	(1, queueFamilyIndex);
452 		const VkBufferCreateInfo	pgqBufferCreateInfo	= makeBufferCreateInfo(pgqResultBufferSize, usage, queueFamilyIndices);
453 
454 		pgqResultsBuffer		= createBuffer(vk, device, &pgqBufferCreateInfo);
455 		pgqResultsBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
456 
457 		VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
458 
459 		if (m_parameters.transformFeedback)
460 		{
461 			const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultBufferSize, usage, queueFamilyIndices);
462 
463 			xfbResultsBuffer		= createBuffer(vk, device, &xfbBufferCreateInfo);
464 			xfbResultsBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
465 
466 			VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
467 		}
468 	}
469 
470 	const VkDeviceSize				primitivesWritten	= primitivesGenerated - 3;
471 	const VkDeviceSize				verticesWritten		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
472 	const VkDeviceSize				primitiveSize		= m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
473 	const VkDeviceSize				bytesPerVertex		= 4 * sizeof(float);
474 	const VkDeviceSize				xfbBufferSize		= primitivesWritten * primitiveSize * bytesPerVertex;
475 
476 	using BufferVec = std::vector<Move<VkBuffer>>;
477 
478 	BufferVec						xfbBuffers;
479 	AllocVec						xfbBufferAllocs;
480 
481 	if (m_parameters.transformFeedback)
482 	{
483 		const VkBufferUsageFlags	usage				= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
484 		const std::vector<deUint32>	queueFamilyIndices	(1, queueFamilyIndex);
485 		const VkBufferCreateInfo	createInfo			= makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
486 
487 		for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
488 		{
489 			auto xfbBuffer		= createBuffer(vk, device, &createInfo);
490 			auto xfbBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
491 
492 			VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
493 
494 			xfbBuffers.emplace_back(xfbBuffer);
495 			xfbBufferAllocs.emplace_back(xfbBufferAlloc);
496 		}
497 	}
498 
499 	fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
500 
501 	VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
502 
503 	// After query pool creation, each query must be reset before it is used.
504 	//
505 	// When resetting them using a queue, we will submit a separate command buffer with the reset operation and wait for it to
506 	// complete. This will make sure queries are properly reset before we attempt to get results from them. This is needed because
507 	// we're not going to wait for any fence when using vkGetQueryPoolResults, so there's a potential race condition with
508 	// vkGetQueryPoolResults attempting to get results before queries are properly reset, which is against the spec.
509 	if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
510 	{
511 		beginCommandBuffer(vk, *resetCmdBuffer);
512 		vk.cmdResetQueryPool(*resetCmdBuffer, *pgqPool, 0u, m_parameters.queryCount);
513 		if (m_parameters.transformFeedback)
514 			vk.cmdResetQueryPool(*resetCmdBuffer, *xfbPool, 0u, m_parameters.queryCount);
515 		endCommandBuffer(vk, *resetCmdBuffer);
516 		submitCommandsAndWait(vk, device, queue, *resetCmdBuffer);
517 	}
518 
519 	beginCommandBuffer(vk, *cmdBuffer);
520 	{
521 		const VkDeviceSize	vertexBufferOffset	= static_cast<VkDeviceSize>(0);
522 
523 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
524 
525 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
526 
527 		for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
528 		{
529 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffers.at(queryIdx), makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
530 			{
531 				const VkQueryControlFlags	queryControlFlags		= 0;
532 
533 				const deUint32				firstCounterBuffer		= 0;
534 				const deUint32				counterBufferCount		= 0;
535 				const VkBuffer*				counterBuffers			= DE_NULL;
536 				const VkDeviceSize*			counterBufferOffsets	= DE_NULL;
537 
538 				const deUint32				vertexCount				= static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
539 				const deUint32				instanceCount			= 1u;
540 				const deUint32				firstVertex				= 0u;
541 				const deUint32				firstInstance			= 0u;
542 
543 				if (m_parameters.dynamicColorWriteDisable())
544 				{
545 					const deUint32	attachmentCount = 1;
546 					const VkBool32	colorWriteEnables = VK_FALSE;
547 
548 					vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
549 				}
550 
551 				if (m_parameters.outsideDraw == OUTSIDE_DRAW_BEFORE)
552 					vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
553 
554 				if (m_parameters.queryOrder == QUERY_ORDER_PGQ_FIRST)
555 				{
556 					if (m_parameters.pgqDefault())
557 						vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
558 					else
559 						vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags, m_parameters.pgqStreamIndex());
560 				}
561 
562 				if (m_parameters.transformFeedback)
563 				{
564 					const deUint32		firstBinding	= 0;
565 					const deUint32		bindingCount	= 1;
566 					const VkDeviceSize	offset			= 0;
567 
568 					vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffers.at(queryIdx), &offset, &xfbBufferSize);
569 
570 					if (m_parameters.xfbDefault())
571 						vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags);
572 					else
573 						vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, queryControlFlags, m_parameters.xfbStreamIndex());
574 
575 					vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
576 				}
577 
578 				if (m_parameters.queryOrder != QUERY_ORDER_PGQ_FIRST)
579 				{
580 					if (m_parameters.pgqDefault())
581 						vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags);
582 					else
583 						vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, queryControlFlags, m_parameters.pgqStreamIndex());
584 				}
585 
586 				vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
587 
588 				if (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS)
589 					vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
590 
591 				if (m_parameters.pgqDefault())
592 					vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIdx);
593 				else
594 					vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIdx, m_parameters.pgqStreamIndex());
595 
596 				if (m_parameters.transformFeedback)
597 				{
598 					if (m_parameters.xfbDefault())
599 						vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIdx);
600 					else
601 						vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIdx, m_parameters.xfbStreamIndex());
602 
603 					vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
604 				}
605 
606 				if (m_parameters.outsideDraw == OUTSIDE_DRAW_AFTER)
607 					vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
608 			}
609 			endRenderPass(vk, *cmdBuffer);
610 		}
611 
612 		if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
613 		{
614 			VkBufferMemoryBarrier bufferBarrier =
615 			{
616 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType
617 				DE_NULL,									// const void*		pNext
618 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask
619 				VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask
620 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
621 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex
622 				*pgqResultsBuffer,							// VkBuffer			buffer
623 				0u,											// VkDeviceSize		offset
624 				VK_WHOLE_SIZE								// VkDeviceSize		size
625 			};
626 
627 			vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, 0u, m_parameters.queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
628 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
629 
630 			if (m_parameters.transformFeedback)
631 			{
632 				bufferBarrier.buffer = *xfbResultsBuffer;
633 				vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, 0u, m_parameters.queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
634 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
635 			}
636 		}
637 	}
638 	vk::endCommandBuffer(vk, *cmdBuffer);
639 
640 	// After query pool creation, each query must be reset before it is used.
641 	if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
642 	{
643 		vk.resetQueryPool(device, *pgqPool, 0u, m_parameters.queryCount);
644 
645 		if (m_parameters.transformFeedback)
646 			vk.resetQueryPool(device, *xfbPool, 0u, m_parameters.queryCount);
647 	}
648 
649 	const auto fence = submitCommands(vk, device, queue, *cmdBuffer);
650 
651 	// To make it more interesting, attempt to get results with WAIT before waiting for the fence.
652 	if (m_parameters.queryReadType == QUERY_READ_TYPE_GET)
653 	{
654 		vk.getQueryPoolResults(device, *pgqPool, 0u, m_parameters.queryCount, pgqResults.size(), pgqResults.data(), pgqResultSize, pgqResultFlags);
655 
656 		if (m_parameters.transformFeedback)
657 			vk.getQueryPoolResults(device, *xfbPool, 0u, m_parameters.queryCount, xfbResults.size(), xfbResults.data(), xfbResultSize, xfbResultFlags);
658 	}
659 
660 	waitForFence(vk, device, *fence);
661 
662 	if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
663 	{
664 		invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
665 		deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
666 
667 		if (m_parameters.transformFeedback)
668 		{
669 			invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
670 			deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
671 		}
672 	}
673 
674 	// Validate counters.
675 	for (uint32_t queryIdx = 0u; queryIdx < m_parameters.queryCount; ++queryIdx)
676 	{
677 		union QueryResults
678 		{
679 			deUint32	elements32[3];
680 			deUint64	elements64[3];
681 		};
682 
683 		const QueryResults*	pgqCounters		= reinterpret_cast<QueryResults*>(pgqResults.data() + queryIdx * pgqResultSize);
684 		const QueryResults*	xfbCounters		= reinterpret_cast<QueryResults*>(xfbResults.data() + queryIdx * xfbResultSize);
685 		const deUint64		pgqGenerated	= pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
686 		const deUint64		xfbWritten		= xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
687 		const deUint64		xfbGenerated	= xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
688 		const deUint32		drawCount		= (m_parameters.cmdBufCase == CMD_BUF_CASE_TWO_DRAWS) ? 2u : 1u;
689 		const uint64_t		pgqAvailability	= (m_parameters.availabilityBit ? (pgq64 ? pgqCounters->elements64[1] : static_cast<deUint64>(pgqCounters->elements32[1])) : 1);
690 		const uint64_t		xfbAvailability	= (m_parameters.availabilityBit ? (xfb64 ? xfbCounters->elements64[2] : static_cast<deUint64>(xfbCounters->elements32[2])) : 1);
691 		tcu::TestLog&		log				= m_context.getTestContext().getLog();
692 
693 		if (queryIdx == 0u)
694 		{
695 			log	<<	tcu::TestLog::Message
696 				<<	"primitivesGenerated: " << primitivesGenerated << "\n"
697 				<<	"primitivesWritten: " << primitivesWritten << "\n"
698 				<<	"verticesWritten: " << verticesWritten << "\n"
699 				<<	"xfbBufferSize: " << xfbBufferSize << "\n"
700 				<<	tcu::TestLog::EndMessage;
701 		}
702 
703 		const std::string logPrefix = std::string("[Query ") + std::to_string(queryIdx) + "] ";
704 
705 		log << tcu::TestLog::Message << logPrefix << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
706 
707 		if (m_parameters.transformFeedback)
708 			log << tcu::TestLog::Message << logPrefix << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
709 
710 		if (pgqGenerated != primitivesGenerated * drawCount)
711 		{
712 			const std::string message = logPrefix + "pgqGenerated == " + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated * drawCount);
713 			return tcu::TestStatus::fail(message);
714 		}
715 
716 		if (pgqAvailability != 1)
717 		{
718 			const std::string message = logPrefix + "pgqAvailability == " + de::toString(pgqAvailability) + ", expected 1";
719 			return tcu::TestStatus::fail(message);
720 		}
721 
722 		if (m_parameters.transformFeedback)
723 		{
724 			if (xfbGenerated != primitivesGenerated * drawCount)
725 			{
726 				const std::string message = logPrefix + "xfbGenerated == " + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated * drawCount);
727 				return tcu::TestStatus::fail(message);
728 			}
729 
730 			if (xfbWritten != primitivesWritten)
731 			{
732 				const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
733 				return tcu::TestStatus::fail(message);
734 			}
735 
736 			if (xfbWritten != (primitivesGenerated - 3))
737 			{
738 				const std::string message = logPrefix + "xfbWritten == " + de::toString(xfbWritten) + ", expected " + de::toString(primitivesGenerated - 3);
739 				return tcu::TestStatus::fail(message);
740 			}
741 
742 			if (xfbAvailability != 1)
743 			{
744 				const std::string message = logPrefix + "xfbAvailability == " + de::toString(xfbAvailability) + ", expected 1";
745 				return tcu::TestStatus::fail(message);
746 			}
747 		}
748 	}
749 
750 	return tcu::TestStatus::pass("Counters OK");
751 }
752 
selectDepthStencilFormat(void)753 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
754 {
755 	constexpr VkFormat			formats[]		=
756 	{
757 		VK_FORMAT_D32_SFLOAT_S8_UINT,
758 		VK_FORMAT_D24_UNORM_S8_UINT
759 	};
760 
761 	const InstanceInterface&	vki				= m_context.getInstanceInterface();
762 	const VkPhysicalDevice		physicalDevice	= m_context.getPhysicalDevice();
763 
764 	for (VkFormat format : formats)
765 	{
766 		const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
767 
768 		if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
769 			return format;
770 	}
771 
772 	return VK_FORMAT_UNDEFINED;
773 }
774 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)775 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface&	vk, const VkDevice device, const VkRenderPass renderPass)
776 {
777 	const VkDescriptorSetLayout						descriptorSetLayout				= DE_NULL;
778 	const Unique<VkPipelineLayout>					pipelineLayout					(makePipelineLayout(vk, device, descriptorSetLayout));
779 	const std::vector<VkViewport>					viewports						(1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
780 	const std::vector<VkRect2D>						scissors						(1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
781 	const deUint32									subpass							= 0u;
782 	const deUint32									patchControlPoints				= topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
783 	const Unique<VkShaderModule>					vertModule						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
784 	Move<VkShaderModule>							tescModule;
785 	Move<VkShaderModule>							teseModule;
786 	Move<VkShaderModule>							geomModule;
787 	Move<VkShaderModule>							fragModule;
788 	VkVertexInputBindingDescription					bindingDescription;
789 	VkVertexInputAttributeDescription				attributeDescription;
790 
791 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
792 	{
793 		tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
794 		teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
795 	}
796 
797 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
798 		geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
799 
800 	if (!m_parameters.rastDiscard())
801 		fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
802 
803 	bindingDescription.binding		= 0;
804 	bindingDescription.stride		= sizeof(tcu::Vec2);
805 	bindingDescription.inputRate	= VK_VERTEX_INPUT_RATE_VERTEX;
806 
807 	attributeDescription.binding	= 0;
808 	attributeDescription.location	= 0;
809 	attributeDescription.format		= VK_FORMAT_R32G32_SFLOAT;
810 	attributeDescription.offset		= 0;
811 
812 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
813 	{
814 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType
815 		DE_NULL,													// const void*								pNext
816 		0u,															// VkPipelineVertexInputStateCreateFlags	flags
817 		1u,															// deUint32									vertexBindingDescriptionCount
818 		&bindingDescription,										// const VkVertexInputBindingDescription*	pVertexBindingDescriptions
819 		1u,															// deUint32									vertexAttributeDescriptionCount
820 		&attributeDescription,										// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions
821 	};
822 
823 	const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
824 	{
825 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType
826 		DE_NULL,													// const void*								pNext
827 		0,															// VkPipelineRasterizationStateCreateFlags	flags
828 		VK_FALSE,													// VkBool32									depthClampEnable
829 		(m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE),			// VkBool32									rasterizerDiscardEnable
830 		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode
831 		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode
832 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace
833 		VK_FALSE,													// VkBool32									depthBiasEnable
834 		0.0f,														// float									depthBiasConstantFactor
835 		0.0f,														// float									depthBiasClamp
836 		0.0f,														// float									depthBiasSlopeFactor
837 		1.0f														// float									lineWidth
838 	};
839 
840 	const VkStencilOpState							stencilOpState					=
841 	{
842 		VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp
843 		VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp
844 		VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp
845 		VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp
846 		0xFFu,					// deUint32		compareMask
847 		0xFFu,					// deUint32		writeMask
848 		0,						// deUint32		reference
849 	};
850 
851 	const VkPipelineDepthStencilStateCreateInfo		depthStencilStateCreateInfo		=
852 	{
853 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType							sType
854 		DE_NULL,													//	const void*								pNext
855 		0,															//	VkPipelineDepthStencilStateCreateFlags	flags
856 		VK_TRUE,													//	VkBool32								depthTestEnable
857 		VK_TRUE,													//	VkBool32								depthWriteEnable
858 		VK_COMPARE_OP_LESS,											//	VkCompareOp								depthCompareOp
859 		VK_FALSE,													//	VkBool32								depthBoundsTestEnable
860 		VK_FALSE,													//	VkBool32								stencilTestEnable
861 		stencilOpState,												//	VkStencilOpState						front
862 		stencilOpState,												//	VkStencilOpState						back
863 		0.0f,														//	float									minDepthBounds
864 		1.0f,														//	float									maxDepthBounds
865 	};
866 
867 	const VkBool32									colorWriteEnables				= VK_FALSE;
868 
869 	const VkPipelineColorWriteCreateInfoEXT			colorWriteCreateInfo			=
870 	{
871 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT,	// VkStructureType	sType;
872 		DE_NULL,												// const void*		pNext;
873 		1,														// deUint32			attachmentCount;
874 		&colorWriteEnables										// const VkBool32*	pColorWriteEnables;
875 	};
876 
877 	const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState		=
878 	{
879 		VK_FALSE,					// VkBool32					blendEnable
880 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcColorBlendFactor
881 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstColorBlendFactor
882 		VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
883 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcAlphaBlendFactor
884 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstAlphaBlendFactor
885 		VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
886 		VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
887 		| VK_COLOR_COMPONENT_G_BIT
888 		| VK_COLOR_COMPONENT_B_BIT
889 		| VK_COLOR_COMPONENT_A_BIT
890 	};
891 
892 	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo		=
893 	{
894 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
895 		&colorWriteCreateInfo,										// const void*									pNext
896 		0,															// VkPipelineColorBlendStateCreateFlags			flags
897 		VK_FALSE,													// VkBool32										logicOpEnable
898 		VK_LOGIC_OP_NO_OP,											// VkLogicOp									logicOp
899 		1,															// deUint32										attachmentCount
900 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments
901 		{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4]
902 	};
903 
904 	const VkDynamicState							dynamicStates					= VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
905 
906 	const VkPipelineDynamicStateCreateInfo			pipelineDynamicStateCreateInfo	=
907 	{
908 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType
909 		DE_NULL,												// const void*							pNext
910 		0u,														// VkPipelineDynamicStateCreateFlags	flags
911 		1u,														// deUint32								dynamicStateCount
912 		&dynamicStates											// const VkDynamicState*				pDynamicStates
913 	};
914 
915 	const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo		=
916 	{
917 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
918 		nullptr,													//	const void*								pNext;
919 		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
920 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
921 		VK_FALSE,													//	VkBool32								sampleShadingEnable;
922 		1.0f,														//	float									minSampleShading;
923 		nullptr,													//	const VkSampleMask*						pSampleMask;
924 		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
925 		VK_FALSE,													//	VkBool32								alphaToOneEnable;
926 	};
927 
928 	return vk::makeGraphicsPipeline(vk,
929 									device,
930 									*pipelineLayout,
931 									*vertModule,
932 									*tescModule,
933 									*teseModule,
934 									*geomModule,
935 									*fragModule,
936 									renderPass,
937 									viewports,
938 									scissors,
939 									m_parameters.primitiveTopology,
940 									subpass,
941 									patchControlPoints,
942 									&vertexInputStateCreateInfo,
943 									&rasterizationStateCreateInfo,
944 									&multisampleStateCreateInfo,
945 									m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
946 									m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
947 									m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
948 }
949 
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)950 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
951 {
952 	const float step = 1.0f / static_cast<float>(primitivesGenerated);
953 
954 	switch (m_parameters.primitiveTopology)
955 	{
956 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
957 		{
958 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
959 			{
960 				vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
961 			}
962 			break;
963 		}
964 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
965 		{
966 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
967 			{
968 				vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
969 				vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
970 			}
971 			break;
972 		}
973 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
974 		{
975 			vertices[0] = tcu::Vec2(-1.0f,-1.0f);
976 			vertices[1] = tcu::Vec2(-1.0f, 1.0f);
977 
978 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
979 			{
980 				if (prim % 2 == 0)
981 				{
982 					vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
983 				}
984 				else
985 				{
986 					vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
987 				}
988 			}
989 			break;
990 		}
991 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
992 		{
993 			vertices[0] = tcu::Vec2(-1.0f,				 1.0f);
994 			vertices[1] = tcu::Vec2(-1.0f,				-1.0f);
995 			vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
996 
997 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
998 			{
999 				if (prim % 2 == 0)
1000 				{
1001 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1002 				}
1003 				else
1004 				{
1005 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1006 				}
1007 			}
1008 			break;
1009 		}
1010 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
1011 		{
1012 			vertices[0] = tcu::Vec2(0.0f, -1.0f);
1013 
1014 			for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
1015 			{
1016 				vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
1017 			}
1018 			break;
1019 		}
1020 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
1021 		{
1022 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1023 			{
1024 				vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
1025 				vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  0.5f);
1026 				vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
1027 				vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1028 			}
1029 			break;
1030 		}
1031 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
1032 		{
1033 			vertices[0] = tcu::Vec2(-1.0f,  0.0f);
1034 			vertices[1] = tcu::Vec2(-1.0f, -1.0f);
1035 			vertices[2] = tcu::Vec2(-1.0f,  1.0f);
1036 
1037 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
1038 			{
1039 				if (prim % 2 == 0)
1040 				{
1041 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
1042 				}
1043 				else
1044 				{
1045 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1046 				}
1047 			}
1048 
1049 			vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
1050 
1051 			break;
1052 		}
1053 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
1054 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
1055 		{
1056 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1057 			{
1058 				if (prim % 2 == 0)
1059 				{
1060 					vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1061 					vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1062 					vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1063 				}
1064 				else
1065 				{
1066 					vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1067 					vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
1068 					vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1069 				}
1070 			}
1071 			break;
1072 		}
1073 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
1074 		{
1075 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
1076 			{
1077 				if (prim % 2 == 0)
1078 				{
1079 					vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1080 					vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1081 					vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1082 					vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
1083 					vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1084 					vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1085 				}
1086 				else
1087 				{
1088 					vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1089 					vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
1090 					vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
1091 					vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
1092 					vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1093 					vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
1094 				}
1095 			}
1096 			break;
1097 		}
1098 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1099 		{
1100 			vertices[0] = tcu::Vec2(-1.0f,  1.0f);
1101 			vertices[1] = tcu::Vec2(-1.0f,  1.0f);
1102 			vertices[2] = tcu::Vec2(-1.0f, -1.0f);
1103 			vertices[3] = tcu::Vec2(-1.0f, -1.0f);
1104 			vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1105 			vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
1106 
1107 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
1108 			{
1109 				if (prim % 2 == 0)
1110 				{
1111 					vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1112 					vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
1113 				}
1114 				else
1115 				{
1116 					vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1117 					vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
1118 				}
1119 			}
1120 			break;
1121 		}
1122 		default:
1123 			TCU_THROW(InternalError, "Unrecognized primitive topology");
1124 	}
1125 }
1126 
1127 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
1128 {
1129 public:
PrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const TestParameters & parameters)1130 							PrimitivesGeneratedQueryTestCase	(tcu::TestContext &context, const char *name, const TestParameters& parameters)
1131 								: TestCase		(context, name)
1132 								, m_parameters	(parameters)
1133 							{
1134 							}
1135 
1136 private:
1137 	void					checkSupport						(vkt::Context& context) const;
1138 	void					initPrograms						(vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const1139 	vkt::TestInstance*		createInstance						(vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
1140 
1141 	const TestParameters	m_parameters;
1142 };
1143 
checkSupport(vkt::Context & context) const1144 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
1145 {
1146 	context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
1147 	context.requireDeviceFunctionality("VK_EXT_transform_feedback");
1148 
1149 	const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT&	pgqFeatures		= context.getPrimitivesGeneratedQueryFeaturesEXT();
1150 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&			xfbFeatures		= context.getTransformFeedbackFeaturesEXT();
1151 	const VkPhysicalDeviceTransformFeedbackPropertiesEXT&		xfbProperties	= context.getTransformFeedbackPropertiesEXT();
1152 
1153 	if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
1154 		TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
1155 
1156 	if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
1157 		TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
1158 
1159 	if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
1160 		context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1161 
1162 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
1163 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
1164 
1165 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1166 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1167 
1168 	if (m_parameters.nonZeroStreams())
1169 	{
1170 		const deUint32 requiredStreams	= de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
1171 
1172 		if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
1173 			TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
1174 
1175 		if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
1176 			TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1177 	}
1178 
1179 	if (m_parameters.transformFeedback)
1180 	{
1181 		if (xfbFeatures.transformFeedback != VK_TRUE)
1182 			TCU_THROW(NotSupportedError, "transformFeedback not supported");
1183 
1184 		if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1185 			TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1186 	}
1187 
1188 	if (m_parameters.colorWriteDisable())
1189 	{
1190 		context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1191 
1192 		if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1193 			TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1194 	}
1195 }
1196 
initPrograms(vk::SourceCollections & programCollection) const1197 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1198 {
1199 	// Vertex shader.
1200 	{
1201 		const bool			vertXfb	= (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1202 		std::ostringstream	src;
1203 
1204 		src	<<	"#version 450\n";
1205 		src << "layout(location=0) in vec2 inPosition;\n";
1206 
1207 		if (vertXfb)
1208 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1209 
1210 		src	<<	"void main (void)\n"
1211 				"{\n";
1212 
1213 		if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1214 			src	<<	"    gl_PointSize = 1.0;\n";
1215 
1216 		src << "	 gl_Position = vec4(inPosition, 0, 1);\n";
1217 
1218 		if (vertXfb)
1219 			src	<<	"    out0 = vec4(42);\n";
1220 
1221 		src	<<	"}\n";
1222 
1223 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1224 	}
1225 
1226 	// Tessellation shaders.
1227 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1228 	{
1229 		std::stringstream	tescSrc;
1230 		std::stringstream	teseSrc;
1231 
1232 		tescSrc	<<	"#version 450\n"
1233 					"#extension GL_EXT_tessellation_shader : require\n"
1234 					"layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1235 					"void main (void)\n"
1236 					"{\n"
1237 					"    gl_TessLevelInner[0] = 1.0;\n"
1238 					"    gl_TessLevelInner[1] = 1.0;\n"
1239 					"    gl_TessLevelOuter[0] = 1.0;\n"
1240 					"    gl_TessLevelOuter[1] = 1.0;\n"
1241 					"    gl_TessLevelOuter[2] = 1.0;\n"
1242 					"    gl_TessLevelOuter[3] = 1.0;\n"
1243 					"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1244 					"}\n";
1245 
1246 		teseSrc	<<	"#version 450\n"
1247 					"#extension GL_EXT_tessellation_shader : require\n"
1248 					"layout(triangles) in;\n";
1249 
1250 		if (m_parameters.transformFeedback)
1251 			teseSrc	<<	"layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1252 
1253 		teseSrc	<<	"void main (void)\n"
1254 					"{\n";
1255 
1256 		if (m_parameters.transformFeedback)
1257 			teseSrc	<<	"    out0 = vec4(42);\n";
1258 
1259 		teseSrc	<<	"    vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1260 					"    vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1261 					"    vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1262 					"    gl_Position = p0 + p1 + p2;\n"
1263 					"}\n";
1264 
1265 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1266 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1267 	}
1268 
1269 	// Geometry shader.
1270 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1271 	{
1272 		const bool			outputPoints	= m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1273 		const char* const	inputTopology	= topologyData.at(m_parameters.primitiveTopology).inputString;
1274 		const char* const	outputTopology	= outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1275 		const VkDeviceSize	outputPrimSize	= outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1276 		const VkDeviceSize	maxVertices		= m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1277 		const std::string	pgqEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1278 		const std::string	xfbEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1279 		const std::string	pgqEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1280 		const std::string	xfbEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1281 		std::ostringstream	src;
1282 
1283 		src	<<	"#version 450\n"
1284 				"layout(" << inputTopology << ") in;\n"
1285 				"layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1286 
1287 		if (m_parameters.transformFeedback)
1288 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1289 
1290 		src	<<	"void main (void)\n"
1291 				"{\n";
1292 
1293 		if (outputPoints)
1294 			src	<<	"    gl_PointSize = 1.0;\n";
1295 
1296 		if (m_parameters.transformFeedback)
1297 			src	<<	"    xfb = vec4(42);\n";
1298 
1299 		for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1300 			src	<<	"    " << pgqEmitCommand << ";\n";
1301 
1302 		src	<<	"    " << pgqEndCommand << ";\n";
1303 
1304 		if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1305 		{
1306 			for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1307 				src	<<	"    " << xfbEmitCommand << ";\n";
1308 
1309 			src	<<	"    " << xfbEndCommand << ";\n";
1310 		}
1311 
1312 		src	<<	"}\n";
1313 
1314 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1315 	}
1316 
1317 	// Fragment shader.
1318 	if (!m_parameters.rastDiscard())
1319 	{
1320 		std::ostringstream src;
1321 
1322 		if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1323 		{
1324 			src	<<	"#version 450\n"
1325 					"void main (void) {}\n";
1326 		}
1327 		else
1328 		{
1329 			src	<<	"#version 450\n"
1330 					"layout(location = 0) out vec4 out0;\n"
1331 					"void main (void)\n"
1332 					"{\n"
1333 					"    out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1334 					"}\n";
1335 		}
1336 
1337 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1338 	}
1339 }
1340 class ConcurrentPrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
1341 {
1342 public:
ConcurrentPrimitivesGeneratedQueryTestInstance(vkt::Context & context,const ConcurrentTestParameters & parameters)1343 							ConcurrentPrimitivesGeneratedQueryTestInstance	(vkt::Context &context, const ConcurrentTestParameters& parameters)
1344 																			: vkt::TestInstance	(context)
1345 																			, m_parameters		(parameters)
1346 																			{}
1347 
1348 private:
1349 	tcu::TestStatus			iterate											(void);
1350 	void					draw											(const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, deUint32 vertexCount, vk::VkBuffer indirectBuffer);
1351 	Move<VkPipeline>		makeGraphicsPipeline							(const DeviceInterface&	vk,
1352 																			 const VkDevice device,
1353 																			 const VkRenderPass renderPass);
1354 	void					fillVertexBuffer								(tcu::Vec2* vertices,
1355 																			 const deUint64 primitivesGenerated);
1356 	void					copyColorImageToBuffer							(const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer);
1357 
1358 	const ConcurrentTestParameters	m_parameters;
1359 	const deUint32					m_imageWidth	= 16;
1360 	const deUint32					m_imageHeight	= 16;
1361 	const deUint32					instanceCount	= 1u;
1362 	const deUint32					firstVertex		= 0u;
1363 	const deUint32					firstInstance	= 0u;
1364 };
1365 
1366 // Create a render pass with an initial and final layout of VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL.
1367 // The load operation will clear the attachment.
makeConstantLayoutRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat colorFormat)1368 Move<VkRenderPass> makeConstantLayoutRenderPass (const DeviceInterface&				vk,
1369 												 const VkDevice						device,
1370 												 const VkFormat						colorFormat)
1371 {
1372 	const auto constantLayout = VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL;
1373 
1374 	const VkAttachmentDescription colorAttachmentDescription =
1375 	{
1376 		0u,									// VkAttachmentDescriptionFlags    flags
1377 		colorFormat,						// VkFormat                        format
1378 		VK_SAMPLE_COUNT_1_BIT,				// VkSampleCountFlagBits           samples
1379 		VK_ATTACHMENT_LOAD_OP_CLEAR,		// VkAttachmentLoadOp              loadOp
1380 		VK_ATTACHMENT_STORE_OP_STORE,		// VkAttachmentStoreOp             storeOp
1381 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,	// VkAttachmentLoadOp              stencilLoadOp
1382 		VK_ATTACHMENT_STORE_OP_DONT_CARE,	// VkAttachmentStoreOp             stencilStoreOp
1383 		constantLayout,						// VkImageLayout                   initialLayout
1384 		constantLayout						// VkImageLayout                   finalLayout
1385 	};
1386 
1387 	const VkAttachmentReference colorAttachmentRef = makeAttachmentReference(0u, constantLayout);
1388 
1389 	const VkSubpassDescription subpassDescription =
1390 	{
1391 		0u,									// VkSubpassDescriptionFlags       flags
1392 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint             pipelineBindPoint
1393 		0u,									// deUint32                        inputAttachmentCount
1394 		nullptr,							// const VkAttachmentReference*    pInputAttachments
1395 		1u,									// deUint32                        colorAttachmentCount
1396 		&colorAttachmentRef,				// const VkAttachmentReference*    pColorAttachments
1397 		nullptr,							// const VkAttachmentReference*    pResolveAttachments
1398 		nullptr,							// const VkAttachmentReference*    pDepthStencilAttachment
1399 		0u,									// deUint32                        preserveAttachmentCount
1400 		nullptr								// const deUint32*                 pPreserveAttachments
1401 	};
1402 
1403 	const VkRenderPassCreateInfo renderPassInfo =
1404 	{
1405 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType                   sType
1406 		nullptr,									// const void*                       pNext
1407 		0u,											// VkRenderPassCreateFlags           flags
1408 		1u,											// deUint32                          attachmentCount
1409 		&colorAttachmentDescription,				// const VkAttachmentDescription*    pAttachments
1410 		1u,											// deUint32                          subpassCount
1411 		&subpassDescription,						// const VkSubpassDescription*       pSubpasses
1412 		0u,											// deUint32                          dependencyCount
1413 		nullptr										// const VkSubpassDependency*        pDependencies
1414 	};
1415 
1416 	return createRenderPass(vk, device, &renderPassInfo);
1417 }
1418 
1419 // Transitions the selected subresource range to color attachment optimal.
prepareColorAttachment(const DeviceInterface & vkd,const VkCommandBuffer cmdBuffer,const VkImage image,const VkImageSubresourceRange imageSRR)1420 void prepareColorAttachment (const DeviceInterface& vkd, const VkCommandBuffer cmdBuffer, const VkImage image, const VkImageSubresourceRange imageSRR)
1421 {
1422 	const auto barrier = makeImageMemoryBarrier(0u, 0u, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, image, imageSRR);
1423 	cmdPipelineImageMemoryBarrier(vkd, cmdBuffer, 0u, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, &barrier);
1424 }
1425 
iterate(void)1426 tcu::TestStatus ConcurrentPrimitivesGeneratedQueryTestInstance::iterate (void)
1427 {
1428 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
1429 	const VkDevice					device				= m_context.getDevice();
1430 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1431 	const VkQueue					queue				= m_context.getUniversalQueue();
1432 	Allocator&						allocator			= m_context.getDefaultAllocator();
1433 	tcu::TestLog&					log					= m_context.getTestContext().getLog();
1434 
1435 	const VkDeviceSize				primitivesGenerated = 32;
1436 	const deUint32					baseMipLevel		= 0;
1437 	const deUint32					levelCount			= 1;
1438 	const deUint32					baseArrayLayer		= 0;
1439 	const deUint32					layerCount			= 1;
1440 
1441 	const VkFormat					colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1442 
1443 	const VkImageCreateInfo colorImageCreateInfo =
1444 	{
1445 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType
1446 		DE_NULL,										// const void*				pNext
1447 		0u,												// VkImageCreateFlags		flags
1448 		VK_IMAGE_TYPE_2D,								// VkImageType				imageType
1449 		colorFormat,									// VkFormat					format
1450 		makeExtent3D(m_imageWidth, m_imageHeight, 1),	// VkExtent3D				extent
1451 		1u,												// deUint32					mipLevels
1452 		1u,												// deUint32					arrayLayers
1453 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples
1454 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling
1455 		VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT
1456 		| VK_IMAGE_USAGE_TRANSFER_SRC_BIT,				// VkImageUsageFlags		usage
1457 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
1458 		0u,												// deUint32					queueFamilyIndexCount
1459 		DE_NULL,										// const deUint32*			pQueueFamilyIndices
1460 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout
1461 	};
1462 
1463 	const VkImageSubresourceRange	colorSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
1464 
1465 	Move<VkImage>					colorImage				= makeImage(vk, device, colorImageCreateInfo);
1466 	de::MovePtr<Allocation>			colorImageAllocation	= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
1467 	Move<VkImageView>				colorImageView			= makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
1468 
1469 	// By using a constant-layout render pass, we can begin and end the render pass multiple times without layout transition hazards.
1470 	const Unique<VkRenderPass>		renderPass			(makeConstantLayoutRenderPass(vk, device, colorFormat));
1471 	const vk::VkClearValue			clearColor			= { { { 0.0f, 0.0f, 0.0f, 0.0f } } };
1472 	const Unique<VkFramebuffer>		framebuffer			(makeFramebuffer(vk, device, *renderPass, *colorImageView, m_imageWidth, m_imageHeight));
1473 	const Unique<VkPipeline>		pipeline			(ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
1474 
1475 	const VkBufferUsageFlags		usage				= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
1476 	const std::vector<deUint32>		queueFamilyIndices	(1, queueFamilyIndex);
1477 	const VkDeviceSize				vtxBufferSize		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
1478 	const VkBufferCreateInfo		createInfo			= makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
1479 
1480 	Move<VkBuffer>					vtxBuffer			= createBuffer(vk, device, &createInfo);
1481 	de::MovePtr<Allocation>			vtxBufferAlloc		= allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
1482 
1483 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1484 	const Unique<VkCommandBuffer>	primaryCmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1485 	const Unique<VkCommandBuffer>	secondaryCmdBuffer	(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_SECONDARY));
1486 
1487 	const bool						pgq64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1488 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
1489 	const bool						xfb64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
1490 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
1491 	const size_t					pgqResultSize		= pgq64 ? sizeof(deUint64) : sizeof(deUint32);
1492 	const size_t					xfbResultSize		= xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
1493 	const size_t					psResultsSize		= sizeof(deUint64);
1494 	const VkQueryResultFlags		pgqResultWidthBit	= pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
1495 	const VkQueryResultFlags		xfbResultWidthBit	= xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
1496 	const VkQueryResultFlags		psResultWidthBit	= 0;
1497 	const VkQueryResultFlags		pgqResultFlags		= VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
1498 	const VkQueryResultFlags		xfbResultFlags		= VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
1499 	const VkQueryResultFlags		psResultFlags		= VK_QUERY_RESULT_WAIT_BIT | psResultWidthBit;
1500 
1501 	const deUint32					pgqQueryCount			= 1;
1502 	const deUint32					xfbQueryCount			= (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ) ? 2 : 0;
1503 	const deUint32					psQueryCount			= (m_parameters.concurrentTestType >= CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1) ? 1 : 0;
1504 
1505 	std::vector<deUint8>				pgqResults			(pgqResultSize, 255u);
1506 	std::vector<std::vector<deUint8>>	xfbResults;
1507 	std::vector<std::vector<deUint8>>	psqResults;
1508 	if (xfbQueryCount > 0)
1509 	{
1510 		xfbResults.resize(xfbQueryCount);
1511 		for (deUint32 i = 0; i < xfbQueryCount; ++i)
1512 			xfbResults[i] = std::vector<deUint8>(xfbResultSize, 255u);
1513 	}
1514 	if (psQueryCount > 0)
1515 	{
1516 		psqResults.resize(psQueryCount);
1517 		for (deUint32 i = 0; i < psQueryCount; ++i)
1518 			psqResults[i] = std::vector<deUint8>(psResultsSize, 255u);
1519 	}
1520 
1521 	const VkQueryPoolCreateInfo		pgqCreateInfo		=
1522 	{
1523 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType
1524 		DE_NULL,									// const void*						pNext
1525 		0u,											// VkQueryPoolCreateFlags			flags
1526 		VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,		// VkQueryType						queryType
1527 		pgqQueryCount,								// deUint32							queryCount
1528 		0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics
1529 	};
1530 
1531 	const VkQueryPoolCreateInfo xfbCreateInfo =
1532 	{
1533 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// VkStructureType					sType
1534 		DE_NULL,										// const void*						pNext
1535 		0u,												// VkQueryPoolCreateFlags			flags
1536 		VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,	// VkQueryType						queryType
1537 		xfbQueryCount,									// deUint32							queryCount
1538 		0u,												// VkQueryPipelineStatisticFlags	pipelineStatistics
1539 	};
1540 
1541 	const VkQueryPoolCreateInfo psCreateInfo =
1542 	{
1543 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// VkStructureType					sType
1544 		DE_NULL,										// const void*						pNext
1545 		0u,												// VkQueryPoolCreateFlags			flags
1546 		VK_QUERY_TYPE_PIPELINE_STATISTICS,				// VkQueryType						queryType
1547 		psQueryCount,									// deUint32							queryCount
1548 		VK_QUERY_PIPELINE_STATISTIC_INPUT_ASSEMBLY_PRIMITIVES_BIT
1549 														// VkQueryPipelineStatisticFlags	pipelineStatistics
1550 	};
1551 
1552 	const Move<VkQueryPool>			pgqPool				(createQueryPool(vk, device, &pgqCreateInfo));
1553 	Move<VkQueryPool>				xfbPool;
1554 	Move<VkQueryPool>				psqPool;
1555 	if (xfbQueryCount > 0)
1556 		xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
1557 	if (psQueryCount > 0)
1558 		psqPool = createQueryPool(vk, device, &psCreateInfo);
1559 
1560 	const VkDeviceSize				primitivesWritten	= primitivesGenerated - 3;
1561 	const VkDeviceSize				verticesWritten		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
1562 	const VkDeviceSize				primitiveSize		= m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1563 	const VkDeviceSize				bytesPerVertex		= 4 * sizeof(float);
1564 	const VkDeviceSize				xfbBufferSize		= primitivesWritten * primitiveSize * bytesPerVertex;
1565 	Move<VkBuffer>					xfbBuffer;
1566 	de::MovePtr<Allocation>			xfbBufferAlloc;
1567 
1568 	{
1569 		const VkBufferUsageFlags	xfbUsage			= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
1570 		const VkBufferCreateInfo	xfbBufferCreateInfo	= makeBufferCreateInfo(xfbBufferSize, xfbUsage);
1571 
1572 		xfbBuffer		= createBuffer(vk, device, &xfbBufferCreateInfo);
1573 		xfbBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
1574 
1575 		VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
1576 	}
1577 
1578 	fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
1579 
1580 	VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
1581 
1582 	const vk::VkDeviceSize				colorOutputBufferSize	= m_imageWidth * m_imageHeight* tcu::getPixelSize(vk::mapVkFormat(colorFormat));
1583 	de::MovePtr<vk::BufferWithMemory>	colorOutputBuffer		= de::MovePtr<vk::BufferWithMemory>(new vk::BufferWithMemory(
1584 		vk, device, allocator, makeBufferCreateInfo(colorOutputBufferSize, vk::VK_BUFFER_USAGE_TRANSFER_DST_BIT), vk::MemoryRequirement::HostVisible));
1585 
1586 	de::MovePtr<vk::BufferWithMemory>	indirectBuffer			= de::MovePtr<BufferWithMemory>(new BufferWithMemory(vk, device, allocator, vk::makeBufferCreateInfo(sizeof(vk::VkDrawIndirectCommand), vk::VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT), vk::MemoryRequirement::HostVisible));;
1587 
1588 	const deUint32						vertexCount				= static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
1589 
1590 	if (m_parameters.indirect)
1591 	{
1592 		const vk::Allocation&			indirectAlloc			= (*indirectBuffer).getAllocation();
1593 		vk::VkDrawIndirectCommand*		indirectDataPtr			= reinterpret_cast<vk::VkDrawIndirectCommand*>(indirectAlloc.getHostPtr());
1594 
1595 		indirectDataPtr->vertexCount = vertexCount;
1596 		indirectDataPtr->instanceCount = instanceCount;
1597 		indirectDataPtr->firstVertex = firstVertex;
1598 		indirectDataPtr->firstInstance = firstInstance;
1599 
1600 		flushAlloc(vk, device, indirectAlloc);
1601 	}
1602 
1603 	const bool					secondaryCmdBufferUsed	= m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER;
1604 	const VkQueryControlFlags	queryControlFlags		= 0;
1605 	const VkDeviceSize			vertexBufferOffset		= static_cast<VkDeviceSize>(0);
1606 
1607 	VkCommandBuffer cmdBuffer;
1608 
1609 	if (secondaryCmdBufferUsed)
1610 	{
1611 		cmdBuffer = *secondaryCmdBuffer;
1612 		beginSecondaryCommandBuffer(vk, cmdBuffer, *renderPass, *framebuffer);
1613 	}
1614 	else
1615 	{
1616 		cmdBuffer = *primaryCmdBuffer;
1617 		beginCommandBuffer(vk, cmdBuffer);
1618 		prepareColorAttachment(vk, cmdBuffer, *colorImage, colorSubresourceRange);
1619 	}
1620 
1621 	if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1622 	{
1623 		const VkCommandBufferInheritanceInfo inheritanceInfo =
1624 		{
1625 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_INHERITANCE_INFO,	//	VkStructureType					sType;
1626 			nullptr,											//	const void*						pNext;
1627 			*renderPass,										//	VkRenderPass					renderPass;
1628 			0u,													//	deUint32						subpass;
1629 			*framebuffer,										//	VkFramebuffer					framebuffer;
1630 			VK_FALSE,											//	VkBool32						occlusionQueryEnable;
1631 			queryControlFlags,									//	VkQueryControlFlags				queryFlags;
1632 			psCreateInfo.pipelineStatistics,					//	VkQueryPipelineStatisticFlags	pipelineStatistics;
1633 		};
1634 
1635 		const VkCommandBufferBeginInfo beginInfo =
1636 		{
1637 			VK_STRUCTURE_TYPE_COMMAND_BUFFER_BEGIN_INFO,		//	VkStructureType							sType;
1638 			nullptr,											//	const void*								pNext;
1639 			VK_COMMAND_BUFFER_USAGE_RENDER_PASS_CONTINUE_BIT,	//	VkCommandBufferUsageFlags				flags;
1640 			&inheritanceInfo,									//	const VkCommandBufferInheritanceInfo*	pInheritanceInfo;
1641 		};
1642 
1643 		vk.beginCommandBuffer(*secondaryCmdBuffer, &beginInfo);
1644 		vk.cmdBeginQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1645 		vk.cmdBindPipeline(*secondaryCmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1646 		vk.cmdBindVertexBuffers(*secondaryCmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1647 		draw(vk, *secondaryCmdBuffer, vertexCount, indirectBuffer->get());
1648 		vk.cmdEndQueryIndexedEXT(*secondaryCmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1649 		vk.endCommandBuffer(*secondaryCmdBuffer);
1650 	}
1651 
1652 	{
1653 		// After query pool creation, each query must be reset before it is used.
1654 		if (!secondaryCmdBufferUsed)
1655 		{
1656 			vk.cmdResetQueryPool(cmdBuffer, *pgqPool, 0, pgqQueryCount);
1657 			if (xfbQueryCount > 0)
1658 				vk.cmdResetQueryPool(cmdBuffer, *xfbPool, 0, xfbQueryCount);
1659 			if (psQueryCount > 0)
1660 				vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1661 		}
1662 
1663 		vk.cmdBindPipeline(cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1664 		vk.cmdBindVertexBuffers(cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
1665 
1666 		{
1667 			const deUint32				firstCounterBuffer		= 0;
1668 			const deUint32				counterBufferCount		= 0;
1669 			const VkBuffer*				counterBuffers			= DE_NULL;
1670 			const VkDeviceSize*			counterBufferOffsets	= DE_NULL;
1671 
1672 			if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1673 			{
1674 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1675 
1676 				// Begin PGQ
1677 				vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1678 
1679 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1680 
1681 				// Begin XFBQ 1
1682 				{
1683 					const deUint32		firstBinding = 0;
1684 					const deUint32		bindingCount = 1;
1685 					const VkDeviceSize	offset = 0;
1686 
1687 					vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
1688 					vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 0, queryControlFlags, m_parameters.xfbStreamIndex());
1689 					vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1690 				}
1691 
1692 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1693 
1694 				// End XFBQ 1
1695 				{
1696 					vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 0, m_parameters.xfbStreamIndex());
1697 					vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1698 				}
1699 
1700 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1701 
1702 				// Begin XFBQ 1
1703 				{
1704 					const deUint32		firstBinding = 0;
1705 					const deUint32		bindingCount = 1;
1706 					const VkDeviceSize	offset = 0;
1707 
1708 					vk.cmdBindTransformFeedbackBuffersEXT(cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
1709 					vk.cmdBeginQueryIndexedEXT(cmdBuffer, *xfbPool, 1, queryControlFlags, m_parameters.xfbStreamIndex());
1710 					vk.cmdBeginTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1711 				}
1712 
1713 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1714 
1715 				// End XFBQ 1
1716 				{
1717 					vk.cmdEndQueryIndexedEXT(cmdBuffer, *xfbPool, 1, m_parameters.xfbStreamIndex());
1718 					vk.cmdEndTransformFeedbackEXT(cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
1719 				}
1720 
1721 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1722 
1723 				// End PGQ
1724 				vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1725 
1726 				endRenderPass(vk, cmdBuffer);
1727 			}
1728 			else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER)
1729 			{
1730 
1731 				vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1732 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1733 				vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1734 			}
1735 			else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1)
1736 			{
1737 				vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1738 				vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1739 
1740 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1741 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1742 				endRenderPass(vk, cmdBuffer);
1743 
1744 				vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1745 
1746 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1747 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1748 				endRenderPass(vk, cmdBuffer);
1749 
1750 				vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1751 			}
1752 			else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1753 			{
1754 				vk.cmdBeginQueryIndexedEXT(cmdBuffer, *pgqPool, 0, queryControlFlags, m_parameters.pgqStreamIndex());
1755 
1756 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1757 				vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1758 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1759 				vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1760 				endRenderPass(vk, cmdBuffer);
1761 
1762 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1763 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1764 				endRenderPass(vk, cmdBuffer);
1765 
1766 				vk.cmdEndQueryIndexedEXT(cmdBuffer, *pgqPool, 0, m_parameters.pgqStreamIndex());
1767 			}
1768 			else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1769 			{
1770 				vk.cmdBeginQuery(cmdBuffer, *psqPool, 0, queryControlFlags);
1771 
1772 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1773 				vk.cmdExecuteCommands(cmdBuffer, 1u, &*secondaryCmdBuffer);
1774 				endRenderPass(vk, cmdBuffer);
1775 
1776 				beginRenderPass(vk, cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor);
1777 				draw(vk, cmdBuffer, vertexCount, indirectBuffer->get());
1778 				endRenderPass(vk, cmdBuffer);
1779 
1780 				vk.cmdEndQuery(cmdBuffer, *psqPool, 0);
1781 			}
1782 		}
1783 	}
1784 
1785 	if (!secondaryCmdBufferUsed)
1786 		copyColorImageToBuffer(vk, cmdBuffer, *colorImage, **colorOutputBuffer);
1787 
1788 	vk::endCommandBuffer(vk, cmdBuffer);
1789 
1790 	if (secondaryCmdBufferUsed)
1791 	{
1792 		vk::beginCommandBuffer(vk, *primaryCmdBuffer);
1793 		prepareColorAttachment(vk, *primaryCmdBuffer, *colorImage, colorSubresourceRange);
1794 		vk.cmdResetQueryPool(*primaryCmdBuffer, *pgqPool, 0, pgqQueryCount);
1795 		if (xfbQueryCount > 0)
1796 			vk.cmdResetQueryPool(*primaryCmdBuffer, *xfbPool, 0, xfbQueryCount);
1797 		if (psQueryCount > 0)
1798 			vk.cmdResetQueryPool(cmdBuffer, *psqPool, 0, psQueryCount);
1799 		beginRenderPass(vk, *primaryCmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)), clearColor, vk::VK_SUBPASS_CONTENTS_SECONDARY_COMMAND_BUFFERS);
1800 		vk.cmdExecuteCommands(*primaryCmdBuffer, 1u, &*secondaryCmdBuffer);
1801 		endRenderPass(vk, *primaryCmdBuffer);
1802 		copyColorImageToBuffer(vk, *primaryCmdBuffer, *colorImage, **colorOutputBuffer);
1803 		vk::endCommandBuffer(vk, *primaryCmdBuffer);
1804 	}
1805 
1806 	vk::submitCommandsAndWait(vk, device, queue, *primaryCmdBuffer);
1807 
1808 	vk.getQueryPoolResults(device, *pgqPool, 0, pgqQueryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
1809 	for (deUint32 i = 0; i < xfbQueryCount; ++i)
1810 		vk.getQueryPoolResults(device, *xfbPool, i, 1, xfbResults[i].size(), xfbResults[i].data(), xfbResults[i].size(), xfbResultFlags);
1811 	for (deUint32 i = 0; i < psQueryCount; ++i)
1812 		vk.getQueryPoolResults(device, *psqPool, i, 1, psqResults[i].size(), psqResults[i].data(), psqResults[i].size(), psResultFlags);
1813 
1814 	// Validate counters.
1815 	{
1816 		deUint32 pgqDrawCount = 1;
1817 		if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
1818 			pgqDrawCount = 5;
1819 		else if (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2)
1820 			pgqDrawCount = 2;
1821 		const deUint32 totalPrimitivesGenerated = static_cast<deUint32>(primitivesGenerated * pgqDrawCount);
1822 
1823 		union QueryResults
1824 		{
1825 			deUint32	elements32[2];
1826 			deUint64	elements64[2];
1827 		};
1828 
1829 		const QueryResults*			pgqCounters		= reinterpret_cast<QueryResults*>(pgqResults.data());
1830 		const deUint64				pgqGenerated	= pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
1831 		std::vector< QueryResults*> xfbCounters		(xfbResults.size());
1832 		std::vector<deUint64>		xfbWritten		(xfbResults.size());
1833 		std::vector<deUint64>		xfbGenerated	(xfbResults.size());
1834 
1835 		for (deUint32 i = 0; i < xfbQueryCount; ++i)
1836 		{
1837 			xfbCounters[i] = reinterpret_cast<QueryResults*>(xfbResults[i].data());
1838 			xfbWritten[i] = xfb64 ? xfbCounters[i]->elements64[0] : static_cast<deUint64>(xfbCounters[i]->elements32[0]);
1839 			xfbGenerated[i] = xfb64 ? xfbCounters[i]->elements64[1] : static_cast<deUint64>(xfbCounters[i]->elements32[1]);
1840 		}
1841 
1842 		log	<<	tcu::TestLog::Message
1843 			<<	"primitivesGenerated: " << totalPrimitivesGenerated << "\n"
1844 			<<	"primitivesWritten: " << primitivesWritten << "\n"
1845 			<<	"verticesWritten: " << verticesWritten << "\n"
1846 			<<	"xfbBufferSize: " << xfbBufferSize << "\n"
1847 			<<	tcu::TestLog::EndMessage;
1848 
1849 		log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
1850 		for (deUint32 i = 0; i < (deUint32)xfbCounters.size(); ++i)
1851 			log << tcu::TestLog::Message << "XFB " << i << ": Written " << xfbWritten[i] << ", generated " << xfbGenerated[i] << tcu::TestLog::EndMessage;
1852 
1853 		if (pgqGenerated != totalPrimitivesGenerated)
1854 		{
1855 			const std::string message = std::string("Total pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(totalPrimitivesGenerated);
1856 			return tcu::TestStatus::fail(message);
1857 		}
1858 
1859 		for (deUint32 i = 0; i < (deUint32)xfbCounters.size(); ++i)
1860 		{
1861 			if (xfbGenerated[i] != primitivesGenerated)
1862 			{
1863 				const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated[i]) + ", expected " + de::toString(primitivesGenerated);
1864 				return tcu::TestStatus::fail(message);
1865 			}
1866 
1867 			if (xfbWritten[i] != primitivesWritten)
1868 			{
1869 				const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) + ", expected " + de::toString(primitivesWritten);
1870 				return tcu::TestStatus::fail(message);
1871 			}
1872 
1873 			if (xfbWritten[i] != (primitivesGenerated - 3))
1874 			{
1875 				const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten[i]) + ", expected " + de::toString(primitivesGenerated - 3);
1876 				return tcu::TestStatus::fail(message);
1877 			}
1878 		}
1879 
1880 		if (psQueryCount > 0)
1881 		{
1882 
1883 			const QueryResults*			psqCounters					= reinterpret_cast<QueryResults*>(psqResults[0].data());
1884 			const deUint64				inputAssemblyPrimitives		= psqCounters->elements32[0];
1885 
1886 			deUint32 drawCount = (m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1 ||
1887 								  m_parameters.concurrentTestType == CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3)
1888 								 ? 2 : 1;
1889 
1890 			if (inputAssemblyPrimitives != primitivesGenerated * drawCount)
1891 			{
1892 				const std::string message = std::string("input assembly primitives == ") + de::toString(inputAssemblyPrimitives) + ", expected " + de::toString(primitivesGenerated * drawCount);
1893 				return tcu::TestStatus::fail(message);
1894 			}
1895 		}
1896 	}
1897 
1898 	const auto tcuFormat	= vk::mapVkFormat(colorFormat);
1899 	const auto iWidth		= static_cast<int>(m_imageWidth);
1900 	const auto iHeight		= static_cast<int>(m_imageHeight);
1901 
1902 	tcu::ConstPixelBufferAccess	resultBuffer	= tcu::ConstPixelBufferAccess(tcuFormat, iWidth, iHeight, 1, colorOutputBuffer->getAllocation().getHostPtr());
1903 	tcu::TextureLevel			referenceLevel	(tcuFormat, iWidth, iHeight);
1904 	const auto					referenceAccess	= referenceLevel.getAccess();
1905 	const tcu::Vec4				bgColor			(0.0f, 0.0f, 0.0f, 0.0f);
1906 	const tcu::Vec4				geomColor		(0.0f, 1.0f, 0.0f, 1.0f);
1907 	const tcu::Vec4				threshold		(0.0f, 0.0f, 0.0f, 0.0f);
1908 	const int					colorRow		= 7;
1909 
1910 	tcu::clear(referenceAccess, bgColor);
1911 	const auto subregion = tcu::getSubregion(referenceAccess, 0, colorRow, iWidth, 1);
1912 	tcu::clear(subregion, geomColor);
1913 
1914 	if (!tcu::floatThresholdCompare(log, "Result", "", referenceAccess, resultBuffer, threshold, tcu::COMPARE_LOG_ON_ERROR))
1915 		return tcu::TestStatus::fail("Color buffer contains unexpected results; check log for details");
1916 	return tcu::TestStatus::pass("Pass");
1917 }
1918 
draw(const DeviceInterface & vk,vk::VkCommandBuffer cmdBuffer,deUint32 vertexCount,vk::VkBuffer indirectBuffer)1919 void ConcurrentPrimitivesGeneratedQueryTestInstance::draw (const DeviceInterface& vk, vk::VkCommandBuffer cmdBuffer, deUint32 vertexCount, vk::VkBuffer indirectBuffer)
1920 {
1921 	if (m_parameters.indirect)
1922 		vk.cmdDrawIndirect(cmdBuffer, indirectBuffer, 0u, 1u, sizeof(vk::VkDrawIndirectCommand));
1923 	else
1924 		vk.cmdDraw(cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
1925 }
1926 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)1927 Move<VkPipeline> ConcurrentPrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface& vk, const VkDevice device, const VkRenderPass renderPass)
1928 {
1929 	const VkDescriptorSetLayout						descriptorSetLayout				= DE_NULL;
1930 	const Unique<VkPipelineLayout>					pipelineLayout					(makePipelineLayout(vk, device, descriptorSetLayout));
1931 	const std::vector<VkViewport>					viewports						(1, makeViewport(makeExtent2D(m_imageWidth, m_imageHeight)));
1932 	const std::vector<VkRect2D>						scissors						(1, makeRect2D(makeExtent2D(m_imageWidth, m_imageHeight)));
1933 	const deUint32									subpass							= 0u;
1934 	const deUint32									patchControlPoints				= topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
1935 	const Unique<VkShaderModule>					vertModule						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1936 	Move<VkShaderModule>							tescModule;
1937 	Move<VkShaderModule>							teseModule;
1938 	Move<VkShaderModule>							geomModule;
1939 	Move<VkShaderModule>							fragModule						= createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
1940 	VkVertexInputBindingDescription					bindingDescription;
1941 	VkVertexInputAttributeDescription				attributeDescription;
1942 
1943 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1944 	{
1945 		tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1946 		teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1947 	}
1948 
1949 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1950 		geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1951 
1952 	bindingDescription.binding		= 0;
1953 	bindingDescription.stride		= sizeof(tcu::Vec2);
1954 	bindingDescription.inputRate	= VK_VERTEX_INPUT_RATE_VERTEX;
1955 
1956 	attributeDescription.binding	= 0;
1957 	attributeDescription.location	= 0;
1958 	attributeDescription.format		= VK_FORMAT_R32G32_SFLOAT;
1959 	attributeDescription.offset		= 0;
1960 
1961 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
1962 	{
1963 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType
1964 		DE_NULL,													// const void*								pNext
1965 		0u,															// VkPipelineVertexInputStateCreateFlags	flags
1966 		1u,															// deUint32									vertexBindingDescriptionCount
1967 		&bindingDescription,										// const VkVertexInputBindingDescription*	pVertexBindingDescriptions
1968 		1u,															// deUint32									vertexAttributeDescriptionCount
1969 		&attributeDescription,										// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions
1970 	};
1971 
1972 	const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
1973 	{
1974 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType
1975 		DE_NULL,													// const void*								pNext
1976 		0,															// VkPipelineRasterizationStateCreateFlags	flags
1977 		VK_FALSE,													// VkBool32									depthClampEnable
1978 		VK_FALSE,													// VkBool32									rasterizerDiscardEnable
1979 		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode
1980 		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode
1981 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace
1982 		VK_FALSE,													// VkBool32									depthBiasEnable
1983 		0.0f,														// float									depthBiasConstantFactor
1984 		0.0f,														// float									depthBiasClamp
1985 		0.0f,														// float									depthBiasSlopeFactor
1986 		1.0f														// float									lineWidth
1987 	};
1988 
1989 	const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState		=
1990 	{
1991 		VK_TRUE,					// VkBool32					blendEnable
1992 		VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcColorBlendFactor
1993 		VK_BLEND_FACTOR_ONE,		// VkBlendFactor			dstColorBlendFactor
1994 		VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
1995 		VK_BLEND_FACTOR_ONE,		// VkBlendFactor			srcAlphaBlendFactor
1996 		VK_BLEND_FACTOR_ONE,		// VkBlendFactor			dstAlphaBlendFactor
1997 		VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
1998 		VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
1999 		| VK_COLOR_COMPONENT_G_BIT
2000 		| VK_COLOR_COMPONENT_B_BIT
2001 		| VK_COLOR_COMPONENT_A_BIT
2002 	};
2003 
2004 	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo		=
2005 	{
2006 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
2007 		DE_NULL,													// const void*									pNext
2008 		0,															// VkPipelineColorBlendStateCreateFlags			flags
2009 		VK_FALSE,													// VkBool32										logicOpEnable
2010 		VK_LOGIC_OP_NO_OP,											// VkLogicOp									logicOp
2011 		1,															// deUint32										attachmentCount
2012 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments
2013 		{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4]
2014 	};
2015 
2016 	const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo		=
2017 	{
2018 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
2019 		nullptr,													//	const void*								pNext;
2020 		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
2021 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
2022 		VK_FALSE,													//	VkBool32								sampleShadingEnable;
2023 		1.0f,														//	float									minSampleShading;
2024 		nullptr,													//	const VkSampleMask*						pSampleMask;
2025 		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
2026 		VK_FALSE,													//	VkBool32								alphaToOneEnable;
2027 	};
2028 
2029 	return vk::makeGraphicsPipeline(vk,
2030 									device,
2031 									*pipelineLayout,
2032 									*vertModule,
2033 									*tescModule,
2034 									*teseModule,
2035 									*geomModule,
2036 									*fragModule,
2037 									renderPass,
2038 									viewports,
2039 									scissors,
2040 									m_parameters.primitiveTopology,
2041 									subpass,
2042 									patchControlPoints,
2043 									&vertexInputStateCreateInfo,
2044 									&rasterizationStateCreateInfo,
2045 									&multisampleStateCreateInfo,
2046 									DE_NULL,
2047 									&colorBlendStateCreateInfo);
2048 }
2049 
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)2050 void ConcurrentPrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
2051 {
2052 	const float step = 1.0f / static_cast<float>(primitivesGenerated - 1);
2053 
2054 	switch (m_parameters.primitiveTopology)
2055 	{
2056 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
2057 		{
2058 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2059 			{
2060 				vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2061 			}
2062 			break;
2063 		}
2064 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
2065 		{
2066 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2067 			{
2068 				vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  0.0f);
2069 				vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2070 			}
2071 			break;
2072 		}
2073 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
2074 		{
2075 			vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2076 			vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2077 
2078 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
2079 				vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  0.0f);
2080 			break;
2081 		}
2082 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
2083 		{
2084 			vertices[0] = tcu::Vec2(-1.0f,				 -0.001f);
2085 			vertices[1] = tcu::Vec2(-1.0f,				 -0.002f);
2086 			vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, -0.002f);
2087 
2088 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
2089 			{
2090 				vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, (prim % 2 == 0) ? -0.002f : -0.001f);
2091 			}
2092 			break;
2093 		}
2094 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
2095 		{
2096 			vertices[0] = tcu::Vec2(0.0f, -0.1f);
2097 			for (deUint32 prim = 0; prim < primitivesGenerated + 1; ++prim)
2098 			{
2099 				vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
2100 			}
2101 			break;
2102 		}
2103 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
2104 		{
2105 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2106 			{
2107 				vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)(prim - 1) * step, 0.0f);
2108 				vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 0) * step, 0.0f);
2109 				vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step, 0.0f);
2110 				vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 2) * step, 0.0f);
2111 			}
2112 			break;
2113 		}
2114 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
2115 		{
2116 			vertices[0] = tcu::Vec2(-1.0f, 0.0f);
2117 			vertices[1] = tcu::Vec2(-1.0f, 0.0f);
2118 
2119 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2120 			{
2121 				vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)(prim + 1) * step,  0.0f);
2122 			}
2123 
2124 			vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
2125 
2126 			break;
2127 		}
2128 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
2129 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
2130 		{
2131 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2132 			{
2133 				vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2134 				vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, 0.01f);
2135 				vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, 0.0f);
2136 			}
2137 			break;
2138 		}
2139 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
2140 		{
2141 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
2142 			{
2143 				vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2144 				vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.01f);
2145 				vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2146 				vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -0.02f);
2147 				vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2148 				vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -0.02f);
2149 			}
2150 			break;
2151 		}
2152 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
2153 		{
2154 			// A strip of triangles, each pair of them forming a quad, crossing the image from left to right.
2155 			const auto	quarterRow	= 2.0f / (static_cast<float>(m_imageHeight) * 4.0f);		// In height.
2156 			const auto	threeQRow	= 3.0f * quarterRow;										// In height.
2157 			const auto	quadStep	= 2.0f / (static_cast<float>(primitivesGenerated) / 2.0f);	// In width.
2158 			const float	yCoords[2]	= { -threeQRow, -quarterRow };
2159 
2160 			// The first two points on the left edge of the image.
2161 			vertices[0] = tcu::Vec2(-1.0f, yCoords[0]);
2162 			vertices[1] = tcu::Vec2(-1.0f, yCoords[0]);
2163 			vertices[2] = tcu::Vec2(-1.0f, yCoords[1]);
2164 			vertices[3] = tcu::Vec2(-1.0f, yCoords[1]);
2165 
2166 			for (uint32_t primIdx = 0u; primIdx < static_cast<uint32_t>(primitivesGenerated); ++primIdx)
2167 			{
2168 				const auto edgeIdx	= primIdx / 2u;
2169 				const auto yIDx		= primIdx % 2u;
2170 				const auto xCoord	= -1.0f + (static_cast<float>(edgeIdx) + 1.0f) * quadStep;
2171 				const auto yCoord	= yCoords[yIDx];
2172 				const auto vertIdx	= primIdx + 2u;
2173 
2174 				vertices[vertIdx * 2u + 0u] = tcu::Vec2(xCoord, yCoord);	// Vertex.
2175 				vertices[vertIdx * 2u + 1u] = tcu::Vec2(xCoord, yCoord);	// Adjacency point.
2176 			}
2177 			break;
2178 		}
2179 		default:
2180 			TCU_THROW(InternalError, "Unrecognized primitive topology");
2181 	}
2182 }
2183 
copyColorImageToBuffer(const DeviceInterface & vk,VkCommandBuffer cmdBuffer,VkImage image,VkBuffer buffer)2184 void ConcurrentPrimitivesGeneratedQueryTestInstance::copyColorImageToBuffer (const DeviceInterface& vk, VkCommandBuffer cmdBuffer, VkImage image, VkBuffer buffer)
2185 {
2186 	const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0, 1, 0, 1);
2187 	vk::VkImageMemoryBarrier postImageBarrier = vk::makeImageMemoryBarrier(vk::VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, vk::VK_ACCESS_TRANSFER_READ_BIT, vk::VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, vk::VK_IMAGE_LAYOUT_GENERAL, image, colorSubresourceRange);
2188 	vk.cmdPipelineBarrier(cmdBuffer, vk::VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, vk::VK_PIPELINE_STAGE_TRANSFER_BIT, (vk::VkDependencyFlags)0u, 0u, (const vk::VkMemoryBarrier*)DE_NULL, 0u, (const vk::VkBufferMemoryBarrier*)DE_NULL, 1u, &postImageBarrier);
2189 	vk::VkExtent3D extent = { m_imageWidth, m_imageHeight, 1 };
2190 	const auto colorSubresourceLayers = vk::makeImageSubresourceLayers(vk::VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u);
2191 	const vk::VkBufferImageCopy	colorCopyRegion = vk::makeBufferImageCopy(extent, colorSubresourceLayers);
2192 	vk.cmdCopyImageToBuffer(cmdBuffer, image, vk::VK_IMAGE_LAYOUT_GENERAL, buffer, 1u, &colorCopyRegion);
2193 }
2194 
2195 class ConcurrentPrimitivesGeneratedQueryTestCase : public vkt::TestCase
2196 {
2197 public:
ConcurrentPrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const ConcurrentTestParameters & parameters)2198 							ConcurrentPrimitivesGeneratedQueryTestCase	(tcu::TestContext &context, const char *name, const ConcurrentTestParameters& parameters)
2199 								: TestCase		(context, name)
2200 								, m_parameters	(parameters)
2201 							{
2202 							}
2203 
2204 private:
2205 	void					checkSupport						(vkt::Context& context) const;
2206 	void					initPrograms						(vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const2207 	vkt::TestInstance*		createInstance						(vkt::Context& context) const { return new ConcurrentPrimitivesGeneratedQueryTestInstance(context, m_parameters); }
2208 
2209 	const ConcurrentTestParameters	m_parameters;
2210 };
2211 
checkSupport(vkt::Context & context) const2212 void ConcurrentPrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
2213 {
2214 	context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
2215 	context.requireDeviceFunctionality("VK_EXT_transform_feedback");
2216 
2217 	const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT&	pgqFeatures		= context.getPrimitivesGeneratedQueryFeaturesEXT();
2218 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&			xfbFeatures		= context.getTransformFeedbackFeaturesEXT();
2219 	const VkPhysicalDeviceTransformFeedbackPropertiesEXT&		xfbProperties	= context.getTransformFeedbackPropertiesEXT();
2220 
2221 	if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
2222 		TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
2223 
2224 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
2225 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
2226 
2227 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
2228 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
2229 
2230 	if (m_parameters.nonZeroStreams())
2231 	{
2232 		const deUint32 requiredStreams	= de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
2233 
2234 		if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
2235 			TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
2236 
2237 		if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
2238 			TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
2239 	}
2240 
2241 	if (xfbFeatures.transformFeedback != VK_TRUE)
2242 		TCU_THROW(NotSupportedError, "transformFeedback not supported");
2243 
2244 	if (xfbProperties.transformFeedbackQueries != VK_TRUE)
2245 		TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
2246 }
2247 
initPrograms(vk::SourceCollections & programCollection) const2248 void ConcurrentPrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
2249 {
2250 	bool transformFeedback = m_parameters.xfbStreamIndex() != VERTEX_STREAM_NONE;
2251 	// Vertex shader.
2252 	{
2253 		const bool			vertXfb	= (transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
2254 		std::ostringstream	src;
2255 
2256 		src	<<	"#version 450\n";
2257 		src << "layout(location=0) in vec2 inPosition;\n";
2258 
2259 		if (vertXfb)
2260 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
2261 
2262 		src	<<	"void main (void)\n"
2263 				"{\n";
2264 
2265 		if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
2266 			src	<<	"    gl_PointSize = 1.0;\n";
2267 
2268 		src << "    gl_Position = vec4(inPosition, 0, 1);\n";
2269 
2270 		if (vertXfb)
2271 			src	<<	"    out0 = vec4(42);\n";
2272 
2273 		src	<<	"}\n";
2274 
2275 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2276 	}
2277 
2278 	// Geometry shader.
2279 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
2280 	{
2281 		const bool			outputPoints	= m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
2282 		const char* const	inputTopology	= topologyData.at(m_parameters.primitiveTopology).inputString;
2283 		const char* const	outputTopology	= outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
2284 		const VkDeviceSize	outputPrimSize	= outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
2285 		VkDeviceSize		maxVertices		= (transformFeedback && m_parameters.multipleStreams()) ? outputPrimSize * 2 : outputPrimSize;
2286 		const bool			outputZero		= m_parameters.pgqStreamIndex() != 0 && (!transformFeedback || (transformFeedback && m_parameters.xfbStreamIndex() != 0));
2287 		if (outputZero) maxVertices *= 2;
2288 		const std::string	pgqEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
2289 		const std::string	xfbEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
2290 		const std::string	pgqEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
2291 		const std::string	xfbEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
2292 		std::string			output;
2293 
2294 		if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY)
2295 		{
2296 			output =
2297 				// Each point will be in the middle X and Y coordinates of each triangle.
2298 				"    const vec3 xCoords = vec3(gl_in[0].gl_Position.x, gl_in[2].gl_Position.x, gl_in[4].gl_Position.x);\n"
2299 				"    const vec3 yCoords = vec3(gl_in[0].gl_Position.y, gl_in[2].gl_Position.y, gl_in[4].gl_Position.y);\n"
2300 				"    const float maxX = max(max(xCoords.x, xCoords.y), xCoords.z);\n"
2301 				"    const float minX = min(min(xCoords.x, xCoords.y), xCoords.z);\n"
2302 				"    const float maxY = max(max(yCoords.x, yCoords.y), yCoords.z);\n"
2303 				"    const float minY = min(min(yCoords.x, yCoords.y), yCoords.z);\n"
2304 				"    gl_Position = vec4((maxX + minX) / 2.0, (maxY + minY) / 2.0, gl_in[0].gl_Position.z, gl_in[0].gl_Position.w);\n"
2305 				;
2306 		}
2307 		else if (m_parameters.primitiveTopology != VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN)
2308 			output = "    gl_Position = gl_in[0].gl_Position;\n";
2309 		else
2310 			output = "    gl_Position = abs(gl_in[0].gl_Position.y) < abs(gl_in[1].gl_Position.y) ? gl_in[0].gl_Position : gl_in[1].gl_Position;\n";
2311 
2312 		if (outputPoints)
2313 			output += "    gl_PointSize = 1.0;\n";
2314 
2315 		std::ostringstream	src;
2316 
2317 		src	<<	"#version 450\n"
2318 				"layout(" << inputTopology << ") in;\n"
2319 				"layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
2320 
2321 		if (transformFeedback)
2322 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
2323 
2324 		src	<<	"void main (void)\n"
2325 				"{\n";
2326 
2327 		if (outputZero)
2328 		{
2329 			src << output;
2330 			src << "    EmitVertex();\n";
2331 			src << "    EndPrimitive();\n";
2332 		}
2333 
2334 		if (transformFeedback)
2335 			src	<<	"    xfb = vec4(42);\n";
2336 
2337 		for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2338 		{
2339 			if (m_parameters.pgqStreamIndex() == 0)
2340 				src << output;
2341 			src	<<	"    " << pgqEmitCommand << ";\n";
2342 		}
2343 
2344 		src	<<	"    " << pgqEndCommand << ";\n";
2345 
2346 		if (transformFeedback && m_parameters.multipleStreams())
2347 		{
2348 			for (VkDeviceSize i = 0; i < outputPrimSize; i++)
2349 			{
2350 				if (m_parameters.xfbStreamIndex() == 0)
2351 					src << output;
2352 				src << "    " << xfbEmitCommand << ";\n";
2353 			}
2354 
2355 			src	<<	"    " << xfbEndCommand << ";\n";
2356 		}
2357 
2358 		src	<<	"}\n";
2359 
2360 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2361 	}
2362 
2363 	// Fragment shader.
2364 	{
2365 		std::ostringstream src;
2366 
2367 		src	<<	"#version 450\n"
2368 				"layout(location = 0) out vec4 out0;\n"
2369 				"void main (void)\n"
2370 				"{\n"
2371 				"    out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
2372 				"}\n";
2373 
2374 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
2375 	}
2376 }
2377 
testGenerator(tcu::TestCaseGroup * pgqGroup)2378 void testGenerator (tcu::TestCaseGroup* pgqGroup)
2379 {
2380 	constexpr struct ReadType
2381 	{
2382 		QueryReadType	type;
2383 		const char*		name;
2384 	} readTypes[] =
2385 	{
2386 		// Tests for vkGetQueryPoolResults
2387 		{ QUERY_READ_TYPE_GET,	"get"},
2388 		// Tests for vkCmdCopyQueryPoolResults
2389 		{ QUERY_READ_TYPE_COPY,	"copy"},
2390 	};
2391 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
2392 
2393 	constexpr struct ResetType
2394 	{
2395 		QueryResetType	type;
2396 		const char*		name;
2397 	} resetTypes[] =
2398 	{
2399 		// Tests for vkCmdResetQueryPool
2400 		{ QUERY_RESET_TYPE_QUEUE,	"queue_reset"},
2401 		// Tests for vkResetQueryPool
2402 		{ QUERY_RESET_TYPE_HOST,	"host_reset"},
2403 	};
2404 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
2405 
2406 	constexpr struct ResultTypes
2407 	{
2408 		QueryResultType	type;
2409 		const char*		name;
2410 	} resultTypes[] =
2411 	{
2412 		// Tests for default query result size
2413 		{ QUERY_RESULT_TYPE_32_BIT,			"32bit"},
2414 		// Tests for VK_QUERY_RESULT_64_BIT
2415 		{ QUERY_RESULT_TYPE_64_BIT,			"64bit"},
2416 		// Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT
2417 		{ QUERY_RESULT_TYPE_PGQ_32_XFB_64,	"pgq_32bit_xfb_64bit"},
2418 		// Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT
2419 		{ QUERY_RESULT_TYPE_PGQ_64_XFB_32,	"pgq_64bit_xfb_32bit"},
2420 	};
2421 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
2422 
2423 	constexpr struct Shader
2424 	{
2425 		ShaderStage	stage;
2426 		const char*	name;
2427 	} shaderStages[] =
2428 	{
2429 		// Vertex shader tests
2430 		{ SHADER_STAGE_VERTEX,					"vert"},
2431 		// Tessellation evaluation shader tests
2432 		{ SHADER_STAGE_TESSELLATION_EVALUATION,	"tese"},
2433 		// Geometry shader tests
2434 		{ SHADER_STAGE_GEOMETRY,				"geom"},
2435 	};
2436 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
2437 
2438 	constexpr struct TransformFeedbackState
2439 	{
2440 		deBool		enable;
2441 		const char*	name;
2442 	} transformFeedbackStates[] =
2443 	{
2444 		// Tests without transform feedback
2445 		{ DE_FALSE,	"no_xfb"},
2446 		// Tests for comparing PGQ results against transform feedback query results
2447 		{ DE_TRUE,	"xfb"},
2448 	};
2449 
2450 	constexpr struct RastCase
2451 	{
2452 		RasterizationCase	type;
2453 		deBool				dsAttachment;
2454 		const char*			name;
2455 	} rastCases[] =
2456 	{
2457 		// Tests with rasterizer discard
2458 		{ RAST_CASE_DISCARD,						DE_FALSE,	"no_rast"},
2459 		// Tests without rasterizer discard
2460 		{ RAST_CASE_DEFAULT,						DE_FALSE,	"rast"},
2461 		// Tests with an empty fragment shader
2462 		{ RAST_CASE_EMPTY_FRAG,						DE_FALSE,	"empty_frag"},
2463 		// Tests with an attachmentless render pass
2464 		{ RAST_CASE_NO_ATTACHMENT,					DE_FALSE,	"no_attachment"},
2465 		// Tests disabling color output using VkPipelineColorWriteCreateInfoEXT
2466 		{ RAST_CASE_COLOR_WRITE_DISABLE_STATIC,		DE_FALSE,	"color_write_disable_static"},
2467 		// Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment
2468 		{ RAST_CASE_COLOR_WRITE_DISABLE_STATIC,		DE_TRUE,	"color_write_disable_static_ds"},
2469 		// Tests disabling color output using vkCmdSetColorWriteEnableEXT
2470 		{ RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,	DE_FALSE,	"color_write_disable_dynamic"},
2471 		// Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment
2472 		{ RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,	DE_TRUE,	"color_write_disable_dynamic_ds"},
2473 	};
2474 
2475 	static const std::set<RasterizationCase> rasterizationCasesWithAvailability
2476 	{
2477 		RAST_CASE_DISCARD,
2478 		RAST_CASE_DEFAULT,
2479 		RAST_CASE_NO_ATTACHMENT,
2480 	};
2481 
2482 	constexpr struct Topology
2483 	{
2484 		VkPrimitiveTopology	type;
2485 		const char*			name;
2486 	} topologies[] =
2487 	{
2488 		// Tests for separate point primitives
2489 		{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,						"point_list"},
2490 		// Tests for separate line primitives
2491 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						"line_list"},
2492 		// Tests for connected line primitives with consecutive lines sharing a vertex
2493 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						"line_strip"},
2494 		// Tests for separate triangle primitives
2495 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					"triangle_list"},
2496 		// Tests for connected triangle primitives with consecutive triangles sharing an edge
2497 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					"triangle_strip"},
2498 		// Tests for connected triangle primitives with all triangles sharing a common vertex
2499 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,					"triangle_fan"},
2500 		// Tests for separate line primitives with adjacency
2501 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,		"line_list_with_adjacency"},
2502 		// Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices
2503 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		"line_strip_with_adjacency"},
2504 		// Tests for separate triangle primitives with adjacency
2505 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,	"triangle_list_with_adjacency"},
2506 		// Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge
2507 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,	"triangle_strip_with_adjacency"},
2508 		// Tests for separate patch primitives
2509 		{ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,						"patch_list"},
2510 	};
2511 
2512 	static const std::set<VkPrimitiveTopology> topologiesWithAvailability
2513 	{
2514 		VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
2515 		VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
2516 		VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
2517 	};
2518 
2519 	// Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
2520 	constexpr struct StreamIndex
2521 	{
2522 		VertexStream	index;
2523 		const char*		name;
2524 	} streamIndices[] =
2525 	{
2526 		{ VERTEX_STREAM_DEFAULT,	"default"	},
2527 		{ VERTEX_STREAM_0,			"0"			},
2528 		{ VERTEX_STREAM_1,			"1"			},
2529 	};
2530 
2531 	constexpr struct CmdBufCase
2532 	{
2533 		CommandBufferCase	type;
2534 		const char*			name;
2535 	} cmdBufCases[] =
2536 	{
2537 		// Test single draw call
2538 		{ CMD_BUF_CASE_SINGLE_DRAW,	"single_draw"},
2539 		// Test two draw calls
2540 		{ CMD_BUF_CASE_TWO_DRAWS,	"two_draws"},
2541 	};
2542 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
2543 
2544 	constexpr struct
2545 	{
2546 		uint32_t			queryCount;
2547 		const char*			nameSuffix;
2548 	} queryCountCases[] =
2549 	{
2550 		{ 1u,	""},
2551 		//  using 2 queries
2552 		{ 2u,	"_2_queries"},
2553 	};
2554 
2555 	constexpr struct QueryOrderCase
2556 	{
2557 		QueryOrder			order;
2558 		const char*			name;
2559 	} queryOrderCases[] =
2560 	{
2561 		// Test starting primitives generated query first
2562 		{ QUERY_ORDER_PGQ_FIRST,	"pqg_first"},
2563 		// Test starting transform feedback query first
2564 		{ QUERY_ORDER_XFBQ_FIRST,	"xfbq_first"},
2565 	};
2566 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(queryOrderCases) == QUERY_ORDER_LAST);
2567 
2568 	constexpr struct OutsideDrawCase
2569 	{
2570 		OutsideDraw			outsideDraw;
2571 		const char*			name;
2572 	} outsideDrawCases[] =
2573 	{
2574 		// Test without draws outside of active queries
2575 		{ OUTSIDE_DRAW_NONE,		"none"},
2576 		// Test with draws before active queries
2577 		{ OUTSIDE_DRAW_BEFORE,		"before"},
2578 		// Test with draw after active queries
2579 		{ OUTSIDE_DRAW_AFTER,		"after"},
2580 	};
2581 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(outsideDrawCases) == OUTSIDE_DRAW_LAST);
2582 
2583 	tcu::TestContext& testCtx = pgqGroup->getTestContext();
2584 
2585 	for (const ReadType& read : readTypes)
2586 	{
2587 		de::MovePtr<tcu::TestCaseGroup> readGroup(new tcu::TestCaseGroup(testCtx, read.name));
2588 
2589 		for (const ResetType& reset : resetTypes)
2590 		{
2591 			de::MovePtr<tcu::TestCaseGroup> resetGroup(new tcu::TestCaseGroup(testCtx, reset.name));
2592 
2593 			for (const ResultTypes& result : resultTypes)
2594 			{
2595 				de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2596 
2597 				for (const Shader& shader : shaderStages)
2598 				{
2599 					de::MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shader.name));
2600 
2601 					for (const TransformFeedbackState& xfbState : transformFeedbackStates)
2602 					{
2603 						de::MovePtr<tcu::TestCaseGroup> xfbGroup(new tcu::TestCaseGroup(testCtx, xfbState.name));
2604 
2605 						// Only test multiple result types with XFB enabled.
2606 						if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
2607 							continue;
2608 
2609 						for (const RastCase& rastCase : rastCases)
2610 						{
2611 							de::MovePtr<tcu::TestCaseGroup> rastGroup(new tcu::TestCaseGroup(testCtx, rastCase.name));
2612 
2613 							// Skip uninteresting cases
2614 							if ((rastCase.type > RAST_CASE_DISCARD)
2615 								&& ((read.type != QUERY_READ_TYPE_GET)
2616 								|| (reset.type != QUERY_RESET_TYPE_QUEUE)
2617 								|| (result.type != QUERY_RESULT_TYPE_32_BIT)))
2618 							{
2619 								continue;
2620 							}
2621 
2622 							for (const Topology& topology : topologies)
2623 							{
2624 								de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name));
2625 
2626 								// Only test patch lists with tessellation shaders.
2627 								if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
2628 								   ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
2629 								{
2630 									continue;
2631 								}
2632 
2633 								// Only test adjacency topologies with geometry shaders.
2634 								if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
2635 									continue;
2636 
2637 								for (const StreamIndex& pgqStream : streamIndices)
2638 								{
2639 									for (const StreamIndex& xfbStream : streamIndices)
2640 									{
2641 										const std::string			streamGroupName	= std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
2642 										const bool					pgqDefault		= (pgqStream.index == VERTEX_STREAM_DEFAULT);
2643 										const bool					xfbDefault		= (xfbStream.index == VERTEX_STREAM_DEFAULT);
2644 										const std::string			pgqDescStr		= std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
2645 										const std::string			xfbDescStr		= std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
2646 										const std::string			streamGroupDesc	= std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
2647 										de::MovePtr<tcu::TestCaseGroup>	streamGroup(new tcu::TestCaseGroup(testCtx, streamGroupName.c_str()));
2648 
2649 										// Only test nondefault vertex streams with geometry shaders.
2650 										if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
2651 											continue;
2652 
2653 										// Skip nondefault vertex streams for XFB when not enabled.
2654 										if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
2655 											continue;
2656 
2657 										for (const CmdBufCase& cmdBufCase : cmdBufCases)
2658 										{
2659 											de::MovePtr<tcu::TestCaseGroup>	cmdBufGroup(new tcu::TestCaseGroup(testCtx, cmdBufCase.name));
2660 
2661 											for (const QueryOrderCase& queryOrderCase : queryOrderCases)
2662 											{
2663 												if (queryOrderCase.order == QUERY_ORDER_XFBQ_FIRST && xfbState.enable == DE_FALSE)
2664 													continue;
2665 
2666 												de::MovePtr<tcu::TestCaseGroup>	queryOrderGroup(new tcu::TestCaseGroup(testCtx, queryOrderCase.name));
2667 												for (const OutsideDrawCase& outSideDrawCase : outsideDrawCases)
2668 												{
2669 													for (const auto& countCase : queryCountCases)
2670 													{
2671 														for (const auto availabilityBit : { false, true})
2672 														{
2673 															if (availabilityBit && topologiesWithAvailability.count(topology.type) == 0)
2674 																continue;
2675 
2676 															if (availabilityBit && rasterizationCasesWithAvailability.count(rastCase.type) == 0)
2677 																continue;
2678 
2679 															if (availabilityBit && cmdBufCase.type != CMD_BUF_CASE_SINGLE_DRAW)
2680 																continue;
2681 
2682 															const TestParameters	parameters =
2683 															{
2684 																read.type,						// QueryReadType		queryReadType
2685 																reset.type,						// QueryResetType		queryResetType
2686 																result.type,					// QueryResultType		queryResultType
2687 																shader.stage,					// ShaderStage			shaderStage
2688 																xfbState.enable,				// deBool				transformFeedback
2689 																rastCase.type,					// RasterizationCase	rastCase
2690 																rastCase.dsAttachment,			// deBool				depthStencilAttachment
2691 																topology.type,					// VkPrimitiveTopology	primitiveTopology
2692 																pgqStream.index,				// VertexStreamIndex	pgqStreamIndex
2693 																xfbStream.index,				// VertexStreamIndex	xfbStreamIndex
2694 																cmdBufCase.type,				// CommandBufferCase	cmdBufCase
2695 																countCase.queryCount,			// const uint32_t		queryCount
2696 																queryOrderCase.order,			// QueryOrder			queryOrder
2697 																outSideDrawCase.outsideDraw,	// OutsideDraw			outsideDraw
2698 																availabilityBit,				// const bool			availabilityBit
2699 															};
2700 
2701 															const auto availabilityNameSuffix = (availabilityBit ? "_with_availability" : "");
2702 															const auto name = std::string(outSideDrawCase.name) + countCase.nameSuffix + availabilityNameSuffix;
2703 
2704 															queryOrderGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, name.c_str(), parameters));
2705 														}
2706 													}
2707 												}
2708 
2709 												cmdBufGroup->addChild(queryOrderGroup.release());
2710 											}
2711 
2712 											streamGroup->addChild(cmdBufGroup.release());
2713 										}
2714 
2715 										topologyGroup->addChild(streamGroup.release());
2716 									}
2717 								}
2718 
2719 								rastGroup->addChild(topologyGroup.release());
2720 							}
2721 
2722 							xfbGroup->addChild(rastGroup.release());
2723 						}
2724 
2725 						shaderGroup->addChild(xfbGroup.release());
2726 					}
2727 
2728 					resultGroup->addChild(shaderGroup.release());
2729 				}
2730 
2731 				resetGroup->addChild(resultGroup.release());
2732 			}
2733 
2734 			readGroup->addChild(resetGroup.release());
2735 		}
2736 
2737 		pgqGroup->addChild(readGroup.release());
2738 	}
2739 
2740 	constexpr struct ConcurrentTestTypeCase
2741 	{
2742 		ConcurrentTestType	type;
2743 		const char*			name;
2744 	}
2745 	concurrentTestTypeCases[] =
2746 	{
2747 		{ CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ,			"two_xfbq_inside_pgq"},
2748 		{ CONCURRENT_TEST_TYPE_PGQ_SECONDARY_CMD_BUFFER,	"pgq_secondary_cmd_buffers"},
2749 		{ CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_1,		"pipeline_statistics_1"},
2750 		{ CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_2,		"pipeline_statistics_2"},
2751 		{ CONCURRENT_TEST_TYPE_PIPELINE_STATISTICS_3,		"pipeline_statistics_3"},
2752 	};
2753 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(concurrentTestTypeCases) == CONCURRENT_TEST_TYPE_LAST);
2754 
2755 
2756 	constexpr struct DrawTypeCase
2757 	{
2758 		bool		indirect;
2759 		const char* name;
2760 	}
2761 	drawTypeCases[] =
2762 	{
2763 		{ false,	"draw"},
2764 		{ true,		"indirect"},
2765 	};
2766 
2767 	de::MovePtr<tcu::TestCaseGroup> concurrentGroup(new tcu::TestCaseGroup(testCtx, "concurrent"));
2768 
2769 	for (const ConcurrentTestTypeCase& concurrentTestType : concurrentTestTypeCases)
2770 	{
2771 		de::MovePtr<tcu::TestCaseGroup> concurrentTypeGroup(new tcu::TestCaseGroup(testCtx, concurrentTestType.name));
2772 		for (const ResultTypes& result : resultTypes)
2773 		{
2774 			de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name));
2775 
2776 			for (const Topology& topology : topologies)
2777 			{
2778 				// Testing only with geometry shaders, skip patch list
2779 				if (topology.type == vk::VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2780 					continue;
2781 
2782 				de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name));
2783 
2784 				for (const DrawTypeCase& draw : drawTypeCases)
2785 				{
2786 					VertexStream pgqStreamIndex = VERTEX_STREAM_DEFAULT;
2787 					VertexStream xfbStreamIndex = VERTEX_STREAM_NONE;
2788 					if (concurrentTestType.type == CONCURRENT_TEST_TYPE_TWO_XFB_INSIDE_PGQ)
2789 						xfbStreamIndex = VERTEX_STREAM_1;
2790 
2791 					const ConcurrentTestParameters	parameters =
2792 					{
2793 						concurrentTestType.type,		// ConcurrentTestType	concurrentTestType;
2794 						result.type,					// QueryResultType		queryResultType
2795 						SHADER_STAGE_GEOMETRY,			// ShaderStage			shaderStage
2796 						topology.type,					// VkPrimitiveTopology	primitiveTopology
2797 						pgqStreamIndex,					// VertexStreamIndex	pgqStreamIndex
2798 						xfbStreamIndex,					// VertexStreamIndex	xfbStreamIndex
2799 						draw.indirect,					// bool					indirect
2800 					};
2801 
2802 					topologyGroup->addChild(new ConcurrentPrimitivesGeneratedQueryTestCase(testCtx, draw.name, parameters));
2803 				}
2804 
2805 				resultGroup->addChild(topologyGroup.release());
2806 			}
2807 
2808 			concurrentTypeGroup->addChild(resultGroup.release());
2809 		}
2810 
2811 		concurrentGroup->addChild(concurrentTypeGroup.release());
2812 	}
2813 	pgqGroup->addChild(concurrentGroup.release());
2814 }
2815 
2816 } // anonymous
2817 
createPrimitivesGeneratedQueryTests(tcu::TestContext & testCtx)2818 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
2819 {
2820 	return createTestGroup(testCtx, "primitives_generated_query", testGenerator);
2821 }
2822 
2823 } // TransformFeedback
2824 } // vkt
2825