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