• 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 
36 #include "tcuTestLog.hpp"
37 
38 #include <functional>
39 #include <map>
40 
41 namespace vkt
42 {
43 namespace TransformFeedback
44 {
45 namespace
46 {
47 using namespace vk;
48 
49 enum
50 {
51 	IMAGE_WIDTH		= 64,
52 	IMAGE_HEIGHT	= IMAGE_WIDTH,
53 };
54 
55 enum QueryReadType
56 {
57 	QUERY_READ_TYPE_GET,
58 	QUERY_READ_TYPE_COPY,
59 
60 	QUERY_READ_TYPE_LAST
61 };
62 
63 enum QueryResetType
64 {
65 	QUERY_RESET_TYPE_QUEUE,
66 	QUERY_RESET_TYPE_HOST,
67 
68 	QUERY_RESET_TYPE_LAST
69 };
70 
71 enum QueryResultType
72 {
73 	QUERY_RESULT_TYPE_32_BIT,
74 	QUERY_RESULT_TYPE_64_BIT,
75 	QUERY_RESULT_TYPE_PGQ_32_XFB_64,
76 	QUERY_RESULT_TYPE_PGQ_64_XFB_32,
77 
78 	QUERY_RESULT_TYPE_LAST
79 };
80 
81 enum ShaderStage
82 {
83 	SHADER_STAGE_VERTEX,
84 	SHADER_STAGE_TESSELLATION_EVALUATION,
85 	SHADER_STAGE_GEOMETRY,
86 
87 	SHADER_STAGE_LAST
88 };
89 
90 enum RasterizationCase
91 {
92 	RAST_CASE_DEFAULT,
93 	RAST_CASE_DISCARD,
94 	RAST_CASE_EMPTY_FRAG,
95 	RAST_CASE_NO_ATTACHMENT,
96 	RAST_CASE_COLOR_WRITE_DISABLE_STATIC,
97 	RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,
98 
99 	RAST_CASE_LAST
100 };
101 
102 enum VertexStream
103 {
104 	VERTEX_STREAM_DEFAULT	= -1,
105 	VERTEX_STREAM_0			= 0,
106 	VERTEX_STREAM_1			= 1,
107 };
108 
109 enum CommandBufferCase
110 {
111 	CMD_BUF_CASE_SINGLE_DRAW,
112 
113 	CMD_BUF_CASE_LAST
114 };
115 
116 struct TestParameters
117 {
118 	QueryReadType		queryReadType;
119 	QueryResetType		queryResetType;
120 	QueryResultType		queryResultType;
121 	ShaderStage			shaderStage;
122 	deBool				transformFeedback;
123 	RasterizationCase	rastCase;
124 	deBool				depthStencilAttachment;
125 	VkPrimitiveTopology	primitiveTopology;
126 	VertexStream		pgqStream;
127 	VertexStream		xfbStream;
128 	CommandBufferCase	cmdBufCase;
129 
pgqDefaultvkt::TransformFeedback::__anone8ff03cc0111::TestParameters130 	bool		pgqDefault					(void)	const	{ return pgqStream == VERTEX_STREAM_DEFAULT;						}
xfbDefaultvkt::TransformFeedback::__anone8ff03cc0111::TestParameters131 	bool		xfbDefault					(void)	const	{ return xfbStream == VERTEX_STREAM_DEFAULT;						}
pgqStreamIndexvkt::TransformFeedback::__anone8ff03cc0111::TestParameters132 	deUint32	pgqStreamIndex				(void)	const	{ return pgqDefault() ? 0 : static_cast<deUint32>(pgqStream);		}
xfbStreamIndexvkt::TransformFeedback::__anone8ff03cc0111::TestParameters133 	deUint32	xfbStreamIndex				(void)	const	{ return xfbDefault() ? 0 : static_cast<deUint32>(xfbStream);		}
multipleStreamsvkt::TransformFeedback::__anone8ff03cc0111::TestParameters134 	bool		multipleStreams				(void)	const	{ return pgqStreamIndex() != xfbStreamIndex();						}
nonZeroStreamsvkt::TransformFeedback::__anone8ff03cc0111::TestParameters135 	bool		nonZeroStreams				(void)	const	{ return (pgqStreamIndex() != 0) || (xfbStreamIndex() != 0);		}
rastDiscardvkt::TransformFeedback::__anone8ff03cc0111::TestParameters136 	bool		rastDiscard					(void)	const	{ return rastCase == RAST_CASE_DISCARD;								}
colorAttachmentvkt::TransformFeedback::__anone8ff03cc0111::TestParameters137 	bool		colorAttachment				(void)	const	{ return !rastDiscard() && rastCase != RAST_CASE_NO_ATTACHMENT;		}
staticColorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters138 	bool		staticColorWriteDisable		(void)	const	{ return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_STATIC;			}
dynamicColorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters139 	bool		dynamicColorWriteDisable	(void)	const	{ return rastCase == RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC;			}
colorWriteDisablevkt::TransformFeedback::__anone8ff03cc0111::TestParameters140 	bool		colorWriteDisable			(void)	const	{ return staticColorWriteDisable() || dynamicColorWriteDisable();	}
141 };
142 
143 struct TopologyInfo
144 {
145 	deUint32							primitiveSize;		// Size of the primitive.
146 	deBool								hasAdjacency;		// True if topology has adjacency.
147 	const char*							inputString;		// Layout qualifier identifier for geometry shader input.
148 	const char*							outputString;		// Layout qualifier identifier for geometry shader output.
149 	std::function<deUint64(deUint64)>	getNumPrimitives;	// Number of primitives generated.
150 	std::function<deUint64(deUint64)>	getNumVertices;		// Number of vertices generated.
151 };
152 
153 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
154 {
__anone8ff03cc0302() 155 	{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,						{ 1, DE_FALSE,	"points",				"points",			[](deUint64 vtxCount) { return vtxCount;				}, [](deUint64 primCount) {	return primCount;			} } },
__anone8ff03cc0502() 156 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						{ 2, DE_FALSE,	"lines",				"line_strip",		[](deUint64 vtxCount) { return vtxCount / 2u;			}, [](deUint64 primCount) {	return primCount * 2u;		} } },
__anone8ff03cc0802() 157 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						{ 2, DE_FALSE,	"lines",				"line_strip",		[](deUint64 vtxCount) { return vtxCount - 1u;			}, [](deUint64 primCount) {	return primCount + 1u;		} } },
__anone8ff03cc0a02() 158 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount / 3u;			}, [](deUint64 primCount) {	return primCount * 3u;		} } },
__anone8ff03cc0c02() 159 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount - 2u;			}, [](deUint64 primCount) {	return primCount + 2u;		} } },
__anone8ff03cc0e02() 160 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,					{ 3, DE_FALSE,	"triangles",			"triangle_strip",	[](deUint64 vtxCount) { return vtxCount - 2u;			}, [](deUint64 primCount) {	return primCount + 2u;		} } },
__anone8ff03cc1002() 161 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,		{ 2, DE_TRUE,	"lines_adjacency",		"line_strip",		[](deUint64 vtxCount) { return vtxCount / 4u;			}, [](deUint64 primCount) {	return primCount * 4u;		} } },
__anone8ff03cc1102() 162 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		{ 2, DE_TRUE,	"lines_adjacency",		"line_strip",		[](deUint64 vtxCount) { return vtxCount - 3u;			}, [](deUint64 primCount) {	return primCount + 3u;		} } },
__anone8ff03cc1402() 163 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,	{ 3, DE_TRUE,	"triangles_adjacency",	"triangle_strip",	[](deUint64 vtxCount) { return vtxCount / 6u;			}, [](deUint64 primCount) {	return primCount * 6u;		} } },
__anone8ff03cc1602() 164 	{ 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;	} } },
__anone8ff03cc1802() 165 	{ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,						{ 3, DE_FALSE,	"ERROR",				"ERROR",			[](deUint64 vtxCount) { return vtxCount / 3u;			}, [](deUint64 primCount) {	return primCount * 3u;		} } },
166 };
167 
168 class PrimitivesGeneratedQueryTestInstance : public vkt::TestInstance
169 {
170 public:
PrimitivesGeneratedQueryTestInstance(vkt::Context & context,const TestParameters & parameters)171 							PrimitivesGeneratedQueryTestInstance	(vkt::Context &context, const TestParameters& parameters)
172 								: vkt::TestInstance	(context)
173 								, m_parameters		(parameters)
174 							{
175 							}
176 
177 private:
178 	tcu::TestStatus			iterate									(void);
179 	VkFormat				selectDepthStencilFormat				(void);
180 	Move<VkPipeline>		makeGraphicsPipeline					(const DeviceInterface&	vk,
181 																	 const VkDevice device,
182 																	 const VkRenderPass renderPass);
183 	void					fillVertexBuffer						(tcu::Vec2* vertices,
184 																	 const deUint64 primitivesGenerated);
185 	const TestParameters	m_parameters;
186 };
187 
iterate(void)188 tcu::TestStatus PrimitivesGeneratedQueryTestInstance::iterate (void)
189 {
190 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
191 	const VkDevice					device				= m_context.getDevice();
192 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
193 	const VkQueue					queue				= m_context.getUniversalQueue();
194 	Allocator&						allocator			= m_context.getDefaultAllocator();
195 
196 	const VkFormat					colorFormat			= m_parameters.colorAttachment() ? VK_FORMAT_R8G8B8A8_UNORM : VK_FORMAT_UNDEFINED;
197 	Move<VkImage>					colorImage;
198 	de::MovePtr<Allocation>			colorImageAllocation;
199 
200 	if (m_parameters.colorAttachment())
201 	{
202 		const VkImageCreateInfo colorImageCreateInfo =
203 		{
204 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,		// VkStructureType			sType
205 			DE_NULL,									// const void*				pNext
206 			0u,											// VkImageCreateFlags		flags
207 			VK_IMAGE_TYPE_2D,							// VkImageType				imageType
208 			colorFormat,								// VkFormat					format
209 			makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),	// VkExtent3D				extent
210 			1u,											// deUint32					mipLevels
211 			1u,											// deUint32					arrayLayers
212 			VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits	samples
213 			VK_IMAGE_TILING_OPTIMAL,					// VkImageTiling			tiling
214 			VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT,		// VkImageUsageFlags		usage
215 			VK_SHARING_MODE_EXCLUSIVE,					// VkSharingMode			sharingMode
216 			0u,											// deUint32					queueFamilyIndexCount
217 			DE_NULL,									// const deUint32*			pQueueFamilyIndices
218 			VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout			initialLayout
219 		};
220 
221 		colorImage				= makeImage(vk, device, colorImageCreateInfo);
222 		colorImageAllocation	= bindImage(vk, device, allocator, *colorImage, MemoryRequirement::Any);
223 	}
224 
225 	const VkFormat					dsFormat			= m_parameters.depthStencilAttachment ? PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat() : VK_FORMAT_UNDEFINED;
226 
227 	if (m_parameters.depthStencilAttachment && dsFormat == VK_FORMAT_UNDEFINED)
228 		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.");
229 
230 	Move<VkImage>					dsImage;
231 	de::MovePtr<Allocation>			dsImageAllocation;
232 
233 	if (m_parameters.depthStencilAttachment)
234 	{
235 		const VkImageCreateInfo dsImageCreateInfo =
236 		{
237 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType
238 			DE_NULL,										// const void*				pNext
239 			0u,												// VkImageCreateFlags		flags
240 			VK_IMAGE_TYPE_2D,								// VkImageType				imageType
241 			dsFormat,										// VkFormat					format
242 			makeExtent3D(IMAGE_WIDTH, IMAGE_HEIGHT, 1),		// VkExtent3D				extent
243 			1u,												// deUint32					mipLevels
244 			1u,												// deUint32					arrayLayers
245 			VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples
246 			VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling
247 			VK_IMAGE_USAGE_DEPTH_STENCIL_ATTACHMENT_BIT,	// VkImageUsageFlags		usage
248 			VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode
249 			0u,												// deUint32					queueFamilyIndexCount
250 			DE_NULL,										// const deUint32*			pQueueFamilyIndices
251 			VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout
252 		};
253 
254 		dsImage				= makeImage(vk, device, dsImageCreateInfo);
255 		dsImageAllocation	= bindImage(vk, device, allocator, *dsImage, MemoryRequirement::Any);
256 	}
257 
258 	const VkDeviceSize				primitivesGenerated = 32;
259 	const deUint32					baseMipLevel		= 0;
260 	const deUint32					levelCount			= 1;
261 	const deUint32					baseArrayLayer		= 0;
262 	const deUint32					layerCount			= 1;
263 
264 	Move<VkImageView>				colorImageView;
265 	Move<VkImageView>				dsImageView;
266 	std::vector<VkImageView>		imageViews;
267 
268 	if (m_parameters.colorAttachment())
269 	{
270 		const VkImageSubresourceRange colorSubresourceRange = makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, baseMipLevel, levelCount, baseArrayLayer, layerCount);
271 		colorImageView = makeImageView(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresourceRange);
272 		imageViews.push_back(*colorImageView);
273 	}
274 
275 	if (m_parameters.depthStencilAttachment)
276 	{
277 		const VkImageSubresourceRange dsSubresourceRange = makeImageSubresourceRange((VK_IMAGE_ASPECT_DEPTH_BIT | vk::VK_IMAGE_ASPECT_STENCIL_BIT), baseMipLevel, levelCount, baseArrayLayer, layerCount);
278 		dsImageView = makeImageView(vk, device, *dsImage, VK_IMAGE_VIEW_TYPE_2D, dsFormat, dsSubresourceRange);
279 		imageViews.push_back(*dsImageView);
280 	}
281 
282 	const Unique<VkRenderPass>		renderPass			(makeRenderPass(vk, device, colorFormat, dsFormat, VK_ATTACHMENT_LOAD_OP_DONT_CARE));
283 	const Unique<VkFramebuffer>		framebuffer			(makeFramebuffer(vk, device, *renderPass, (deUint32)imageViews.size(), imageViews.data(), IMAGE_WIDTH, IMAGE_HEIGHT));
284 	const Unique<VkPipeline>		pipeline			(PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline(vk, device, *renderPass));
285 	Move<VkBuffer>					vtxBuffer;
286 	de::MovePtr<Allocation>			vtxBufferAlloc;
287 
288 	{
289 		const VkBufferUsageFlags		usage				= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT;
290 		const std::vector<deUint32>		queueFamilyIndices	(1, queueFamilyIndex);
291 		const VkDeviceSize				vtxBufferSize		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated) * sizeof(tcu::Vec2);
292 		const VkBufferCreateInfo		createInfo			= makeBufferCreateInfo(vtxBufferSize, usage, queueFamilyIndices);
293 
294 		vtxBuffer			= createBuffer(vk, device, &createInfo);
295 		vtxBufferAlloc		= allocator.allocate(getBufferMemoryRequirements(vk, device, *vtxBuffer), MemoryRequirement::HostVisible);
296 	}
297 
298 	const VkCommandPoolCreateFlags	cmdPoolCreateFlags	= VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT;
299 	const VkCommandBufferLevel		cmdBufferLevel		= VK_COMMAND_BUFFER_LEVEL_PRIMARY;
300 	const Unique<VkCommandPool>		cmdPool				(createCommandPool(vk, device, cmdPoolCreateFlags, queueFamilyIndex));
301 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer(vk, device, *cmdPool, cmdBufferLevel));
302 
303 	const bool						pgq64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
304 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_64_XFB_32);
305 	const bool						xfb64				= (m_parameters.queryResultType == QUERY_RESULT_TYPE_64_BIT ||
306 														   m_parameters.queryResultType == QUERY_RESULT_TYPE_PGQ_32_XFB_64);
307 	const size_t					pgqResultSize		= pgq64 ? sizeof(deUint64) : sizeof(deUint32);
308 	const size_t					xfbResultSize		= xfb64 ? sizeof(deUint64) * 2 : sizeof(deUint32) * 2;
309 	const VkQueryResultFlags		pgqResultWidthBit	= pgq64 ? VK_QUERY_RESULT_64_BIT : 0;
310 	const VkQueryResultFlags		xfbResultWidthBit	= xfb64 ? VK_QUERY_RESULT_64_BIT : 0;
311 	const VkQueryResultFlags		pgqResultFlags		= VK_QUERY_RESULT_WAIT_BIT | pgqResultWidthBit;
312 	const VkQueryResultFlags		xfbResultFlags		= VK_QUERY_RESULT_WAIT_BIT | xfbResultWidthBit;
313 
314 	const deUint32					queryIndex			= 0;
315 	const deUint32					queryCount			= 1;
316 
317 	std::vector<deUint8>			pgqResults			(pgqResultSize, 255u);
318 	std::vector<deUint8>			xfbResults			(xfbResultSize, 255u);
319 
320 	const VkQueryPoolCreateInfo		pgqCreateInfo		=
321 	{
322 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,	// VkStructureType					sType
323 		DE_NULL,									// const void*						pNext
324 		0u,											// VkQueryPoolCreateFlags			flags
325 		VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT,		// VkQueryType						queryType
326 		queryCount,									// deUint32							queryCount
327 		0u,											// VkQueryPipelineStatisticFlags	pipelineStatistics
328 	};
329 
330 	const Unique<VkQueryPool>		pgqPool				(createQueryPool(vk, device, &pgqCreateInfo));
331 	Move<VkQueryPool>				xfbPool;
332 
333 	if (m_parameters.transformFeedback)
334 	{
335 		const VkQueryPoolCreateInfo xfbCreateInfo =
336 		{
337 			VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		// VkStructureType					sType
338 			DE_NULL,										// const void*						pNext
339 			0u,												// VkQueryPoolCreateFlags			flags
340 			VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,	// VkQueryType						queryType
341 			queryCount,										// deUint32							queryCount
342 			0u,												// VkQueryPipelineStatisticFlags	pipelineStatistics
343 		};
344 
345 		xfbPool = createQueryPool(vk, device, &xfbCreateInfo);
346 	}
347 
348 	Move<VkBuffer>					pgqResultsBuffer;
349 	Move<VkBuffer>					xfbResultsBuffer;
350 	de::MovePtr<Allocation>			pgqResultsBufferAlloc;
351 	de::MovePtr<Allocation>			xfbResultsBufferAlloc;
352 
353 	if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
354 	{
355 		const VkBufferUsageFlags	usage				= VK_BUFFER_USAGE_TRANSFER_DST_BIT;
356 		const std::vector<deUint32>	queueFamilyIndices	(1, queueFamilyIndex);
357 		const VkBufferCreateInfo	pgqBufferCreateInfo	= makeBufferCreateInfo(pgqResultSize, usage, queueFamilyIndices);
358 
359 		pgqResultsBuffer		= createBuffer(vk, device, &pgqBufferCreateInfo);
360 		pgqResultsBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *pgqResultsBuffer), MemoryRequirement::HostVisible);
361 
362 		VK_CHECK(vk.bindBufferMemory(device, *pgqResultsBuffer, pgqResultsBufferAlloc->getMemory(), pgqResultsBufferAlloc->getOffset()));
363 
364 		if (m_parameters.transformFeedback)
365 		{
366 			const VkBufferCreateInfo xfbBufferCreateInfo = makeBufferCreateInfo(xfbResultSize, usage, queueFamilyIndices);
367 
368 			xfbResultsBuffer		= createBuffer(vk, device, &xfbBufferCreateInfo);
369 			xfbResultsBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbResultsBuffer), MemoryRequirement::HostVisible);
370 
371 			VK_CHECK(vk.bindBufferMemory(device, *xfbResultsBuffer, xfbResultsBufferAlloc->getMemory(), xfbResultsBufferAlloc->getOffset()));
372 		}
373 	}
374 
375 	const VkDeviceSize				primitivesWritten	= primitivesGenerated - 3;
376 	const VkDeviceSize				verticesWritten		= topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesWritten);
377 	const VkDeviceSize				primitiveSize		= m_parameters.nonZeroStreams() ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
378 	const VkDeviceSize				bytesPerVertex		= 4 * sizeof(float);
379 	const VkDeviceSize				xfbBufferSize		= primitivesWritten * primitiveSize * bytesPerVertex;
380 	Move<VkBuffer>					xfbBuffer;
381 	de::MovePtr<Allocation>			xfbBufferAlloc;
382 
383 	if (m_parameters.transformFeedback)
384 	{
385 		const VkBufferUsageFlags	usage				= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
386 		const std::vector<deUint32>	queueFamilyIndices	(1, queueFamilyIndex);
387 		const VkBufferCreateInfo	createInfo			= makeBufferCreateInfo(xfbBufferSize, usage, queueFamilyIndices);
388 
389 		xfbBuffer		= createBuffer(vk, device, &createInfo);
390 		xfbBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
391 
392 		VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferAlloc->getMemory(), xfbBufferAlloc->getOffset()));
393 	}
394 
395 	fillVertexBuffer(static_cast<tcu::Vec2*>(vtxBufferAlloc.get()->getHostPtr()), primitivesGenerated);
396 
397 	VK_CHECK(vk.bindBufferMemory(device, *vtxBuffer, vtxBufferAlloc->getMemory(), vtxBufferAlloc->getOffset()));
398 
399 	beginCommandBuffer(vk, *cmdBuffer);
400 	{
401 		const VkDeviceSize	vertexBufferOffset	= static_cast<VkDeviceSize>(0);
402 
403 		// After query pool creation, each query must be reset before it is used.
404 		if (m_parameters.queryResetType == QUERY_RESET_TYPE_QUEUE)
405 		{
406 			vk.cmdResetQueryPool(*cmdBuffer, *pgqPool, queryIndex, queryCount);
407 
408 			if (m_parameters.transformFeedback)
409 				vk.cmdResetQueryPool(*cmdBuffer, *xfbPool, queryIndex, queryCount);
410 		}
411 
412 		vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
413 
414 		vk.cmdBindVertexBuffers(*cmdBuffer, 0, 1, &vtxBuffer.get(), &vertexBufferOffset);
415 
416 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
417 		{
418 			const VkQueryControlFlags	queryControlFlags		= 0;
419 
420 			if (m_parameters.pgqDefault())
421 				vk.cmdBeginQuery(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags);
422 			else
423 				vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, queryControlFlags, m_parameters.pgqStreamIndex());
424 
425 			const deUint32				firstCounterBuffer		= 0;
426 			const deUint32				counterBufferCount		= 0;
427 			const VkBuffer*				counterBuffers			= DE_NULL;
428 			const VkDeviceSize*			counterBufferOffsets	= DE_NULL;
429 
430 			if (m_parameters.transformFeedback)
431 			{
432 				const deUint32		firstBinding	= 0;
433 				const deUint32		bindingCount	= 1;
434 				const VkDeviceSize	offset			= 0;
435 
436 				vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, firstBinding, bindingCount, &*xfbBuffer, &offset, &xfbBufferSize);
437 
438 				if (m_parameters.xfbDefault())
439 					vk.cmdBeginQuery(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags);
440 				else
441 					vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, queryControlFlags, m_parameters.xfbStreamIndex());
442 
443 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
444 			}
445 
446 			if (m_parameters.dynamicColorWriteDisable())
447 			{
448 				const deUint32	attachmentCount		= 1;
449 				const VkBool32	colorWriteEnables	= VK_FALSE;
450 
451 				vk.cmdSetColorWriteEnableEXT(*cmdBuffer, attachmentCount, &colorWriteEnables);
452 			}
453 
454 			const deUint32				vertexCount				= static_cast<deUint32>(topologyData.at(m_parameters.primitiveTopology).getNumVertices(primitivesGenerated));
455 			const deUint32				instanceCount			= 1u;
456 			const deUint32				firstVertex				= 0u;
457 			const deUint32				firstInstance			= 0u;
458 
459 			vk.cmdDraw(*cmdBuffer, vertexCount, instanceCount, firstVertex, firstInstance);
460 
461 			if (m_parameters.pgqDefault())
462 				vk.cmdEndQuery(*cmdBuffer, *pgqPool, queryIndex);
463 			else
464 				vk.cmdEndQueryIndexedEXT(*cmdBuffer, *pgqPool, queryIndex, m_parameters.pgqStreamIndex());
465 
466 			if (m_parameters.transformFeedback)
467 			{
468 				if (m_parameters.xfbDefault())
469 					vk.cmdEndQuery(*cmdBuffer, *xfbPool, queryIndex);
470 				else
471 					vk.cmdEndQueryIndexedEXT(*cmdBuffer, *xfbPool, queryIndex, m_parameters.xfbStreamIndex());
472 
473 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, firstCounterBuffer, counterBufferCount, counterBuffers, counterBufferOffsets);
474 			}
475 		}
476 		endRenderPass(vk, *cmdBuffer);
477 
478 		if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
479 		{
480 			VkBufferMemoryBarrier bufferBarrier =
481 			{
482 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType
483 				DE_NULL,									// const void*		pNext
484 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask
485 				VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask
486 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex
487 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex
488 				*pgqResultsBuffer,							// VkBuffer			buffer
489 				0u,											// VkDeviceSize		offset
490 				VK_WHOLE_SIZE								// VkDeviceSize		size
491 			};
492 
493 			vk.cmdCopyQueryPoolResults(*cmdBuffer, *pgqPool, queryIndex, queryCount, *pgqResultsBuffer, 0u, pgqResultSize, pgqResultFlags);
494 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
495 
496 			if (m_parameters.transformFeedback)
497 			{
498 				bufferBarrier.buffer = *xfbResultsBuffer;
499 				vk.cmdCopyQueryPoolResults(*cmdBuffer, *xfbPool, queryIndex, queryCount, *xfbResultsBuffer, 0u, xfbResultSize, xfbResultFlags);
500 				vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
501 			}
502 		}
503 	}
504 	endCommandBuffer(vk, *cmdBuffer);
505 
506 	// After query pool creation, each query must be reset before it is used.
507 	if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
508 	{
509 		vk.resetQueryPool(device, *pgqPool, queryIndex, queryCount);
510 
511 		if (m_parameters.transformFeedback)
512 			vk.resetQueryPool(device, *xfbPool, queryIndex, queryCount);
513 	}
514 
515 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
516 
517 	if (m_parameters.queryReadType == QUERY_READ_TYPE_COPY)
518 	{
519 		invalidateAlloc(vk, device, *pgqResultsBufferAlloc);
520 		deMemcpy(pgqResults.data(), pgqResultsBufferAlloc->getHostPtr(), pgqResults.size());
521 
522 		if (m_parameters.transformFeedback)
523 		{
524 			invalidateAlloc(vk, device, *xfbResultsBufferAlloc);
525 			deMemcpy(xfbResults.data(), xfbResultsBufferAlloc->getHostPtr(), xfbResults.size());
526 		}
527 	}
528 	else
529 	{
530 		vk.getQueryPoolResults(device, *pgqPool, queryIndex, queryCount, pgqResults.size(), pgqResults.data(), pgqResults.size(), pgqResultFlags);
531 
532 		if (m_parameters.transformFeedback)
533 			vk.getQueryPoolResults(device, *xfbPool, queryIndex, queryCount, xfbResults.size(), xfbResults.data(), xfbResults.size(), xfbResultFlags);
534 	}
535 
536 	// Validate counters.
537 	{
538 		union QueryResults
539 		{
540 			deUint32	elements32[2];
541 			deUint64	elements64[2];
542 		};
543 
544 		const QueryResults*	pgqCounters		= reinterpret_cast<QueryResults*>(pgqResults.data());
545 		const QueryResults*	xfbCounters		= reinterpret_cast<QueryResults*>(xfbResults.data());
546 		const deUint64		pgqGenerated	= pgq64 ? pgqCounters->elements64[0] : static_cast<deUint64>(pgqCounters->elements32[0]);
547 		const deUint64		xfbWritten		= xfb64 ? xfbCounters->elements64[0] : static_cast<deUint64>(xfbCounters->elements32[0]);
548 		const deUint64		xfbGenerated	= xfb64 ? xfbCounters->elements64[1] : static_cast<deUint64>(xfbCounters->elements32[1]);
549 		tcu::TestLog&		log				= m_context.getTestContext().getLog();
550 
551 		log	<<	tcu::TestLog::Message
552 			<<	"primitivesGenerated: " << primitivesGenerated << "\n"
553 			<<	"primitivesWritten: " << primitivesWritten << "\n"
554 			<<	"verticesWritten: " << verticesWritten << "\n"
555 			<<	"xfbBufferSize: " << xfbBufferSize << "\n"
556 			<<	tcu::TestLog::EndMessage;
557 
558 		log << tcu::TestLog::Message << "PGQ: Generated " << pgqGenerated << tcu::TestLog::EndMessage;
559 
560 		if (m_parameters.transformFeedback)
561 			log << tcu::TestLog::Message << "XFB: Written " << xfbWritten << ", generated " << xfbGenerated << tcu::TestLog::EndMessage;
562 
563 		if (pgqGenerated != primitivesGenerated)
564 		{
565 			const std::string message = std::string("pgqGenerated == ") + de::toString(pgqGenerated) + ", expected " + de::toString(primitivesGenerated);
566 			return tcu::TestStatus::fail(message);
567 		}
568 
569 		if (m_parameters.transformFeedback)
570 		{
571 			if (xfbGenerated != primitivesGenerated)
572 			{
573 				const std::string message = std::string("xfbGenerated == ") + de::toString(xfbGenerated) + ", expected " + de::toString(primitivesGenerated);
574 				return tcu::TestStatus::fail(message);
575 			}
576 
577 			if (xfbWritten != primitivesWritten)
578 			{
579 				const std::string message = std::string("xfbWritten == ") + de::toString(xfbWritten) + ", expected " + de::toString(primitivesWritten);
580 				return tcu::TestStatus::fail(message);
581 			}
582 		}
583 	}
584 
585 	return tcu::TestStatus::pass("Counters OK");
586 }
587 
selectDepthStencilFormat(void)588 VkFormat PrimitivesGeneratedQueryTestInstance::selectDepthStencilFormat (void)
589 {
590 	constexpr VkFormat			formats[]		=
591 	{
592 		VK_FORMAT_D32_SFLOAT_S8_UINT,
593 		VK_FORMAT_D24_UNORM_S8_UINT
594 	};
595 
596 	const InstanceInterface&	vki				= m_context.getInstanceInterface();
597 	const VkPhysicalDevice		physicalDevice	= m_context.getPhysicalDevice();
598 
599 	for (VkFormat format : formats)
600 	{
601 		const VkFormatFeatureFlags features = getPhysicalDeviceFormatProperties(vki, physicalDevice, format).optimalTilingFeatures;
602 
603 		if (features & VK_FORMAT_FEATURE_DEPTH_STENCIL_ATTACHMENT_BIT)
604 			return format;
605 	}
606 
607 	return VK_FORMAT_UNDEFINED;
608 }
609 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkRenderPass renderPass)610 Move<VkPipeline> PrimitivesGeneratedQueryTestInstance::makeGraphicsPipeline (const DeviceInterface&	vk, const VkDevice device, const VkRenderPass renderPass)
611 {
612 	const VkDescriptorSetLayout						descriptorSetLayout				= DE_NULL;
613 	const Unique<VkPipelineLayout>					pipelineLayout					(makePipelineLayout(vk, device, descriptorSetLayout));
614 	const std::vector<VkViewport>					viewports						(1, makeViewport(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
615 	const std::vector<VkRect2D>						scissors						(1, makeRect2D(makeExtent2D(IMAGE_WIDTH, IMAGE_HEIGHT)));
616 	const deUint32									subpass							= 0u;
617 	const deUint32									patchControlPoints				= topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize;
618 	const Unique<VkShaderModule>					vertModule						(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
619 	Move<VkShaderModule>							tescModule;
620 	Move<VkShaderModule>							teseModule;
621 	Move<VkShaderModule>							geomModule;
622 	Move<VkShaderModule>							fragModule;
623 	VkVertexInputBindingDescription					bindingDescription;
624 	VkVertexInputAttributeDescription				attributeDescription;
625 
626 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
627 	{
628 		tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
629 		teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
630 	}
631 
632 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
633 		geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
634 
635 	if (!m_parameters.rastDiscard())
636 		fragModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0u);
637 
638 	bindingDescription.binding		= 0;
639 	bindingDescription.stride		= sizeof(tcu::Vec2);
640 	bindingDescription.inputRate	= VK_VERTEX_INPUT_RATE_VERTEX;
641 
642 	attributeDescription.binding	= 0;
643 	attributeDescription.location	= 0;
644 	attributeDescription.format		= VK_FORMAT_R32G32_SFLOAT;
645 	attributeDescription.offset		= 0;
646 
647 	const VkPipelineVertexInputStateCreateInfo		vertexInputStateCreateInfo		=
648 	{
649 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// VkStructureType							sType
650 		DE_NULL,													// const void*								pNext
651 		0u,															// VkPipelineVertexInputStateCreateFlags	flags
652 		1u,															// deUint32									vertexBindingDescriptionCount
653 		&bindingDescription,										// const VkVertexInputBindingDescription*	pVertexBindingDescriptions
654 		1u,															// deUint32									vertexAttributeDescriptionCount
655 		&attributeDescription,										// const VkVertexInputAttributeDescription*	pVertexAttributeDescriptions
656 	};
657 
658 	const VkPipelineRasterizationStateCreateInfo	rasterizationStateCreateInfo	=
659 	{
660 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// VkStructureType							sType
661 		DE_NULL,													// const void*								pNext
662 		0,															// VkPipelineRasterizationStateCreateFlags	flags
663 		VK_FALSE,													// VkBool32									depthClampEnable
664 		(m_parameters.rastDiscard() ? VK_TRUE : VK_FALSE),			// VkBool32									rasterizerDiscardEnable
665 		VK_POLYGON_MODE_FILL,										// VkPolygonMode							polygonMode
666 		VK_CULL_MODE_NONE,											// VkCullModeFlags							cullMode
667 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							// VkFrontFace								frontFace
668 		VK_FALSE,													// VkBool32									depthBiasEnable
669 		0.0f,														// float									depthBiasConstantFactor
670 		0.0f,														// float									depthBiasClamp
671 		0.0f,														// float									depthBiasSlopeFactor
672 		1.0f														// float									lineWidth
673 	};
674 
675 	const VkStencilOpState							stencilOpState					=
676 	{
677 		VK_STENCIL_OP_KEEP,		// VkStencilOp	failOp
678 		VK_STENCIL_OP_KEEP,		// VkStencilOp	passOp
679 		VK_STENCIL_OP_KEEP,		// VkStencilOp	depthFailOp
680 		VK_COMPARE_OP_ALWAYS,	// VkCompareOp	compareOp
681 		0xFFu,					// deUint32		compareMask
682 		0xFFu,					// deUint32		writeMask
683 		0,						// deUint32		reference
684 	};
685 
686 	const VkPipelineDepthStencilStateCreateInfo		depthStencilStateCreateInfo		=
687 	{
688 		VK_STRUCTURE_TYPE_PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,	//	VkStructureType							sType
689 		DE_NULL,													//	const void*								pNext
690 		0,															//	VkPipelineDepthStencilStateCreateFlags	flags
691 		VK_TRUE,													//	VkBool32								depthTestEnable
692 		VK_TRUE,													//	VkBool32								depthWriteEnable
693 		VK_COMPARE_OP_LESS,											//	VkCompareOp								depthCompareOp
694 		VK_FALSE,													//	VkBool32								depthBoundsTestEnable
695 		VK_FALSE,													//	VkBool32								stencilTestEnable
696 		stencilOpState,												//	VkStencilOpState						front
697 		stencilOpState,												//	VkStencilOpState						back
698 		0.0f,														//	float									minDepthBounds
699 		1.0f,														//	float									maxDepthBounds
700 	};
701 
702 	const VkBool32									colorWriteEnables				= VK_FALSE;
703 
704 	const VkPipelineColorWriteCreateInfoEXT			colorWriteCreateInfo			=
705 	{
706 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_WRITE_CREATE_INFO_EXT,	// VkStructureType	sType;
707 		DE_NULL,												// const void*		pNext;
708 		1,														// deUint32			attachmentCount;
709 		&colorWriteEnables										// const VkBool32*	pColorWriteEnables;
710 	};
711 
712 	const VkPipelineColorBlendAttachmentState		colorBlendAttachmentState		=
713 	{
714 		VK_FALSE,					// VkBool32					blendEnable
715 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcColorBlendFactor
716 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstColorBlendFactor
717 		VK_BLEND_OP_ADD,			// VkBlendOp				colorBlendOp
718 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			srcAlphaBlendFactor
719 		VK_BLEND_FACTOR_ZERO,		// VkBlendFactor			dstAlphaBlendFactor
720 		VK_BLEND_OP_ADD,			// VkBlendOp				alphaBlendOp
721 		VK_COLOR_COMPONENT_R_BIT	// VkColorComponentFlags	colorWriteMask
722 		| VK_COLOR_COMPONENT_G_BIT
723 		| VK_COLOR_COMPONENT_B_BIT
724 		| VK_COLOR_COMPONENT_A_BIT
725 	};
726 
727 	const VkPipelineColorBlendStateCreateInfo		colorBlendStateCreateInfo		=
728 	{
729 		VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,	// VkStructureType								sType
730 		&colorWriteCreateInfo,										// const void*									pNext
731 		0,															// VkPipelineColorBlendStateCreateFlags			flags
732 		VK_FALSE,													// VkBool32										logicOpEnable
733 		VK_LOGIC_OP_NO_OP,											// VkLogicOp									logicOp
734 		1,															// deUint32										attachmentCount
735 		&colorBlendAttachmentState,									// const VkPipelineColorBlendAttachmentState*	pAttachments
736 		{ 0.0f, 0.0f, 0.0f, 0.0f }									// float										blendConstants[4]
737 	};
738 
739 	const VkDynamicState							dynamicStates					= VK_DYNAMIC_STATE_COLOR_WRITE_ENABLE_EXT;
740 
741 	const VkPipelineDynamicStateCreateInfo			pipelineDynamicStateCreateInfo	=
742 	{
743 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	// VkStructureType						sType
744 		DE_NULL,												// const void*							pNext
745 		0u,														// VkPipelineDynamicStateCreateFlags	flags
746 		1u,														// deUint32								dynamicStateCount
747 		&dynamicStates											// const VkDynamicState*				pDynamicStates
748 	};
749 
750 	const VkPipelineMultisampleStateCreateInfo		multisampleStateCreateInfo		=
751 	{
752 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,	//	VkStructureType							sType;
753 		nullptr,													//	const void*								pNext;
754 		0u,															//	VkPipelineMultisampleStateCreateFlags	flags;
755 		VK_SAMPLE_COUNT_1_BIT,										//	VkSampleCountFlagBits					rasterizationSamples;
756 		VK_FALSE,													//	VkBool32								sampleShadingEnable;
757 		1.0f,														//	float									minSampleShading;
758 		nullptr,													//	const VkSampleMask*						pSampleMask;
759 		VK_FALSE,													//	VkBool32								alphaToCoverageEnable;
760 		VK_FALSE,													//	VkBool32								alphaToOneEnable;
761 	};
762 
763 	return vk::makeGraphicsPipeline(vk,
764 									device,
765 									*pipelineLayout,
766 									*vertModule,
767 									*tescModule,
768 									*teseModule,
769 									*geomModule,
770 									*fragModule,
771 									renderPass,
772 									viewports,
773 									scissors,
774 									m_parameters.primitiveTopology,
775 									subpass,
776 									patchControlPoints,
777 									&vertexInputStateCreateInfo,
778 									&rasterizationStateCreateInfo,
779 									&multisampleStateCreateInfo,
780 									m_parameters.depthStencilAttachment ? &depthStencilStateCreateInfo : DE_NULL,
781 									m_parameters.staticColorWriteDisable() ? &colorBlendStateCreateInfo : DE_NULL,
782 									m_parameters.dynamicColorWriteDisable() ? &pipelineDynamicStateCreateInfo : DE_NULL);
783 }
784 
fillVertexBuffer(tcu::Vec2 * vertices,const deUint64 primitivesGenerated)785 void PrimitivesGeneratedQueryTestInstance::fillVertexBuffer(tcu::Vec2* vertices, const deUint64 primitivesGenerated)
786 {
787 	const float step = 1.0f / static_cast<float>(primitivesGenerated);
788 
789 	switch (m_parameters.primitiveTopology)
790 	{
791 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
792 		{
793 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
794 			{
795 				vertices[prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 0.0f);
796 			}
797 			break;
798 		}
799 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
800 		{
801 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
802 			{
803 				vertices[2* prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
804 				vertices[2* prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
805 			}
806 			break;
807 		}
808 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
809 		{
810 			vertices[0] = tcu::Vec2(-1.0f,-1.0f);
811 			vertices[1] = tcu::Vec2(-1.0f, 1.0f);
812 
813 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
814 			{
815 				if (prim % 2 == 0)
816 				{
817 					vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
818 				}
819 				else
820 				{
821 					vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
822 				}
823 			}
824 			break;
825 		}
826 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
827 		{
828 			vertices[0] = tcu::Vec2(-1.0f,				 1.0f);
829 			vertices[1] = tcu::Vec2(-1.0f,				-1.0f);
830 			vertices[2] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
831 
832 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
833 			{
834 				if (prim % 2 == 0)
835 				{
836 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
837 				}
838 				else
839 				{
840 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
841 				}
842 			}
843 			break;
844 		}
845 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
846 		{
847 			vertices[0] = tcu::Vec2(0.0f, -1.0f);
848 
849 			for (deUint32 prim = 0; prim < primitivesGenerated+1; ++prim)
850 			{
851 				vertices[1 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f + 2.0f * (float)prim * step);
852 			}
853 			break;
854 		}
855 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
856 		{
857 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
858 			{
859 				vertices[4 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
860 				vertices[4 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  0.5f);
861 				vertices[4 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -0.5f);
862 				vertices[4 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
863 			}
864 			break;
865 		}
866 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
867 		{
868 			vertices[0] = tcu::Vec2(-1.0f,  0.0f);
869 			vertices[1] = tcu::Vec2(-1.0f, -1.0f);
870 			vertices[2] = tcu::Vec2(-1.0f,  1.0f);
871 
872 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
873 			{
874 				if (prim % 2 == 0)
875 				{
876 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step,  1.0f);
877 				}
878 				else
879 				{
880 					vertices[2 + prim] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
881 				}
882 			}
883 
884 			vertices[2 + primitivesGenerated] = tcu::Vec2(1.0f, 0.0f);
885 
886 			break;
887 		}
888 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
889 		case VK_PRIMITIVE_TOPOLOGY_PATCH_LIST:
890 		{
891 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
892 			{
893 				if (prim % 2 == 0)
894 				{
895 					vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
896 					vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
897 					vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
898 				}
899 				else
900 				{
901 					vertices[3 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
902 					vertices[3 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
903 					vertices[3 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
904 				}
905 			}
906 			break;
907 		}
908 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
909 		{
910 			for (deUint32 prim = 0; prim < primitivesGenerated; ++prim)
911 			{
912 				if (prim % 2 == 0)
913 				{
914 					vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
915 					vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
916 					vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
917 					vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step, -1.0f);
918 					vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
919 					vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
920 				}
921 				else
922 				{
923 					vertices[6 * prim + 0] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
924 					vertices[6 * prim + 1] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step, -1.0f);
925 					vertices[6 * prim + 2] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
926 					vertices[6 * prim + 3] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 1) * step,  1.0f);
927 					vertices[6 * prim + 4] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
928 					vertices[6 * prim + 5] = tcu::Vec2(-1.0f + 2.0f * ((float)prim + 0) * step,  1.0f);
929 				}
930 			}
931 			break;
932 		}
933 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
934 		{
935 			vertices[0] = tcu::Vec2(-1.0f,  1.0f);
936 			vertices[1] = tcu::Vec2(-1.0f,  1.0f);
937 			vertices[2] = tcu::Vec2(-1.0f, -1.0f);
938 			vertices[3] = tcu::Vec2(-1.0f, -1.0f);
939 			vertices[4] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
940 			vertices[5] = tcu::Vec2(-1.0f + 2.0f * step, 1.0f);
941 
942 			for (deUint32 prim = 1; prim < primitivesGenerated; ++prim)
943 			{
944 				if (prim % 2 == 0)
945 				{
946 					vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
947 					vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, 1.0f);
948 				}
949 				else
950 				{
951 					vertices[5 + prim + 0] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
952 					vertices[5 + prim + 1] = tcu::Vec2(-1.0f + 2.0f * (float)prim * step, -1.0f);
953 				}
954 			}
955 			break;
956 		}
957 		default:
958 			TCU_THROW(InternalError, "Unrecognized primitive topology");
959 	}
960 }
961 
962 class PrimitivesGeneratedQueryTestCase : public vkt::TestCase
963 {
964 public:
PrimitivesGeneratedQueryTestCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)965 							PrimitivesGeneratedQueryTestCase	(tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
966 								: TestCase		(context, name, description)
967 								, m_parameters	(parameters)
968 							{
969 							}
970 
971 private:
972 	void					checkSupport						(vkt::Context& context) const;
973 	void					initPrograms						(vk::SourceCollections& programCollection) const;
createInstance(vkt::Context & context) const974 	vkt::TestInstance*		createInstance						(vkt::Context& context) const { return new PrimitivesGeneratedQueryTestInstance(context, m_parameters); }
975 
976 	const TestParameters	m_parameters;
977 };
978 
checkSupport(vkt::Context & context) const979 void PrimitivesGeneratedQueryTestCase::checkSupport (vkt::Context& context) const
980 {
981 	context.requireDeviceFunctionality("VK_EXT_primitives_generated_query");
982 	context.requireDeviceFunctionality("VK_EXT_transform_feedback");
983 
984 	const VkPhysicalDevicePrimitivesGeneratedQueryFeaturesEXT&	pgqFeatures		= context.getPrimitivesGeneratedQueryFeaturesEXT();
985 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&			xfbFeatures		= context.getTransformFeedbackFeaturesEXT();
986 	const VkPhysicalDeviceTransformFeedbackPropertiesEXT&		xfbProperties	= context.getTransformFeedbackPropertiesEXT();
987 
988 	if (pgqFeatures.primitivesGeneratedQuery != VK_TRUE)
989 		TCU_THROW(NotSupportedError, "VK_QUERY_TYPE_PRIMITIVES_GENERATED_EXT not supported");
990 
991 	if (m_parameters.rastDiscard() && (pgqFeatures.primitivesGeneratedQueryWithRasterizerDiscard != VK_TRUE))
992 		TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithRasterizerDiscard not supported");
993 
994 	if (m_parameters.queryResetType == QUERY_RESET_TYPE_HOST)
995 		context.requireDeviceFunctionality("VK_EXT_host_query_reset");
996 
997 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY || topologyData.at(m_parameters.primitiveTopology).hasAdjacency)
998 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
999 
1000 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1001 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_TESSELLATION_SHADER);
1002 
1003 	if (m_parameters.nonZeroStreams())
1004 	{
1005 		const deUint32 requiredStreams	= de::max(m_parameters.pgqStreamIndex(), m_parameters.xfbStreamIndex());
1006 
1007 		if (m_parameters.pgqStreamIndex() > 0 && pgqFeatures.primitivesGeneratedQueryWithNonZeroStreams != VK_TRUE)
1008 			TCU_THROW(NotSupportedError, "primitivesGeneratedQueryWithNonZeroStreams not supported");
1009 
1010 		if (xfbProperties.maxTransformFeedbackStreams <= requiredStreams)
1011 			TCU_THROW(NotSupportedError, "Required amount of XFB streams not supported");
1012 	}
1013 
1014 	if (m_parameters.transformFeedback)
1015 	{
1016 		if (xfbFeatures.transformFeedback != VK_TRUE)
1017 			TCU_THROW(NotSupportedError, "transformFeedback not supported");
1018 
1019 		if (xfbProperties.transformFeedbackQueries != VK_TRUE)
1020 			TCU_THROW(NotSupportedError, "transformFeedbackQueries not supported");
1021 	}
1022 
1023 	if (m_parameters.colorWriteDisable())
1024 	{
1025 		context.requireDeviceFunctionality("VK_EXT_color_write_enable");
1026 
1027 		if (context.getColorWriteEnableFeaturesEXT().colorWriteEnable != VK_TRUE)
1028 			TCU_THROW(NotSupportedError, "colorWriteEnable not supported");
1029 	}
1030 }
1031 
initPrograms(vk::SourceCollections & programCollection) const1032 void PrimitivesGeneratedQueryTestCase::initPrograms (vk::SourceCollections& programCollection) const
1033 {
1034 	// Vertex shader.
1035 	{
1036 		const bool			vertXfb	= (m_parameters.transformFeedback && m_parameters.shaderStage == SHADER_STAGE_VERTEX);
1037 		std::ostringstream	src;
1038 
1039 		src	<<	"#version 450\n";
1040 		src << "layout(location=0) in vec2 inPosition;\n";
1041 
1042 		if (vertXfb)
1043 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n";
1044 
1045 		src	<<	"void main (void)\n"
1046 				"{\n";
1047 
1048 		if (m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && m_parameters.shaderStage == SHADER_STAGE_VERTEX)
1049 			src	<<	"    gl_PointSize = 1.0;\n";
1050 
1051 		src << "	 gl_Position = vec4(inPosition, 0, 1);\n";
1052 
1053 		if (vertXfb)
1054 			src	<<	"    out0 = vec4(42);\n";
1055 
1056 		src	<<	"}\n";
1057 
1058 		programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
1059 	}
1060 
1061 	// Tessellation shaders.
1062 	if (m_parameters.shaderStage == SHADER_STAGE_TESSELLATION_EVALUATION)
1063 	{
1064 		std::stringstream	tescSrc;
1065 		std::stringstream	teseSrc;
1066 
1067 		tescSrc	<<	"#version 450\n"
1068 					"#extension GL_EXT_tessellation_shader : require\n"
1069 					"layout(vertices = "<< topologyData.at(VK_PRIMITIVE_TOPOLOGY_PATCH_LIST).primitiveSize << ") out;\n"
1070 					"void main (void)\n"
1071 					"{\n"
1072 					"    gl_TessLevelInner[0] = 1.0;\n"
1073 					"    gl_TessLevelInner[1] = 1.0;\n"
1074 					"    gl_TessLevelOuter[0] = 1.0;\n"
1075 					"    gl_TessLevelOuter[1] = 1.0;\n"
1076 					"    gl_TessLevelOuter[2] = 1.0;\n"
1077 					"    gl_TessLevelOuter[3] = 1.0;\n"
1078 					"    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
1079 					"}\n";
1080 
1081 		teseSrc	<<	"#version 450\n"
1082 					"#extension GL_EXT_tessellation_shader : require\n"
1083 					"layout(triangles) in;\n";
1084 
1085 		if (m_parameters.transformFeedback)
1086 			teseSrc	<<	"layout(xfb_buffer = 0, xfb_offset = 0, location = 0) out vec4 out0;\n";
1087 
1088 		teseSrc	<<	"void main (void)\n"
1089 					"{\n";
1090 
1091 		if (m_parameters.transformFeedback)
1092 			teseSrc	<<	"    out0 = vec4(42);\n";
1093 
1094 		teseSrc	<<	"    vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
1095 					"    vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
1096 					"    vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
1097 					"    gl_Position = p0 + p1 + p2;\n"
1098 					"}\n";
1099 
1100 		programCollection.glslSources.add("tesc") << glu::TessellationControlSource(tescSrc.str());
1101 		programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(teseSrc.str());
1102 	}
1103 
1104 	// Geometry shader.
1105 	if (m_parameters.shaderStage == SHADER_STAGE_GEOMETRY)
1106 	{
1107 		const bool			outputPoints	= m_parameters.nonZeroStreams() || m_parameters.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_POINT_LIST;
1108 		const char* const	inputTopology	= topologyData.at(m_parameters.primitiveTopology).inputString;
1109 		const char* const	outputTopology	= outputPoints ? "points" : topologyData.at(m_parameters.primitiveTopology).outputString;
1110 		const VkDeviceSize	outputPrimSize	= outputPoints ? 1 : topologyData.at(m_parameters.primitiveTopology).primitiveSize;
1111 		const VkDeviceSize	maxVertices		= m_parameters.multipleStreams() ? outputPrimSize * 2 : outputPrimSize;
1112 		const std::string	pgqEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EmitVertex()";
1113 		const std::string	xfbEmitCommand	= m_parameters.nonZeroStreams() ? std::string("EmitStreamVertex(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EmitVertex()";
1114 		const std::string	pgqEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.pgqStreamIndex()) + ")" : "EndPrimitive()";
1115 		const std::string	xfbEndCommand	= m_parameters.nonZeroStreams() ? std::string("EndStreamPrimitive(") + de::toString(m_parameters.xfbStreamIndex()) + ")" : "EndPrimitive()";
1116 		std::ostringstream	src;
1117 
1118 		src	<<	"#version 450\n"
1119 				"layout(" << inputTopology << ") in;\n"
1120 				"layout(" << outputTopology << ", max_vertices = " << maxVertices << ") out;\n";
1121 
1122 		if (m_parameters.transformFeedback)
1123 			src	<<	"layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0, stream = " << m_parameters.xfbStreamIndex() << ") out vec4 xfb;\n";
1124 
1125 		src	<<	"void main (void)\n"
1126 				"{\n";
1127 
1128 		if (outputPoints)
1129 			src	<<	"    gl_PointSize = 1.0;\n";
1130 
1131 		if (m_parameters.transformFeedback)
1132 			src	<<	"    xfb = vec4(42);\n";
1133 
1134 		for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1135 			src	<<	"    " << pgqEmitCommand << ";\n";
1136 
1137 		src	<<	"    " << pgqEndCommand << ";\n";
1138 
1139 		if (m_parameters.transformFeedback && m_parameters.multipleStreams())
1140 		{
1141 			for (VkDeviceSize i = 0; i < outputPrimSize; i++)
1142 				src	<<	"    " << xfbEmitCommand << ";\n";
1143 
1144 			src	<<	"    " << xfbEndCommand << ";\n";
1145 		}
1146 
1147 		src	<<	"}\n";
1148 
1149 		programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
1150 	}
1151 
1152 	// Fragment shader.
1153 	if (!m_parameters.rastDiscard())
1154 	{
1155 		std::ostringstream src;
1156 
1157 		if (m_parameters.rastCase == RAST_CASE_EMPTY_FRAG)
1158 		{
1159 			src	<<	"#version 450\n"
1160 					"void main (void) {}\n";
1161 		}
1162 		else
1163 		{
1164 			src	<<	"#version 450\n"
1165 					"layout(location = 0) out vec4 out0;\n"
1166 					"void main (void)\n"
1167 					"{\n"
1168 					"    out0 = vec4(0.0, 1.0, 0.0, 1.0);\n"
1169 					"}\n";
1170 		}
1171 
1172 		programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
1173 	}
1174 }
1175 
testGenerator(tcu::TestCaseGroup * pgqGroup)1176 void testGenerator (tcu::TestCaseGroup* pgqGroup)
1177 {
1178 	constexpr struct ReadType
1179 	{
1180 		QueryReadType	type;
1181 		const char*		name;
1182 		const char*		desc;
1183 	} readTypes[] =
1184 	{
1185 		{ QUERY_READ_TYPE_GET,	"get",	"Tests for vkGetQueryPoolResults"		},
1186 		{ QUERY_READ_TYPE_COPY,	"copy",	"Tests for vkCmdCopyQueryPoolResults"	},
1187 	};
1188 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(readTypes) == QUERY_READ_TYPE_LAST);
1189 
1190 	constexpr struct ResetType
1191 	{
1192 		QueryResetType	type;
1193 		const char*		name;
1194 		const char*		desc;
1195 	} resetTypes[] =
1196 	{
1197 		{ QUERY_RESET_TYPE_QUEUE,	"queue_reset",	"Tests for vkCmdResetQueryPool"	},
1198 		{ QUERY_RESET_TYPE_HOST,	"host_reset",	"Tests for vkResetQueryPool"	},
1199 	};
1200 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resetTypes) == QUERY_RESET_TYPE_LAST);
1201 
1202 	constexpr struct ResultTypes
1203 	{
1204 		QueryResultType	type;
1205 		const char*		name;
1206 		const char*		desc;
1207 	} resultTypes[] =
1208 	{
1209 		{ QUERY_RESULT_TYPE_32_BIT,			"32bit",				"Tests for default query result size"							},
1210 		{ QUERY_RESULT_TYPE_64_BIT,			"64bit",				"Tests for VK_QUERY_RESULT_64_BIT"								},
1211 		{ QUERY_RESULT_TYPE_PGQ_32_XFB_64,	"pgq_32bit_xfb_64bit",	"Tests for PGQ without and XFBQ with VK_QUERY_RESULT_64_BIT"	},
1212 		{ QUERY_RESULT_TYPE_PGQ_64_XFB_32,	"pgq_64bit_xfb_32bit",	"Tests for PGQ with and XFBQ without VK_QUERY_RESULT_64_BIT"	},
1213 	};
1214 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(resultTypes) == QUERY_RESULT_TYPE_LAST);
1215 
1216 	constexpr struct Shader
1217 	{
1218 		ShaderStage	stage;
1219 		const char*	name;
1220 		const char*	desc;
1221 	} shaderStages[] =
1222 	{
1223 		{ SHADER_STAGE_VERTEX,					"vert",	"Vertex shader tests"					},
1224 		{ SHADER_STAGE_TESSELLATION_EVALUATION,	"tese",	"Tessellation evaluation shader tests"	},
1225 		{ SHADER_STAGE_GEOMETRY,				"geom",	"Geometry shader tests"					},
1226 	};
1227 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(shaderStages) == SHADER_STAGE_LAST);
1228 
1229 	constexpr struct TransformFeedbackState
1230 	{
1231 		deBool		enable;
1232 		const char*	name;
1233 		const char*	desc;
1234 	} transformFeedbackStates[] =
1235 	{
1236 		{ DE_FALSE,	"no_xfb",	"Tests without transform feedback"											},
1237 		{ DE_TRUE,	"xfb",		"Tests for comparing PGQ results against transform feedback query results"	},
1238 	};
1239 
1240 	constexpr struct RastCase
1241 	{
1242 		RasterizationCase	type;
1243 		deBool				dsAttachment;
1244 		const char*			name;
1245 		const char*			desc;
1246 	} rastCases[] =
1247 	{
1248 		{ RAST_CASE_DISCARD,						DE_FALSE,	"no_rast",							"Tests with rasterizer discard"																			},
1249 		{ RAST_CASE_DEFAULT,						DE_FALSE,	"rast",								"Tests without rasterizer discard"																		},
1250 		{ RAST_CASE_EMPTY_FRAG,						DE_FALSE,	"empty_frag",						"Tests with an empty fragment shader"																	},
1251 		{ RAST_CASE_NO_ATTACHMENT,					DE_FALSE,	"no_attachment",					"Tests with an attachmentless render pass"																},
1252 		{ RAST_CASE_COLOR_WRITE_DISABLE_STATIC,		DE_FALSE,	"color_write_disable_static",		"Tests disabling color output using VkPipelineColorWriteCreateInfoEXT"									},
1253 		{ RAST_CASE_COLOR_WRITE_DISABLE_STATIC,		DE_TRUE,	"color_write_disable_static_ds",	"Tests disabling color output using VkPipelineColorWriteCreateInfoEXT with a depth stencil attachment"	},
1254 		{ RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,	DE_FALSE,	"color_write_disable_dynamic",		"Tests disabling color output using vkCmdSetColorWriteEnableEXT"										},
1255 		{ RAST_CASE_COLOR_WRITE_DISABLE_DYNAMIC,	DE_TRUE,	"color_write_disable_dynamic_ds",	"Tests disabling color output using vkCmdSetColorWriteEnableEXT with a depth stencil attachment"		},
1256 	};
1257 
1258 	constexpr struct Topology
1259 	{
1260 		VkPrimitiveTopology	type;
1261 		const char*			name;
1262 		const char*			desc;
1263 	} topologies[] =
1264 	{
1265 		{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST,						"point_list",						"Tests for separate point primitives"																		},
1266 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						"line_list",						"Tests for separate line primitives"																		},
1267 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						"line_strip",						"Tests for connected line primitives with consecutive lines sharing a vertex"								},
1268 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					"triangle_list",					"Tests for separate triangle primitives"																	},
1269 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					"triangle_strip",					"Tests for connected triangle primitives with consecutive triangles sharing an edge"						},
1270 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,					"triangle_fan",						"Tests for connected triangle primitives with all triangles sharing a common vertex"						},
1271 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,		"line_list_with_adjacency",			"Tests for separate line primitives with adjacency"															},
1272 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		"line_strip_with_adjacency",		"Tests for connected line primitives with adjacency, with consecutive primitives sharing three vertices"	},
1273 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,	"triangle_list_with_adjacency",		"Tests for separate triangle primitives with adjacency"														},
1274 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,	"triangle_strip_with_adjacency",	"Tests for connected triangle primitives with adjacency, with consecutive triangles sharing an edge"		},
1275 		{ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,						"patch_list",						"Tests for separate patch primitives"																		},
1276 	};
1277 
1278 	// Tests for vkCmdBeginQueryIndexedEXT and vkCmdEndQueryIndexedEXT.
1279 	constexpr struct StreamIndex
1280 	{
1281 		VertexStream	index;
1282 		const char*		name;
1283 	} streamIndices[] =
1284 	{
1285 		{ VERTEX_STREAM_DEFAULT,	"default"	},
1286 		{ VERTEX_STREAM_0,			"0"			},
1287 		{ VERTEX_STREAM_1,			"1"			},
1288 	};
1289 
1290 	constexpr struct CmdBufCase
1291 	{
1292 		CommandBufferCase	type;
1293 		const char*			name;
1294 		const char*			desc;
1295 	} cmdBufCases[] =
1296 	{
1297 		{ CMD_BUF_CASE_SINGLE_DRAW,	"single_draw",	"Test single draw call"	},
1298 	};
1299 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(cmdBufCases) == CMD_BUF_CASE_LAST);
1300 
1301 	tcu::TestContext& testCtx = pgqGroup->getTestContext();
1302 
1303 	for (const ReadType& read : readTypes)
1304 	{
1305 		de::MovePtr<tcu::TestCaseGroup> readGroup(new tcu::TestCaseGroup(testCtx, read.name, read.desc));
1306 
1307 		for (const ResetType& reset : resetTypes)
1308 		{
1309 			de::MovePtr<tcu::TestCaseGroup> resetGroup(new tcu::TestCaseGroup(testCtx, reset.name, reset.desc));
1310 
1311 			for (const ResultTypes& result : resultTypes)
1312 			{
1313 				de::MovePtr<tcu::TestCaseGroup> resultGroup(new tcu::TestCaseGroup(testCtx, result.name, result.desc));
1314 
1315 				for (const Shader& shader : shaderStages)
1316 				{
1317 					de::MovePtr<tcu::TestCaseGroup> shaderGroup(new tcu::TestCaseGroup(testCtx, shader.name, shader.desc));
1318 
1319 					for (const TransformFeedbackState& xfbState : transformFeedbackStates)
1320 					{
1321 						de::MovePtr<tcu::TestCaseGroup> xfbGroup(new tcu::TestCaseGroup(testCtx, xfbState.name, xfbState.desc));
1322 
1323 						// Only test multiple result types with XFB enabled.
1324 						if ((result.type == QUERY_RESULT_TYPE_PGQ_32_XFB_64 || result.type == QUERY_RESULT_TYPE_PGQ_64_XFB_32) && !xfbState.enable)
1325 							continue;
1326 
1327 						for (const RastCase& rastCase : rastCases)
1328 						{
1329 							de::MovePtr<tcu::TestCaseGroup> rastGroup(new tcu::TestCaseGroup(testCtx, rastCase.name, rastCase.desc));
1330 
1331 							// Skip uninteresting cases
1332 							if ((rastCase.type > RAST_CASE_DISCARD)
1333 								&& ((read.type != QUERY_READ_TYPE_GET)
1334 								|| (reset.type != QUERY_RESET_TYPE_QUEUE)
1335 								|| (result.type != QUERY_RESULT_TYPE_32_BIT)))
1336 							{
1337 								continue;
1338 							}
1339 
1340 							for (const Topology& topology : topologies)
1341 							{
1342 								de::MovePtr<tcu::TestCaseGroup> topologyGroup(new tcu::TestCaseGroup(testCtx, topology.name, topology.desc));
1343 
1344 								// Only test patch lists with tessellation shaders.
1345 								if ((topology.type == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage != SHADER_STAGE_TESSELLATION_EVALUATION) ||
1346 								   ((topology.type != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST && shader.stage == SHADER_STAGE_TESSELLATION_EVALUATION)))
1347 								{
1348 									continue;
1349 								}
1350 
1351 								// Only test adjacency topologies with geometry shaders.
1352 								if (shader.stage != SHADER_STAGE_GEOMETRY && topologyData.at(topology.type).hasAdjacency)
1353 									continue;
1354 
1355 								for (const StreamIndex& pgqStream : streamIndices)
1356 								{
1357 									for (const StreamIndex& xfbStream : streamIndices)
1358 									{
1359 										const std::string			streamGroupName	= std::string("pgq_") + pgqStream.name + (xfbState.enable ? std::string("_xfb_") + xfbStream.name : "");
1360 										const bool					pgqDefault		= (pgqStream.index == VERTEX_STREAM_DEFAULT);
1361 										const bool					xfbDefault		= (xfbStream.index == VERTEX_STREAM_DEFAULT);
1362 										const std::string			pgqDescStr		= std::string("PGQ on ") + (pgqDefault ? "default " : "") + std::string("vertex stream ") + (pgqDefault ? "" : pgqStream.name);
1363 										const std::string			xfbDescStr		= std::string("XFB on ") + (xfbDefault ? "default " : "") + std::string("vertex stream ") + (xfbDefault ? "" : xfbStream.name);
1364 										const std::string			streamGroupDesc	= std::string("Tests for ") + pgqDescStr + (xfbState.enable ? (std::string(" and ") + xfbDescStr) : "");
1365 										de::MovePtr<tcu::TestCaseGroup>	streamGroup(new tcu::TestCaseGroup(testCtx, streamGroupName.c_str(), streamGroupDesc.c_str()));
1366 
1367 										// Only test nondefault vertex streams with geometry shaders.
1368 										if ((pgqStream.index != VERTEX_STREAM_DEFAULT || xfbStream.index != VERTEX_STREAM_DEFAULT) && shader.stage != SHADER_STAGE_GEOMETRY)
1369 											continue;
1370 
1371 										// Skip nondefault vertex streams for XFB when not enabled.
1372 										if (!xfbState.enable && xfbStream.index != VERTEX_STREAM_DEFAULT)
1373 											continue;
1374 
1375 										for (const CmdBufCase& cmdBufCase : cmdBufCases)
1376 										{
1377 											const TestParameters	parameters	=
1378 											{
1379 												read.type,				// QueryReadType		queryReadType
1380 												reset.type,				// QueryResetType		queryResetType
1381 												result.type,			// QueryResultType		queryResultType
1382 												shader.stage,			// ShaderStage			shaderStage
1383 												xfbState.enable,		// deBool				transformFeedback
1384 												rastCase.type,			// RasterizationCase	rastCase
1385 												rastCase.dsAttachment,	// deBool				depthStencilAttachment
1386 												topology.type,			// VkPrimitiveTopology	primitiveTopology
1387 												pgqStream.index,		// VertexStreamIndex	pgqStreamIndex
1388 												xfbStream.index,		// VertexStreamIndex	xfbStreamIndex
1389 												cmdBufCase.type,		// CommandBufferCase	cmdBufCase
1390 											};
1391 
1392 											streamGroup->addChild(new PrimitivesGeneratedQueryTestCase(testCtx, cmdBufCase.name, cmdBufCase.desc, parameters));
1393 										}
1394 
1395 										topologyGroup->addChild(streamGroup.release());
1396 									}
1397 								}
1398 
1399 								rastGroup->addChild(topologyGroup.release());
1400 							}
1401 
1402 							xfbGroup->addChild(rastGroup.release());
1403 						}
1404 
1405 						shaderGroup->addChild(xfbGroup.release());
1406 					}
1407 
1408 					resultGroup->addChild(shaderGroup.release());
1409 				}
1410 
1411 				resetGroup->addChild(resultGroup.release());
1412 			}
1413 
1414 			readGroup->addChild(resetGroup.release());
1415 		}
1416 
1417 		pgqGroup->addChild(readGroup.release());
1418 	}
1419 }
1420 
1421 } // anonymous
1422 
createPrimitivesGeneratedQueryTests(tcu::TestContext & testCtx)1423 tcu::TestCaseGroup* createPrimitivesGeneratedQueryTests (tcu::TestContext& testCtx)
1424 {
1425 	return createTestGroup(testCtx, "primitives_generated_query", "Primitives Generated Query Tests", testGenerator);
1426 }
1427 
1428 } // TransformFeedback
1429 } // vkt
1430