• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2019 The Khronos Group Inc.
6  * Copyright (c) 2019 Google LLC.
7  *
8  * Licensed under the Apache License, Version 2.0 (the "License");
9  * you may not use this file except in compliance with the License.
10  * You may obtain a copy of the License at
11  *
12  *      http://www.apache.org/licenses/LICENSE-2.0
13  *
14  * Unless required by applicable law or agreed to in writing, software
15  * distributed under the License is distributed on an "AS IS" BASIS,
16  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
17  * See the License for the specific language governing permissions and
18  * limitations under the License.
19  *
20  *//*!
21  * \file
22  * \brief Tests for provoking vertex
23  *//*--------------------------------------------------------------------*/
24 
25 #include "vktRasterizationProvokingVertexTests.hpp"
26 
27 #include "vkBarrierUtil.hpp"
28 #include "vkCmdUtil.hpp"
29 #include "vkImageUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkQueryUtil.hpp"
32 #include "vkRefUtil.hpp"
33 #include "vkTypeUtil.hpp"
34 #include "vktTestGroupUtil.hpp"
35 #include "tcuRGBA.hpp"
36 #include "tcuSurface.hpp"
37 #include "tcuTextureUtil.hpp"
38 #include "tcuTestLog.hpp"
39 
40 using namespace vk;
41 
42 namespace vkt
43 {
44 namespace rasterization
45 {
46 namespace
47 {
48 
49 enum ProvokingVertexMode
50 {
51 	PROVOKING_VERTEX_DEFAULT,
52 	PROVOKING_VERTEX_FIRST,
53 	PROVOKING_VERTEX_LAST,
54 	PROVOKING_VERTEX_PER_PIPELINE
55 };
56 
57 struct Params
58 {
59 	VkFormat			format;
60 	tcu::UVec2			size;
61 	VkPrimitiveTopology	primitiveTopology;
62 	bool				requireGeometryShader;
63 	bool				transformFeedback;
64 	ProvokingVertexMode	provokingVertexMode;
65 };
66 
getXfbBufferSize(deUint32 vertexCount,VkPrimitiveTopology topology)67 static VkDeviceSize getXfbBufferSize (deUint32 vertexCount, VkPrimitiveTopology topology)
68 {
69 	switch (topology)
70 	{
71 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
72 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
73 			return vertexCount * sizeof(tcu::Vec4);
74 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
75 			return (vertexCount - 1) * 2 * sizeof(tcu::Vec4);
76 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
77 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
78 			return (vertexCount - 2) * 3 * sizeof(tcu::Vec4);
79 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
80 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
81 			return vertexCount / 2 * sizeof(tcu::Vec4);
82 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
83 			return (vertexCount - 3) * 2 * sizeof(tcu::Vec4);
84 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
85 			return (vertexCount / 2 - 2) * 3 * sizeof(tcu::Vec4);
86 		default:
87 			DE_FATAL("Unknown primitive topology");
88 			return 0;
89 	}
90 }
91 
verifyXfbBuffer(const tcu::Vec4 * const xfbResults,deUint32 count,VkPrimitiveTopology topology,ProvokingVertexMode mode,std::string & errorMessage)92 static bool verifyXfbBuffer (const tcu::Vec4* const	xfbResults,
93 							 deUint32				count,
94 							 VkPrimitiveTopology	topology,
95 							 ProvokingVertexMode	mode,
96 							 std::string&			errorMessage)
97 {
98 	const deUint32	primitiveSize	= ((topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST) ||
99 									   (topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP) ||
100 									   (topology == VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY) ||
101 									   (topology == VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY))
102 									? 2
103 									: 3;
104 
105 	const tcu::Vec4	expected		(1.0f, 0.0f, 0.0f, 1.0f);
106 	const deUint32	start			= (mode == PROVOKING_VERTEX_LAST)
107 									? primitiveSize - 1
108 									: 0;
109 
110 	DE_ASSERT(count % primitiveSize == 0);
111 
112 	for (deUint32 ndx = start; ndx < count; ndx += primitiveSize)
113 	{
114 		if (xfbResults[ndx] != expected)
115 		{
116 			errorMessage =	"Vertex " + de::toString(ndx) +
117 							": Expected red, got " + de::toString(xfbResults[ndx]);
118 			return false;
119 		}
120 	}
121 
122 	errorMessage = "";
123 	return true;
124 }
125 
126 class ProvokingVertexTestInstance : public TestInstance
127 {
128 public:
129 						ProvokingVertexTestInstance	(Context& context, Params params);
130 	tcu::TestStatus		iterate						(void);
131 	Move<VkRenderPass>	makeRenderPass				(const DeviceInterface& vk, const VkDevice device);
132 private:
133 	Params	m_params;
134 };
135 
ProvokingVertexTestInstance(Context & context,Params params)136 ProvokingVertexTestInstance::ProvokingVertexTestInstance (Context& context, Params params)
137 	: TestInstance	(context)
138 	, m_params		(params)
139 {
140 }
141 
142 class ProvokingVertexTestCase : public TestCase
143 {
144 public:
145 							ProvokingVertexTestCase	(tcu::TestContext&	testCtx,
146 													 const std::string&	name,
147 													 const std::string&	description,
148 													 const Params	params);
149 	virtual void			initPrograms			(SourceCollections& programCollection) const;
150 	virtual void			checkSupport			(Context& context) const;
151 	virtual TestInstance*	createInstance			(Context& context) const;
152 private:
153 	const Params			m_params;
154 };
155 
ProvokingVertexTestCase(tcu::TestContext & testCtx,const std::string & name,const std::string & description,const Params params)156 ProvokingVertexTestCase::ProvokingVertexTestCase (tcu::TestContext& testCtx,
157 												  const std::string& name,
158 												  const std::string& description,
159 												  const Params params)
160 	: TestCase	(testCtx, name, description)
161 	, m_params	(params)
162 {
163 }
164 
initPrograms(SourceCollections & programCollection) const165 void ProvokingVertexTestCase::initPrograms (SourceCollections& programCollection) const
166 {
167 	std::ostringstream vertShader;
168 
169 	vertShader	<< "#version 450\n"
170 				<< "layout(location = 0) in vec4 in_position;\n"
171 				<< "layout(location = 1) in vec4 in_color;\n"
172 				<< "layout(location = 0) flat out vec4 out_color;\n";
173 
174 	if (m_params.transformFeedback)
175 		vertShader << "layout(xfb_buffer = 0, xfb_offset = 0, location = 1) out vec4 out_xfb;\n";
176 
177 	vertShader	<< "void main()\n"
178 				<< "{\n";
179 
180 	if (m_params.transformFeedback)
181 		vertShader << "    out_xfb = in_color;\n";
182 
183 	vertShader	<< "    out_color = in_color;\n"
184 				<< "    gl_Position = in_position;\n"
185 				<< "}\n";
186 
187 	const std::string	fragShader (
188 		"#version 450\n"
189 		"layout(location = 0) flat in vec4 in_color;\n"
190 		"layout(location = 0) out vec4 out_color;\n"
191 		"void main()\n"
192 		"{\n"
193 		"    out_color = in_color;\n"
194 		"}\n");
195 
196 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.str());
197 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
198 }
199 
checkSupport(Context & context) const200 void ProvokingVertexTestCase::checkSupport (Context& context) const
201 {
202 	if (m_params.requireGeometryShader)
203 		context.requireDeviceCoreFeature(DEVICE_CORE_FEATURE_GEOMETRY_SHADER);
204 
205 	if (m_params.transformFeedback)
206 		context.requireDeviceFunctionality("VK_EXT_transform_feedback");
207 
208 	if (m_params.provokingVertexMode != PROVOKING_VERTEX_DEFAULT)
209 	{
210 		const VkPhysicalDeviceProvokingVertexFeaturesEXT&	features	= context.getProvokingVertexFeaturesEXT();
211 		const VkPhysicalDeviceProvokingVertexPropertiesEXT&	properties	= context.getProvokingVertexPropertiesEXT();
212 
213 		context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
214 
215 		if (m_params.transformFeedback && features.transformFeedbackPreservesProvokingVertex != VK_TRUE)
216 			TCU_THROW(NotSupportedError, "transformFeedbackPreservesProvokingVertex not supported");
217 
218 		if (m_params.transformFeedback && (m_params.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN) && (properties.transformFeedbackPreservesTriangleFanProvokingVertex != VK_TRUE))
219 			TCU_THROW(NotSupportedError, "transformFeedbackPreservesTriangleFanProvokingVertex not supported");
220 
221 		if (m_params.provokingVertexMode != PROVOKING_VERTEX_FIRST)
222 		{
223 			if (features.provokingVertexLast != VK_TRUE)
224 				TCU_THROW(NotSupportedError, "VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT not supported");
225 
226 			if ((m_params.provokingVertexMode == PROVOKING_VERTEX_PER_PIPELINE) && (properties.provokingVertexModePerPipeline != VK_TRUE))
227 				TCU_THROW(NotSupportedError, "provokingVertexModePerPipeline not supported");
228 		}
229 	}
230 
231 	if (m_params.primitiveTopology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN &&
232 		context.isDeviceFunctionalitySupported("VK_KHR_portability_subset") &&
233 		!context.getPortabilitySubsetFeatures().triangleFans)
234 	{
235 		TCU_THROW(NotSupportedError, "VK_KHR_portability_subset: Triangle fans are not supported by this implementation");
236 	}
237 }
238 
createInstance(Context & context) const239 TestInstance* ProvokingVertexTestCase::createInstance (Context& context) const
240 {
241 	return new ProvokingVertexTestInstance(context, m_params);
242 }
243 
iterate(void)244 tcu::TestStatus ProvokingVertexTestInstance::iterate (void)
245 {
246 	const bool					useProvokingVertexExt	= (m_params.provokingVertexMode != PROVOKING_VERTEX_DEFAULT);
247 	const DeviceInterface&		vk						= m_context.getDeviceInterface();
248 	const VkDevice				device					= m_context.getDevice();
249 	const deUint32				queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
250 	const tcu::TextureFormat	textureFormat			= vk::mapVkFormat(m_params.format);
251 	const VkDeviceSize			counterBufferOffset		= 0u;
252 	Allocator&					allocator				= m_context.getDefaultAllocator();
253 	Move<VkImage>				image;
254 	Move<VkImageView>			imageView;
255 	de::MovePtr<Allocation>		imageMemory;
256 	Move<VkBuffer>				resultBuffer;
257 	de::MovePtr<Allocation>		resultBufferMemory;
258 	Move<VkBuffer>				xfbBuffer;
259 	de::MovePtr<Allocation>		xfbBufferMemory;
260 	VkDeviceSize				xfbBufferSize			= 0;
261 	Move<VkBuffer>				counterBuffer;
262 	de::MovePtr<Allocation>		counterBufferMemory;
263 	Move<VkBuffer>				vertexBuffer;
264 	de::MovePtr<Allocation>		vertexBufferMemory;
265 	Move<VkRenderPass>			renderPass;
266 	Move<VkFramebuffer>			framebuffer;
267 	Move<VkPipeline>			pipeline;
268 	Move<VkPipeline>			altPipeline;
269 	deUint32					vertexCount				= 0;
270 
271 	// Image
272 	{
273 		const VkExtent3D		extent		= makeExtent3D(m_params.size.x(), m_params.size.y(), 1u);
274 		const VkImageUsageFlags	usage		= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT |
275 											  VK_IMAGE_USAGE_TRANSFER_SRC_BIT;
276 
277 		const VkImageCreateInfo	createInfo	=
278 		{
279 			VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// sType
280 			DE_NULL,								// pNext
281 			0u,										// flags
282 			VK_IMAGE_TYPE_2D,						// imageType
283 			m_params.format,						// format
284 			extent,									// extent
285 			1u,										// mipLevels
286 			1u,										// arrayLayers
287 			VK_SAMPLE_COUNT_1_BIT,					// samples
288 			VK_IMAGE_TILING_OPTIMAL,				// tiling
289 			usage,									// usage
290 			VK_SHARING_MODE_EXCLUSIVE,				// sharingMode
291 			1u,										// queueFamilyIndexCount
292 			&queueFamilyIndex,						// pQueueFamilyIndices
293 			VK_IMAGE_LAYOUT_UNDEFINED				// initialLayout
294 		};
295 
296 		image = createImage(vk, device, &createInfo, DE_NULL);
297 
298 		imageMemory	= allocator.allocate(getImageMemoryRequirements(vk, device, *image), MemoryRequirement::Any);
299 		VK_CHECK(vk.bindImageMemory(device, *image, imageMemory->getMemory(), imageMemory->getOffset()));
300 	}
301 
302 	// Image view
303 	{
304 		const VkImageSubresourceRange	subresourceRange	=
305 		{
306 			VK_IMAGE_ASPECT_COLOR_BIT,	// aspectMask
307 			0u,							// baseMipLevel
308 			1u,							// mipLevels
309 			0u,							// baseArrayLayer
310 			1u							// arraySize
311 		};
312 
313 		imageView = makeImageView(vk, device, *image, VK_IMAGE_VIEW_TYPE_2D, m_params.format, subresourceRange, DE_NULL);
314 	}
315 
316 	// Result Buffer
317 	{
318 		const VkDeviceSize			bufferSize	= textureFormat.getPixelSize() * m_params.size.x() * m_params.size.y();
319 		const VkBufferCreateInfo	createInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
320 
321 		resultBuffer		= createBuffer(vk, device, &createInfo);
322 		resultBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *resultBuffer), MemoryRequirement::HostVisible);
323 
324 		VK_CHECK(vk.bindBufferMemory(device, *resultBuffer, resultBufferMemory->getMemory(), resultBufferMemory->getOffset()));
325 	}
326 
327 	// Render pass, framebuffer and pipelines
328 	{
329 		const Unique<VkShaderModule>									vertexShader					(createShaderModule(vk, device, m_context.getBinaryCollection().get("vert"), 0));
330 		const Unique<VkShaderModule>									fragmentShader					(createShaderModule(vk, device, m_context.getBinaryCollection().get("frag"), 0));
331 		const std::vector<VkViewport>									viewports						(1, makeViewport(tcu::UVec2(m_params.size)));
332 		const std::vector<VkRect2D>										scissors						(1, makeRect2D(tcu::UVec2(m_params.size)));
333 		const Move<VkPipelineLayout>									pipelineLayout					= makePipelineLayout(vk, device, 0, DE_NULL);
334 
335 		const VkVertexInputBindingDescription							vertexInputBindingDescription	=
336 		{
337 			0,							// binding
338 			sizeof(tcu::Vec4) * 2,		// strideInBytes
339 			VK_VERTEX_INPUT_RATE_VERTEX	// stepRate
340 		};
341 
342 		const VkVertexInputAttributeDescription							vertexAttributeDescriptions[2]	=
343 		{
344 			// Position
345 			{
346 				0u,								// location
347 				0u,								// binding
348 				VK_FORMAT_R32G32B32A32_SFLOAT,	// format
349 				0u								// offsetInBytes
350 			},
351 			// Color
352 			{
353 				1u,								// location
354 				0u,								// binding
355 				VK_FORMAT_R32G32B32A32_SFLOAT,	// format
356 				sizeof(tcu::Vec4)				// offsetInBytes
357 			}
358 		};
359 
360 		const VkPipelineVertexInputStateCreateInfo						vertexInputStateParams			=
361 		{
362 			VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,	// sType
363 			DE_NULL,													// pNext
364 			0,															// flags
365 			1u,															// bindingCount
366 			&vertexInputBindingDescription,								// pVertexBindingDescriptions
367 			2u,															// attributeCount
368 			vertexAttributeDescriptions									// pVertexAttributeDescriptions
369 		};
370 
371 		const VkProvokingVertexModeEXT									provokingVertexMode				= m_params.provokingVertexMode == PROVOKING_VERTEX_LAST
372 																										? VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT
373 																										: VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT;
374 
375 		const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT	provokingVertexCreateInfo		=
376 		{
377 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,	// sType
378 			DE_NULL,																			// pNext
379 			provokingVertexMode																	// provokingVertexMode
380 		};
381 
382 		const VkPipelineRasterizationStateCreateInfo					rasterizationStateCreateInfo	=
383 		{
384 			VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,		// sType
385 			useProvokingVertexExt ? &provokingVertexCreateInfo : DE_NULL,	// pNext
386 			0,																// flags
387 			false,															// depthClipEnable
388 			false,															// rasterizerDiscardEnable
389 			VK_POLYGON_MODE_FILL,											// fillMode
390 			VK_CULL_MODE_NONE,												// cullMode
391 			VK_FRONT_FACE_COUNTER_CLOCKWISE,								// frontFace
392 			VK_FALSE,														// depthBiasEnable
393 			0.0f,															// depthBias
394 			0.0f,															// depthBiasClamp
395 			0.0f,															// slopeScaledDepthBias
396 			1.0f															// lineWidth
397 		};
398 
399 		renderPass	= ProvokingVertexTestInstance::makeRenderPass(vk, device);
400 		framebuffer	= makeFramebuffer(vk, device, *renderPass, *imageView, m_params.size.x(), m_params.size.y(), 1u);
401 		pipeline	= makeGraphicsPipeline(vk,
402 										   device,
403 										   *pipelineLayout,
404 										   *vertexShader,
405 										   DE_NULL,							// tessellationControlShaderModule
406 										   DE_NULL,							// tessellationEvalShaderModule
407 										   DE_NULL,							// geometryShaderModule
408 										   *fragmentShader,
409 										   *renderPass,
410 										   viewports,
411 										   scissors,
412 										   m_params.primitiveTopology,
413 										   0u,								// subpass
414 										   0u,								// patchControlPoints
415 										   &vertexInputStateParams,
416 										   &rasterizationStateCreateInfo,
417 										   DE_NULL,							// multisampleStateCreateInfo
418 										   DE_NULL,							// depthStencilStateCreateInfo
419 										   DE_NULL,							// colorBlendStateCreateInfo
420 										   DE_NULL);						// dynamicStateCreateInfo
421 
422 		if (m_params.provokingVertexMode == PROVOKING_VERTEX_PER_PIPELINE)
423 		{
424 			const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT	altProvokingVertexCreateInfo	=
425 			{
426 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,	// sType
427 				DE_NULL,																			// pNext
428 				VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT											// provokingVertexMode
429 			};
430 
431 			const VkPipelineRasterizationStateCreateInfo					altRasterizationStateCreateInfo	=
432 			{
433 				VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,	// sType
434 				&altProvokingVertexCreateInfo,								// pNext
435 				0,															// flags
436 				false,														// depthClipEnable
437 				false,														// rasterizerDiscardEnable
438 				VK_POLYGON_MODE_FILL,										// fillMode
439 				VK_CULL_MODE_NONE,											// cullMode
440 				VK_FRONT_FACE_COUNTER_CLOCKWISE,							// frontFace
441 				VK_FALSE,													// depthBiasEnable
442 				0.0f,														// depthBias
443 				0.0f,														// depthBiasClamp
444 				0.0f,														// slopeScaledDepthBias
445 				1.0f,														// lineWidth
446 			};
447 
448 			altPipeline = makeGraphicsPipeline(vk,
449 											   device,
450 											   *pipelineLayout,
451 											   *vertexShader,
452 											   DE_NULL,							// tessellationControlShaderModule
453 											   DE_NULL,							// tessellationEvalShaderModule
454 											   DE_NULL,							// geometryShaderModule
455 											   *fragmentShader,
456 											   *renderPass,
457 											   viewports,
458 											   scissors,
459 											   m_params.primitiveTopology,
460 											   0u,								// subpass
461 											   0u,								// patchControlPoints
462 											   &vertexInputStateParams,
463 											   &altRasterizationStateCreateInfo,
464 											   DE_NULL,							// multisampleStateCreateInfo
465 											   DE_NULL,							// depthStencilStateCreateInfo
466 											   DE_NULL,							// colorBlendStateCreateInfo
467 											   DE_NULL);						// dynamicStateCreateInfo
468 		}
469 	}
470 
471 	// Vertex buffer
472 	{
473 		const tcu::Vec4			red		(1.0f, 0.0f, 0.0f, 1.0f);
474 		const tcu::Vec4			green	(0.0f, 1.0f, 0.0f, 1.0f);
475 		const tcu::Vec4			blue	(0.0f, 0.0f, 1.0f, 1.0f);
476 		const tcu::Vec4			yellow	(1.0f, 1.0f, 0.0f, 1.0f);
477 		const tcu::Vec4			white	(1.0f, 1.0f, 1.0f, 1.0f);
478 
479 		std::vector<tcu::Vec4>	vertices;
480 
481 		switch (m_params.primitiveTopology)
482 		{
483 			case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
484 				// Position												//Color
485 				vertices.push_back(tcu::Vec4(-1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);	// line 0
486 				vertices.push_back(tcu::Vec4( 1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
487 				vertices.push_back(tcu::Vec4(-1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);	// line 1
488 				vertices.push_back(tcu::Vec4( 1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
489 
490 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// line 1 reverse
491 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
492 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// line 0 reverse
493 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
494 				break;
495 			case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
496 				// Position												// Color
497 				vertices.push_back(tcu::Vec4(-1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red); // line strip
498 				vertices.push_back(tcu::Vec4( 1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);
499 				vertices.push_back(tcu::Vec4(-1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
500 				vertices.push_back(tcu::Vec4( 1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(green);
501 
502 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green); // line strip reverse
503 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
504 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
505 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
506 				break;
507 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
508 				// Position												// Color
509 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle 0
510 				vertices.push_back(tcu::Vec4(-0.6f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
511 				vertices.push_back(tcu::Vec4(-0.2f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
512 				vertices.push_back(tcu::Vec4( 0.2f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle 1
513 				vertices.push_back(tcu::Vec4( 0.6f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
514 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
515 
516 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle 1 reverse
517 				vertices.push_back(tcu::Vec4(-0.6f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
518 				vertices.push_back(tcu::Vec4(-0.2f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
519 				vertices.push_back(tcu::Vec4( 0.2f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle 0 reverse
520 				vertices.push_back(tcu::Vec4( 0.6f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
521 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
522 				break;
523 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
524 				// Position												// Color
525 				vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle strip
526 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
527 				vertices.push_back(tcu::Vec4( 0.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
528 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
529 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
530 
531 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle strip reverse
532 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
533 				vertices.push_back(tcu::Vec4( 0.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
534 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
535 				vertices.push_back(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
536 				break;
537 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
538 				// Position												// Color
539 				vertices.push_back(tcu::Vec4( 0.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);	// triangle fan
540 				vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
541 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
542 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
543 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
544 
545 				vertices.push_back(tcu::Vec4( 0.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green); // triangle fan reverse
546 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
547 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
548 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
549 				vertices.push_back(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
550 				break;
551 			case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
552 				// Position												// Color
553 				vertices.push_back(tcu::Vec4(-1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(green);	// line 0
554 				vertices.push_back(tcu::Vec4(-0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);
555 				vertices.push_back(tcu::Vec4( 0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
556 				vertices.push_back(tcu::Vec4( 1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(yellow);
557 				vertices.push_back(tcu::Vec4(-1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(green);	// line 1
558 				vertices.push_back(tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
559 				vertices.push_back(tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
560 				vertices.push_back(tcu::Vec4( 1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(yellow);
561 
562 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(yellow);	// line 1 reverse
563 				vertices.push_back(tcu::Vec4(-0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
564 				vertices.push_back(tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
565 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
566 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(yellow);	// line 0 reverse
567 				vertices.push_back(tcu::Vec4( 0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
568 				vertices.push_back(tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
569 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
570 				break;
571 			case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
572 				// Position												// Color
573 				vertices.push_back(tcu::Vec4(-1.0f,-0.5f, 0.0f, 1.0f));	vertices.push_back(green);	// line strip
574 				vertices.push_back(tcu::Vec4(-0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);
575 				vertices.push_back(tcu::Vec4( 0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);
576 				vertices.push_back(tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
577 				vertices.push_back(tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
578 				vertices.push_back(tcu::Vec4( 1.0f, 0.5f, 0.0f, 1.0f));	vertices.push_back(yellow);
579 
580 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(yellow);	// line strip reverse
581 				vertices.push_back(tcu::Vec4(-0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(blue);
582 				vertices.push_back(tcu::Vec4(-0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
583 				vertices.push_back(tcu::Vec4( 0.5f,-0.5f, 0.0f, 1.0f));	vertices.push_back(red);
584 				vertices.push_back(tcu::Vec4( 0.5f, 0.5f, 0.0f, 1.0f));	vertices.push_back(red);
585 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
586 				break;
587 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
588 				// Position												// Color
589 				vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle 0
590 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
591 				vertices.push_back(tcu::Vec4(-0.6f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
592 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
593 				vertices.push_back(tcu::Vec4(-0.2f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
594 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
595 				vertices.push_back(tcu::Vec4( 0.2f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle 1
596 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
597 				vertices.push_back(tcu::Vec4( 0.6f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
598 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
599 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
600 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
601 
602 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle 1 reverse
603 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
604 				vertices.push_back(tcu::Vec4(-0.6f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
605 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
606 				vertices.push_back(tcu::Vec4(-0.2f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
607 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
608 				vertices.push_back(tcu::Vec4( 0.2f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle 0 reverse
609 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
610 				vertices.push_back(tcu::Vec4( 0.6f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
611 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
612 				vertices.push_back(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
613 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
614 				break;
615 			case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
616 				// Position												// Color
617 				vertices.push_back(tcu::Vec4(-1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);	// triangle strip
618 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
619 				vertices.push_back(tcu::Vec4(-0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
620 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
621 				vertices.push_back(tcu::Vec4( 0.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
622 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
623 				vertices.push_back(tcu::Vec4( 0.5f,-1.0f, 0.0f, 1.0f));	vertices.push_back(green);
624 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
625 				vertices.push_back(tcu::Vec4( 1.0f, 1.0f, 0.0f, 1.0f));	vertices.push_back(blue);
626 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
627 
628 				vertices.push_back(tcu::Vec4(-1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(blue);	// triangle strip reverse
629 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
630 				vertices.push_back(tcu::Vec4(-0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(green);
631 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
632 				vertices.push_back(tcu::Vec4( 0.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
633 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
634 				vertices.push_back(tcu::Vec4( 0.5f, 1.0f, 0.0f, 1.0f));	vertices.push_back(red);
635 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
636 				vertices.push_back(tcu::Vec4( 1.0f,-1.0f, 0.0f, 1.0f));	vertices.push_back(red);
637 				vertices.push_back(tcu::Vec4( 0.0f, 0.0f, 0.0f, 1.0f));	vertices.push_back(white);
638 				break;
639 			default:
640 				DE_FATAL("Unknown primitive topology");
641 		}
642 
643 		const size_t				bufferSize	= vertices.size() * sizeof(tcu::Vec4);
644 		const VkBufferCreateInfo	createInfo	= makeBufferCreateInfo(bufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
645 
646 		vertexCount			= (deUint32)vertices.size() / 4;
647 		vertexBuffer		= createBuffer(vk, device, &createInfo);
648 		vertexBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *vertexBuffer), MemoryRequirement::HostVisible);
649 		VK_CHECK(vk.bindBufferMemory(device, *vertexBuffer, vertexBufferMemory->getMemory(), vertexBufferMemory->getOffset()));
650 		deMemcpy(vertexBufferMemory->getHostPtr(), &vertices[0], bufferSize);
651 		flushAlloc(vk, device, *vertexBufferMemory);
652 	}
653 
654 	// Transform feedback and counter buffers
655 	if (m_params.transformFeedback)
656 	{
657 		xfbBufferSize	= getXfbBufferSize(vertexCount, m_params.primitiveTopology);
658 
659 		if (m_params.provokingVertexMode ==PROVOKING_VERTEX_PER_PIPELINE)
660 			xfbBufferSize = xfbBufferSize * 2;
661 
662 		const int					xfbBufferUsage		= VK_BUFFER_USAGE_TRANSFER_SRC_BIT | VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT;
663 		const VkBufferCreateInfo	xfbCreateInfo		= makeBufferCreateInfo(xfbBufferSize, xfbBufferUsage);
664 		const VkDeviceSize			counterBufferSize	= 16 * sizeof(deUint32);
665 		const VkBufferCreateInfo	counterBufferInfo	= makeBufferCreateInfo(counterBufferSize, VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_COUNTER_BUFFER_BIT_EXT);
666 
667 		xfbBuffer			= createBuffer(vk, device, &xfbCreateInfo);
668 		xfbBufferMemory		= allocator.allocate(getBufferMemoryRequirements(vk, device, *xfbBuffer), MemoryRequirement::HostVisible);
669 		VK_CHECK(vk.bindBufferMemory(device, *xfbBuffer, xfbBufferMemory->getMemory(), xfbBufferMemory->getOffset()));
670 
671 		counterBuffer		= createBuffer(vk, device, &counterBufferInfo);
672 		counterBufferMemory	= allocator.allocate(getBufferMemoryRequirements(vk, device, *counterBuffer), MemoryRequirement::HostVisible);
673 		VK_CHECK(vk.bindBufferMemory(device, *counterBuffer, counterBufferMemory->getMemory(), counterBufferMemory->getOffset()));
674 		// Make sure uninitialized values are not read when starting XFB for the first time.
675 		deMemset(counterBufferMemory->getHostPtr(), 0, static_cast<size_t>(counterBufferSize));
676 		flushAlloc(vk, device, *counterBufferMemory);
677 	}
678 
679 	// Clear the color buffer to red and check the drawing doesn't add any
680 	// other colors from non-provoking vertices
681 	{
682 		const VkQueue					queue				= m_context.getUniversalQueue();
683 		const VkRect2D					renderArea			= makeRect2D(m_params.size.x(), m_params.size.y());
684 		const VkDeviceSize				vertexBufferOffset	= 0;
685 		const VkClearValue				clearValue			= makeClearValueColor(tcu::Vec4(1.0f, 0.0f, 0.0f, 1.0f));
686 		const VkPipelineStageFlags		srcStageMask		= VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT;
687 		const VkPipelineStageFlags		dstStageMask		= VK_PIPELINE_STAGE_ALL_COMMANDS_BIT;
688 
689 		const VkImageSubresourceRange	subResourcerange	=
690 		{
691 			VK_IMAGE_ASPECT_COLOR_BIT,	// aspectMask
692 			0,							// baseMipLevel
693 			1,							// levelCount
694 			0,							// baseArrayLayer
695 			1							// layerCount
696 		};
697 
698 		const VkImageMemoryBarrier		imageBarrier		=
699 		{
700 			VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER,		// sType
701 			DE_NULL,									// pNext
702 			0,											// srcAccessMask
703 			VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT,		// dstAccessMask
704 			VK_IMAGE_LAYOUT_UNDEFINED,					// oldLayout
705 			VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// newLayout
706 			VK_QUEUE_FAMILY_IGNORED,					// srcQueueFamilyIndex
707 			VK_QUEUE_FAMILY_IGNORED,					// destQueueFamilyIndex
708 			*image,										// image
709 			subResourcerange							// subresourceRange
710 		};
711 
712 		const VkMemoryBarrier			xfbMemoryBarrier	= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_WRITE_BIT_EXT, VK_ACCESS_HOST_READ_BIT);
713 		const VkMemoryBarrier			counterBarrier		= makeMemoryBarrier(VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT, VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT);
714 
715 		// The first half of the vertex buffer is for PROVOKING_VERTEX_FIRST,
716 		// the second half for PROVOKING_VERTEX_LAST
717 		const deUint32					firstVertex			= m_params.provokingVertexMode == PROVOKING_VERTEX_LAST
718 															? vertexCount
719 															: 0u;
720 
721 		Move<VkCommandPool>				commandPool			= makeCommandPool(vk, device, queueFamilyIndex);
722 		Move<VkCommandBuffer>			commandBuffer		= allocateCommandBuffer(vk, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
723 
724 		beginCommandBuffer(vk, *commandBuffer, 0u);
725 		{
726 			vk.cmdPipelineBarrier(*commandBuffer, srcStageMask, dstStageMask, 0, 0, DE_NULL, 0, DE_NULL, 1, &imageBarrier);
727 
728 			beginRenderPass(vk, *commandBuffer, *renderPass, *framebuffer, renderArea, 1, &clearValue);
729 			{
730 				vk.cmdBindVertexBuffers(*commandBuffer, 0, 1, &*vertexBuffer, &vertexBufferOffset);
731 				vk.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *pipeline);
732 
733 				if (m_params.transformFeedback)
734 				{
735 					const VkDeviceSize	xfbBufferOffset	= 0;
736 
737 					vk.cmdBindTransformFeedbackBuffersEXT(*commandBuffer, 0, 1, &*xfbBuffer, &xfbBufferOffset, &xfbBufferSize);
738 					vk.cmdBeginTransformFeedbackEXT(*commandBuffer, 0, 1, &*counterBuffer, &counterBufferOffset);
739 				}
740 
741 				vk.cmdDraw(*commandBuffer, vertexCount, 1u, firstVertex, 0u);
742 
743 				if (m_params.provokingVertexMode == PROVOKING_VERTEX_PER_PIPELINE)
744 				{
745 					// vkCmdBindPipeline must not be recorded when transform feedback is active.
746 					if (m_params.transformFeedback)
747 					{
748 						vk.cmdEndTransformFeedbackEXT(*commandBuffer, 0, 1, &*counterBuffer, &counterBufferOffset);
749 						vk.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, 0u, 1u, &counterBarrier, 0u, DE_NULL, 0u, DE_NULL);
750 					}
751 
752 					vk.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, *altPipeline);
753 
754 					if (m_params.transformFeedback)
755 						vk.cmdBeginTransformFeedbackEXT(*commandBuffer, 0, 1, &*counterBuffer, &counterBufferOffset);
756 
757 					vk.cmdDraw(*commandBuffer, vertexCount, 1u, vertexCount, 0u);
758 				}
759 
760 				if (m_params.transformFeedback)
761 					vk.cmdEndTransformFeedbackEXT(*commandBuffer, 0, 1, &*counterBuffer, &counterBufferOffset);
762 			}
763 			endRenderPass(vk, *commandBuffer);
764 
765 			if (m_params.transformFeedback)
766 				vk.cmdPipelineBarrier(*commandBuffer, VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT, VK_PIPELINE_STAGE_HOST_BIT, 0u, 1u, &xfbMemoryBarrier, 0u, DE_NULL, 0u, DE_NULL);
767 
768 			copyImageToBuffer(vk, *commandBuffer, *image, *resultBuffer, tcu::IVec2(m_params.size.x(), m_params.size.y()));
769 		}
770 		endCommandBuffer(vk, *commandBuffer);
771 
772 		submitCommandsAndWait(vk, device, queue, commandBuffer.get());
773 		invalidateAlloc(vk, device, *resultBufferMemory);
774 
775 		if (m_params.transformFeedback)
776 			invalidateAlloc(vk, device, *xfbBufferMemory);
777 	}
778 
779 	// Verify result
780 	{
781 		tcu::TestLog&				log					= m_context.getTestContext().getLog();
782 		const size_t				bufferSize			= textureFormat.getPixelSize() * m_params.size.x() * m_params.size.y();
783 		tcu::Surface				referenceSurface	(m_params.size.x(), m_params.size.y());
784 		tcu::ConstPixelBufferAccess	referenceAccess		= referenceSurface.getAccess();
785 		tcu::Surface				resultSurface		(m_params.size.x(), m_params.size.y());
786 		tcu::ConstPixelBufferAccess	resultAccess		(textureFormat,
787 														 tcu::IVec3(m_params.size.x(), m_params.size.y(), 1),
788 														 resultBufferMemory->getHostPtr());
789 
790 		// Verify transform feedback buffer
791 		if (m_params.transformFeedback)
792 		{
793 			const tcu::Vec4* const	xfbResults		= static_cast<tcu::Vec4*>(xfbBufferMemory->getHostPtr());
794 			const deUint32			count			= static_cast<deUint32>(xfbBufferSize / sizeof(tcu::Vec4));
795 			std::string				errorMessage	= "";
796 
797 			log << tcu::TestLog::Section("XFB Vertex colors", "vertex colors");
798 
799 			for (deUint32 i = 0; i < count; i++)
800 			{
801 				log	<< tcu::TestLog::Message
802 					<< "[" << de::toString(i) << "]\t"
803 					<< de::toString(xfbResults[i])
804 					<< tcu::TestLog::EndMessage;
805 			}
806 
807 			log << tcu::TestLog::EndSection;
808 
809 			if (m_params.provokingVertexMode != PROVOKING_VERTEX_PER_PIPELINE)
810 			{
811 				if (!verifyXfbBuffer(xfbResults, count, m_params.primitiveTopology, m_params.provokingVertexMode, errorMessage))
812 					return tcu::TestStatus::fail(errorMessage);
813 			}
814 			else
815 			{
816 				const deUint32 halfCount = count / 2;
817 
818 				if (!verifyXfbBuffer(xfbResults, halfCount, m_params.primitiveTopology, PROVOKING_VERTEX_FIRST, errorMessage))
819 					return tcu::TestStatus::fail(errorMessage);
820 
821 				if (!verifyXfbBuffer(&xfbResults[halfCount], halfCount, m_params.primitiveTopology, PROVOKING_VERTEX_LAST, errorMessage))
822 					return tcu::TestStatus::fail(errorMessage);
823 			}
824 		}
825 
826 		// Create reference
827 		for (deUint32 y = 0; y < m_params.size.y(); y++)
828 		for (deUint32 x = 0; x < m_params.size.x(); x++)
829 			referenceSurface.setPixel(x, y, tcu::RGBA::red());
830 
831 		// Copy result
832 		tcu::copy(resultSurface.getAccess(), resultAccess);
833 
834 		// Compare
835 		if (deMemCmp(referenceAccess.getDataPtr(), resultAccess.getDataPtr(), bufferSize) != 0)
836 		{
837 			log	<< tcu::TestLog::ImageSet("Result of rendering", "Result of rendering")
838 				<< tcu::TestLog::Image("Result", "Result", resultSurface)
839 				<< tcu::TestLog::EndImageSet;
840 			return tcu::TestStatus::fail("Incorrect rendering");
841 		}
842 	}
843 
844 	return tcu::TestStatus::pass("Solid red");
845 }
846 
847 // Copied from vkObjUtil.cpp with an additional subpass.
makeRenderPass(const DeviceInterface & vk,const VkDevice device)848 Move<VkRenderPass> ProvokingVertexTestInstance::makeRenderPass (const DeviceInterface& vk, const VkDevice device)
849 {
850 	const VkAttachmentDescription		colorAttachmentDescription	=
851 	{
852 		(VkAttachmentDescriptionFlags)0,			// VkAttachmentDescriptionFlags    flags
853 		m_params.format,							// VkFormat                        format
854 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits           samples
855 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp              loadOp
856 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp             storeOp
857 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp              stencilLoadOp
858 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp             stencilStoreOp
859 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout                   initialLayout
860 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL,	// VkImageLayout                   finalLayout
861 	};
862 
863 	const VkAttachmentReference			colorAttachmentRef			=
864 	{
865 		0u,											// deUint32         attachment
866 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout    layout
867 	};
868 
869 	const VkSubpassDescription			subpassDescription			=
870 	{
871 		(VkSubpassDescriptionFlags)0,		// VkSubpassDescriptionFlags       flags
872 		VK_PIPELINE_BIND_POINT_GRAPHICS,	// VkPipelineBindPoint             pipelineBindPoint
873 		0u,									// deUint32                        inputAttachmentCount
874 		DE_NULL,							// const VkAttachmentReference*    pInputAttachments
875 		1u,									// deUint32                        colorAttachmentCount
876 		&colorAttachmentRef,				// const VkAttachmentReference*    pColorAttachments
877 		DE_NULL,							// const VkAttachmentReference*    pResolveAttachments
878 		DE_NULL,							// const VkAttachmentReference*    pDepthStencilAttachment
879 		0u,									// deUint32                        preserveAttachmentCount
880 		DE_NULL								// const deUint32*                 pPreserveAttachments
881 	};
882 
883 	const VkSubpassDependency			selfDependency			=
884 	{
885 		0u,													// deUint32                srcSubpass
886 		0u,													// deUint32                dstSubpass
887 		VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,		// VkPipelineStageFlags    srcStageMask
888 		VK_PIPELINE_STAGE_TRANSFORM_FEEDBACK_BIT_EXT,		// VkPipelineStageFlags    dstStageMask
889 		VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_WRITE_BIT_EXT,	// VkAccessFlags           srcAccessMask
890 		VK_ACCESS_TRANSFORM_FEEDBACK_COUNTER_READ_BIT_EXT,	// VkAccessFlags           dstAccessMask
891 		0u													// VkDependencyFlags       dependencyFlags
892 	};
893 
894 	const bool							xfbPerPipeline				= m_params.transformFeedback && m_params.provokingVertexMode == PROVOKING_VERTEX_PER_PIPELINE;
895 
896 	const VkRenderPassCreateInfo		renderPassInfo				=
897 	{
898 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,	// VkStructureType                   sType
899 		DE_NULL,									// const void*                       pNext
900 		(VkRenderPassCreateFlags)0,					// VkRenderPassCreateFlags           flags
901 		1u,											// deUint32                          attachmentCount
902 		&colorAttachmentDescription,				// const VkAttachmentDescription*    pAttachments
903 		1u,											// deUint32                          subpassCount
904 		&subpassDescription,						// const VkSubpassDescription*       pSubpasses
905 		xfbPerPipeline ? 1u : 0u,					// deUint32                          dependencyCount
906 		xfbPerPipeline ? &selfDependency : DE_NULL	// const VkSubpassDependency*        pDependencies
907 	};
908 
909 	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
910 }
911 
createTests(tcu::TestCaseGroup * testGroup)912 void createTests (tcu::TestCaseGroup* testGroup)
913 {
914 	tcu::TestContext&	testCtx	= testGroup->getTestContext();
915 
916 	const struct Provoking
917 	{
918 		const char*			name;
919 		const char*			desc;
920 		ProvokingVertexMode	mode;
921 	} provokingVertexModes[] =
922 	{
923 		{ "default",		"Default provoking vertex convention",				PROVOKING_VERTEX_DEFAULT,		},
924 		{ "first",			"VK_PROVOKING_VERTEX_MODE_FIRST_VERTEX_EXT",		PROVOKING_VERTEX_FIRST,			},
925 		{ "last",			"VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT",			PROVOKING_VERTEX_LAST,			},
926 		{ "per_pipeline",	"Pipelines with different provokingVertexModes",	PROVOKING_VERTEX_PER_PIPELINE	}
927 	};
928 
929 	const struct Topology
930 	{
931 		std::string			name;
932 		VkPrimitiveTopology	type;
933 		bool				requiresGeometryShader;
934 	} topologies[] =
935 	{
936 		{ "line_list",						VK_PRIMITIVE_TOPOLOGY_LINE_LIST,						false	},
937 		{ "line_strip",						VK_PRIMITIVE_TOPOLOGY_LINE_STRIP,						false	},
938 		{ "triangle_list",					VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,					false	},
939 		{ "triangle_strip",					VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP,					false	},
940 		{ "triangle_fan",					VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN,						false	},
941 		{ "line_list_with_adjacency",		VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY,			true	},
942 		{ "line_strip_with_adjacency",		VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY,		true	},
943 		{ "triangle_list_with_adjacency",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY,		true	},
944 		{ "triangle_strip_with_adjacency",	VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY,	true	}
945 	};
946 
947 	const struct TestType
948 	{
949 		const char*	name;
950 		const char* desc;
951 		bool		transformFeedback;
952 	} testTypes[] =
953 	{
954 		{ "draw",				"Test that primitives are flat shaded with the provoking vertex color",			false	},
955 		{ "transform_feedback",	"Test that transform feedback preserves the position of the provoking vertex",	true	}
956 	};
957 
958 	for (const TestType& testType: testTypes)
959 	{
960 		tcu::TestCaseGroup* const typeGroup = new tcu::TestCaseGroup(testCtx, testType.name, testType.desc);
961 
962 		for (const Provoking& provoking : provokingVertexModes)
963 		{
964 			// Only test transformFeedbackPreservesProvokingVertex with VK_EXT_provoking_vertex
965 			if (testType.transformFeedback && (provoking.mode == PROVOKING_VERTEX_DEFAULT))
966 				continue;
967 
968 			tcu::TestCaseGroup* const provokingGroup = new tcu::TestCaseGroup(testCtx, provoking.name, provoking.desc);
969 
970 			for (const Topology& topology : topologies)
971 			{
972 				const std::string	caseName	= topology.name;
973 				const std::string	caseDesc	= getPrimitiveTopologyName(topology.type);
974 
975 				const Params		params		=
976 				{
977 					VK_FORMAT_R8G8B8A8_UNORM,			// format
978 					tcu::UVec2(32, 32),					// size
979 					topology.type,						// primitiveTopology
980 					topology.requiresGeometryShader,	// requireGeometryShader
981 					testType.transformFeedback,			// transformFeedback
982 					provoking.mode						// provokingVertexMode
983 				};
984 
985 				provokingGroup->addChild(new ProvokingVertexTestCase(testCtx, caseName, caseDesc, params));
986 			}
987 
988 			typeGroup->addChild(provokingGroup);
989 		}
990 
991 		testGroup->addChild(typeGroup);
992 	}
993 }
994 
995 }	// anonymous
996 
createProvokingVertexTests(tcu::TestContext & testCtx)997 tcu::TestCaseGroup* createProvokingVertexTests (tcu::TestContext& testCtx)
998 {
999 	return createTestGroup(testCtx,
1000 						   "provoking_vertex",
1001 						   "Tests for provoking vertex",
1002 						   createTests);
1003 }
1004 
1005 }	// rasterization
1006 }	// vkt
1007 
1008