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 70 enum MatrixLoadFlags 71 { 72 LOAD_FULL_MATRIX = 0, 73 LOAD_MATRIX_COMPONENTS = 1, 74 }; 75 76 class StructType; 77 78 class VarType 79 { 80 public: 81 VarType (void); 82 VarType (const VarType& other); 83 VarType (glu::DataType basicType, deUint32 flags); 84 VarType (const VarType& elementType, int arraySize); 85 explicit VarType (const StructType* structPtr, deUint32 flags = 0u); 86 ~VarType (void); 87 isBasicType(void) const88 bool isBasicType (void) const { return m_type == TYPE_BASIC; } isArrayType(void) const89 bool isArrayType (void) const { return m_type == TYPE_ARRAY; } isStructType(void) const90 bool isStructType (void) const { return m_type == TYPE_STRUCT; } 91 getFlags(void) const92 deUint32 getFlags (void) const { return m_flags; } getBasicType(void) const93 glu::DataType getBasicType (void) const { return m_data.basicType; } 94 getElementType(void) const95 const VarType& getElementType (void) const { return *m_data.array.elementType; } getArraySize(void) const96 int getArraySize (void) const { return m_data.array.size; } 97 getStruct(void) const98 const StructType& getStruct (void) const { return *m_data.structPtr; } getStructPtr(void) const99 const StructType* getStructPtr (void) const { DE_ASSERT(isStructType()); return m_data.structPtr; } 100 101 VarType& operator= (const VarType& other); 102 103 private: 104 enum Type 105 { 106 TYPE_BASIC, 107 TYPE_ARRAY, 108 TYPE_STRUCT, 109 110 TYPE_LAST 111 }; 112 113 Type m_type; 114 deUint32 m_flags; 115 union Data 116 { 117 glu::DataType basicType; 118 struct 119 { 120 VarType* elementType; 121 int size; 122 } array; 123 const StructType* structPtr; 124 Data(void)125 Data (void) 126 { 127 array.elementType = DE_NULL; 128 array.size = 0; 129 }; 130 } m_data; 131 }; 132 133 class StructMember 134 { 135 public: StructMember(const std::string & name,const VarType & type,deUint32 flags)136 StructMember (const std::string& name, const VarType& type, deUint32 flags) 137 : m_name(name), m_type(type), m_flags(flags) 138 {} StructMember(void)139 StructMember (void) 140 : m_flags(0) 141 {} 142 getName(void) const143 const std::string& getName (void) const { return m_name; } getType(void) const144 const VarType& getType (void) const { return m_type; } getFlags(void) const145 deUint32 getFlags (void) const { return m_flags; } 146 147 private: 148 std::string m_name; 149 VarType m_type; 150 deUint32 m_flags; 151 }; 152 153 class StructType 154 { 155 public: 156 typedef std::vector<StructMember>::iterator Iterator; 157 typedef std::vector<StructMember>::const_iterator ConstIterator; 158 StructType(const std::string & typeName)159 StructType (const std::string& typeName) : m_typeName(typeName) {} ~StructType(void)160 ~StructType (void) {} 161 getTypeName(void) const162 const std::string& getTypeName (void) const { return m_typeName; } hasTypeName(void) const163 bool hasTypeName (void) const { return !m_typeName.empty(); } 164 begin(void)165 inline Iterator begin (void) { return m_members.begin(); } begin(void) const166 inline ConstIterator begin (void) const { return m_members.begin(); } end(void)167 inline Iterator end (void) { return m_members.end(); } end(void) const168 inline ConstIterator end (void) const { return m_members.end(); } 169 170 void addMember (const std::string& name, const VarType& type, deUint32 flags = 0); 171 172 private: 173 std::string m_typeName; 174 std::vector<StructMember> m_members; 175 }; 176 177 class Uniform 178 { 179 public: 180 Uniform (const std::string& name, const VarType& type, deUint32 flags = 0); 181 getName(void) const182 const std::string& getName (void) const { return m_name; } getType(void) const183 const VarType& getType (void) const { return m_type; } getFlags(void) const184 deUint32 getFlags (void) const { return m_flags; } 185 186 private: 187 std::string m_name; 188 VarType m_type; 189 deUint32 m_flags; 190 }; 191 192 class UniformBlock 193 { 194 public: 195 typedef std::vector<Uniform>::iterator Iterator; 196 typedef std::vector<Uniform>::const_iterator ConstIterator; 197 198 UniformBlock (const std::string& blockName); 199 getBlockName(void) const200 const std::string& getBlockName (void) const { return m_blockName; } getInstanceName(void) const201 const std::string& getInstanceName (void) const { return m_instanceName; } hasInstanceName(void) const202 bool hasInstanceName (void) const { return !m_instanceName.empty(); } isArray(void) const203 bool isArray (void) const { return m_arraySize > 0; } getArraySize(void) const204 int getArraySize (void) const { return m_arraySize; } getFlags(void) const205 deUint32 getFlags (void) const { return m_flags; } 206 setInstanceName(const std::string & name)207 void setInstanceName (const std::string& name) { m_instanceName = name; } setFlags(deUint32 flags)208 void setFlags (deUint32 flags) { m_flags = flags; } setArraySize(int arraySize)209 void setArraySize (int arraySize) { m_arraySize = arraySize; } addUniform(const Uniform & uniform)210 void addUniform (const Uniform& uniform) { m_uniforms.push_back(uniform); } 211 begin(void)212 inline Iterator begin (void) { return m_uniforms.begin(); } begin(void) const213 inline ConstIterator begin (void) const { return m_uniforms.begin(); } end(void)214 inline Iterator end (void) { return m_uniforms.end(); } end(void) const215 inline ConstIterator end (void) const { return m_uniforms.end(); } 216 217 private: 218 std::string m_blockName; 219 std::string m_instanceName; 220 std::vector<Uniform> m_uniforms; 221 int m_arraySize; //!< Array size or 0 if not interface block array. 222 deUint32 m_flags; 223 }; 224 225 typedef de::SharedPtr<StructType> StructTypeSP; 226 typedef de::SharedPtr<UniformBlock> UniformBlockSP; 227 228 class ShaderInterface 229 { 230 public: 231 ShaderInterface (void); 232 ~ShaderInterface (void); 233 234 StructType& allocStruct (const std::string& name); 235 void getNamedStructs (std::vector<const StructType*>& structs) const; 236 237 UniformBlock& allocBlock (const std::string& name); 238 getNumUniformBlocks(void) const239 int getNumUniformBlocks (void) const { return (int)m_uniformBlocks.size(); } getUniformBlock(int ndx) const240 const UniformBlock& getUniformBlock (int ndx) const { return *m_uniformBlocks[ndx]; } 241 bool usesBlockLayout (UniformFlags layoutFlag) const; 242 243 private: 244 std::vector<StructTypeSP> m_structs; 245 std::vector<UniformBlockSP> m_uniformBlocks; 246 }; 247 248 struct BlockLayoutEntry 249 { BlockLayoutEntryvkt::ubo::BlockLayoutEntry250 BlockLayoutEntry (void) 251 : size (0) 252 , blockDeclarationNdx (-1) 253 , bindingNdx (-1) 254 , instanceNdx (-1) 255 { 256 } 257 258 std::string name; 259 int size; 260 std::vector<int> activeUniformIndices; 261 int blockDeclarationNdx; 262 int bindingNdx; 263 int instanceNdx; 264 }; 265 266 struct UniformLayoutEntry 267 { UniformLayoutEntryvkt::ubo::UniformLayoutEntry268 UniformLayoutEntry (void) 269 : type (glu::TYPE_LAST) 270 , size (0) 271 , blockNdx (-1) 272 , offset (-1) 273 , arraySize (-1) 274 , arrayStride (-1) 275 , matrixStride (-1) 276 , topLevelArraySize (-1) 277 , topLevelArrayStride (-1) 278 , isRowMajor (false) 279 , instanceNdx (0) 280 { 281 } 282 283 std::string name; 284 glu::DataType type; 285 int size; 286 int blockNdx; 287 int offset; 288 int arraySize; 289 int arrayStride; 290 int matrixStride; 291 int topLevelArraySize; 292 int topLevelArrayStride; 293 bool isRowMajor; 294 int instanceNdx; 295 }; 296 297 class UniformLayout 298 { 299 public: 300 std::vector<BlockLayoutEntry> blocks; 301 std::vector<UniformLayoutEntry> uniforms; 302 303 int getUniformLayoutIndex (int blockDeclarationNdx, const std::string& name) const; 304 int getBlockLayoutIndex (int blockDeclarationNdx, int instanceNdx) const; 305 }; 306 307 class UniformBlockCase : public vkt::TestCase 308 { 309 public: 310 enum BufferMode 311 { 312 BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks. 313 BUFFERMODE_PER_BLOCK, //!< Per-block buffers 314 315 BUFFERMODE_LAST 316 }; 317 318 UniformBlockCase (tcu::TestContext& testCtx, 319 const std::string& name, 320 const std::string& description, 321 BufferMode bufferMode, 322 MatrixLoadFlags matrixLoadFlag, 323 bool shuffleUniformMembers = false); 324 ~UniformBlockCase (void); 325 326 virtual void initPrograms (vk::SourceCollections& programCollection) const; 327 virtual TestInstance* createInstance (Context& context) const; usesBlockLayout(UniformFlags layoutFlag) const328 bool usesBlockLayout (UniformFlags layoutFlag) const { return m_interface.usesBlockLayout(layoutFlag); } 329 330 protected: 331 void init (void); 332 333 BufferMode m_bufferMode; 334 ShaderInterface m_interface; 335 MatrixLoadFlags m_matrixLoadFlag; 336 const bool m_shuffleUniformMembers; //!< Used with explicit offsets to test out of order member offsets 337 338 private: 339 std::string m_vertShaderSource; 340 std::string m_fragShaderSource; 341 342 std::vector<deUint8> m_data; //!< Data. 343 std::map<int, void*> m_blockPointers; //!< Reference block pointers. 344 UniformLayout m_uniformLayout; //!< std140 layout. 345 }; 346 347 } // ubo 348 } // vkt 349 350 #endif // _VKTUNIFORMBLOCKCASE_HPP 351