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