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