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