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, uint32_t flags); 79 VarType(const VarType &elementType, int arraySize); 80 explicit VarType(const StructType *structPtr, uint32_t flags = 0u); 81 ~VarType(void); 82 isBasicType(void) const83 bool isBasicType(void) const 84 { 85 return m_type == TYPE_BASIC; 86 } isArrayType(void) const87 bool isArrayType(void) const 88 { 89 return m_type == TYPE_ARRAY; 90 } isStructType(void) const91 bool isStructType(void) const 92 { 93 return m_type == TYPE_STRUCT; 94 } 95 getFlags(void) const96 uint32_t getFlags(void) const 97 { 98 return m_flags; 99 } getBasicType(void) const100 glu::DataType getBasicType(void) const 101 { 102 return m_data.basicType; 103 } 104 getElementType(void) const105 const VarType &getElementType(void) const 106 { 107 return *m_data.array.elementType; 108 } getArraySize(void) const109 int getArraySize(void) const 110 { 111 return m_data.array.size; 112 } 113 getStruct(void) const114 const StructType &getStruct(void) const 115 { 116 return *m_data.structPtr; 117 } 118 119 VarType &operator=(const VarType &other); 120 121 private: 122 enum Type 123 { 124 TYPE_BASIC, 125 TYPE_ARRAY, 126 TYPE_STRUCT, 127 128 TYPE_LAST 129 }; 130 131 Type m_type; 132 uint32_t m_flags; 133 union Data 134 { 135 glu::DataType basicType; 136 struct 137 { 138 VarType *elementType; 139 int size; 140 } array; 141 const StructType *structPtr; 142 Data(void)143 Data(void) 144 { 145 array.elementType = DE_NULL; 146 array.size = 0; 147 } 148 } m_data; 149 }; 150 151 class StructMember 152 { 153 public: StructMember(const std::string & name,const VarType & type,uint32_t flags)154 StructMember(const std::string &name, const VarType &type, uint32_t flags) 155 : m_name(name) 156 , m_type(type) 157 , m_flags(flags) 158 { 159 } 160 StructMember(void)161 StructMember(void) : m_flags(0) 162 { 163 } 164 getName(void) const165 const std::string &getName(void) const 166 { 167 return m_name; 168 } getType(void) const169 const VarType &getType(void) const 170 { 171 return m_type; 172 } getFlags(void) const173 uint32_t getFlags(void) const 174 { 175 return m_flags; 176 } 177 178 private: 179 std::string m_name; 180 VarType m_type; 181 uint32_t m_flags; 182 }; 183 184 class StructType 185 { 186 public: 187 typedef std::vector<StructMember>::iterator Iterator; 188 typedef std::vector<StructMember>::const_iterator ConstIterator; 189 StructType(const std::string & typeName)190 StructType(const std::string &typeName) : m_typeName(typeName) 191 { 192 } ~StructType(void)193 ~StructType(void) 194 { 195 } 196 getTypeName(void) const197 const std::string &getTypeName(void) const 198 { 199 return m_typeName; 200 } hasTypeName(void) const201 bool hasTypeName(void) const 202 { 203 return !m_typeName.empty(); 204 } 205 begin(void)206 inline Iterator begin(void) 207 { 208 return m_members.begin(); 209 } begin(void) const210 inline ConstIterator begin(void) const 211 { 212 return m_members.begin(); 213 } end(void)214 inline Iterator end(void) 215 { 216 return m_members.end(); 217 } end(void) const218 inline ConstIterator end(void) const 219 { 220 return m_members.end(); 221 } 222 223 void addMember(const std::string &name, const VarType &type, uint32_t flags = 0); 224 225 private: 226 std::string m_typeName; 227 std::vector<StructMember> m_members; 228 }; 229 230 class InterfaceBlockMember 231 { 232 public: 233 InterfaceBlockMember(const std::string &name, const VarType &type, uint32_t flags = 0); 234 getName(void) const235 const std::string &getName(void) const 236 { 237 return m_name; 238 } getType(void) const239 const VarType &getType(void) const 240 { 241 return m_type; 242 } getFlags(void) const243 uint32_t getFlags(void) const 244 { 245 return m_flags; 246 } 247 248 private: 249 std::string m_name; 250 VarType m_type; 251 uint32_t m_flags; 252 }; 253 254 class InterfaceBlock 255 { 256 public: 257 typedef std::vector<InterfaceBlockMember>::iterator Iterator; 258 typedef std::vector<InterfaceBlockMember>::const_iterator ConstIterator; 259 260 InterfaceBlock(const std::string &blockName); 261 getBlockName(void) const262 const std::string &getBlockName(void) const 263 { 264 return m_blockName; 265 } hasInstanceName(void) const266 bool hasInstanceName(void) const 267 { 268 return !m_instanceName.empty(); 269 } getInstanceName(void) const270 const std::string &getInstanceName(void) const 271 { 272 return m_instanceName; 273 } isArray(void) const274 bool isArray(void) const 275 { 276 return m_arraySize > 0; 277 } getArraySize(void) const278 int getArraySize(void) const 279 { 280 return m_arraySize; 281 } getXfbBuffer(void) const282 int getXfbBuffer(void) const 283 { 284 return m_xfbBuffer; 285 } getFlags(void) const286 uint32_t getFlags(void) const 287 { 288 return m_flags; 289 } 290 setInstanceName(const std::string & name)291 void setInstanceName(const std::string &name) 292 { 293 m_instanceName = name; 294 } setFlags(uint32_t flags)295 void setFlags(uint32_t flags) 296 { 297 m_flags = flags; 298 } setFlag(uint32_t flag)299 void setFlag(uint32_t flag) 300 { 301 m_flags |= flag; 302 } setArraySize(int arraySize)303 void setArraySize(int arraySize) 304 { 305 m_arraySize = arraySize; 306 } setXfbBuffer(int xfbBuffer)307 void setXfbBuffer(int xfbBuffer) 308 { 309 m_xfbBuffer = xfbBuffer; 310 } addInterfaceMember(const InterfaceBlockMember & interfaceBlockMember)311 void addInterfaceMember(const InterfaceBlockMember &interfaceBlockMember) 312 { 313 m_members.push_back(interfaceBlockMember); 314 } 315 begin(void)316 inline Iterator begin(void) 317 { 318 return m_members.begin(); 319 } begin(void) const320 inline ConstIterator begin(void) const 321 { 322 return m_members.begin(); 323 } end(void)324 inline Iterator end(void) 325 { 326 return m_members.end(); 327 } end(void) const328 inline ConstIterator end(void) const 329 { 330 return m_members.end(); 331 } 332 333 private: 334 std::string m_blockName; 335 std::string m_instanceName; 336 std::vector<InterfaceBlockMember> m_members; 337 int m_xfbBuffer; 338 int m_arraySize; //!< Array size or 0 if not interface block array. 339 uint32_t m_flags; 340 }; 341 342 typedef de::SharedPtr<StructType> StructTypeSP; 343 typedef de::SharedPtr<InterfaceBlock> InterfaceBlockSP; 344 345 class ShaderInterface 346 { 347 public: 348 ShaderInterface(void); 349 ~ShaderInterface(void); 350 351 StructType &allocStruct(const std::string &name); 352 void getNamedStructs(std::vector<const StructType *> &structs) const; 353 354 InterfaceBlock &allocBlock(const std::string &name); 355 getNumInterfaceBlocks(void) const356 int getNumInterfaceBlocks(void) const 357 { 358 return (int)m_interfaceBlocks.size(); 359 } getInterfaceBlock(int ndx) const360 const InterfaceBlock &getInterfaceBlock(int ndx) const 361 { 362 return *m_interfaceBlocks[ndx]; 363 } getInterfaceBlockForModify(int ndx)364 InterfaceBlock &getInterfaceBlockForModify(int ndx) 365 { 366 return *m_interfaceBlocks[ndx]; 367 } 368 369 private: 370 std::vector<StructTypeSP> m_structs; 371 std::vector<InterfaceBlockSP> m_interfaceBlocks; 372 }; 373 374 struct BlockLayoutEntry 375 { BlockLayoutEntryvkt::TransformFeedback::BlockLayoutEntry376 BlockLayoutEntry(void) 377 : xfbBuffer(-1) 378 , xfbOffset(-1) 379 , xfbSize(0) 380 , xfbStride(0) 381 , blockDeclarationNdx(-1) 382 , instanceNdx(-1) 383 , locationNdx(-1) 384 , locationSize(-1) 385 { 386 } 387 388 std::string name; 389 int xfbBuffer; 390 int xfbOffset; 391 int xfbSize; 392 int xfbStride; 393 std::vector<int> activeInterfaceIndices; 394 int blockDeclarationNdx; 395 int instanceNdx; 396 // Location are not used for transform feedback, but they must be not overlap to pass GLSL compiler 397 int locationNdx; 398 int locationSize; 399 }; 400 401 struct InterfaceLayoutEntry 402 { InterfaceLayoutEntryvkt::TransformFeedback::InterfaceLayoutEntry403 InterfaceLayoutEntry(void) 404 : type(glu::TYPE_LAST) 405 , arraySize(0) 406 , blockLayoutNdx(-1) 407 , offset(-1) 408 , arrayStride(-1) 409 , matrixStride(-1) 410 , instanceNdx(0) 411 , locationNdx(-1) 412 , validate(true) 413 { 414 } 415 416 std::string name; 417 glu::DataType type; 418 int arraySize; 419 int blockLayoutNdx; 420 int offset; 421 int arrayStride; 422 int matrixStride; 423 int instanceNdx; 424 // Location are not used for transform feedback, but they must be not overlap to pass GLSL compiler 425 int locationNdx; 426 bool validate; 427 }; 428 429 class InterfaceLayout 430 { 431 public: 432 std::vector<BlockLayoutEntry> blocks; 433 std::vector<InterfaceLayoutEntry> interfaces; 434 435 int getInterfaceLayoutIndex(int blockDeclarationNdx, const std::string &name) const; 436 int getBlockLayoutIndex(int blockDeclarationNdx, int instanceNdx) const; 437 }; 438 439 typedef std::vector<vk::VkDeviceSize> DeviceSizeVector; 440 441 class InterfaceBlockCase : public vkt::TestCase 442 { 443 public: 444 InterfaceBlockCase(tcu::TestContext &testCtx, const std::string &name, MatrixLoadFlags matrixLoadFlag, 445 TestStageFlags testStageFlag, bool shuffleInterfaceMembers = false); 446 ~InterfaceBlockCase(void); 447 448 virtual void delayedInit(void); 449 virtual void initPrograms(vk::SourceCollections &programCollection) const; 450 virtual TestInstance *createInstance(Context &context) const; 451 452 protected: 453 ShaderInterface m_interface; 454 MatrixLoadFlags m_matrixLoadFlag; 455 TestStageFlags m_testStageFlags; 456 bool m_shuffleInterfaceMembers; //!< Used with explicit offsets to test out of order member offsets 457 uint32_t m_locationsRequired; 458 459 private: 460 std::string m_vertShaderSource; 461 std::string m_geomShaderSource; 462 463 std::vector<uint8_t> m_data; //!< Data. 464 DeviceSizeVector m_tfBufBindingSizes; 465 DeviceSizeVector m_tfBufBindingOffsets; 466 std::map<int, void *> m_blockPointers; //!< Reference block pointers. 467 InterfaceLayout m_interfaceLayout; //!< interface layout. 468 }; 469 470 } // namespace TransformFeedback 471 } // namespace vkt 472 473 #endif // _VKTTRANSFORMFEEDBACKFUZZLAYOUTCASE_HPP 474