1/*------------------------------------------------------------------------ 2 * Vulkan Conformance Tests 3 * ------------------------ 4 * 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 8 * 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 12 * 13 * http://www.apache.org/licenses/LICENSE-2.0 14 * 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. 20 * 21 *//*! 22 * \file 23 * \brief Random uniform block layout case. 24 *//*--------------------------------------------------------------------*/ 25 26#include "vktRandomUniformBlockCase.hpp" 27#include "deRandom.hpp" 28 29namespace vkt 30{ 31namespace ubo 32{ 33 34namespace 35{ 36 37static std::string genName (char first, char last, int ndx) 38{ 39 std::string str = ""; 40 int alphabetLen = last - first + 1; 41 42 while (ndx > alphabetLen) 43 { 44 str.insert(str.begin(), (char)(first + ((ndx - 1) % alphabetLen))); 45 ndx = (ndx - 1) / alphabetLen; 46 } 47 48 str.insert(str.begin(), (char)(first + (ndx % (alphabetLen + 1)) - 1)); 49 50 return str; 51} 52 53} // anonymous 54 55RandomUniformBlockCase::RandomUniformBlockCase (tcu::TestContext& testCtx, 56 const std::string& name, 57 const std::string& description, 58 BufferMode bufferMode, 59 deUint32 features, 60 deUint32 seed) 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) 71 , m_seed (seed) 72 , m_blockNdx (1) 73 , m_uniformNdx (1) 74 , m_structNdx (1) 75{ 76 de::Random rnd(m_seed); 77 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; 81 82 for (int ndx = 0; ndx < numShared; ndx++) 83 generateBlock(rnd, DECLARE_VERTEX | DECLARE_FRAGMENT); 84 85 for (int ndx = 0; ndx < numVtxBlocks; ndx++) 86 generateBlock(rnd, DECLARE_VERTEX); 87 88 for (int ndx = 0; ndx < numFragBlocks; ndx++) 89 generateBlock(rnd, DECLARE_FRAGMENT); 90 91 init(); 92} 93 94void RandomUniformBlockCase::generateBlock (de::Random& rnd, deUint32 layoutFlags) 95{ 96 DE_ASSERT(m_blockNdx <= 'z' - 'a'); 97 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); 102 103 if (numInstances > 0) 104 block.setArraySize(numInstances); 105 106 if (numInstances > 0 || rnd.getBool()) 107 block.setInstanceName(std::string("block") + (char)('A' + m_blockNdx)); 108 109 // Layout flag candidates. 110 std::vector<deUint32> layoutFlagCandidates; 111 layoutFlagCandidates.push_back(0); 112 113 if (m_features & FEATURE_STD140_LAYOUT) 114 layoutFlagCandidates.push_back(LAYOUT_STD140); 115 116 layoutFlags |= rnd.choose<deUint32>(layoutFlagCandidates.begin(), layoutFlagCandidates.end()); 117 118 if (m_features & FEATURE_MATRIX_LAYOUT) 119 { 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)]); 122 } 123 124 block.setFlags(layoutFlags); 125 126 for (int ndx = 0; ndx < numUniforms; ndx++) 127 generateUniform(rnd, block); 128 129 m_blockNdx += 1; 130} 131 132void RandomUniformBlockCase::generateUniform (de::Random& rnd, UniformBlock& block) 133{ 134 const float unusedVtxWeight = 0.15f; 135 const float unusedFragWeight = 0.15f; 136 bool unusedOk = (m_features & FEATURE_UNUSED_UNIFORMS) != 0; 137 deUint32 flags = 0; 138 std::string name = genName('a', 'z', m_uniformNdx); 139 VarType type = generateType(rnd, 0, true); 140 141 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0; 142 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0; 143 144 block.addUniform(Uniform(name, type, flags)); 145 146 m_uniformNdx += 1; 147} 148 149VarType RandomUniformBlockCase::generateType (de::Random& rnd, int typeDepth, bool arrayOk) 150{ 151 const float structWeight = 0.1f; 152 const float arrayWeight = 0.1f; 153 154 if (typeDepth < m_maxStructDepth && rnd.getFloat() < structWeight) 155 { 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); 161 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)); 165 166 StructType& structType = m_interface.allocStruct(std::string("s") + genName('A', 'Z', m_structNdx)); 167 m_structNdx += 1; 168 169 DE_ASSERT(numMembers <= 'Z' - 'A'); 170 for (int ndx = 0; ndx < numMembers; ndx++) 171 { 172 deUint32 flags = 0; 173 174 flags |= (unusedOk && rnd.getFloat() < unusedVtxWeight) ? UNUSED_VERTEX : 0; 175 flags |= (unusedOk && rnd.getFloat() < unusedFragWeight) ? UNUSED_FRAGMENT : 0; 176 177 structType.addMember(std::string("m") + (char)('A' + ndx), memberTypes[ndx], flags); 178 } 179 180 return VarType(&structType, m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u); 181 } 182 else if (m_maxArrayLength > 0 && arrayOk && rnd.getFloat() < arrayWeight) 183 { 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); 188 } 189 else 190 { 191 std::vector<glu::DataType> typeCandidates; 192 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); 197 198 if (m_features & FEATURE_VECTORS) 199 { 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); 212 } 213 214 if (m_features & FEATURE_MATRICES) 215 { 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); 224 } 225 226 glu::DataType type = rnd.choose<glu::DataType>(typeCandidates.begin(), typeCandidates.end()); 227 deUint32 flags = (m_shuffleUniformMembers ? static_cast<deUint32>(LAYOUT_OFFSET) : 0u); 228 229 if (!glu::isDataTypeBoolOrBVec(type)) 230 { 231 // Precision. 232 static const deUint32 precisionCandidates[] = { PRECISION_LOW, PRECISION_MEDIUM, PRECISION_HIGH }; 233 flags |= rnd.choose<deUint32>(&precisionCandidates[0], &precisionCandidates[DE_LENGTH_OF_ARRAY(precisionCandidates)]); 234 } 235 236 return VarType(type, flags); 237 } 238} 239 240} // ubo 241} // vkt 242