1 /*-------------------------------------------------------------------------
2 * drawElements Quality Program OpenGL (ES) 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 Random uniform block layout case.
22 *//*--------------------------------------------------------------------*/
23
24 #include "glsRandomUniformBlockCase.hpp"
25 #include "tcuCommandLine.hpp"
26 #include "deRandom.hpp"
27 #include "deStringUtil.hpp"
28
29 using std::string;
30 using std::vector;
31
32 namespace deqp
33 {
34 namespace gls
35 {
36
37 using namespace gls::ub;
38
RandomUniformBlockCase(tcu::TestContext & testCtx,glu::RenderContext & renderCtx,glu::GLSLVersion glslVersion,const char * name,const char * description,BufferMode bufferMode,deUint32 features,deUint32 seed)39 RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext& testCtx,
40 glu::RenderContext& renderCtx,
41 glu::GLSLVersion glslVersion,
42 const char* name,
43 const char* description,
44 BufferMode bufferMode,
45 deUint32 features,
46 deUint32 seed)
47 : UniformBlockCase (testCtx, renderCtx, name, description, glslVersion, bufferMode)
48 , m_features (features)
49 , m_maxVertexBlocks ((features & FEATURE_VERTEX_BLOCKS) ? 4 : 0)
50 , m_maxFragmentBlocks ((features & FEATURE_FRAGMENT_BLOCKS) ? 4 : 0)
51 , m_maxSharedBlocks ((features & FEATURE_SHARED_BLOCKS) ? 4 : 0)
52 , m_maxInstances ((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
53 , m_maxArrayLength ((features & FEATURE_ARRAYS) ? 8 : 0)
54 , m_maxStructDepth ((features & FEATURE_STRUCTS) ? 2 : 0)
55 , m_maxBlockMembers (5)
56 , m_maxStructMembers (4)
57 , m_seed (seed)
58 , m_blockNdx (1)
59 , m_uniformNdx (1)
60 , m_structNdx (1)
61 {
62 }
63
init(void)64 void RandomUniformBlockCase::init (void)
65 {
66 de::Random rnd(m_seed);
67
68 int numShared = m_maxSharedBlocks > 0 ? rnd.getInt(1, m_maxSharedBlocks) : 0;
69 int numVtxBlocks = m_maxVertexBlocks-numShared > 0 ? rnd.getInt(1, m_maxVertexBlocks-numShared) : 0;
70 int numFragBlocks = m_maxFragmentBlocks-numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks-numShared) : 0;
71
72 for (int ndx = 0; ndx < numShared; ndx++)
73 generateBlock(rnd, DECLARE_VERTEX|DECLARE_FRAGMENT);
74
75 for (int ndx = 0; ndx < numVtxBlocks; ndx++)
76 generateBlock(rnd, DECLARE_VERTEX);
77
78 for (int ndx = 0; ndx < numFragBlocks; ndx++)
79 generateBlock(rnd, DECLARE_FRAGMENT);
80 }
81
generateBlock(de::Random & rnd,deUint32 layoutFlags)82 void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
83 {
84 DE_ASSERT(m_blockNdx <= 'z' - 'a');
85
86 const float instanceArrayWeight = 0.3f;
87 UniformBlock& block = m_interface.allocBlock((string("Block") + (char)('A' + m_blockNdx)).c_str());
88 int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
89 int numUniforms = rnd.getInt(1, m_maxBlockMembers);
90
91 if (numInstances > 0)
92 block.setArraySize(numInstances);
93
94 if (numInstances > 0 || rnd.getBool())
95 block.setInstanceName((string("block") + (char)('A' + m_blockNdx)).c_str());
96
97 // Layout flag candidates.
98 vector<deUint32> layoutFlagCandidates;
99 layoutFlagCandidates.push_back(0);
100 if (m_features & FEATURE_PACKED_LAYOUT)
101 layoutFlagCandidates.push_back(LAYOUT_SHARED);
102 if ((m_features & FEATURE_SHARED_LAYOUT) && ((layoutFlags & DECLARE_BOTH) != DECLARE_BOTH))
103 layoutFlagCandidates.push_back(LAYOUT_PACKED); // \note packed layout can only be used in a single shader stage.
104 if (m_features & FEATURE_STD140_LAYOUT)
105 layoutFlagCandidates.push_back(LAYOUT_STD140);
106
107 layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
108
109 if (m_features & FEATURE_MATRIX_LAYOUT)
110 {
111 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
112 layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
113 }
114
115 block.setFlags(layoutFlags);
116
117 for (int ndx = 0; ndx < numUniforms; ndx++)
118 generateUniform(rnd, block);
119
120 m_blockNdx += 1;
121 }
122
genName(char first,char last,int ndx)123 static std::string genName (char first, char last, int ndx)
124 {
125 std::string str = "";
126 int alphabetLen = last - first + 1;
127
128 while (ndx > alphabetLen)
129 {
130 str.insert(str.begin(), (char)(first + ((ndx-1)%alphabetLen)));
131 ndx = ((ndx-1) / alphabetLen);
132 }
133
134 str.insert(str.begin(), (char)(first + (ndx%(alphabetLen+1)) - 1));
135
136 return str;
137 }
138
generateUniform(de::Random & rnd,UniformBlock & block)139 void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
140 {
141 const float unusedVtxWeight = 0.15f;
142 const float unusedFragWeight = 0.15f;
143 bool unusedOk = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
144 deUint32 flags = 0;
145 std::string name = genName('a', 'z', m_uniformNdx);
146 VarType type = generateType(rnd, 0, true);
147
148 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
149 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
150
151 block.addUniform(Uniform(name.c_str(), type, flags));
152
153 m_uniformNdx += 1;
154 }
155
generateType(de::Random & rnd,int typeDepth,bool arrayOk)156 VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
157 {
158 const float structWeight = 0.1f;
159 const float arrayWeight = 0.1f;
160
161 if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
162 {
163 const float unusedVtxWeight = 0.15f;
164 const float unusedFragWeight = 0.15f;
165 bool unusedOk = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
166 vector<VarType> memberTypes;
167 int numMembers = rnd.getInt(1, m_maxStructMembers);
168
169 // Generate members first so nested struct declarations are in correct order.
170 for (int ndx = 0; ndx < numMembers; ndx++)
171 memberTypes.push_back(generateType(rnd, typeDepth+1, true));
172
173 StructType& structType = m_interface.allocStruct((string("s") + genName('A', 'Z', m_structNdx)).c_str());
174 m_structNdx += 1;
175
176 DE_ASSERT(numMembers <= 'Z' - 'A');
177 for (int ndx = 0; ndx < numMembers; ndx++)
178 {
179 deUint32 flags = 0;
180
181 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
182 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
183
184 structType.addMember((string("m") + (char)('A' + ndx)).c_str(), memberTypes[ndx], flags);
185 }
186
187 return VarType(&structType);
188 }
189 else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
190 {
191 const bool arraysOfArraysOk = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
192 const int arrayLength = rnd.getInt(1, m_maxArrayLength);
193 VarType elementType = generateType(rnd, typeDepth, arraysOfArraysOk);
194 return VarType(elementType, arrayLength);
195 }
196 else
197 {
198 vector<glu::DataType> typeCandidates;
199
200 typeCandidates.push_back(glu::TYPE_FLOAT);
201 typeCandidates.push_back(glu::TYPE_INT);
202 typeCandidates.push_back(glu::TYPE_UINT);
203 typeCandidates.push_back(glu::TYPE_BOOL);
204
205 if (m_features & FEATURE_VECTORS)
206 {
207 typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
208 typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
209 typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
210 typeCandidates.push_back(glu::TYPE_INT_VEC2);
211 typeCandidates.push_back(glu::TYPE_INT_VEC3);
212 typeCandidates.push_back(glu::TYPE_INT_VEC4);
213 typeCandidates.push_back(glu::TYPE_UINT_VEC2);
214 typeCandidates.push_back(glu::TYPE_UINT_VEC3);
215 typeCandidates.push_back(glu::TYPE_UINT_VEC4);
216 typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
217 typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
218 typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
219 }
220
221 if (m_features & FEATURE_MATRICES)
222 {
223 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
224 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
225 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
226 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
227 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
228 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
229 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
230 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
231 }
232
233 glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
234 deUint32 flags = 0;
235
236 if (!glu::isDataTypeBoolOrBVec(type))
237 {
238 // Precision.
239 static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
240 flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
241 }
242
243 return VarType(type, flags);
244 }
245 }
246
247 } // gls
248 } // deqp
249