1 #ifndef _VKTTRANSFORMFEEDBACKFUZZLAYOUTCASE_HPP 2 #define _VKTTRANSFORMFEEDBACKFUZZLAYOUTCASE_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 * Copyright (c) 2018 The Khronos Group Inc. 10 * 11 * Licensed under the Apache License, Version 2.0 (the "License"); 12 * you may not use this file except in compliance with the License. 13 * You may obtain a copy of the License at 14 * 15 * http://www.apache.org/licenses/LICENSE-2.0 16 * 17 * Unless required by applicable law or agreed to in writing, software 18 * distributed under the License is distributed on an "AS IS" BASIS, 19 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 20 * See the License for the specific language governing permissions and 21 * limitations under the License. 22 * 23 *//*! 24 * \file 25 * \brief Vulkan Transform Feedback Fuzz Layout Tests 26 *//*--------------------------------------------------------------------*/ 27 28 #include "deSharedPtr.hpp" 29 #include "vktTestCase.hpp" 30 #include "tcuDefs.hpp" 31 #include "gluShaderUtil.hpp" 32 33 #include <map> 34 35 namespace vkt 36 { 37 namespace TransformFeedback 38 { 39 40 // Interface block details. 41 42 enum InterfaceFlags 43 { 44 PRECISION_LOW = (1<<0), 45 PRECISION_MEDIUM = (1<<1), 46 PRECISION_HIGH = (1<<2), 47 PRECISION_MASK = PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH, 48 49 LAYOUT_XFBBUFFER = (1<<3), 50 LAYOUT_XFBOFFSET = (1<<4), 51 LAYOUT_XFBSTRIDE = (1<<5), 52 LAYOUT_MASK = LAYOUT_XFBBUFFER|LAYOUT_XFBOFFSET|LAYOUT_XFBSTRIDE, 53 54 FIELD_UNASSIGNED = (1<<6), //!< Interface or struct member is not used in shader. 55 FIELD_MISSING = (1<<7), //!< Interface or struct member will be commented out in shader. 56 FIELD_OPTIONS = FIELD_UNASSIGNED|FIELD_MISSING, 57 }; 58 59 enum MatrixLoadFlags 60 { 61 LOAD_FULL_MATRIX = 0, 62 LOAD_MATRIX_COMPONENTS = 1, 63 }; 64 65 enum TestStageFlags 66 { 67 TEST_STAGE_VERTEX = 0, 68 TEST_STAGE_GEOMETRY = 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) 132 , m_type(type) 133 , m_flags(flags) 134 {} 135 StructMember(void)136 StructMember (void) 137 : m_flags(0) 138 {} 139 getName(void) const140 const std::string& getName (void) const { return m_name; } getType(void) const141 const VarType& getType (void) const { return m_type; } getFlags(void) const142 deUint32 getFlags (void) const { return m_flags; } 143 144 private: 145 std::string m_name; 146 VarType m_type; 147 deUint32 m_flags; 148 }; 149 150 class StructType 151 { 152 public: 153 typedef std::vector<StructMember>::iterator Iterator; 154 typedef std::vector<StructMember>::const_iterator ConstIterator; 155 StructType(const std::string & typeName)156 StructType (const std::string& typeName) : m_typeName(typeName) {} ~StructType(void)157 ~StructType (void) {} 158 getTypeName(void) const159 const std::string& getTypeName (void) const { return m_typeName; } hasTypeName(void) const160 bool hasTypeName (void) const { return !m_typeName.empty(); } 161 begin(void)162 inline Iterator begin (void) { return m_members.begin(); } begin(void) const163 inline ConstIterator begin (void) const { return m_members.begin(); } end(void)164 inline Iterator end (void) { return m_members.end(); } end(void) const165 inline ConstIterator end (void) const { return m_members.end(); } 166 167 void addMember (const std::string& name, const VarType& type, deUint32 flags = 0); 168 169 private: 170 std::string m_typeName; 171 std::vector<StructMember> m_members; 172 }; 173 174 class InterfaceBlockMember 175 { 176 public: 177 InterfaceBlockMember (const std::string& name, const VarType& type, deUint32 flags = 0); 178 getName(void) const179 const std::string& getName (void) const { return m_name; } getType(void) const180 const VarType& getType (void) const { return m_type; } getFlags(void) const181 deUint32 getFlags (void) const { return m_flags; } 182 183 private: 184 std::string m_name; 185 VarType m_type; 186 deUint32 m_flags; 187 }; 188 189 class InterfaceBlock 190 { 191 public: 192 typedef std::vector<InterfaceBlockMember>::iterator Iterator; 193 typedef std::vector<InterfaceBlockMember>::const_iterator ConstIterator; 194 195 InterfaceBlock (const std::string& blockName); 196 getBlockName(void) const197 const std::string& getBlockName (void) const { return m_blockName; } hasInstanceName(void) const198 bool hasInstanceName (void) const { return !m_instanceName.empty(); } getInstanceName(void) const199 const std::string& getInstanceName (void) const { return m_instanceName; } isArray(void) const200 bool isArray (void) const { return m_arraySize > 0; } getArraySize(void) const201 int getArraySize (void) const { return m_arraySize; } getXfbBuffer(void) const202 int getXfbBuffer (void) const { return m_xfbBuffer; } getFlags(void) const203 deUint32 getFlags (void) const { return m_flags; } 204 setInstanceName(const std::string & name)205 void setInstanceName (const std::string& name) { m_instanceName = name; } setFlags(deUint32 flags)206 void setFlags (deUint32 flags) { m_flags = flags; } setFlag(deUint32 flag)207 void setFlag (deUint32 flag) { m_flags |= flag; } setArraySize(int arraySize)208 void setArraySize (int arraySize) { m_arraySize = arraySize; } setXfbBuffer(int xfbBuffer)209 void setXfbBuffer (int xfbBuffer) { m_xfbBuffer = xfbBuffer; } addInterfaceMember(const InterfaceBlockMember & interfaceBlockMember)210 void addInterfaceMember (const InterfaceBlockMember& interfaceBlockMember) { m_members.push_back(interfaceBlockMember); } 211 begin(void)212 inline Iterator begin (void) { return m_members.begin(); } begin(void) const213 inline ConstIterator begin (void) const { return m_members.begin(); } end(void)214 inline Iterator end (void) { return m_members.end(); } end(void) const215 inline ConstIterator end (void) const { return m_members.end(); } 216 217 private: 218 std::string m_blockName; 219 std::string m_instanceName; 220 std::vector<InterfaceBlockMember> m_members; 221 int m_xfbBuffer; 222 int m_arraySize; //!< Array size or 0 if not interface block array. 223 deUint32 m_flags; 224 }; 225 226 typedef de::SharedPtr<StructType> StructTypeSP; 227 typedef de::SharedPtr<InterfaceBlock> InterfaceBlockSP; 228 229 class ShaderInterface 230 { 231 public: 232 ShaderInterface (void); 233 ~ShaderInterface (void); 234 235 StructType& allocStruct (const std::string& name); 236 void getNamedStructs (std::vector<const StructType*>& structs) const; 237 238 InterfaceBlock& allocBlock (const std::string& name); 239 getNumInterfaceBlocks(void) const240 int getNumInterfaceBlocks (void) const { return (int)m_interfaceBlocks.size(); } getInterfaceBlock(int ndx) const241 const InterfaceBlock& getInterfaceBlock (int ndx) const { return *m_interfaceBlocks[ndx]; } getInterfaceBlockForModify(int ndx)242 InterfaceBlock& getInterfaceBlockForModify (int ndx) { return *m_interfaceBlocks[ndx]; } 243 244 private: 245 std::vector<StructTypeSP> m_structs; 246 std::vector<InterfaceBlockSP> m_interfaceBlocks; 247 }; 248 249 struct BlockLayoutEntry 250 { BlockLayoutEntryvkt::TransformFeedback::BlockLayoutEntry251 BlockLayoutEntry (void) 252 : xfbBuffer (-1) 253 , xfbOffset (-1) 254 , xfbSize (0) 255 , xfbStride (0) 256 , blockDeclarationNdx (-1) 257 , instanceNdx (-1) 258 , locationNdx (-1) 259 , locationSize (-1) 260 { 261 } 262 263 std::string name; 264 int xfbBuffer; 265 int xfbOffset; 266 int xfbSize; 267 int xfbStride; 268 std::vector<int> activeInterfaceIndices; 269 int blockDeclarationNdx; 270 int instanceNdx; 271 // Location are not used for transform feedback, but they must be not overlap to pass GLSL compiler 272 int locationNdx; 273 int locationSize; 274 }; 275 276 struct InterfaceLayoutEntry 277 { InterfaceLayoutEntryvkt::TransformFeedback::InterfaceLayoutEntry278 InterfaceLayoutEntry (void) 279 : type (glu::TYPE_LAST) 280 , arraySize (0) 281 , blockLayoutNdx(-1) 282 , offset (-1) 283 , arrayStride (-1) 284 , matrixStride (-1) 285 , instanceNdx (0) 286 , locationNdx (-1) 287 , validate (true) 288 { 289 } 290 291 std::string name; 292 glu::DataType type; 293 int arraySize; 294 int blockLayoutNdx; 295 int offset; 296 int arrayStride; 297 int matrixStride; 298 int instanceNdx; 299 // Location are not used for transform feedback, but they must be not overlap to pass GLSL compiler 300 int locationNdx; 301 bool validate; 302 }; 303 304 class InterfaceLayout 305 { 306 public: 307 std::vector<BlockLayoutEntry> blocks; 308 std::vector<InterfaceLayoutEntry> interfaces; 309 310 int getInterfaceLayoutIndex (int blockDeclarationNdx, const std::string& name) const; 311 int getBlockLayoutIndex (int blockDeclarationNdx, int instanceNdx) const; 312 }; 313 314 typedef std::vector<vk::VkDeviceSize> DeviceSizeVector; 315 316 class InterfaceBlockCase : public vkt::TestCase 317 { 318 public: 319 InterfaceBlockCase (tcu::TestContext& testCtx, 320 const std::string& name, 321 const std::string& description, 322 MatrixLoadFlags matrixLoadFlag, 323 TestStageFlags testStageFlag, 324 bool shuffleInterfaceMembers = false); 325 ~InterfaceBlockCase (void); 326 327 virtual void delayedInit (void); 328 virtual void initPrograms (vk::SourceCollections& programCollection) const; 329 virtual TestInstance* createInstance (Context& context) const; 330 331 protected: 332 ShaderInterface m_interface; 333 MatrixLoadFlags m_matrixLoadFlag; 334 TestStageFlags m_testStageFlags; 335 bool m_shuffleInterfaceMembers; //!< Used with explicit offsets to test out of order member offsets 336 deUint32 m_locationsRequired; 337 338 private: 339 std::string m_vertShaderSource; 340 std::string m_geomShaderSource; 341 342 std::vector<deUint8> m_data; //!< Data. 343 DeviceSizeVector m_tfBufBindingSizes; 344 DeviceSizeVector m_tfBufBindingOffsets; 345 std::map<int, void*> m_blockPointers; //!< Reference block pointers. 346 InterfaceLayout m_interfaceLayout; //!< interface layout. 347 }; 348 349 } // TransformFeedback 350 } // vkt 351 352 #endif // _VKTTRANSFORMFEEDBACKFUZZLAYOUTCASE_HPP 353