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_STD430 = (1<<9), 55 LAYOUT_SCALAR = (1<<10), 56 LAYOUT_MASK = LAYOUT_SHARED|LAYOUT_PACKED|LAYOUT_STD140|LAYOUT_STD430|LAYOUT_SCALAR|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR|LAYOUT_OFFSET, 57 58 DECLARE_VERTEX = (1<<11), 59 DECLARE_FRAGMENT = (1<<12), 60 DECLARE_BOTH = DECLARE_VERTEX|DECLARE_FRAGMENT, 61 62 UNUSED_VERTEX = (1<<13), //!< Uniform or struct member is not read in vertex shader. 63 UNUSED_FRAGMENT = (1<<14), //!< Uniform or struct member is not read in fragment shader. 64 UNUSED_BOTH = UNUSED_VERTEX|UNUSED_FRAGMENT, 65 66 LAYOUT_16BIT_STORAGE= (1<<15), //!< Support VK_KHR_16bit_storage extension 67 LAYOUT_8BIT_STORAGE = (1<<16), //!< Support VK_KHR_8bit_storage extension 68 69 LAYOUT_DESCRIPTOR_INDEXING = (1 << 17), //!< Support VK_KHR_descriptor_indexing extension 70 }; 71 72 enum MatrixLoadFlags 73 { 74 LOAD_FULL_MATRIX = 0, 75 LOAD_MATRIX_COMPONENTS = 1, 76 }; 77 78 class StructType; 79 80 class VarType 81 { 82 public: 83 VarType (void); 84 VarType (const VarType& other); 85 VarType (glu::DataType basicType, deUint32 flags); 86 VarType (const VarType& elementType, int arraySize); 87 explicit VarType (const StructType* structPtr, deUint32 flags = 0u); 88 ~VarType (void); 89 isBasicType(void) const90 bool isBasicType (void) const { return m_type == TYPE_BASIC; } isArrayType(void) const91 bool isArrayType (void) const { return m_type == TYPE_ARRAY; } isStructType(void) const92 bool isStructType (void) const { return m_type == TYPE_STRUCT; } 93 getFlags(void) const94 deUint32 getFlags (void) const { return m_flags; } getBasicType(void) const95 glu::DataType getBasicType (void) const { return m_data.basicType; } 96 getElementType(void) const97 const VarType& getElementType (void) const { return *m_data.array.elementType; } getArraySize(void) const98 int getArraySize (void) const { return m_data.array.size; } 99 getStruct(void) const100 const StructType& getStruct (void) const { return *m_data.structPtr; } getStructPtr(void) const101 const StructType* getStructPtr (void) const { DE_ASSERT(isStructType()); return m_data.structPtr; } 102 103 VarType& operator= (const VarType& other); 104 105 private: 106 enum Type 107 { 108 TYPE_BASIC, 109 TYPE_ARRAY, 110 TYPE_STRUCT, 111 112 TYPE_LAST 113 }; 114 115 Type m_type; 116 deUint32 m_flags; 117 union Data 118 { 119 glu::DataType basicType; 120 struct 121 { 122 VarType* elementType; 123 int size; 124 } array; 125 const StructType* structPtr; 126 Data(void)127 Data (void) 128 { 129 array.elementType = DE_NULL; 130 array.size = 0; 131 } 132 } m_data; 133 }; 134 135 class StructMember 136 { 137 public: StructMember(const std::string & name,const VarType & type,deUint32 flags)138 StructMember (const std::string& name, const VarType& type, deUint32 flags) 139 : m_name(name), m_type(type), m_flags(flags) 140 {} StructMember(void)141 StructMember (void) 142 : m_flags(0) 143 {} 144 getName(void) const145 const std::string& getName (void) const { return m_name; } getType(void) const146 const VarType& getType (void) const { return m_type; } getFlags(void) const147 deUint32 getFlags (void) const { return m_flags; } 148 149 private: 150 std::string m_name; 151 VarType m_type; 152 deUint32 m_flags; 153 }; 154 155 class StructType 156 { 157 public: 158 typedef std::vector<StructMember>::iterator Iterator; 159 typedef std::vector<StructMember>::const_iterator ConstIterator; 160 StructType(const std::string & typeName)161 StructType (const std::string& typeName) : m_typeName(typeName) {} ~StructType(void)162 ~StructType (void) {} 163 getTypeName(void) const164 const std::string& getTypeName (void) const { return m_typeName; } hasTypeName(void) const165 bool hasTypeName (void) const { return !m_typeName.empty(); } 166 begin(void)167 inline Iterator begin (void) { return m_members.begin(); } begin(void) const168 inline ConstIterator begin (void) const { return m_members.begin(); } end(void)169 inline Iterator end (void) { return m_members.end(); } end(void) const170 inline ConstIterator end (void) const { return m_members.end(); } 171 172 void addMember (const std::string& name, const VarType& type, deUint32 flags = 0); 173 174 private: 175 std::string m_typeName; 176 std::vector<StructMember> m_members; 177 }; 178 179 class Uniform 180 { 181 public: 182 Uniform (const std::string& name, const VarType& type, deUint32 flags = 0); 183 getName(void) const184 const std::string& getName (void) const { return m_name; } getType(void) const185 const VarType& getType (void) const { return m_type; } getFlags(void) const186 deUint32 getFlags (void) const { return m_flags; } 187 188 private: 189 std::string m_name; 190 VarType m_type; 191 deUint32 m_flags; 192 }; 193 194 class UniformBlock 195 { 196 public: 197 typedef std::vector<Uniform>::iterator Iterator; 198 typedef std::vector<Uniform>::const_iterator ConstIterator; 199 200 UniformBlock (const std::string& blockName); 201 getBlockName(void) const202 const std::string& getBlockName (void) const { return m_blockName; } getInstanceName(void) const203 const std::string& getInstanceName (void) const { return m_instanceName; } hasInstanceName(void) const204 bool hasInstanceName (void) const { return !m_instanceName.empty(); } isArray(void) const205 bool isArray (void) const { return m_arraySize > 0; } getArraySize(void) const206 int getArraySize (void) const { return m_arraySize; } getFlags(void) const207 deUint32 getFlags (void) const { return m_flags; } 208 setInstanceName(const std::string & name)209 void setInstanceName (const std::string& name) { m_instanceName = name; } setFlags(deUint32 flags)210 void setFlags (deUint32 flags) { m_flags = flags; } setArraySize(int arraySize)211 void setArraySize (int arraySize) { m_arraySize = arraySize; } addUniform(const Uniform & uniform)212 void addUniform (const Uniform& uniform) { m_uniforms.push_back(uniform); } 213 begin(void)214 inline Iterator begin (void) { return m_uniforms.begin(); } begin(void) const215 inline ConstIterator begin (void) const { return m_uniforms.begin(); } end(void)216 inline Iterator end (void) { return m_uniforms.end(); } end(void) const217 inline ConstIterator end (void) const { return m_uniforms.end(); } 218 219 private: 220 std::string m_blockName; 221 std::string m_instanceName; 222 std::vector<Uniform> m_uniforms; 223 int m_arraySize; //!< Array size or 0 if not interface block array. 224 deUint32 m_flags; 225 }; 226 227 typedef de::SharedPtr<StructType> StructTypeSP; 228 typedef de::SharedPtr<UniformBlock> UniformBlockSP; 229 230 class ShaderInterface 231 { 232 public: 233 ShaderInterface (void); 234 ~ShaderInterface (void); 235 236 StructType& allocStruct (const std::string& name); 237 void getNamedStructs (std::vector<const StructType*>& structs) const; 238 239 UniformBlock& allocBlock (const std::string& name); 240 getNumUniformBlocks(void) const241 int getNumUniformBlocks (void) const { return (int)m_uniformBlocks.size(); } getUniformBlock(int ndx) const242 const UniformBlock& getUniformBlock (int ndx) const { return *m_uniformBlocks[ndx]; } 243 bool usesBlockLayout (UniformFlags layoutFlag) const; 244 245 private: 246 std::vector<StructTypeSP> m_structs; 247 std::vector<UniformBlockSP> m_uniformBlocks; 248 }; 249 250 struct BlockLayoutEntry 251 { BlockLayoutEntryvkt::ubo::BlockLayoutEntry252 BlockLayoutEntry (void) 253 : size (0) 254 , blockDeclarationNdx (-1) 255 , bindingNdx (-1) 256 , instanceNdx (-1) 257 { 258 } 259 260 std::string name; 261 int size; 262 std::vector<int> activeUniformIndices; 263 int blockDeclarationNdx; 264 int bindingNdx; 265 int instanceNdx; 266 }; 267 268 struct UniformLayoutEntry 269 { UniformLayoutEntryvkt::ubo::UniformLayoutEntry270 UniformLayoutEntry (void) 271 : type (glu::TYPE_LAST) 272 , size (0) 273 , blockNdx (-1) 274 , offset (-1) 275 , arraySize (-1) 276 , arrayStride (-1) 277 , matrixStride (-1) 278 , topLevelArraySize (-1) 279 , topLevelArrayStride (-1) 280 , isRowMajor (false) 281 , instanceNdx (0) 282 { 283 } 284 285 std::string name; 286 glu::DataType type; 287 int size; 288 int blockNdx; 289 int offset; 290 int arraySize; 291 int arrayStride; 292 int matrixStride; 293 int topLevelArraySize; 294 int topLevelArrayStride; 295 bool isRowMajor; 296 int instanceNdx; 297 }; 298 299 class UniformLayout 300 { 301 public: 302 std::vector<BlockLayoutEntry> blocks; 303 std::vector<UniformLayoutEntry> uniforms; 304 305 int getUniformLayoutIndex (int blockDeclarationNdx, const std::string& name) const; 306 int getBlockLayoutIndex (int blockDeclarationNdx, int instanceNdx) const; 307 }; 308 309 class UniformBlockCase : public vkt::TestCase 310 { 311 public: 312 enum BufferMode 313 { 314 BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks. 315 BUFFERMODE_PER_BLOCK, //!< Per-block buffers 316 317 BUFFERMODE_LAST 318 }; 319 320 UniformBlockCase (tcu::TestContext& testCtx, 321 const std::string& name, 322 const std::string& description, 323 BufferMode bufferMode, 324 MatrixLoadFlags matrixLoadFlag, 325 bool shuffleUniformMembers = false); 326 ~UniformBlockCase (void); 327 328 virtual void delayedInit (void); 329 virtual void initPrograms (vk::SourceCollections& programCollection) const; 330 virtual TestInstance* createInstance (Context& context) const; usesBlockLayout(UniformFlags layoutFlag) const331 bool usesBlockLayout (UniformFlags layoutFlag) const { return m_interface.usesBlockLayout(layoutFlag); } 332 333 protected: 334 BufferMode m_bufferMode; 335 ShaderInterface m_interface; 336 MatrixLoadFlags m_matrixLoadFlag; 337 const bool m_shuffleUniformMembers; //!< Used with explicit offsets to test out of order member offsets 338 339 private: 340 std::string m_vertShaderSource; 341 std::string m_fragShaderSource; 342 343 std::vector<deUint8> m_data; //!< Data. 344 std::map<int, void*> m_blockPointers; //!< Reference block pointers. 345 UniformLayout m_uniformLayout; //!< std140 layout. 346 }; 347 348 } // ubo 349 } // vkt 350 351 #endif // _VKTUNIFORMBLOCKCASE_HPP 352