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_MASK			= LAYOUT_SHARED|LAYOUT_PACKED|LAYOUT_STD140|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR,
54 
55 	DECLARE_VERTEX		= (1<<8),
56 	DECLARE_FRAGMENT	= (1<<9),
57 	DECLARE_BOTH		= DECLARE_VERTEX|DECLARE_FRAGMENT,
58 
59 	UNUSED_VERTEX		= (1<<10),	//!< Uniform or struct member is not read in vertex shader.
60 	UNUSED_FRAGMENT		= (1<<11),	//!< Uniform or struct member is not read in fragment shader.
61 	UNUSED_BOTH			= UNUSED_VERTEX|UNUSED_FRAGMENT
62 };
63 
64 class StructType;
65 
66 class VarType
67 {
68 public:
69 						VarType			(void);
70 						VarType			(const VarType& other);
71 						VarType			(glu::DataType basicType, deUint32 flags);
72 						VarType			(const VarType& elementType, int arraySize);
73 	explicit			VarType			(const StructType* structPtr);
74 						~VarType		(void);
75 
isBasicType(void) const76 	bool				isBasicType		(void) const	{ return m_type == TYPE_BASIC;	}
isArrayType(void) const77 	bool				isArrayType		(void) const	{ return m_type == TYPE_ARRAY;	}
isStructType(void) const78 	bool				isStructType	(void) const	{ return m_type == TYPE_STRUCT;	}
79 
getFlags(void) const80 	deUint32			getFlags		(void) const	{ return m_flags;					}
getBasicType(void) const81 	glu::DataType		getBasicType	(void) const	{ return m_data.basicType;			}
82 
getElementType(void) const83 	const VarType&		getElementType	(void) const	{ return *m_data.array.elementType;	}
getArraySize(void) const84 	int					getArraySize	(void) const	{ return m_data.array.size;			}
85 
getStruct(void) const86 	const StructType&	getStruct		(void) const	{ return *m_data.structPtr;			}
87 
88 	VarType&			operator=		(const VarType& other);
89 
90 private:
91 	enum Type
92 	{
93 		TYPE_BASIC,
94 		TYPE_ARRAY,
95 		TYPE_STRUCT,
96 
97 		TYPE_LAST
98 	};
99 
100 	Type				m_type;
101 	deUint32			m_flags;
102 	union Data
103 	{
104 		glu::DataType		basicType;
105 		struct
106 		{
107 			VarType*		elementType;
108 			int				size;
109 		} array;
110 		const StructType*	structPtr;
111 
Data(void)112 		Data (void)
113 		{
114 			array.elementType	= DE_NULL;
115 			array.size			= 0;
116 		};
117 	} m_data;
118 };
119 
120 class StructMember
121 {
122 public:
StructMember(const std::string & name,const VarType & type,deUint32 flags)123 						StructMember	(const std::string& name, const VarType& type, deUint32 flags)
124 							: m_name(name), m_type(type), m_flags(flags)
125 						{}
StructMember(void)126 						StructMember	(void)
127 							: m_flags(0)
128 						{}
129 
getName(void) const130 	const std::string&	getName			(void) const { return m_name;	}
getType(void) const131 	const VarType&		getType			(void) const { return m_type;	}
getFlags(void) const132 	deUint32			getFlags		(void) const { return m_flags;	}
133 
134 private:
135 	std::string			m_name;
136 	VarType				m_type;
137 	deUint32			m_flags;
138 };
139 
140 class StructType
141 {
142 public:
143 	typedef std::vector<StructMember>::iterator			Iterator;
144 	typedef std::vector<StructMember>::const_iterator	ConstIterator;
145 
StructType(const std::string & typeName)146 								StructType		(const std::string& typeName) : m_typeName(typeName) {}
~StructType(void)147 								~StructType		(void) {}
148 
getTypeName(void) const149 	const std::string&			getTypeName		(void) const	{ return m_typeName;			}
hasTypeName(void) const150 	bool						hasTypeName		(void) const	{ return !m_typeName.empty();	}
151 
begin(void)152 	inline Iterator				begin			(void)			{ return m_members.begin();		}
begin(void) const153 	inline ConstIterator		begin			(void) const	{ return m_members.begin();		}
end(void)154 	inline Iterator				end				(void)			{ return m_members.end();		}
end(void) const155 	inline ConstIterator		end				(void) const	{ return m_members.end();		}
156 
157 	void						addMember		(const std::string& name, const VarType& type, deUint32 flags = 0);
158 
159 private:
160 	std::string					m_typeName;
161 	std::vector<StructMember>	m_members;
162 };
163 
164 class Uniform
165 {
166 public:
167 						Uniform			(const std::string& name, const VarType& type, deUint32 flags = 0);
168 
getName(void) const169 	const std::string&	getName			(void) const { return m_name;	}
getType(void) const170 	const VarType&		getType			(void) const { return m_type;	}
getFlags(void) const171 	deUint32			getFlags		(void) const { return m_flags;	}
172 
173 private:
174 	std::string			m_name;
175 	VarType				m_type;
176 	deUint32			m_flags;
177 };
178 
179 class UniformBlock
180 {
181 public:
182 	typedef std::vector<Uniform>::iterator			Iterator;
183 	typedef std::vector<Uniform>::const_iterator	ConstIterator;
184 
185 							UniformBlock		(const std::string& blockName);
186 
getBlockName(void) const187 	const std::string&		getBlockName		(void) const { return m_blockName;		}
getInstanceName(void) const188 	const std::string&		getInstanceName		(void) const { return m_instanceName;	}
hasInstanceName(void) const189 	bool					hasInstanceName		(void) const { return !m_instanceName.empty();	}
isArray(void) const190 	bool					isArray				(void) const { return m_arraySize > 0;			}
getArraySize(void) const191 	int						getArraySize		(void) const { return m_arraySize;				}
getFlags(void) const192 	deUint32				getFlags			(void) const { return m_flags;					}
193 
setInstanceName(const std::string & name)194 	void					setInstanceName		(const std::string& name)	{ m_instanceName = name;			}
setFlags(deUint32 flags)195 	void					setFlags			(deUint32 flags)			{ m_flags = flags;					}
setArraySize(int arraySize)196 	void					setArraySize		(int arraySize)				{ m_arraySize = arraySize;			}
addUniform(const Uniform & uniform)197 	void					addUniform			(const Uniform& uniform)	{ m_uniforms.push_back(uniform);	}
198 
begin(void)199 	inline Iterator			begin				(void)			{ return m_uniforms.begin();	}
begin(void) const200 	inline ConstIterator	begin				(void) const	{ return m_uniforms.begin();	}
end(void)201 	inline Iterator			end					(void)			{ return m_uniforms.end();		}
end(void) const202 	inline ConstIterator	end					(void) const	{ return m_uniforms.end();		}
203 
204 private:
205 	std::string				m_blockName;
206 	std::string				m_instanceName;
207 	std::vector<Uniform>	m_uniforms;
208 	int						m_arraySize;	//!< Array size or 0 if not interface block array.
209 	deUint32				m_flags;
210 };
211 
212 typedef de::SharedPtr<StructType>	StructTypeSP;
213 typedef de::SharedPtr<UniformBlock>	UniformBlockSP;
214 
215 class ShaderInterface
216 {
217 public:
218 								ShaderInterface			(void);
219 								~ShaderInterface		(void);
220 
221 	StructType&					allocStruct				(const std::string& name);
222 	void						getNamedStructs			(std::vector<const StructType*>& structs) const;
223 
224 	UniformBlock&				allocBlock				(const std::string& name);
225 
getNumUniformBlocks(void) const226 	int							getNumUniformBlocks		(void) const	{ return (int)m_uniformBlocks.size();	}
getUniformBlock(int ndx) const227 	const UniformBlock&			getUniformBlock			(int ndx) const	{ return *m_uniformBlocks[ndx];			}
228 
229 private:
230 	std::vector<StructTypeSP>		m_structs;
231 	std::vector<UniformBlockSP>		m_uniformBlocks;
232 };
233 
234 struct BlockLayoutEntry
235 {
BlockLayoutEntryvkt::ubo::BlockLayoutEntry236 	BlockLayoutEntry (void)
237 		: size					(0)
238 		, blockDeclarationNdx	(-1)
239 		, bindingNdx			(-1)
240 		, instanceNdx			(-1)
241 	{
242 	}
243 
244 	std::string			name;
245 	int					size;
246 	std::vector<int>	activeUniformIndices;
247 	int					blockDeclarationNdx;
248 	int					bindingNdx;
249 	int					instanceNdx;
250 };
251 
252 struct UniformLayoutEntry
253 {
UniformLayoutEntryvkt::ubo::UniformLayoutEntry254 	UniformLayoutEntry (void)
255 		: type			(glu::TYPE_LAST)
256 		, size			(0)
257 		, blockLayoutNdx(-1)
258 		, offset		(-1)
259 		, arrayStride	(-1)
260 		, matrixStride	(-1)
261 		, isRowMajor	(false)
262 		, instanceNdx	(0)
263 	{
264 	}
265 
266 	std::string			name;
267 	glu::DataType		type;
268 	int					size;
269 	int					blockLayoutNdx;
270 	int					offset;
271 	int					arrayStride;
272 	int					matrixStride;
273 	bool				isRowMajor;
274 	int					instanceNdx;
275 };
276 
277 class UniformLayout
278 {
279 public:
280 	std::vector<BlockLayoutEntry>		blocks;
281 	std::vector<UniformLayoutEntry>		uniforms;
282 
283 	int									getUniformLayoutIndex	(int blockDeclarationNdx, const std::string& name) const;
284 	int									getBlockLayoutIndex		(int blockDeclarationNdx, int instanceNdx) const;
285 };
286 
287 class UniformBlockCase : public vkt::TestCase
288 {
289 public:
290 	enum BufferMode
291 	{
292 		BUFFERMODE_SINGLE = 0,	//!< Single buffer shared between uniform blocks.
293 		BUFFERMODE_PER_BLOCK,	//!< Per-block buffers
294 
295 		BUFFERMODE_LAST
296 	};
297 
298 								UniformBlockCase			(tcu::TestContext&	testCtx,
299 															 const std::string&	name,
300 															 const std::string&	description,
301 															 BufferMode			bufferMode);
302 								~UniformBlockCase			(void);
303 
304 	virtual	void				initPrograms				(vk::SourceCollections& programCollection) const;
305 	virtual TestInstance*		createInstance				(Context& context) const;
306 
307 protected:
308 	void						init						(void);
309 
310 	BufferMode					m_bufferMode;
311 	ShaderInterface				m_interface;
312 
313 private:
314 	std::string					m_vertShaderSource;
315 	std::string					m_fragShaderSource;
316 
317 	std::vector<deUint8>		m_data;				//!< Data.
318 	std::map<int, void*>		m_blockPointers;	//!< Reference block pointers.
319 	UniformLayout				m_uniformLayout;	//!< std140 layout.
320 };
321 
322 } // ubo
323 } // vkt
324 
325 #endif // _VKTUNIFORMBLOCKCASE_HPP
326