1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL ES 3.1 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 "es31fUniformBlockTests.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 gles31
37 {
38 namespace Functional
39 {
40 namespace
41 {
42
43 using gls::RandomUniformBlockCase;
44 using gls::UniformBlockCase;
45 using namespace gls::ub;
46
createRandomCaseGroup(tcu::TestCaseGroup * parentGroup,Context & context,const char * groupName,const char * description,UniformBlockCase::BufferMode bufferMode,uint32_t features,int numCases,uint32_t baseSeed)47 void createRandomCaseGroup(tcu::TestCaseGroup *parentGroup, Context &context, const char *groupName,
48 const char *description, UniformBlockCase::BufferMode bufferMode, uint32_t features,
49 int numCases, uint32_t baseSeed)
50 {
51 tcu::TestCaseGroup *group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description);
52 parentGroup->addChild(group);
53
54 baseSeed += (uint32_t)context.getTestContext().getCommandLine().getBaseSeed();
55
56 for (int ndx = 0; ndx < numCases; ndx++)
57 group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(),
58 glu::GLSL_VERSION_310_ES, de::toString(ndx).c_str(), "", bufferMode,
59 features, (uint32_t)ndx + baseSeed));
60 }
61
62 class BlockBasicTypeCase : public UniformBlockCase
63 {
64 public:
BlockBasicTypeCase(Context & context,const char * name,const char * description,const VarType & type,uint32_t layoutFlags,int numInstances)65 BlockBasicTypeCase(Context &context, const char *name, const char *description, const VarType &type,
66 uint32_t layoutFlags, int numInstances)
67 : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description,
68 glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK)
69 {
70 UniformBlock &block = m_interface.allocBlock("Block");
71 block.addUniform(Uniform("var", type, 0));
72 block.setFlags(layoutFlags);
73
74 if (numInstances > 0)
75 {
76 block.setArraySize(numInstances);
77 block.setInstanceName("block");
78 }
79 }
80 };
81
createBlockBasicTypeCases(tcu::TestCaseGroup * group,Context & context,const char * name,const VarType & type,uint32_t layoutFlags,int numInstances=0)82 static void createBlockBasicTypeCases(tcu::TestCaseGroup *group, Context &context, const char *name,
83 const VarType &type, uint32_t layoutFlags, int numInstances = 0)
84 {
85 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(), "", type,
86 layoutFlags | DECLARE_VERTEX, numInstances));
87 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(), "", type,
88 layoutFlags | DECLARE_FRAGMENT, numInstances));
89
90 if (!(layoutFlags & LAYOUT_PACKED))
91 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(), "", type,
92 layoutFlags | DECLARE_VERTEX | DECLARE_FRAGMENT, numInstances));
93 }
94
95 class Block2LevelStructArrayCase : public UniformBlockCase
96 {
97 public:
Block2LevelStructArrayCase(Context & context,const char * name,const char * description,uint32_t layoutFlags,BufferMode bufferMode,int numInstances)98 Block2LevelStructArrayCase(Context &context, const char *name, const char *description, uint32_t layoutFlags,
99 BufferMode bufferMode, int numInstances)
100 : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description,
101 glu::GLSL_VERSION_310_ES, bufferMode)
102 , m_layoutFlags(layoutFlags)
103 , m_numInstances(numInstances)
104 {
105 }
106
init(void)107 void init(void)
108 {
109 StructType &typeS = m_interface.allocStruct("S");
110 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH);
111 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4));
112 typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW));
113
114 UniformBlock &block = m_interface.allocBlock("Block");
115 block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM)));
116 block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2)));
117 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM)));
118 block.setFlags(m_layoutFlags);
119
120 if (m_numInstances > 0)
121 {
122 block.setInstanceName("block");
123 block.setArraySize(m_numInstances);
124 }
125 }
126
127 private:
128 uint32_t m_layoutFlags;
129 int m_numInstances;
130 };
131
132 } // namespace
133
UniformBlockTests(Context & context)134 UniformBlockTests::UniformBlockTests(Context &context) : TestCaseGroup(context, "ubo", "Uniform Block tests")
135 {
136 }
137
~UniformBlockTests(void)138 UniformBlockTests::~UniformBlockTests(void)
139 {
140 }
141
init(void)142 void UniformBlockTests::init(void)
143 {
144 static const glu::DataType basicTypes[] = {
145 glu::TYPE_FLOAT, glu::TYPE_FLOAT_VEC2, glu::TYPE_FLOAT_VEC3, glu::TYPE_FLOAT_VEC4,
146 glu::TYPE_INT, glu::TYPE_INT_VEC2, glu::TYPE_INT_VEC3, glu::TYPE_INT_VEC4,
147 glu::TYPE_UINT, glu::TYPE_UINT_VEC2, glu::TYPE_UINT_VEC3, glu::TYPE_UINT_VEC4,
148 glu::TYPE_BOOL, glu::TYPE_BOOL_VEC2, glu::TYPE_BOOL_VEC3, glu::TYPE_BOOL_VEC4,
149 glu::TYPE_FLOAT_MAT2, glu::TYPE_FLOAT_MAT3, glu::TYPE_FLOAT_MAT4, glu::TYPE_FLOAT_MAT2X3,
150 glu::TYPE_FLOAT_MAT2X4, glu::TYPE_FLOAT_MAT3X2, glu::TYPE_FLOAT_MAT3X4, glu::TYPE_FLOAT_MAT4X2,
151 glu::TYPE_FLOAT_MAT4X3};
152
153 static const struct
154 {
155 const char *name;
156 uint32_t flags;
157 } layoutFlags[] = {{"shared", LAYOUT_SHARED}, {"packed", LAYOUT_PACKED}, {"std140", LAYOUT_STD140}};
158
159 static const struct
160 {
161 const char *name;
162 uint32_t flags;
163 } matrixFlags[] = {{"row_major", LAYOUT_ROW_MAJOR}, {"column_major", LAYOUT_COLUMN_MAJOR}};
164
165 static const struct
166 {
167 const char *name;
168 UniformBlockCase::BufferMode mode;
169 } bufferModes[] = {{"per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK},
170 {"single_buffer", UniformBlockCase::BUFFERMODE_SINGLE}};
171
172 // ubo.2_level_array
173 {
174 tcu::TestCaseGroup *nestedArrayGroup =
175 new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer");
176 addChild(nestedArrayGroup);
177
178 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
179 {
180 tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
181 nestedArrayGroup->addChild(layoutGroup);
182
183 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
184 {
185 const glu::DataType type = basicTypes[basicTypeNdx];
186 const char *typeName = glu::getDataTypeName(type);
187 const int childSize = 4;
188 const int parentSize = 3;
189 const VarType childType(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize);
190 const VarType parentType(childType, parentSize);
191
192 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType,
193 layoutFlags[layoutFlagNdx].flags);
194
195 if (glu::isDataTypeMatrix(type))
196 {
197 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
198 createBlockBasicTypeCases(
199 layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
200 parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
201 }
202 }
203 }
204 }
205
206 // ubo.3_level_array
207 {
208 tcu::TestCaseGroup *nestedArrayGroup =
209 new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer");
210 addChild(nestedArrayGroup);
211
212 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
213 {
214 tcu::TestCaseGroup *layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, "");
215 nestedArrayGroup->addChild(layoutGroup);
216
217 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++)
218 {
219 const glu::DataType type = basicTypes[basicTypeNdx];
220 const char *typeName = glu::getDataTypeName(type);
221 const int childSize0 = 2;
222 const int childSize1 = 4;
223 const int parentSize = 3;
224 const VarType childType0(VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH),
225 childSize0);
226 const VarType childType1(childType0, childSize1);
227 const VarType parentType(childType1, parentSize);
228
229 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType,
230 layoutFlags[layoutFlagNdx].flags);
231
232 if (glu::isDataTypeMatrix(type))
233 {
234 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++)
235 createBlockBasicTypeCases(
236 layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(),
237 parentType, layoutFlags[layoutFlagNdx].flags | matrixFlags[matFlagNdx].flags);
238 }
239 }
240 }
241 }
242
243 // ubo.2_level_struct_array
244 {
245 tcu::TestCaseGroup *structArrayArrayGroup =
246 new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block");
247 addChild(structArrayArrayGroup);
248
249 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++)
250 {
251 tcu::TestCaseGroup *modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, "");
252 structArrayArrayGroup->addChild(modeGroup);
253
254 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++)
255 {
256 for (int isArray = 0; isArray < 2; isArray++)
257 {
258 std::string baseName = layoutFlags[layoutFlagNdx].name;
259 uint32_t baseFlags = layoutFlags[layoutFlagNdx].flags;
260
261 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0)
262 continue; // Doesn't make sense to add this variant.
263
264 if (isArray)
265 baseName += "_instance_array";
266
267 modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_vertex").c_str(), "",
268 baseFlags | DECLARE_VERTEX,
269 bufferModes[modeNdx].mode, isArray ? 3 : 0));
270 modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_fragment").c_str(), "",
271 baseFlags | DECLARE_FRAGMENT,
272 bufferModes[modeNdx].mode, isArray ? 3 : 0));
273
274 if (!(baseFlags & LAYOUT_PACKED))
275 modeGroup->addChild(new Block2LevelStructArrayCase(
276 m_context, (baseName + "_both").c_str(), "", baseFlags | DECLARE_VERTEX | DECLARE_FRAGMENT,
277 bufferModes[modeNdx].mode, isArray ? 3 : 0));
278 }
279 }
280 }
281 }
282
283 // ubo.random
284 {
285 const uint32_t allShaders = FEATURE_VERTEX_BLOCKS | FEATURE_FRAGMENT_BLOCKS | FEATURE_SHARED_BLOCKS;
286 const uint32_t allLayouts = FEATURE_PACKED_LAYOUT | FEATURE_SHARED_LAYOUT | FEATURE_STD140_LAYOUT;
287 const uint32_t allBasicTypes = FEATURE_VECTORS | FEATURE_MATRICES;
288 const uint32_t unused = FEATURE_UNUSED_MEMBERS | FEATURE_UNUSED_UNIFORMS;
289 const uint32_t matFlags = FEATURE_MATRIX_LAYOUT;
290 const uint32_t basicTypeArrays =
291 allShaders | allLayouts | unused | allBasicTypes | matFlags | FEATURE_ARRAYS | FEATURE_ARRAYS_OF_ARRAYS;
292 const uint32_t allFeatures = ~0u;
293
294 tcu::TestCaseGroup *randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases");
295 addChild(randomGroup);
296
297 createRandomCaseGroup(randomGroup, m_context, "basic_type_arrays", "Arrays, per-block buffers",
298 UniformBlockCase::BUFFERMODE_PER_BLOCK, basicTypeArrays, 25, 1150);
299 createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers",
300 UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures, 50, 11200);
301 createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer",
302 UniformBlockCase::BUFFERMODE_SINGLE, allFeatures, 50, 11250);
303 }
304 }
305
306 } // namespace Functional
307 } // namespace gles31
308 } // namespace deqp
309