1 #ifndef _VKTUNIFORMBLOCKCASE_HPP 2 #define _VKTUNIFORMBLOCKCASE_HPP 3 /*------------------------------------------------------------------------ 4 * Vulkan Conformance Tests 5 * ------------------------ 6 * 7 * Copyright (c) 2015 The Khronos Group Inc. 8 * Copyright (c) 2015 Samsung Electronics Co., Ltd. 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 "deSharedPtr.hpp" 28 #include "vktTestCase.hpp" 29 #include "tcuDefs.hpp" 30 #include "gluShaderUtil.hpp" 31 32 #include <map> 33 34 namespace vkt 35 { 36 namespace ubo 37 { 38 39 // Uniform block details. 40 41 enum UniformFlags 42 { 43 PRECISION_LOW = (1<<0), 44 PRECISION_MEDIUM = (1<<1), 45 PRECISION_HIGH = (1<<2), 46 PRECISION_MASK = PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH, 47 48 LAYOUT_SHARED = (1<<3), 49 LAYOUT_PACKED = (1<<4), 50 LAYOUT_STD140 = (1<<5), 51 LAYOUT_ROW_MAJOR = (1<<6), 52 LAYOUT_COLUMN_MAJOR = (1<<7), //!< \note Lack of both flags means column-major matrix. 53 LAYOUT_OFFSET = (1<<8), 54 LAYOUT_MASK = LAYOUT_SHARED|LAYOUT_PACKED|LAYOUT_STD140|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR|LAYOUT_OFFSET, 55 56 DECLARE_VERTEX = (1<<9), 57 DECLARE_FRAGMENT = (1<<10), 58 DECLARE_BOTH = DECLARE_VERTEX|DECLARE_FRAGMENT, 59 60 UNUSED_VERTEX = (1<<11), //!< Uniform or struct member is not read in vertex shader. 61 UNUSED_FRAGMENT = (1<<12), //!< Uniform or struct member is not read in fragment shader. 62 UNUSED_BOTH = UNUSED_VERTEX|UNUSED_FRAGMENT 63 }; 64 65 enum MatrixLoadFlags 66 { 67 LOAD_FULL_MATRIX = 0, 68 LOAD_MATRIX_COMPONENTS = 1, 69 }; 70 71 class StructType; 72 73 class VarType 74 { 75 public: 76 VarType (void); 77 VarType (const VarType& other); 78 VarType (glu::DataType basicType, deUint32 flags); 79 VarType (const VarType& elementType, int arraySize); 80 explicit VarType (const StructType* structPtr, deUint32 flags = 0u); 81 ~VarType (void); 82 isBasicType(void) const83 bool isBasicType (void) const { return m_type == TYPE_BASIC; } isArrayType(void) const84 bool isArrayType (void) const { return m_type == TYPE_ARRAY; } isStructType(void) const85 bool isStructType (void) const { return m_type == TYPE_STRUCT; } 86 getFlags(void) const87 deUint32 getFlags (void) const { return m_flags; } getBasicType(void) const88 glu::DataType getBasicType (void) const { return m_data.basicType; } 89 getElementType(void) const90 const VarType& getElementType (void) const { return *m_data.array.elementType; } getArraySize(void) const91 int getArraySize (void) const { return m_data.array.size; } 92 getStruct(void) const93 const StructType& getStruct (void) const { return *m_data.structPtr; } 94 95 VarType& operator= (const VarType& other); 96 97 private: 98 enum Type 99 { 100 TYPE_BASIC, 101 TYPE_ARRAY, 102 TYPE_STRUCT, 103 104 TYPE_LAST 105 }; 106 107 Type m_type; 108 deUint32 m_flags; 109 union Data 110 { 111 glu::DataType basicType; 112 struct 113 { 114 VarType* elementType; 115 int size; 116 } array; 117 const StructType* structPtr; 118 Data(void)119 Data (void) 120 { 121 array.elementType = DE_NULL; 122 array.size = 0; 123 }; 124 } m_data; 125 }; 126 127 class StructMember 128 { 129 public: StructMember(const std::string & name,const VarType & type,deUint32 flags)130 StructMember (const std::string& name, const VarType& type, deUint32 flags) 131 : m_name(name), m_type(type), m_flags(flags) 132 {} StructMember(void)133 StructMember (void) 134 : m_flags(0) 135 {} 136 getName(void) const137 const std::string& getName (void) const { return m_name; } getType(void) const138 const VarType& getType (void) const { return m_type; } getFlags(void) const139 deUint32 getFlags (void) const { return m_flags; } 140 141 private: 142 std::string m_name; 143 VarType m_type; 144 deUint32 m_flags; 145 }; 146 147 class StructType 148 { 149 public: 150 typedef std::vector<StructMember>::iterator Iterator; 151 typedef std::vector<StructMember>::const_iterator ConstIterator; 152 StructType(const std::string & typeName)153 StructType (const std::string& typeName) : m_typeName(typeName) {} ~StructType(void)154 ~StructType (void) {} 155 getTypeName(void) const156 const std::string& getTypeName (void) const { return m_typeName; } hasTypeName(void) const157 bool hasTypeName (void) const { return !m_typeName.empty(); } 158 begin(void)159 inline Iterator begin (void) { return m_members.begin(); } begin(void) const160 inline ConstIterator begin (void) const { return m_members.begin(); } end(void)161 inline Iterator end (void) { return m_members.end(); } end(void) const162 inline ConstIterator end (void) const { return m_members.end(); } 163 164 void addMember (const std::string& name, const VarType& type, deUint32 flags = 0); 165 166 private: 167 std::string m_typeName; 168 std::vector<StructMember> m_members; 169 }; 170 171 class Uniform 172 { 173 public: 174 Uniform (const std::string& name, const VarType& type, deUint32 flags = 0); 175 getName(void) const176 const std::string& getName (void) const { return m_name; } getType(void) const177 const VarType& getType (void) const { return m_type; } getFlags(void) const178 deUint32 getFlags (void) const { return m_flags; } 179 180 private: 181 std::string m_name; 182 VarType m_type; 183 deUint32 m_flags; 184 }; 185 186 class UniformBlock 187 { 188 public: 189 typedef std::vector<Uniform>::iterator Iterator; 190 typedef std::vector<Uniform>::const_iterator ConstIterator; 191 192 UniformBlock (const std::string& blockName); 193 getBlockName(void) const194 const std::string& getBlockName (void) const { return m_blockName; } getInstanceName(void) const195 const std::string& getInstanceName (void) const { return m_instanceName; } hasInstanceName(void) const196 bool hasInstanceName (void) const { return !m_instanceName.empty(); } isArray(void) const197 bool isArray (void) const { return m_arraySize > 0; } getArraySize(void) const198 int getArraySize (void) const { return m_arraySize; } getFlags(void) const199 deUint32 getFlags (void) const { return m_flags; } 200 setInstanceName(const std::string & name)201 void setInstanceName (const std::string& name) { m_instanceName = name; } setFlags(deUint32 flags)202 void setFlags (deUint32 flags) { m_flags = flags; } setArraySize(int arraySize)203 void setArraySize (int arraySize) { m_arraySize = arraySize; } addUniform(const Uniform & uniform)204 void addUniform (const Uniform& uniform) { m_uniforms.push_back(uniform); } 205 begin(void)206 inline Iterator begin (void) { return m_uniforms.begin(); } begin(void) const207 inline ConstIterator begin (void) const { return m_uniforms.begin(); } end(void)208 inline Iterator end (void) { return m_uniforms.end(); } end(void) const209 inline ConstIterator end (void) const { return m_uniforms.end(); } 210 211 private: 212 std::string m_blockName; 213 std::string m_instanceName; 214 std::vector<Uniform> m_uniforms; 215 int m_arraySize; //!< Array size or 0 if not interface block array. 216 deUint32 m_flags; 217 }; 218 219 typedef de::SharedPtr<StructType> StructTypeSP; 220 typedef de::SharedPtr<UniformBlock> UniformBlockSP; 221 222 class ShaderInterface 223 { 224 public: 225 ShaderInterface (void); 226 ~ShaderInterface (void); 227 228 StructType& allocStruct (const std::string& name); 229 void getNamedStructs (std::vector<const StructType*>& structs) const; 230 231 UniformBlock& allocBlock (const std::string& name); 232 getNumUniformBlocks(void) const233 int getNumUniformBlocks (void) const { return (int)m_uniformBlocks.size(); } getUniformBlock(int ndx) const234 const UniformBlock& getUniformBlock (int ndx) const { return *m_uniformBlocks[ndx]; } 235 236 private: 237 std::vector<StructTypeSP> m_structs; 238 std::vector<UniformBlockSP> m_uniformBlocks; 239 }; 240 241 struct BlockLayoutEntry 242 { BlockLayoutEntryvkt::ubo::BlockLayoutEntry243 BlockLayoutEntry (void) 244 : size (0) 245 , blockDeclarationNdx (-1) 246 , bindingNdx (-1) 247 , instanceNdx (-1) 248 { 249 } 250 251 std::string name; 252 int size; 253 std::vector<int> activeUniformIndices; 254 int blockDeclarationNdx; 255 int bindingNdx; 256 int instanceNdx; 257 }; 258 259 struct UniformLayoutEntry 260 { UniformLayoutEntryvkt::ubo::UniformLayoutEntry261 UniformLayoutEntry (void) 262 : type (glu::TYPE_LAST) 263 , size (0) 264 , blockLayoutNdx(-1) 265 , offset (-1) 266 , arrayStride (-1) 267 , matrixStride (-1) 268 , isRowMajor (false) 269 , instanceNdx (0) 270 { 271 } 272 273 std::string name; 274 glu::DataType type; 275 int size; 276 int blockLayoutNdx; 277 int offset; 278 int arrayStride; 279 int matrixStride; 280 bool isRowMajor; 281 int instanceNdx; 282 }; 283 284 class UniformLayout 285 { 286 public: 287 std::vector<BlockLayoutEntry> blocks; 288 std::vector<UniformLayoutEntry> uniforms; 289 290 int getUniformLayoutIndex (int blockDeclarationNdx, const std::string& name) const; 291 int getBlockLayoutIndex (int blockDeclarationNdx, int instanceNdx) const; 292 }; 293 294 class UniformBlockCase : public vkt::TestCase 295 { 296 public: 297 enum BufferMode 298 { 299 BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks. 300 BUFFERMODE_PER_BLOCK, //!< Per-block buffers 301 302 BUFFERMODE_LAST 303 }; 304 305 UniformBlockCase (tcu::TestContext& testCtx, 306 const std::string& name, 307 const std::string& description, 308 BufferMode bufferMode, 309 MatrixLoadFlags matrixLoadFlag, 310 bool shuffleUniformMembers = false); 311 ~UniformBlockCase (void); 312 313 virtual void initPrograms (vk::SourceCollections& programCollection) const; 314 virtual TestInstance* createInstance (Context& context) const; 315 316 protected: 317 void init (void); 318 319 BufferMode m_bufferMode; 320 ShaderInterface m_interface; 321 MatrixLoadFlags m_matrixLoadFlag; 322 const bool m_shuffleUniformMembers; //!< Used with explicit offsets to test out of order member offsets 323 324 private: 325 std::string m_vertShaderSource; 326 std::string m_fragShaderSource; 327 328 std::vector<deUint8> m_data; //!< Data. 329 std::map<int, void*> m_blockPointers; //!< Reference block pointers. 330 UniformLayout m_uniformLayout; //!< std140 layout. 331 }; 332 333 } // ubo 334 } // vkt 335 336 #endif // _VKTUNIFORMBLOCKCASE_HPP 337