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