1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES 3.1 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 Uniform block tests. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "es31fUniformBlockTests.hpp" 25 #include "glsUniformBlockCase.hpp" 26 #include "glsRandomUniformBlockCase.hpp" 27 #include "tcuCommandLine.hpp" 28 #include "deRandom.hpp" 29 #include "deStringUtil.hpp" 30 31 using std::string; 32 using std::vector; 33 34 namespace deqp 35 { 36 namespace gles31 37 { 38 namespace Functional 39 { 40 namespace 41 { 42 43 using gls::UniformBlockCase; 44 using gls::RandomUniformBlockCase; 45 using namespace gls::ub; 46 47 void createRandomCaseGroup (tcu::TestCaseGroup* parentGroup, Context& context, const char* groupName, const char* description, UniformBlockCase::BufferMode bufferMode, deUint32 features, int numCases, deUint32 baseSeed) 48 { 49 tcu::TestCaseGroup* group = new tcu::TestCaseGroup(context.getTestContext(), groupName, description); 50 parentGroup->addChild(group); 51 52 baseSeed += (deUint32)context.getTestContext().getCommandLine().getBaseSeed(); 53 54 for (int ndx = 0; ndx < numCases; ndx++) 55 group->addChild(new RandomUniformBlockCase(context.getTestContext(), context.getRenderContext(), glu::GLSL_VERSION_310_ES, 56 de::toString(ndx).c_str(), "", bufferMode, features, (deUint32)ndx+baseSeed)); 57 } 58 59 class BlockBasicTypeCase : public UniformBlockCase 60 { 61 public: 62 BlockBasicTypeCase (Context& context, const char* name, const char* description, const VarType& type, deUint32 layoutFlags, int numInstances) 63 : UniformBlockCase(context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_310_ES, BUFFERMODE_PER_BLOCK) 64 { 65 UniformBlock& block = m_interface.allocBlock("Block"); 66 block.addUniform(Uniform("var", type, 0)); 67 block.setFlags(layoutFlags); 68 69 if (numInstances > 0) 70 { 71 block.setArraySize(numInstances); 72 block.setInstanceName("block"); 73 } 74 } 75 }; 76 77 static void createBlockBasicTypeCases (tcu::TestCaseGroup* group, Context& context, const char* name, const VarType& type, deUint32 layoutFlags, int numInstances = 0) 78 { 79 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_vertex").c_str(), "", type, layoutFlags|DECLARE_VERTEX, numInstances)); 80 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_fragment").c_str(), "", type, layoutFlags|DECLARE_FRAGMENT, numInstances)); 81 82 if (!(layoutFlags & LAYOUT_PACKED)) 83 group->addChild(new BlockBasicTypeCase(context, (string(name) + "_both").c_str(), "", type, layoutFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, numInstances)); 84 } 85 86 class Block2LevelStructArrayCase : public UniformBlockCase 87 { 88 public: 89 Block2LevelStructArrayCase (Context& context, const char* name, const char* description, deUint32 layoutFlags, BufferMode bufferMode, int numInstances) 90 : UniformBlockCase (context.getTestContext(), context.getRenderContext(), name, description, glu::GLSL_VERSION_310_ES, bufferMode) 91 , m_layoutFlags (layoutFlags) 92 , m_numInstances (numInstances) 93 { 94 } 95 96 void init (void) 97 { 98 StructType& typeS = m_interface.allocStruct("S"); 99 typeS.addMember("a", VarType(glu::TYPE_UINT_VEC3, PRECISION_HIGH), UNUSED_BOTH); 100 typeS.addMember("b", VarType(VarType(glu::TYPE_FLOAT_MAT2, PRECISION_MEDIUM), 4)); 101 typeS.addMember("c", VarType(glu::TYPE_UINT, PRECISION_LOW)); 102 103 UniformBlock& block = m_interface.allocBlock("Block"); 104 block.addUniform(Uniform("u", VarType(glu::TYPE_INT, PRECISION_MEDIUM))); 105 block.addUniform(Uniform("s", VarType(VarType(VarType(&typeS), 3), 2))); 106 block.addUniform(Uniform("v", VarType(glu::TYPE_FLOAT_VEC2, PRECISION_MEDIUM))); 107 block.setFlags(m_layoutFlags); 108 109 if (m_numInstances > 0) 110 { 111 block.setInstanceName("block"); 112 block.setArraySize(m_numInstances); 113 } 114 } 115 116 private: 117 deUint32 m_layoutFlags; 118 int m_numInstances; 119 }; 120 121 } // anonymous 122 123 UniformBlockTests::UniformBlockTests (Context& context) 124 : TestCaseGroup(context, "ubo", "Uniform Block tests") 125 { 126 } 127 128 UniformBlockTests::~UniformBlockTests (void) 129 { 130 } 131 132 void UniformBlockTests::init (void) 133 { 134 static const glu::DataType basicTypes[] = 135 { 136 glu::TYPE_FLOAT, 137 glu::TYPE_FLOAT_VEC2, 138 glu::TYPE_FLOAT_VEC3, 139 glu::TYPE_FLOAT_VEC4, 140 glu::TYPE_INT, 141 glu::TYPE_INT_VEC2, 142 glu::TYPE_INT_VEC3, 143 glu::TYPE_INT_VEC4, 144 glu::TYPE_UINT, 145 glu::TYPE_UINT_VEC2, 146 glu::TYPE_UINT_VEC3, 147 glu::TYPE_UINT_VEC4, 148 glu::TYPE_BOOL, 149 glu::TYPE_BOOL_VEC2, 150 glu::TYPE_BOOL_VEC3, 151 glu::TYPE_BOOL_VEC4, 152 glu::TYPE_FLOAT_MAT2, 153 glu::TYPE_FLOAT_MAT3, 154 glu::TYPE_FLOAT_MAT4, 155 glu::TYPE_FLOAT_MAT2X3, 156 glu::TYPE_FLOAT_MAT2X4, 157 glu::TYPE_FLOAT_MAT3X2, 158 glu::TYPE_FLOAT_MAT3X4, 159 glu::TYPE_FLOAT_MAT4X2, 160 glu::TYPE_FLOAT_MAT4X3 161 }; 162 163 static const struct 164 { 165 const char* name; 166 deUint32 flags; 167 } layoutFlags[] = 168 { 169 { "shared", LAYOUT_SHARED }, 170 { "packed", LAYOUT_PACKED }, 171 { "std140", LAYOUT_STD140 } 172 }; 173 174 static const struct 175 { 176 const char* name; 177 deUint32 flags; 178 } matrixFlags[] = 179 { 180 { "row_major", LAYOUT_ROW_MAJOR }, 181 { "column_major", LAYOUT_COLUMN_MAJOR } 182 }; 183 184 static const struct 185 { 186 const char* name; 187 UniformBlockCase::BufferMode mode; 188 } bufferModes[] = 189 { 190 { "per_block_buffer", UniformBlockCase::BUFFERMODE_PER_BLOCK }, 191 { "single_buffer", UniformBlockCase::BUFFERMODE_SINGLE } 192 }; 193 194 // ubo.2_level_array 195 { 196 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_array", "2-level basic array variable in single buffer"); 197 addChild(nestedArrayGroup); 198 199 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) 200 { 201 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""); 202 nestedArrayGroup->addChild(layoutGroup); 203 204 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++) 205 { 206 const glu::DataType type = basicTypes[basicTypeNdx]; 207 const char* typeName = glu::getDataTypeName(type); 208 const int childSize = 4; 209 const int parentSize = 3; 210 const VarType childType (VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize); 211 const VarType parentType (childType, parentSize); 212 213 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, layoutFlags[layoutFlagNdx].flags); 214 215 if (glu::isDataTypeMatrix(type)) 216 { 217 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++) 218 createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), 219 parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags); 220 } 221 } 222 } 223 } 224 225 // ubo.3_level_array 226 { 227 tcu::TestCaseGroup* nestedArrayGroup = new tcu::TestCaseGroup(m_testCtx, "3_level_array", "3-level basic array variable in single buffer"); 228 addChild(nestedArrayGroup); 229 230 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) 231 { 232 tcu::TestCaseGroup* layoutGroup = new tcu::TestCaseGroup(m_testCtx, layoutFlags[layoutFlagNdx].name, ""); 233 nestedArrayGroup->addChild(layoutGroup); 234 235 for (int basicTypeNdx = 0; basicTypeNdx < DE_LENGTH_OF_ARRAY(basicTypes); basicTypeNdx++) 236 { 237 const glu::DataType type = basicTypes[basicTypeNdx]; 238 const char* typeName = glu::getDataTypeName(type); 239 const int childSize0 = 2; 240 const int childSize1 = 4; 241 const int parentSize = 3; 242 const VarType childType0 (VarType(type, glu::isDataTypeBoolOrBVec(type) ? 0 : PRECISION_HIGH), childSize0); 243 const VarType childType1 (childType0, childSize1); 244 const VarType parentType (childType1, parentSize); 245 246 createBlockBasicTypeCases(layoutGroup, m_context, typeName, parentType, layoutFlags[layoutFlagNdx].flags); 247 248 if (glu::isDataTypeMatrix(type)) 249 { 250 for (int matFlagNdx = 0; matFlagNdx < DE_LENGTH_OF_ARRAY(matrixFlags); matFlagNdx++) 251 createBlockBasicTypeCases(layoutGroup, m_context, (string(matrixFlags[matFlagNdx].name) + "_" + typeName).c_str(), 252 parentType, layoutFlags[layoutFlagNdx].flags|matrixFlags[matFlagNdx].flags); 253 } 254 } 255 } 256 } 257 258 // ubo.2_level_struct_array 259 { 260 tcu::TestCaseGroup* structArrayArrayGroup = new tcu::TestCaseGroup(m_testCtx, "2_level_struct_array", "Struct array in one uniform block"); 261 addChild(structArrayArrayGroup); 262 263 for (int modeNdx = 0; modeNdx < DE_LENGTH_OF_ARRAY(bufferModes); modeNdx++) 264 { 265 tcu::TestCaseGroup* modeGroup = new tcu::TestCaseGroup(m_testCtx, bufferModes[modeNdx].name, ""); 266 structArrayArrayGroup->addChild(modeGroup); 267 268 for (int layoutFlagNdx = 0; layoutFlagNdx < DE_LENGTH_OF_ARRAY(layoutFlags); layoutFlagNdx++) 269 { 270 for (int isArray = 0; isArray < 2; isArray++) 271 { 272 std::string baseName = layoutFlags[layoutFlagNdx].name; 273 deUint32 baseFlags = layoutFlags[layoutFlagNdx].flags; 274 275 if (bufferModes[modeNdx].mode == UniformBlockCase::BUFFERMODE_SINGLE && isArray == 0) 276 continue; // Doesn't make sense to add this variant. 277 278 if (isArray) 279 baseName += "_instance_array"; 280 281 modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_vertex").c_str(), "", baseFlags|DECLARE_VERTEX, bufferModes[modeNdx].mode, isArray ? 3 : 0)); 282 modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_fragment").c_str(), "", baseFlags|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0)); 283 284 if (!(baseFlags & LAYOUT_PACKED)) 285 modeGroup->addChild(new Block2LevelStructArrayCase(m_context, (baseName + "_both").c_str(), "", baseFlags|DECLARE_VERTEX|DECLARE_FRAGMENT, bufferModes[modeNdx].mode, isArray ? 3 : 0)); 286 } 287 } 288 } 289 } 290 291 // ubo.random 292 { 293 const deUint32 allShaders = FEATURE_VERTEX_BLOCKS|FEATURE_FRAGMENT_BLOCKS|FEATURE_SHARED_BLOCKS; 294 const deUint32 allLayouts = FEATURE_PACKED_LAYOUT|FEATURE_SHARED_LAYOUT|FEATURE_STD140_LAYOUT; 295 const deUint32 allBasicTypes = FEATURE_VECTORS|FEATURE_MATRICES; 296 const deUint32 unused = FEATURE_UNUSED_MEMBERS|FEATURE_UNUSED_UNIFORMS; 297 const deUint32 matFlags = FEATURE_MATRIX_LAYOUT; 298 const deUint32 basicTypeArrays = allShaders|allLayouts|unused|allBasicTypes|matFlags|FEATURE_ARRAYS|FEATURE_ARRAYS_OF_ARRAYS; 299 const deUint32 allFeatures = ~0u; 300 301 tcu::TestCaseGroup* randomGroup = new tcu::TestCaseGroup(m_testCtx, "random", "Random Uniform Block cases"); 302 addChild(randomGroup); 303 304 createRandomCaseGroup(randomGroup, m_context, "basic_type_arrays", "Arrays, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, basicTypeArrays, 25, 1150); 305 createRandomCaseGroup(randomGroup, m_context, "all_per_block_buffers", "All random features, per-block buffers", UniformBlockCase::BUFFERMODE_PER_BLOCK, allFeatures, 50, 11200); 306 createRandomCaseGroup(randomGroup, m_context, "all_shared_buffer", "All random features, shared buffer", UniformBlockCase::BUFFERMODE_SINGLE, allFeatures, 50, 11250); 307 } 308 } 309 310 } // Functional 311 } // gles31 312 } // deqp 313