1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.0 Module
3 * -------------------------------------------------
4 *
5 * Copyright 2014 The Android Open Source Project
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 Uniform block tests.
22 *//*--------------------------------------------------------------------*/
23
24 #include "es3fUniformBlockTests.hpp"
25 #include "glsUniformBlockCase.hpp"
26 #include "glsRandomUniformBlockCase.hpp"
27 #include "tcuCommandLine.hpp"
28 #include "deRandom.hpp"
29 #include "deStringUtil.hpp"
30
31 using std::string;
32 using std::vector;
33
34 namespace deqp
35 {
36 namespace gles3
37 {
38 namespace Functional
39 {
40
41 using gls::UniformBlockCase;
42 using gls::RandomUniformBlockCase;
43 using namespace gls::ub;
44
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,Context & context,const char * groupName,const char * description,UniformBlockCase::BufferMode bufferMode,deUint32 features,int numCases,deUint32 baseSeed)45 static void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, Context& context, const char* groupName, const char* description, UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed)
46 {
47 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
48 parentGroup->addChild(group);
49
50 baseSeed += (deUint32)context.getTestContext().getCommandLine().getBaseSeed();
51
52 for (int ndx = 0; ndx < numCases; ndx++)
53 group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(), glu::GLSL_VERSION_300_ES,
54 de::toString(ndx).c_str(), "", bufferMode, features, (deUint32)ndx+baseSeed));
55 }
56
57 class BlockBasicTypeCase : public UniformBlockCase
58 {
59 public:
BlockBasicTypeCase(Context & context,const char * name,const char * description,const VarType & type,deUint32 layoutFlags,int numInstances)60 BlockBasicTypeCase (Context& context, const char* name, const char* description, const VarType& type, deUint32 layoutFlags, int numInstances)
61 : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, BUFFERMODE_PER_BLOCK)
62 {
63 UniformBlock& block = m_interface.allocBlock("Block");
64 block.addUniform(Uniform("var", type, 0));
65 block.setFlags(layoutFlags);
66
67 if (numInstances > 0)
68 {
69 block.setArraySize(numInstances);
70 block.setInstanceName("block");
71 }
72 }
73 };
74
createBlockBasicTypeCases(tcu::TestCaseGroup * group,Context & context,const char * name,const VarType & type,deUint32 layoutFlags,int numInstances=0)75 static void createBlockBasicTypeCases (tcu::TestCaseGroup* group, Context& context, const char* name, const VarType& type, deUint32 layoutFlags, int numInstances = 0)
76 {
77 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(), "", type, layoutFlags|DECLARE_VERTEX, numInstances));
78 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(), "", type, layoutFlags|DECLARE_FRAGMENT, numInstances));
79
80 if (!(layoutFlags & LAYOUT_PACKED))
81 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(), "", type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, numInstances));
82 }
83
84 class BlockSingleStructCase : public UniformBlockCase
85 {
86 public:
BlockSingleStructCase(Context & context,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)87 BlockSingleStructCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
88 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
89 , m_layoutFlags (layoutFlags)
90 , m_numInstances (numInstances)
91 {
92 }
93
init(void)94 void init (void)
95 {
96 StructType& typeS = m_interface.allocStruct("S");
97 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH); // First member is unused.
98 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
99 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
100
101 UniformBlock& block = m_interface.allocBlock("Block");
102 block.addUniform(Uniform("s", VarType(&typeS), 0));
103 block.setFlags(m_layoutFlags);
104
105 if (m_numInstances > 0)
106 {
107 block.setInstanceName("block");
108 block.setArraySize(m_numInstances);
109 }
110 }
111
112 private:
113 deUint32 m_layoutFlags;
114 int m_numInstances;
115 };
116
117 class BlockSingleStructArrayCase : public UniformBlockCase
118 {
119 public:
BlockSingleStructArrayCase(Context & context,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)120 BlockSingleStructArrayCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
121 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
122 , m_layoutFlags (layoutFlags)
123 , m_numInstances (numInstances)
124 {
125 }
126
init(void)127 void init (void)
128 {
129 StructType& typeS = m_interface.allocStruct("S");
130 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
131 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
132 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
133
134 UniformBlock& block = m_interface.allocBlock("Block");
135 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_LOW)));
136 block.addUniform(Uniform("s", VarType(VarType(&typeS), 3)));
137 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_MEDIUM)));
138 block.setFlags(m_layoutFlags);
139
140 if (m_numInstances > 0)
141 {
142 block.setInstanceName("block");
143 block.setArraySize(m_numInstances);
144 }
145 }
146
147 private:
148 deUint32 m_layoutFlags;
149 int m_numInstances;
150 };
151
152 class BlockSingleNestedStructCase : public UniformBlockCase
153 {
154 public:
BlockSingleNestedStructCase(Context & context,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)155 BlockSingleNestedStructCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
156 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
157 , m_layoutFlags (layoutFlags)
158 , m_numInstances (numInstances)
159 {
160 }
161
init(void)162 void init (void)
163 {
164 StructType& typeS = m_interface.allocStruct("S");
165 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
166 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
167 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
168
169 StructType& typeT = m_interface.allocStruct("T");
170 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
171 typeT.addMember("b", VarType(&typeS));
172
173 UniformBlock& block = m_interface.allocBlock("Block");
174 block.addUniform(Uniform("s", VarType(&typeS), 0));
175 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
176 block.addUniform(Uniform("t", VarType(&typeT), 0));
177 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
178 block.setFlags(m_layoutFlags);
179
180 if (m_numInstances > 0)
181 {
182 block.setInstanceName("block");
183 block.setArraySize(m_numInstances);
184 }
185 }
186
187 private:
188 deUint32 m_layoutFlags;
189 int m_numInstances;
190 };
191
192 class BlockSingleNestedStructMixedMatrixPackingCase : public UniformBlockCase
193 {
194 public:
BlockSingleNestedStructMixedMatrixPackingCase(Context & context,const char * name,const char * description,deUint32 blockLayoutFlags,deUint32 matrixLayoutFlags,deUint32 matrixArrayLayoutFlags,BufferMode bufferMode,int numInstances)195 BlockSingleNestedStructMixedMatrixPackingCase (Context& context, const char* name, const char* description, deUint32 blockLayoutFlags, deUint32 matrixLayoutFlags, deUint32 matrixArrayLayoutFlags, BufferMode bufferMode, int numInstances)
196 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
197 , m_blockLayoutFlags (blockLayoutFlags)
198 , m_matrixLayoutFlags (matrixLayoutFlags)
199 , m_matrixArrayLayoutFlags (matrixArrayLayoutFlags)
200 , m_numInstances (numInstances)
201 {
202 }
203
init(void)204 void init (void)
205 {
206 StructType& typeS = m_interface.allocStruct("S");
207 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
208 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM), 4));
209 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
210
211 StructType& typeT = m_interface.allocStruct("T");
212 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
213 typeT.addMember("b", VarType(&typeS));
214
215 UniformBlock& block = m_interface.allocBlock("Block");
216 block.addUniform(Uniform("s", VarType(&typeS, m_matrixArrayLayoutFlags), 0));
217 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
218 block.addUniform(Uniform("t", VarType(&typeT, m_matrixLayoutFlags), 0));
219 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
220 block.setFlags(m_blockLayoutFlags);
221
222 if (m_numInstances > 0)
223 {
224 block.setInstanceName("block");
225 block.setArraySize(m_numInstances);
226 }
227 }
228
229 private:
230 deUint32 m_blockLayoutFlags;
231 deUint32 m_matrixLayoutFlags;
232 deUint32 m_matrixArrayLayoutFlags;
233 int m_numInstances;
234 };
235
236 class BlockSingleNestedStructArrayCase : public UniformBlockCase
237 {
238 public:
BlockSingleNestedStructArrayCase(Context & context,const char * name,const char * description,deUint32 layoutFlags,BufferMode bufferMode,int numInstances)239 BlockSingleNestedStructArrayCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances)
240 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
241 , m_layoutFlags (layoutFlags)
242 , m_numInstances (numInstances)
243 {
244 }
245
init(void)246 void init (void)
247 {
248 StructType& typeS = m_interface.allocStruct("S");
249 typeS.addMember("a", VarType(glu::TYPE_INT_VEC3, PRECISION_HIGH));
250 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
251 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH);
252
253 StructType& typeT = m_interface.allocStruct("T");
254 typeT.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM));
255 typeT.addMember("b", VarType(VarType(&typeS), 3));
256
257 UniformBlock& block = m_interface.allocBlock("Block");
258 block.addUniform(Uniform("s", VarType(&typeS), 0));
259 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_LOW), UNUSED_BOTH));
260 block.addUniform(Uniform("t", VarType(VarType(&typeT), 2), 0));
261 block.addUniform(Uniform("u", VarType(glu::TYPE_UINT, PRECISION_HIGH), 0));
262 block.setFlags(m_layoutFlags);
263
264 if (m_numInstances > 0)
265 {
266 block.setInstanceName("block");
267 block.setArraySize(m_numInstances);
268 }
269 }
270
271 private:
272 deUint32 m_layoutFlags;
273 int m_numInstances;
274 };
275
276 class BlockMultiBasicTypesCase : public UniformBlockCase
277 {
278 public:
BlockMultiBasicTypesCase(Context & context,const char * name,const char * description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances)279 BlockMultiBasicTypesCase (Context& context, const char* name, const char* description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
280 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
281 , m_flagsA (flagsA)
282 , m_flagsB (flagsB)
283 , m_numInstances (numInstances)
284 {
285 }
286
init(void)287 void init (void)
288 {
289 UniformBlock& blockA = m_interface.allocBlock("BlockA");
290 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
291 blockA.addUniform(Uniform("b", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
292 blockA.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
293 blockA.setInstanceName("blockA");
294 blockA.setFlags(m_flagsA);
295
296 UniformBlock& blockB = m_interface.allocBlock("BlockB");
297 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_MEDIUM)));
298 blockB.addUniform(Uniform("b", VarType(glu::TYPE_INT_VEC2, PRECISION_LOW)));
299 blockB.addUniform(Uniform("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH), UNUSED_BOTH));
300 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
301 blockB.setInstanceName("blockB");
302 blockB.setFlags(m_flagsB);
303
304 if (m_numInstances > 0)
305 {
306 blockA.setArraySize(m_numInstances);
307 blockB.setArraySize(m_numInstances);
308 }
309 }
310
311 private:
312 deUint32 m_flagsA;
313 deUint32 m_flagsB;
314 int m_numInstances;
315 };
316
317 class BlockMultiNestedStructCase : public UniformBlockCase
318 {
319 public:
BlockMultiNestedStructCase(Context & context,const char * name,const char * description,deUint32 flagsA,deUint32 flagsB,BufferMode bufferMode,int numInstances)320 BlockMultiNestedStructCase (Context& context, const char* name, const char* description, deUint32 flagsA, deUint32 flagsB, BufferMode bufferMode, int numInstances)
321 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_300_ES, bufferMode)
322 , m_flagsA (flagsA)
323 , m_flagsB (flagsB)
324 , m_numInstances (numInstances)
325 {
326 }
327
init(void)328 void init (void)
329 {
330 StructType& typeS = m_interface.allocStruct("S");
331 typeS.addMember("a", VarType(glu::TYPE_FLOAT_MAT3, PRECISION_LOW));
332 typeS.addMember("b", VarType(VarType(glu::TYPE_INT_VEC2, PRECISION_MEDIUM), 4));
333 typeS.addMember("c", VarType(glu::TYPE_FLOAT_VEC4, PRECISION_HIGH));
334
335 StructType& typeT = m_interface.allocStruct("T");
336 typeT.addMember("a", VarType(glu::TYPE_UINT, PRECISION_MEDIUM), UNUSED_BOTH);
337 typeT.addMember("b", VarType(&typeS));
338 typeT.addMember("c", VarType(glu::TYPE_BOOL_VEC4, 0));
339
340 UniformBlock& blockA = m_interface.allocBlock("BlockA");
341 blockA.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT, PRECISION_HIGH)));
342 blockA.addUniform(Uniform("b", VarType(&typeS)));
343 blockA.addUniform(Uniform("c", VarType(glu::TYPE_UINT_VEC3, PRECISION_LOW), UNUSED_BOTH));
344 blockA.setInstanceName("blockA");
345 blockA.setFlags(m_flagsA);
346
347 UniformBlock& blockB = m_interface.allocBlock("BlockB");
348 blockB.addUniform(Uniform("a", VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM)));
349 blockB.addUniform(Uniform("b", VarType(&typeT)));
350 blockB.addUniform(Uniform("c", VarType(glu::TYPE_BOOL_VEC4, 0), UNUSED_BOTH));
351 blockB.addUniform(Uniform("d", VarType(glu::TYPE_BOOL, 0)));
352 blockB.setInstanceName("blockB");
353 blockB.setFlags(m_flagsB);
354
355 if (m_numInstances > 0)
356 {
357 blockA.setArraySize(m_numInstances);
358 blockB.setArraySize(m_numInstances);
359 }
360 }
361
362 private:
363 deUint32 m_flagsA;
364 deUint32 m_flagsB;
365 int m_numInstances;
366 };
367
UniformBlockTests(Context & context)368 UniformBlockTests::UniformBlockTests (Context& context)
369 : TestCaseGroup(context, "ubo", "Uniform Block tests")
370 {
371 }
372
~UniformBlockTests(void)373 UniformBlockTests::~UniformBlockTests (void)
374 {
375 }
376
init(void)377 void UniformBlockTests::init (void)
378 {
379 static const glu::DataType basicTypes[] =
380 {
381 glu::TYPE_FLOAT,
382 glu::TYPE_FLOAT_VEC2,
383 glu::TYPE_FLOAT_VEC3,
384 glu::TYPE_FLOAT_VEC4,
385 glu::TYPE_INT,
386 glu::TYPE_INT_VEC2,
387 glu::TYPE_INT_VEC3,
388 glu::TYPE_INT_VEC4,
389 glu::TYPE_UINT,
390 glu::TYPE_UINT_VEC2,
391 glu::TYPE_UINT_VEC3,
392 glu::TYPE_UINT_VEC4,
393 glu::TYPE_BOOL,
394 glu::TYPE_BOOL_VEC2,
395 glu::TYPE_BOOL_VEC3,
396 glu::TYPE_BOOL_VEC4,
397 glu::TYPE_FLOAT_MAT2,
398 glu::TYPE_FLOAT_MAT3,
399 glu::TYPE_FLOAT_MAT4,
400 glu::TYPE_FLOAT_MAT2X3,
401 glu::TYPE_FLOAT_MAT2X4,
402 glu::TYPE_FLOAT_MAT3X2,
403 glu::TYPE_FLOAT_MAT3X4,
404 glu::TYPE_FLOAT_MAT4X2,
405 glu::TYPE_FLOAT_MAT4X3
406 };
407
408 static const struct
409 {
410 const char* name;
411 deUint32 flags;
412 } precisionFlags[] =
413 {
414 { "lowp", PRECISION_LOW },
415 { "mediump", PRECISION_MEDIUM },
416 { "highp", PRECISION_HIGH }
417 };
418
419 static const struct
420 {
421 const char* name;
422 deUint32 flags;
423 } layoutFlags[] =
424 {
425 { "shared", LAYOUT_SHARED },
426 { "packed", LAYOUT_PACKED },
427 { "std140", LAYOUT_STD140 }
428 };
429
430 static const struct
431 {
432 const char* name;
433 deUint32 flags;
434 } matrixFlags[] =
435 {
436 { "row_major", LAYOUT_ROW_MAJOR },
437 { "column_major", LAYOUT_COLUMN_MAJOR }
438 };
439
440 static const struct
441 {
442 const char* name;
443 UniformBlockCase::BufferMode mode;
444 } bufferModes[] =
445 {
446 { "per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK },
447 { "single_buffer", UniformBlockCase::BUFFERMODE_SINGLE }
448 };
449
450 // ubo.single_basic_type
451 {
452 tcu::TestCaseGroup* singleBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_type", "Single basic variable in single buffer");
453 addChild(singleBasicTypeGroup);
454
455 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
456 {
457 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
458 singleBasicTypeGroup->addChild(layoutGroup);
459
460 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
461 {
462 glu::DataType type = basicTypes[basicTypeNdx];
463 const char* typeName = glu::getDataTypeName(type);
464
465 if (glu::isDataTypeBoolOrBVec(type))
466 createBlockBasicTypeCases(layoutGroup, m_context, typeName, VarType(type, 0), layoutFlags[layoutFlagNdx].flags);
467 else
468 {
469 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
470 createBlockBasicTypeCases(layoutGroup, m_context, (string(precisionFlags[precNdx].name) + "_" + typeName).c_str(),
471 VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags);
472 }
473
474 if (glu::isDataTypeMatrix(type))
475 {
476 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
477 {
478 for (int precNdx = 0; precNdx < DE_LENGTH_OF_ARRAY(precisionFlags); precNdx++)
479 createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + precisionFlags[precNdx].name + "_" + typeName).c_str(),
480 VarType(type, precisionFlags[precNdx].flags), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
481 }
482 }
483 }
484 }
485 }
486
487 // ubo.single_basic_array
488 {
489 tcu::TestCaseGroup* singleBasicArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_basic_array", "Single basic array variable in single buffer");
490 addChild(singleBasicArrayGroup);
491
492 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
493 {
494 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
495 singleBasicArrayGroup->addChild(layoutGroup);
496
497 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
498 {
499 glu::DataType type = basicTypes[basicTypeNdx];
500 const char* typeName = glu::getDataTypeName(type);
501 const int arraySize = 3;
502
503 createBlockBasicTypeCases(layoutGroup, m_context, typeName,
504 VarType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), arraySize),
505 layoutFlags[layoutFlagNdx].flags);
506
507 if (glu::isDataTypeMatrix(type))
508 {
509 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
510 createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
511 VarType(VarType(type, PRECISION_HIGH), arraySize),
512 layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags);
513 }
514 }
515 }
516 }
517
518 // ubo.single_struct
519 {
520 tcu::TestCaseGroup* singleStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct", "Single struct in uniform block");
521 addChild(singleStructGroup);
522
523 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
524 {
525 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
526 singleStructGroup->addChild(modeGroup);
527
528 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
529 {
530 for (int isArray = 0; isArray < 2; isArray++)
531 {
532 std::string baseName = layoutFlags[layoutFlagNdx].name;
533 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
534
535 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
536 continue; // Doesn't make sense to add this variant.
537
538 if (isArray)
539 baseName += "_instance_array";
540
541 modeGroup->addChild(new BlockSingleStructCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
542 modeGroup->addChild(new BlockSingleStructCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
543
544 if (!(baseFlags & LAYOUT_PACKED))
545 modeGroup->addChild(new BlockSingleStructCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
546 }
547 }
548 }
549 }
550
551 // ubo.single_struct_array
552 {
553 tcu::TestCaseGroup* singleStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_struct_array", "Struct array in one uniform block");
554 addChild(singleStructArrayGroup);
555
556 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
557 {
558 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
559 singleStructArrayGroup->addChild(modeGroup);
560
561 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
562 {
563 for (int isArray = 0; isArray < 2; isArray++)
564 {
565 std::string baseName = layoutFlags[layoutFlagNdx].name;
566 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
567
568 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
569 continue; // Doesn't make sense to add this variant.
570
571 if (isArray)
572 baseName += "_instance_array";
573
574 modeGroup->addChild(new BlockSingleStructArrayCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
575 modeGroup->addChild(new BlockSingleStructArrayCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
576
577 if (!(baseFlags & LAYOUT_PACKED))
578 modeGroup->addChild(new BlockSingleStructArrayCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
579 }
580 }
581 }
582 }
583
584 // ubo.single_nested_struct
585 {
586 tcu::TestCaseGroup* singleNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct", "Nested struct in one uniform block");
587 addChild(singleNestedStructGroup);
588
589 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
590 {
591 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
592 singleNestedStructGroup->addChild(modeGroup);
593
594 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
595 {
596 for (int isArray = 0; isArray < 2; isArray++)
597 {
598 std::string baseName = layoutFlags[layoutFlagNdx].name;
599 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
600
601 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
602 continue; // Doesn't make sense to add this variant.
603
604 if (isArray)
605 baseName += "_instance_array";
606
607 modeGroup->addChild(new BlockSingleNestedStructCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
608 modeGroup->addChild(new BlockSingleNestedStructCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
609
610 if (!(baseFlags & LAYOUT_PACKED))
611 modeGroup->addChild(new BlockSingleNestedStructCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
612 }
613 }
614 }
615 }
616
617 // ubo.single_nested_struct_mixed_matrix_packing
618 {
619 tcu::TestCaseGroup* singleNestedStructMixedMatrixPackingGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_mixed_matrix_packing", "Nested struct in one uniform block with a mixed matrix packing");
620 addChild(singleNestedStructMixedMatrixPackingGroup);
621
622 for (const auto& bufferMode : bufferModes)
623 {
624 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferMode.name, "");
625 singleNestedStructMixedMatrixPackingGroup->addChild(modeGroup);
626
627 for (const auto& layoutFlag : layoutFlags)
628 for (const auto& blockMatrixFlag : matrixFlags)
629 for (const auto& singleMatrixFlag : matrixFlags)
630 for (const auto& arrayMatrixFlag : matrixFlags)
631 for (int isArray = 0; isArray < 2; isArray++)
632 {
633 std::string baseName = layoutFlag.name;
634 deUint32 baseFlags = layoutFlag.flags;
635 deUint32 blockFlags = baseFlags | blockMatrixFlag.flags;
636
637 baseName += std::string("_block_") + blockMatrixFlag.name;
638 baseName += std::string("_matrix_") + singleMatrixFlag.name;
639 baseName += std::string("_matrixarray_") + arrayMatrixFlag.name;
640
641 if (bufferMode.mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
642 continue; // Doesn't make sense to add this variant.
643
644 if (isArray)
645 baseName += "_instance_array";
646
647 modeGroup->addChild(new BlockSingleNestedStructMixedMatrixPackingCase(m_context, (baseName + "_vertex").c_str(), "", blockFlags | DECLARE_VERTEX, singleMatrixFlag.flags, arrayMatrixFlag.flags, bufferMode.mode, isArray ? 3 : 0));
648 modeGroup->addChild(new BlockSingleNestedStructMixedMatrixPackingCase(m_context, (baseName + "_fragment").c_str(), "", blockFlags | DECLARE_FRAGMENT, singleMatrixFlag.flags, arrayMatrixFlag.flags, bufferMode.mode, isArray ? 3 : 0));
649
650 if (!(baseFlags & LAYOUT_PACKED))
651 modeGroup->addChild(new BlockSingleNestedStructMixedMatrixPackingCase(m_context, (baseName + "_both").c_str(), "", blockFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, singleMatrixFlag.flags, arrayMatrixFlag.flags, bufferMode.mode, isArray ? 3 : 0));
652 }
653 }
654 }
655
656 // ubo.single_nested_struct_array
657 {
658 tcu::TestCaseGroup* singleNestedStructArrayGroup = new tcu::TestCaseGroup(m_testCtx, "single_nested_struct_array", "Nested struct array in one uniform block");
659 addChild(singleNestedStructArrayGroup);
660
661 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
662 {
663 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
664 singleNestedStructArrayGroup->addChild(modeGroup);
665
666 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
667 {
668 for (int isArray = 0; isArray < 2; isArray++)
669 {
670 std::string baseName = layoutFlags[layoutFlagNdx].name;
671 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
672
673 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
674 continue; // Doesn't make sense to add this variant.
675
676 if (isArray)
677 baseName += "_instance_array";
678
679 modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
680 modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
681
682 if (!(baseFlags & LAYOUT_PACKED))
683 modeGroup->addChild(new BlockSingleNestedStructArrayCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
684 }
685 }
686 }
687 }
688
689 // ubo.instance_array_basic_type
690 {
691 tcu::TestCaseGroup* instanceArrayBasicTypeGroup = new tcu::TestCaseGroup(m_testCtx, "instance_array_basic_type", "Single basic variable in instance array");
692 addChild(instanceArrayBasicTypeGroup);
693
694 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
695 {
696 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
697 instanceArrayBasicTypeGroup->addChild(layoutGroup);
698
699 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
700 {
701 glu::DataType type = basicTypes[basicTypeNdx];
702 const char* typeName = glu::getDataTypeName(type);
703 const int numInstances = 3;
704
705 createBlockBasicTypeCases(layoutGroup, m_context, typeName,
706 VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH),
707 layoutFlags[layoutFlagNdx].flags, numInstances);
708
709 if (glu::isDataTypeMatrix(type))
710 {
711 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
712 createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
713 VarType(type, PRECISION_HIGH), layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags,
714 numInstances);
715 }
716 }
717 }
718 }
719
720 // ubo.multi_basic_types
721 {
722 tcu::TestCaseGroup* multiBasicTypesGroup = new tcu::TestCaseGroup(m_testCtx, "multi_basic_types", "Multiple buffers with basic types");
723 addChild(multiBasicTypesGroup);
724
725 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
726 {
727 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
728 multiBasicTypesGroup->addChild(modeGroup);
729
730 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
731 {
732 for (int isArray = 0; isArray < 2; isArray++)
733 {
734 std::string baseName = layoutFlags[layoutFlagNdx].name;
735 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
736
737 if (isArray)
738 baseName += "_instance_array";
739
740 modeGroup->addChild(new BlockMultiBasicTypesCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
741 modeGroup->addChild(new BlockMultiBasicTypesCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
742
743 if (!(baseFlags & LAYOUT_PACKED))
744 modeGroup->addChild(new BlockMultiBasicTypesCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
745
746 modeGroup->addChild(new BlockMultiBasicTypesCase(m_context, (baseName + "_mixed").c_str(), "", baseFlags|DECLARE_VERTEX, baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
747 }
748 }
749 }
750 }
751
752 // ubo.multi_nested_struct
753 {
754 tcu::TestCaseGroup* multiNestedStructGroup = new tcu::TestCaseGroup(m_testCtx, "multi_nested_struct", "Multiple buffers with nested structs");
755 addChild(multiNestedStructGroup);
756
757 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
758 {
759 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
760 multiNestedStructGroup->addChild(modeGroup);
761
762 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
763 {
764 for (int isArray = 0; isArray < 2; isArray++)
765 {
766 std::string baseName = layoutFlags[layoutFlagNdx].name;
767 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags;
768
769 if (isArray)
770 baseName += "_instance_array";
771
772 modeGroup->addChild(new BlockMultiNestedStructCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0));
773 modeGroup->addChild(new BlockMultiNestedStructCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
774
775 if (!(baseFlags & LAYOUT_PACKED))
776 modeGroup->addChild(new BlockMultiNestedStructCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
777
778 modeGroup->addChild(new BlockMultiNestedStructCase(m_context, (baseName + "_mixed").c_str(), "", baseFlags|DECLARE_VERTEX, baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0));
779 }
780 }
781 }
782 }
783
784 // ubo.random
785 {
786 const deUint32 allShaders = FEATURE_VERTEX_BLOCKS|FEATURE_FRAGMENT_BLOCKS|FEATURE_SHARED_BLOCKS;
787 const deUint32 allLayouts = FEATURE_PACKED_LAYOUT|FEATURE_SHARED_LAYOUT|FEATURE_STD140_LAYOUT;
788 const deUint32 allBasicTypes = FEATURE_VECTORS|FEATURE_MATRICES;
789 const deUint32 unused = FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_UNIFORMS;
790 const deUint32 matFlags = FEATURE_MATRIX_LAYOUT;
791 const deUint32 allFeatures = ~FEATURE_ARRAYS_OF_ARRAYS;
792
793 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
794 addChild(randomGroup);
795
796 // Basic types.
797 createRandomCaseGroup(randomGroup, m_context, "scalar_types", "Scalar types only, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused, 25, 0);
798 createRandomCaseGroup(randomGroup, m_context, "vector_types", "Scalar and vector types only, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|FEATURE_VECTORS, 25, 25);
799 createRandomCaseGroup(randomGroup, m_context, "basic_types", "All basic types, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags, 25, 50);
800 createRandomCaseGroup(randomGroup, m_context, "basic_arrays", "Arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS, 25, 50);
801
802 createRandomCaseGroup(randomGroup, m_context, "basic_instance_arrays", "Basic instance arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_INSTANCE_ARRAYS, 25, 75);
803 createRandomCaseGroup(randomGroup, m_context, "nested_structs", "Nested structs, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS, 25, 100);
804 createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays", "Nested structs, arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS, 25, 150);
805 createRandomCaseGroup(randomGroup, m_context, "nested_structs_instance_arrays", "Nested structs, instance arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_INSTANCE_ARRAYS, 25, 125);
806 createRandomCaseGroup(randomGroup, m_context, "nested_structs_arrays_instance_arrays", "Nested structs, instance arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_STRUCTS|FEATURE_ARRAYS|FEATURE_INSTANCE_ARRAYS, 25, 175);
807
808 createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures, 50, 200);
809 createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer", UniformBlockCase::BUFFERMODE_SINGLE, allFeatures, 50, 250);
810 }
811 }
812
813 } // Functional
814 } // gles3
815 } // deqp
816