• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /*------------------------------------------------------------------------
2  * Vulkan Conformance Tests
3  * ------------------------
4  *
5  * Copyright (c) 2015 The Khronos Group Inc.
6  * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7  * Copyright (c) 2016 The Android Open Source Project
8  * Copyright (c) 2018 The Khronos Group Inc.
9  *
10  * Licensed under the Apache License, Version 2.0 (the "License");
11  * you may not use this file except in compliance with the License.
12  * You may obtain a copy of the License at
13  *
14  *      http://www.apache.org/licenses/LICENSE-2.0
15  *
16  * Unless required by applicable law or agreed to in writing, software
17  * distributed under the License is distributed on an "AS IS" BASIS,
18  * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
19  * See the License for the specific language governing permissions and
20  * limitations under the License.
21  *
22  *//*!
23  * \file
24  * \brief Vulkan Transform Feedback Fuzz Layout Tests
25  *//*--------------------------------------------------------------------*/
26 
27 #include "vktTransformFeedbackFuzzLayoutCase.hpp"
28 #include "vktTransformFeedbackRandomLayoutCase.hpp"
29 
30 #include "tcuCommandLine.hpp"
31 #include "deStringUtil.hpp"
32 
33 namespace vkt
34 {
35 namespace TransformFeedback
36 {
37 
38 namespace
39 {
40 
41 class BlockBasicTypeCase : public InterfaceBlockCase
42 {
43 public:
BlockBasicTypeCase(tcu::TestContext & testCtx,const std::string & name,const VarType & type,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)44 	BlockBasicTypeCase (tcu::TestContext&	testCtx,
45 						const std::string&	name,
46 						const VarType&		type,
47 						deUint32			layoutFlags,
48 						int					numInstances,
49 						MatrixLoadFlags		matrixLoadFlag,
50 						TestStageFlags		testStageFlags)
51 		: InterfaceBlockCase(testCtx, name, matrixLoadFlag, testStageFlags)
52 	{
53 		InterfaceBlock& block = m_interface.allocBlock("Block");
54 		block.addInterfaceMember(InterfaceBlockMember("var", type, 0));
55 
56 		VarType tempType = type;
57 		while (tempType.isArrayType())
58 		{
59 			tempType = tempType.getElementType();
60 		}
61 
62 		block.setFlags(layoutFlags);
63 
64 		if (numInstances > 0)
65 		{
66 			block.setArraySize(numInstances);
67 			block.setInstanceName("block");
68 		}
69 	}
70 };
71 
createBlockBasicTypeCases(tcu::TestCaseGroup & group,tcu::TestContext & testCtx,const std::string & name,const VarType & type,deUint32 layoutFlags,int numInstances=0)72 void createBlockBasicTypeCases (tcu::TestCaseGroup& group, tcu::TestContext& testCtx, const std::string& name, const VarType& type, deUint32 layoutFlags, int numInstances = 0)
73 {
74 	de::MovePtr<tcu::TestCaseGroup>	typeGroup(new tcu::TestCaseGroup(group.getTestContext(), name.c_str()));
75 
76 	typeGroup->addChild(new BlockBasicTypeCase(testCtx, "vertex", type, layoutFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
77 	typeGroup->addChild(new BlockBasicTypeCase(testCtx, "geometry", type, layoutFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
78 
79 	group.addChild(typeGroup.release());
80 }
81 
82 class BlockSingleStructCase : public InterfaceBlockCase
83 {
84 public:
BlockSingleStructCase(tcu::TestContext & testCtx,const std::string & name,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)85 	BlockSingleStructCase (tcu::TestContext&	testCtx,
86 						   const std::string&	name,
87 						   deUint32				layoutFlags,
88 						   int					numInstances,
89 						   MatrixLoadFlags		matrixLoadFlag,
90 						   TestStageFlags		testStageFlags)
91 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
92 	{
93 		StructType& typeS = m_interface.allocStruct("S");
94 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), FIELD_UNASSIGNED); // First member is unused.
95 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_VEC3, PRECISION_HIGH), 2));
96 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
97 
98 		InterfaceBlock& block = m_interface.allocBlock("Block");
99 		block.addInterfaceMember(InterfaceBlockMember("s", VarType(&typeS), 0));
100 		block.setFlags(layoutFlags);
101 
102 		if (numInstances > 0)
103 		{
104 			block.setInstanceName("block");
105 			block.setArraySize(numInstances);
106 		}
107 	}
108 };
109 
110 class BlockSingleStructArrayCase : public InterfaceBlockCase
111 {
112 public:
BlockSingleStructArrayCase(tcu::TestContext & testCtx,const std::string & name,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)113 	BlockSingleStructArrayCase (tcu::TestContext&	testCtx,
114 								const std::string&	name,
115 								deUint32			layoutFlags,
116 								int					numInstances,
117 								MatrixLoadFlags		matrixLoadFlag,
118 								TestStageFlags		testStageFlags)
119 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
120 	{
121 		StructType& typeS = m_interface.allocStruct("S");
122 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), FIELD_UNASSIGNED);
123 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 2));
124 		typeS.addMember("c", VarType(glu::TYPE_FLOAT, PRECISION_HIGH));
125 
126 		InterfaceBlock& block = m_interface.allocBlock("Block");
127 		block.addInterfaceMember(InterfaceBlockMember("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
128 		block.addInterfaceMember(InterfaceBlockMember("s", VarType(VarType(&typeS), 2)));
129 		block.addInterfaceMember(InterfaceBlockMember("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
130 		block.setFlags(layoutFlags);
131 
132 		if (numInstances > 0)
133 		{
134 			block.setInstanceName("block");
135 			block.setArraySize(numInstances);
136 		}
137 	}
138 };
139 
140 class BlockSingleNestedStructCase : public InterfaceBlockCase
141 {
142 public:
BlockSingleNestedStructCase(tcu::TestContext & testCtx,const std::string & name,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)143 	BlockSingleNestedStructCase (tcu::TestContext&	testCtx,
144 								 const std::string&	name,
145 								 deUint32			layoutFlags,
146 								 int				numInstances,
147 								 MatrixLoadFlags	matrixLoadFlag,
148 								 TestStageFlags		testStageFlags)
149 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
150 	{
151 		StructType& typeS = m_interface.allocStruct("S");
152 		typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
153 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 2));
154 		typeS.addMember("c", VarType(glu::TYPE_FLOAT, PRECISION_HIGH), FIELD_UNASSIGNED);
155 
156 		StructType& typeT = m_interface.allocStruct("T");
157 		typeT.addMember("a", VarType(glu::TYPE_FLOAT_VEC3, PRECISION_MEDIUM));
158 		typeT.addMember("b", VarType(&typeS));
159 
160 		InterfaceBlock& block = m_interface.allocBlock("Block");
161 		block.addInterfaceMember(InterfaceBlockMember("s", VarType(&typeS), 0));
162 		block.addInterfaceMember(InterfaceBlockMember("v", VarType(glu::TYPE_UINT, PRECISION_LOW), FIELD_UNASSIGNED));
163 		block.addInterfaceMember(InterfaceBlockMember("t", VarType(&typeT), 0));
164 		block.addInterfaceMember(InterfaceBlockMember("u", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_HIGH), 0));
165 		block.setFlags(layoutFlags);
166 
167 		if (numInstances > 0)
168 		{
169 			block.setInstanceName("block");
170 			block.setArraySize(numInstances);
171 		}
172 	}
173 };
174 
175 class BlockSingleNestedStructArrayCase : public InterfaceBlockCase
176 {
177 public:
BlockSingleNestedStructArrayCase(tcu::TestContext & testCtx,const std::string & name,deUint32 layoutFlags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)178 	BlockSingleNestedStructArrayCase (tcu::TestContext&		testCtx,
179 									  const std::string&	name,
180 									  deUint32				layoutFlags,
181 									  int					numInstances,
182 									  MatrixLoadFlags		matrixLoadFlag,
183 									  TestStageFlags		testStageFlags)
184 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
185 	{
186 		StructType& typeS = m_interface.allocStruct("S");
187 		typeS.addMember("a", VarType(VarType(glu::TYPE_FLOAT, PRECISION_HIGH), 2));
188 
189 		StructType& typeT = m_interface.allocStruct("T");
190 		typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM));
191 		typeT.addMember("b", VarType(VarType(&typeS), 2));
192 
193 		InterfaceBlock& block = m_interface.allocBlock("Block");
194 		block.addInterfaceMember(InterfaceBlockMember("s", VarType(&typeS), 0));
195 		block.addInterfaceMember(InterfaceBlockMember("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), FIELD_UNASSIGNED));
196 		block.addInterfaceMember(InterfaceBlockMember("t", VarType(VarType(&typeT), 2), 0));
197 		block.addInterfaceMember(InterfaceBlockMember("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
198 		block.setFlags(layoutFlags);
199 
200 		if (numInstances > 0)
201 		{
202 			block.setInstanceName("block");
203 			block.setArraySize(numInstances);
204 		}
205 	}
206 };
207 
208 class BlockMultiBasicTypesCase : public InterfaceBlockCase
209 {
210 public:
BlockMultiBasicTypesCase(tcu::TestContext & testCtx,const std::string & name,deUint32 flagsA,deUint32 flagsB,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)211 	BlockMultiBasicTypesCase (tcu::TestContext&		testCtx,
212 							  const std::string&	name,
213 							  deUint32				flagsA,
214 							  deUint32				flagsB,
215 							  int					numInstances,
216 							  MatrixLoadFlags		matrixLoadFlag,
217 							  TestStageFlags		testStageFlags)
218 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
219 	{
220 		InterfaceBlock& blockA = m_interface.allocBlock("BlockA");
221 		blockA.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
222 		blockA.addInterfaceMember(InterfaceBlockMember("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), FIELD_UNASSIGNED));
223 		blockA.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
224 		blockA.setInstanceName("blockA");
225 		blockA.setFlags(flagsA);
226 
227 		InterfaceBlock& blockB = m_interface.allocBlock("BlockB");
228 		blockB.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
229 		blockB.addInterfaceMember(InterfaceBlockMember("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
230 		blockB.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), FIELD_UNASSIGNED));
231 		blockB.addInterfaceMember(InterfaceBlockMember("d", VarType(glu::TYPE_INT, 0)));
232 		blockB.setInstanceName("blockB");
233 		blockB.setFlags(flagsB);
234 
235 		if (numInstances > 0)
236 		{
237 			blockA.setArraySize(numInstances);
238 			blockB.setArraySize(numInstances);
239 		}
240 	}
241 };
242 
243 class BlockMultiNestedStructCase : public InterfaceBlockCase
244 {
245 public:
BlockMultiNestedStructCase(tcu::TestContext & testCtx,const std::string & name,deUint32 flagsA,deUint32 flagsB,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)246 	BlockMultiNestedStructCase (tcu::TestContext&	testCtx,
247 								const std::string&	name,
248 								deUint32			flagsA,
249 								deUint32			flagsB,
250 								int					numInstances,
251 								MatrixLoadFlags		matrixLoadFlag,
252 								TestStageFlags		testStageFlags)
253 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
254 	{
255 		StructType& typeS = m_interface.allocStruct("S");
256 		typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_LOW));
257 		typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 2));
258 
259 		StructType& typeT = m_interface.allocStruct("T");
260 		typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), FIELD_UNASSIGNED);
261 		typeT.addMember("b", VarType(&typeS));
262 		typeT.addMember("c", VarType(glu::TYPE_UINT_VEC3, 0));
263 
264 		InterfaceBlock& blockA = m_interface.allocBlock("BlockA");
265 		blockA.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
266 		blockA.addInterfaceMember(InterfaceBlockMember("b", VarType(&typeS)));
267 		blockA.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW), FIELD_UNASSIGNED));
268 		blockA.setInstanceName("blockA");
269 		blockA.setFlags(flagsA);
270 
271 		InterfaceBlock& blockB = m_interface.allocBlock("BlockB");
272 		blockB.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
273 		blockB.addInterfaceMember(InterfaceBlockMember("b", VarType(&typeT)));
274 		blockB.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_INT, 0)));
275 		blockB.setInstanceName("blockB");
276 		blockB.setFlags(flagsB);
277 
278 		if (numInstances > 0)
279 		{
280 			blockA.setArraySize(numInstances);
281 			blockB.setArraySize(numInstances);
282 		}
283 	}
284 };
285 
286 class BlockVariousBuffersCase : public InterfaceBlockCase
287 {
288 public:
BlockVariousBuffersCase(tcu::TestContext & testCtx,const std::string & name,deUint32 flags,deUint32 xfbBufferA,deUint32 xfbBufferB,deUint32 xfbBufferC,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)289 	BlockVariousBuffersCase (tcu::TestContext&		testCtx,
290 							 const std::string&		name,
291 							 deUint32				flags,
292 							 deUint32				xfbBufferA,
293 							 deUint32				xfbBufferB,
294 							 deUint32				xfbBufferC,
295 							 int					numInstances,
296 							 MatrixLoadFlags		matrixLoadFlag,
297 							 TestStageFlags			testStageFlags)
298 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
299 	{
300 		StructType& typeS = m_interface.allocStruct("S");
301 		typeS.addMember("a", VarType(VarType(glu::TYPE_FLOAT, PRECISION_LOW), 3));
302 		typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM), 2));
303 		typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
304 
305 		StructType& typeT = m_interface.allocStruct("T");
306 		typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), FIELD_UNASSIGNED);
307 		typeT.addMember("b", VarType(glu::TYPE_INT_VEC3, 0));
308 
309 		InterfaceBlock& blockA = m_interface.allocBlock("BlockA");
310 		blockA.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_INT, PRECISION_HIGH)));
311 		blockA.addInterfaceMember(InterfaceBlockMember("b", VarType(&typeS)));
312 		blockA.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), FIELD_UNASSIGNED));
313 		blockA.setInstanceName("blockA");
314 		blockA.setFlags(flags);
315 		blockA.setXfbBuffer(xfbBufferA);
316 
317 		InterfaceBlock& blockB = m_interface.allocBlock("BlockB");
318 		blockB.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
319 		blockB.addInterfaceMember(InterfaceBlockMember("b", VarType(&typeT)));
320 		blockB.addInterfaceMember(InterfaceBlockMember("c", VarType(glu::TYPE_INT_VEC4, 0), FIELD_UNASSIGNED));
321 		blockB.addInterfaceMember(InterfaceBlockMember("d", VarType(glu::TYPE_INT, 0)));
322 		blockB.setInstanceName("blockB");
323 		blockB.setFlags(flags);
324 		blockB.setXfbBuffer(xfbBufferB);
325 
326 		InterfaceBlock& blockC = m_interface.allocBlock("BlockC");
327 		blockC.addInterfaceMember(InterfaceBlockMember("a", VarType(glu::TYPE_UINT, PRECISION_HIGH)));
328 		blockC.addInterfaceMember(InterfaceBlockMember("b", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_HIGH)));
329 		blockC.setInstanceName("blockC");
330 		blockC.setFlags(flags);
331 		blockC.setXfbBuffer(xfbBufferC);
332 
333 		if (numInstances > 0)
334 		{
335 			blockA.setArraySize(numInstances);
336 			blockB.setArraySize(numInstances);
337 		}
338 	}
339 };
340 
341 class Block2LevelStructArrayCase : public InterfaceBlockCase
342 {
343 public:
Block2LevelStructArrayCase(tcu::TestContext & testCtx,const std::string & name,deUint32 flags,int numInstances,MatrixLoadFlags matrixLoadFlag,TestStageFlags testStageFlags)344 	Block2LevelStructArrayCase (tcu::TestContext&		testCtx,
345 								const std::string&		name,
346 								deUint32				flags,
347 								int						numInstances,
348 								MatrixLoadFlags			matrixLoadFlag,
349 								TestStageFlags			testStageFlags)
350 		: InterfaceBlockCase	(testCtx, name, matrixLoadFlag, testStageFlags)
351 	{
352 		StructType& typeS = m_interface.allocStruct("S");
353 		typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), FIELD_UNASSIGNED);
354 		typeS.addMember("b", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM));
355 
356 		InterfaceBlock& block = m_interface.allocBlock("Block");
357 		block.addInterfaceMember(InterfaceBlockMember("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
358 		block.addInterfaceMember(InterfaceBlockMember("s", VarType(VarType(VarType(&typeS), 2), 2)));
359 		block.addInterfaceMember(InterfaceBlockMember("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
360 		block.setFlags(flags);
361 
362 		if (numInstances > 0)
363 		{
364 			block.setInstanceName("block");
365 			block.setArraySize(numInstances);
366 		}
367 	}
368 };
369 
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,tcu::TestContext & testCtx,const char * groupName,deUint32 numCases,TestStageFlags testStageFlags,deUint32 features)370 void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, tcu::TestContext& testCtx, const char* groupName, deUint32 numCases, TestStageFlags testStageFlags, deUint32 features)
371 {
372 	const deUint32			baseSeed	= deStringHash(groupName) + static_cast<deUint32>(testCtx.getCommandLine().getBaseSeed());
373 	tcu::TestCaseGroup*		group		= new tcu::TestCaseGroup(testCtx, groupName);
374 
375 	parentGroup->addChild(group);
376 
377 	for (deUint32 ndx = 0; ndx < numCases; ndx++)
378 		group->addChild(new RandomInterfaceBlockCase(testCtx, de::toString(ndx), testStageFlags, features, ndx + baseSeed));
379 }
380 
381 // InterfaceBlockTests
382 
383 class InterfaceBlockTests : public tcu::TestCaseGroup
384 {
385 public:
386 							InterfaceBlockTests		(tcu::TestContext& testCtx);
387 							~InterfaceBlockTests	(void);
388 
389 	void					init					(void);
390 
391 private:
392 							InterfaceBlockTests		(const InterfaceBlockTests& other);
393 	InterfaceBlockTests&	operator=				(const InterfaceBlockTests& other);
394 };
395 
InterfaceBlockTests(tcu::TestContext & testCtx)396 InterfaceBlockTests::InterfaceBlockTests (tcu::TestContext& testCtx)
397 	: TestCaseGroup(testCtx, "fuzz")
398 {
399 }
400 
~InterfaceBlockTests(void)401 InterfaceBlockTests::~InterfaceBlockTests (void)
402 {
403 }
404 
init(void)405 void InterfaceBlockTests::init (void)
406 {
407 	static const glu::DataType basicTypes[] =
408 	{
409 		glu::TYPE_FLOAT,
410 		glu::TYPE_FLOAT_VEC2,
411 		glu::TYPE_FLOAT_VEC3,
412 		glu::TYPE_FLOAT_VEC4,
413 		glu::TYPE_INT,
414 		glu::TYPE_INT_VEC2,
415 		glu::TYPE_INT_VEC3,
416 		glu::TYPE_INT_VEC4,
417 		glu::TYPE_UINT,
418 		glu::TYPE_UINT_VEC2,
419 		glu::TYPE_UINT_VEC3,
420 		glu::TYPE_UINT_VEC4,
421 		glu::TYPE_FLOAT_MAT2,
422 		glu::TYPE_FLOAT_MAT3,
423 		glu::TYPE_FLOAT_MAT4,
424 		glu::TYPE_FLOAT_MAT2X3,
425 		glu::TYPE_FLOAT_MAT2X4,
426 		glu::TYPE_FLOAT_MAT3X2,
427 		glu::TYPE_FLOAT_MAT3X4,
428 		glu::TYPE_FLOAT_MAT4X2,
429 		glu::TYPE_FLOAT_MAT4X3,
430 		glu::TYPE_DOUBLE,
431 		glu::TYPE_DOUBLE_VEC2,
432 		glu::TYPE_DOUBLE_VEC3,
433 		glu::TYPE_DOUBLE_VEC4,
434 		glu::TYPE_DOUBLE_MAT2,
435 		glu::TYPE_DOUBLE_MAT2X3,
436 		glu::TYPE_DOUBLE_MAT2X4,
437 		glu::TYPE_DOUBLE_MAT3X2,
438 		glu::TYPE_DOUBLE_MAT3,
439 		glu::TYPE_DOUBLE_MAT3X4,
440 		glu::TYPE_DOUBLE_MAT4X2,
441 		glu::TYPE_DOUBLE_MAT4X3,
442 		glu::TYPE_DOUBLE_MAT4,
443 	};
444 
445 	static const struct
446 	{
447 		const std::string	name;
448 		deUint32			flags;
449 	} precisionFlags[] =
450 	{
451 		// TODO remove PRECISION_LOW because both PRECISION_LOW and PRECISION_MEDIUM means relaxed precision?
452 		{ "lowp",		PRECISION_LOW		},
453 		{ "mediump",	PRECISION_MEDIUM	},
454 		{ "highp",		PRECISION_HIGH		}
455 	};
456 	const deUint32	defaultFlags	= LAYOUT_XFBBUFFER | LAYOUT_XFBOFFSET;
457 
458 	// .2_level_array
459 	{
460 		// 2-level basic array variable in single buffer
461 		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array");
462 		addChild(nestedArrayGroup);
463 
464 		for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
465 		{
466 			const glu::DataType	type		= basicTypes[basicTypeNdx];
467 			const char* const	typeName	= glu::getDataTypeName(type);
468 			const int			childSize	= 2;
469 			const int			parentSize	= 2;
470 			const VarType		childType	(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH), childSize);
471 			const VarType		parentType	(childType, parentSize);
472 
473 			createBlockBasicTypeCases(*nestedArrayGroup, m_testCtx, typeName, parentType, defaultFlags);
474 		}
475 	}
476 
477 	// .3_level_array
478 	{
479 		tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
480 		addChild(nestedArrayGroup);
481 
482 		for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
483 		{
484 			const glu::DataType	type		= basicTypes[basicTypeNdx];
485 			const char* const	typeName	= glu::getDataTypeName(type);
486 			const int			childSize0	= 2;
487 			const int			childSize1	= 2;
488 			const int			parentSize	= 2;
489 			const VarType		childType0	(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH), childSize0);
490 			const VarType		childType1	(childType0, childSize1);
491 			const VarType		parentType	(childType1, parentSize);
492 
493 			createBlockBasicTypeCases(*nestedArrayGroup, m_testCtx, typeName, parentType, defaultFlags);
494 		}
495 	}
496 
497 	// .2_level_struct_array
498 	{
499 		tcu::TestCaseGroup* structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one interface block");
500 		addChild(structArrayArrayGroup);
501 
502 		for (int isArray = 0; isArray < 2; isArray++)
503 		{
504 			const std::string	baseName		= isArray ? "instance_array" : "std";
505 			const int			numInstances	= isArray ? 2 : 0;
506 
507 			structArrayArrayGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_vertex"), defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
508 			structArrayArrayGroup->addChild(new Block2LevelStructArrayCase(m_testCtx, (baseName + "_geometry"), defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
509 		}
510 	}
511 
512 	// .single_basic_type
513 	{
514 		tcu::TestCaseGroup* singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
515 		addChild(singleBasicTypeGroup);
516 
517 		for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
518 		{
519 			glu::DataType		type = basicTypes[basicTypeNdx];
520 			const char* const	typeName = glu::getDataTypeName(type);
521 
522 			if (!dataTypeSupportsPrecisionModifier(type))
523 				createBlockBasicTypeCases(*singleBasicTypeGroup, m_testCtx, typeName, VarType(type, 0), defaultFlags);
524 		}
525 
526 		for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
527 		{
528 			de::MovePtr<tcu::TestCaseGroup>	precGroup(new tcu::TestCaseGroup(m_testCtx, precisionFlags[precNdx].name.c_str()));
529 
530 			for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
531 			{
532 				glu::DataType		type		= basicTypes[basicTypeNdx];
533 				const char* const	typeName	= glu::getDataTypeName(type);
534 
535 				if (dataTypeSupportsPrecisionModifier(type))
536 					createBlockBasicTypeCases(*precGroup, m_testCtx, typeName, VarType(type, precisionFlags[precNdx].flags), defaultFlags);
537 			}
538 			singleBasicTypeGroup->addChild(precGroup.release());
539 		}
540 	}
541 
542 	// .single_basic_array
543 	{
544 		tcu::TestCaseGroup* singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
545 		addChild(singleBasicArrayGroup);
546 
547 		for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
548 		{
549 			glu::DataType		type		= basicTypes[basicTypeNdx];
550 			const char* const	typeName	= glu::getDataTypeName(type);
551 			const int			arraySize	= 3;
552 
553 			createBlockBasicTypeCases(*singleBasicArrayGroup, m_testCtx, typeName,
554 										VarType(VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH), arraySize),
555 										defaultFlags);
556 		}
557 	}
558 
559 	// .single_struct
560 	{
561 		tcu::TestCaseGroup* singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in interface block");
562 		addChild(singleStructGroup);
563 
564 		for (int isArray = 0; isArray < 2; isArray++)
565 		{
566 			const std::string	baseName		= isArray ? "instance_array" : "std";
567 			const int			numInstances	= isArray ? 3 : 0;
568 
569 			singleStructGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_vertex", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
570 			singleStructGroup->addChild(new BlockSingleStructCase(m_testCtx, baseName + "_geometry", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
571 		}
572 	}
573 
574 	// .single_struct_array
575 	{
576 		tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one interface block");
577 		addChild(singleStructArrayGroup);
578 
579 		for (int isArray = 0; isArray < 2; isArray++)
580 		{
581 			const std::string	baseName		= isArray ? "instance_array" : "std";
582 			const int			numInstances	= isArray ? 2 : 0;
583 
584 			singleStructArrayGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_vertex", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
585 			singleStructArrayGroup->addChild(new BlockSingleStructArrayCase(m_testCtx, baseName + "_geometry", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
586 		}
587 	}
588 
589 	// .single_nested_struct
590 	{
591 		tcu::TestCaseGroup* singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one interface block");
592 		addChild(singleNestedStructGroup);
593 
594 		for (int isArray = 0; isArray < 2; isArray++)
595 		{
596 			const std::string	baseName		= isArray ? "instance_array" : "std";
597 			const int			numInstances	= isArray ? 2 : 0;
598 
599 			singleNestedStructGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_vertex", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
600 			singleNestedStructGroup->addChild(new BlockSingleNestedStructCase(m_testCtx, baseName + "_geometry", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
601 		}
602 	}
603 
604 	// .single_nested_struct_array
605 	{
606 		tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one interface block");
607 		addChild(singleNestedStructArrayGroup);
608 
609 		for (int isArray = 0; isArray < 2; isArray++)
610 		{
611 			const std::string	baseName		= isArray ? "instance_array" : "std";
612 			const int			numInstances	= isArray ? 2 : 0;
613 
614 			singleNestedStructArrayGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_vertex", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
615 			singleNestedStructArrayGroup->addChild(new BlockSingleNestedStructArrayCase(m_testCtx, baseName + "_geometry", defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
616 		}
617 	}
618 
619 	// .instance_array_basic_type
620 	{
621 		tcu::TestCaseGroup* instanceArrayBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
622 		addChild(instanceArrayBasicTypeGroup);
623 
624 		for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
625 		{
626 			glu::DataType		type			= basicTypes[basicTypeNdx];
627 			const char* const	typeName		= glu::getDataTypeName(type);
628 			const int			numInstances	= 3;
629 
630 			createBlockBasicTypeCases(*instanceArrayBasicTypeGroup, m_testCtx, typeName,
631 										VarType(type, !dataTypeSupportsPrecisionModifier(type) ? 0 : PRECISION_HIGH),
632 										defaultFlags, numInstances);
633 		}
634 	}
635 
636 	// .multi_basic_types
637 	{
638 		tcu::TestCaseGroup* multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
639 		addChild(multiBasicTypesGroup);
640 
641 		for (int isArray = 0; isArray < 2; isArray++)
642 		{
643 			const std::string	baseName		= isArray ? "instance_array" : "std";
644 			const int			numInstances	= isArray ? 2 : 0;
645 
646 			multiBasicTypesGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_vertex", defaultFlags,	defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
647 			multiBasicTypesGroup->addChild(new BlockMultiBasicTypesCase(m_testCtx, baseName + "_geometry", defaultFlags,	defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
648 		}
649 	}
650 
651 	// .multi_nested_struct
652 	{
653 		tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
654 		addChild(multiNestedStructGroup);
655 
656 		for (int isArray = 0; isArray < 2; isArray++)
657 		{
658 			const std::string	baseName		= isArray ? "instance_array" : "std";
659 			const int			numInstances	= isArray ? 2 : 0;
660 
661 			multiNestedStructGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_vertex", defaultFlags,	defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
662 			multiNestedStructGroup->addChild(new BlockMultiNestedStructCase(m_testCtx, baseName + "_geometry", defaultFlags,	defaultFlags,	numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
663 		}
664 	}
665 
666 	// .various_buffers
667 	{
668 		static const struct
669 		{
670 			const std::string	name;
671 			deUint32			bufferA;
672 			deUint32			bufferB;
673 			deUint32			bufferC;
674 		} xfbBufferNumbers[] =
675 		{
676 			{ "000",	0,	0,	0	},
677 			{ "010",	0,	1,	0	},
678 			{ "100",	1,	0,	0	},
679 			{ "110",	1,	1,	0	},
680 		};
681 
682 		tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "various_buffers", "Output data into several transform feedback buffers");
683 		addChild(multiNestedStructGroup);
684 
685 		for (int xfbBufferNdx = 0; xfbBufferNdx < DE_LENGTH_OF_ARRAY(xfbBufferNumbers); xfbBufferNdx++)
686 		{
687 			const deUint32 bufferA = xfbBufferNumbers[xfbBufferNdx].bufferA;
688 			const deUint32 bufferB = xfbBufferNumbers[xfbBufferNdx].bufferB;
689 			const deUint32 bufferC = xfbBufferNumbers[xfbBufferNdx].bufferC;
690 
691 			for (int isArray = 0; isArray < 2; isArray++)
692 			{
693 				std::string	baseName		= "buffers" + xfbBufferNumbers[xfbBufferNdx].name;
694 				const int	numInstances	= isArray ? 2 : 0;
695 
696 				if (isArray)
697 					baseName += "_instance_array";
698 
699 				multiNestedStructGroup->addChild(new BlockVariousBuffersCase(m_testCtx, baseName + "_vertex", defaultFlags, bufferA, bufferB, bufferC, numInstances, LOAD_FULL_MATRIX, TEST_STAGE_VERTEX));
700 				multiNestedStructGroup->addChild(new BlockVariousBuffersCase(m_testCtx, baseName + "_geometry", defaultFlags, bufferA, bufferB, bufferC, numInstances, LOAD_FULL_MATRIX, TEST_STAGE_GEOMETRY));
701 			}
702 		}
703 	}
704 
705 	// .random
706 	{
707 		static const struct
708 		{
709 			std::string		name;
710 			TestStageFlags	testStageFlags;
711 		}
712 		stages[] =
713 		{
714 			{ "vertex",		TEST_STAGE_VERTEX	},
715 			{ "geometry",	TEST_STAGE_GEOMETRY	},
716 		};
717 
718 		for (size_t stageNdx = 0; stageNdx < DE_LENGTH_OF_ARRAY(stages); ++stageNdx)
719 		{
720 			const std::string		groupName		= "random_" + stages[stageNdx].name;
721 			const TestStageFlags	stage			= stages[stageNdx].testStageFlags;
722 			const deUint32			allBasicTypes	= FEATURE_VECTORS|FEATURE_MATRICES|FEATURE_DOUBLES;
723 			const deUint32			unused			= FEATURE_UNASSIGNED_FIELDS|FEATURE_UNASSIGNED_BLOCK_MEMBERS;
724 			const deUint32			disabled		= FEATURE_INSTANCE_ARRAYS|FEATURE_MISSING_BLOCK_MEMBERS|FEATURE_OUT_OF_ORDER_OFFSETS; // OOO & missing offsets handled in a dedicated case group
725 			const deUint32			allFeatures		= ~disabled;
726 			const deUint32			numCases		= 50;
727 
728 			tcu::TestCaseGroup* group = new tcu::TestCaseGroup(m_testCtx, groupName.c_str(), "Random Interface Block cases");
729 			addChild(group);
730 
731 			// Scalar types only, per-block buffers
732 			createRandomCaseGroup(group, m_testCtx, "scalar_types", numCases, stage, unused								);
733 			// Scalar and vector types only, per-block buffers
734 			createRandomCaseGroup(group, m_testCtx, "vector_types", numCases, stage, unused|FEATURE_VECTORS				);
735 			// All basic types, per-block buffers
736 			createRandomCaseGroup(group, m_testCtx, "basic_types", numCases, stage, unused|allBasicTypes				);
737 			// Arrays, per-block buffers
738 			createRandomCaseGroup(group, m_testCtx, "basic_arrays", numCases, stage, unused|allBasicTypes|FEATURE_ARRAYS);
739 
740 			// Basic instance arrays, per-block buffers
741 			createRandomCaseGroup(group, m_testCtx, "basic_instance_arrays", numCases, stage, unused|allBasicTypes|FEATURE_INSTANCE_ARRAYS								);
742 			// Nested structs, per-block buffers
743 			createRandomCaseGroup(group, m_testCtx, "nested_structs", numCases, stage, unused|allBasicTypes|FEATURE_STRUCTS										);
744 			// Nested structs, arrays, per-block buffers
745 			createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays", numCases, stage, unused|allBasicTypes|FEATURE_STRUCTS|FEATURE_ARRAYS						);
746 			// Nested structs, instance arrays, per-block buffers
747 			createRandomCaseGroup(group, m_testCtx, "nested_structs_instance_arrays", numCases, stage, unused|allBasicTypes|FEATURE_STRUCTS|FEATURE_INSTANCE_ARRAYS				);
748 			// Nested structs, instance arrays, per-block buffers
749 			createRandomCaseGroup(group, m_testCtx, "nested_structs_arrays_instance_arrays", numCases, stage, unused|allBasicTypes|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_INSTANCE_ARRAYS);
750 
751 			// All random features, shared buffer
752 			createRandomCaseGroup(group, m_testCtx, "all_instance_array", numCases*2, stage, allFeatures|FEATURE_INSTANCE_ARRAYS);
753 			// All random features, out of order member offsets
754 			createRandomCaseGroup(group, m_testCtx, "all_unordered_and_instance_array", numCases*2, stage, allFeatures|FEATURE_OUT_OF_ORDER_OFFSETS|FEATURE_INSTANCE_ARRAYS);
755 			// All random features, missing interface members
756 			createRandomCaseGroup(group, m_testCtx, "all_missing", numCases*2, stage, allFeatures|FEATURE_MISSING_BLOCK_MEMBERS);
757 			// All random features, unordered and missing members
758 			createRandomCaseGroup(group, m_testCtx, "all_unordered_and_missing", numCases*2, stage, allFeatures|FEATURE_OUT_OF_ORDER_OFFSETS|FEATURE_MISSING_BLOCK_MEMBERS);
759 		}
760 	}
761 }
762 
763 } // anonymous
764 
createTransformFeedbackFuzzLayoutTests(tcu::TestContext & testCtx)765 tcu::TestCaseGroup*	createTransformFeedbackFuzzLayoutTests (tcu::TestContext& testCtx)
766 {
767 	return new InterfaceBlockTests(testCtx);
768 }
769 
770 } // TransformFeedback
771 } // vkt
772