• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2018 The Khronos Group Inc.
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 Vulkan Transform Feedback Simple Tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktTransformFeedbackSimpleTests.hpp"
25 #include "vktTestGroupUtil.hpp"
26 #include "vktTestCase.hpp"
27 
28 #include "vkBuilderUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkImageUtil.hpp"
31 #include "vkObjUtil.hpp"
32 #include "vkQueryUtil.hpp"
33 #include "vkRefUtil.hpp"
34 #include "vkTypeUtil.hpp"
35 
36 #include "deUniquePtr.hpp"
37 #include "deRandom.hpp"
38 
39 #include "tcuTextureUtil.hpp"
40 #include "tcuVectorUtil.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuRGBA.hpp"
43 #include "tcuTestLog.hpp"
44 #include "tcuCommandLine.hpp"
45 
46 #include <iostream>
47 #include <functional>
48 #include <set>
49 #include <algorithm>
50 
51 namespace vkt
52 {
53 namespace TransformFeedback
54 {
55 namespace
56 {
57 using namespace vk;
58 using de::MovePtr;
59 using de::UniquePtr;
60 using de::SharedPtr;
61 
62 #define VALIDATE_MINIMUM(A,B) if ((A) < (B)) TCU_FAIL(#A "==" + de::toString(A) + " which is less than required by specification (" + de::toString(B) + ")")
63 #define VALIDATE_BOOL(A) if (! ( (A) == VK_TRUE || (A) == VK_FALSE) ) TCU_FAIL(#A " expected to be VK_TRUE or VK_FALSE. Received " + de::toString((deUint64)(A)))
64 
65 const deUint32				INVOCATION_COUNT	= 8u;
66 const std::vector<deUint32>	LINES_LIST			{ 2, 6, 3 };
67 const std::vector<deUint32>	TRIANGLES_LIST		{ 3, 8, 6, 5, 4 };
68 
69 enum TestType
70 {
71 	TEST_TYPE_BASIC,
72 	TEST_TYPE_RESUME,
73 	TEST_TYPE_STREAMS,
74 	TEST_TYPE_XFB_POINTSIZE,
75 	TEST_TYPE_XFB_CLIPDISTANCE,
76 	TEST_TYPE_XFB_CULLDISTANCE,
77 	TEST_TYPE_XFB_CLIP_AND_CULL,
78 	TEST_TYPE_WINDING,
79 	TEST_TYPE_STREAMS_POINTSIZE,
80 	TEST_TYPE_STREAMS_CLIPDISTANCE,
81 	TEST_TYPE_STREAMS_CULLDISTANCE,
82 	TEST_TYPE_MULTISTREAMS,
83 	TEST_TYPE_DRAW_INDIRECT,
84 	TEST_TYPE_BACKWARD_DEPENDENCY,
85 	TEST_TYPE_QUERY_GET,
86 	TEST_TYPE_QUERY_COPY,
87 	TEST_TYPE_QUERY_COPY_STRIDE_ZERO,
88 	TEST_TYPE_QUERY_RESET,
89 	TEST_TYPE_MULTIQUERY,
90 	TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX,
91 	TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY,
92 	TEST_TYPE_DEPTH_CLIP_CONTROL_TESE,
93 	TEST_TYPE_LINES_TRIANGLES,
94 	TEST_TYPE_LAST
95 };
96 
97 enum StreamId0Mode
98 {
99 	STREAM_ID_0_NORMAL					= 0,
100 	STREAM_ID_0_BEGIN_QUERY_INDEXED		= 1,
101 	STREAM_ID_0_END_QUERY_INDEXED		= 2,
102 };
103 
104 struct TestParameters
105 {
106 	TestType			testType;
107 	deUint32			bufferSize;
108 	deUint32			partCount;
109 	deUint32			streamId;
110 	deUint32			pointSize;
111 	deUint32			vertexStride;
112 	StreamId0Mode		streamId0Mode;
113 	bool				query64bits;
114 	bool				noOffsetArray;
115 	bool				requireRastStreamSelect;
116 	bool				omitShaderWrite;
117 	VkPrimitiveTopology	primTopology;
118 };
119 
120 struct TopologyInfo
121 {
122 	deUint32							primSize;			// The size of the on primitive.
123 	std::string							topologyName;		// The suffix for the name of test.
124 	std::function<deUint64(deUint64)>	getNumPrimitives;	// The number of primitives generated.
125 	std::function<deUint64(deUint64)>	getNumVertices;		// The number of vertices generated.
126 };
127 
128 const std::map<VkPrimitiveTopology, TopologyInfo> topologyData =
129 {
__anond6854b9f0202() 130 	{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST						, { 1, ""								,[](deUint64 vertexCount)	{	return vertexCount;				}	,[](deUint64 primCount)	{	return primCount;			}, } },
__anond6854b9f0402() 131 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST						, { 2, "line_list_"						,[](deUint64 vertexCount)	{	return vertexCount / 2u;		}	,[](deUint64 primCount) {	return primCount * 2u;		}, } },
__anond6854b9f0602() 132 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP						, { 2, "line_strip_"					,[](deUint64 vertexCount)	{	return vertexCount - 1u;		}	,[](deUint64 primCount) {	return primCount + 1u;		}, } },
__anond6854b9f0802() 133 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST					, { 3, "triangle_list_"					,[](deUint64 vertexCount)	{	return vertexCount / 3u;		}	,[](deUint64 primCount) {	return primCount * 3u;		}, } },
__anond6854b9f0b02() 134 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP					, { 3, "triangle_strip_"				,[](deUint64 vertexCount)	{	return vertexCount - 2u;		}	,[](deUint64 primCount) {	return primCount + 2u;		}, } },
__anond6854b9f0d02() 135 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN					, { 3, "triangle_fan_"					,[](deUint64 vertexCount)	{	return vertexCount - 2u;		}	,[](deUint64 primCount) {	return primCount + 2u;		}, } },
__anond6854b9f0f02() 136 	{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY		, { 2, "line_list_with_adjacency_"		,[](deUint64 vertexCount)	{	return vertexCount / 4u;		}	,[](deUint64 primCount) {	return primCount * 4u;		}, } },
__anond6854b9f1002() 137 	{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY		, { 2, "line_strip_with_adjacency_"		,[](deUint64 vertexCount)	{	return vertexCount - 3u;		}	,[](deUint64 primCount) {	return primCount + 3u;		}, } },
__anond6854b9f1302() 138 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY	, { 3, "triangle_list_with_adjacency_"	,[](deUint64 vertexCount)	{	return vertexCount / 6u;		}	,[](deUint64 primCount) {	return primCount * 6u;		}, } },
__anond6854b9f1502() 139 	{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY	, { 3, "triangle_strip_with_adjacency_"	,[](deUint64 vertexCount)	{	return (vertexCount - 4u) / 2u;	}	,[](deUint64 primCount) {	return primCount * 2u + 4u;	}, } },
__anond6854b9f1702() 140 	{ VK_PRIMITIVE_TOPOLOGY_PATCH_LIST						, { 3, "patch_list_"					,[](deUint64 vertexCount)	{	return vertexCount / 3u;		}	,[](deUint64 primCount) {	return primCount * 3u;		}, } },
141 };
142 
143 struct TransformFeedbackQuery
144 {
145 	deUint32	written;
146 	deUint32	attempts;
147 };
148 
149 const deUint32	MINIMUM_TF_BUFFER_SIZE	= (1<<27);
150 const deUint32	IMAGE_SIZE				= 64u;
151 
152 template<typename T>
makeSharedPtr(Move<T> move)153 inline SharedPtr<Unique<T> > makeSharedPtr(Move<T> move)
154 {
155 	return SharedPtr<Unique<T> >(new Unique<T>(move));
156 }
157 
158 template<typename T>
getInvalidatedHostPtr(const DeviceInterface & vk,const VkDevice device,Allocation & bufAlloc)159 const T* getInvalidatedHostPtr (const DeviceInterface& vk, const VkDevice device, Allocation& bufAlloc)
160 {
161 	invalidateAlloc(vk, device, bufAlloc);
162 
163 	return static_cast<T*>(bufAlloc.getHostPtr());
164 }
165 
makePipelineLayout(const DeviceInterface & vk,const VkDevice device)166 Move<VkPipelineLayout> makePipelineLayout (const DeviceInterface&		vk,
167 										   const VkDevice				device)
168 {
169 	const VkPushConstantRange			pushConstantRanges			=
170 	{
171 		VK_SHADER_STAGE_VERTEX_BIT,						//  VkShaderStageFlags				stageFlags;
172 		0u,												//  deUint32						offset;
173 		sizeof(deUint32)								//  deUint32						size;
174 	};
175 	const VkPipelineLayoutCreateInfo	pipelineLayoutCreateInfo	=
176 	{
177 		VK_STRUCTURE_TYPE_PIPELINE_LAYOUT_CREATE_INFO,	//  VkStructureType					sType;
178 		DE_NULL,										//  const void*						pNext;
179 		(VkPipelineLayoutCreateFlags)0,					//  VkPipelineLayoutCreateFlags		flags;
180 		0u,												//  deUint32						setLayoutCount;
181 		DE_NULL,										//  const VkDescriptorSetLayout*	pSetLayouts;
182 		1u,												//  deUint32						pushConstantRangeCount;
183 		&pushConstantRanges,							//  const VkPushConstantRange*		pPushConstantRanges;
184 	};
185 	return createPipelineLayout(vk, device, &pipelineLayoutCreateInfo);
186 }
187 
makeGraphicsPipeline(const DeviceInterface & vk,const VkDevice device,const VkPipelineLayout pipelineLayout,const VkRenderPass renderPass,const VkShaderModule vertexModule,const VkShaderModule tessellationControlModule,const VkShaderModule tessellationEvalModule,const VkShaderModule geometryModule,const VkShaderModule fragmentModule,const VkExtent2D renderSize,const deUint32 subpass,const deUint32 * rasterizationStreamPtr=DE_NULL,const VkPrimitiveTopology topology=VK_PRIMITIVE_TOPOLOGY_POINT_LIST,const bool inputVertices=false,const bool depthClipControl=false)188 Move<VkPipeline> makeGraphicsPipeline (const DeviceInterface&		vk,
189 									   const VkDevice				device,
190 									   const VkPipelineLayout		pipelineLayout,
191 									   const VkRenderPass			renderPass,
192 									   const VkShaderModule			vertexModule,
193 									   const VkShaderModule			tessellationControlModule,
194 									   const VkShaderModule			tessellationEvalModule,
195 									   const VkShaderModule			geometryModule,
196 									   const VkShaderModule			fragmentModule,
197 									   const VkExtent2D				renderSize,
198 									   const deUint32				subpass,
199 									   const deUint32*				rasterizationStreamPtr	= DE_NULL,
200 									   const VkPrimitiveTopology	topology				= VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
201 									   const bool					inputVertices			= false,
202 									   const bool					depthClipControl		= false)
203 {
204 	VkViewport												viewport							= makeViewport(renderSize);
205 	VkRect2D												scissor								= makeRect2D(renderSize);
206 
207 	const VkPipelineViewportDepthClipControlCreateInfoEXT	depthClipControlCreateInfo			=
208 	{
209 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_DEPTH_CLIP_CONTROL_CREATE_INFO_EXT,	// VkStructureType	sType;
210 		DE_NULL,																// const void*		pNext;
211 		VK_TRUE,																// VkBool32		negativeOneToOne;
212 	};
213 
214 	const VkPipelineViewportStateCreateInfo					viewportStateCreateInfo				=
215 	{
216 		VK_STRUCTURE_TYPE_PIPELINE_VIEWPORT_STATE_CREATE_INFO,		// VkStructureType                             sType
217 		depthClipControl ? &depthClipControlCreateInfo : DE_NULL,	// const void*                                 pNext
218 		(VkPipelineViewportStateCreateFlags)0,						// VkPipelineViewportStateCreateFlags          flags
219 		1u,															// deUint32                                    viewportCount
220 		&viewport,													// const VkViewport*                           pViewports
221 		1u,															// deUint32                                    scissorCount
222 		&scissor													// const VkRect2D*                             pScissors
223 	};
224 
225 	const VkPipelineInputAssemblyStateCreateInfo			inputAssemblyStateCreateInfo		=
226 	{
227 		VK_STRUCTURE_TYPE_PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,	// VkStructureType                            sType
228 		DE_NULL,														// const void*                                pNext
229 		0u,																// VkPipelineInputAssemblyStateCreateFlags    flags
230 		topology,														// VkPrimitiveTopology                        topology
231 		VK_FALSE														// VkBool32                                   primitiveRestartEnable
232 	};
233 
234 	const VkPipelineVertexInputStateCreateInfo				vertexInputStateCreateInfo			=
235 	{
236 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,									//  VkStructureType									sType
237 		DE_NULL,																					//  const void*										pNext
238 		(VkPipelineVertexInputStateCreateFlags)0,													//  VkPipelineVertexInputStateCreateFlags			flags
239 		0u,																							//  deUint32										vertexBindingDescriptionCount
240 		DE_NULL,																					//  const VkVertexInputBindingDescription*			pVertexBindingDescriptions
241 		0u,																							//  deUint32										vertexAttributeDescriptionCount
242 		DE_NULL,																					//  const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions
243 	};
244 
245 	const VkPipelineVertexInputStateCreateInfo*				vertexInputStateCreateInfoPtr		= (inputVertices) ? DE_NULL : &vertexInputStateCreateInfo;
246 	const VkBool32											disableRasterization				= (fragmentModule == DE_NULL);
247 	const deUint32											rasterizationStream					= (rasterizationStreamPtr == DE_NULL) ? 0 : *rasterizationStreamPtr;
248 
249 	const VkPipelineRasterizationStateStreamCreateInfoEXT	rasterizationStateStreamCreateInfo	=
250 	{
251 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_STREAM_CREATE_INFO_EXT,						//  VkStructureType										sType;
252 		DE_NULL,																					//  const void*											pNext;
253 		0,																							//  VkPipelineRasterizationStateStreamCreateFlagsEXT	flags;
254 		rasterizationStream																			//  deUint32											rasterizationStream;
255 	};
256 
257 	const VkPipelineRasterizationStateCreateInfo			rasterizationStateCreateInfo		=
258 	{
259 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	//  VkStructureType							sType
260 		&rasterizationStateStreamCreateInfo,						//  const void*								pNext
261 		0u,															//  VkPipelineRasterizationStateCreateFlags	flags
262 		VK_FALSE,													//  VkBool32								depthClampEnable
263 		disableRasterization,										//  VkBool32								rasterizerDiscardEnable
264 		VK_POLYGON_MODE_FILL,										//  VkPolygonMode							polygonMode
265 		VK_CULL_MODE_NONE,											//  VkCullModeFlags							cullMode
266 		VK_FRONT_FACE_COUNTER_CLOCKWISE,							//  VkFrontFace								frontFace
267 		VK_FALSE,													//  VkBool32								depthBiasEnable
268 		0.0f,														//  float									depthBiasConstantFactor
269 		0.0f,														//  float									depthBiasClamp
270 		0.0f,														//  float									depthBiasSlopeFactor
271 		1.0f														//  float									lineWidth
272 	};
273 
274 	const VkPipelineRasterizationStateCreateInfo*			rasterizationStateCreateInfoPtr		= (rasterizationStreamPtr == DE_NULL) ? DE_NULL : &rasterizationStateCreateInfo;
275 
276 	const VkPipelineTessellationStateCreateInfo				tessStateCreateInfo					=
277 	{
278 		VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,	// VkStructureType                           sType
279 		DE_NULL,													// const void*                               pNext
280 		0u,															// VkPipelineTessellationStateCreateFlags    flags
281 		3u															// deUint32                                  patchControlPoints
282 	};
283 
284 	return makeGraphicsPipeline(vk,									// const DeviceInterface&							vk
285 								device,								// const VkDevice									device
286 								pipelineLayout,						// const VkPipelineLayout							pipelineLayout
287 								vertexModule,						// const VkShaderModule								vertexShaderModule
288 								tessellationControlModule,			// const VkShaderModule								tessellationControlModule
289 								tessellationEvalModule,				// const VkShaderModule								tessellationEvalModule
290 								geometryModule,						// const VkShaderModule								geometryShaderModule
291 								fragmentModule,						// const VkShaderModule								fragmentShaderModule
292 								renderPass,							// const VkRenderPass								renderPass
293 								subpass,							// const deUint32									subpass
294 								vertexInputStateCreateInfoPtr,		// const VkPipelineVertexInputStateCreateInfo*		vertexInputStateCreateInfo
295 								&inputAssemblyStateCreateInfo,		// const VkPipelineInputAssemblyStateCreateInfo*	inputAssemblyStateCreateInfo
296 								&tessStateCreateInfo,				// const VkPipelineTessellationStateCreateInfo*		tessStateCreateInfo
297 								&viewportStateCreateInfo,			// const VkPipelineViewportStateCreateInfo*			viewportStateCreateInfo
298 								rasterizationStateCreateInfoPtr);	// const VkPipelineRasterizationStateCreateInfo*	rasterizationStateCreateInfo
299 }
300 
makeImageCreateInfo(const VkImageCreateFlags flags,const VkImageType type,const VkFormat format,const VkExtent2D size,const deUint32 numLayers,const VkImageUsageFlags usage)301 VkImageCreateInfo makeImageCreateInfo (const VkImageCreateFlags flags, const VkImageType type, const VkFormat format, const VkExtent2D size, const deUint32 numLayers, const VkImageUsageFlags usage)
302 {
303 	const VkExtent3D		extent		= { size.width, size.height, 1u };
304 	const VkImageCreateInfo imageParams =
305 	{
306 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,			// VkStructureType			sType;
307 		DE_NULL,										// const void*				pNext;
308 		flags,											// VkImageCreateFlags		flags;
309 		type,											// VkImageType				imageType;
310 		format,											// VkFormat					format;
311 		extent,											// VkExtent3D				extent;
312 		1u,												// deUint32					mipLevels;
313 		numLayers,										// deUint32					arrayLayers;
314 		VK_SAMPLE_COUNT_1_BIT,							// VkSampleCountFlagBits	samples;
315 		VK_IMAGE_TILING_OPTIMAL,						// VkImageTiling			tiling;
316 		usage,											// VkImageUsageFlags		usage;
317 		VK_SHARING_MODE_EXCLUSIVE,						// VkSharingMode			sharingMode;
318 		0u,												// deUint32					queueFamilyIndexCount;
319 		DE_NULL,										// const deUint32*			pQueueFamilyIndices;
320 		VK_IMAGE_LAYOUT_UNDEFINED,						// VkImageLayout			initialLayout;
321 	};
322 	return imageParams;
323 }
324 
makeRenderPass(const DeviceInterface & vk,const VkDevice device)325 Move<VkRenderPass> makeRenderPass (const DeviceInterface&		vk,
326 								   const VkDevice				device)
327 {
328 	std::vector<VkSubpassDescription>	subpassDescriptions;
329 	std::vector<VkSubpassDependency>	subpassDependencies;
330 
331 	const VkSubpassDescription	description	=
332 	{
333 		(VkSubpassDescriptionFlags)0,		//  VkSubpassDescriptionFlags		flags;
334 		VK_PIPELINE_BIND_POINT_GRAPHICS,	//  VkPipelineBindPoint				pipelineBindPoint;
335 		0u,									//  deUint32						inputAttachmentCount;
336 		DE_NULL,							//  const VkAttachmentReference*	pInputAttachments;
337 		0u,									//  deUint32						colorAttachmentCount;
338 		DE_NULL,							//  const VkAttachmentReference*	pColorAttachments;
339 		DE_NULL,							//  const VkAttachmentReference*	pResolveAttachments;
340 		DE_NULL,							//  const VkAttachmentReference*	pDepthStencilAttachment;
341 		0,									//  deUint32						preserveAttachmentCount;
342 		DE_NULL								//  const deUint32*					pPreserveAttachments;
343 	};
344 	subpassDescriptions.push_back(description);
345 
346 	const VkSubpassDependency	dependency	=
347 	{
348 		0u,													//  deUint32				srcSubpass;
349 		0u,													//  deUint32				dstSubpass;
350 		VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,		//  VkPipelineStageFlags	srcStageMask;
351 		VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT,				//  VkPipelineStageFlags	dstStageMask;
352 		VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,	//  VkAccessFlags			srcAccessMask;
353 		VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,	//  VkAccessFlags			dstAccessMask;
354 		0u													//  VkDependencyFlags		dependencyFlags;
355 	};
356 	subpassDependencies.push_back(dependency);
357 
358 	const VkRenderPassCreateInfo renderPassInfo =
359 	{
360 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,							//  VkStructureType					sType;
361 		DE_NULL,															//  const void*						pNext;
362 		static_cast<VkRenderPassCreateFlags>(0u),							//  VkRenderPassCreateFlags			flags;
363 		0u,																	//  deUint32						attachmentCount;
364 		DE_NULL,															//  const VkAttachmentDescription*	pAttachments;
365 		static_cast<deUint32>(subpassDescriptions.size()),					//  deUint32						subpassCount;
366 		&subpassDescriptions[0],											//  const VkSubpassDescription*		pSubpasses;
367 		static_cast<deUint32>(subpassDependencies.size()),					//  deUint32						dependencyCount;
368 		subpassDependencies.size() > 0 ? &subpassDependencies[0] : DE_NULL	//  const VkSubpassDependency*		pDependencies;
369 	};
370 
371 	return createRenderPass(vk, device, &renderPassInfo);
372 }
373 
makeImageMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkImageLayout oldLayout,const VkImageLayout newLayout,const VkImage image,const VkImageSubresourceRange subresourceRange)374 VkImageMemoryBarrier makeImageMemoryBarrier	(const VkAccessFlags			srcAccessMask,
375 											 const VkAccessFlags			dstAccessMask,
376 											 const VkImageLayout			oldLayout,
377 											 const VkImageLayout			newLayout,
378 											 const VkImage					image,
379 											 const VkImageSubresourceRange	subresourceRange)
380 {
381 	const VkImageMemoryBarrier barrier =
382 	{
383 		VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,			// VkStructureType			sType;
384 		DE_NULL,										// const void*				pNext;
385 		srcAccessMask,									// VkAccessFlags			outputMask;
386 		dstAccessMask,									// VkAccessFlags			inputMask;
387 		oldLayout,										// VkImageLayout			oldLayout;
388 		newLayout,										// VkImageLayout			newLayout;
389 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					srcQueueFamilyIndex;
390 		VK_QUEUE_FAMILY_IGNORED,						// deUint32					destQueueFamilyIndex;
391 		image,											// VkImage					image;
392 		subresourceRange,								// VkImageSubresourceRange	subresourceRange;
393 	};
394 	return barrier;
395 }
396 
makeBufferMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask,const VkBuffer buffer,const VkDeviceSize offset,const VkDeviceSize bufferSizeBytes)397 VkBufferMemoryBarrier makeBufferMemoryBarrier (const VkAccessFlags	srcAccessMask,
398 											   const VkAccessFlags	dstAccessMask,
399 											   const VkBuffer		buffer,
400 											   const VkDeviceSize	offset,
401 											   const VkDeviceSize	bufferSizeBytes)
402 {
403 	const VkBufferMemoryBarrier barrier =
404 	{
405 		VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	//  VkStructureType	sType;
406 		DE_NULL,									//  const void*		pNext;
407 		srcAccessMask,								//  VkAccessFlags	srcAccessMask;
408 		dstAccessMask,								//  VkAccessFlags	dstAccessMask;
409 		VK_QUEUE_FAMILY_IGNORED,					//  deUint32		srcQueueFamilyIndex;
410 		VK_QUEUE_FAMILY_IGNORED,					//  deUint32		destQueueFamilyIndex;
411 		buffer,										//  VkBuffer		buffer;
412 		offset,										//  VkDeviceSize	offset;
413 		bufferSizeBytes,							//  VkDeviceSize	size;
414 	};
415 	return barrier;
416 }
417 
makeMemoryBarrier(const VkAccessFlags srcAccessMask,const VkAccessFlags dstAccessMask)418 VkMemoryBarrier makeMemoryBarrier (const VkAccessFlags	srcAccessMask,
419 								   const VkAccessFlags	dstAccessMask)
420 {
421 	const VkMemoryBarrier barrier =
422 	{
423 		VK_STRUCTURE_TYPE_MEMORY_BARRIER,	// VkStructureType			sType;
424 		DE_NULL,							// const void*				pNext;
425 		srcAccessMask,						// VkAccessFlags			outputMask;
426 		dstAccessMask,						// VkAccessFlags			inputMask;
427 	};
428 	return barrier;
429 }
430 
makeQueryPoolCreateInfo(const deUint32 queryCountersNumber)431 VkQueryPoolCreateInfo makeQueryPoolCreateInfo (const deUint32 queryCountersNumber)
432 {
433 	const VkQueryPoolCreateInfo			queryPoolCreateInfo		=
434 	{
435 		VK_STRUCTURE_TYPE_QUERY_POOL_CREATE_INFO,		//  VkStructureType					sType;
436 		DE_NULL,										//  const void*						pNext;
437 		(VkQueryPoolCreateFlags)0,						//  VkQueryPoolCreateFlags			flags;
438 		VK_QUERY_TYPE_TRANSFORM_FEEDBACK_STREAM_EXT,	//  VkQueryType						queryType;
439 		queryCountersNumber,							//  deUint32						queryCount;
440 		0u,												//  VkQueryPipelineStatisticFlags	pipelineStatistics;
441 	};
442 
443 	return queryPoolCreateInfo;
444 }
445 
fillBuffer(const DeviceInterface & vk,const VkDevice device,Allocation & bufferAlloc,VkDeviceSize bufferSize,const void * data,const VkDeviceSize dataSize)446 void fillBuffer (const DeviceInterface& vk, const VkDevice device, Allocation& bufferAlloc, VkDeviceSize bufferSize, const void* data, const VkDeviceSize dataSize)
447 {
448 	const VkMappedMemoryRange	memRange		=
449 	{
450 		VK_STRUCTURE_TYPE_MAPPED_MEMORY_RANGE,	//  VkStructureType	sType;
451 		DE_NULL,								//  const void*		pNext;
452 		bufferAlloc.getMemory(),				//  VkDeviceMemory	memory;
453 		bufferAlloc.getOffset(),				//  VkDeviceSize	offset;
454 		VK_WHOLE_SIZE							//  VkDeviceSize	size;
455 	};
456 	std::vector<deUint8>		dataVec			(static_cast<deUint32>(bufferSize), 0u);
457 
458 	DE_ASSERT(bufferSize >= dataSize);
459 
460 	deMemcpy(&dataVec[0], data, static_cast<deUint32>(dataSize));
461 
462 	deMemcpy(bufferAlloc.getHostPtr(), &dataVec[0], dataVec.size());
463 	VK_CHECK(vk.flushMappedMemoryRanges(device, 1u, &memRange));
464 }
465 
destripedLineCount(const std::vector<deUint32> & lineStripeSizesList)466 deUint32 destripedLineCount (const std::vector<deUint32>& lineStripeSizesList)
467 {
468 	deUint32 result = 0;
469 
470 	DE_ASSERT(!lineStripeSizesList.empty());
471 
472 	for (auto x : lineStripeSizesList)
473 		result += x > 1 ? x - 1 : 0;
474 
475 	return result;
476 }
477 
destripedTriangleCount(const std::vector<deUint32> & triangleStripeSizesList)478 deUint32 destripedTriangleCount (const std::vector<deUint32>& triangleStripeSizesList)
479 {
480 	deUint32 result = 0;
481 
482 	DE_ASSERT(!triangleStripeSizesList.empty());
483 
484 	for (auto x : triangleStripeSizesList)
485 		result += x > 2 ? x - 2 : 0;
486 
487 	return result;
488 }
489 
490 class TransformFeedbackTestInstance : public TestInstance
491 {
492 public:
493 													TransformFeedbackTestInstance	(Context& context, const TestParameters& parameters);
494 protected:
495 	void											validateLimits					();
496 	std::vector<VkDeviceSize>						generateSizesList				(const size_t bufBytes, const size_t chunkCount);
497 	std::vector<VkDeviceSize>						generateOffsetsList				(const std::vector<VkDeviceSize>& sizesList);
498 	void											verifyTransformFeedbackBuffer	(const MovePtr<Allocation>& bufAlloc,
499 																					 const deUint32 bufBytes);
500 
501 	const VkExtent2D								m_imageExtent2D;
502 	const TestParameters							m_parameters;
503 	VkPhysicalDeviceTransformFeedbackPropertiesEXT	m_transformFeedbackProperties;
504 	de::Random										m_rnd;
505 };
506 
TransformFeedbackTestInstance(Context & context,const TestParameters & parameters)507 TransformFeedbackTestInstance::TransformFeedbackTestInstance (Context& context, const TestParameters& parameters)
508 	: TestInstance		(context)
509 	, m_imageExtent2D	(makeExtent2D(IMAGE_SIZE, IMAGE_SIZE))
510 	, m_parameters		(parameters)
511 	, m_rnd				(context.getTestContext().getCommandLine().getBaseSeed())
512 {
513 	VkPhysicalDeviceProperties2 deviceProperties2;
514 
515 	deMemset(&deviceProperties2, 0, sizeof(deviceProperties2));
516 	deMemset(&m_transformFeedbackProperties, 0, sizeof(m_transformFeedbackProperties));
517 
518 	deviceProperties2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PROPERTIES_2;
519 	deviceProperties2.pNext = &m_transformFeedbackProperties;
520 
521 	m_transformFeedbackProperties.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_TRANSFORM_FEEDBACK_PROPERTIES_EXT;
522 	m_transformFeedbackProperties.pNext = DE_NULL;
523 
524 	context.getInstanceInterface().getPhysicalDeviceProperties2(context.getPhysicalDevice(), &deviceProperties2);
525 
526 	validateLimits();
527 }
528 
validateLimits()529 void TransformFeedbackTestInstance::validateLimits ()
530 {
531 	VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBuffers, 1);
532 	VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferSize, MINIMUM_TF_BUFFER_SIZE);
533 	VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize, 512);
534 	VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize, 512);
535 	VALIDATE_MINIMUM(m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride, 512);
536 
537 	VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackQueries);
538 	VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles);
539 	VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackRasterizationStreamSelect);
540 	VALIDATE_BOOL(m_transformFeedbackProperties.transformFeedbackDraw);
541 }
542 
generateSizesList(const size_t bufBytes,const size_t chunkCount)543 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
544 {
545 	const int					minChunkSlot	= static_cast<int>(1);
546 	const int					maxChunkSlot	= static_cast<int>(bufBytes / sizeof(deUint32));
547 	int							prevOffsetSlot	= 0;
548 	std::map<int, bool>			offsetsSet;
549 	std::vector<VkDeviceSize>	result;
550 
551 	DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
552 	DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
553 	DE_ASSERT(minChunkSlot <= maxChunkSlot);
554 	DE_ASSERT(chunkCount > 0);
555 	// To be effective this algorithm requires that chunkCount is much less than amount of chunks possible
556 	DE_ASSERT(8 * chunkCount <= static_cast<size_t>(maxChunkSlot));
557 
558 	offsetsSet[0] = true;
559 
560 	// Create a list of unique offsets first
561 	for (size_t chunkNdx = 1; chunkNdx < chunkCount; ++chunkNdx)
562 	{
563 		int chunkSlot;
564 
565 		do
566 		{
567 			chunkSlot = m_rnd.getInt(minChunkSlot, maxChunkSlot - 1);
568 		} while (offsetsSet.find(chunkSlot) != offsetsSet.end());
569 
570 		offsetsSet[chunkSlot] = true;
571 	}
572 	offsetsSet[maxChunkSlot] = true;
573 
574 	// Calculate sizes of offsets list
575 	result.reserve(chunkCount);
576 	for (std::map<int, bool>::iterator mapIt = offsetsSet.begin(); mapIt != offsetsSet.end(); ++mapIt)
577 	{
578 		const int offsetSlot = mapIt->first;
579 
580 		if (offsetSlot == 0)
581 			continue;
582 
583 		DE_ASSERT(prevOffsetSlot < offsetSlot && offsetSlot > 0);
584 
585 		result.push_back(static_cast<VkDeviceSize>(static_cast<size_t>(offsetSlot - prevOffsetSlot) * sizeof(deUint32)));
586 
587 		prevOffsetSlot = offsetSlot;
588 	}
589 
590 	DE_ASSERT(result.size() == chunkCount);
591 
592 	return result;
593 }
594 
generateOffsetsList(const std::vector<VkDeviceSize> & sizesList)595 std::vector<VkDeviceSize> TransformFeedbackTestInstance::generateOffsetsList (const std::vector<VkDeviceSize>& sizesList)
596 {
597 	VkDeviceSize				offset	= 0ull;
598 	std::vector<VkDeviceSize>	result;
599 
600 	result.reserve(sizesList.size());
601 
602 	for (size_t chunkNdx = 0; chunkNdx < sizesList.size(); ++chunkNdx)
603 	{
604 		result.push_back(offset);
605 
606 		offset += sizesList[chunkNdx];
607 	}
608 
609 	DE_ASSERT(sizesList.size() == result.size());
610 
611 	return result;
612 }
613 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)614 void TransformFeedbackTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>&	bufAlloc,
615 																   const deUint32				bufBytes)
616 {
617 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
618 	const VkDevice			device		= m_context.getDevice();
619 	const deUint32			numPoints	= static_cast<deUint32>(bufBytes / sizeof(deUint32));
620 	const deUint32*			tfData		= getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
621 
622 	for (deUint32 i = 0; i < numPoints; ++i)
623 		if (tfData[i] != i)
624 			TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
625 }
626 
627 class TransformFeedbackBasicTestInstance : public TransformFeedbackTestInstance
628 {
629 public:
630 						TransformFeedbackBasicTestInstance	(Context& context, const TestParameters& parameters);
631 
632 protected:
633 	tcu::TestStatus		iterate								(void);
634 };
635 
TransformFeedbackBasicTestInstance(Context & context,const TestParameters & parameters)636 TransformFeedbackBasicTestInstance::TransformFeedbackBasicTestInstance (Context& context, const TestParameters& parameters)
637 	: TransformFeedbackTestInstance	(context, parameters)
638 {
639 }
640 
iterate(void)641 tcu::TestStatus TransformFeedbackBasicTestInstance::iterate (void)
642 {
643 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
644 	const VkDevice						device					= m_context.getDevice();
645 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
646 	const VkQueue						queue					= m_context.getUniversalQueue();
647 	Allocator&							allocator				= m_context.getDefaultAllocator();
648 
649 	const Unique<VkShaderModule>		vertexModule			(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
650 	const Unique<VkRenderPass>			renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
651 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
652 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
653 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
654 	const Unique<VkCommandPool>			cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
655 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
656 
657 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
658 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
659 	const MovePtr<Allocation>			tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
660 	const VkMemoryBarrier				tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
661 	const std::vector<VkDeviceSize>		tfBufBindingSizes		= generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
662 	const std::vector<VkDeviceSize>		tfBufBindingOffsets		= generateOffsetsList(tfBufBindingSizes);
663 
664 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
665 
666 	beginCommandBuffer(vk, *cmdBuffer);
667 	{
668 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
669 		{
670 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
671 
672 			for (deUint32 drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
673 			{
674 				const deUint32	startValue	= static_cast<deUint32>(tfBufBindingOffsets[drawNdx] / sizeof(deUint32));
675 				const deUint32	numPoints	= static_cast<deUint32>(tfBufBindingSizes[drawNdx] / sizeof(deUint32));
676 
677 				vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[drawNdx], &tfBufBindingSizes[drawNdx]);
678 
679 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
680 
681 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
682 				{
683 					vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
684 				}
685 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
686 			}
687 		}
688 		endRenderPass(vk, *cmdBuffer);
689 
690 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
691 	}
692 	endCommandBuffer(vk, *cmdBuffer);
693 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
694 
695 	verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
696 
697 	return tcu::TestStatus::pass("Pass");
698 }
699 
700 class TransformFeedbackResumeTestInstance : public TransformFeedbackTestInstance
701 {
702 public:
703 						TransformFeedbackResumeTestInstance	(Context& context, const TestParameters& parameters);
704 
705 protected:
706 	tcu::TestStatus		iterate								(void);
707 };
708 
TransformFeedbackResumeTestInstance(Context & context,const TestParameters & parameters)709 TransformFeedbackResumeTestInstance::TransformFeedbackResumeTestInstance (Context& context, const TestParameters& parameters)
710 	: TransformFeedbackTestInstance	(context, parameters)
711 {
712 }
713 
iterate(void)714 tcu::TestStatus TransformFeedbackResumeTestInstance::iterate (void)
715 {
716 	const DeviceInterface&					vk						= m_context.getDeviceInterface();
717 	const VkDevice							device					= m_context.getDevice();
718 	const deUint32							queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
719 	const VkQueue							queue					= m_context.getUniversalQueue();
720 	Allocator&								allocator				= m_context.getDefaultAllocator();
721 
722 	const Unique<VkShaderModule>			vertexModule			(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
723 	const Unique<VkRenderPass>				renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
724 	const Unique<VkFramebuffer>				framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
725 	const Unique<VkPipelineLayout>			pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
726 	const Unique<VkPipeline>				pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
727 
728 	const Unique<VkCommandPool>				cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
729 	const Unique<VkCommandBuffer>			cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
730 
731 	const VkBufferCreateInfo				tfBufCreateInfo			= makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
732 	const Move<VkBuffer>					tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
733 	const MovePtr<Allocation>				tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
734 	const VkMemoryBarrier					tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
735 	const std::vector<VkDeviceSize>			tfBufBindingSizes		= std::vector<VkDeviceSize>(1, m_parameters.bufferSize);
736 	const std::vector<VkDeviceSize>			tfBufBindingOffsets		= std::vector<VkDeviceSize>(1, 0ull);
737 
738 	const size_t							tfcBufSize				= 16 * sizeof(deUint32) * m_parameters.partCount;
739 	const VkBufferCreateInfo				tfcBufCreateInfo		= makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
740 	const Move<VkBuffer>					tfcBuf					= createBuffer(vk, device, &tfcBufCreateInfo);
741 	const MovePtr<Allocation>				tfcBufAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
742 	const std::vector<VkDeviceSize>			tfcBufBindingOffsets	= generateOffsetsList(generateSizesList(tfcBufSize, m_parameters.partCount));
743 	const VkBufferMemoryBarrier				tfcBufBarrier			= makeBufferMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT, *tfcBuf, 0ull, VK_WHOLE_SIZE);
744 
745 	const std::vector<VkDeviceSize>			chunkSizesList			= generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
746 	const std::vector<VkDeviceSize>			chunkOffsetsList		= generateOffsetsList(chunkSizesList);
747 
748 	DE_ASSERT(tfBufBindingSizes.size() == 1);
749 	DE_ASSERT(tfBufBindingOffsets.size() == 1);
750 
751 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
752 	VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
753 
754 	beginCommandBuffer(vk, *cmdBuffer);
755 	{
756 		for (size_t drawNdx = 0; drawNdx < m_parameters.partCount; ++drawNdx)
757 		{
758 			const deUint32	startValue = static_cast<deUint32>(chunkOffsetsList[drawNdx] / sizeof(deUint32));
759 			const deUint32	numPoints = static_cast<deUint32>(chunkSizesList[drawNdx] / sizeof(deUint32));
760 			const deUint32	countBuffersCount = (drawNdx == 0) ? 0 : 1;
761 
762 			beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
763 			{
764 
765 				vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
766 
767 				vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
768 
769 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
770 
771 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, countBuffersCount, (drawNdx == 0) ? DE_NULL : &*tfcBuf, (drawNdx == 0) ? DE_NULL : &tfcBufBindingOffsets[drawNdx - 1]);
772 				{
773 					vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
774 				}
775 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, &tfcBufBindingOffsets[drawNdx]);
776 			}
777 			endRenderPass(vk, *cmdBuffer);
778 
779 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 0u, DE_NULL, 1u, &tfcBufBarrier, 0u, DE_NULL);
780 		}
781 
782 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
783 	}
784 	endCommandBuffer(vk, *cmdBuffer);
785 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
786 
787 	verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
788 
789 	return tcu::TestStatus::pass("Pass");
790 }
791 
792 class TransformFeedbackWindingOrderTestInstance : public TransformFeedbackTestInstance
793 {
794 public:
795 	TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters);
796 
797 protected:
798 	struct TopologyParameters
799 	{
800 		// number of vertex in primitive; 2 for line, 3 for triangle
801 		deUint32 vertexPerPrimitive;
802 
803 		// pointer to function calculating number of points that
804 		// will be generated for given part count
805 		std::function<deUint32(deUint32)> getNumGeneratedPoints;
806 
807 		// pointer to function generating expected values; parameter is
808 		// primitive index, result array with expected data for primitive vertex
809 		std::function<std::vector<deUint32>(deUint32)> getExpectedValuesForPrimitive;
810 	};
811 	typedef const std::map<VkPrimitiveTopology, TopologyParameters> TopologyParametersMap;
812 
813 protected:
814 	const TopologyParametersMap&	getTopologyParametersMap					(void);
815 	tcu::TestStatus					iterate										(void);
816 	void							verifyTransformFeedbackBuffer				(const MovePtr<Allocation>& bufAlloc,
817 																				 const deUint32 bufBytes);
818 
819 private:
820 	TopologyParameters				m_tParameters;
821 	const bool						m_requiresTesselationStage;
822 };
823 
TransformFeedbackWindingOrderTestInstance(Context & context,const TestParameters & parameters)824 TransformFeedbackWindingOrderTestInstance::TransformFeedbackWindingOrderTestInstance(Context& context, const TestParameters& parameters)
825 	: TransformFeedbackTestInstance	(context, parameters)
826 	, m_requiresTesselationStage(parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
827 {
828 	if (m_requiresTesselationStage && !context.getDeviceFeatures().tessellationShader)
829 		throw tcu::NotSupportedError("Tessellation shader not supported");
830 
831 	TopologyParametersMap topologyParametersMap = getTopologyParametersMap();
832 	DE_ASSERT(topologyParametersMap.find(parameters.primTopology) != topologyParametersMap.end());
833 	m_tParameters = topologyParametersMap.at(parameters.primTopology);
834 }
835 
getTopologyParametersMap(void)836 const TransformFeedbackWindingOrderTestInstance::TopologyParametersMap& TransformFeedbackWindingOrderTestInstance::getTopologyParametersMap(void)
837 {
838 	static const TopologyParametersMap topologyParametersMap =
839 	{
840 		{
841 			VK_PRIMITIVE_TOPOLOGY_POINT_LIST,
842 			{
843 				1u,
844 				[](deUint32 partCount)	{	return partCount;	},
845 				[](deUint32 i)			{	return std::vector<deUint32>{ i, i + 1u };	}
846 			}
847 		},
848 		{
849 			VK_PRIMITIVE_TOPOLOGY_LINE_LIST,
850 			{
851 				2u,
852 				[](deUint32 partCount)	{	return partCount;	},
853 				[](deUint32 i)			{	return std::vector<deUint32>{ 2 * i, 2 * i + 1u };	}
854 			}
855 		},
856 		{
857 			VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,
858 			{
859 				2u,
860 				[](deUint32 partCount)	{	return 2u * (partCount - 1);	},
861 				[](deUint32 i)			{	return std::vector<deUint32>{ i, i + 1u };	}
862 			}
863 		},
864 		{
865 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,
866 			{
867 				3u,
868 				[](deUint32 partCount)	{	return partCount;	},
869 				[](deUint32 i)			{	return std::vector<deUint32>{ 3 * i, 3 * i + 1u, 3 * i + 2u };	}
870 			}
871 		},
872 		{
873 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,
874 			{
875 				3u,
876 				[](deUint32 partCount)	{	return 3u * (partCount - 2);	},
877 				[](deUint32 i)
878 				{
879 					const deUint32	iMod2 = i % 2;
880 					return std::vector<deUint32>{ i, i + 1 + iMod2, i + 2 - iMod2 };
881 				}
882 			}
883 		},
884 		{
885 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,
886 			{
887 				3u,
888 				[](deUint32 partCount)	{	return partCount;	},
889 				[](deUint32 i)			{	return std::vector<deUint32>{ i + 1, i + 2, 0 };	}
890 			}
891 		},
892 		{
893 			VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,
894 			{
895 				2u,
896 				[](deUint32 partCount)	{	return partCount / 4u;	},		// note: this cant be replaced with partCount / 2 as for partCount=6 we will get 3 instead of 2
897 				[](deUint32 i)			{	return std::vector<deUint32>{ i + 1u, i + 2u };	}
898 			}
899 		},
900 		{
901 			VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,
902 			{
903 				2u,
904 				[](deUint32 partCount)	{	return 2u * (partCount - 3u);	},
905 				[](deUint32 i)			{	return std::vector<deUint32>{ i + 1u, i + 2u };	}
906 			}
907 		},
908 		{
909 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,
910 			{
911 				3u,
912 				[](deUint32 partCount)	{	return partCount / 2u;	},
913 				[](deUint32 i)			{	return std::vector<deUint32>{ 6 * i, 6 * i + 2u, 6 * i + 4u	};	}
914 			}
915 		},
916 		{
917 			VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,
918 			{
919 				3u,
920 				[](deUint32 partCount)	{	return 3u * (partCount / 2u - 2u);	},
921 				[](deUint32 i)
922 				{
923 					const bool even = (0 == i % 2);
924 					if (even)
925 						return std::vector<deUint32>{ 2 * i + 0, 2 * i + 2, 2 * i + 4 };
926 					return std::vector<deUint32>{ 2 * i + 0, 2 * i + 4, 2 * i + 2 };
927 				}
928 			}
929 		},
930 		{
931 			VK_PRIMITIVE_TOPOLOGY_PATCH_LIST,
932 			{
933 				9u,
934 				[](deUint32 partCount)	{	return partCount * 3u;	},
935 				[](deUint32 i)
936 				{
937 					// we cant generate vertex numbers in tesselation evaluation shader;
938 					// check if patch index is correct for every 9 generated vertex
939 					return std::vector<deUint32>(9, i);
940 				}
941 			}
942 		}
943 	};
944 
945 	return topologyParametersMap;
946 }
947 
iterate(void)948 tcu::TestStatus TransformFeedbackWindingOrderTestInstance::iterate (void)
949 {
950 	DE_ASSERT(m_parameters.partCount >= 6);
951 
952 	const DeviceInterface&			vk					= m_context.getDeviceInterface();
953 	const VkDevice					device				= m_context.getDevice();
954 	const deUint32					queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
955 	const VkQueue					queue				= m_context.getUniversalQueue();
956 	Allocator&						allocator			= m_context.getDefaultAllocator();
957 
958 	const Move<VkShaderModule>		vertexModule(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
959 	Move<VkShaderModule>			tescModule;
960 	Move<VkShaderModule>			teseModule;
961 	if (m_requiresTesselationStage)
962 	{
963 		tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
964 		teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
965 	}
966 
967 	const Unique<VkRenderPass>		renderPass			(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
968 	const Unique<VkFramebuffer>		framebuffer			(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
969 	const Unique<VkPipelineLayout>	pipelineLayout		(TransformFeedback::makePipelineLayout	(vk, device));
970 	const Unique<VkPipeline>		pipeline			(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass,
971 																								 *vertexModule,
972 																								 m_requiresTesselationStage ? *tescModule : DE_NULL,
973 																								 m_requiresTesselationStage ? *teseModule : DE_NULL,
974 																								 DE_NULL,
975 																								 DE_NULL,
976 																								 m_imageExtent2D, 0u, DE_NULL, m_parameters.primTopology));
977 	const Unique<VkCommandPool>		cmdPool				(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
978 	const Unique<VkCommandBuffer>	cmdBuffer			(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
979 	const VkDeviceSize				bufferSize			= m_tParameters.getNumGeneratedPoints	(m_parameters.partCount) * sizeof(deUint32);
980 	const VkBufferCreateInfo		tfBufCreateInfo		= makeBufferCreateInfo					(bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
981 	const Move<VkBuffer>			tfBuf				= createBuffer							(vk, device, &tfBufCreateInfo);
982 	const MovePtr<Allocation>		tfBufAllocation		= allocator.allocate					(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
983 	const VkMemoryBarrier			tfMemoryBarrier		= makeMemoryBarrier						(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
984 	const VkDeviceSize				tfBufBindingSize	= bufferSize;
985 	const VkDeviceSize				tfBufBindingOffset	= 0u;
986 	const deUint32					startValue			= 0u;
987 
988 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
989 
990 	beginCommandBuffer(vk, *cmdBuffer);
991 	{
992 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
993 		{
994 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
995 
996 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
997 
998 			vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
999 
1000 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1001 			{
1002 				vk.cmdDraw(*cmdBuffer, m_parameters.partCount, 1u, 0u, 0u);
1003 			}
1004 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1005 		}
1006 		endRenderPass(vk, *cmdBuffer);
1007 
1008 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1009 	}
1010 	endCommandBuffer(vk, *cmdBuffer);
1011 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1012 
1013 	verifyTransformFeedbackBuffer(tfBufAllocation, static_cast<deUint32>(bufferSize));
1014 
1015 	return tcu::TestStatus::pass("Pass");
1016 }
1017 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)1018 void TransformFeedbackWindingOrderTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>&	bufAlloc,
1019 																			   const deUint32				bufBytes)
1020 {
1021 	const DeviceInterface&	vk					= m_context.getDeviceInterface();
1022 	const VkDevice			device				= m_context.getDevice();
1023 	const deUint32			numPoints			= static_cast<deUint32>(bufBytes / sizeof(deUint32));
1024 	const deUint32			vertexPerPrimitive	= m_tParameters.vertexPerPrimitive;
1025 	const deUint32			numPrimitives		= numPoints / vertexPerPrimitive;
1026 	const deUint32*			tfData				= getInvalidatedHostPtr<deUint32>(vk, device, *bufAlloc);
1027 
1028 	for (deUint32 primitiveIndex = 0; primitiveIndex < numPrimitives; ++primitiveIndex)
1029 	{
1030 		const deUint32*			tfDataForPrimitive			= &tfData[primitiveIndex * vertexPerPrimitive];
1031 		std::vector<deUint32>	expectedDataForPrimitive	= m_tParameters.getExpectedValuesForPrimitive(primitiveIndex);
1032 
1033 		// For multi - vertex primitives, all values for a given vertex are written before writing values for any other vertex.
1034 		// Implementations may write out any vertex within the primitive first, but all subsequent vertices for that primitive
1035 		// must be written out in a consistent winding order
1036 		bool correctWinding = true;
1037 		for (deUint32 combinationIndex = 0; combinationIndex < vertexPerPrimitive; combinationIndex++)
1038 		{
1039 			correctWinding = true;
1040 			for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1041 			{
1042 				correctWinding &= (tfDataForPrimitive[vertexIndex] == expectedDataForPrimitive[(combinationIndex + vertexIndex) % vertexPerPrimitive]);
1043 
1044 				// if data for this vertex is not correct then there
1045 				// is no need to check other, go to next combination
1046 				if (!correctWinding)
1047 					break;
1048 			}
1049 
1050 			// no need to check other combinations, we found correct one
1051 			if (correctWinding)
1052 				break;
1053 		}
1054 
1055 		if (!correctWinding)
1056 		{
1057 			std::stringstream message;
1058 			message << "Failed at primitive " << primitiveIndex << " received: [";
1059 			for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1060 				message << de::toString(tfDataForPrimitive[vertexIndex]) << " ";
1061 			message << "] expected: [";
1062 			for (deUint32 vertexIndex = 0; vertexIndex < vertexPerPrimitive; vertexIndex++)
1063 				message << de::toString(expectedDataForPrimitive[vertexIndex]) << " ";
1064 			message << "]";
1065 			TCU_FAIL(message.str());
1066 		}
1067 	}
1068 }
1069 
1070 class TransformFeedbackBuiltinTestInstance : public TransformFeedbackTestInstance
1071 {
1072 public:
1073 						TransformFeedbackBuiltinTestInstance	(Context& context, const TestParameters& parameters);
1074 
1075 protected:
1076 	tcu::TestStatus		iterate									(void);
1077 	void				verifyTransformFeedbackBuffer			(const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1078 };
1079 
TransformFeedbackBuiltinTestInstance(Context & context,const TestParameters & parameters)1080 TransformFeedbackBuiltinTestInstance::TransformFeedbackBuiltinTestInstance (Context& context, const TestParameters& parameters)
1081 	: TransformFeedbackTestInstance	(context, parameters)
1082 {
1083 	const InstanceInterface&		vki			= m_context.getInstanceInterface();
1084 	const VkPhysicalDevice			physDevice	= m_context.getPhysicalDevice();
1085 	const VkPhysicalDeviceFeatures	features	= getPhysicalDeviceFeatures(vki, physDevice);
1086 
1087 	const deUint32 tfBuffersSupported	= m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1088 	const deUint32 tfBuffersRequired	= m_parameters.partCount;
1089 
1090 	if ((m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderClipDistance)
1091 		TCU_THROW(NotSupportedError, std::string("shaderClipDistance feature is not supported"));
1092 	if ((m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE || m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) && !features.shaderCullDistance)
1093 		TCU_THROW(NotSupportedError, std::string("shaderCullDistance feature is not supported"));
1094 	if (tfBuffersSupported < tfBuffersRequired)
1095 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1096 }
1097 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const VkDeviceSize offset,const deUint32 bufBytes)1098 void TransformFeedbackBuiltinTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1099 {
1100 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1101 	const VkDevice			device		= m_context.getDevice();
1102 	const deUint32			numPoints	= bufBytes / static_cast<deUint32>(sizeof(float));
1103 	const deUint8*			tfDataBytes	= getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1104 	const float*			tfData		= (float*)&tfDataBytes[offset];
1105 
1106 	for (deUint32 i = 0; i < numPoints; ++i)
1107 	{
1108 		const deUint32	divisor		= 32768u;
1109 		const float		epsilon		= 1.0f / float(divisor);
1110 		const float		expected	= float(i) / float(divisor);
1111 
1112 		if (deAbs(tfData[i] - expected) > epsilon)
1113 			TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
1114 	}
1115 }
1116 
iterate(void)1117 tcu::TestStatus TransformFeedbackBuiltinTestInstance::iterate (void)
1118 {
1119 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
1120 	const VkDevice						device					= m_context.getDevice();
1121 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1122 	const VkQueue						queue					= m_context.getUniversalQueue();
1123 	Allocator&							allocator				= m_context.getDefaultAllocator();
1124 
1125 	const Unique<VkShaderModule>		vertexModule			(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1126 	const Unique<VkRenderPass>			renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
1127 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1128 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
1129 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1130 	const Unique<VkCommandPool>			cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1131 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1132 
1133 	const VkDeviceSize					tfBufSize				= m_parameters.bufferSize * m_parameters.partCount;
1134 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1135 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
1136 	const std::vector<VkBuffer>			tfBufArray				= std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1137 	const MovePtr<Allocation>			tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1138 	const VkMemoryBarrier				tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1139 	const std::vector<VkDeviceSize>		tfBufBindingSizes		= std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1140 	const std::vector<VkDeviceSize>		tfBufBindingOffsets		= generateOffsetsList(tfBufBindingSizes);
1141 	const deUint32						perVertexDataSize		= (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)    ? static_cast<deUint32>(sizeof(float))
1142 																: (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1143 																: (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE) ? static_cast<deUint32>(8u * sizeof(float))
1144 																: (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? static_cast<deUint32>(6u * sizeof(float))
1145 																: 0u;
1146 	const deUint32						numPoints				= m_parameters.bufferSize / perVertexDataSize;
1147 
1148 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1149 
1150 	beginCommandBuffer(vk, *cmdBuffer);
1151 	{
1152 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1153 		{
1154 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1155 
1156 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1157 
1158 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1159 			{
1160 				vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1161 			}
1162 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1163 		}
1164 		endRenderPass(vk, *cmdBuffer);
1165 
1166 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1167 	}
1168 	endCommandBuffer(vk, *cmdBuffer);
1169 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1170 
1171 	verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], numPoints * perVertexDataSize);
1172 
1173 	return tcu::TestStatus::pass("Pass");
1174 }
1175 
1176 class TransformFeedbackDepthClipControlTestInstance : public TransformFeedbackTestInstance
1177 {
1178 public:
1179 	TransformFeedbackDepthClipControlTestInstance		(Context& context, const TestParameters& parameters);
1180 
1181 protected:
1182 	tcu::TestStatus		iterate							(void);
1183 	void				verifyTransformFeedbackBuffer	(const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes);
1184 };
1185 
TransformFeedbackDepthClipControlTestInstance(Context & context,const TestParameters & parameters)1186 TransformFeedbackDepthClipControlTestInstance::TransformFeedbackDepthClipControlTestInstance (Context& context, const TestParameters& parameters)
1187 		: TransformFeedbackTestInstance	(context, parameters)
1188 {
1189 	const InstanceInterface&		vki			= m_context.getInstanceInterface();
1190 	const VkPhysicalDevice			physDevice	= m_context.getPhysicalDevice();
1191 	const VkPhysicalDeviceFeatures	features	= getPhysicalDeviceFeatures(vki, physDevice);
1192 
1193 	const deUint32 tfBuffersSupported	= m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1194 	const deUint32 tfBuffersRequired	= m_parameters.partCount;
1195 
1196 	if (!context.isDeviceFunctionalitySupported("VK_EXT_depth_clip_control"))
1197 		TCU_THROW(NotSupportedError, "VK_EXT_depth_clip_control is not supported");
1198 
1199 	if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY && !features.geometryShader)
1200 		TCU_THROW(NotSupportedError, "Geometry shader not supported");
1201 
1202 	if (parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE && !features.tessellationShader)
1203 		TCU_THROW(NotSupportedError, "Tessellation shader not supported");
1204 
1205 	if (tfBuffersSupported < tfBuffersRequired)
1206 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1207 }
1208 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const VkDeviceSize offset,const deUint32 bufBytes)1209 void TransformFeedbackDepthClipControlTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const VkDeviceSize offset, const deUint32 bufBytes)
1210 {
1211 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1212 	const VkDevice			device		= m_context.getDevice();
1213 	const deUint32			numVertices	= bufBytes / static_cast<deUint32>(sizeof(float) * 4);
1214 	const deUint8*			tfDataBytes	= getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
1215 	const float*			tfData		= (float*)&tfDataBytes[offset];
1216 	std::vector<float>		result;
1217 
1218 	// We only care about the depth (z) value.
1219 	for (deUint32 i = 0; i < numVertices; i++)
1220 		result.push_back(tfData[i * 4 + 2]);
1221 
1222 	// Tessellation generates triangles whose vertex data might be written into
1223 	// transform feedback buffer in a different order than generated by the vertex
1224 	// shader. Sort the values here to allow comparison.
1225 	if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
1226 	{
1227 		std::sort(result.begin(), result.end());
1228 	}
1229 
1230 	// Verify the vertex depth values match with the ones written by the shader.
1231 	for (deUint32 i = 0; i < numVertices; i++)
1232 	{
1233 		const float	expected	= (float)i / 3.0f - 1.0f;
1234 		const float	epsilon		= 0.0001f;
1235 
1236 		if (deAbs(result[i] - expected) > epsilon)
1237 			TCU_FAIL(std::string("Failed at vertex ") + de::toString(i) + " depth. Received:" + de::toString(result[i]) + " expected:" + de::toString(expected));
1238 	}
1239 }
1240 
iterate(void)1241 tcu::TestStatus TransformFeedbackDepthClipControlTestInstance::iterate (void)
1242 {
1243 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
1244 	const VkDevice						device					= m_context.getDevice();
1245 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1246 	const VkQueue						queue					= m_context.getUniversalQueue();
1247 	Allocator&							allocator				= m_context.getDefaultAllocator();
1248 
1249 	const Unique<VkShaderModule>		vertexModule			(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1250 	Move<VkShaderModule>				geomModule;
1251 	Move<VkShaderModule>				tescModule;
1252 	Move<VkShaderModule>				teseModule;
1253 	const bool							hasGeomShader			= m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY;
1254 	const bool							hasTessellation			= m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE;
1255 
1256 	if (hasGeomShader)
1257 		geomModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("geom"), 0u);
1258 
1259 	if (hasTessellation)
1260 	{
1261 		tescModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tesc"), 0u);
1262 		teseModule = createShaderModule(vk, device, m_context.getBinaryCollection().get("tese"), 0u);
1263 	}
1264 
1265 	const Unique<VkRenderPass>			renderPass				(makeRenderPass(vk, device, VK_FORMAT_UNDEFINED));
1266 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1267 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
1268 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline(vk, device, *pipelineLayout, *renderPass, *vertexModule, hasTessellation ? *tescModule : DE_NULL, hasTessellation ? *teseModule : DE_NULL, hasGeomShader ? *geomModule : DE_NULL, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId, m_parameters.primTopology, false, true));
1269 	const Unique<VkCommandPool>			cmdPool					(createCommandPool(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1270 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1271 	const VkDeviceSize					tfBufSize				= m_parameters.bufferSize * m_parameters.partCount;
1272 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(tfBufSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1273 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
1274 	const std::vector<VkBuffer>			tfBufArray				= std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1275 	const MovePtr<Allocation>			tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1276 	const VkMemoryBarrier				tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1277 	const std::vector<VkDeviceSize>		tfBufBindingSizes		= std::vector<VkDeviceSize>(m_parameters.partCount, m_parameters.bufferSize);
1278 	const std::vector<VkDeviceSize>		tfBufBindingOffsets		= generateOffsetsList(tfBufBindingSizes);
1279 	const deUint32						perVertexDataSize		= static_cast<deUint32>(4u * sizeof(float));
1280 	const deUint32						numVertices				= m_parameters.bufferSize / perVertexDataSize;
1281 
1282 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1283 
1284 	beginCommandBuffer(vk, *cmdBuffer);
1285 	{
1286 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1287 		{
1288 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1289 
1290 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1291 
1292 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1293 			{
1294 				vk.cmdDraw(*cmdBuffer, numVertices, 1u, 0u, 0u);
1295 			}
1296 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1297 		}
1298 		endRenderPass(vk, *cmdBuffer);
1299 
1300 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1301 	}
1302 	endCommandBuffer(vk, *cmdBuffer);
1303 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1304 
1305 	verifyTransformFeedbackBuffer(tfBufAllocation, tfBufBindingOffsets[m_parameters.partCount - 1], m_parameters.bufferSize);
1306 
1307 	return tcu::TestStatus::pass("Pass");
1308 }
1309 
1310 class TransformFeedbackMultistreamTestInstance : public TransformFeedbackTestInstance
1311 {
1312 public:
1313 								TransformFeedbackMultistreamTestInstance	(Context& context, const TestParameters& parameters);
1314 
1315 protected:
1316 	std::vector<VkDeviceSize>	generateSizesList							(const size_t bufBytes, const size_t chunkCount);
1317 	void						verifyTransformFeedbackBuffer				(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes);
1318 	tcu::TestStatus				iterate										(void);
1319 };
1320 
TransformFeedbackMultistreamTestInstance(Context & context,const TestParameters & parameters)1321 TransformFeedbackMultistreamTestInstance::TransformFeedbackMultistreamTestInstance (Context& context, const TestParameters& parameters)
1322 	: TransformFeedbackTestInstance	(context, parameters)
1323 {
1324 	const InstanceInterface&								vki							= m_context.getInstanceInterface();
1325 	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
1326 	const VkPhysicalDeviceFeatures							features					= getPhysicalDeviceFeatures(vki, physDevice);
1327 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
1328 	const deUint32											streamsSupported			= m_transformFeedbackProperties.maxTransformFeedbackStreams;
1329 	const deUint32											streamsRequired				= m_parameters.streamId + 1;
1330 	const deUint32											tfBuffersSupported			= m_transformFeedbackProperties.maxTransformFeedbackBuffers;
1331 	const deUint32											tfBuffersRequired			= m_parameters.partCount;
1332 	const deUint32											bytesPerVertex				= m_parameters.bufferSize / m_parameters.partCount;
1333 	const deUint32											tfStreamDataSizeSupported	= m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
1334 	const deUint32											tfBufferDataSizeSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1335 	const deUint32											tfBufferDataStrideSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1336 
1337 	DE_ASSERT(m_parameters.partCount == 2u);
1338 
1339 	if (!features.geometryShader)
1340 		TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1341 
1342 	if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1343 		TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1344 
1345 	if (streamsSupported < streamsRequired)
1346 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1347 
1348 	if (tfBuffersSupported < tfBuffersRequired)
1349 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
1350 
1351 	if (tfStreamDataSizeSupported < bytesPerVertex)
1352 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1353 
1354 	if (tfBufferDataSizeSupported < bytesPerVertex)
1355 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1356 
1357 	if (tfBufferDataStrideSupported < bytesPerVertex)
1358 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
1359 }
1360 
generateSizesList(const size_t bufBytes,const size_t chunkCount)1361 std::vector<VkDeviceSize> TransformFeedbackMultistreamTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1362 {
1363 	const VkDeviceSize			chunkSize	= bufBytes / chunkCount;
1364 	std::vector<VkDeviceSize>	result		(chunkCount, chunkSize);
1365 
1366 	DE_ASSERT(chunkSize * chunkCount == bufBytes);
1367 	DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1368 	DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1369 	DE_ASSERT(chunkCount > 0);
1370 	DE_ASSERT(result.size() == chunkCount);
1371 
1372 	return result;
1373 }
1374 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes)1375 void TransformFeedbackMultistreamTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes)
1376 {
1377 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
1378 	const VkDevice			device		= m_context.getDevice();
1379 	const deUint32			numPoints	= static_cast<deUint32>(bufBytes / sizeof(deUint32));
1380 	const float*			tfData		= getInvalidatedHostPtr<float>(vk, device, *bufAlloc);
1381 
1382 	for (deUint32 i = 0; i < numPoints; ++i)
1383 		if (tfData[i] != float(i))
1384 			TCU_FAIL(std::string("Failed at item ") + de::toString(float(i)) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(i));
1385 }
1386 
iterate(void)1387 tcu::TestStatus TransformFeedbackMultistreamTestInstance::iterate (void)
1388 {
1389 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
1390 	const VkDevice						device					= m_context.getDevice();
1391 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1392 	const VkQueue						queue					= m_context.getUniversalQueue();
1393 	Allocator&							allocator				= m_context.getDefaultAllocator();
1394 
1395 	const Unique<VkRenderPass>			renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
1396 
1397 	const Unique<VkShaderModule>		vertexModule			(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1398 	const Unique<VkShaderModule>		geomModule				(createShaderModule						(vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1399 
1400 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1401 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
1402 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
1403 	const Unique<VkCommandPool>			cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1404 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1405 
1406 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1407 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
1408 	const std::vector<VkBuffer>			tfBufArray				= std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
1409 	const MovePtr<Allocation>			tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1410 	const VkMemoryBarrier				tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1411 	const std::vector<VkDeviceSize>		tfBufBindingSizes		= generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1412 	const std::vector<VkDeviceSize>		tfBufBindingOffsets		= generateOffsetsList(tfBufBindingSizes);
1413 
1414 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1415 
1416 	beginCommandBuffer(vk, *cmdBuffer);
1417 	{
1418 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1419 		{
1420 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1421 
1422 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
1423 
1424 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1425 			{
1426 				vk.cmdDraw(*cmdBuffer, 1u, 1u, 0u, 0u);
1427 			}
1428 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1429 		}
1430 		endRenderPass(vk, *cmdBuffer);
1431 
1432 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1433 	}
1434 	endCommandBuffer(vk, *cmdBuffer);
1435 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1436 
1437 	verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1438 
1439 	return tcu::TestStatus::pass("Pass");
1440 }
1441 
1442 class TransformFeedbackStreamsTestInstance : public TransformFeedbackTestInstance
1443 {
1444 public:
1445 						TransformFeedbackStreamsTestInstance	(Context& context, const TestParameters& parameters);
1446 
1447 protected:
1448 	tcu::TestStatus		iterate									(void);
1449 	bool				verifyImage								(const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1450 };
1451 
TransformFeedbackStreamsTestInstance(Context & context,const TestParameters & parameters)1452 TransformFeedbackStreamsTestInstance::TransformFeedbackStreamsTestInstance (Context& context, const TestParameters& parameters)
1453 	: TransformFeedbackTestInstance	(context, parameters)
1454 {
1455 	const InstanceInterface&								vki							= m_context.getInstanceInterface();
1456 	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
1457 	const VkPhysicalDeviceFeatures							features					= getPhysicalDeviceFeatures(vki, physDevice);
1458 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
1459 	const deUint32											streamsSupported			= m_transformFeedbackProperties.maxTransformFeedbackStreams;
1460 	const deUint32											streamsRequired				= m_parameters.streamId + 1;
1461 	const bool												geomPointSizeRequired		= m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE;
1462 
1463 	if (!features.geometryShader)
1464 		TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1465 
1466 	if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
1467 		TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1468 
1469 	if (streamsSupported < streamsRequired)
1470 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1471 
1472 	if (geomPointSizeRequired && !features.shaderTessellationAndGeometryPointSize)
1473 		TCU_THROW(NotSupportedError, "shaderTessellationAndGeometryPointSize feature is not supported");
1474 }
1475 
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1476 bool TransformFeedbackStreamsTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1477 {
1478 	const tcu::RGBA				magentaRGBA		(tcu::RGBA(0xFF, 0x00, 0xFF, 0xFF));
1479 	const tcu::Vec4				magenta			(magentaRGBA.toVec());
1480 	const tcu::Vec4				black			(tcu::RGBA::black().toVec());
1481 	const tcu::TextureFormat	textureFormat	(mapVkFormat(imageFormat));
1482 	const int					dataSize		(size.width * size.height * textureFormat.getPixelSize());
1483 	tcu::TextureLevel			referenceImage	(textureFormat, size.width, size.height);
1484 	tcu::PixelBufferAccess		referenceAccess	(referenceImage.getAccess());
1485 
1486 	// Generate reference image
1487 	if (m_parameters.testType == TEST_TYPE_STREAMS)
1488 	{
1489 		for (int y = 0; y < referenceImage.getHeight(); ++y)
1490 		{
1491 			const tcu::Vec4&	validColor = y < referenceImage.getHeight() / 2 ? black : magenta;
1492 
1493 			for (int x = 0; x < referenceImage.getWidth(); ++x)
1494 				referenceAccess.setPixel(validColor, x, y);
1495 		}
1496 	}
1497 
1498 	if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE || m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
1499 	{
1500 		for (int y = 0; y < referenceImage.getHeight(); ++y)
1501 			for (int x = 0; x < referenceImage.getWidth(); ++x)
1502 			{
1503 				const tcu::Vec4&	validColor	= (y >= referenceImage.getHeight() / 2) && (x >= referenceImage.getWidth() / 2) ? magenta : black;
1504 
1505 				referenceAccess.setPixel(validColor, x, y);
1506 			}
1507 	}
1508 
1509 	if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
1510 	{
1511 		const int			pointSize	= static_cast<int>(m_parameters.pointSize);
1512 		const tcu::Vec4&	validColor	= black;
1513 
1514 		for (int y = 0; y < referenceImage.getHeight(); ++y)
1515 			for (int x = 0; x < referenceImage.getWidth(); ++x)
1516 				referenceAccess.setPixel(validColor, x, y);
1517 
1518 		referenceAccess.setPixel(magenta, (1 + referenceImage.getWidth()) / 4 - 1, (referenceImage.getHeight() * 3) / 4 - 1);
1519 
1520 		for (int y = 0; y < pointSize; ++y)
1521 			for (int x = 0; x < pointSize; ++x)
1522 				referenceAccess.setPixel(magenta, x + (referenceImage.getWidth() * 3) / 4 - 1, y + (referenceImage.getHeight() * 3) / 4 - 1);
1523 	}
1524 
1525 	if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1526 	{
1527 		const tcu::ConstPixelBufferAccess	resultImage	(textureFormat, size.width, size.height, 1, resultData);
1528 		bool								ok;
1529 
1530 		ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1531 
1532 		return ok;
1533 	}
1534 
1535 	return true;
1536 }
1537 
iterate(void)1538 tcu::TestStatus TransformFeedbackStreamsTestInstance::iterate (void)
1539 {
1540 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
1541 	const VkDevice						device				= m_context.getDevice();
1542 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1543 	const VkQueue						queue				= m_context.getUniversalQueue();
1544 	Allocator&							allocator			= m_context.getDefaultAllocator();
1545 
1546 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1547 
1548 	const Unique<VkShaderModule>		vertModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1549 	const Unique<VkShaderModule>		geomModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1550 	const Unique<VkShaderModule>		fragModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1551 
1552 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1553 	const VkImageUsageFlags				imageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1554 	const tcu::RGBA						clearColor			(tcu::RGBA::black());
1555 	const VkImageSubresourceRange		colorSubresRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1556 	const VkDeviceSize					colorBufferSize		(m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1557 	const Unique<VkImage>				colorImage			(makeImage								(vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1558 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage								(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1559 	const Unique<VkImageView>			colorAttachment		(makeImageView							(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1560 	const Unique<VkBuffer>				colorBuffer			(makeBuffer								(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1561 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer								(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1562 
1563 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer						(vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1564 	const Unique<VkPipelineLayout>		pipelineLayout		(TransformFeedback::makePipelineLayout	(vk, device));
1565 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, *fragModule, m_imageExtent2D, 0u, &m_parameters.streamId));
1566 	const Unique<VkCommandPool>			cmdPool				(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1567 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1568 
1569 	const VkImageMemoryBarrier			preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1570 																					 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1571 																					 *colorImage, colorSubresRange);
1572 	const VkBufferImageCopy				region				= makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1573 																				  makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1574 	const VkBufferMemoryBarrier			postCopyBarrier		= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1575 
1576 	beginCommandBuffer(vk, *cmdBuffer);
1577 	{
1578 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1579 		{
1580 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1581 
1582 			vk.cmdDraw(*cmdBuffer, 2u, 1u, 0u, 0u);
1583 		}
1584 		endRenderPass(vk, *cmdBuffer);
1585 
1586 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1587 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1588 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1589 
1590 		invalidateAlloc(vk, device, *colorBufferAlloc);
1591 	}
1592 	endCommandBuffer(vk, *cmdBuffer);
1593 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1594 
1595 	if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1596 		return tcu::TestStatus::fail("Fail");
1597 
1598 	return tcu::TestStatus::pass("Pass");
1599 }
1600 
1601 class TransformFeedbackIndirectDrawTestInstance : public TransformFeedbackTestInstance
1602 {
1603 public:
1604 						TransformFeedbackIndirectDrawTestInstance	(Context& context, const TestParameters& parameters);
1605 
1606 protected:
1607 	tcu::TestStatus		iterate										(void);
1608 	bool				verifyImage									(const VkFormat imageFormat, const VkExtent2D& size, const void* resultData);
1609 };
1610 
TransformFeedbackIndirectDrawTestInstance(Context & context,const TestParameters & parameters)1611 TransformFeedbackIndirectDrawTestInstance::TransformFeedbackIndirectDrawTestInstance (Context& context, const TestParameters& parameters)
1612 	: TransformFeedbackTestInstance	(context, parameters)
1613 {
1614 	const InstanceInterface&		vki							= m_context.getInstanceInterface();
1615 	const VkPhysicalDevice			physDevice					= m_context.getPhysicalDevice();
1616 	const VkPhysicalDeviceLimits	limits						= getPhysicalDeviceProperties(vki, physDevice).limits;
1617 	const deUint32					tfBufferDataSizeSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
1618 	const deUint32					tfBufferDataStrideSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
1619 
1620 	if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1621 		TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1622 
1623 	if (limits.maxVertexInputBindingStride < m_parameters.vertexStride)
1624 		TCU_THROW(NotSupportedError, std::string("maxVertexInputBindingStride=" + de::toString(limits.maxVertexInputBindingStride) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1625 
1626 	if (tfBufferDataSizeSupported < m_parameters.vertexStride)
1627 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1628 
1629 	if (tfBufferDataStrideSupported < m_parameters.vertexStride)
1630 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(m_parameters.vertexStride)).c_str());
1631 }
1632 
verifyImage(const VkFormat imageFormat,const VkExtent2D & size,const void * resultData)1633 bool TransformFeedbackIndirectDrawTestInstance::verifyImage (const VkFormat imageFormat, const VkExtent2D& size, const void* resultData)
1634 {
1635 	const tcu::Vec4				white			(tcu::RGBA::white().toVec());
1636 	const tcu::TextureFormat	textureFormat	(mapVkFormat(imageFormat));
1637 	const int					dataSize		(size.width * size.height * textureFormat.getPixelSize());
1638 	tcu::TextureLevel			referenceImage	(textureFormat, size.width, size.height);
1639 	tcu::PixelBufferAccess		referenceAccess	(referenceImage.getAccess());
1640 
1641 	// Generate reference image
1642 	for (int y = 0; y < referenceImage.getHeight(); ++y)
1643 		for (int x = 0; x < referenceImage.getWidth(); ++x)
1644 			referenceAccess.setPixel(white, x, y);
1645 
1646 	if (deMemCmp(resultData, referenceAccess.getDataPtr(), dataSize) != 0)
1647 	{
1648 		const tcu::ConstPixelBufferAccess	resultImage	(textureFormat, size.width, size.height, 1, resultData);
1649 		bool								ok;
1650 
1651 		ok = tcu::intThresholdCompare(m_context.getTestContext().getLog(), "Image comparison", "", referenceAccess, resultImage, tcu::UVec4(1), tcu::COMPARE_LOG_RESULT);
1652 
1653 		return ok;
1654 	}
1655 
1656 	return true;
1657 }
1658 
iterate(void)1659 tcu::TestStatus TransformFeedbackIndirectDrawTestInstance::iterate (void)
1660 {
1661 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
1662 	const VkDevice						device				= m_context.getDevice();
1663 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1664 	const VkQueue						queue				= m_context.getUniversalQueue();
1665 	Allocator&							allocator			= m_context.getDefaultAllocator();
1666 
1667 	const Unique<VkRenderPass>			renderPass			(makeRenderPass			(vk, device, VK_FORMAT_R8G8B8A8_UNORM));
1668 
1669 	const Unique<VkShaderModule>		vertModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1670 	const Unique<VkShaderModule>		fragModule			(createShaderModule		(vk, device, m_context.getBinaryCollection().get("frag"), 0u));
1671 
1672 	const VkFormat						colorFormat			= VK_FORMAT_R8G8B8A8_UNORM;
1673 	const VkImageUsageFlags				imageUsageFlags		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
1674 	const tcu::RGBA						clearColor			(tcu::RGBA::black());
1675 	const VkImageSubresourceRange		colorSubresRange	(makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u));
1676 	const VkDeviceSize					colorBufferSize		(m_imageExtent2D.width * m_imageExtent2D.height * tcu::getPixelSize(mapVkFormat(colorFormat)));
1677 	const Unique<VkImage>				colorImage			(makeImage				(vk, device, makeImageCreateInfo(0u, VK_IMAGE_TYPE_2D, colorFormat, m_imageExtent2D, 1u, imageUsageFlags)));
1678 	const UniquePtr<Allocation>			colorImageAlloc		(bindImage				(vk, device, allocator, *colorImage, MemoryRequirement::Any));
1679 	const Unique<VkImageView>			colorAttachment		(makeImageView			(vk, device, *colorImage, VK_IMAGE_VIEW_TYPE_2D, colorFormat, colorSubresRange));
1680 	const Unique<VkBuffer>				colorBuffer			(makeBuffer				(vk, device, colorBufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT));
1681 	const UniquePtr<Allocation>			colorBufferAlloc	(bindBuffer				(vk, device, allocator, *colorBuffer, MemoryRequirement::HostVisible));
1682 
1683 	const deUint32						vertexCount			= 6u;
1684 	const VkDeviceSize					vertexBufferSize	= vertexCount * m_parameters.vertexStride;
1685 	const VkBufferUsageFlags			vertexBufferUsage	= VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1686 	const Unique<VkBuffer>				vertexBuffer		(makeBuffer				(vk, device, vertexBufferSize, vertexBufferUsage));
1687 	const UniquePtr<Allocation>			vertexBufferAlloc	(bindBuffer				(vk, device, allocator, *vertexBuffer, MemoryRequirement::HostVisible));
1688 	const VkDeviceSize					vertexBufferOffset	(0u);
1689 	const float							vertexBufferVals[]	=
1690 																{
1691 																	-1.0f, -1.0f, 0.0f, 1.0f,
1692 																	-1.0f, +1.0f, 0.0f, 1.0f,
1693 																	+1.0f, -1.0f, 0.0f, 1.0f,
1694 																	-1.0f, +1.0f, 0.0f, 1.0f,
1695 																	+1.0f, -1.0f, 0.0f, 1.0f,
1696 																	+1.0f, +1.0f, 0.0f, 1.0f,
1697 																};
1698 
1699 	const deUint32						counterBufferValue	= m_parameters.vertexStride * vertexCount;
1700 	const VkDeviceSize					counterBufferSize	= sizeof(counterBufferValue);
1701 	const VkBufferUsageFlags			counterBufferUsage	= VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_TRANSFER_DST_BIT;
1702 	const Unique<VkBuffer>				counterBuffer		(makeBuffer								(vk, device, counterBufferSize, counterBufferUsage));
1703 	const UniquePtr<Allocation>			counterBufferAlloc	(bindBuffer								(vk, device, allocator, *counterBuffer, MemoryRequirement::HostVisible));
1704 
1705 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer						(vk, device, *renderPass, *colorAttachment, m_imageExtent2D.width, m_imageExtent2D.height));
1706 	const Unique<VkPipelineLayout>		pipelineLayout		(TransformFeedback::makePipelineLayout	(vk, device));
1707 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, DE_NULL, *fragModule, m_imageExtent2D, 0u, DE_NULL, VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST, true));
1708 	const Unique<VkCommandPool>			cmdPool				(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1709 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1710 
1711 	const VkImageMemoryBarrier			preCopyBarrier		= makeImageMemoryBarrier(VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_ACCESS_TRANSFER_READ_BIT,
1712 																					 VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL,
1713 																					 *colorImage, colorSubresRange);
1714 	const VkBufferImageCopy				region				= makeBufferImageCopy(makeExtent3D(m_imageExtent2D.width, m_imageExtent2D.height, 1u),
1715 																				  makeImageSubresourceLayers(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 0u, 1u));
1716 	const VkBufferMemoryBarrier			postCopyBarrier		= makeBufferMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_HOST_READ_BIT, *colorBuffer, 0ull, VK_WHOLE_SIZE);
1717 
1718 	fillBuffer(vk, device, *counterBufferAlloc, counterBufferSize, &counterBufferValue, counterBufferSize);
1719 	fillBuffer(vk, device, *vertexBufferAlloc, vertexBufferSize, vertexBufferVals, sizeof(vertexBufferVals));
1720 
1721 	beginCommandBuffer(vk, *cmdBuffer);
1722 	{
1723 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D), clearColor.toVec());
1724 		{
1725 			vk.cmdBindVertexBuffers(*cmdBuffer, 0u, 1u, &*vertexBuffer, &vertexBufferOffset);
1726 
1727 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1728 
1729 			vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *counterBuffer, 0u, 0u, m_parameters.vertexStride);
1730 		}
1731 		endRenderPass(vk, *cmdBuffer);
1732 
1733 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, VK_PIPELINE_STAGE_TRANSFER_BIT, 0u, 0u, DE_NULL, 0u, DE_NULL, 1u, &preCopyBarrier);
1734 		vk.cmdCopyImageToBuffer(*cmdBuffer, *colorImage, VK_IMAGE_LAYOUT_TRANSFER_SRC_OPTIMAL, *colorBuffer, 1u, &region);
1735 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &postCopyBarrier, DE_NULL, 0u);
1736 
1737 		invalidateAlloc(vk, device, *colorBufferAlloc);
1738 	}
1739 	endCommandBuffer(vk, *cmdBuffer);
1740 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1741 
1742 	if (!verifyImage(colorFormat, m_imageExtent2D, colorBufferAlloc->getHostPtr()))
1743 		return tcu::TestStatus::fail("Fail");
1744 
1745 	return tcu::TestStatus::pass("Pass");
1746 }
1747 
1748 class TransformFeedbackBackwardDependencyTestInstance : public TransformFeedbackTestInstance
1749 {
1750 public:
1751 								TransformFeedbackBackwardDependencyTestInstance	(Context& context, const TestParameters& parameters);
1752 
1753 protected:
1754 	tcu::TestStatus				iterate											(void);
1755 	std::vector<VkDeviceSize>	generateSizesList								(const size_t bufBytes, const size_t chunkCount);
1756 };
1757 
TransformFeedbackBackwardDependencyTestInstance(Context & context,const TestParameters & parameters)1758 TransformFeedbackBackwardDependencyTestInstance::TransformFeedbackBackwardDependencyTestInstance (Context& context, const TestParameters& parameters)
1759 	: TransformFeedbackTestInstance	(context, parameters)
1760 {
1761 	if (m_transformFeedbackProperties.transformFeedbackDraw == DE_FALSE)
1762 		TCU_THROW(NotSupportedError, "transformFeedbackDraw feature is not supported");
1763 }
1764 
generateSizesList(const size_t bufBytes,const size_t chunkCount)1765 std::vector<VkDeviceSize> TransformFeedbackBackwardDependencyTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
1766 {
1767 	const VkDeviceSize			chunkSize	= bufBytes / chunkCount;
1768 	std::vector<VkDeviceSize>	result		(chunkCount, chunkSize);
1769 
1770 	DE_ASSERT(chunkSize * chunkCount == bufBytes);
1771 	DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
1772 	DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
1773 	DE_ASSERT(chunkCount > 0);
1774 	DE_ASSERT(result.size() == chunkCount);
1775 
1776 	return result;
1777 }
1778 
iterate(void)1779 tcu::TestStatus TransformFeedbackBackwardDependencyTestInstance::iterate (void)
1780 {
1781 	const DeviceInterface&				vk					= m_context.getDeviceInterface();
1782 	const VkDevice						device				= m_context.getDevice();
1783 	const deUint32						queueFamilyIndex	= m_context.getUniversalQueueFamilyIndex();
1784 	const VkQueue						queue				= m_context.getUniversalQueue();
1785 	Allocator&							allocator			= m_context.getDefaultAllocator();
1786 
1787 	const Unique<VkShaderModule>		vertexModule		(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1788 	const Unique<VkRenderPass>			renderPass			(TransformFeedback::makeRenderPass		(vk, device));
1789 	const Unique<VkFramebuffer>			framebuffer			(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1790 	const Unique<VkPipelineLayout>		pipelineLayout		(TransformFeedback::makePipelineLayout	(vk, device));
1791 	const Unique<VkPipeline>			pipeline			(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, DE_NULL, DE_NULL, m_imageExtent2D, 0u));
1792 	const Unique<VkCommandPool>			cmdPool				(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1793 	const Unique<VkCommandBuffer>		cmdBuffer			(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1794 
1795 	const VkBufferCreateInfo			tfBufCreateInfo		= makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1796 	const Move<VkBuffer>				tfBuf				= createBuffer(vk, device, &tfBufCreateInfo);
1797 	const MovePtr<Allocation>			tfBufAllocation		= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
1798 	const VkMemoryBarrier				tfMemoryBarrier		= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
1799 	const VkDeviceSize					tfBufBindingSize	= m_parameters.bufferSize;
1800 	const VkDeviceSize					tfBufBindingOffset	= 0ull;
1801 
1802 	const size_t						tfcBufSize			= sizeof(deUint32);
1803 	const VkBufferCreateInfo			tfcBufCreateInfo	= makeBufferCreateInfo(tfcBufSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT | VK_BUFFER_USAGE_INDIRECT_BUFFER_BIT);
1804 	const Move<VkBuffer>				tfcBuf				= createBuffer(vk, device, &tfcBufCreateInfo);
1805 	const MovePtr<Allocation>			tfcBufAllocation	= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfcBuf), MemoryRequirement::Any);
1806 	const VkDeviceSize					tfcBufBindingOffset	= 0ull;
1807 	const VkMemoryBarrier				tfcMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
1808 
1809 	const std::vector<VkDeviceSize>		chunkSizesList		= generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
1810 	const std::vector<VkDeviceSize>		chunkOffsetsList	= generateOffsetsList(chunkSizesList);
1811 
1812 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
1813 	VK_CHECK(vk.bindBufferMemory(device, *tfcBuf, tfcBufAllocation->getMemory(), tfcBufAllocation->getOffset()));
1814 
1815 	DE_ASSERT(m_parameters.partCount == 2u);
1816 
1817 	beginCommandBuffer(vk, *cmdBuffer);
1818 	{
1819 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1820 		{
1821 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1822 
1823 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0, 1, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1824 
1825 			{
1826 				const deUint32	startValue	= static_cast<deUint32>(chunkOffsetsList[0] / sizeof(deUint32));
1827 				const deUint32	numPoints	= static_cast<deUint32>(chunkSizesList[0] / sizeof(deUint32));
1828 
1829 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1830 
1831 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1832 				{
1833 					vk.cmdDraw(*cmdBuffer, numPoints, 1u, 0u, 0u);
1834 				}
1835 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1836 			}
1837 
1838 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_DRAW_INDIRECT_BIT, 0u, 1u, &tfcMemoryBarrier, 0u, DE_NULL, DE_NULL, 0u);
1839 
1840 			{
1841 				const deUint32	startValue	= static_cast<deUint32>(chunkOffsetsList[1] / sizeof(deUint32));
1842 
1843 				vk.cmdPushConstants(*cmdBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(startValue), &startValue);
1844 
1845 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 1, &*tfcBuf, m_parameters.noOffsetArray ? DE_NULL : &tfcBufBindingOffset);
1846 				{
1847 					vk.cmdDrawIndirectByteCountEXT(*cmdBuffer, 1u, 0u, *tfcBuf, 0u, 0u, 4u);
1848 				}
1849 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1850 			}
1851 
1852 		}
1853 		endRenderPass(vk, *cmdBuffer);
1854 
1855 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
1856 	}
1857 	endCommandBuffer(vk, *cmdBuffer);
1858 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
1859 
1860 	verifyTransformFeedbackBuffer(tfBufAllocation, m_parameters.bufferSize);
1861 
1862 	return tcu::TestStatus::pass("Pass");
1863 }
1864 
1865 
1866 class TransformFeedbackQueryTestInstance : public TransformFeedbackTestInstance
1867 {
1868 public:
1869 						TransformFeedbackQueryTestInstance	(Context& context, const TestParameters& parameters);
1870 
1871 protected:
1872 	tcu::TestStatus		iterate								(void);
1873 };
1874 
TransformFeedbackQueryTestInstance(Context & context,const TestParameters & parameters)1875 TransformFeedbackQueryTestInstance::TransformFeedbackQueryTestInstance (Context& context, const TestParameters& parameters)
1876 	: TransformFeedbackTestInstance	(context, parameters)
1877 {
1878 	const InstanceInterface&								vki							= m_context.getInstanceInterface();
1879 	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
1880 	const VkPhysicalDeviceFeatures							features					= getPhysicalDeviceFeatures(vki, physDevice);
1881 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
1882 	const deUint32											streamsSupported			= m_transformFeedbackProperties.maxTransformFeedbackStreams;
1883 	const deUint32											streamsRequired				= m_parameters.streamId + 1;
1884 
1885 	if (!features.geometryShader)
1886 		TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
1887 
1888 	if (streamsRequired > 1 && transformFeedbackFeatures.geometryStreams == DE_FALSE)
1889 		TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
1890 
1891 	if (streamsSupported < streamsRequired)
1892 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
1893 
1894 	if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
1895 		TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
1896 
1897 	if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
1898 	{
1899 		// Check VK_EXT_host_query_reset is supported
1900 		m_context.requireDeviceFunctionality("VK_EXT_host_query_reset");
1901 		if(m_context.getHostQueryResetFeatures().hostQueryReset == VK_FALSE)
1902 			throw tcu::NotSupportedError(std::string("Implementation doesn't support resetting queries from the host").c_str());
1903 	}
1904 }
1905 
iterate(void)1906 tcu::TestStatus TransformFeedbackQueryTestInstance::iterate (void)
1907 {
1908 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
1909 	const VkDevice						device					= m_context.getDevice();
1910 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1911 	const VkQueue						queue					= m_context.getUniversalQueue();
1912 	Allocator&							allocator				= m_context.getDefaultAllocator();
1913 
1914 	const deUint64						overflowVertices		= 3u;
1915 	const deUint32						bytesPerVertex			= static_cast<deUint32>(4 * sizeof(float));
1916 	const deUint64						numVerticesInBuffer		= m_parameters.bufferSize / bytesPerVertex;
1917 	const deUint64						numVerticesToWrite		= numVerticesInBuffer + overflowVertices;
1918 	const Unique<VkRenderPass>			renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
1919 
1920 	const Unique<VkShaderModule>		vertModule				(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
1921 	const Unique<VkShaderModule>		geomModule				(createShaderModule						(vk, device, m_context.getBinaryCollection().get("geom"), 0u));
1922 
1923 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
1924 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
1925 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId, m_parameters.primTopology));
1926 	const Unique<VkCommandPool>			cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
1927 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
1928 
1929 	const deUint32						tfBufferSize			= (deUint32)topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer) * (deUint32)topologyData.at(m_parameters.primTopology).primSize * bytesPerVertex;
1930 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
1931 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
1932 	const MovePtr<Allocation>			tfBufAllocation			= bindBuffer(vk, device, allocator, *tfBuf, MemoryRequirement::HostVisible);
1933 	const VkDeviceSize					tfBufBindingSize		= tfBufferSize;
1934 	const VkDeviceSize					tfBufBindingOffset		= 0ull;
1935 
1936 	const size_t						queryResultWidth		= (m_parameters.query64bits ? sizeof(deUint64) : sizeof(deUint32));
1937 	const vk::VkQueryControlFlags		queryExtraFlags			= (m_parameters.query64bits ? vk::VK_QUERY_RESULT_64_BIT : 0);
1938 	const deUint32						queryCountersNumber		= 1u;
1939 	const deUint32						queryIndex				= 0u;
1940 	constexpr deUint32					queryResultElements		= 2u;
1941 	const deUint32						queryDataSize			= static_cast<deUint32>(queryResultElements * queryResultWidth);
1942 	const VkQueryPoolCreateInfo			queryPoolCreateInfo		= makeQueryPoolCreateInfo(queryCountersNumber);
1943 	const Unique<VkQueryPool>			queryPool				(createQueryPool(vk, device, &queryPoolCreateInfo));
1944 
1945 	Move<VkBuffer>						queryPoolResultsBuffer;
1946 	de::MovePtr<Allocation>				queryPoolResultsBufferAlloc;
1947 
1948 	tcu::TestLog&						log						= m_context.getTestContext().getLog();
1949 
1950 	DE_ASSERT(numVerticesInBuffer * bytesPerVertex == m_parameters.bufferSize);
1951 
1952 	if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
1953 	{
1954 		const VkBufferCreateInfo bufferParams =
1955 		{
1956 			VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO,       // VkStructureType      sType;
1957 			DE_NULL,                                    // const void*          pNext;
1958 			0u,                                         // VkBufferCreateFlags  flags;
1959 			queryDataSize,                              // VkDeviceSize         size;
1960 			VK_BUFFER_USAGE_TRANSFER_DST_BIT,           // VkBufferUsageFlags   usage;
1961 			VK_SHARING_MODE_EXCLUSIVE,                  // VkSharingMode        sharingMode;
1962 			1u,                                         // deUint32             queueFamilyCount;
1963 			&queueFamilyIndex                           // const deUint32*      pQueueFamilyIndices;
1964 		};
1965 
1966 		queryPoolResultsBuffer = createBuffer(vk, device, &bufferParams);
1967 		queryPoolResultsBufferAlloc = allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
1968 
1969 		VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
1970 	}
1971 
1972 	beginCommandBuffer(vk, *cmdBuffer);
1973 	{
1974 		if (m_parameters.testType != TEST_TYPE_QUERY_RESET)
1975 			vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
1976 
1977 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
1978 		{
1979 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
1980 
1981 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, 1u, &*tfBuf, &tfBufBindingOffset, &tfBufBindingSize);
1982 
1983 			if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_BEGIN_QUERY_INDEXED)
1984 				vk.cmdBeginQuery(*cmdBuffer, *queryPool, queryIndex, 0u);
1985 			else
1986 				vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, 0u, m_parameters.streamId);
1987 			{
1988 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1989 				{
1990 					vk.cmdDraw(*cmdBuffer, static_cast<deUint32>(numVerticesToWrite), 1u, 0u, 0u);
1991 				}
1992 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
1993 			}
1994 			if (m_parameters.streamId == 0 && m_parameters.streamId0Mode != STREAM_ID_0_END_QUERY_INDEXED)
1995 				vk.cmdEndQuery(*cmdBuffer, *queryPool, queryIndex);
1996 			else
1997 				vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex, m_parameters.streamId);
1998 		}
1999 		endRenderPass(vk, *cmdBuffer);
2000 
2001 		if (m_parameters.testType == TEST_TYPE_QUERY_COPY || m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2002 		{
2003 			VkDeviceSize copyStride = queryDataSize;
2004 			if (queryCountersNumber == 1u && m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2005 				copyStride = 0;
2006 			vk.cmdCopyQueryPoolResults(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber, *queryPoolResultsBuffer, 0u, copyStride, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
2007 
2008 			const VkBufferMemoryBarrier bufferBarrier =
2009 			{
2010 				VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER,	// VkStructureType	sType;
2011 				DE_NULL,									// const void*		pNext;
2012 				VK_ACCESS_TRANSFER_WRITE_BIT,				// VkAccessFlags	srcAccessMask;
2013 				VK_ACCESS_HOST_READ_BIT,					// VkAccessFlags	dstAccessMask;
2014 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			srcQueueFamilyIndex;
2015 				VK_QUEUE_FAMILY_IGNORED,					// deUint32			dstQueueFamilyIndex;
2016 				*queryPoolResultsBuffer,					// VkBuffer			buffer;
2017 				0ull,										// VkDeviceSize		offset;
2018 				VK_WHOLE_SIZE								// VkDeviceSize		size;
2019 			};
2020 			vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 0u, DE_NULL, 1u, &bufferBarrier, 0u, DE_NULL);
2021 		}
2022 
2023 	}
2024 	endCommandBuffer(vk, *cmdBuffer);
2025 
2026 	if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2027 		vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2028 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2029 
2030 	{
2031 		union Results
2032 		{
2033 			deUint32	elements32[queryResultElements];
2034 			deUint64	elements64[queryResultElements];
2035 		};
2036 
2037 		std::vector<deUint8>	queryData		(queryDataSize, 0u);
2038 		const Results*			queryResults	= reinterpret_cast<Results*>(queryData.data());
2039 
2040 		if (m_parameters.testType != TEST_TYPE_QUERY_COPY && m_parameters.testType != TEST_TYPE_QUERY_COPY_STRIDE_ZERO)
2041 		{
2042 			vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryData.data(), queryDataSize, (vk::VK_QUERY_RESULT_WAIT_BIT | queryExtraFlags));
2043 		}
2044 		else
2045 		{
2046 			invalidateAlloc(vk, device, *queryPoolResultsBufferAlloc);
2047 			deMemcpy(queryData.data(), queryPoolResultsBufferAlloc->getHostPtr(), queryData.size());
2048 		}
2049 
2050 		// The number of primitives successfully written to the corresponding transform feedback buffer.
2051 		const deUint64	numPrimitivesWritten	= (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2052 
2053 		// The number of primitives output to the vertex stream.
2054 		const deUint64	numPrimitivesNeeded		= (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2055 
2056 		// Count how many primitives we should get by using selected topology.
2057 		const auto		primitivesInBuffer		= topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesInBuffer);
2058 		const auto		primitivesToWrite		= topologyData.at(m_parameters.primTopology).getNumPrimitives(numVerticesToWrite);
2059 
2060 		log << tcu::TestLog::Message << "Primitives Written / Expected :  " << de::toString(numPrimitivesWritten) << " / " << de::toString(primitivesInBuffer) << tcu::TestLog::EndMessage;
2061 		log << tcu::TestLog::Message << "Primitives  Needed / Expected :  " << de::toString(numPrimitivesNeeded) << " / " << de::toString(primitivesToWrite) << tcu::TestLog::EndMessage;
2062 
2063 		if (numPrimitivesWritten != primitivesInBuffer)
2064 			return tcu::TestStatus::fail("numPrimitivesWritten=" + de::toString(numPrimitivesWritten) + " while expected " + de::toString(primitivesInBuffer));
2065 
2066 		if (numPrimitivesNeeded != primitivesToWrite)
2067 			return tcu::TestStatus::fail("numPrimitivesNeeded=" + de::toString(numPrimitivesNeeded) + " while expected " + de::toString(primitivesToWrite));
2068 	}
2069 
2070 	if (m_parameters.testType == TEST_TYPE_QUERY_RESET)
2071 	{
2072 		constexpr deUint32		queryResetElements		= queryResultElements + 1; // For the availability bit.
2073 
2074 		union Results
2075 		{
2076 			deUint32	elements32[queryResetElements];
2077 			deUint64	elements64[queryResetElements];
2078 		};
2079 
2080 		const deUint32			queryDataAvailSize		(static_cast<deUint32>(queryResetElements * queryResultWidth));
2081 		std::vector<deUint8>	queryData				(queryDataAvailSize, 0u);
2082 		Results*				queryResults			= reinterpret_cast<Results*>(queryData.data());
2083 
2084 		// Initialize values
2085 		if (m_parameters.query64bits)
2086 		{
2087 			queryResults->elements64[0] = 1u;	// numPrimitivesWritten
2088 			queryResults->elements64[1] = 1u;	// numPrimitivesNeeded
2089 			queryResults->elements64[2] = 1u;	// Availability bit
2090 		}
2091 		else
2092 		{
2093 			queryResults->elements32[0] = 1u;	// numPrimitivesWritten
2094 			queryResults->elements32[1] = 1u;	// numPrimitivesNeeded
2095 			queryResults->elements32[2] = 1u;	// Availability bit
2096 		}
2097 
2098 		vk.resetQueryPool(device, *queryPool, queryIndex, queryCountersNumber);
2099 
2100 		vk::VkResult	res						= vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataAvailSize, queryData.data(), queryDataAvailSize, (vk::VK_QUERY_RESULT_WITH_AVAILABILITY_BIT | queryExtraFlags));
2101 		const deUint64	numPrimitivesWritten	= (m_parameters.query64bits ? queryResults->elements64[0] : queryResults->elements32[0]);
2102 		const deUint64	numPrimitivesNeeded		= (m_parameters.query64bits ? queryResults->elements64[1] : queryResults->elements32[1]);
2103 		const deUint64	availabilityState		= (m_parameters.query64bits ? queryResults->elements64[2] : queryResults->elements32[2]);
2104 
2105 		/* From the Vulkan spec:
2106 			*
2107 			* If VK_QUERY_RESULT_WAIT_BIT and VK_QUERY_RESULT_PARTIAL_BIT are both not set then no result values are written to pData
2108 			* for queries that are in the unavailable state at the time of the call, and vkGetQueryPoolResults returns VK_NOT_READY.
2109 			* However, availability state is still written to pData for those queries if VK_QUERY_RESULT_WITH_AVAILABILITY_BIT is set.
2110 			*/
2111 		if (res != vk::VK_NOT_READY || availabilityState != 0u)
2112 			return tcu::TestStatus::fail("QueryPoolResults incorrect reset");
2113 	    if (numPrimitivesWritten != 1u || numPrimitivesNeeded != 1u)
2114 			return tcu::TestStatus::fail("QueryPoolResults data was modified");
2115 
2116 	}
2117 
2118 	return tcu::TestStatus::pass("Pass");
2119 }
2120 
2121 class TransformFeedbackMultiQueryTestInstance : public TransformFeedbackTestInstance
2122 {
2123 public:
2124 								TransformFeedbackMultiQueryTestInstance	(Context& context, const TestParameters& parameters);
2125 
2126 protected:
2127 	std::vector<VkDeviceSize>	generateSizesList							(const size_t bufBytes, const size_t chunkCount);
2128 	void						verifyTransformFeedbackBuffer				(const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected);
2129 	tcu::TestStatus				iterate										(void);
2130 };
2131 
TransformFeedbackMultiQueryTestInstance(Context & context,const TestParameters & parameters)2132 TransformFeedbackMultiQueryTestInstance::TransformFeedbackMultiQueryTestInstance (Context& context, const TestParameters& parameters)
2133 	: TransformFeedbackTestInstance	(context, parameters)
2134 {
2135 	const InstanceInterface&								vki							= m_context.getInstanceInterface();
2136 	const VkPhysicalDevice									physDevice					= m_context.getPhysicalDevice();
2137 	const VkPhysicalDeviceFeatures							features					= getPhysicalDeviceFeatures(vki, physDevice);
2138 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&		transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
2139 	const deUint32											streamsSupported			= m_transformFeedbackProperties.maxTransformFeedbackStreams;
2140 	const deUint32											streamsRequired				= m_parameters.streamId + 1;
2141 	const deUint32											tfBuffersSupported			= m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2142 	const deUint32											tfBuffersRequired			= m_parameters.partCount;
2143 	const deUint32											bytesPerVertex				= m_parameters.bufferSize / m_parameters.partCount;
2144 	const deUint32											tfStreamDataSizeSupported	= m_transformFeedbackProperties.maxTransformFeedbackStreamDataSize;
2145 	const deUint32											tfBufferDataSizeSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataSize;
2146 	const deUint32											tfBufferDataStrideSupported	= m_transformFeedbackProperties.maxTransformFeedbackBufferDataStride;
2147 
2148 	DE_ASSERT(m_parameters.partCount == 2u);
2149 
2150 	if (!features.geometryShader)
2151 		TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2152 
2153 	if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2154 		TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2155 
2156 	if (streamsSupported < streamsRequired)
2157 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2158 
2159 	if (tfBuffersSupported < tfBuffersRequired)
2160 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2161 
2162 	if (tfStreamDataSizeSupported < bytesPerVertex)
2163 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreamDataSize=" + de::toString(tfStreamDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2164 
2165 	if (tfBufferDataSizeSupported < bytesPerVertex)
2166 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataSize=" + de::toString(tfBufferDataSizeSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2167 
2168 	if (tfBufferDataStrideSupported < bytesPerVertex)
2169 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBufferDataStride=" + de::toString(tfBufferDataStrideSupported) + ", while test requires " + de::toString(bytesPerVertex)).c_str());
2170 
2171 	if (m_transformFeedbackProperties.transformFeedbackQueries == DE_FALSE)
2172 		TCU_THROW(NotSupportedError, "transformFeedbackQueries feature is not supported");
2173 }
2174 
generateSizesList(const size_t bufBytes,const size_t chunkCount)2175 std::vector<VkDeviceSize> TransformFeedbackMultiQueryTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2176 {
2177 	const VkDeviceSize			chunkSize	= bufBytes / chunkCount;
2178 	std::vector<VkDeviceSize>	result		(chunkCount, chunkSize);
2179 
2180 	DE_ASSERT(chunkSize * chunkCount == bufBytes);
2181 	DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2182 	DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2183 	DE_ASSERT(chunkCount > 0);
2184 	DE_ASSERT(result.size() == chunkCount);
2185 
2186 	return result;
2187 }
2188 
verifyTransformFeedbackBuffer(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const deUint32 bufOffset,const float expected)2189 void TransformFeedbackMultiQueryTestInstance::verifyTransformFeedbackBuffer (const MovePtr<Allocation>& bufAlloc, const deUint32 bufBytes, const deUint32 bufOffset, const float expected)
2190 {
2191 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2192 	const VkDevice			device		= m_context.getDevice();
2193 	const deUint32			numPoints	= bufBytes / static_cast<deUint32>(sizeof(float));
2194 	const deUint8*			tfDataRaw	= getInvalidatedHostPtr<deUint8>(vk, device, *bufAlloc);
2195 	const float*			tfData		= reinterpret_cast<const float*>(&tfDataRaw[bufOffset]);
2196 
2197 	for (deUint32 i = 0; i < numPoints; ++i)
2198 		if (tfData[i] != expected)
2199 			TCU_FAIL(std::string("Failed at item ") + de::toString(i) + " received:" + de::toString(tfData[i]) + " expected:" + de::toString(expected));
2200 }
2201 
iterate(void)2202 tcu::TestStatus TransformFeedbackMultiQueryTestInstance::iterate (void)
2203 {
2204 	const DeviceInterface&						vk							= m_context.getDeviceInterface();
2205 	const VkDevice								device						= m_context.getDevice();
2206 	const deUint32								queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
2207 	const std::vector<deUint32>					queueFamilyIndices			= { queueFamilyIndex };
2208 	const VkQueue								queue						= m_context.getUniversalQueue();
2209 	Allocator&									allocator					= m_context.getDefaultAllocator();
2210 
2211 	const Unique<VkRenderPass>					renderPass					(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
2212 
2213 	const Unique<VkShaderModule>				vertModule					(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2214 	const Unique<VkShaderModule>				geomModule					(createShaderModule						(vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2215 
2216 	const Unique<VkFramebuffer>					framebuffer					(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2217 	const Unique<VkPipelineLayout>				pipelineLayout				(TransformFeedback::makePipelineLayout	(vk, device));
2218 	const Unique<VkPipeline>					pipeline					(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u));
2219 	const Unique<VkCommandPool>					cmdPool						(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2220 	const Unique<VkCommandBuffer>				cmdBuffer					(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2221 
2222 	const VkBufferCreateInfo					tfBufCreateInfo				= makeBufferCreateInfo(m_parameters.bufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2223 	const Move<VkBuffer>						tfBuf						= createBuffer(vk, device, &tfBufCreateInfo);
2224 	const std::vector<VkBuffer>					tfBufArray					= std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2225 	const MovePtr<Allocation>					tfBufAllocation				= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2226 	const VkMemoryBarrier						tfMemoryBarrier				= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2227 	const std::vector<VkDeviceSize>				tfBufBindingSizes			= generateSizesList(m_parameters.bufferSize, m_parameters.partCount);
2228 	const std::vector<VkDeviceSize>				tfBufBindingOffsets			= generateOffsetsList(tfBufBindingSizes);
2229 	const std::vector<float>					tfBufExpectedValues			= { 0.5f, 0.5f + float(m_parameters.streamId) };
2230 	const deUint32								maxBufferSizeBytes			= static_cast<deUint32>(*std::max_element(tfBufBindingSizes.begin(), tfBufBindingSizes.end()));
2231 	const deUint32								bytesPerVertex				= static_cast<deUint32>(4 * sizeof(float));
2232 	const deUint32								numVerticesInBuffer			= maxBufferSizeBytes / bytesPerVertex;
2233 	const deUint32								numDrawVertices				= numVerticesInBuffer / 2;
2234 
2235 	const deUint32								queryIndex					= 0u;
2236 	const deUint32								queryCountersNumber			= 2u;
2237 	const deUint32								queryStride					= sizeof(TransformFeedbackQuery);
2238 	const deUint32								queryDataSize				= queryCountersNumber * queryStride;
2239 	const VkQueryPoolCreateInfo					queryPoolCreateInfo			= makeQueryPoolCreateInfo(queryCountersNumber);
2240 	const Unique<VkQueryPool>					queryPool					(createQueryPool(vk, device, &queryPoolCreateInfo));
2241 	const deUint32								queryInvalidCounterValue	= 999999u;
2242 	std::vector<TransformFeedbackQuery>			queryResultData				(queryCountersNumber, TransformFeedbackQuery{ queryInvalidCounterValue, queryInvalidCounterValue });
2243 	const std::vector<TransformFeedbackQuery>	queryExpectedData			({ TransformFeedbackQuery{ numVerticesInBuffer, 3 * numDrawVertices }, TransformFeedbackQuery{ numDrawVertices, numDrawVertices } });
2244 
2245 	const VkBufferCreateInfo					queryBufferCreateInfo		= makeBufferCreateInfo(queryDataSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT, queueFamilyIndices);
2246 	const Move<VkBuffer>						queryPoolResultsBuffer		= createBuffer(vk, device, &queryBufferCreateInfo);
2247 	const MovePtr<Allocation>					queryPoolResultsBufferAlloc	= allocator.allocate(getBufferMemoryRequirements(vk, device, *queryPoolResultsBuffer), MemoryRequirement::HostVisible);
2248 
2249 	DE_ASSERT(queryCountersNumber == queryExpectedData.size());
2250 
2251 	VK_CHECK(vk.bindBufferMemory(device, *queryPoolResultsBuffer, queryPoolResultsBufferAlloc->getMemory(), queryPoolResultsBufferAlloc->getOffset()));
2252 
2253 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2254 
2255 	beginCommandBuffer(vk, *cmdBuffer);
2256 	{
2257 		vk.cmdResetQueryPool(*cmdBuffer, *queryPool, queryIndex, queryCountersNumber);
2258 
2259 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2260 		{
2261 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2262 
2263 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2264 
2265 			vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0u, 0u);
2266 			vk.cmdBeginQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, 0u, m_parameters.streamId);
2267 			{
2268 				vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2269 				{
2270 					vk.cmdDraw(*cmdBuffer, numDrawVertices, 1u, 0u, 0u);
2271 				}
2272 				vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2273 			}
2274 			vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 1, m_parameters.streamId);
2275 			vk.cmdEndQueryIndexedEXT(*cmdBuffer, *queryPool, queryIndex + 0, 0);
2276 		}
2277 		endRenderPass(vk, *cmdBuffer);
2278 
2279 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2280 	}
2281 	endCommandBuffer(vk, *cmdBuffer);
2282 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2283 
2284 	vk.getQueryPoolResults(device, *queryPool, queryIndex, queryCountersNumber, queryDataSize, queryResultData.data(), queryStride, (vk::VK_QUERY_RESULT_WAIT_BIT));
2285 
2286 	DE_ASSERT(queryResultData.size() == queryCountersNumber && queryExpectedData.size() == queryCountersNumber);
2287 	DE_ASSERT(queryCountersNumber > 0);
2288 
2289 	for (size_t counterNdx = 0; counterNdx < queryCountersNumber; ++counterNdx)
2290 	{
2291 		const TransformFeedbackQuery&	result		= queryResultData[counterNdx];
2292 		const TransformFeedbackQuery&	expected	= queryExpectedData[counterNdx];
2293 
2294 		DE_ASSERT(expected.written != queryInvalidCounterValue);
2295 		DE_ASSERT(expected.attempts != queryInvalidCounterValue);
2296 
2297 		if (result.written == queryInvalidCounterValue || result.attempts == queryInvalidCounterValue)
2298 			return tcu::TestStatus::fail("Query counters read failed");
2299 
2300 		if (result.written != expected.written)
2301 		{
2302 			const std::string	comment	= "At counter " + de::toString(counterNdx) + " vertices written " + de::toString(result.written) + ", while expected " + de::toString(expected.written);
2303 
2304 			return tcu::TestStatus::fail(comment.c_str());
2305 		}
2306 
2307 
2308 		if (result.attempts != expected.attempts)
2309 		{
2310 			const std::string	comment = "At counter " + de::toString(counterNdx) + " attempts committed " + de::toString(result.attempts) + ", while expected " + de::toString(expected.attempts);
2311 
2312 			return tcu::TestStatus::fail(comment.c_str());
2313 		}
2314 
2315 		if (counterNdx == 0 && !m_parameters.omitShaderWrite)
2316 			verifyTransformFeedbackBuffer(tfBufAllocation, bytesPerVertex * expected.written, static_cast<deUint32>(tfBufBindingOffsets[counterNdx]), tfBufExpectedValues[counterNdx]);
2317 	}
2318 
2319 	return tcu::TestStatus::pass("Pass");
2320 }
2321 
2322 
2323 class TransformFeedbackLinesOrTrianglesTestInstance : public TransformFeedbackTestInstance
2324 {
2325 public:
2326 								TransformFeedbackLinesOrTrianglesTestInstance	(Context& context, const TestParameters& parameters);
2327 
2328 protected:
2329 	std::vector<VkDeviceSize>	generateSizesList								(const size_t bufBytes, const size_t chunkCount);
2330 	void						verifyTransformFeedbackBufferLines				(const MovePtr<Allocation>&		bufAlloc,
2331 																				 const deUint32					bufBytes,
2332 																				 const std::vector<deUint32>&	primitives,
2333 																				 const deUint32					invocationCount,
2334 																				 const deUint32					partCount);
2335 	void						verifyTransformFeedbackBufferTriangles			(const MovePtr<Allocation>&		bufAlloc,
2336 																				 const deUint32					bufBytes,
2337 																				 const std::vector<deUint32>&	primitives,
2338 																				 const deUint32					invocationCount,
2339 																				 const deUint32					partCount);
2340 	tcu::TestStatus				iterate											(void);
2341 };
2342 
TransformFeedbackLinesOrTrianglesTestInstance(Context & context,const TestParameters & parameters)2343 TransformFeedbackLinesOrTrianglesTestInstance::TransformFeedbackLinesOrTrianglesTestInstance (Context& context, const TestParameters& parameters)
2344 	: TransformFeedbackTestInstance	(context, parameters)
2345 {
2346 	const InstanceInterface&							vki							= m_context.getInstanceInterface();
2347 	const VkPhysicalDevice								physDevice					= m_context.getPhysicalDevice();
2348 	const VkPhysicalDeviceFeatures						features					= getPhysicalDeviceFeatures(vki, physDevice);
2349 	const VkPhysicalDeviceTransformFeedbackFeaturesEXT&	transformFeedbackFeatures	= m_context.getTransformFeedbackFeaturesEXT();
2350 	const deUint32										streamsSupported			= m_transformFeedbackProperties.maxTransformFeedbackStreams;
2351 	const deUint32										streamsRequired				= m_parameters.streamId + 1;
2352 	const deUint32										tfBuffersSupported			= m_transformFeedbackProperties.maxTransformFeedbackBuffers;
2353 	const deUint32										tfBuffersRequired			= m_parameters.partCount;
2354 
2355 	DE_ASSERT(m_parameters.partCount == 2u);
2356 
2357 	if (m_transformFeedbackProperties.transformFeedbackStreamsLinesTriangles == DE_FALSE)
2358 		TCU_THROW(NotSupportedError, "transformFeedbackStreamsLinesTriangles required");
2359 
2360 	if (!features.geometryShader)
2361 		TCU_THROW(NotSupportedError, "Missing feature: geometryShader");
2362 
2363 	if (transformFeedbackFeatures.geometryStreams == DE_FALSE)
2364 		TCU_THROW(NotSupportedError, "geometryStreams feature is not supported");
2365 
2366 	if (streamsSupported < streamsRequired)
2367 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackStreams=" + de::toString(streamsSupported) + ", while test requires " + de::toString(streamsRequired)).c_str());
2368 
2369 	if (tfBuffersSupported < tfBuffersRequired)
2370 		TCU_THROW(NotSupportedError, std::string("maxTransformFeedbackBuffers=" + de::toString(tfBuffersSupported) + ", while test requires " + de::toString(tfBuffersRequired)).c_str());
2371 }
2372 
generateSizesList(const size_t bufBytes,const size_t chunkCount)2373 std::vector<VkDeviceSize> TransformFeedbackLinesOrTrianglesTestInstance::generateSizesList (const size_t bufBytes, const size_t chunkCount)
2374 {
2375 	const VkDeviceSize			chunkSize	= bufBytes / chunkCount;
2376 	std::vector<VkDeviceSize>	result		(chunkCount, chunkSize);
2377 
2378 	DE_ASSERT(chunkSize * chunkCount == bufBytes);
2379 	DE_ASSERT(bufBytes <= MINIMUM_TF_BUFFER_SIZE);
2380 	DE_ASSERT(bufBytes % sizeof(deUint32) == 0);
2381 	DE_ASSERT(chunkCount > 0);
2382 	DE_ASSERT(result.size() == chunkCount);
2383 
2384 	return result;
2385 }
2386 
verifyTransformFeedbackBufferLines(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const std::vector<deUint32> & primitives,const deUint32 invocationCount,const deUint32 partCount)2387 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferLines (const MovePtr<Allocation>&		bufAlloc,
2388 																						const deUint32					bufBytes,
2389 																						const std::vector<deUint32>&	primitives,
2390 																						const deUint32					invocationCount,
2391 																						const deUint32					partCount)
2392 {
2393 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2394 	const VkDevice			device		= m_context.getDevice();
2395 	const tcu::Vec4*		tfData		= getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2396 	const deUint32			stripeCount	= static_cast<deUint32>(primitives.size());
2397 	const deUint32			vertexCount	= 2 * destripedLineCount(primitives) * invocationCount * partCount;
2398 	const deUint32			numPoints	= static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2399 	deUint32				n			= 0;
2400 	std::vector<tcu::Vec4>	reference;
2401 
2402 	reference.reserve(vertexCount);
2403 
2404 	for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2405 	{
2406 		for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2407 		{
2408 			for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2409 			{
2410 				const deUint32 stripeVertexCount = primitives[stripeNdx];
2411 
2412 				for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2413 				{
2414 					const bool		firstOrLast	= vertexNdx == 0 || vertexNdx == stripeVertexCount - 1;
2415 					const tcu::Vec4 v			(float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2416 
2417 					reference.push_back(v);
2418 
2419 					if (!firstOrLast)
2420 						reference.push_back(v);
2421 				}
2422 			}
2423 		}
2424 	}
2425 
2426 	DE_ASSERT(reference.size() == numPoints);
2427 
2428 	for (deUint32 i = 0; i < numPoints; ++i)
2429 	{
2430 		if (tfData[i] != reference[i])
2431 		{
2432 			tcu::TestLog&		log		= m_context.getTestContext().getLog();
2433 			std::stringstream	err;
2434 			std::stringstream	css;
2435 
2436 			err << "Failed at item " << i
2437 				<< " received:" << tfData[i]
2438 				<< " expected:" << reference[i];
2439 
2440 			for (deUint32 j = 0; j < numPoints; ++j)
2441 				css << j << ": " << tfData[j] << (i == j ? " <= fail" : "") <<std::endl;
2442 
2443 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2444 
2445 			TCU_FAIL(err.str());
2446 		}
2447 	}
2448 }
2449 
verifyTransformFeedbackBufferTriangles(const MovePtr<Allocation> & bufAlloc,const deUint32 bufBytes,const std::vector<deUint32> & primitives,const deUint32 invocationCount,const deUint32 partCount)2450 void TransformFeedbackLinesOrTrianglesTestInstance::verifyTransformFeedbackBufferTriangles (const MovePtr<Allocation>&		bufAlloc,
2451 																							const deUint32					bufBytes,
2452 																							const std::vector<deUint32>&	primitives,
2453 																							const deUint32					invocationCount,
2454 																							const deUint32					partCount)
2455 {
2456 	const DeviceInterface&	vk			= m_context.getDeviceInterface();
2457 	const VkDevice			device		= m_context.getDevice();
2458 	const tcu::Vec4*		tfData		= getInvalidatedHostPtr<tcu::Vec4>(vk, device, *bufAlloc);
2459 	const deUint32			stripeCount	= static_cast<deUint32>(primitives.size());
2460 	const deUint32			vertexCount	= 3 * destripedLineCount(primitives) * invocationCount * partCount;
2461 	const deUint32			numPoints	= static_cast<deUint32>(bufBytes / sizeof(tcu::Vec4));
2462 	deUint32				n			= 0;
2463 	std::vector<tcu::Vec4>	reference;
2464 
2465 	reference.reserve(vertexCount);
2466 
2467 	for (deUint32 partNdx = 0; partNdx < partCount; ++partNdx)
2468 	{
2469 		for (deUint32 invocationNdx = 0; invocationNdx < invocationCount; ++invocationNdx)
2470 		{
2471 			for (deUint32 stripeNdx = 0; stripeNdx < stripeCount; ++stripeNdx)
2472 			{
2473 				const deUint32			stripeVertexCount	= primitives[stripeNdx];
2474 				const deUint32			trianglesCount		= stripeVertexCount - 2;
2475 				std::vector<tcu::Vec4>	stripe				(stripeVertexCount);
2476 
2477 				for (deUint32 vertexNdx = 0; vertexNdx < stripeVertexCount; ++vertexNdx)
2478 					stripe[vertexNdx] = tcu::Vec4(float(n++), float(invocationNdx), float(stripeNdx), float(vertexNdx));
2479 
2480 				for (deUint32 triangleNdx = 0; triangleNdx < trianglesCount; ++triangleNdx)
2481 				{
2482 					if (triangleNdx % 2 == 0)
2483 					{
2484 						reference.push_back(stripe[triangleNdx + 0]);
2485 						reference.push_back(stripe[triangleNdx + 1]);
2486 						reference.push_back(stripe[triangleNdx + 2]);
2487 					}
2488 					else
2489 					{
2490 						reference.push_back(stripe[triangleNdx + 0]);
2491 						reference.push_back(stripe[triangleNdx + 2]);
2492 						reference.push_back(stripe[triangleNdx + 1]);
2493 					}
2494 				}
2495 			}
2496 		}
2497 	}
2498 
2499 	DE_ASSERT(reference.size() == numPoints);
2500 
2501 	for (deUint32 i = 0; i < numPoints; ++i)
2502 	{
2503 		if (tfData[i] != reference[i])
2504 		{
2505 			tcu::TestLog&		log		= m_context.getTestContext().getLog();
2506 			std::stringstream	err;
2507 			std::stringstream	css;
2508 
2509 			err << "Failed at item " << i
2510 				<< " received:" << tfData[i]
2511 				<< " expected:" << reference[i];
2512 
2513 			for (deUint32 j = 0; j < numPoints; ++j)
2514 				css << j << ": " << tfData[j] << (i == j ? " <= fail" : "") <<std::endl;
2515 
2516 			log << tcu::TestLog::Message << css.str() << tcu::TestLog::EndMessage;
2517 
2518 			TCU_FAIL(err.str());
2519 		}
2520 	}
2521 }
2522 
iterate(void)2523 tcu::TestStatus TransformFeedbackLinesOrTrianglesTestInstance::iterate (void)
2524 {
2525 	const DeviceInterface&				vk						= m_context.getDeviceInterface();
2526 	const VkDevice						device					= m_context.getDevice();
2527 	const deUint32						queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
2528 	const VkQueue						queue					= m_context.getUniversalQueue();
2529 	Allocator&							allocator				= m_context.getDefaultAllocator();
2530 
2531 	const Unique<VkRenderPass>			renderPass				(makeRenderPass							(vk, device, VK_FORMAT_UNDEFINED));
2532 
2533 	const Unique<VkShaderModule>		vertexModule			(createShaderModule						(vk, device, m_context.getBinaryCollection().get("vert"), 0u));
2534 	const Unique<VkShaderModule>		geomModule				(createShaderModule						(vk, device, m_context.getBinaryCollection().get("geom"), 0u));
2535 
2536 	const Unique<VkFramebuffer>			framebuffer				(makeFramebuffer						(vk, device, *renderPass, 0u, DE_NULL, m_imageExtent2D.width, m_imageExtent2D.height));
2537 	const Unique<VkPipelineLayout>		pipelineLayout			(TransformFeedback::makePipelineLayout	(vk, device));
2538 	const Unique<VkPipeline>			pipeline				(makeGraphicsPipeline					(vk, device, *pipelineLayout, *renderPass, *vertexModule, DE_NULL, DE_NULL, *geomModule, DE_NULL, m_imageExtent2D, 0u, &m_parameters.streamId));
2539 	const Unique<VkCommandPool>			cmdPool					(createCommandPool						(vk, device, VK_COMMAND_POOL_CREATE_RESET_COMMAND_BUFFER_BIT, queueFamilyIndex));
2540 	const Unique<VkCommandBuffer>		cmdBuffer				(allocateCommandBuffer					(vk, device, *cmdPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY));
2541 
2542 	const deUint32						tfBufferSize			= m_parameters.bufferSize;
2543 	const VkBufferCreateInfo			tfBufCreateInfo			= makeBufferCreateInfo(tfBufferSize, VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT);
2544 	const Move<VkBuffer>				tfBuf					= createBuffer(vk, device, &tfBufCreateInfo);
2545 	const std::vector<VkBuffer>			tfBufArray				= std::vector<VkBuffer>(m_parameters.partCount, *tfBuf);
2546 	const MovePtr<Allocation>			tfBufAllocation			= allocator.allocate(getBufferMemoryRequirements(vk, device, *tfBuf), MemoryRequirement::HostVisible);
2547 	const VkMemoryBarrier				tfMemoryBarrier			= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
2548 	const std::vector<VkDeviceSize>		tfBufBindingSizes		= generateSizesList(tfBufferSize, m_parameters.partCount);
2549 	const std::vector<VkDeviceSize>		tfBufBindingOffsets		= generateOffsetsList(tfBufBindingSizes);
2550 
2551 	VK_CHECK(vk.bindBufferMemory(device, *tfBuf, tfBufAllocation->getMemory(), tfBufAllocation->getOffset()));
2552 
2553 	beginCommandBuffer(vk, *cmdBuffer);
2554 	{
2555 		beginRenderPass(vk, *cmdBuffer, *renderPass, *framebuffer, makeRect2D(m_imageExtent2D));
2556 		{
2557 			vk.cmdBindPipeline(*cmdBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
2558 
2559 			vk.cmdBindTransformFeedbackBuffersEXT(*cmdBuffer, 0u, m_parameters.partCount, &tfBufArray[0], &tfBufBindingOffsets[0], &tfBufBindingSizes[0]);
2560 
2561 			vk.cmdBeginTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2562 			{
2563 				vk.cmdDraw(*cmdBuffer, INVOCATION_COUNT, 1u, 0u, 0u);
2564 			}
2565 			vk.cmdEndTransformFeedbackEXT(*cmdBuffer, 0, 0, DE_NULL, DE_NULL);
2566 		}
2567 		endRenderPass(vk, *cmdBuffer);
2568 
2569 		vk.cmdPipelineBarrier(*cmdBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &tfMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
2570 	}
2571 	endCommandBuffer(vk, *cmdBuffer);
2572 	submitCommandsAndWait(vk, device, queue, *cmdBuffer);
2573 
2574 	switch (m_parameters.primTopology)
2575 	{
2576 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:		verifyTransformFeedbackBufferLines(tfBufAllocation, tfBufferSize, LINES_LIST, INVOCATION_COUNT, m_parameters.partCount);			break;
2577 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:	verifyTransformFeedbackBufferTriangles(tfBufAllocation, tfBufferSize, TRIANGLES_LIST, INVOCATION_COUNT, m_parameters.partCount);	break;
2578 		default:									TCU_THROW(InternalError, "Unknown topology");
2579 	}
2580 
2581 	return tcu::TestStatus::pass("Pass");
2582 }
2583 
2584 class TransformFeedbackTestCase : public vkt::TestCase
2585 {
2586 public:
2587 						TransformFeedbackTestCase	(tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters);
2588 
2589 protected:
2590 	vkt::TestInstance*	createInstance				(vkt::Context& context) const;
2591 	void				initPrograms				(SourceCollections& programCollection) const;
2592 	virtual void		checkSupport				(Context& context) const;
2593 
2594 	TestParameters		m_parameters;
2595 };
2596 
TransformFeedbackTestCase(tcu::TestContext & context,const char * name,const char * description,const TestParameters & parameters)2597 TransformFeedbackTestCase::TransformFeedbackTestCase (tcu::TestContext &context, const char *name, const char *description, const TestParameters& parameters)
2598 	: TestCase		(context, name, description)
2599 	, m_parameters	(parameters)
2600 {
2601 }
2602 
vectorToString(const std::vector<deUint32> & v)2603 std::string vectorToString (const std::vector<deUint32>& v)
2604 {
2605 	std::ostringstream css;
2606 
2607 	DE_ASSERT(!v.empty());
2608 
2609 	for (auto x: v)
2610 		css << x << ",";
2611 
2612 	return css.str().substr(0, css.str().size() - 1);
2613 }
2614 
createInstance(vkt::Context & context) const2615 vkt::TestInstance*	TransformFeedbackTestCase::createInstance (vkt::Context& context) const
2616 {
2617 	if (m_parameters.testType == TEST_TYPE_BASIC)
2618 		return new TransformFeedbackBasicTestInstance(context, m_parameters);
2619 
2620 	if (m_parameters.testType == TEST_TYPE_RESUME)
2621 		return new TransformFeedbackResumeTestInstance(context, m_parameters);
2622 
2623 	if (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)
2624 		return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2625 
2626 	if (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)
2627 		return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2628 
2629 	if (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)
2630 		return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2631 
2632 	if (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL)
2633 		return new TransformFeedbackBuiltinTestInstance(context, m_parameters);
2634 
2635 	if (m_parameters.testType == TEST_TYPE_WINDING)
2636 		return new TransformFeedbackWindingOrderTestInstance(context, m_parameters);
2637 
2638 	if (m_parameters.testType == TEST_TYPE_STREAMS)
2639 		return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2640 
2641 	if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
2642 		return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2643 
2644 	if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
2645 		return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2646 
2647 	if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
2648 		return new TransformFeedbackStreamsTestInstance(context, m_parameters);
2649 
2650 	if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2651 		return new TransformFeedbackMultistreamTestInstance(context, m_parameters);
2652 
2653 	if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
2654 		return new TransformFeedbackIndirectDrawTestInstance(context, m_parameters);
2655 
2656 	if (m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY)
2657 		return new TransformFeedbackBackwardDependencyTestInstance(context, m_parameters);
2658 
2659 	if (m_parameters.testType == TEST_TYPE_QUERY_GET				||
2660 		m_parameters.testType == TEST_TYPE_QUERY_COPY				||
2661 		m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO	||
2662 	    m_parameters.testType == TEST_TYPE_QUERY_RESET)
2663 		return new TransformFeedbackQueryTestInstance(context, m_parameters);
2664 
2665 	if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
2666 		return new TransformFeedbackMultiQueryTestInstance(context, m_parameters);
2667 
2668 	if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX	||
2669 		m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY	||
2670 		m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
2671 		return new TransformFeedbackDepthClipControlTestInstance(context, m_parameters);
2672 
2673 	if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
2674 		return new TransformFeedbackLinesOrTrianglesTestInstance(context, m_parameters);
2675 
2676 	TCU_THROW(InternalError, "Specified test type not found");
2677 }
2678 
checkSupport(Context & context) const2679 void TransformFeedbackTestCase::checkSupport (Context& context) const
2680 {
2681 	context.requireDeviceFunctionality("VK_EXT_transform_feedback");
2682 
2683 	if (context.getTransformFeedbackFeaturesEXT().transformFeedback == VK_FALSE)
2684 		TCU_THROW(NotSupportedError, "transformFeedback feature is not supported");
2685 
2686 	// transformFeedbackRasterizationStreamSelect is required when vertex streams other than zero are rasterized
2687 	if (m_parameters.requireRastStreamSelect && (context.getTransformFeedbackPropertiesEXT().transformFeedbackRasterizationStreamSelect == VK_FALSE) && (m_parameters.streamId > 0))
2688 		TCU_THROW(NotSupportedError, "transformFeedbackRasterizationStreamSelect property is not supported");
2689 }
2690 
initPrograms(SourceCollections & programCollection) const2691 void TransformFeedbackTestCase::initPrograms (SourceCollections& programCollection) const
2692 {
2693 	const bool vertexShaderOnly		=  m_parameters.testType == TEST_TYPE_BASIC
2694 									|| m_parameters.testType == TEST_TYPE_RESUME
2695 									|| m_parameters.testType == TEST_TYPE_BACKWARD_DEPENDENCY
2696 									|| (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2697 	const bool requiresFullPipeline	=  m_parameters.testType == TEST_TYPE_STREAMS
2698 									|| m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE
2699 									|| m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE
2700 									|| m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE
2701 									|| (m_parameters.testType == TEST_TYPE_WINDING && m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST);
2702 	const bool xfbBuiltinPipeline	=  m_parameters.testType == TEST_TYPE_XFB_POINTSIZE
2703 									|| m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE
2704 									|| m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE
2705 									|| m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL;
2706 
2707 	if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX)
2708 	{
2709 		// Vertex shader
2710 		{
2711 			std::ostringstream src;
2712 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2713 				<< "\n"
2714 				<< "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2715 				<< "{\n"
2716 				<< "    vec4 gl_Position;\n"
2717 				<< "};\n"
2718 				<< "\n"
2719 				<< "void main(void)\n"
2720 				<< "{\n"
2721 				<< "    gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2722 				<< "}\n";
2723 
2724 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2725 		}
2726 
2727 		return;
2728 	}
2729 
2730 	if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY)
2731 	{
2732 		// Vertex shader
2733 		{
2734 			std::ostringstream src;
2735 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2736 				<< "\n"
2737 				<< "void main(void)\n"
2738 				<< "{\n"
2739 				<< "    gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2740 				<< "}\n";
2741 
2742 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2743 		}
2744 
2745 		// Geometry shader
2746 		{
2747 			std::ostringstream src;
2748 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2749 				<< "\n"
2750 				<< "layout(points) in;\n"
2751 				<< "layout(points, max_vertices = 1) out;\n"
2752 				<< "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2753 				<< "{\n"
2754 				<< "    vec4 gl_Position;\n"
2755 				<< "};\n"
2756 				<< "\n"
2757 				<< "void main(void)\n"
2758 				<< "{\n"
2759 				<< "    gl_Position = gl_in[0].gl_Position;\n"
2760 				<< "    EmitVertex();\n"
2761 				<< "    EndPrimitive();\n"
2762 				<< "}\n";
2763 
2764 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2765 		}
2766 
2767 		return;
2768 	}
2769 
2770 	if (m_parameters.testType == TEST_TYPE_DEPTH_CLIP_CONTROL_TESE)
2771 	{
2772 		// Vertex shader
2773 		{
2774 			std::ostringstream src;
2775 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2776 				<< "\n"
2777 				<< "void main(void)\n"
2778 				<< "{\n"
2779 				<< "    gl_Position = vec4(1.0, 1.0, float(gl_VertexIndex) / 3.0 - 1.0, 1.0);\n"
2780 				<< "}\n";
2781 
2782 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2783 		}
2784 
2785 		// Tesselation control shader
2786 		{
2787 			std::ostringstream src;
2788 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2789 				<< "layout(vertices = 3) out;\n"
2790 				<< "void main (void)\n"
2791 				<< "{\n"
2792 				<< "    gl_TessLevelInner[0] = 0.0;\n"
2793 				<< "    gl_TessLevelOuter[0] = 1.0;\n"
2794 				<< "    gl_TessLevelOuter[1] = 1.0;\n"
2795 				<< "    gl_TessLevelOuter[2] = 1.0;\n"
2796 				<< "    gl_out[gl_InvocationID].gl_Position = gl_in[gl_InvocationID].gl_Position;\n"
2797 				<< "}\n";
2798 			programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2799 		}
2800 
2801 		// Tessellation evaluation shader
2802 		{
2803 			std::ostringstream src;
2804 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2805 				<< "layout(triangles, ccw) in;\n"
2806 				<< "layout(xfb_buffer = 0, xfb_offset = 0) out gl_PerVertex\n"
2807 				<< "{\n"
2808 				<< "    vec4 gl_Position;\n"
2809 				<< "};\n"
2810 				<< "\n"
2811 				<< "void main (void)\n"
2812 				<< "{\n"
2813 				<< "    vec4 p0 = gl_TessCoord.x * gl_in[0].gl_Position;\n"
2814 				<< "    vec4 p1 = gl_TessCoord.y * gl_in[1].gl_Position;\n"
2815 				<< "    vec4 p2 = gl_TessCoord.z * gl_in[2].gl_Position;\n"
2816 				<< "    gl_Position = p0 + p1 + p2;\n"
2817 				<< "}\n";
2818 			programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2819 		}
2820 
2821 		return;
2822 	}
2823 
2824 	if (vertexShaderOnly)
2825 	{
2826 		// Vertex shader
2827 		{
2828 			std::ostringstream src;
2829 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2830 				<< "\n"
2831 				<< "layout(push_constant) uniform pushConstants\n"
2832 				<< "{\n"
2833 				<< "    uint start;\n"
2834 				<< "} uInput;\n"
2835 				<< "\n"
2836 				<< "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2837 				<< "\n"
2838 				<< "void main(void)\n"
2839 				<< "{\n"
2840 				<< "    idx_out = uInput.start + gl_VertexIndex;\n"
2841 				<< "}\n";
2842 
2843 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2844 		}
2845 
2846 		return;
2847 	}
2848 
2849 	if (m_parameters.primTopology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
2850 	{
2851 		// Vertex shader
2852 		{
2853 			std::ostringstream src;
2854 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2855 				<< "layout(push_constant) uniform pushConstants\n"
2856 				<< "{\n"
2857 				<< "    uint start;\n"
2858 				<< "} uInput;\n"
2859 				<< "void main(void)\n"
2860 				<< "{\n"
2861 				<< "}\n";
2862 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2863 		}
2864 
2865 		// Tesselation control shader
2866 		{
2867 			std::ostringstream src;
2868 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2869 				<< "layout(vertices = 3) out;\n"
2870 				<< "void main (void)\n"
2871 				<< "{\n"
2872 				<< "    gl_TessLevelInner[0] = 2.0;\n" // generate three triangles out of each patch
2873 				<< "    gl_TessLevelOuter[0] = 1.0;\n"
2874 				<< "    gl_TessLevelOuter[1] = 1.0;\n"
2875 				<< "    gl_TessLevelOuter[2] = 1.0;\n"
2876 				<< "}\n";
2877 			programCollection.glslSources.add("tesc") << glu::TessellationControlSource(src.str());
2878 		}
2879 
2880 		// Tessellation evaluation shader
2881 		{
2882 			std::ostringstream src;
2883 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2884 				<< "layout(triangles, ccw) in;\n"
2885 				<< "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 4, location = 0) out uint idx_out;\n"
2886 				<< "\n"
2887 				<< "void main (void)\n"
2888 				<< "{\n"
2889 				<< "    idx_out = gl_PrimitiveID;\n" // all vertex generated from patch will have its id
2890 				<< "}\n";
2891 			programCollection.glslSources.add("tese") << glu::TessellationEvaluationSource(src.str());
2892 		}
2893 
2894 		return;
2895 	}
2896 
2897 	if (xfbBuiltinPipeline)
2898 	{
2899 		const std::string	outputBuiltIn		= (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)     ? "float gl_PointSize;\n"
2900 												: (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)  ? "float gl_ClipDistance[8];\n"
2901 												: (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)  ? "float gl_CullDistance[8];\n"
2902 												: (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "float gl_CullDistance[5];\nfloat gl_ClipDistance[1];\n"
2903 												: "";
2904 		const std::string	operationBuiltIn	= (m_parameters.testType == TEST_TYPE_XFB_POINTSIZE)     ? "gl_PointSize = float(gl_VertexIndex) / 32768.0f;"
2905 												: (m_parameters.testType == TEST_TYPE_XFB_CLIPDISTANCE)  ? "for (int i=0; i<8; i++) gl_ClipDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2906 												: (m_parameters.testType == TEST_TYPE_XFB_CULLDISTANCE)  ? "for (int i=0; i<8; i++) gl_CullDistance[i] = float(8 * gl_VertexIndex + i) / 32768.0f;"
2907 												: (m_parameters.testType == TEST_TYPE_XFB_CLIP_AND_CULL) ? "for (int i=0; i<5; i++) gl_CullDistance[i] = float(6 * gl_VertexIndex + i) / 32768.0f;\n"
2908 																										   "gl_ClipDistance[0] = float(6 * gl_VertexIndex + 5) / 32768.0f;\n"
2909 												: "";
2910 
2911 		// Vertex shader
2912 		{
2913 			std::ostringstream src;
2914 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2915 				<< "\n"
2916 				<< "layout(xfb_buffer = " << m_parameters.partCount - 1 << ", xfb_offset = 0) out gl_PerVertex\n"
2917 				<< "{\n"
2918 				<< outputBuiltIn
2919 				<< "};\n"
2920 				<< "\n"
2921 				<< "void main(void)\n"
2922 				<< "{\n"
2923 				<< operationBuiltIn
2924 				<< "}\n";
2925 
2926 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2927 		}
2928 
2929 		return;
2930 	}
2931 
2932 	if (m_parameters.testType == TEST_TYPE_MULTISTREAMS)
2933 	{
2934 		// vertex shader
2935 		{
2936 			std::ostringstream src;
2937 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2938 				<< "\n"
2939 				<< "void main(void)\n"
2940 				<< "{\n"
2941 				<< "}\n";
2942 
2943 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
2944 		}
2945 
2946 		// geometry shader
2947 		{
2948 			const deUint32		s	= m_parameters.streamId;
2949 			std::ostringstream	src;
2950 
2951 			DE_ASSERT(s != 0);
2952 
2953 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
2954 				<< "\n"
2955 				<< "layout(points) in;\n"
2956 				<< "\n"
2957 				<< "layout(points, max_vertices = 32) out;\n"
2958 				<< "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
2959 				<< "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
2960 				<< "\n"
2961 				<< "const int counts[] = int[](1, 1, 2, 4, 8);\n"
2962 				<< "\n"
2963 				<< "void main(void)\n"
2964 				<< "{\n"
2965 				<< "    int c0 = 0;\n"
2966 				<< "    int c1 = 0;\n"
2967 				<< "\n"
2968 				<< "    // Start 1st buffer from point where 0th buffer ended\n"
2969 				<< "    for (int i = 0; i < counts.length(); i++)\n"
2970 				<< "        c1 = c1 + 4 * counts[i];\n"
2971 				<< "\n"
2972 				<< "    for (int i = 0; i < counts.length(); i++)\n"
2973 				<< "    {\n"
2974 				<< "        const int n0 = counts[i];\n"
2975 				<< "        const int n1 = counts[counts.length() - 1 - i];\n"
2976 				<< "\n"
2977 				<< "        for (int j = 0; j < n0; j++)\n"
2978 				<< "        {\n"
2979 				<< "            out0 = vec4(ivec4(c0, c0 + 1, c0 + 2, c0 + 3));\n"
2980 				<< "            c0 = c0 + 4;\n"
2981 				<< "            EmitStreamVertex(0);\n"
2982 				<< "            EndStreamPrimitive(0);\n"
2983 				<< "        }\n"
2984 				<< "\n"
2985 				<< "        for (int j = 0; j < n1; j++)\n"
2986 				<< "        {\n"
2987 				<< "            out1 = vec4(ivec4(c1, c1 + 1, c1 + 2, c1 + 3));\n"
2988 				<< "            c1 = c1 + 4;\n"
2989 				<< "            EmitStreamVertex(" << s << ");\n"
2990 				<< "            EndStreamPrimitive(" << s << ");\n"
2991 				<< "        }\n"
2992 				<< "    }\n"
2993 				<< "}\n";
2994 
2995 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
2996 		}
2997 
2998 		return;
2999 	}
3000 
3001 	if (requiresFullPipeline)
3002 	{
3003 		// vertex shader
3004 		{
3005 			std::ostringstream src;
3006 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3007 				<< "\n"
3008 				<< "void main(void)\n"
3009 				<< "{\n"
3010 				<< "}\n";
3011 
3012 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3013 		}
3014 
3015 		// geometry shader
3016 		{
3017 			const deUint32		s					= m_parameters.streamId;
3018 			const bool			requirePoints		= (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE || m_parameters.testType == TEST_TYPE_MULTISTREAMS);
3019 			const std::string	outputPrimitiveType	= requirePoints ? "points" : "triangle_strip";
3020 			const std::string	outputBuiltIn		= (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)    ? "    float gl_PointSize;\n"
3021 													: (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE) ? "    float gl_ClipDistance[];\n"
3022 													: (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE) ? "    float gl_CullDistance[];\n"
3023 													: "";
3024 			std::ostringstream	src;
3025 
3026 			DE_ASSERT(s != 0);
3027 
3028 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3029 				<< "\n"
3030 				<< "layout(points) in;\n"
3031 				<< "layout(" << outputPrimitiveType << ", max_vertices = 16) out;\n"
3032 				<< "layout(stream = " << s << ") out;\n"
3033 				<< "layout(location = 0) out vec4 color;\n"
3034 				<< "\n"
3035 				<< "layout(stream = " << s << ") out gl_PerVertex\n"
3036 				<< "{\n"
3037 				<< "    vec4 gl_Position;\n"
3038 				<< outputBuiltIn
3039 				<< "};\n"
3040 				<< "\n"
3041 				<< "void main(void)\n"
3042 				<< "{\n"
3043 				<< "    // Color constants\n"
3044 				<< "    vec4 g = vec4(0.0, 1.0, 0.0, 1.0);\n"
3045 				<< "    vec4 m = vec4(1.0, 0.0, 1.0, 1.0);\n"
3046 				<< "    // Coordinate constants: leftmost column\n"
3047 				<< "    vec4 a = vec4(-1.0,-1.0, 0.0, 1.0);\n"
3048 				<< "    vec4 b = vec4(-1.0, 0.0, 0.0, 1.0);\n"
3049 				<< "    vec4 c = vec4(-1.0, 1.0, 0.0, 1.0);\n"
3050 				<< "    // Coordinate constants: middle column\n"
3051 				<< "    vec4 i = vec4( 0.0,-1.0, 0.0, 1.0);\n"
3052 				<< "    vec4 j = vec4( 0.0, 0.0, 0.0, 1.0);\n"
3053 				<< "    vec4 k = vec4( 0.0, 1.0, 0.0, 1.0);\n"
3054 				<< "    // Coordinate constants: rightmost column\n"
3055 				<< "    vec4 x = vec4( 1.0,-1.0, 0.0, 1.0);\n"
3056 				<< "    vec4 y = vec4( 1.0, 0.0, 0.0, 1.0);\n"
3057 				<< "    vec4 z = vec4( 1.0, 1.0, 0.0, 1.0);\n"
3058 				<< "\n";
3059 
3060 			if (m_parameters.testType == TEST_TYPE_STREAMS)
3061 			{
3062 				src << "    if (gl_PrimitiveIDIn == 0)\n"
3063 					<< "    {\n"
3064 					<< "        color = m; gl_Position = b; EmitStreamVertex(" << s << ");\n"
3065 					<< "        color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3066 					<< "        color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3067 					<< "        EndStreamPrimitive(" << s << ");\n"
3068 					<< "    }\n"
3069 					<< "    else\n"
3070 					<< "    {\n"
3071 					<< "        color = m; gl_Position = y; EmitStreamVertex(" << s << ");\n"
3072 					<< "        color = m; gl_Position = c; EmitStreamVertex(" << s << ");\n"
3073 					<< "        color = m; gl_Position = z; EmitStreamVertex(" << s << ");\n"
3074 					<< "        EndStreamPrimitive(" << s << ");\n"
3075 					<< "    }\n";
3076 			}
3077 
3078 			if (m_parameters.testType == TEST_TYPE_STREAMS_POINTSIZE)
3079 			{
3080 				const std::string	pointSize	= "gl_PointSize = " + de::toString(m_parameters.pointSize) + ".0f";
3081 
3082 				src << "    if (gl_PrimitiveIDIn == 0)\n"
3083 					<< "    {\n"
3084 					<< "        color = g; gl_Position = (a + j) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(0);\n"
3085 					<< "        EndStreamPrimitive(0);\n"
3086 					<< "        color = m; gl_Position = (b + k) / 2.0f; gl_PointSize = 1.0f; EmitStreamVertex(" << s << ");\n"
3087 					<< "        EndStreamPrimitive(" << s << ");\n"
3088 					<< "    }\n"
3089 					<< "    else\n"
3090 					<< "    {\n"
3091 					<< "        color = g; gl_Position = (j + x) / 2.0f; " << pointSize << "; EmitStreamVertex(0);\n"
3092 					<< "        EndStreamPrimitive(0);\n"
3093 					<< "        color = m; gl_Position = (k + y) / 2.0f; " << pointSize << "; EmitStreamVertex(" << s << ");\n"
3094 					<< "        EndStreamPrimitive(" << s << ");\n"
3095 					<< "    }\n";
3096 			}
3097 
3098 			if (m_parameters.testType == TEST_TYPE_STREAMS_CLIPDISTANCE)
3099 			{
3100 				src << "    if (gl_PrimitiveIDIn == 0)\n"
3101 					<< "    {\n"
3102 					<< "        color = m; gl_Position = b; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3103 					<< "        color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3104 					<< "        color = m; gl_Position = y; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3105 					<< "        EndStreamPrimitive(" << s << ");\n"
3106 					<< "    }\n"
3107 					<< "    else\n"
3108 					<< "    {\n"
3109 					<< "        color = m; gl_Position = y; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3110 					<< "        color = m; gl_Position = c; gl_ClipDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3111 					<< "        color = m; gl_Position = z; gl_ClipDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3112 					<< "        EndStreamPrimitive(" << s << ");\n"
3113 					<< "    }\n";
3114 			}
3115 
3116 			if (m_parameters.testType == TEST_TYPE_STREAMS_CULLDISTANCE)
3117 			{
3118 				src << "    if (gl_PrimitiveIDIn == 0)\n"
3119 					<< "    {\n"
3120 					<< "        color = m; gl_Position = b; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3121 					<< "        color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3122 					<< "        color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3123 					<< "        EndStreamPrimitive(" << s << ");\n"
3124 					<< "        color = m; gl_Position = j; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3125 					<< "        color = m; gl_Position = c; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3126 					<< "        color = m; gl_Position = k; gl_CullDistance[0] = -1.0; EmitStreamVertex(" << s << ");\n"
3127 					<< "        EndStreamPrimitive(" << s << ");\n"
3128 					<< "    }\n"
3129 					<< "    else\n"
3130 					<< "    {\n"
3131 					<< "        color = m; gl_Position = j; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3132 					<< "        color = m; gl_Position = k; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3133 					<< "        color = m; gl_Position = y; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3134 					<< "        EndStreamPrimitive(" << s << ");\n"
3135 					<< "        color = m; gl_Position = y; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3136 					<< "        color = m; gl_Position = k; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3137 					<< "        color = m; gl_Position = z; gl_CullDistance[0] =  1.0; EmitStreamVertex(" << s << ");\n"
3138 					<< "        EndStreamPrimitive(" << s << ");\n"
3139 					<< "    }\n";
3140 			}
3141 
3142 			src << "}\n";
3143 
3144 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3145 		}
3146 
3147 		// Fragment shader
3148 		{
3149 			std::ostringstream src;
3150 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3151 				<< "\n"
3152 				<< "layout(location = 0) in  vec4 i_color;\n"
3153 				<< "layout(location = 0) out vec4 o_color;\n"
3154 				<< "\n"
3155 				<< "void main(void)\n"
3156 				<< "{\n"
3157 				<< "    o_color = i_color;\n"
3158 				<< "}\n";
3159 
3160 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3161 		}
3162 
3163 		return;
3164 	}
3165 
3166 	if (m_parameters.testType == TEST_TYPE_DRAW_INDIRECT)
3167 	{
3168 		// vertex shader
3169 		{
3170 			std::ostringstream src;
3171 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3172 				<< "\n"
3173 				<< "layout(location = 0) in vec4 in_position;\n"
3174 				<< "\n"
3175 				<< "void main(void)\n"
3176 				<< "{\n"
3177 				<< "    gl_Position = in_position;\n"
3178 				<< "}\n";
3179 
3180 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3181 		}
3182 
3183 		// Fragment shader
3184 		{
3185 			std::ostringstream src;
3186 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3187 				<< "\n"
3188 				<< "layout(location = 0) out vec4 o_color;\n"
3189 				<< "\n"
3190 				<< "void main(void)\n"
3191 				<< "{\n"
3192 				<< "    o_color = vec4(1.0, 1.0, 1.0, 1.0);\n"
3193 				<< "}\n";
3194 
3195 			programCollection.glslSources.add("frag") << glu::FragmentSource(src.str());
3196 		}
3197 
3198 		return;
3199 	}
3200 
3201 	if (m_parameters.testType == TEST_TYPE_QUERY_GET				||
3202 		m_parameters.testType == TEST_TYPE_QUERY_COPY				||
3203 		m_parameters.testType == TEST_TYPE_QUERY_COPY_STRIDE_ZERO	||
3204 		m_parameters.testType == TEST_TYPE_QUERY_RESET)
3205 	{
3206 		struct TopologyShaderInfo
3207 		{
3208 			std::string glslIn;
3209 			std::string glslOut;
3210 			std::string spirvIn;
3211 			std::string spirvOut;
3212 		};
3213 
3214 		const std::map<VkPrimitiveTopology, TopologyShaderInfo>	primitiveNames	=
3215 		{
3216 			{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST						, { "points"				, "points"			, "InputPoints"				, "OutputPoints"		} },
3217 			{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST						, { "lines"					, "line_strip"		, "InputLines"				, "OutputLineStrip"		} },
3218 			{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP						, { "lines"					, "line_strip"		, "InputLines"				, "OutputLineStrip"		} },
3219 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST					, { "triangles"				, "triangle_strip"	, "Triangles"				, "OutputTriangleStrip"	} },
3220 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP					, { "triangles"				, "triangle_strip"	, "Triangles"				, "OutputTriangleStrip"	} },
3221 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN					, { "triangles"				, "triangle_strip"	, "Triangles"				, "OutputTriangleStrip"	} },
3222 			{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY		, { "lines_adjacency"		, "line_strip"		, "InputLinesAdjacency"		, "OutputLineStrip"		} },
3223 			{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY		, { "lines_adjacency"		, "line_strip"		, "InputLinesAdjacency"		, "OutputLineStrip"		} },
3224 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY	, { "triangles_adjacency"	, "triangle_strip"	, "InputTrianglesAdjacency"	, "OutputTriangleStrip"	} },
3225 			{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY	, { "triangles_adjacency"	, "triangle_strip"	, "InputTrianglesAdjacency"	, "OutputTriangleStrip"	} }
3226 		};
3227 
3228 		// Vertex shader
3229 		{
3230 			std::ostringstream src;
3231 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3232 				<< "\n"
3233 				<< "layout(location = 0) out vec4 out0;\n"
3234 				<< "\n"
3235 				<< "void main(void)\n"
3236 				<< "{\n"
3237 				<< "    float n = 4.0 * float(gl_VertexIndex);\n"
3238 				<< "    out0 = vec4(n + 0.0, n + 1.0, n + 2.0, n + 3.0);\n"
3239 				<< "}\n";
3240 
3241 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3242 		}
3243 
3244 		// geometry shader
3245 		if (m_parameters.streamId == 0)
3246 		{
3247 			std::ostringstream	src;
3248 
3249 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3250 				<< "\n"
3251 				<< "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
3252 				<< "layout(location = 0) in vec4 in0[];\n"
3253 				<< "\n"
3254 				<< "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize<< ") out;\n"
3255 				<< "layout(xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3256 				<< "\n"
3257 				<< "void main(void)\n"
3258 				<< "{\n";
3259 
3260 			for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
3261 			{
3262 				if (!m_parameters.omitShaderWrite)
3263 					src << "    out0 = in0[" << i << "];\n";
3264 				src << "    EmitVertex();\n";
3265 			}
3266 
3267 			src << "    EndPrimitive();\n"
3268 				<< "}\n";
3269 
3270 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3271 		}
3272 		else
3273 		{
3274 			const deUint32		s	= m_parameters.streamId;
3275 			std::ostringstream	src;
3276 
3277 			if (m_parameters.testType == TEST_TYPE_QUERY_GET)
3278 			{
3279 				// The SPIR-V program below is roughly equivalent to the following GLSL code:
3280 				//
3281 				// #version 450
3282 				// #extension GL_ARB_enhanced_layouts : require
3283 				//
3284 				// layout(points) in;
3285 				// layout(location = 0) in vec4 in0[];
3286 				//
3287 				// layout(points, max_vertices = 1) out;
3288 				// layout(location=0, stream=1, xfb_buffer=0, xfb_stride=16) out OutBlock {
3289 				//     layout(xfb_offset=0, location=0) vec4 out0;
3290 				// } outBlock;
3291 				//
3292 				// void main(void)
3293 				// {
3294 				//     outBlock.out0 = in0[0];
3295 				//     EmitStreamVertex(1);
3296 				//     EndStreamPrimitive(1);
3297 				// }
3298 				//
3299 				// However, the stream number has been parametrized and the code generated by glslang has been tuned to move the
3300 				// Stream, XfbBuffer and XfbStride decorations to the structure member instead of the block. This allows us to test
3301 				// transform feedback decorations on structure members as part of these basic tests.
3302 				src	<< "; SPIR-V\n"
3303 					<< "; Version: 1.0\n"
3304 					<< "; Generator: Khronos Glslang Reference Front End; 10\n"
3305 					<< "; Bound: 64\n"
3306 					<< "; Schema: 0\n"
3307 					<< "               OpCapability Geometry\n"
3308 					<< "               OpCapability TransformFeedback\n"
3309 					<< "               OpCapability GeometryStreams\n"
3310 					<< "          %1 = OpExtInstImport \"GLSL.std.450\"\n"
3311 					<< "               OpMemoryModel Logical GLSL450\n"
3312 					<< "               OpEntryPoint Geometry %main \"main\" %outBlock %in0\n"
3313 					<< "               OpExecutionMode %main Xfb\n"
3314 					<< "               OpExecutionMode %main " << primitiveNames.at(m_parameters.primTopology).spirvIn << "\n"
3315 					<< "               OpExecutionMode %main Invocations 1\n"
3316 					<< "               OpExecutionMode %main  " << primitiveNames.at(m_parameters.primTopology).spirvOut << "\n"
3317 					<< "               OpExecutionMode %main OutputVertices " << topologyData.at(m_parameters.primTopology).primSize << "\n"
3318 					<< "               OpSource GLSL 450\n"
3319 					<< "               OpSourceExtension \"GL_ARB_enhanced_layouts\"\n"
3320 					<< "               OpName %main \"main\"\n"
3321 					<< "               OpName %OutBlock \"OutBlock\"\n"
3322 					<< "               OpMemberName %OutBlock 0 \"out0\"\n"
3323 					<< "               OpName %outBlock \"outBlock\"\n"
3324 					<< "               OpName %in0 \"in0\"\n"
3325 					<< "               OpMemberDecorate %OutBlock 0 Location 0\n"
3326 					<< "               OpMemberDecorate %OutBlock 0 Offset 0\n"
3327 					// These Stream, XfbBuffer and XfbStride decorations have been moved to the struct member.
3328 					<< "               OpMemberDecorate %OutBlock 0 Stream " << s << "\n"
3329 					<< "               OpMemberDecorate %OutBlock 0 XfbBuffer 0\n"
3330 					<< "               OpMemberDecorate %OutBlock 0 XfbStride 16\n"
3331 					<< "               OpDecorate %OutBlock Block\n"
3332 					// The decorations mentioned above were using OpDecorate and assigned to %outBlock itself here.
3333 					<< "               OpDecorate %in0 Location 0\n"
3334 					<< "       %void = OpTypeVoid\n"
3335 					<< "          %3 = OpTypeFunction %void\n"
3336 					<< "      %float = OpTypeFloat 32\n"
3337 					<< "    %v4float = OpTypeVector %float 4\n"
3338 					<< "   %OutBlock = OpTypeStruct %v4float\n"
3339 					<< "%_ptr_Output_OutBlock = OpTypePointer Output %OutBlock\n"
3340 					<< "   %outBlock = OpVariable %_ptr_Output_OutBlock Output\n"
3341 					<< "        %int = OpTypeInt 32 1\n"
3342 					<< "      %int_0 = OpConstant %int 0\n";
3343 
3344 				for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
3345 				{
3346 					src << "%int_" << i << " = OpConstant %int " << i << "\n";
3347 				}
3348 
3349 				src << "       %uint = OpTypeInt 32 0\n"
3350 					<< "     %uint_0 = OpConstant %uint " << topologyData.at(m_parameters.primTopology).primSize << "\n"
3351 					<< "%_arr_v4float_uint_0 = OpTypeArray %v4float %uint_0\n"
3352 					<< "%_ptr_Input__arr_v4float_uint_0 = OpTypePointer Input %_arr_v4float_uint_0\n"
3353 					<< "        %in0 = OpVariable %_ptr_Input__arr_v4float_uint_0 Input\n"
3354 					<< "%_ptr_Input_v4float = OpTypePointer Input %v4float\n"
3355 					<< "%_ptr_Output_v4float = OpTypePointer Output %v4float\n"
3356 					<< "  %streamNum = OpConstant %int " << s << "\n"
3357 					<< "       %main = OpFunction %void None %3\n"
3358 					<< "          %5 = OpLabel\n";
3359 
3360 				for (deUint32 i = 1; i < topologyData.at(m_parameters.primTopology).primSize + 1; i++)
3361 				{
3362 					src << "%" << i << "1 = OpAccessChain %_ptr_Input_v4float %in0 %int_" << i << "\n"
3363 						<< "          %" << i << "2 = OpLoad %v4float %" << i << "1\n"
3364 						<< "          %" << i << "3 = OpAccessChain %_ptr_Output_v4float %outBlock %int_0\n"
3365 						<< "               OpStore %" << i << "3 %" << i << "2\n"
3366 						<< "               OpEmitStreamVertex %streamNum\n";
3367 				}
3368 
3369 				src << "               OpEndStreamPrimitive %streamNum\n"
3370 					<< "               OpReturn\n"
3371 					<< "               OpFunctionEnd\n"
3372 					;
3373 
3374 				programCollection.spirvAsmSources.add("geom") << src.str();
3375 			}
3376 			else
3377 			{
3378 				src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3379 					<< "\n"
3380 					<< "layout(" << primitiveNames.at(m_parameters.primTopology).glslIn << ") in;\n"
3381 					<< "layout(location = 0) in vec4 in0[];\n"
3382 					<< "\n"
3383 					<< "layout(" << primitiveNames.at(m_parameters.primTopology).glslOut << ", max_vertices = " << topologyData.at(m_parameters.primTopology).primSize << ") out;\n"
3384 					<< "layout(stream = " << s << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3385 					<< "\n"
3386 					<< "void main(void)\n"
3387 					<< "{\n";
3388 
3389 				for (deUint32 i = 0; i < topologyData.at(m_parameters.primTopology).primSize; i++)
3390 				{
3391 					src << "    out0 = in0[" << i << "];\n"
3392 						<< "    EmitStreamVertex(" << s << ");\n";
3393 				}
3394 
3395 				src << "    EndStreamPrimitive(" << s << ");\n"
3396 					<< "}\n";
3397 
3398 				programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3399 			}
3400 		}
3401 
3402 		return;
3403 	}
3404 
3405 	if (m_parameters.testType == TEST_TYPE_MULTIQUERY)
3406 	{
3407 		// vertex shader
3408 		{
3409 			std::ostringstream src;
3410 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3411 				<< "\n"
3412 				<< "layout(location = 0) out ivec4 out0;\n"
3413 				<< "\n"
3414 				<< "void main(void)\n"
3415 				<< "{\n"
3416 				<< "    out0 = ivec4(gl_VertexIndex);\n"
3417 				<< "}\n";
3418 
3419 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3420 		}
3421 
3422 		// geometry shader
3423 		{
3424 			const deUint32		s	= m_parameters.streamId;
3425 			std::ostringstream	src;
3426 
3427 			DE_ASSERT(s != 0);
3428 
3429 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3430 				<< "\n"
3431 				<< "layout(points) in;\n"
3432 				<< "\n"
3433 				<< "layout(points, max_vertices = 4) out;\n"
3434 				<< "\n"
3435 				<< "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3436 				<< "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
3437 				<< "\n"
3438 				<< "void main(void)\n"
3439 				<< "{\n"
3440 				<< "    const int   n0 = 3;\n"
3441 				<< "    const int   n1 = 1;\n"
3442 				<< "    const float c0 = 0.5f;\n"
3443 				<< "    const float c1 = 0.5f + float(" << s << ");\n"
3444 				<< "\n"
3445 				<< "    for (int j = 0; j < n0; j++)\n"
3446 				<< "    {\n";
3447 
3448 			if (!m_parameters.omitShaderWrite)
3449 				src << "        out0 = vec4(c0);\n";
3450 
3451 			src	<< "        EmitStreamVertex(0);\n"
3452 				<< "        EndStreamPrimitive(0);\n"
3453 				<< "    }\n"
3454 				<< "\n"
3455 				<< "    for (int j = 0; j < n1; j++)\n"
3456 				<< "    {\n"
3457 				<< "        out1 = vec4(c1);\n"
3458 				<< "        EmitStreamVertex(" << s << ");\n"
3459 				<< "        EndStreamPrimitive(" << s << ");\n"
3460 				<< "    }\n"
3461 				<< "}\n";
3462 
3463 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3464 		}
3465 
3466 		return;
3467 	}
3468 
3469 	if (m_parameters.testType == TEST_TYPE_LINES_TRIANGLES)
3470 	{
3471 		// vertex shader
3472 		{
3473 			std::ostringstream src;
3474 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3475 				<< "\n"
3476 				<< "void main(void)\n"
3477 				<< "{\n"
3478 				<< "}\n";
3479 
3480 			programCollection.glslSources.add("vert") << glu::VertexSource(src.str());
3481 		}
3482 
3483 		// geometry shader
3484 		{
3485 			const deUint32		s			= m_parameters.streamId;
3486 			const bool			line		= isPrimitiveTopologyLine(m_parameters.primTopology);
3487 			const bool			tri			= isPrimitiveTopologyTriangle(m_parameters.primTopology);
3488 			const std::string	p			= line ? std::string("line_strip")
3489 											: tri ? std::string("triangle_strip")
3490 											: std::string("");
3491 			const std::string	vertexCount	= line ? vectorToString(LINES_LIST)
3492 											: tri ? vectorToString(TRIANGLES_LIST)
3493 											: std::string("");
3494 			std::ostringstream	src;
3495 
3496 			DE_ASSERT(s != 0);
3497 
3498 			src << glu::getGLSLVersionDeclaration(glu::GLSL_VERSION_450) << "\n"
3499 				<< "\n"
3500 				<< "layout(points) in;\n"
3501 				<< "\n"
3502 				<< "layout(" << p << ", max_vertices = 256) out;\n"
3503 				<< "layout(stream = " << 0 << ", xfb_buffer = 0, xfb_offset = 0, xfb_stride = 16, location = 0) out vec4 out0;\n"
3504 				<< "layout(stream = " << s << ", xfb_buffer = 1, xfb_offset = 0, xfb_stride = 16, location = 1) out vec4 out1;\n"
3505 				<< "\n"
3506 				<< "const int vertices_in_primitive[] = int[](" << vertexCount  << ");\n"
3507 				<< "\n"
3508 				<< "int num_vertices_in_primitives()\n"
3509 				<< "{\n"
3510 				<< "    int c = 0;\n"
3511 				<< "\n"
3512 				<< "    for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
3513 				<< "        c = c + vertices_in_primitive[i];\n"
3514 				<< "\n"
3515 				<< "    return c;\n"
3516 				<< "}\n"
3517 				<< "\n"
3518 				<< "void main(void)\n"
3519 				<< "{\n"
3520 				<< "    int vc = num_vertices_in_primitives();\n"
3521 				<< "    int c0 = vc * gl_PrimitiveIDIn;\n"
3522 				<< "    int c1 = vc * (" << INVOCATION_COUNT << " + gl_PrimitiveIDIn);\n"
3523 				<< "\n"
3524 				<< "    for (int i = 0; i < vertices_in_primitive.length(); i++)\n"
3525 				<< "    {\n"
3526 				<< "        const int n = vertices_in_primitive[i];\n"
3527 				<< "\n"
3528 				<< "        for (int j = 0; j < n; j++)\n"
3529 				<< "        {\n"
3530 				<< "            out0 = vec4(ivec4(c0, gl_PrimitiveIDIn, i, j));\n"
3531 				<< "            c0 = c0 + 1;\n"
3532 				<< "            EmitStreamVertex(0);\n"
3533 				<< "\n"
3534 				<< "            out1 = vec4(ivec4(c1, gl_PrimitiveIDIn, i, j));\n"
3535 				<< "            c1 = c1 + 1;\n"
3536 				<< "            EmitStreamVertex(" << s << ");\n"
3537 				<< "        }\n"
3538 				<< "\n"
3539 				<< "        EndStreamPrimitive(0);\n"
3540 				<< "        EndStreamPrimitive(" << s << ");\n"
3541 				<< "    }\n"
3542 				<< "}\n";
3543 
3544 			programCollection.glslSources.add("geom") << glu::GeometrySource(src.str());
3545 		}
3546 
3547 		return;
3548 	}
3549 
3550 	DE_ASSERT(0 && "Unknown test");
3551 }
3552 
createTransformFeedbackSimpleTests(tcu::TestCaseGroup * group)3553 void createTransformFeedbackSimpleTests(tcu::TestCaseGroup* group)
3554 {
3555 	{
3556 		const deUint32		bufferCounts[]	= { 1u, 2u, 4u, 8u };
3557 		const deUint32		bufferSizes[]	= { 256u, 512u, 128u * 1024u };
3558 		const TestType		testTypes[]		= { TEST_TYPE_BASIC, TEST_TYPE_RESUME, TEST_TYPE_XFB_POINTSIZE, TEST_TYPE_XFB_CLIPDISTANCE, TEST_TYPE_XFB_CULLDISTANCE, TEST_TYPE_XFB_CLIP_AND_CULL };
3559 		const std::string	testTypeNames[]	= { "basic", "resume", "xfb_pointsize", "xfb_clipdistance", "xfb_culldistance", "xfb_clip_and_cull" };
3560 
3561 		for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3562 		{
3563 			const TestType		testType	= testTypes[testTypesNdx];
3564 			const std::string	testName	= testTypeNames[testTypesNdx];
3565 
3566 			for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
3567 			{
3568 				const deUint32	partCount	= bufferCounts[bufferCountsNdx];
3569 
3570 				for (deUint32 bufferSizesNdx = 0; bufferSizesNdx < DE_LENGTH_OF_ARRAY(bufferSizes); ++bufferSizesNdx)
3571 				{
3572 					const deUint32	bufferSize	= bufferSizes[bufferSizesNdx];
3573 					TestParameters	parameters	= { testType, bufferSize, partCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3574 
3575 					group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3576 					parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3577 					group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3578 					parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3579 					group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(partCount) + "_" + de::toString(bufferSize)).c_str(), "Simple Transform Feedback test", parameters));
3580 				}
3581 			}
3582 		}
3583 	}
3584 
3585 	{
3586 		const deUint32		bufferCounts[]	= { 6u, 8u, 10u, 12u };
3587 		const TestType		testType		= TEST_TYPE_WINDING;
3588 		const std::string	testName		= "winding";
3589 
3590 		for (const auto& topology : topologyData)
3591 		{
3592 			// Note: no need to test POINT_LIST as is tested in many tests.
3593 			if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST)
3594 				continue;
3595 
3596 			for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(bufferCounts); ++bufferCountsNdx)
3597 			{
3598 				const deUint32	vertexCount	= bufferCounts[bufferCountsNdx];
3599 
3600 				TestParameters	parameters	= { testType, 0u, vertexCount, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, topology.first };
3601 
3602 				group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + topology.second.topologyName + de::toString(vertexCount)).c_str(), "Topology winding test", parameters));
3603 			}
3604 		}
3605 	}
3606 
3607 	{
3608 		const deUint32		vertexStrides[]	= { 4u, 61u, 127u, 251u, 509u };
3609 		const TestType		testType		= TEST_TYPE_DRAW_INDIRECT;
3610 		const std::string	testName		= "draw_indirect";
3611 
3612 		for (deUint32 vertexStridesNdx = 0; vertexStridesNdx < DE_LENGTH_OF_ARRAY(vertexStrides); ++vertexStridesNdx)
3613 		{
3614 			const deUint32	vertexStrideBytes	= static_cast<deUint32>(sizeof(deUint32) * vertexStrides[vertexStridesNdx]);
3615 			TestParameters	parameters			= { testType, 0u, 0u, 0u, 0u, vertexStrideBytes, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3616 
3617 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3618 			parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3619 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3620 			parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3621 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0_" + de::toString(vertexStrideBytes)).c_str(), "Rendering tests with various strides", parameters));
3622 		}
3623 	}
3624 
3625 	{
3626 		const TestType		testType	= TEST_TYPE_BACKWARD_DEPENDENCY;
3627 		const std::string	testName	= "backward_dependency";
3628 		TestParameters		parameters	= { testType, 512u, 2u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3629 
3630 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testName.c_str(), "Rendering test checks backward pipeline dependency", parameters));
3631 		parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3632 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_beginqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
3633 		parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3634 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_endqueryindexed_streamid_0").c_str(), "Rendering test checks backward pipeline dependency", parameters));
3635 
3636 		parameters.noOffsetArray = true;
3637 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_no_offset_array").c_str(), "Rendering test checks backward pipeline dependency (using NULL for offset array)", parameters));
3638 	}
3639 
3640 	{
3641 		const deUint32		usedStreamId[]			= { 0u, 1u, 3u, 6u, 14u };
3642 		const deUint32		vertexCounts[]			= { 6u, 61u, 127u, 251u, 509u }; // Lowest value has to be at least 6. Otherwise the triangles with adjacency can't be generated.
3643 		const TestType		testType				= TEST_TYPE_QUERY_GET;
3644 		const std::string	testName				= "query";
3645 		const TestType		testTypeCopy[]			= { TEST_TYPE_QUERY_COPY, TEST_TYPE_QUERY_COPY_STRIDE_ZERO };
3646 		const std::string	testNameCopy[]			= { "query_copy", "query_copy_stride_zero" };
3647 		const TestType		testTypeHostQueryReset	= TEST_TYPE_QUERY_RESET;
3648 		const std::string	testNameHostQueryReset	= "host_query_reset";
3649 
3650 		for (const auto& topology : topologyData)
3651 		{
3652 			// Currently, we don't test tessellation here.
3653 			if (topology.first == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST)
3654 				continue;
3655 
3656 			for (const auto& streamCounts : usedStreamId)
3657 			{
3658 				const deUint32	streamId	= streamCounts;
3659 
3660 				for (const auto& numVertices : vertexCounts)
3661 				{
3662 					for (deUint32 i = 0; i < 2; ++i)
3663 					{
3664 						const bool				query64Bits		= (i == 1);
3665 						const std::string		widthStr		= (query64Bits ? "_64bits" : "_32bits");
3666 
3667 						deUint32				vertCount		= numVertices;
3668 
3669 						// The number of vertices in original test was 4.
3670 						if (topology.first == VK_PRIMITIVE_TOPOLOGY_POINT_LIST && vertCount == 6) vertCount -= 2;
3671 
3672 						// Round the number of vertices to match the used primitive topology - if necessary.
3673 						const deUint32			primitiveCount	= (deUint32)topology.second.getNumPrimitives(vertCount);
3674 						const deUint32			vertexCount		= (deUint32)topology.second.getNumVertices(primitiveCount);
3675 
3676 						DE_ASSERT(vertexCount > 0);
3677 
3678 						const deUint32			bytesPerVertex	= static_cast<deUint32>(4 * sizeof(float));
3679 						const deUint32			bufferSize		= bytesPerVertex * vertexCount;
3680 						TestParameters			parameters		= { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3681 						const std::string		fullTestName	= testName + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3682 						group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "Written primitives query test", parameters));
3683 
3684 						TestParameters			omitParameters	= { testType, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, true, topology.first };
3685 						const std::string		omitTestName	= testName + "_omit_write_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3686 						group->addChild(new TransformFeedbackTestCase(group->getTestContext(), omitTestName.c_str(), "Written primitives query test", omitParameters));
3687 
3688 						for (deUint32 testTypeCopyNdx = 0; testTypeCopyNdx < DE_LENGTH_OF_ARRAY(testTypeCopy); testTypeCopyNdx++)
3689 						{
3690 							const TestParameters	parametersCopy		= { testTypeCopy[testTypeCopyNdx], bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3691 							const std::string		fullTestNameCopy	= testNameCopy[testTypeCopyNdx] + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3692 							group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameCopy.c_str(), "Written primitives query test", parametersCopy));
3693 						}
3694 
3695 						const TestParameters	parametersHostQueryReset	= { testTypeHostQueryReset, bufferSize, 0u, streamId, 0u, 0u, STREAM_ID_0_NORMAL, query64Bits, false, true, false, topology.first };
3696 						const std::string		fullTestNameHostQueryReset	= testNameHostQueryReset + "_" + topology.second.topologyName + de::toString(streamId) + "_" + de::toString(vertexCount) + widthStr;
3697 						group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestNameHostQueryReset.c_str(), "Written primitives query test", parametersHostQueryReset));
3698 
3699 						if (streamId == 0)
3700 						{
3701 							std::string	testNameStream0 = fullTestName;
3702 							testNameStream0 += "_beginqueryindexed_streamid_0";
3703 							parameters.streamId0Mode = STREAM_ID_0_BEGIN_QUERY_INDEXED;
3704 							group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3705 							testNameStream0 = fullTestName;
3706 							testNameStream0 += "_endqueryindexed_streamid_0";
3707 							parameters.streamId0Mode = STREAM_ID_0_END_QUERY_INDEXED;
3708 							group->addChild(new TransformFeedbackTestCase(group->getTestContext(), testNameStream0.c_str(), "Written primitives query test", parameters));
3709 						}
3710 					}
3711 				}
3712 			}
3713 		}
3714 	}
3715 
3716 	// Depth clip control tests.
3717 	{
3718 		TestParameters	parameters	= { TEST_TYPE_DEPTH_CLIP_CONTROL_VERTEX, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3719 
3720 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_vertex", "", parameters));
3721 	}
3722 	{
3723 		TestParameters	parameters	= { TEST_TYPE_DEPTH_CLIP_CONTROL_GEOMETRY, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3724 
3725 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_geometry", "", parameters));
3726 	}
3727 	{
3728 		TestParameters	parameters	= { TEST_TYPE_DEPTH_CLIP_CONTROL_TESE, 96, 1u, 0u, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_PATCH_LIST };
3729 
3730 		group->addChild(new TransformFeedbackTestCase(group->getTestContext(), "depth_clip_control_tese", "", parameters));
3731 	}
3732 
3733 	{
3734 		const deUint32		usedStreamId[]	= { 1u, 3u, 6u, 14u };
3735 		const TestType		testType		= TEST_TYPE_LINES_TRIANGLES;
3736 		const std::string	testName		= "lines_or_triangles";
3737 
3738 		for (const auto& topology : topologyData)
3739 		{
3740 			const deUint32	outputVertexCount	= (topology.first == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP)     ? 2 * destripedLineCount(LINES_LIST)
3741 												: (topology.first == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP) ? 3 * destripedTriangleCount(TRIANGLES_LIST)
3742 												: 0;
3743 
3744 			if (outputVertexCount == 0)
3745 				continue;
3746 
3747 			for (const auto& streamId : usedStreamId)
3748 			{
3749 				const deUint32			partCount		= 2u;
3750 				const deUint32			bytesPerVertex	= static_cast<deUint32>(sizeof(tcu::Vec4));
3751 				const deUint32			bufferSize		= partCount * INVOCATION_COUNT * outputVertexCount * bytesPerVertex;
3752 				const std::string		fullTestName	= testName + "_" + topology.second.topologyName + de::toString(streamId);
3753 				const TestParameters	parameters		=
3754 				{
3755 					testType,			//  TestType			testType;
3756 					bufferSize,			//  deUint32			bufferSize;
3757 					partCount,			//  deUint32			partCount;
3758 					streamId,			//  deUint32			streamId;
3759 					0u,					//  deUint32			pointSize;
3760 					0u,					//  deUint32			vertexStride;
3761 					STREAM_ID_0_NORMAL,	//  StreamId0Mode		streamId0Mode;
3762 					false,				//  bool				query64bits;
3763 					false,				//  bool				noOffsetArray;
3764 					true,				//  bool				requireRastStreamSelect;
3765 					false,				//  bool				omitShaderWrite;
3766 					topology.first		//  VkPrimitiveTopology	primTopology;
3767 				};
3768 
3769 				group->addChild(new TransformFeedbackTestCase(group->getTestContext(), fullTestName.c_str(), "", parameters));
3770 			}
3771 		}
3772 	}
3773 }
3774 
createTransformFeedbackStreamsSimpleTests(tcu::TestCaseGroup * group)3775 void createTransformFeedbackStreamsSimpleTests (tcu::TestCaseGroup* group)
3776 {
3777 	const deUint32		usedStreamId[]		= { 1u, 3u, 6u, 14u };
3778 	const TestType		testTypes[]			= { TEST_TYPE_STREAMS, TEST_TYPE_STREAMS_POINTSIZE, TEST_TYPE_STREAMS_CLIPDISTANCE, TEST_TYPE_STREAMS_CULLDISTANCE };
3779 	const std::string	testTypeNames[]		= { "streams", "streams_pointsize", "streams_clipdistance", "streams_culldistance" };
3780 
3781 	for (deUint32 testTypesNdx = 0; testTypesNdx < DE_LENGTH_OF_ARRAY(testTypes); ++testTypesNdx)
3782 	{
3783 		const TestType		testType	= testTypes[testTypesNdx];
3784 		const std::string	testName	= testTypeNames[testTypesNdx];
3785 		const deUint32		pointSize	= (testType == TEST_TYPE_STREAMS_POINTSIZE) ? 2u : 0u;
3786 
3787 		for (deUint32 streamCountsNdx = 0; streamCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++streamCountsNdx)
3788 		{
3789 			const deUint32	streamId	= usedStreamId[streamCountsNdx];
3790 			TestParameters	parameters	= { testType, 0u, 0u, streamId, pointSize, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3791 
3792 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Streams usage test", parameters));
3793 		}
3794 	}
3795 
3796 	{
3797 		const TestType		testType	= TEST_TYPE_MULTISTREAMS;
3798 		const std::string	testName	= "multistreams";
3799 
3800 		for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3801 		{
3802 			const deUint32			streamId			= usedStreamId[bufferCountsNdx];
3803 			const deUint32			streamsUsed			= 2u;
3804 			const deUint32			maxBytesPerVertex	= 256u;
3805 			const TestParameters	parameters			= { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, true, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3806 
3807 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple streams usage test", parameters));
3808 		}
3809 	}
3810 
3811 	{
3812 		const TestType		testType	= TEST_TYPE_MULTIQUERY;
3813 		const std::string	testName	= "multiquery";
3814 
3815 		for (deUint32 bufferCountsNdx = 0; bufferCountsNdx < DE_LENGTH_OF_ARRAY(usedStreamId); ++bufferCountsNdx)
3816 		{
3817 			const deUint32			streamId			= usedStreamId[bufferCountsNdx];
3818 			const deUint32			streamsUsed			= 2u;
3819 			const deUint32			maxBytesPerVertex	= 256u;
3820 			const TestParameters	parameters			= { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, false, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3821 			const TestParameters	writeOmitParameters	= { testType, maxBytesPerVertex * streamsUsed, streamsUsed, streamId, 0u, 0u, STREAM_ID_0_NORMAL, false, false, false, true, VK_PRIMITIVE_TOPOLOGY_POINT_LIST };
3822 
3823 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", parameters));
3824 			group->addChild(new TransformFeedbackTestCase(group->getTestContext(), (testName + "_omit_write_" + de::toString(streamId)).c_str(), "Simultaneous multiple queries usage test", writeOmitParameters));
3825 		}
3826 	}
3827 }
3828 
createTransformFeedbackAndStreamsSimpleTests(tcu::TestCaseGroup * group)3829 void createTransformFeedbackAndStreamsSimpleTests (tcu::TestCaseGroup* group)
3830 {
3831 	createTransformFeedbackSimpleTests(group);
3832 	createTransformFeedbackStreamsSimpleTests(group);
3833 }
3834 } // anonymous
3835 
createTransformFeedbackSimpleTests(tcu::TestContext & testCtx)3836 tcu::TestCaseGroup* createTransformFeedbackSimpleTests (tcu::TestContext& testCtx)
3837 {
3838 	return createTestGroup(testCtx, "simple", "Transform Feedback Simple tests", createTransformFeedbackAndStreamsSimpleTests);
3839 }
3840 
3841 } // TransformFeedback
3842 } // vkt
3843