• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2021 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 Fragment Shading Barycentric extention tests
22  *//*--------------------------------------------------------------------*/
23 
24 #include "vktFragmentShadingBarycentricTests.hpp"
25 
26 #include "vkDefs.hpp"
27 #include "vktTestCase.hpp"
28 #include "vktTestGroupUtil.hpp"
29 #include "vkCmdUtil.hpp"
30 #include "vkObjUtil.hpp"
31 #include "vkBuilderUtil.hpp"
32 #include "vkBarrierUtil.hpp"
33 #include "vkBufferWithMemory.hpp"
34 #include "vkImageWithMemory.hpp"
35 #include "vkTypeUtil.hpp"
36 #include "vkImageUtil.hpp"
37 #include "vkPipelineConstructionUtil.hpp"
38 
39 #include "tcuTestLog.hpp"
40 #include "tcuStringTemplate.hpp"
41 #include "tcuImageCompare.hpp"
42 #include "tcuVectorUtil.hpp"
43 
44 #include <string>
45 #include <vector>
46 #include <map>
47 
48 namespace vkt
49 {
50 namespace FragmentShadingBarycentric
51 {
52 namespace
53 {
54 using namespace vk;
55 using namespace vkt;
56 
57 using std::string;
58 using std::vector;
59 using std::map;
60 using de::MovePtr;
61 using tcu::mix;
62 
63 enum TestType
64 {
65 	TEST_TYPE_DATA		= 0,
66 	TEST_TYPE_WEIGHTS,
67 };
68 
69 enum TestSubtype
70 {
71 	TEST_SUBTYPE_DEFAULT = 0,
72 	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID,
73 	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE,
74 	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET,
75 	TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER,
76 	TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER,
77 	TEST_SUBTYPE_PERVERTEX_CORRECTNESS,
78 };
79 
80 const size_t	DATA_TEST_WIDTH		= 8u;
81 const size_t	DATA_TEST_HEIGHT	= 8u;
82 const size_t	WEIGHT_TEST_WIDTH	= 128u;
83 const size_t	WEIGHT_TEST_HEIGHT	= 128u;
84 const float		WEIGHT_TEST_SLOPE	= 16.0f;
85 
86 struct TestParams
87 {
88 	const PipelineConstructionType	pipelineConstructionType;
89 	TestType						testType;
90 	TestSubtype						testSubtype;
91 	VkPrimitiveTopology				topology;
92 	bool							dynamicIndexing;
93 	size_t							aggregate; // 0: value itself, 1:struct, 2+:Array
94 	glu::DataType					dataType;
95 	size_t							width;
96 	size_t							height;
97 	bool							perspective;
98 	bool							provokingVertexLast;
99 	uint32_t						rotation;
100 	bool							dynamicTopologyInPipeline;
101 	VkSampleCountFlagBits			sampleCount;
102 };
103 
getComponentCount(const TestParams & testParams)104 size_t getComponentCount (const TestParams& testParams)
105 {
106 	const size_t	scalarSize		= static_cast<size_t>(getDataTypeScalarSize(testParams.dataType));
107 	const size_t	aggregateSize	= (testParams.aggregate > 0) ? testParams.aggregate : 1;
108 	const size_t	topologySize	= 3; // Test always check three items in array: "Reads of per-vertex values for missing vertices, such as the third vertex of a line primitive, will return zero."
109 	const size_t	result			= scalarSize * aggregateSize * topologySize;
110 
111 	return result;
112 }
113 
makeImageCreateInfo(const VkFormat format,const uint32_t width,uint32_t height,VkSampleCountFlagBits samples)114 static VkImageCreateInfo makeImageCreateInfo (const VkFormat format, const uint32_t width, uint32_t height, VkSampleCountFlagBits samples)
115 {
116 	const VkImageUsageFlags	usage			= VK_IMAGE_USAGE_COLOR_ATTACHMENT_BIT | VK_IMAGE_USAGE_TRANSFER_SRC_BIT | VK_IMAGE_USAGE_TRANSFER_DST_BIT;
117 	const VkImageCreateInfo	imageCreateInfo	=
118 	{
119 		VK_STRUCTURE_TYPE_IMAGE_CREATE_INFO,	// VkStructureType			sType;
120 		DE_NULL,								// const void*				pNext;
121 		0u,										// VkImageCreateFlags		flags;
122 		VK_IMAGE_TYPE_2D,						// VkImageType				imageType;
123 		format,									// VkFormat					format;
124 		makeExtent3D(width, height, 1u),		// VkExtent3D				extent;
125 		1u,										// uint32_t					mipLevels;
126 		1u,										// uint32_t					arrayLayers;
127 		samples,								// VkSampleCountFlagBits	samples;
128 		VK_IMAGE_TILING_OPTIMAL,				// VkImageTiling			tiling;
129 		usage,									// VkImageUsageFlags		usage;
130 		VK_SHARING_MODE_EXCLUSIVE,				// VkSharingMode			sharingMode;
131 		0u,										// uint32_t					queueFamilyIndexCount;
132 		DE_NULL,								// const uint32_t*			pQueueFamilyIndices;
133 		VK_IMAGE_LAYOUT_UNDEFINED,				// VkImageLayout			initialLayout;
134 	};
135 
136 	return imageCreateInfo;
137 }
138 
makeRenderPass(const DeviceInterface & vk,const VkDevice device,const VkFormat format,VkSampleCountFlagBits samples)139 static Move<VkRenderPass> makeRenderPass(const DeviceInterface& vk, const VkDevice device, const VkFormat format, VkSampleCountFlagBits samples)
140 {
141 	const VkAttachmentDescription attachmentSingleSampleDesc
142 	{
143 		(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
144 		format,										// VkFormat							format;
145 		VK_SAMPLE_COUNT_1_BIT,						// VkSampleCountFlagBits			samples;
146 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
147 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
148 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
149 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
150 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout;
151 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout;
152 	};
153 
154 	const VkAttachmentDescription attachmentMultiSampleDesc
155 	{
156 		(VkAttachmentDescriptionFlags)0u,			// VkAttachmentDescriptionFlags		flags;
157 		format,										// VkFormat							format;
158 		samples,									// VkSampleCountFlagBits			samples;
159 		VK_ATTACHMENT_LOAD_OP_CLEAR,				// VkAttachmentLoadOp				loadOp;
160 		VK_ATTACHMENT_STORE_OP_STORE,				// VkAttachmentStoreOp				storeOp;
161 		VK_ATTACHMENT_LOAD_OP_DONT_CARE,			// VkAttachmentLoadOp				stencilLoadOp;
162 		VK_ATTACHMENT_STORE_OP_DONT_CARE,			// VkAttachmentStoreOp				stencilStoreOp;
163 		VK_IMAGE_LAYOUT_UNDEFINED,					// VkImageLayout					initialLayout;
164 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout					finalLayout;
165 	};
166 
167 	const VkAttachmentDescription attachments[] = { attachmentSingleSampleDesc, attachmentMultiSampleDesc };
168 
169 	const VkAttachmentReference attachmentSingleSampleRef
170 	{
171 		0u,											// deUint32			attachment;
172 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
173 	};
174 
175 	const VkAttachmentReference attachmentMultiSampleRef
176 	{
177 		1u,											// deUint32			attachment;
178 		VK_IMAGE_LAYOUT_COLOR_ATTACHMENT_OPTIMAL	// VkImageLayout	layout;
179 	};
180 
181 	const bool useMultisampling = (samples > VK_SAMPLE_COUNT_1_BIT);
182 	const VkAttachmentReference* colorAttachment	= useMultisampling ? &attachmentMultiSampleRef : &attachmentSingleSampleRef;
183 	const VkAttachmentReference* resolveAttachment	= useMultisampling ? &attachmentSingleSampleRef : DE_NULL;
184 
185 	const VkSubpassDescription subpassDescription
186 	{
187 		(VkSubpassDescriptionFlags)0u,				// VkSubpassDescriptionFlags		flags;
188 		VK_PIPELINE_BIND_POINT_GRAPHICS,			// VkPipelineBindPoint				pipelineBindPoint;
189 		0u,											// deUint32							inputAttachmentCount;
190 		DE_NULL,									// const VkAttachmentReference*		pInputAttachments;
191 		1u,											// deUint32							colorAttachmentCount;
192 		colorAttachment,							// const VkAttachmentReference*		pColorAttachments;
193 		resolveAttachment,							// const VkAttachmentReference*		pResolveAttachments;
194 		DE_NULL,									// const VkAttachmentReference*		pDepthStencilAttachment;
195 		0u,											// deUint32							preserveAttachmentCount;
196 		DE_NULL										// const deUint32*					pPreserveAttachments;
197 	};
198 
199 	const VkRenderPassCreateInfo renderPassInfo
200 	{
201 		VK_STRUCTURE_TYPE_RENDER_PASS_CREATE_INFO,			// VkStructureType					sType;
202 		DE_NULL,											// const void*						pNext;
203 		(VkRenderPassCreateFlags)0u,						// VkRenderPassCreateFlags			flags;
204 		1u + useMultisampling,								// deUint32							attachmentCount;
205 		attachments,										// const VkAttachmentDescription*	pAttachments;
206 		1u,													// deUint32							subpassCount;
207 		&subpassDescription,								// const VkSubpassDescription*		pSubpasses;
208 		0u,													// deUint32							dependencyCount;
209 		DE_NULL												// const VkSubpassDependency*		pDependencies;
210 	};
211 
212 	return createRenderPass(vk, device, &renderPassInfo, DE_NULL);
213 }
214 
215 using GraphicsPipelinePtr = std::unique_ptr<GraphicsPipelineWrapper>;
216 
makeGraphicsPipeline(PipelineConstructionType pipelineConstructionType,const InstanceInterface & vki,const DeviceInterface & vkd,const VkPhysicalDevice physicalDevice,const VkDevice device,const std::vector<std::string> & deviceExtensions,const PipelineLayoutWrapper & pipelineLayout,const VkRenderPass renderPass,const ShaderWrapper vertShaderModule,const ShaderWrapper fragShaderModule,const uint32_t width,const uint32_t height,const VkPrimitiveTopology topology,const VkSampleCountFlagBits rasterizationSamples,const bool withColor=false,const bool provokingVertexLast=false,const bool dynamicTopology=false)217 static GraphicsPipelinePtr makeGraphicsPipeline (PipelineConstructionType			pipelineConstructionType,
218 												 const InstanceInterface&			vki,
219 												 const DeviceInterface&				vkd,
220 												 const VkPhysicalDevice				physicalDevice,
221 												 const VkDevice						device,
222 												 const std::vector<std::string>&	deviceExtensions,
223 												 const PipelineLayoutWrapper&		pipelineLayout,
224 												 const VkRenderPass					renderPass,
225 												 const ShaderWrapper				vertShaderModule,
226 												 const ShaderWrapper				fragShaderModule,
227 												 const uint32_t						width,
228 												 const uint32_t						height,
229 												 const VkPrimitiveTopology			topology,
230 												 const VkSampleCountFlagBits		rasterizationSamples,
231 												 const bool							withColor = false,
232 												 const bool							provokingVertexLast = false,
233 												 const bool							dynamicTopology = false)
234 {
235 	const std::vector<VkViewport>									viewports							(1, makeViewport(width, height));
236 	const std::vector<VkRect2D>										scissors							(1, makeRect2D(width, height));
237 	const VkVertexInputBindingDescription							vertexInputBindingDescription		=
238 	{
239 		0u,										// uint32_t				binding;
240 		2 * sizeof(tcu::Vec4),					// uint32_t				stride;
241 		VK_VERTEX_INPUT_RATE_VERTEX,			// VkVertexInputRate	inputRate;
242 	};
243 	const VkVertexInputAttributeDescription							vertexInputAttributeDescriptions[]	=
244 	{
245 		{
246 			0u,										// uint32_t		location;
247 			0u,										// uint32_t		binding;
248 			VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat		format;
249 			0u										// uint32_t		offset;
250 		},
251 		{
252 			1u,										// uint32_t		location;
253 			0u,										// uint32_t		binding;
254 			VK_FORMAT_R32G32B32A32_SFLOAT,			// VkFormat		format;
255 			sizeof(tcu::Vec4)						// uint32_t		offset;
256 		},
257 	};
258 	const VkPipelineVertexInputStateCreateInfo						vertexInputStateInfo				=
259 	{
260 		VK_STRUCTURE_TYPE_PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,		// VkStructureType								sType;
261 		DE_NULL,														// const void*									pNext;
262 		(VkPipelineVertexInputStateCreateFlags)0,						// VkPipelineVertexInputStateCreateFlags		flags;
263 		1u,																// uint32_t										vertexBindingDescriptionCount;
264 		&vertexInputBindingDescription,									// const VkVertexInputBindingDescription*		pVertexBindingDescriptions;
265 		DE_LENGTH_OF_ARRAY(vertexInputAttributeDescriptions),			// uint32_t										vertexAttributeDescriptionCount;
266 		vertexInputAttributeDescriptions,								// const VkVertexInputAttributeDescription*		pVertexAttributeDescriptions;
267 	};
268 	const VkPipelineRasterizationProvokingVertexStateCreateInfoEXT	provokingVertexStateCreateInfoEXT	=
269 	{
270 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_PROVOKING_VERTEX_STATE_CREATE_INFO_EXT,	//  VkStructureType				sType;
271 		DE_NULL,																			//  const void*					pNext;
272 		VK_PROVOKING_VERTEX_MODE_LAST_VERTEX_EXT,											//  VkProvokingVertexModeEXT	provokingVertexMode;
273 	};
274 	const VkPipelineRasterizationStateCreateInfo					rasterizationStateCreateInfo		=
275 	{
276 		VK_STRUCTURE_TYPE_PIPELINE_RASTERIZATION_STATE_CREATE_INFO,				//  VkStructureType							sType;
277 		provokingVertexLast ? &provokingVertexStateCreateInfoEXT : DE_NULL,		//  const void*								pNext;
278 		0u,																		//  VkPipelineRasterizationStateCreateFlags	flags;
279 		VK_FALSE,																//  VkBool32								depthClampEnable;
280 		DE_FALSE,																//  VkBool32								rasterizerDiscardEnable;
281 		VK_POLYGON_MODE_FILL,													//  VkPolygonMode							polygonMode;
282 		VK_CULL_MODE_NONE,														//  VkCullModeFlags							cullMode;
283 		VK_FRONT_FACE_COUNTER_CLOCKWISE,										//  VkFrontFace								frontFace;
284 		VK_FALSE,																//  VkBool32								depthBiasEnable;
285 		0.0f,																	//  float									depthBiasConstantFactor;
286 		0.0f,																	//  float									depthBiasClamp;
287 		0.0f,																	//  float									depthBiasSlopeFactor;
288 		1.0f																	//  float									lineWidth;
289 	};
290 	const bool									isMultiSample			= (rasterizationSamples > VK_SAMPLE_COUNT_1_BIT);
291 	const VkPipelineMultisampleStateCreateInfo	multisampleStateInfo
292 	{
293 		VK_STRUCTURE_TYPE_PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,				// VkStructureType							sType;
294 		nullptr,																// const void*								pNext;
295 		0u,																		// VkPipelineMultisampleStateCreateFlags	flags;
296 		rasterizationSamples,													// VkSampleCountFlagBits					rasterizationSamples;
297 		(isMultiSample ? VK_TRUE : VK_FALSE),									// VkBool32									sampleShadingEnable;
298 		1.0f,																	// float									minSampleShading;
299 		DE_NULL,																// const VkSampleMask*						pSampleMask;
300 		VK_FALSE,																// VkBool32									alphaToCoverageEnable;
301 		VK_FALSE,																// VkBool32									alphaToOneEnable;
302 	};
303 	const VkDynamicState											dynamicStates[]						=
304 	{
305 		VK_DYNAMIC_STATE_PRIMITIVE_TOPOLOGY,
306 	};
307 	const VkPipelineDynamicStateCreateInfo							dynamicStateCreateInfo				=
308 	{
309 		VK_STRUCTURE_TYPE_PIPELINE_DYNAMIC_STATE_CREATE_INFO,	//  VkStructureType						sType;
310 		DE_NULL,												//  const void*							pNext;
311 		0u,														//  VkPipelineDynamicStateCreateFlags	flags;
312 		DE_LENGTH_OF_ARRAY(dynamicStates),						//  uint32_t							dynamicStateCount;
313 		dynamicStates,											//  const VkDynamicState*				pDynamicStates;
314 	};
315 	const VkPipelineDynamicStateCreateInfo*							pDynamicStateCreateInfo				= dynamicTopology ? &dynamicStateCreateInfo : DE_NULL;
316 	const auto														pVertexInputStateCreateInfo			= (withColor ? &vertexInputStateInfo : nullptr);
317 
318 	GraphicsPipelinePtr	pipelineWrapperPtr	(new GraphicsPipelineWrapper(vki, vkd, physicalDevice, device, deviceExtensions, pipelineConstructionType));
319 	auto&				pipelineWrapper		= *pipelineWrapperPtr.get();
320 
321 	pipelineWrapper
322 		.setMonolithicPipelineLayout(pipelineLayout)
323 		.setDefaultDepthStencilState()
324 		.setDefaultColorBlendState()
325 		.setDefaultTopology(topology)
326 		.setDynamicState(pDynamicStateCreateInfo)
327 		.setupVertexInputState(pVertexInputStateCreateInfo)
328 		.setupPreRasterizationShaderState(viewports, scissors, pipelineLayout, renderPass, 0u, vertShaderModule, &rasterizationStateCreateInfo)
329 		.setupFragmentShaderState(pipelineLayout, renderPass, 0u, fragShaderModule)
330 		.setupFragmentOutputState(renderPass, 0u, nullptr, &multisampleStateInfo)
331 		.buildPipeline();
332 
333 	return pipelineWrapperPtr;
334 }
335 
336 // Function replacing all occurrences of substring with string passed in last parameter.
replace(const std::string & str,const std::string & from,const std::string & to)337 static inline std::string replace(const std::string& str, const std::string& from, const std::string& to)
338 {
339 	std::string result(str);
340 
341 	size_t start_pos = 0;
342 	while ((start_pos = result.find(from, start_pos)) != std::string::npos)
343 	{
344 		result.replace(start_pos, from.length(), to);
345 		start_pos += to.length();
346 	}
347 
348 	return result;
349 }
350 
351 
352 class FragmentShadingBarycentricDataTestInstance : public TestInstance
353 {
354 public:
355 								FragmentShadingBarycentricDataTestInstance	(Context&			context,
356 																			 const TestParams&	testParams);
357 	virtual						~FragmentShadingBarycentricDataTestInstance	();
358 	virtual tcu::TestStatus		iterate										(void);
359 
360 protected:
361 	vector<tcu::Vec4>			generateVertexBuffer						(void);
362 	MovePtr<BufferWithMemory>	createVertexBuffer							(const vector<tcu::Vec4>& vertices);
363 	bool						verify										(BufferWithMemory* resultBuffer);
364 	bool						getProvokingVertexLast						(void);
365 
366 	TestParams					m_testParams;
367 };
368 
FragmentShadingBarycentricDataTestInstance(Context & context,const TestParams & testParams)369 FragmentShadingBarycentricDataTestInstance::FragmentShadingBarycentricDataTestInstance (Context& context, const TestParams& testParams)
370 	: TestInstance	(context)
371 	, m_testParams	(testParams)
372 {
373 }
374 
~FragmentShadingBarycentricDataTestInstance()375 FragmentShadingBarycentricDataTestInstance::~FragmentShadingBarycentricDataTestInstance ()
376 {
377 }
378 
generateVertexBuffer(void)379 vector<tcu::Vec4> FragmentShadingBarycentricDataTestInstance::generateVertexBuffer (void)
380 {
381 	size_t				verticesCount	=	static_cast<size_t>(~0ull);
382 	vector<tcu::Vec4>	result;
383 
384 	switch (m_testParams.topology)
385 	{
386 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
387 		{
388 			verticesCount = m_testParams.width * m_testParams.height;
389 
390 			result.reserve(verticesCount);
391 
392 			for (size_t y = 0; y < m_testParams.height; y++)
393 			{
394 				const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
395 
396 				for (size_t x = 0; x < m_testParams.width; x++)
397 				{
398 					const float xx = -1.0f + 2.0f * ((0.5f + float(x)) / float(m_testParams.width));
399 
400 					result.push_back(tcu::Vec4(xx, yy, 0.0f, 1.0f));
401 				}
402 			}
403 
404 			break;
405 		}
406 
407 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
408 		{
409 			verticesCount = 2 * m_testParams.height;
410 
411 			result.reserve(verticesCount);
412 
413 			for (size_t y = 0; y < m_testParams.height; y++)
414 			{
415 				const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
416 
417 				result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
418 				result.push_back(tcu::Vec4( 1.0f, yy, 0.0f, 1.0f));
419 			}
420 
421 			break;
422 		}
423 
424 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
425 		{
426 			verticesCount = 2 * m_testParams.height;
427 
428 			result.reserve(verticesCount);
429 
430 			for (size_t y = 0; y < m_testParams.height; y++)
431 			{
432 				const float yy = -1.0f + 2.0f * (0.5f + float(y)) / float(m_testParams.height);;
433 
434 				if (y % 2 == 0)
435 				{
436 					result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
437 					result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
438 				}
439 				else
440 				{
441 					result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
442 					result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
443 				}
444 			}
445 
446 			break;
447 		}
448 
449 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
450 		{
451 			verticesCount = 6;
452 
453 			result.reserve(verticesCount);
454 
455 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
456 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
457 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
458 
459 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
460 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
461 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
462 
463 			break;
464 		}
465 
466 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
467 		{
468 			verticesCount = 4;
469 
470 			result.reserve(verticesCount);
471 
472 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
473 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
474 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
475 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
476 
477 			break;
478 		}
479 
480 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
481 		{
482 			verticesCount = 4;
483 
484 			result.reserve(verticesCount);
485 
486 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
487 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
488 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
489 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
490 
491 			break;
492 		}
493 
494 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
495 		{
496 			verticesCount = 4 * m_testParams.height;
497 
498 			result.reserve(verticesCount);
499 
500 			for (size_t y = 0; y < m_testParams.height; y++)
501 			{
502 				const float yy = -1.0f + 2.0f * ((0.5f + float(y)) / float(m_testParams.height));
503 
504 				result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
505 				result.push_back(tcu::Vec4(-1.0f, yy, 0.0f, 1.0f));
506 				result.push_back(tcu::Vec4( 1.0f, yy, 0.0f, 1.0f));
507 				result.push_back(tcu::Vec4( 2.0f, yy, 0.0f, 1.0f));
508 			}
509 
510 			break;
511 		}
512 
513 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
514 		{
515 			verticesCount = 2 * m_testParams.height + 2;
516 
517 			result.reserve(verticesCount);
518 
519 			result.push_back(tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f));
520 
521 			for (size_t y = 0; y < m_testParams.height; y++)
522 			{
523 				const float ky = (0.5f + float(y)) / float(m_testParams.height);
524 				const float yy = -1.0f + 2.0f * ky;
525 
526 				if (y % 2 == 0)
527 				{
528 					result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
529 					result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
530 				}
531 				else
532 				{
533 					result.push_back(tcu::Vec4(+2.0f, yy, 0.0f, 1.0f));
534 					result.push_back(tcu::Vec4(-2.0f, yy, 0.0f, 1.0f));
535 				}
536 			}
537 
538 			result.push_back(tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f));
539 
540 			break;
541 		}
542 
543 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
544 		{
545 			verticesCount = 12;
546 
547 			result.reserve(verticesCount);
548 
549 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
550 			result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
551 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
552 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
553 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
554 			result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
555 
556 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
557 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
558 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
559 			result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
560 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
561 			result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
562 
563 			break;
564 		}
565 
566 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
567 		{
568 			verticesCount = 8;
569 
570 			result.reserve(verticesCount);
571 
572 			result.push_back(tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f));
573 			result.push_back(tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f));
574 			result.push_back(tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f));
575 			result.push_back(tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f));
576 			result.push_back(tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f));
577 			result.push_back(tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f));
578 			result.push_back(tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f));
579 			result.push_back(tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f));
580 
581 			break;
582 		}
583 
584 		default:
585 			TCU_THROW(InternalError, "Unknown topology");
586 	}
587 
588 	DE_ASSERT(result.size() == verticesCount);
589 
590 	return result;
591 }
592 
verify(BufferWithMemory * resultBuffer)593 bool FragmentShadingBarycentricDataTestInstance::verify (BufferWithMemory* resultBuffer)
594 {
595 	const size_t	components	= getComponentCount(m_testParams);
596 	const deUint32	expected	= m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS ? 10u : static_cast<deUint32>(1 << components) - 1;
597 	const deUint32* retrieved	= (deUint32*)resultBuffer->getAllocation().getHostPtr();
598 	size_t			failures	= 0;
599 
600 	{
601 		size_t n = 0;
602 
603 		for (size_t y = 0; y < m_testParams.height; y++)
604 		for (size_t x = 0; x < m_testParams.width; x++)
605 		{
606 			if (retrieved[n] != expected)
607 				failures++;
608 
609 			n++ ;
610 		}
611 	}
612 
613 	if (failures)
614 	{
615 		const uint8_t			places	= static_cast<uint8_t>(components / 4);
616 		tcu::TestLog&			log		= m_context.getTestContext().getLog();
617 		size_t					n		= 0;
618 		std::ostringstream		s;
619 
620 		s << "Expected mask:" << std::setfill('0') << std::hex << std::setw(places) << expected << std::endl;
621 
622 		for (size_t y = 0; y < m_testParams.height; y++)
623 		{
624 			for (size_t x = 0; x < m_testParams.width; x++)
625 			{
626 				s << std::setw(places) << retrieved[n] << ' ';
627 
628 				n++;
629 			}
630 
631 			s << std::endl;
632 		}
633 
634 		log << tcu::TestLog::Message << s.str() << tcu::TestLog::EndMessage;
635 	}
636 
637 	return failures == 0;
638 }
639 
createVertexBuffer(const vector<tcu::Vec4> & vertices)640 MovePtr<BufferWithMemory> FragmentShadingBarycentricDataTestInstance::createVertexBuffer (const vector<tcu::Vec4>& vertices)
641 {
642 	const DeviceInterface&			vkd							= m_context.getDeviceInterface();
643 	const VkDevice					device						= m_context.getDevice();
644 	Allocator&						allocator					= m_context.getDefaultAllocator();
645 	const VkDeviceSize				vertexBufferSize			= vertices.size() * sizeof(vertices[0]);
646 	const VkBufferCreateInfo		vertexBufferCreateInfo		= makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
647 	MovePtr<BufferWithMemory>		vertexBuffer				= MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
648 	Allocation&						vertexBufferAlloc			= vertexBuffer->getAllocation();
649 
650 	// Initialize vertex data
651 	deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
652 	flushAlloc(vkd, device, vertexBufferAlloc);
653 
654 	return vertexBuffer;
655 }
656 
getProvokingVertexLast(void)657 bool FragmentShadingBarycentricDataTestInstance::getProvokingVertexLast (void)
658 {
659 	if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
660 	{
661 		const VkPhysicalDeviceFragmentShaderBarycentricPropertiesKHR&	fragmentShaderBarycentricProperties	= m_context.getFragmentShaderBarycentricProperties();
662 
663 		if (fragmentShaderBarycentricProperties.triStripVertexOrderIndependentOfProvokingVertex)
664 			return false;
665 	}
666 
667 	return m_testParams.provokingVertexLast;
668 }
669 
iterate(void)670 tcu::TestStatus FragmentShadingBarycentricDataTestInstance::iterate (void)
671 {
672 	const InstanceInterface&		vki							= m_context.getInstanceInterface();
673 	const DeviceInterface&			vkd							= m_context.getDeviceInterface();
674 	const VkPhysicalDevice			physicalDevice				= m_context.getPhysicalDevice();
675 	const VkDevice					device						= m_context.getDevice();
676 	const auto&						deviceExtensions			= m_context.getDeviceExtensions();
677 	const VkQueue					queue						= m_context.getUniversalQueue();
678 	Allocator&						allocator					= m_context.getDefaultAllocator();
679 	const uint32_t					queueFamilyIndex			= m_context.getUniversalQueueFamilyIndex();
680 
681 	const VkDeviceSize				offsetZero					= 0ull;
682 	const VkFormat					format						= VK_FORMAT_R32_UINT;
683 	const uint32_t					pixelSize					= mapVkFormat(format).getPixelSize();
684 	const tcu::Vec4					clearColor					= tcu::Vec4(0.0f, 0.0f, 0.0f, 1.0f);
685 	const uint32_t					width						= static_cast<deUint32>(m_testParams.width);
686 	const uint32_t					height						= static_cast<deUint32>(m_testParams.height);
687 	const VkPrimitiveTopology		topology					= m_testParams.topology;
688 	const bool						withColor					= false;
689 	const bool						provokingVertexLast			= getProvokingVertexLast();
690 
691 	const vector<tcu::Vec4>			vertices					= generateVertexBuffer();
692 	const uint32_t					vertexCount					= static_cast<uint32_t>(vertices.size());
693 	MovePtr<BufferWithMemory>		vertexBuffer				= createVertexBuffer(vertices);
694 
695 	const VkImageCreateInfo			imageCreateInfo				= makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
696 	const VkImageSubresourceRange	imageSubresourceRange		= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
697 	const MovePtr<ImageWithMemory>	image						= MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
698 	const Move<VkImageView>			imageView					= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
699 
700 	const VkBufferCreateInfo		resultBufferCreateInfo		= makeBufferCreateInfo(width * height * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
701 	MovePtr<BufferWithMemory>		resultBuffer				= MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, resultBufferCreateInfo, MemoryRequirement::HostVisible));
702 
703 	const string					shaderSuffix				= (provokingVertexLast == m_testParams.provokingVertexLast) ? "" : "-forced";
704 	const ShaderWrapper				vertModule					= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert" + shaderSuffix), 0u);
705 	const ShaderWrapper				fragModule					= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("frag" + shaderSuffix), 0u);
706 	RenderPassWrapper				renderPass					= RenderPassWrapper(m_testParams.pipelineConstructionType, vkd, device, format);
707 	renderPass.createFramebuffer(vkd, device, **image, *imageView, width, height);
708 	const deUint32					pushConstants[]				= { 0, 1, 2 };
709 	const VkPushConstantRange		pushConstantRange			= makePushConstantRange(VK_SHADER_STAGE_FRAGMENT_BIT, 0, sizeof(pushConstants));
710 	const VkPushConstantRange*		pushConstantRangePtr		= m_testParams.dynamicIndexing ? &pushConstantRange : DE_NULL;
711 	const deUint32					pushConstantRangeCount		= m_testParams.dynamicIndexing ? 1 : 0;
712 	const PipelineLayoutWrapper		pipelineLayout				(m_testParams.pipelineConstructionType, vkd, device, 0, DE_NULL, pushConstantRangeCount, pushConstantRangePtr);
713 	const auto						pipelineWrapper				= makeGraphicsPipeline(m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, vertModule, fragModule, width, height, topology, VK_SAMPLE_COUNT_1_BIT, withColor, provokingVertexLast);
714 
715 	const Move<VkCommandPool>		commandPool					= createCommandPool(vkd, device, 0, queueFamilyIndex);
716 	const Move<VkCommandBuffer>		commandBuffer				= allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
717 
718 	beginCommandBuffer(vkd, *commandBuffer);
719 	{
720 		renderPass.begin(vkd, *commandBuffer, makeRect2D(width, height), clearColor);
721 
722 		pipelineWrapper->bind(*commandBuffer);
723 
724 		vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
725 
726 		if (m_testParams.dynamicIndexing)
727 			vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_FRAGMENT_BIT, 0u, sizeof(pushConstants), &pushConstants);
728 
729 		vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
730 
731 		renderPass.end(vkd, *commandBuffer);
732 
733 		copyImageToBuffer(vkd, *commandBuffer, image->get(), resultBuffer->get(), tcu::IVec2(width, height));
734 	}
735 
736 	endCommandBuffer(vkd, *commandBuffer);
737 	submitCommandsAndWait(vkd, device, queue, *commandBuffer);
738 
739 	invalidateMappedMemoryRange(vkd, device, resultBuffer->getAllocation().getMemory(), resultBuffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
740 
741 	DE_ASSERT(8 * pixelSize >= getComponentCount(m_testParams));
742 
743 	if (verify(resultBuffer.get()))
744 		return tcu::TestStatus::pass("Pass");
745 	else
746 		return tcu::TestStatus::fail("Fail");
747 }
748 
749 
750 class FragmentShadingBarycentricWeightTestInstance : public TestInstance
751 {
752 public:
753 								FragmentShadingBarycentricWeightTestInstance	(Context&			context,
754 																				 const TestParams&	testParams);
755 	virtual						~FragmentShadingBarycentricWeightTestInstance	();
756 	virtual tcu::TestStatus		iterate											(void);
757 
758 protected:
759 	void						addVertexWithColor								(vector<tcu::Vec4>&			vertices,
760 																				 const tcu::Vec4&				vertex,
761 																				 const tcu::Vec4&				color);
762 	vector<tcu::Vec4>			generateVertexBuffer							(void);
763 	MovePtr<BufferWithMemory>	createVertexBuffer								(const vector<tcu::Vec4>&	vertices);
764 	bool						verify											(VkFormat					format,
765 																				 BufferWithMemory*			referenceBuffer,
766 																				 BufferWithMemory*			resultBuffer);
767 
768 	TestParams					m_testParams;
769 };
770 
FragmentShadingBarycentricWeightTestInstance(Context & context,const TestParams & testParams)771 FragmentShadingBarycentricWeightTestInstance::FragmentShadingBarycentricWeightTestInstance (Context& context, const TestParams& testParams)
772 	: TestInstance	(context)
773 	, m_testParams	(testParams)
774 {
775 }
776 
~FragmentShadingBarycentricWeightTestInstance()777 FragmentShadingBarycentricWeightTestInstance::~FragmentShadingBarycentricWeightTestInstance ()
778 {
779 }
780 
addVertexWithColor(vector<tcu::Vec4> & vertices,const tcu::Vec4 & vertex,const tcu::Vec4 & color)781 void FragmentShadingBarycentricWeightTestInstance::addVertexWithColor (vector<tcu::Vec4>&	vertices,
782 																	   const tcu::Vec4&		vertex,
783 																	   const tcu::Vec4&		color)
784 {
785 	vertices.push_back(vertex);
786 	vertices.push_back(color);
787 }
788 
generateVertexBuffer(void)789 vector<tcu::Vec4> FragmentShadingBarycentricWeightTestInstance::generateVertexBuffer (void)
790 {
791 	const float			slope			= WEIGHT_TEST_SLOPE;
792 	const tcu::Vec4		leftBotColor	= tcu::Vec4(0.00f, 0.00f, 0.00f, 1.0f);
793 	const tcu::Vec4		leftTopColor	= tcu::Vec4(1.00f, 0.00f, 0.00f, 1.0f);
794 	const tcu::Vec4		rightTopColor	= tcu::Vec4(0.00f, 1.00f, 0.00f, 1.0f);
795 	const tcu::Vec4		rightBotColor	= tcu::Vec4(0.00f, 0.00f, 1.00f, 1.0f);
796 	const tcu::Vec4		noneColor		= tcu::Vec4(0.25f, 0.50f, 0.75f, 1.0f);
797 	size_t				vertexCount		= static_cast<size_t>(~0ull);
798 	vector<tcu::Vec4>	result;
799 
800 	DE_ASSERT(slope >= 1.0f);
801 
802 	switch (m_testParams.topology)
803 	{
804 		case VK_PRIMITIVE_TOPOLOGY_POINT_LIST:
805 		{
806 			vertexCount = m_testParams.width * m_testParams.height;
807 
808 			result.reserve(2 * vertexCount);
809 
810 			for (size_t y = 0; y < m_testParams.height; y++)
811 			{
812 				const float		ky			= (0.5f + float(y)) / float(m_testParams.height);
813 				const float		yy			= -1.0f + 2.0f * ky;
814 				const tcu::Vec4	leftColor	= mix(leftTopColor, leftBotColor, ky);
815 				const tcu::Vec4	rightColor	= mix(rightTopColor, rightBotColor, ky);
816 
817 				for (size_t x = 0; x < m_testParams.width; x++)
818 				{
819 					const float		kx			= (0.5f + float(x)) / float(m_testParams.width);
820 					const float		xx			= -1.0f + 2.0f * kx;
821 					const float		pointSlope	= 1.0f + kx * (slope - 1.0f);
822 					const tcu::Vec4	point		= tcu::Vec4(xx, yy, 0.0f, 1.0f) * pointSlope;
823 					const tcu::Vec4	color		= mix(leftColor, rightColor, kx);
824 
825 					addVertexWithColor(result, point, color);
826 				}
827 			}
828 
829 			break;
830 		}
831 
832 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST:
833 		{
834 			vertexCount = 2 * m_testParams.height;
835 
836 			result.reserve(2 * vertexCount);
837 
838 			for (size_t y = 0; y < m_testParams.height; y++)
839 			{
840 				const float		ky			= (0.5f + float(y)) / float(m_testParams.height);
841 				const float		yy			= -1.0f + 2.0f * ky;
842 				const tcu::Vec4	leftColor	= mix(leftTopColor, leftBotColor, ky);
843 				const tcu::Vec4	rightColor	= mix(rightTopColor, rightBotColor, ky);
844 				const tcu::Vec4	left		= tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
845 				const tcu::Vec4	right		= tcu::Vec4( 1.0f, yy, 0.0f, 1.0f) * slope;
846 
847 				addVertexWithColor(result, left, leftColor);
848 				addVertexWithColor(result, right, rightColor);
849 			}
850 
851 			break;
852 		}
853 
854 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP:
855 		{
856 			vertexCount = 2 * m_testParams.height;
857 
858 			result.reserve(2 * vertexCount);
859 
860 			for (size_t y = 0; y < m_testParams.height; y++)
861 			{
862 				const float		ky			= (0.5f + float(y)) / float(m_testParams.height);
863 				const float		yy			= -1.0f + 2.0f * ky;
864 				const tcu::Vec4	leftColor	= mix(leftTopColor, leftBotColor, ky);
865 				const tcu::Vec4	rightColor	= mix(rightTopColor, rightBotColor, ky);
866 				const tcu::Vec4	left		= tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
867 				const tcu::Vec4	right		= tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
868 
869 				if (y % 2 == 0)
870 				{
871 					addVertexWithColor(result, left, leftColor);
872 					addVertexWithColor(result, right, rightColor);
873 				}
874 				else
875 				{
876 					addVertexWithColor(result, right, rightColor);
877 					addVertexWithColor(result, left, leftColor);
878 				}
879 			}
880 
881 			break;
882 		}
883 
884 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST:
885 		{
886 			vertexCount = 6;
887 
888 			result.reserve(2 * vertexCount);
889 
890 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
891 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			leftBotColor);
892 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
893 
894 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
895 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	rightTopColor);
896 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
897 
898 			break;
899 		}
900 
901 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP:
902 		{
903 			vertexCount = 4;
904 
905 			result.reserve(2 * vertexCount);
906 
907 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			leftBotColor);
908 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
909 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
910 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	rightTopColor);
911 
912 			break;
913 		}
914 
915 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN:
916 		{
917 			vertexCount = 4;
918 
919 			result.reserve(2 * vertexCount);
920 
921 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
922 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			leftBotColor);
923 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
924 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	rightTopColor);
925 
926 			break;
927 		}
928 
929 		case VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY:
930 		{
931 			vertexCount = 4 * m_testParams.height;
932 
933 			result.reserve(2 * vertexCount);
934 
935 			for (size_t y = 0; y < m_testParams.height; y++)
936 			{
937 				const float		ky			= (0.5f + float(y)) / float(m_testParams.height);
938 				const float		yy			= -1.0f + 2.0f * ky;
939 				const tcu::Vec4	leftColor	= mix(leftTopColor, leftBotColor, ky);
940 				const tcu::Vec4	rightColor	= mix(rightTopColor, rightBotColor, ky);
941 				const tcu::Vec4	preLeft		= tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
942 				const tcu::Vec4	left		= tcu::Vec4(-1.0f, yy, 0.0f, 1.0f);
943 				const tcu::Vec4	right		= tcu::Vec4( 1.0f, yy, 0.0f, 1.0f) * slope;
944 				const tcu::Vec4	afterRight	= tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
945 
946 				addVertexWithColor(result, preLeft, noneColor);
947 				addVertexWithColor(result, left, leftColor);
948 				addVertexWithColor(result, right, rightColor);
949 				addVertexWithColor(result, afterRight, noneColor);
950 			}
951 
952 			break;
953 		}
954 
955 		case VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY:
956 		{
957 			vertexCount = 2 * m_testParams.height + 2;
958 
959 			result.reserve(2 * vertexCount);
960 
961 			addVertexWithColor(result, tcu::Vec4(-10.0f, -10.0f, 0.0f, 1.0f), noneColor);
962 
963 			for (size_t y = 0; y < m_testParams.height; y++)
964 			{
965 				const float		ky			= (0.5f + float(y)) / float(m_testParams.height);
966 				const float		yy			= -1.0f + 2.0f * ky;
967 				const tcu::Vec4	leftColor	= mix(leftTopColor, leftBotColor, ky);
968 				const tcu::Vec4	rightColor	= mix(rightTopColor, rightBotColor, ky);
969 				const tcu::Vec4	left		= tcu::Vec4(-2.0f, yy, 0.0f, 1.0f);
970 				const tcu::Vec4	right		= tcu::Vec4( 2.0f, yy, 0.0f, 1.0f) * slope;
971 
972 				if (y % 2 == 0)
973 				{
974 					addVertexWithColor(result, left, leftColor);
975 					addVertexWithColor(result, right, rightColor);
976 				}
977 				else
978 				{
979 					addVertexWithColor(result, right, rightColor);
980 					addVertexWithColor(result, left, leftColor);
981 				}
982 			}
983 
984 			addVertexWithColor(result, tcu::Vec4(+10.0f, +10.0f, 0.0f, 1.0f), noneColor);
985 
986 			break;
987 		}
988 
989 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY:
990 		{
991 			vertexCount = 12;
992 
993 			result.reserve(2 * vertexCount);
994 
995 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			leftBotColor);
996 			addVertexWithColor(result, tcu::Vec4(-3.0f, +1.0f, 0.0f, 1.0f),			noneColor);
997 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
998 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	noneColor);
999 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
1000 			addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope,	noneColor);
1001 
1002 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
1003 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			noneColor);
1004 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
1005 			addVertexWithColor(result, tcu::Vec4(+3.0f, +1.0f, 0.0f, 1.0f) * slope,	noneColor);
1006 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	rightTopColor);
1007 			addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f),			leftTopColor);
1008 
1009 			break;
1010 		}
1011 
1012 		case VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY:
1013 		{
1014 			vertexCount = 8;
1015 
1016 			result.reserve(2 * vertexCount);
1017 
1018 			addVertexWithColor(result, tcu::Vec4(-1.0f, +1.0f, 0.0f, 1.0f),			leftBotColor);
1019 			addVertexWithColor(result, tcu::Vec4(-3.0f, -1.0f, 0.0f, 1.0f),			noneColor);
1020 			addVertexWithColor(result, tcu::Vec4(-1.0f, -1.0f, 0.0f, 1.0f),			leftTopColor);
1021 			addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope,	noneColor);
1022 			addVertexWithColor(result, tcu::Vec4(+1.0f, +1.0f, 0.0f, 1.0f) * slope,	rightBotColor);
1023 			addVertexWithColor(result, tcu::Vec4(-1.0f, -3.0f, 0.0f, 1.0f),			noneColor);
1024 			addVertexWithColor(result, tcu::Vec4(+1.0f, -1.0f, 0.0f, 1.0f) * slope,	rightTopColor);
1025 			addVertexWithColor(result, tcu::Vec4(+1.0f, +3.0f, 0.0f, 1.0f) * slope,	noneColor);
1026 
1027 			break;
1028 		}
1029 
1030 		default:
1031 			TCU_THROW(InternalError, "Unknown topology");
1032 	}
1033 
1034 	DE_ASSERT(result.size() == 2 * vertexCount);
1035 
1036 	return result;
1037 }
1038 
verify(VkFormat format,BufferWithMemory * referenceBuffer,BufferWithMemory * resultBuffer)1039 bool FragmentShadingBarycentricWeightTestInstance::verify (VkFormat format, BufferWithMemory* referenceBuffer, BufferWithMemory* resultBuffer)
1040 {
1041 	const deUint32*						refernceData	= (deUint32*)referenceBuffer->getAllocation().getHostPtr();
1042 	const deUint32*						resultData		= (deUint32*)resultBuffer->getAllocation().getHostPtr();
1043 	tcu::TestLog&						log				= m_context.getTestContext().getLog();
1044 	const tcu::ConstPixelBufferAccess	refImage		(mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height, 1u, refernceData);
1045 	const tcu::ConstPixelBufferAccess	resultImage		(mapVkFormat(format), (int)m_testParams.width, (int)m_testParams.height, 1u, resultData);
1046 	const tcu::UVec4					threshold		(1, 1, 1, 1);
1047 	bool								result			= tcu::intThresholdCompare(log,
1048 																				   "ComparisonResult",
1049 																				   "Image comparison result",
1050 																				   refImage,
1051 																				   resultImage,
1052 																				   threshold,
1053 																				   tcu::COMPARE_LOG_ON_ERROR);
1054 
1055 	return result;
1056 }
1057 
createVertexBuffer(const vector<tcu::Vec4> & vertices)1058 MovePtr<BufferWithMemory> FragmentShadingBarycentricWeightTestInstance::createVertexBuffer (const vector<tcu::Vec4>& vertices)
1059 {
1060 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
1061 	const VkDevice					device					= m_context.getDevice();
1062 	Allocator&						allocator				= m_context.getDefaultAllocator();
1063 	const VkDeviceSize				vertexBufferSize		= vertices.size() * sizeof(vertices[0]);
1064 	const VkBufferCreateInfo		vertexBufferCreateInfo	= makeBufferCreateInfo(vertexBufferSize, VK_BUFFER_USAGE_VERTEX_BUFFER_BIT);
1065 	MovePtr<BufferWithMemory>		vertexBuffer			= MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, vertexBufferCreateInfo, MemoryRequirement::HostVisible));
1066 	Allocation&						vertexBufferAlloc		= vertexBuffer->getAllocation();
1067 
1068 	// Initialize vertex data
1069 	deMemcpy(vertexBufferAlloc.getHostPtr(), vertices.data(), (size_t)vertexBufferSize);
1070 	flushAlloc(vkd, device, vertexBufferAlloc);
1071 
1072 	return vertexBuffer;
1073 }
1074 
iterate(void)1075 tcu::TestStatus FragmentShadingBarycentricWeightTestInstance::iterate (void)
1076 {
1077 	const InstanceInterface&		vki						= m_context.getInstanceInterface();
1078 	const DeviceInterface&			vkd						= m_context.getDeviceInterface();
1079 	const VkPhysicalDevice			physicalDevice			= m_context.getPhysicalDevice();
1080 	const VkDevice					device					= m_context.getDevice();
1081 	const auto&						deviceExtensions		= m_context.getDeviceExtensions();
1082 	const VkQueue					queue					= m_context.getUniversalQueue();
1083 	Allocator&						allocator				= m_context.getDefaultAllocator();
1084 	const uint32_t					queueFamilyIndex		= m_context.getUniversalQueueFamilyIndex();
1085 
1086 	const VkDeviceSize				offsetZero				= 0ull;
1087 	const VkFormat					format					= VK_FORMAT_R8G8B8A8_UNORM;
1088 	const uint32_t					pixelSize				= mapVkFormat(format).getPixelSize();
1089 	const uint32_t					width					= static_cast<deUint32>(m_testParams.width);
1090 	const uint32_t					height					= static_cast<deUint32>(m_testParams.height);
1091 	const bool						dynamicStateTopology	= m_testParams.dynamicTopologyInPipeline;
1092 	const VkPrimitiveTopology		pipelineTopology		= dynamicStateTopology ? primitiveTopologyCastToList(m_testParams.topology) : m_testParams.topology;
1093 	const bool						withColor				= true;
1094 	const bool						provokingVertexLast		= m_testParams.provokingVertexLast;
1095 	const bool						useMultisampling		= m_testParams.sampleCount > VK_SAMPLE_COUNT_1_BIT;
1096 	const float						teta					= deFloatRadians(-float(m_testParams.rotation));
1097 	const float						mvp[4*4]				=
1098 	{
1099 		cos(teta), -sin(teta), 0.0f, 0.0f,
1100 		sin(teta),  cos(teta), 0.0f, 0.0f,
1101 		0.0f,            0.0f, 1.0f, 0.0f,
1102 		0.0f,            0.0f, 0.0f, 1.0f
1103 	};
1104 	const vector<tcu::Vec4>			vertices				= generateVertexBuffer();
1105 	const uint32_t					vertexCount				= static_cast<uint32_t>(vertices.size() / 2);
1106 	MovePtr<BufferWithMemory>		vertexBuffer			= createVertexBuffer(vertices);
1107 
1108 	const VkBufferCreateInfo		bufferCreateInfo		= makeBufferCreateInfo(width * height * pixelSize, VK_BUFFER_USAGE_TRANSFER_DST_BIT);
1109 	MovePtr<BufferWithMemory>		resultBuffer			= MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1110 	MovePtr<BufferWithMemory>		referenceBuffer			= MovePtr<BufferWithMemory>(new BufferWithMemory(vkd, device, allocator, bufferCreateInfo, MemoryRequirement::HostVisible));
1111 	const Move<VkRenderPass>		renderPass				= makeRenderPass(vkd, device, format, m_testParams.sampleCount);
1112 	const Move<VkCommandPool>		commandPool				= createCommandPool(vkd, device, 0, queueFamilyIndex);
1113 	const ShaderWrapper				vertModule				= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get("vert"), 0u);
1114 	const VkImageCreateInfo			imageCreateInfo			= makeImageCreateInfo(format, width, height, VK_SAMPLE_COUNT_1_BIT);
1115 	const VkImageCreateInfo			msImageCreateInfo		= makeImageCreateInfo(format, width, height, m_testParams.sampleCount);
1116 	const VkImageSubresourceRange	imageSubresourceRange	= makeImageSubresourceRange(VK_IMAGE_ASPECT_COLOR_BIT, 0u, 1u, 0u, 1u);
1117 	const std::vector<VkClearValue> clearValues				(2u, makeClearValueColorU32(0u, 0u, 0u, 0u));
1118 
1119 	std::vector<VkImageMemoryBarrier> initialImageBarriers(2, makeImageMemoryBarrier(VK_ACCESS_TRANSFER_WRITE_BIT, VK_ACCESS_COLOR_ATTACHMENT_READ_BIT | VK_ACCESS_COLOR_ATTACHMENT_WRITE_BIT, VK_IMAGE_LAYOUT_UNDEFINED, VK_IMAGE_LAYOUT_GENERAL, DE_NULL, imageSubresourceRange));
1120 
1121 	for (size_t ndx = 0; ndx < 2; ndx++)
1122 	{
1123 		const MovePtr<ImageWithMemory>	image				= MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, imageCreateInfo, MemoryRequirement::Any));
1124 		const Move<VkImageView>			imageView			= makeImageView(vkd, device, **image, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1125 		MovePtr<ImageWithMemory>		msImage;
1126 		Move<VkImageView>				msImageView;
1127 
1128 		initialImageBarriers[0].image = **image;
1129 
1130 		if (useMultisampling)
1131 		{
1132 			msImage		= MovePtr<ImageWithMemory>(new ImageWithMemory(vkd, device, allocator, msImageCreateInfo, MemoryRequirement::Any));
1133 			msImageView	= makeImageView(vkd, device, **msImage, VK_IMAGE_VIEW_TYPE_2D, format, imageSubresourceRange);
1134 			initialImageBarriers[1].image = **msImage;
1135 		}
1136 
1137 		const std::vector<VkImageView>	imageViewVect		= { *imageView, *msImageView };
1138 		const Move<VkFramebuffer>		framebuffer			= makeFramebuffer(vkd, device, *renderPass, 1u + useMultisampling, imageViewVect.data(), width, height);
1139 		const Move<VkCommandBuffer>		commandBuffer		= allocateCommandBuffer(vkd, device, *commandPool, VK_COMMAND_BUFFER_LEVEL_PRIMARY);
1140 		const BufferWithMemory*			buffer				= (ndx == 0) ? resultBuffer.get() : referenceBuffer.get();
1141 		const string					fragModuleName		= (ndx == 0) ? "frag_test" : "frag_reference";
1142 		const ShaderWrapper				fragModule			= ShaderWrapper(vkd, device, m_context.getBinaryCollection().get(fragModuleName), 0u);
1143 		const VkPushConstantRange		pushConstantRange	= makePushConstantRange(VK_SHADER_STAGE_VERTEX_BIT, 0, sizeof(mvp));
1144 		const PipelineLayoutWrapper		pipelineLayout		(m_testParams.pipelineConstructionType, vkd, device, 0, DE_NULL, 1, &pushConstantRange);
1145 		const auto						pipelineWrapper		= makeGraphicsPipeline(m_testParams.pipelineConstructionType, vki, vkd, physicalDevice, device, deviceExtensions, pipelineLayout, *renderPass, vertModule, fragModule, width, height, pipelineTopology, m_testParams.sampleCount, withColor, provokingVertexLast, dynamicStateTopology);
1146 		const VkPipeline				pipeline			= pipelineWrapper->getPipeline();
1147 
1148 		beginCommandBuffer(vkd, *commandBuffer);
1149 		{
1150 			cmdPipelineImageMemoryBarrier(vkd, *commandBuffer, VK_PIPELINE_STAGE_TRANSFER_BIT, VK_PIPELINE_STAGE_COLOR_ATTACHMENT_OUTPUT_BIT, initialImageBarriers.data(), 1u + useMultisampling);
1151 
1152 			if (dynamicStateTopology)
1153 				vkd.cmdSetPrimitiveTopology(*commandBuffer, m_testParams.topology);
1154 
1155 			beginRenderPass(vkd, *commandBuffer, *renderPass, *framebuffer, makeRect2D(width, height), 1u + useMultisampling, clearValues.data());
1156 			{
1157 				vkd.cmdBindPipeline(*commandBuffer, VK_PIPELINE_BIND_POINT_GRAPHICS, pipeline);
1158 
1159 				vkd.cmdBindVertexBuffers(*commandBuffer, 0u, 1u, &vertexBuffer->get(), &offsetZero);
1160 
1161 				vkd.cmdPushConstants(*commandBuffer, *pipelineLayout, VK_SHADER_STAGE_VERTEX_BIT, 0u, sizeof(mvp), &mvp);
1162 
1163 				vkd.cmdDraw(*commandBuffer, vertexCount, 1u, 0u, 0u);
1164 			}
1165 			endRenderPass(vkd, *commandBuffer);
1166 
1167 			copyImageToBuffer(vkd, *commandBuffer, image->get(), buffer->get(), tcu::IVec2(width, height));
1168 		}
1169 		endCommandBuffer(vkd, *commandBuffer);
1170 		submitCommandsAndWait(vkd, device, queue, *commandBuffer);
1171 
1172 		invalidateMappedMemoryRange(vkd, device, buffer->getAllocation().getMemory(), buffer->getAllocation().getOffset(), VK_WHOLE_SIZE);
1173 	}
1174 
1175 	if (verify(format, referenceBuffer.get(), resultBuffer.get()))
1176 		return tcu::TestStatus::pass("Pass");
1177 	else
1178 		return tcu::TestStatus::fail("Fail");
1179 }
1180 
1181 
1182 class FragmentShadingBarycentricTestCase : public TestCase
1183 {
1184 public:
1185 							FragmentShadingBarycentricTestCase	(tcu::TestContext&	context,
1186 																 const char*		name,
1187 																 const TestParams	testParams);
1188 							~FragmentShadingBarycentricTestCase	(void);
1189 
1190 	virtual void			checkSupport						(Context&			context) const;
1191 	virtual	void			initPrograms						(SourceCollections&	programCollection) const;
1192 	virtual TestInstance*	createInstance						(Context&			context) const;
1193 
1194 private:
1195 	void					initDataPrograms					(SourceCollections&	programCollection) const;
1196 	void					initMiscDataPrograms				(SourceCollections& programCollection) const;
1197 	void					initWeightPrograms					(SourceCollections&	programCollection) const;
1198 	string					getDataPrimitiveFormula				(void) const;
1199 	string					getDataVertexFormula				(const uint32_t		vertex,
1200 																 const bool*		provokingVertexLastPtr = DE_NULL) const;
1201 
1202 	TestParams				m_testParams;
1203 };
1204 
FragmentShadingBarycentricTestCase(tcu::TestContext & context,const char * name,const TestParams testParams)1205 FragmentShadingBarycentricTestCase::FragmentShadingBarycentricTestCase (tcu::TestContext& context, const char* name, const TestParams testParams)
1206 	: vkt::TestCase	(context, name)
1207 	, m_testParams	(testParams)
1208 {
1209 }
1210 
~FragmentShadingBarycentricTestCase(void)1211 FragmentShadingBarycentricTestCase::~FragmentShadingBarycentricTestCase (void)
1212 {
1213 }
1214 
checkSupport(Context & context) const1215 void FragmentShadingBarycentricTestCase::checkSupport (Context& context) const
1216 {
1217 	const auto&		vki				= context.getInstanceInterface();
1218 	const auto		physicalDevice	= context.getPhysicalDevice();
1219 
1220 	context.requireDeviceFunctionality("VK_KHR_fragment_shader_barycentric");
1221 
1222 	const VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR& fragmentShaderBarycentricFeatures = context.getFragmentShaderBarycentricFeatures();
1223 
1224 	if (!fragmentShaderBarycentricFeatures.fragmentShaderBarycentric)
1225 		TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceFragmentShaderBarycentricFeaturesKHR.fragmentShaderBarycentric");
1226 
1227 	checkPipelineConstructionRequirements(vki, physicalDevice, m_testParams.pipelineConstructionType);
1228 
1229 	if (m_testParams.provokingVertexLast)
1230 	{
1231 		context.requireDeviceFunctionality("VK_EXT_provoking_vertex");
1232 
1233 		const VkPhysicalDeviceProvokingVertexFeaturesEXT&	provokingVertexFeaturesEXT	= context.getProvokingVertexFeaturesEXT();
1234 
1235 		if (!provokingVertexFeaturesEXT.provokingVertexLast)
1236 			TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceProvokingVertexFeaturesEXT.provokingVertexLast");
1237 	}
1238 
1239 	if (m_testParams.dynamicTopologyInPipeline)
1240 	{
1241 		context.requireDeviceFunctionality("VK_EXT_extended_dynamic_state");
1242 
1243 		const VkPhysicalDeviceExtendedDynamicStateFeaturesEXT& extendedDynamicStateFeaturesEXT	= context.getExtendedDynamicStateFeaturesEXT();
1244 
1245 		if (!extendedDynamicStateFeaturesEXT.extendedDynamicState)
1246 			TCU_THROW(NotSupportedError, "Requires VkPhysicalDeviceExtendedDynamicStateFeaturesEXT.extendedDynamicState");
1247 	}
1248 
1249 	if ((m_testParams.dataType == glu::TYPE_DOUBLE) ||
1250 		(m_testParams.dataType == glu::TYPE_DOUBLE_VEC2) ||
1251 		(m_testParams.dataType == glu::TYPE_DOUBLE_VEC3) ||
1252 		(m_testParams.dataType == glu::TYPE_DOUBLE_VEC4))
1253 	{
1254 		VkPhysicalDeviceFeatures2 features2;
1255 		deMemset(&features2, 0, sizeof(features2));
1256 		features2.sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_FEATURES_2;
1257 		features2.pNext = nullptr;
1258 		vki.getPhysicalDeviceFeatures2(physicalDevice, &features2);
1259 		if (features2.features.shaderFloat64 != VK_TRUE)
1260 		{
1261 			TCU_THROW(NotSupportedError, "shaderFloat64 not supported");
1262 		}
1263 	}
1264 }
1265 
createInstance(Context & context) const1266 TestInstance* FragmentShadingBarycentricTestCase::createInstance (Context& context) const
1267 {
1268 	switch (m_testParams.testType)
1269 	{
1270 		case TEST_TYPE_DATA:	return new FragmentShadingBarycentricDataTestInstance(context, m_testParams);
1271 		case TEST_TYPE_WEIGHTS:	return new FragmentShadingBarycentricWeightTestInstance(context, m_testParams);
1272 		default:				TCU_THROW(InternalError, "Unknown testType");
1273 	}
1274 }
1275 
initPrograms(SourceCollections & programCollection) const1276 void FragmentShadingBarycentricTestCase::initPrograms (SourceCollections& programCollection) const
1277 {
1278 	switch (m_testParams.testType)
1279 	{
1280 		case TEST_TYPE_DATA:
1281 			if (m_testParams.testSubtype == TEST_SUBTYPE_PERVERTEX_CORRECTNESS)
1282 				initMiscDataPrograms(programCollection);
1283 			else
1284 				initDataPrograms(programCollection);
1285 			break;
1286 		case TEST_TYPE_WEIGHTS:
1287 			initWeightPrograms(programCollection);
1288 			break;
1289 		default:
1290 			TCU_THROW(InternalError, "Unknown testType");
1291 	}
1292 }
1293 
getDataPrimitiveFormula(void) const1294 string FragmentShadingBarycentricTestCase::getDataPrimitiveFormula (void) const
1295 {
1296 	const char*	primitiveFormulas[] =
1297 	{
1298 		"w * y + x",		//  VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1299 		"y",				//  VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1300 		"2*y",				//  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1301 		"(x < y) ? 0 : 1",	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1302 		"(x < y) ? 0 : 1",	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1303 		"(x < y) ? 0 : 1",	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1304 		"y",				//  VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1305 		"2*y",				//  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1306 		"(x < y) ? 0 : 1",	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1307 		"(x < y) ? 0 : 1",	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1308 		"NOT IMPLEMENTED",	//  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1309 	};
1310 
1311 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(primitiveFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1312 	DE_ASSERT(m_testParams.topology < DE_LENGTH_OF_ARRAY(primitiveFormulas));
1313 
1314 	return primitiveFormulas[m_testParams.topology];
1315 }
1316 
getDataVertexFormula(const uint32_t vertex,const bool * provokingVertexLastPtr) const1317 string FragmentShadingBarycentricTestCase::getDataVertexFormula (const uint32_t vertex, const bool* provokingVertexLastPtr) const
1318 {
1319 	typedef const char* TriVertexFormula[3];
1320 
1321 	// Accoriding "Barycentric Interpolation" section
1322 	const TriVertexFormula	topologyVertexFormulas[]		=
1323 	{
1324 		{	"p",				"p",				"p"					},	//  VK_PRIMITIVE_TOPOLOGY_POINT_LIST
1325 		{	"2*p",				"2*p+1",			"2*p+1"				},	//  VK_PRIMITIVE_TOPOLOGY_LINE_LIST
1326 		{	"p",				"p+1",				"p+1"				},	//  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP
1327 		{	"3*p",				"3*p+1",			"3*p+2"				},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST
1328 		{	"p",				"even?p+1:p+2",		"even?p+2:p+1"		},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1329 		{	"p+1",				"p+2",				"0"					},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1330 		{	"4*p+1",			"4*p+2",			"4*p+2"				},	//  VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY
1331 		{	"p+1",				"p+2",				"p+2"				},	//  VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY
1332 		{	"6*p",				"6*p+2",			"6*p+4"				},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY
1333 		{	"2*p",				"even?2*p+2:2*p+4",	"even?2*p+4:2*p+2"	},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1334 		{	"",					"",					""					},	//  VK_PRIMITIVE_TOPOLOGY_PATCH_LIST
1335 	};
1336 	const TriVertexFormula	topologyVertexFormulasLast[]	=
1337 	{
1338 		{	"even?p:p+1",		"even?p+1:p",		"p+2"				},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP
1339 		{	"0",				"p+1",				"p+2"				},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN
1340 		{	"even?2*p:2*p+2",	"even?2*p+2:2*p",	"2*p+4"				},	//  VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY
1341 	};
1342 	const bool				provokingVertexLast				= provokingVertexLastPtr ? (*provokingVertexLastPtr) : m_testParams.provokingVertexLast;
1343 	const bool				provokingLastTriangleStrip		= provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP;
1344 	const bool				provokingLastTriangleFan		= provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN;
1345 	const bool				provokingLastTriangleStripAdj	= provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY;
1346 	const TriVertexFormula*	triVertexFormula				= provokingLastTriangleStrip    ? &topologyVertexFormulasLast[0]
1347 															: provokingLastTriangleFan      ? &topologyVertexFormulasLast[1]
1348 															: provokingLastTriangleStripAdj ? &topologyVertexFormulasLast[2]
1349 															: &topologyVertexFormulas[static_cast<size_t>(m_testParams.topology)];
1350 
1351 	DE_STATIC_ASSERT(DE_LENGTH_OF_ARRAY(topologyVertexFormulas) == vk::VK_PRIMITIVE_TOPOLOGY_LAST);
1352 	DE_ASSERT(vertex < DE_LENGTH_OF_ARRAY(triVertexFormula[0]));
1353 
1354 	return "(" + string(triVertexFormula[0][vertex]) + ")";
1355 }
1356 
initDataPrograms(SourceCollections & programCollection) const1357 void FragmentShadingBarycentricTestCase::initDataPrograms (SourceCollections& programCollection) const
1358 {
1359 	map<string, string>			attributes;
1360 	const string				primitiveType	= string(getDataTypeName(m_testParams.dataType));
1361 	const string				dataStructType	= m_testParams.aggregate == 1 ? "struct DataStruct {" + primitiveType + " q;};" : "";
1362 	const string				typePrefix		= m_testParams.aggregate == 0 ? primitiveType
1363 												: m_testParams.aggregate == 1 ? "DataStruct"
1364 												: primitiveType;
1365 	const string				typeSuffix		= m_testParams.aggregate == 0 ? ""
1366 												: m_testParams.aggregate == 1 ? ""
1367 												: "[" + de::toString(m_testParams.aggregate) + "]";
1368 	const int					scalarSize		= getDataTypeScalarSize(m_testParams.dataType);
1369 	const string				scalarName		= getDataTypeName(getDataTypeScalarType(m_testParams.dataType));
1370 	const string				vectoredInit	= (scalarSize == 1) ? primitiveType + "(n)"
1371 												: (scalarSize == 2) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n))"
1372 												: (scalarSize == 3) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n), " + scalarName + "(4*n))"
1373 												: (scalarSize == 4) ? primitiveType + "(" + scalarName + "(n), " + scalarName + "(2*n), " + scalarName + "(4*n), " + scalarName + "(8*n))"
1374 												: "NOT IMPLEMENTED";
1375 	const string				value			= m_testParams.aggregate == 0 ? vectoredInit
1376 												: m_testParams.aggregate == 1 ? "DataStruct(" + vectoredInit + ")"
1377 												: m_testParams.aggregate == 2 ? primitiveType + "[2](" + vectoredInit + ", " + scalarName + "(3)*" + vectoredInit + ")"
1378 												: "NOT IMPLEMENTED";
1379 	const size_t				componentCount	= getComponentCount(m_testParams);
1380 	const string				scalarized		= (scalarSize == 1) ? "e${R},"
1381 												: (scalarSize == 2) ? "e${R}.x,e${R}.y,"
1382 												: (scalarSize == 3) ? "e${R}.x,e${R}.y,e${R}.z,"
1383 												: (scalarSize == 4) ? "e${R}.x,e${R}.y,e${R}.z,e${R}.w,"
1384 												: "NOT IMPLEMENTED";
1385 	const string				deaggregated	= m_testParams.aggregate == 0 ? replace(scalarized, "${R}", "${S}")
1386 												: m_testParams.aggregate == 1 ? replace(scalarized, "${R}", "${S}.q")
1387 												: m_testParams.aggregate == 2 ? replace(scalarized, "${R}", "${S}[0]") + replace(scalarized, "${R}", "${S}[1]")
1388 												: "NOT IMPLEMENTED";
1389 	const string				unwrap			= replace(deaggregated, "${S}", "A") + replace(deaggregated, "${S}", "B")+ replace(deaggregated, "${S}", "C");
1390 	const string				expected		= unwrap.substr(0, unwrap.size() - 1);
1391 	const string				arrived			= replace(expected, "e", "v");
1392 	const string				dynamicIndexing	= m_testParams.dynamicIndexing ? "layout(push_constant) uniform PushConstant { uint n[3]; } pc;\n" : "";
1393 	const string				i0				= m_testParams.dynamicIndexing ? "pc.n[0]" : "0";
1394 	const string				i1				= m_testParams.dynamicIndexing ? "pc.n[1]" : "1";
1395 	const string				i2				= m_testParams.dynamicIndexing ? "pc.n[2]" : "2";
1396 	const string				primitiveId		= getDataPrimitiveFormula();
1397 	const string				vertexFormula[]	= { getDataVertexFormula(0), getDataVertexFormula(1), getDataVertexFormula(2) };
1398 	const tcu::StringTemplate	vertShader		(string(
1399 		"#version 450\n"
1400 		"#extension GL_EXT_fragment_shader_barycentric : require\n"
1401 		"\n"
1402 		"${dataStruct}\n"
1403 		"\n"
1404 		"layout(location = 0) in  vec4 in_position;\n"
1405 		"layout(location = 0) out ${typePrefix} data${typeSuffix};\n"
1406 		"\n"
1407 		"out gl_PerVertex\n"
1408 		"{\n"
1409 		"    vec4  gl_Position;\n"
1410 		"    float gl_PointSize;\n"
1411 		"};\n"
1412 		"\n"
1413 		"void main()\n"
1414 		"{\n"
1415 		"    const int n  = gl_VertexIndex + 1;\n"
1416 		"    data         = ${value};\n"
1417 		"    gl_PointSize = 1.0;\n"
1418 		"    gl_Position  = in_position;\n"
1419 		"}\n"));
1420 	const tcu::StringTemplate	fragShader		(
1421 		string("#version 450\n") +
1422 		"#extension GL_EXT_fragment_shader_barycentric : require\n"
1423 		"\n"
1424 		"${dataStruct}\n"
1425 		"\n"
1426 		"${dynamicIndexing}\n"
1427 		"layout(location = 0) pervertexEXT in ${typePrefix} data[]${typeSuffix};\n"
1428 		"layout(location = 0) out uvec4 out_color;\n"
1429 		"\n"
1430 		"void main()\n"
1431 		"{\n"
1432 		"    const int  w    = " + de::toString(m_testParams.width) + ";\n"
1433 		"    const int  h    = " + de::toString(m_testParams.height) + ";\n"
1434 		"    const int  x    = int(gl_FragCoord.x - 0.5f);\n"
1435 		"    const int  y    = int(gl_FragCoord.y - 0.5f);\n"
1436 		"    const int  p    = ${primitiveId};\n"
1437 		"    const bool even = (p%2 == 0);\n"
1438 		"\n"
1439 		"    ${typePrefix} eA${typeSuffix}; { const int n = 1 + ${vertexFormula0}; eA = ${value}; }\n"
1440 		"    ${typePrefix} eB${typeSuffix}; { const int n = 1 + ${vertexFormula1}; eB = ${value}; }\n"
1441 		"    ${typePrefix} eC${typeSuffix}; { const int n = 1 + ${vertexFormula2}; eC = ${value}; }\n"
1442 		"\n"
1443 		"    ${scalarName} e[${componentCount}] = { ${expected} };\n"
1444 		"\n"
1445 		"    ${typePrefix} vA${typeSuffix}; { vA = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i0}][0],data[${i0}][1])" : "data[${i0}]") + "; }\n"
1446 		"    ${typePrefix} vB${typeSuffix}; { vB = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i1}][0],data[${i1}][1])" : "data[${i1}]") + "; }\n"
1447 		"    ${typePrefix} vC${typeSuffix}; { vC = " + string(m_testParams.aggregate == 2 ? "${typePrefix}${typeSuffix}(data[${i2}][0],data[${i2}][1])" : "data[${i2}]") + "; }\n"
1448 		"    ${scalarName} v[${componentCount}] = { ${arrived} };\n"
1449 		"\n"
1450 		"    int mask = 0;\n"
1451 		"\n"
1452 		"    for (int i = 0; i<${componentCount}; i++)\n"
1453 		"        if (e[i] == v[i])\n"
1454 		"            mask = mask | (1<<i);\n"
1455 		"\n"
1456 		"    out_color = uvec4(mask);\n"
1457 		"}\n");
1458 
1459 	attributes["typePrefix"]		= typePrefix;
1460 	attributes["typeSuffix"]		= typeSuffix;
1461 	attributes["value"]				= value;
1462 	attributes["componentCount"]	= de::toString(componentCount);
1463 	attributes["expected"]			= expected;
1464 	attributes["arrived"]			= arrived;
1465 	attributes["scalarName"]		= scalarName;
1466 	attributes["dataStruct"]		= dataStructType;
1467 	attributes["dynamicIndexing"]	= dynamicIndexing;
1468 	attributes["primitiveId"]		= primitiveId;
1469 	attributes["i0"]				= i0;
1470 	attributes["i1"]				= i1;
1471 	attributes["i2"]				= i2;
1472 	attributes["vertexFormula0"]	= vertexFormula[0];
1473 	attributes["vertexFormula1"]	= vertexFormula[1];
1474 	attributes["vertexFormula2"]	= vertexFormula[2];
1475 
1476 	if (isPrimitiveTopologyLine(m_testParams.topology))
1477 	{
1478 		DE_ASSERT(vertexFormula[2] == vertexFormula[1]);
1479 	}
1480 	else if (isPrimitiveTopologyPoint(m_testParams.topology))
1481 	{
1482 		DE_ASSERT(vertexFormula[2] == vertexFormula[1] && vertexFormula[1] == vertexFormula[0]);
1483 	}
1484 
1485 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader.specialize(attributes));
1486 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader.specialize(attributes));
1487 
1488 	if (m_testParams.provokingVertexLast && m_testParams.topology == VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP)
1489 	{
1490 		const bool	provokingVertexLast = false;
1491 
1492 		attributes["vertexFormula0"] = getDataVertexFormula(0, &provokingVertexLast);
1493 		attributes["vertexFormula1"] = getDataVertexFormula(1, &provokingVertexLast);
1494 		attributes["vertexFormula2"] = getDataVertexFormula(2, &provokingVertexLast);
1495 
1496 		programCollection.glslSources.add("vert-forced") << glu::VertexSource(vertShader.specialize(attributes));
1497 		programCollection.glslSources.add("frag-forced") << glu::FragmentSource(fragShader.specialize(attributes));
1498 	}
1499 }
1500 
initMiscDataPrograms(SourceCollections & programCollection) const1501 void FragmentShadingBarycentricTestCase::initMiscDataPrograms(SourceCollections& programCollection) const
1502 {
1503 	const std::string vertShader(
1504 		"#version 450\n"
1505 		"#extension GL_EXT_fragment_shader_barycentric : require\n"
1506 		"\n"
1507 		"layout(location = 0) in  vec4 in_position;\n"
1508 		"layout(location = 0) out uvec2 dataA;\n"
1509 		"layout(location = 1) out uvec2 dataB;\n"
1510 		"void main()\n"
1511 		"{\n"
1512 		// we will draw two triangles and we need to convert dataA for
1513 		// second triangle to 0-2 range to simplify verification
1514 		"    dataA       = uvec2(mod(gl_VertexIndex, 3));\n"
1515 		"    dataB       = uvec2(7);\n"
1516 		"    gl_Position = in_position;\n"
1517 		"}\n");
1518 	const std::string fragShader(
1519 		"#version 450\n"
1520 		"#extension GL_EXT_fragment_shader_barycentric : require\n"
1521 		"layout(location = 0) pervertexEXT in uvec2 dataA[];\n"
1522 		"layout(location = 1) flat in uvec2 dataB;\n"
1523 		"layout(location = 0) out uvec4 out_color;\n"
1524 		"void main()\n"
1525 		"{\n"
1526 		// make sure that PerVertex decoration is only applied to location 0
1527 		// and that the location 1 isn't compacted/remapped to location 0
1528 		// by adding all values and making sure the result is 10
1529 		"    out_color = uvec4(dataA[0].y + dataA[1].x + dataA[2].y + dataB.x);\n"
1530 		"}\n");
1531 
1532 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
1533 	programCollection.glslSources.add("frag") << glu::FragmentSource(fragShader);
1534 }
1535 
initWeightPrograms(SourceCollections & programCollection) const1536 void FragmentShadingBarycentricTestCase::initWeightPrograms (SourceCollections& programCollection) const
1537 {
1538 	const string				baryCoordVariable	= m_testParams.perspective
1539 													? "BaryCoord"
1540 													: "BaryCoordNoPersp";
1541 	const string				declspecRef			= m_testParams.perspective ? "" : "noperspective";
1542 	const string				vertShader			=
1543 		"#version 450\n"
1544 		"\n"
1545 		"layout(location = 0) in  vec4 in_position;\n"
1546 		"layout(location = 1) in  vec4 in_color;\n"
1547 		"layout(location = 0) out vec3 color;\n"
1548 		"layout(push_constant) uniform PushConstant { mat4 mvp; } pc;\n"
1549 		"\n"
1550 		"void main()\n"
1551 		"{\n"
1552 		"    color        = in_color.xyz;\n"
1553 		"    gl_Position  = transpose(pc.mvp) * in_position;\n"
1554 		"    gl_PointSize = 1.0;\n"
1555 		"}\n";
1556 	const tcu::StringTemplate	fragShaderReference(
1557 		"#version 450\n"
1558 		"\n"
1559 		"layout(location = 0) ${glslDeclspecRef} in vec3 in_color;\n"
1560 		"layout(location = 0) out vec4 out_color;\n"
1561 		"\n"
1562 		"void main()\n"
1563 		"{\n"
1564 		"    out_color = vec4(in_color, 1.0f);\n"
1565 		"}\n");
1566 	const tcu::StringTemplate	fragShaderTestGLSL(
1567 		"#version 450\n"
1568 		"#extension GL_EXT_fragment_shader_barycentric : require\n"
1569 		"\n"
1570 		"layout(location = 0) pervertexEXT in vec3 in_color[];\n"
1571 		"layout(location = 0) out vec4 out_color;\n"
1572 		"\n"
1573 		"void main()\n"
1574 		"{\n"
1575 		"    vec3 bc = ${glslFormulaeTest};\n"
1576 		"    out_color = vec4(in_color[0] * bc.x + in_color[1] * bc.y + in_color[2] * bc.z, 1.0f);\n"
1577 		"}\n");
1578 
1579 	// it is not possible to add centroid/sample qualifiers to gl_BaryCoordEXT/gl_BaryCoordNoPerspEXT
1580 	// but it is possible to do this with SPIR-V - code below is a slightly modified version of fragShaderTestGLSL
1581 	const tcu::StringTemplate fragShaderTestSPIRV(
1582 		"OpCapability Shader\n"
1583 		"OpCapability FragmentBarycentricKHR\n"
1584 		"${spirvAdditionalCapabilities}"
1585 		"OpExtension \"SPV_KHR_fragment_shader_barycentric\"\n"
1586 		"%1 = OpExtInstImport \"GLSL.std.450\"\n"
1587 		"OpMemoryModel Logical GLSL450\n"
1588 		"OpEntryPoint Fragment %4 \"main\" %var_BaryCoord %15 %20\n"
1589 		"OpExecutionMode %4 OriginUpperLeft\n"
1590 		"OpDecorate %var_BaryCoord BuiltIn ${spirvBaryCoordVariable}\n"
1591 		"OpDecorate %var_BaryCoord ${spirvBaryCoordDecoration}\n"
1592 		"OpDecorate %15 Location 0\n"
1593 		"OpDecorate %20 Location 0\n"
1594 		"OpDecorate %20 PerVertexKHR\n"
1595 		"%2				= OpTypeVoid\n"
1596 		"%3				= OpTypeFunction %2\n"
1597 		"%6				= OpTypeFloat 32\n"
1598 		"%7				= OpTypeVector %6 3\n"
1599 		"%8				= OpTypePointer Function %7\n"
1600 		"%10			= OpTypePointer Input %7\n"
1601 		"%var_BaryCoord = OpVariable %10 Input\n"
1602 		"%13			= OpTypeVector %6 4\n"
1603 		"%14			= OpTypePointer Output %13\n"
1604 		"%15			= OpVariable %14 Output\n"
1605 		"%16			= OpTypeInt 32 0\n"
1606 		"%17			= OpConstant %16 3\n"
1607 		"%18			= OpTypeArray %7 %17\n"
1608 		"%19			= OpTypePointer Input %18\n"
1609 		"%20			= OpVariable %19 Input\n"
1610 		"%21			= OpTypeInt 32 1\n"
1611 		"%22			= OpConstant %21 0\n"
1612 		"%25			= OpConstant %16 0\n"
1613 		"%26			= OpTypePointer Function %6\n"
1614 		"%30			= OpConstant %21 1\n"
1615 		"%33			= OpConstant %16 1\n"
1616 		"%38			= OpConstant %21 2\n"
1617 		"%41			= OpConstant %16 2\n"
1618 		"%46			= OpConstant %6 1\n"
1619 		"%4				= OpFunction %2 None %3\n"
1620 		"%5				= OpLabel\n"
1621 		"%9				= OpVariable %8 Function\n"
1622 		"%12			= OpLoad %7 %var_BaryCoord\n"
1623 		"OpStore %9 %12\n"
1624 		"%23			= OpAccessChain %10 %20 %22\n"
1625 		"%24			= OpLoad %7 %23\n"
1626 		"%27			= OpAccessChain %26 %9 %25\n"
1627 		"%28			= OpLoad %6 %27\n"
1628 		"%29			= OpVectorTimesScalar %7 %24 %28\n"
1629 		"%31			= OpAccessChain %10 %20 %30\n"
1630 		"%32			= OpLoad %7 %31\n"
1631 		"%34			= OpAccessChain %26 %9 %33\n"
1632 		"%35			= OpLoad %6 %34\n"
1633 		"%36			= OpVectorTimesScalar %7 %32 %35\n"
1634 		"%37			= OpFAdd %7 %29 %36\n"
1635 		"%39			= OpAccessChain %10 %20 %38\n"
1636 		"%40			= OpLoad %7 %39\n"
1637 		"%42			= OpAccessChain %26 %9 %41\n"
1638 		"%43			= OpLoad %6 %42\n"
1639 		"%44			= OpVectorTimesScalar %7 %40 %43\n"
1640 		"%45			= OpFAdd %7 %37 %44\n"
1641 		"%47			= OpCompositeExtract %6 %45 0\n"
1642 		"%48			= OpCompositeExtract %6 %45 1\n"
1643 		"%49			= OpCompositeExtract %6 %45 2\n"
1644 		"%50			= OpCompositeConstruct %13 %47 %48 %49 %46\n"
1645 		"OpStore %15 %50\n"
1646 		"OpReturn\n"
1647 		"OpFunctionEnd\n");
1648 
1649 	// use single specialization map for test and reference fragment shaders
1650 	// as well as for spirv version of test shader
1651 	map<string, string> attributes
1652 	{
1653 		{ "glslDeclspecRef",	declspecRef }
1654 	};
1655 
1656 	switch (m_testParams.testSubtype)
1657 	{
1658 	case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID:
1659 		attributes["glslFormulaeTest"] = std::string("interpolateAtCentroid(gl_") + baryCoordVariable + "EXT)";
1660 		attributes["glslDeclspecRef"] += " centroid";
1661 		break;
1662 	case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE:
1663 		attributes["glslFormulaeTest"] = std::string("interpolateAtSample(gl_") + baryCoordVariable + "EXT, gl_SampleID)";
1664 		attributes["glslDeclspecRef"] += " sample";
1665 		break;
1666 	case TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET:
1667 		attributes["glslFormulaeTest"] = std::string("interpolateAtOffset(gl_") + baryCoordVariable + "EXT, vec2(gl_SamplePosition - vec2(0.5)))";
1668 		attributes["glslDeclspecRef"] += " sample";
1669 		break;
1670 	case TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER:
1671 		attributes["spirvBaryCoordVariable"]		= baryCoordVariable + "KHR";
1672 		attributes["spirvBaryCoordDecoration"]		= "Centroid";
1673 		attributes["spirvAdditionalCapabilities"]	= "";
1674 		attributes["glslDeclspecRef"]				+= " centroid";
1675 		break;
1676 	case TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER:
1677 		attributes["spirvBaryCoordVariable"]		= baryCoordVariable + "KHR";
1678 		attributes["spirvBaryCoordDecoration"]		= "Sample";
1679 		attributes["spirvAdditionalCapabilities"]	= "OpCapability SampleRateShading\n";
1680 		attributes["glslDeclspecRef"]				+= " sample";
1681 		break;
1682 	default:
1683 		attributes["glslFormulaeTest"] = std::string("gl_") + baryCoordVariable + "EXT";
1684 		break;
1685 	}
1686 
1687 	programCollection.glslSources.add("vert") << glu::VertexSource(vertShader);
1688 	programCollection.glslSources.add("frag_reference") << glu::FragmentSource(fragShaderReference.specialize(attributes));
1689 
1690 	// use "spirvBaryCoordVariable" key to determine if we should use glsl or spir-v version of test shader
1691 	if (attributes.count("spirvBaryCoordVariable"))
1692 		programCollection.spirvAsmSources.add("frag_test") << fragShaderTestSPIRV.specialize(attributes);
1693 	else
1694 		programCollection.glslSources.add("frag_test") << glu::FragmentSource(fragShaderTestGLSL.specialize(attributes));
1695 }
1696 }	// anonymous
1697 
createTests(tcu::TestContext & testCtx,const std::string & name)1698 tcu::TestCaseGroup* createTests (tcu::TestContext& testCtx, const std::string& name)
1699 {
1700 	const bool					notused			= false;
1701 	MovePtr<tcu::TestCaseGroup>	group			(new tcu::TestCaseGroup(testCtx, name.c_str(), "Tests fragment shading barycentric extension"));
1702 	// Tests using graphics pipeline libraries
1703 	MovePtr<tcu::TestCaseGroup>	libGroup		(new tcu::TestCaseGroup(testCtx, "pipeline_library"));
1704 	MovePtr<tcu::TestCaseGroup>	fastLinkGroup	(new tcu::TestCaseGroup(testCtx, "fast_linked_library", "Tests using graphics pipeline libraries with fast linking"));
1705 
1706 	const struct
1707 	{
1708 		PipelineConstructionType		constructionType;
1709 		tcu::TestCaseGroup*				testGroup;
1710 	} constructionTypeCases[] =
1711 	{
1712 		{ PIPELINE_CONSTRUCTION_TYPE_MONOLITHIC,					group.get()			},
1713 		{ PIPELINE_CONSTRUCTION_TYPE_LINK_TIME_OPTIMIZED_LIBRARY,	libGroup.get()		},
1714 		{ PIPELINE_CONSTRUCTION_TYPE_FAST_LINKED_LIBRARY,			fastLinkGroup.get()	},
1715 	};
1716 
1717 	const struct PrimitiveTestSpec
1718 	{
1719 		VkPrimitiveTopology	topology;
1720 		const char*			name;
1721 	}
1722 	topologies[] =
1723 	{
1724 		{ VK_PRIMITIVE_TOPOLOGY_POINT_LIST							, "point_list"						},
1725 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST							, "line_list"						},
1726 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP							, "line_strip"						},
1727 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST						, "triangle_list"					},
1728 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP						, "triangle_strip"					},
1729 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_FAN						, "triangle_fan"					},
1730 		{ VK_PRIMITIVE_TOPOLOGY_LINE_LIST_WITH_ADJACENCY			, "line_list_with_adjacency"		},
1731 		{ VK_PRIMITIVE_TOPOLOGY_LINE_STRIP_WITH_ADJACENCY			, "line_strip_with_adjacency"		},
1732 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST_WITH_ADJACENCY		, "triangle_list_with_adjacency"	},
1733 		{ VK_PRIMITIVE_TOPOLOGY_TRIANGLE_STRIP_WITH_ADJACENCY		, "triangle_strip_with_adjacency"	},
1734 	};
1735 	const glu::DataType	dataTypes[] =
1736 	{
1737 		glu::TYPE_FLOAT,
1738 		glu::TYPE_FLOAT_VEC2,
1739 		glu::TYPE_FLOAT_VEC3,
1740 		glu::TYPE_FLOAT_VEC4,
1741 		glu::TYPE_DOUBLE,
1742 		glu::TYPE_DOUBLE_VEC2,
1743 		glu::TYPE_DOUBLE_VEC3,
1744 		glu::TYPE_DOUBLE_VEC4,
1745 		glu::TYPE_INT,
1746 		glu::TYPE_INT_VEC2,
1747 		glu::TYPE_INT_VEC3,
1748 		glu::TYPE_INT_VEC4,
1749 		glu::TYPE_UINT,
1750 		glu::TYPE_UINT_VEC2,
1751 		glu::TYPE_UINT_VEC3,
1752 		glu::TYPE_UINT_VEC4,
1753 	};
1754 	const struct Perspective
1755 	{
1756 		const char*		name;
1757 		bool			value;
1758 	}
1759 	perspectives[] =
1760 	{
1761 		{ "perspective",	true	},
1762 		{ "noperspective",	false	},
1763 	};
1764 	const struct DynamicIndexing
1765 	{
1766 		const char* name;
1767 		bool		value;
1768 	}
1769 	dynamicIndexings[] =
1770 	{
1771 		{ "static",		false	},
1772 		{ "dynamic",	true	},
1773 	};
1774 	const struct ProvokingVertex
1775 	{
1776 		const char* name;
1777 		bool		value;
1778 	}
1779 	provokingVertices[] =
1780 	{
1781 		{ "provoking_first",	false	},
1782 		{ "provoking_last",		true	},
1783 	};
1784 	const uint32_t rotations[]	= { 0, 85, 95 };
1785 	const struct TopologyInPipeline
1786 	{
1787 		const char*	name;
1788 		bool		value;
1789 	}
1790 	topologiesInPipeline[] =
1791 	{
1792 		{ "pipeline_topology_static",	false	},
1793 		{ "pipeline_topology_dynamic",	true	},
1794 	};
1795 
1796 	for (const auto& constructionTypeCase : constructionTypeCases)
1797 	{
1798 		MovePtr<tcu::TestCaseGroup>	testTypeGroup	(new tcu::TestCaseGroup(testCtx, "data"));
1799 		const TestType				testType		= TEST_TYPE_DATA;
1800 
1801 		for (size_t provokingVertexNdx = 0; provokingVertexNdx < DE_LENGTH_OF_ARRAY(provokingVertices); ++provokingVertexNdx)
1802 		{
1803 			MovePtr<tcu::TestCaseGroup>	provokingVertexGroup	(new tcu::TestCaseGroup(testCtx, provokingVertices[provokingVertexNdx].name));
1804 			const bool					provokingVertexLast		= provokingVertices[provokingVertexNdx].value;
1805 
1806 			for (size_t dynamicNdx = 0; dynamicNdx < DE_LENGTH_OF_ARRAY(dynamicIndexings); ++dynamicNdx)
1807 			{
1808 				MovePtr<tcu::TestCaseGroup>	dynamicIndexingGroup	(new tcu::TestCaseGroup(testCtx, dynamicIndexings[dynamicNdx].name));
1809 				const bool					dynamicIndexing			= dynamicIndexings[dynamicNdx].value;
1810 
1811 				for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1812 				{
1813 					MovePtr<tcu::TestCaseGroup>	topologyGroup	(new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1814 					const VkPrimitiveTopology	topology		= topologies[topologyNdx].topology;
1815 
1816 					for (size_t aggregateNdx = 0; aggregateNdx < 3; ++aggregateNdx)
1817 					{
1818 						const string				aggregateName	= aggregateNdx == 0 ? "type"
1819 																	: aggregateNdx == 1 ? "struct"
1820 																	: "array" + de::toString(aggregateNdx);
1821 						MovePtr<tcu::TestCaseGroup>	aggregateGroup	(new tcu::TestCaseGroup(testCtx, aggregateName.c_str()));
1822 
1823 						for (size_t dataTypeNdx = 0; dataTypeNdx < DE_LENGTH_OF_ARRAY(dataTypes); ++dataTypeNdx)
1824 						{
1825 							const glu::DataType	dataType		= dataTypes[dataTypeNdx];
1826 							const char*			dataTypeName	= getDataTypeName(dataType);
1827 
1828 							const TestParams	testParams
1829 							{
1830 								constructionTypeCase.constructionType,
1831 								testType,				//  TestType				testType;
1832 								TEST_SUBTYPE_DEFAULT,	//  TestSubtype				testSubtype;
1833 								topology,				//  VkPrimitiveTopology		topology;
1834 								dynamicIndexing,		//  bool					dynamicIndexing;
1835 								aggregateNdx,			//  size_t					aggregate;
1836 								dataType,				//  glu::DataType			dataType;
1837 								DATA_TEST_WIDTH,		//  uint32_t				width;
1838 								DATA_TEST_HEIGHT,		//  uint32_t				height;
1839 								notused,				//  bool					perspective;
1840 								provokingVertexLast,	//  bool					provokingVertexLast;
1841 								(uint32_t)notused,		//  uint32_t				rotation;
1842 								notused,				//  bool					dynamicTopologyInPipeline
1843 								VK_SAMPLE_COUNT_1_BIT,	//  VkSampleCountFlagBits	sampleCount;
1844 							};
1845 
1846 							aggregateGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, dataTypeName, testParams));
1847 						}
1848 
1849 						topologyGroup->addChild(aggregateGroup.release());
1850 					}
1851 
1852 					dynamicIndexingGroup->addChild(topologyGroup.release());
1853 				}
1854 
1855 				provokingVertexGroup->addChild(dynamicIndexingGroup.release());
1856 			}
1857 
1858 			testTypeGroup->addChild(provokingVertexGroup.release());
1859 		}
1860 
1861 		{
1862 			MovePtr<tcu::TestCaseGroup> miscGroup(new tcu::TestCaseGroup(testCtx, "misc"));
1863 			const TestParams testParams
1864 			{
1865 				constructionTypeCase.constructionType,
1866 				TEST_TYPE_DATA,							//  TestType				testType;
1867 				TEST_SUBTYPE_PERVERTEX_CORRECTNESS,		//  TestSubtype				testSubtype;
1868 				VK_PRIMITIVE_TOPOLOGY_TRIANGLE_LIST,	//  VkPrimitiveTopology		topology;
1869 				notused,								//  bool					dynamicIndexing;
1870 				notused,								//  size_t					aggregate;
1871 				glu::TYPE_FLOAT_VEC2,					//  glu::DataType			dataType;
1872 				DATA_TEST_WIDTH,						//  uint32_t				width;
1873 				DATA_TEST_HEIGHT,						//  uint32_t				height;
1874 				notused,								//  bool					perspective;
1875 				notused,								//  bool					provokingVertexLast;
1876 				(uint32_t)notused,						//  uint32_t				rotation;
1877 				notused,								//  bool					dynamicTopologyInPipeline
1878 				VK_SAMPLE_COUNT_1_BIT,					//  VkSampleCountFlagBits	sampleCount;
1879 			};
1880 			miscGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, "pervertex_correctness", testParams));
1881 			testTypeGroup->addChild(miscGroup.release());
1882 		}
1883 
1884 		constructionTypeCase.testGroup->addChild(testTypeGroup.release());
1885 	}
1886 
1887 	for (const auto& constructionTypeCase : constructionTypeCases)
1888 	{
1889 		const struct MsaaTestCase
1890 		{
1891 			const char*				name;
1892 			VkSampleCountFlagBits	samples;
1893 			TestSubtype				subtype;
1894 		}
1895 		msaaCases[] =
1896 		{
1897 			{ "single_sample",					VK_SAMPLE_COUNT_1_BIT,	TEST_SUBTYPE_DEFAULT },
1898 			{ "msaa_interpolate_at_centroid",	VK_SAMPLE_COUNT_4_BIT,	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_CENTROID },
1899 			{ "msaa_interpolate_at_sample",		VK_SAMPLE_COUNT_4_BIT,	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_SAMPLE },
1900 			{ "msaa_interpolate_at_offset",		VK_SAMPLE_COUNT_4_BIT,	TEST_SUBTYPE_MSAA_INTERPOLATE_AT_OFFSET },
1901 			{ "msaa_centroid_qualifier",		VK_SAMPLE_COUNT_4_BIT,	TEST_SUBTYPE_MSAA_CENTROID_QUALIFIER },
1902 			{ "msaa_sample_qualifier",			VK_SAMPLE_COUNT_4_BIT,	TEST_SUBTYPE_MSAA_SAMPLE_QUALIFIER },
1903 		};
1904 
1905 		MovePtr<tcu::TestCaseGroup>	testTypeGroup	(new tcu::TestCaseGroup(testCtx, "weights"));
1906 		const TestType				testType		= TEST_TYPE_WEIGHTS;
1907 
1908 		for (size_t topologyInPipelineNdx = 0; topologyInPipelineNdx < DE_LENGTH_OF_ARRAY(topologiesInPipeline); ++topologyInPipelineNdx)
1909 		{
1910 			MovePtr<tcu::TestCaseGroup>	topologyInPipelineGroup	(new tcu::TestCaseGroup(testCtx, topologiesInPipeline[topologyInPipelineNdx].name));
1911 			const bool					topologyInPipeline		= topologiesInPipeline[topologyInPipelineNdx].value;
1912 
1913 			if (topologyInPipeline)
1914 			{
1915 				for (size_t msaaCaseNdx = 0; msaaCaseNdx < DE_LENGTH_OF_ARRAY(msaaCases); ++msaaCaseNdx)
1916 				{
1917 					MovePtr<tcu::TestCaseGroup> msaaGroup(new tcu::TestCaseGroup(testCtx, msaaCases[msaaCaseNdx].name));
1918 					for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1919 					{
1920 						MovePtr<tcu::TestCaseGroup>	topologyGroup(new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1921 						const VkPrimitiveTopology	topology = topologies[topologyNdx].topology;
1922 						const bool					testableTopology = isPrimitiveTopologyLine(topology) || isPrimitiveTopologyTriangle(topology);
1923 
1924 						if (!testableTopology)
1925 							continue;
1926 
1927 						for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives); ++perspectiveNdx)
1928 						{
1929 							const bool	perspective = perspectives[perspectiveNdx].value;
1930 							const char* perspectiveName = perspectives[perspectiveNdx].name;
1931 
1932 							const TestParams testParams
1933 							{
1934 								constructionTypeCase.constructionType,
1935 								testType,							//  TestType				testType;
1936 								msaaCases[msaaCaseNdx].subtype,		//  TestSubtype				testSubtype;
1937 								topology,							//  VkPrimitiveTopology		topology;
1938 								notused,							//  bool					dynamicIndexing;
1939 								(size_t)notused,					//  size_t					aggregate;
1940 								(glu::DataType)notused,				//  glu::DataType			dataType;
1941 								WEIGHT_TEST_WIDTH,					//  uint32_t				width;
1942 								WEIGHT_TEST_HEIGHT,					//  uint32_t				height;
1943 								perspective,						//  bool					perspective;
1944 								false,								//  bool					provokingVertexLast;
1945 								0,									//  uint32_t				rotation;
1946 								topologyInPipeline,					//  bool					dynamicTopologyInPipeline
1947 								msaaCases[msaaCaseNdx].samples,		//  VkSampleCountFlagBits	sampleCount;
1948 							};
1949 
1950 							topologyGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, perspectiveName, testParams));
1951 						}
1952 						msaaGroup->addChild(topologyGroup.release());
1953 					}
1954 					topologyInPipelineGroup->addChild(msaaGroup.release());
1955 				}
1956 			}
1957 			else
1958 			{
1959 				for (size_t rotationNdx = 0; rotationNdx < DE_LENGTH_OF_ARRAY(rotations); ++rotationNdx)
1960 				{
1961 					const uint32_t				rotation		= rotations[rotationNdx];
1962 					MovePtr<tcu::TestCaseGroup>	rotationGroup	(new tcu::TestCaseGroup(testCtx, de::toString(rotation).c_str()));
1963 
1964 					for (size_t topologyNdx = 0; topologyNdx < DE_LENGTH_OF_ARRAY(topologies); ++topologyNdx)
1965 					{
1966 						const VkPrimitiveTopology	topology		= topologies[topologyNdx].topology;
1967 						MovePtr<tcu::TestCaseGroup>	topologyGroup	(new tcu::TestCaseGroup(testCtx, topologies[topologyNdx].name));
1968 
1969 						for (size_t perspectiveNdx = 0; perspectiveNdx < DE_LENGTH_OF_ARRAY(perspectives); ++perspectiveNdx)
1970 						{
1971 							const bool	perspective		= perspectives[perspectiveNdx].value;
1972 							const char*	perspectiveName	= perspectives[perspectiveNdx].name;
1973 
1974 							const TestParams testParams
1975 							{
1976 								constructionTypeCase.constructionType,
1977 								testType,				//  TestType				testType;
1978 								TEST_SUBTYPE_DEFAULT,	//  TestSubtype				testSubtype;
1979 								topology,				//  VkPrimitiveTopology		topology;
1980 								notused,				//  bool					dynamicIndexing;
1981 								(size_t)-1,				//  size_t					aggregate;
1982 								glu::TYPE_INVALID,		//  glu::DataType			dataType;
1983 								WEIGHT_TEST_WIDTH,		//  uint32_t				width;
1984 								WEIGHT_TEST_HEIGHT,		//  uint32_t				height;
1985 								perspective,			//  bool					perspective;
1986 								false,					//  bool					provokingVertexLast;
1987 								rotation,				//  uint32_t				rotation;
1988 								topologyInPipeline,		//  bool					dynamicTopologyInPipeline
1989 								VK_SAMPLE_COUNT_1_BIT,	//  VkSampleCountFlagBits	sampleCount;
1990 							};
1991 
1992 							topologyGroup->addChild(new FragmentShadingBarycentricTestCase(testCtx, perspectiveName, testParams));
1993 						}
1994 
1995 						rotationGroup->addChild(topologyGroup.release());
1996 					}
1997 
1998 					topologyInPipelineGroup->addChild(rotationGroup.release());
1999 				}
2000 			}
2001 
2002 			testTypeGroup->addChild(topologyInPipelineGroup.release());
2003 		}
2004 
2005 		constructionTypeCase.testGroup->addChild(testTypeGroup.release());
2006 	}
2007 
2008 	group->addChild(libGroup.release());
2009 	group->addChild(fastLinkGroup.release());
2010 
2011 	return group.release();
2012 }
2013 
2014 }	// FragmentShadingBarycentric
2015 }	// vkt
2016