1 #ifndef _GLCUNIFORMBLOCKCASE_HPP 2 #define _GLCUNIFORMBLOCKCASE_HPP 3 /*------------------------------------------------------------------------- 4 * OpenGL Conformance Test Suite 5 * ----------------------------- 6 * 7 * Copyright (c) 2016 Google Inc. 8 * Copyright (c) 2016 The Khronos Group Inc. 9 * 10 * Licensed under the Apache License, Version 2.0 (the "License"); 11 * you may not use this file except in compliance with the License. 12 * You may obtain a copy of the License at 13 * 14 * http://www.apache.org/licenses/LICENSE-2.0 15 * 16 * Unless required by applicable law or agreed to in writing, software 17 * distributed under the License is distributed on an "AS IS" BASIS, 18 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 19 * See the License for the specific language governing permissions and 20 * limitations under the License. 21 * 22 */ /*! 23 * \file 24 * \brief Uniform block tests. 25 */ /*-------------------------------------------------------------------*/ 26 27 #include "glcTestCase.hpp" 28 #include "gluShaderProgram.hpp" 29 #include "gluShaderUtil.hpp" 30 #include "tcuDefs.hpp" 31 32 namespace deqp 33 { 34 35 // Uniform block details. 36 namespace ub 37 { 38 39 enum UniformFlags 40 { 41 PRECISION_LOW = (1 << 0), 42 PRECISION_MEDIUM = (1 << 1), 43 PRECISION_HIGH = (1 << 2), 44 PRECISION_MASK = PRECISION_LOW | PRECISION_MEDIUM | PRECISION_HIGH, 45 46 LAYOUT_SHARED = (1 << 3), 47 LAYOUT_PACKED = (1 << 4), 48 LAYOUT_STD140 = (1 << 5), 49 LAYOUT_ROW_MAJOR = (1 << 6), 50 LAYOUT_COLUMN_MAJOR = (1 << 7), //!< \note Lack of both flags means column-major matrix. 51 LAYOUT_MASK = LAYOUT_SHARED | LAYOUT_PACKED | LAYOUT_STD140 | LAYOUT_ROW_MAJOR | LAYOUT_COLUMN_MAJOR, 52 53 DECLARE_VERTEX = (1 << 8), 54 DECLARE_FRAGMENT = (1 << 9), 55 DECLARE_BOTH = DECLARE_VERTEX | DECLARE_FRAGMENT, 56 57 UNUSED_VERTEX = (1 << 10), //!< Uniform or struct member is not read in vertex shader. 58 UNUSED_FRAGMENT = (1 << 11), //!< Uniform or struct member is not read in fragment shader. 59 UNUSED_BOTH = UNUSED_VERTEX | UNUSED_FRAGMENT 60 }; 61 62 // \todo [2012-07-25 pyry] Use glu::VarType. 63 64 class StructType; 65 66 class VarType 67 { 68 public: 69 VarType(void); 70 VarType(const VarType &other); 71 VarType(glu::DataType basicType, uint32_t flags); 72 VarType(const VarType &elementType, int arraySize); 73 explicit VarType(const StructType *structPtr); 74 ~VarType(void); 75 isBasicType(void) const76 bool isBasicType(void) const 77 { 78 return m_type == TYPE_BASIC; 79 } isArrayType(void) const80 bool isArrayType(void) const 81 { 82 return m_type == TYPE_ARRAY; 83 } isStructType(void) const84 bool isStructType(void) const 85 { 86 return m_type == TYPE_STRUCT; 87 } 88 getFlags(void) const89 uint32_t getFlags(void) const 90 { 91 return m_flags; 92 } getBasicType(void) const93 glu::DataType getBasicType(void) const 94 { 95 return m_data.basicType; 96 } 97 getElementType(void) const98 const VarType &getElementType(void) const 99 { 100 return *m_data.array.elementType; 101 } getArraySize(void) const102 int getArraySize(void) const 103 { 104 return m_data.array.size; 105 } 106 getStruct(void) const107 const StructType &getStruct(void) const 108 { 109 return *m_data.structPtr; 110 } 111 112 VarType &operator=(const VarType &other); 113 114 private: 115 enum Type 116 { 117 TYPE_BASIC, 118 TYPE_ARRAY, 119 TYPE_STRUCT, 120 121 TYPE_LAST 122 }; 123 124 Type m_type; 125 uint32_t m_flags; 126 union Data 127 { 128 glu::DataType basicType; 129 struct 130 { 131 VarType *elementType; 132 int size; 133 } array; 134 const StructType *structPtr; 135 Data(void)136 Data(void) 137 { 138 array.elementType = DE_NULL; 139 array.size = 0; 140 } 141 } m_data; 142 }; 143 144 class StructMember 145 { 146 public: StructMember(const char * name,const VarType & type,uint32_t flags)147 StructMember(const char *name, const VarType &type, uint32_t flags) : m_name(name), m_type(type), m_flags(flags) 148 { 149 } StructMember(void)150 StructMember(void) : m_flags(0) 151 { 152 } 153 getName(void) const154 const char *getName(void) const 155 { 156 return m_name.c_str(); 157 } getType(void) const158 const VarType &getType(void) const 159 { 160 return m_type; 161 } getFlags(void) const162 uint32_t getFlags(void) const 163 { 164 return m_flags; 165 } 166 167 private: 168 std::string m_name; 169 VarType m_type; 170 uint32_t m_flags; 171 }; 172 173 class StructType 174 { 175 public: 176 typedef std::vector<StructMember>::iterator Iterator; 177 typedef std::vector<StructMember>::const_iterator ConstIterator; 178 StructType(const char * typeName)179 StructType(const char *typeName) : m_typeName(typeName) 180 { 181 } ~StructType(void)182 ~StructType(void) 183 { 184 } 185 getTypeName(void) const186 const char *getTypeName(void) const 187 { 188 return m_typeName.empty() ? DE_NULL : m_typeName.c_str(); 189 } 190 begin(void)191 inline Iterator begin(void) 192 { 193 return m_members.begin(); 194 } begin(void) const195 inline ConstIterator begin(void) const 196 { 197 return m_members.begin(); 198 } end(void)199 inline Iterator end(void) 200 { 201 return m_members.end(); 202 } end(void) const203 inline ConstIterator end(void) const 204 { 205 return m_members.end(); 206 } 207 208 void addMember(const char *name, const VarType &type, uint32_t flags = 0); 209 210 private: 211 std::string m_typeName; 212 std::vector<StructMember> m_members; 213 }; 214 215 class Uniform 216 { 217 public: 218 Uniform(const char *name, const VarType &type, uint32_t flags = 0); 219 getName(void) const220 const char *getName(void) const 221 { 222 return m_name.c_str(); 223 } getType(void) const224 const VarType &getType(void) const 225 { 226 return m_type; 227 } getFlags(void) const228 uint32_t getFlags(void) const 229 { 230 return m_flags; 231 } 232 233 private: 234 std::string m_name; 235 VarType m_type; 236 uint32_t m_flags; 237 }; 238 239 class UniformBlock 240 { 241 public: 242 typedef std::vector<Uniform>::iterator Iterator; 243 typedef std::vector<Uniform>::const_iterator ConstIterator; 244 245 UniformBlock(const char *blockName); 246 getBlockName(void) const247 const char *getBlockName(void) const 248 { 249 return m_blockName.c_str(); 250 } getInstanceName(void) const251 const char *getInstanceName(void) const 252 { 253 return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str(); 254 } isArray(void) const255 bool isArray(void) const 256 { 257 return m_arraySize > 0; 258 } getArraySize(void) const259 int getArraySize(void) const 260 { 261 return m_arraySize; 262 } getFlags(void) const263 uint32_t getFlags(void) const 264 { 265 return m_flags; 266 } 267 setInstanceName(const char * name)268 void setInstanceName(const char *name) 269 { 270 m_instanceName = name; 271 } setFlags(uint32_t flags)272 void setFlags(uint32_t flags) 273 { 274 m_flags = flags; 275 } setArraySize(int arraySize)276 void setArraySize(int arraySize) 277 { 278 m_arraySize = arraySize; 279 } addUniform(const Uniform & uniform)280 void addUniform(const Uniform &uniform) 281 { 282 m_uniforms.push_back(uniform); 283 } 284 begin(void)285 inline Iterator begin(void) 286 { 287 return m_uniforms.begin(); 288 } begin(void) const289 inline ConstIterator begin(void) const 290 { 291 return m_uniforms.begin(); 292 } end(void)293 inline Iterator end(void) 294 { 295 return m_uniforms.end(); 296 } end(void) const297 inline ConstIterator end(void) const 298 { 299 return m_uniforms.end(); 300 } 301 302 private: 303 std::string m_blockName; 304 std::string m_instanceName; 305 std::vector<Uniform> m_uniforms; 306 int m_arraySize; //!< Array size or 0 if not interface block array. 307 uint32_t m_flags; 308 }; 309 310 class ShaderInterface 311 { 312 public: 313 ShaderInterface(void); 314 ~ShaderInterface(void); 315 316 StructType &allocStruct(const char *name); 317 const StructType *findStruct(const char *name) const; 318 void getNamedStructs(std::vector<const StructType *> &structs) const; 319 320 UniformBlock &allocBlock(const char *name); 321 getNumUniformBlocks(void) const322 int getNumUniformBlocks(void) const 323 { 324 return (int)m_uniformBlocks.size(); 325 } getUniformBlock(int ndx) const326 const UniformBlock &getUniformBlock(int ndx) const 327 { 328 return *m_uniformBlocks[ndx]; 329 } 330 331 private: 332 std::vector<StructType *> m_structs; 333 std::vector<UniformBlock *> m_uniformBlocks; 334 }; 335 336 class UniformLayout; 337 338 } // namespace ub 339 340 class UniformBlockCase : public TestCase 341 { 342 public: 343 enum BufferMode 344 { 345 BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks. 346 BUFFERMODE_PER_BLOCK, //!< Per-block buffers 347 348 BUFFERMODE_LAST 349 }; 350 351 UniformBlockCase(Context &context, const char *name, const char *description, glu::GLSLVersion glslVersion, 352 BufferMode bufferMode); 353 ~UniformBlockCase(void); 354 355 IterateResult iterate(void); 356 357 protected: 358 bool compareStd140Blocks(const ub::UniformLayout &refLayout, const ub::UniformLayout &cmpLayout) const; 359 bool compareSharedBlocks(const ub::UniformLayout &refLayout, const ub::UniformLayout &cmpLayout) const; 360 bool compareTypes(const ub::UniformLayout &refLayout, const ub::UniformLayout &cmpLayout) const; 361 bool checkLayoutIndices(const ub::UniformLayout &layout) const; 362 bool checkLayoutBounds(const ub::UniformLayout &layout) const; 363 bool checkIndexQueries(uint32_t program, const ub::UniformLayout &layout) const; 364 365 bool render(glu::ShaderProgram &program) const; 366 367 glu::GLSLVersion m_glslVersion; 368 BufferMode m_bufferMode; 369 ub::ShaderInterface m_interface; 370 }; 371 372 } // namespace deqp 373 374 #endif // _GLCUNIFORMBLOCKCASE_HPP 375