Jarkko Poyry | 3c82736 | 2014-09-02 11:48:52 +0300 | [diff] [blame] | 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 |