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 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 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 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 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 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 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