1 /*------------------------------------------------------------------------
2 * Vulkan Conformance Tests
3 * ------------------------
5 * Copyright (c) 2015 The Khronos Group Inc.
6 * Copyright (c) 2015 Samsung Electronics Co., Ltd.
7 * Copyright (c) 2016 The Android Open Source Project
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
13 * http://www.apache.org/licenses/LICENSE-2.0
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
23 * \brief Random uniform block layout case.
24 *//*--------------------------------------------------------------------*/
26 #include "vktRandomUniformBlockCase.hpp"
27 #include "deRandom.hpp"
37 static std::string genName (char first, char last, int ndx)
40 int alphabetLen = last - first + 1;
42 while (ndx > alphabetLen)
44 str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen)));
45 ndx = (ndx - 1) / alphabetLen;
48 str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1));
55 RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext& testCtx,
56 const std::string& name,
57 const std::string& description,
58 BufferMode bufferMode,
61 : UniformBlockCase (testCtx, name, description, bufferMode, LOAD_FULL_MATRIX, (features & FEATURE_OUT_OF_ORDER_OFFSETS) != 0u)
62 , m_features (features)
63 , m_maxVertexBlocks ((features & FEATURE_VERTEX_BLOCKS) ? 4 : 0)
64 , m_maxFragmentBlocks ((features & FEATURE_FRAGMENT_BLOCKS) ? 4 : 0)
65 , m_maxSharedBlocks ((features & FEATURE_SHARED_BLOCKS) ? 4 : 0)
66 , m_maxInstances ((features & FEATURE_INSTANCE_ARRAYS) ? 3 : 0)
67 , m_maxArrayLength ((features & FEATURE_ARRAYS) ? 8 : 0)
68 , m_maxStructDepth ((features & FEATURE_STRUCTS) ? 2 : 0)
69 , m_maxBlockMembers (5)
70 , m_maxStructMembers (4)
76 de::Random rnd(m_seed);
78 int numShared = m_maxSharedBlocks > 0 ? rnd.getInt(1, m_maxSharedBlocks) : 0;
79 int numVtxBlocks = m_maxVertexBlocks-numShared > 0 ? rnd.getInt(1, m_maxVertexBlocks - numShared) : 0;
80 int numFragBlocks = m_maxFragmentBlocks-numShared > 0 ? rnd.getInt(1, m_maxFragmentBlocks - numShared): 0;
82 for (int ndx = 0; ndx < numShared; ndx++)
83 generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT);
85 for (int ndx = 0; ndx < numVtxBlocks; ndx++)
86 generateBlock(rnd, DECLARE_VERTEX);
88 for (int ndx = 0; ndx < numFragBlocks; ndx++)
89 generateBlock(rnd, DECLARE_FRAGMENT);
94 void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags)
96 DE_ASSERT(m_blockNdx <= 'z' - 'a');
98 const float instanceArrayWeight = 0.3f;
99 UniformBlock& block = m_interface.allocBlock(std::string("Block") + (char)('A' + m_blockNdx));
100 int numInstances = (m_maxInstances > 0 && rnd.getFloat() < instanceArrayWeight) ? rnd.getInt(0, m_maxInstances) : 0;
101 int numUniforms = rnd.getInt(1, m_maxBlockMembers);
103 if (numInstances > 0)
104 block.setArraySize(numInstances);
106 if (numInstances > 0 || rnd.getBool())
107 block.setInstanceName(std::string("block") + (char)('A' + m_blockNdx));
109 // Layout flag candidates.
110 std::vector<deUint32> layoutFlagCandidates;
111 layoutFlagCandidates.push_back(0);
113 if (m_features & FEATURE_STD140_LAYOUT)
114 layoutFlagCandidates.push_back(LAYOUT_STD140);
116 layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end());
118 if (m_features & FEATURE_MATRIX_LAYOUT)
120 static const deUint32 matrixCandidates[] = { 0, LAYOUT_ROW_MAJOR, LAYOUT_COLUMN_MAJOR };
121 layoutFlags |= rnd.choose<deUint32>(&matrixCandidates[0], &matrixCandidates[DE_LENGTH_OF_ARRAY(matrixCandidates)]);
124 block.setFlags(layoutFlags);
126 for (int ndx = 0; ndx < numUniforms; ndx++)
127 generateUniform(rnd, block);
132 void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block)
134 const float unusedVtxWeight = 0.15f;
135 const float unusedFragWeight = 0.15f;
136 bool unusedOk = (m_features & FEATURE_UNUSED_UNIFORMS) != 0;
138 std::string name = genName('a', 'z', m_uniformNdx);
139 VarType type = generateType(rnd, 0, true);
141 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
142 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
144 block.addUniform(Uniform(name, type, flags));
149 VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk)
151 const float structWeight = 0.1f;
152 const float arrayWeight = 0.1f;
154 if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight)
156 const float unusedVtxWeight = 0.15f;
157 const float unusedFragWeight = 0.15f;
158 bool unusedOk = (m_features & FEATURE_UNUSED_MEMBERS) != 0;
159 std::vector<VarType> memberTypes;
160 int numMembers = rnd.getInt(1, m_maxStructMembers);
162 // Generate members first so nested struct declarations are in correct order.
163 for (int ndx = 0; ndx < numMembers; ndx++)
164 memberTypes.push_back(generateType(rnd, typeDepth+1, true));
166 StructType& structType = m_interface.allocStruct(std::string("s") + genName('A', 'Z', m_structNdx));
169 DE_ASSERT(numMembers <= 'Z' - 'A');
170 for (int ndx = 0; ndx < numMembers; ndx++)
174 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0;
175 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0;
177 structType.addMember(std::string("m") + (char)('A' + ndx), memberTypes[ndx], flags);
180 return VarType(&structType, m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);
182 else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight)
184 const bool arraysOfArraysOk = (m_features & FEATURE_ARRAYS_OF_ARRAYS) != 0;
185 const int arrayLength = rnd.getInt(1, m_maxArrayLength);
186 VarType elementType = generateType(rnd, typeDepth, arraysOfArraysOk);
187 return VarType(elementType, arrayLength);
191 std::vector<glu::DataType> typeCandidates;
193 typeCandidates.push_back(glu::TYPE_FLOAT);
194 typeCandidates.push_back(glu::TYPE_INT);
195 typeCandidates.push_back(glu::TYPE_UINT);
196 typeCandidates.push_back(glu::TYPE_BOOL);
198 if (m_features & FEATURE_VECTORS)
200 typeCandidates.push_back(glu::TYPE_FLOAT_VEC2);
201 typeCandidates.push_back(glu::TYPE_FLOAT_VEC3);
202 typeCandidates.push_back(glu::TYPE_FLOAT_VEC4);
203 typeCandidates.push_back(glu::TYPE_INT_VEC2);
204 typeCandidates.push_back(glu::TYPE_INT_VEC3);
205 typeCandidates.push_back(glu::TYPE_INT_VEC4);
206 typeCandidates.push_back(glu::TYPE_UINT_VEC2);
207 typeCandidates.push_back(glu::TYPE_UINT_VEC3);
208 typeCandidates.push_back(glu::TYPE_UINT_VEC4);
209 typeCandidates.push_back(glu::TYPE_BOOL_VEC2);
210 typeCandidates.push_back(glu::TYPE_BOOL_VEC3);
211 typeCandidates.push_back(glu::TYPE_BOOL_VEC4);
214 if (m_features & FEATURE_MATRICES)
216 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2);
217 typeCandidates.push_back(glu::TYPE_FLOAT_MAT2X3);
218 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X2);
219 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3);
220 typeCandidates.push_back(glu::TYPE_FLOAT_MAT3X4);
221 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X2);
222 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4X3);
223 typeCandidates.push_back(glu::TYPE_FLOAT_MAT4);
226 glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end());
227 deUint32 flags = (m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u);
229 if (!glu::isDataTypeBoolOrBVec(type))
232 static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH };
233 flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]);
236 return VarType(type, flags);