xref: /aosp_15_r20/external/deqp/external/vulkancts/modules/vulkan/ubo/vktUniformBlockCase.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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 |
57                   LAYOUT_COLUMN_MAJOR | LAYOUT_OFFSET,
58 
59     DECLARE_VERTEX   = (1 << 11),
60     DECLARE_FRAGMENT = (1 << 12),
61     DECLARE_BOTH     = DECLARE_VERTEX | DECLARE_FRAGMENT,
62 
63     UNUSED_VERTEX   = (1 << 13), //!< Uniform or struct member is not read in vertex shader.
64     UNUSED_FRAGMENT = (1 << 14), //!< Uniform or struct member is not read in fragment shader.
65     UNUSED_BOTH     = UNUSED_VERTEX | UNUSED_FRAGMENT,
66 
67     LAYOUT_16BIT_STORAGE = (1 << 15), //!< Support VK_KHR_16bit_storage extension
68     LAYOUT_8BIT_STORAGE  = (1 << 16), //!< Support VK_KHR_8bit_storage extension
69 
70     LAYOUT_DESCRIPTOR_INDEXING = (1 << 17), //!< Support VK_KHR_descriptor_indexing extension
71 };
72 
73 enum MatrixLoadFlags
74 {
75     LOAD_FULL_MATRIX       = 0,
76     LOAD_MATRIX_COMPONENTS = 1,
77 };
78 
79 class StructType;
80 
81 class VarType
82 {
83 public:
84     VarType(void);
85     VarType(const VarType &other);
86     VarType(glu::DataType basicType, uint32_t flags);
87     VarType(const VarType &elementType, int arraySize);
88     explicit VarType(const StructType *structPtr, uint32_t flags = 0u);
89     ~VarType(void);
90 
isBasicType(void) const91     bool isBasicType(void) const
92     {
93         return m_type == TYPE_BASIC;
94     }
isArrayType(void) const95     bool isArrayType(void) const
96     {
97         return m_type == TYPE_ARRAY;
98     }
isStructType(void) const99     bool isStructType(void) const
100     {
101         return m_type == TYPE_STRUCT;
102     }
103 
getFlags(void) const104     uint32_t getFlags(void) const
105     {
106         return m_flags;
107     }
getBasicType(void) const108     glu::DataType getBasicType(void) const
109     {
110         return m_data.basicType;
111     }
112 
getElementType(void) const113     const VarType &getElementType(void) const
114     {
115         return *m_data.array.elementType;
116     }
getArraySize(void) const117     int getArraySize(void) const
118     {
119         return m_data.array.size;
120     }
121 
getStruct(void) const122     const StructType &getStruct(void) const
123     {
124         return *m_data.structPtr;
125     }
getStructPtr(void) const126     const StructType *getStructPtr(void) const
127     {
128         DE_ASSERT(isStructType());
129         return m_data.structPtr;
130     }
131 
132     VarType &operator=(const VarType &other);
133 
134 private:
135     enum Type
136     {
137         TYPE_BASIC,
138         TYPE_ARRAY,
139         TYPE_STRUCT,
140 
141         TYPE_LAST
142     };
143 
144     Type m_type;
145     uint32_t m_flags;
146     union Data
147     {
148         glu::DataType basicType;
149         struct
150         {
151             VarType *elementType;
152             int size;
153         } array;
154         const StructType *structPtr;
155 
Data(void)156         Data(void)
157         {
158             array.elementType = DE_NULL;
159             array.size        = 0;
160         }
161     } m_data;
162 };
163 
164 class StructMember
165 {
166 public:
StructMember(const std::string & name,const VarType & type,uint32_t flags)167     StructMember(const std::string &name, const VarType &type, uint32_t flags)
168         : m_name(name)
169         , m_type(type)
170         , m_flags(flags)
171     {
172     }
StructMember(void)173     StructMember(void) : m_flags(0)
174     {
175     }
176 
getName(void) const177     const std::string &getName(void) const
178     {
179         return m_name;
180     }
getType(void) const181     const VarType &getType(void) const
182     {
183         return m_type;
184     }
getFlags(void) const185     uint32_t getFlags(void) const
186     {
187         return m_flags;
188     }
189 
190 private:
191     std::string m_name;
192     VarType m_type;
193     uint32_t m_flags;
194 };
195 
196 class StructType
197 {
198 public:
199     typedef std::vector<StructMember>::iterator Iterator;
200     typedef std::vector<StructMember>::const_iterator ConstIterator;
201 
StructType(const std::string & typeName)202     StructType(const std::string &typeName) : m_typeName(typeName)
203     {
204     }
~StructType(void)205     ~StructType(void)
206     {
207     }
208 
getTypeName(void) const209     const std::string &getTypeName(void) const
210     {
211         return m_typeName;
212     }
hasTypeName(void) const213     bool hasTypeName(void) const
214     {
215         return !m_typeName.empty();
216     }
217 
begin(void)218     inline Iterator begin(void)
219     {
220         return m_members.begin();
221     }
begin(void) const222     inline ConstIterator begin(void) const
223     {
224         return m_members.begin();
225     }
end(void)226     inline Iterator end(void)
227     {
228         return m_members.end();
229     }
end(void) const230     inline ConstIterator end(void) const
231     {
232         return m_members.end();
233     }
234 
235     void addMember(const std::string &name, const VarType &type, uint32_t flags = 0);
236 
237 private:
238     std::string m_typeName;
239     std::vector<StructMember> m_members;
240 };
241 
242 class Uniform
243 {
244 public:
245     Uniform(const std::string &name, const VarType &type, uint32_t flags = 0);
246 
getName(void) const247     const std::string &getName(void) const
248     {
249         return m_name;
250     }
getType(void) const251     const VarType &getType(void) const
252     {
253         return m_type;
254     }
getFlags(void) const255     uint32_t getFlags(void) const
256     {
257         return m_flags;
258     }
259 
260 private:
261     std::string m_name;
262     VarType m_type;
263     uint32_t m_flags;
264 };
265 
266 class UniformBlock
267 {
268 public:
269     typedef std::vector<Uniform>::iterator Iterator;
270     typedef std::vector<Uniform>::const_iterator ConstIterator;
271 
272     UniformBlock(const std::string &blockName);
273 
getBlockName(void) const274     const std::string &getBlockName(void) const
275     {
276         return m_blockName;
277     }
getInstanceName(void) const278     const std::string &getInstanceName(void) const
279     {
280         return m_instanceName;
281     }
hasInstanceName(void) const282     bool hasInstanceName(void) const
283     {
284         return !m_instanceName.empty();
285     }
isArray(void) const286     bool isArray(void) const
287     {
288         return m_arraySize > 0;
289     }
getArraySize(void) const290     int getArraySize(void) const
291     {
292         return m_arraySize;
293     }
getFlags(void) const294     uint32_t getFlags(void) const
295     {
296         return m_flags;
297     }
298 
setInstanceName(const std::string & name)299     void setInstanceName(const std::string &name)
300     {
301         m_instanceName = name;
302     }
setFlags(uint32_t flags)303     void setFlags(uint32_t flags)
304     {
305         m_flags = flags;
306     }
setArraySize(int arraySize)307     void setArraySize(int arraySize)
308     {
309         m_arraySize = arraySize;
310     }
addUniform(const Uniform & uniform)311     void addUniform(const Uniform &uniform)
312     {
313         m_uniforms.push_back(uniform);
314     }
315 
begin(void)316     inline Iterator begin(void)
317     {
318         return m_uniforms.begin();
319     }
begin(void) const320     inline ConstIterator begin(void) const
321     {
322         return m_uniforms.begin();
323     }
end(void)324     inline Iterator end(void)
325     {
326         return m_uniforms.end();
327     }
end(void) const328     inline ConstIterator end(void) const
329     {
330         return m_uniforms.end();
331     }
332 
333 private:
334     std::string m_blockName;
335     std::string m_instanceName;
336     std::vector<Uniform> m_uniforms;
337     int m_arraySize; //!< Array size or 0 if not interface block array.
338     uint32_t m_flags;
339 };
340 
341 typedef de::SharedPtr<StructType> StructTypeSP;
342 typedef de::SharedPtr<UniformBlock> UniformBlockSP;
343 
344 class ShaderInterface
345 {
346 public:
347     ShaderInterface(void);
348     ~ShaderInterface(void);
349 
350     StructType &allocStruct(const std::string &name);
351     void getNamedStructs(std::vector<const StructType *> &structs) const;
352 
353     UniformBlock &allocBlock(const std::string &name);
354 
getNumUniformBlocks(void) const355     int getNumUniformBlocks(void) const
356     {
357         return (int)m_uniformBlocks.size();
358     }
getUniformBlock(int ndx) const359     const UniformBlock &getUniformBlock(int ndx) const
360     {
361         return *m_uniformBlocks[ndx];
362     }
363     bool usesBlockLayout(UniformFlags layoutFlag) const;
364 
365 private:
366     std::vector<StructTypeSP> m_structs;
367     std::vector<UniformBlockSP> m_uniformBlocks;
368 };
369 
370 struct BlockLayoutEntry
371 {
BlockLayoutEntryvkt::ubo::BlockLayoutEntry372     BlockLayoutEntry(void) : size(0), blockDeclarationNdx(-1), bindingNdx(-1), instanceNdx(-1)
373     {
374     }
375 
376     std::string name;
377     int size;
378     std::vector<int> activeUniformIndices;
379     int blockDeclarationNdx;
380     int bindingNdx;
381     int instanceNdx;
382 };
383 
384 struct UniformLayoutEntry
385 {
UniformLayoutEntryvkt::ubo::UniformLayoutEntry386     UniformLayoutEntry(void)
387         : type(glu::TYPE_LAST)
388         , size(0)
389         , blockNdx(-1)
390         , offset(-1)
391         , arraySize(-1)
392         , arrayStride(-1)
393         , matrixStride(-1)
394         , topLevelArraySize(-1)
395         , topLevelArrayStride(-1)
396         , isRowMajor(false)
397         , instanceNdx(0)
398     {
399     }
400 
401     std::string name;
402     glu::DataType type;
403     int size;
404     int blockNdx;
405     int offset;
406     int arraySize;
407     int arrayStride;
408     int matrixStride;
409     int topLevelArraySize;
410     int topLevelArrayStride;
411     bool isRowMajor;
412     int instanceNdx;
413 };
414 
415 class UniformLayout
416 {
417 public:
418     std::vector<BlockLayoutEntry> blocks;
419     std::vector<UniformLayoutEntry> uniforms;
420 
421     int getUniformLayoutIndex(int blockDeclarationNdx, const std::string &name) const;
422     int getBlockLayoutIndex(int blockDeclarationNdx, int instanceNdx) const;
423 };
424 
425 class UniformBlockCase : public vkt::TestCase
426 {
427 public:
428     enum BufferMode
429     {
430         BUFFERMODE_SINGLE = 0, //!< Single buffer shared between uniform blocks.
431         BUFFERMODE_PER_BLOCK,  //!< Per-block buffers
432 
433         BUFFERMODE_LAST
434     };
435 
436     UniformBlockCase(tcu::TestContext &testCtx, const std::string &name, BufferMode bufferMode,
437                      MatrixLoadFlags matrixLoadFlag, bool shuffleUniformMembers = false);
438     ~UniformBlockCase(void);
439 
440     virtual void delayedInit(void);
441     virtual void initPrograms(vk::SourceCollections &programCollection) const;
442     virtual TestInstance *createInstance(Context &context) const;
usesBlockLayout(UniformFlags layoutFlag) const443     bool usesBlockLayout(UniformFlags layoutFlag) const
444     {
445         return m_interface.usesBlockLayout(layoutFlag);
446     }
447 
448 protected:
449     BufferMode m_bufferMode;
450     ShaderInterface m_interface;
451     MatrixLoadFlags m_matrixLoadFlag;
452     const bool m_shuffleUniformMembers; //!< Used with explicit offsets to test out of order member offsets
453 
454 private:
455     std::string m_vertShaderSource;
456     std::string m_fragShaderSource;
457 
458     std::vector<uint8_t> m_data;           //!< Data.
459     std::map<int, void *> m_blockPointers; //!< Reference block pointers.
460     UniformLayout m_uniformLayout;         //!< std140 layout.
461 };
462 
463 } // namespace ubo
464 } // namespace vkt
465 
466 #endif // _VKTUNIFORMBLOCKCASE_HPP
467