1#ifndef _GLSUNIFORMBLOCKCASE_HPP
2#define _GLSUNIFORMBLOCKCASE_HPP
3/*-------------------------------------------------------------------------
4 * drawElements Quality Program OpenGL (ES) Module
5 * -----------------------------------------------
6 *
7 * Copyright 2014 The Android Open Source Project
8 *
9 * Licensed under the Apache License, Version 2.0 (the "License");
10 * you may not use this file except in compliance with the License.
11 * You may obtain a copy of the License at
12 *
13 *      http://www.apache.org/licenses/LICENSE-2.0
14 *
15 * Unless required by applicable law or agreed to in writing, software
16 * distributed under the License is distributed on an "AS IS" BASIS,
17 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
18 * See the License for the specific language governing permissions and
19 * limitations under the License.
20 *
21 *//*!
22 * \file
23 * \brief Uniform block tests.
24 *//*--------------------------------------------------------------------*/
25
26#include "tcuDefs.hpp"
27#include "tcuTestCase.hpp"
28#include "gluShaderUtil.hpp"
29
30namespace glu
31{
32class RenderContext;
33}
34
35namespace deqp
36{
37namespace gls
38{
39
40// Uniform block details.
41namespace ub
42{
43
44enum UniformFlags
45{
46	PRECISION_LOW		= (1<<0),
47	PRECISION_MEDIUM	= (1<<1),
48	PRECISION_HIGH		= (1<<2),
49	PRECISION_MASK		= PRECISION_LOW|PRECISION_MEDIUM|PRECISION_HIGH,
50
51	LAYOUT_SHARED		= (1<<3),
52	LAYOUT_PACKED		= (1<<4),
53	LAYOUT_STD140		= (1<<5),
54	LAYOUT_ROW_MAJOR	= (1<<6),
55	LAYOUT_COLUMN_MAJOR	= (1<<7),	//!< \note Lack of both flags means column-major matrix.
56	LAYOUT_MASK			= LAYOUT_SHARED|LAYOUT_PACKED|LAYOUT_STD140|LAYOUT_ROW_MAJOR|LAYOUT_COLUMN_MAJOR,
57
58	DECLARE_VERTEX		= (1<<8),
59	DECLARE_FRAGMENT	= (1<<9),
60	DECLARE_BOTH		= DECLARE_VERTEX|DECLARE_FRAGMENT,
61
62	UNUSED_VERTEX		= (1<<10),	//!< Uniform or struct member is not read in vertex shader.
63	UNUSED_FRAGMENT		= (1<<11),	//!< Uniform or struct member is not read in fragment shader.
64	UNUSED_BOTH			= UNUSED_VERTEX|UNUSED_FRAGMENT
65};
66
67// \todo [2012-07-25 pyry] Use glu::VarType.
68
69class StructType;
70
71class VarType
72{
73public:
74						VarType			(void);
75						VarType			(const VarType& other);
76						VarType			(glu::DataType basicType, deUint32 flags);
77						VarType			(const VarType& elementType, int arraySize);
78	explicit			VarType			(const StructType* structPtr);
79						~VarType		(void);
80
81	bool				isBasicType		(void) const	{ return m_type == TYPE_BASIC;	}
82	bool				isArrayType		(void) const	{ return m_type == TYPE_ARRAY;	}
83	bool				isStructType	(void) const	{ return m_type == TYPE_STRUCT;	}
84
85	deUint32			getFlags		(void) const	{ return m_flags;					}
86	glu::DataType		getBasicType	(void) const	{ return m_data.basicType;			}
87
88	const VarType&		getElementType	(void) const	{ return *m_data.array.elementType;	}
89	int					getArraySize	(void) const	{ return m_data.array.size;			}
90
91	const StructType&	getStruct		(void) const	{ return *m_data.structPtr;			}
92
93	VarType&			operator=		(const VarType& other);
94
95private:
96	enum Type
97	{
98		TYPE_BASIC,
99		TYPE_ARRAY,
100		TYPE_STRUCT,
101
102		TYPE_LAST
103	};
104
105	Type				m_type;
106	deUint32			m_flags;
107	union Data
108	{
109		glu::DataType		basicType;
110		struct
111		{
112			VarType*		elementType;
113			int				size;
114		} array;
115		const StructType*	structPtr;
116
117		Data (void)
118		{
119			array.elementType	= DE_NULL;
120			array.size			= 0;
121		};
122	} m_data;
123};
124
125class StructMember
126{
127public:
128						StructMember	(const char* name, const VarType& type, deUint32 flags) : m_name(name), m_type(type), m_flags(flags) {}
129						StructMember	(void) : m_flags(0) {}
130
131	const char*			getName			(void) const { return m_name.c_str();	}
132	const VarType&		getType			(void) const { return m_type;			}
133	deUint32			getFlags		(void) const { return m_flags;			}
134
135private:
136	std::string			m_name;
137	VarType				m_type;
138	deUint32			m_flags;
139};
140
141class StructType
142{
143public:
144	typedef std::vector<StructMember>::iterator			Iterator;
145	typedef std::vector<StructMember>::const_iterator	ConstIterator;
146
147								StructType		(const char* typeName) : m_typeName(typeName) {}
148								~StructType		(void) {}
149
150	const char*					getTypeName		(void) const	{ return m_typeName.empty() ? DE_NULL : m_typeName.c_str();	}
151
152	inline Iterator				begin			(void)			{ return m_members.begin();		}
153	inline ConstIterator		begin			(void) const	{ return m_members.begin();		}
154	inline Iterator				end				(void)			{ return m_members.end();		}
155	inline ConstIterator		end				(void) const	{ return m_members.end();		}
156
157	void						addMember		(const char* name, const VarType& type, deUint32 flags = 0);
158
159private:
160	std::string					m_typeName;
161	std::vector<StructMember>	m_members;
162};
163
164class Uniform
165{
166public:
167					Uniform			(const char* name, const VarType& type, deUint32 flags = 0);
168
169	const char*		getName			(void) const { return m_name.c_str();	}
170	const VarType&	getType			(void) const { return m_type;			}
171	deUint32		getFlags		(void) const { return m_flags;			}
172
173private:
174	std::string		m_name;
175	VarType			m_type;
176	deUint32		m_flags;
177};
178
179class UniformBlock
180{
181public:
182	typedef std::vector<Uniform>::iterator			Iterator;
183	typedef std::vector<Uniform>::const_iterator	ConstIterator;
184
185							UniformBlock		(const char* blockName);
186
187	const char*				getBlockName		(void) const { return m_blockName.c_str();		}
188	const char*				getInstanceName		(void) const { return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str();	}
189	bool					isArray				(void) const { return m_arraySize > 0;			}
190	int						getArraySize		(void) const { return m_arraySize;				}
191	deUint32				getFlags			(void) const { return m_flags;					}
192
193	void					setInstanceName		(const char* name)			{ m_instanceName = name;			}
194	void					setFlags			(deUint32 flags)			{ m_flags = flags;					}
195	void					setArraySize		(int arraySize)				{ m_arraySize = arraySize;			}
196	void					addUniform			(const Uniform& uniform)	{ m_uniforms.push_back(uniform);	}
197
198	inline Iterator			begin				(void)			{ return m_uniforms.begin();	}
199	inline ConstIterator	begin				(void) const	{ return m_uniforms.begin();	}
200	inline Iterator			end					(void)			{ return m_uniforms.end();		}
201	inline ConstIterator	end					(void) const	{ return m_uniforms.end();		}
202
203private:
204	std::string				m_blockName;
205	std::string				m_instanceName;
206	std::vector<Uniform>	m_uniforms;
207	int						m_arraySize;	//!< Array size or 0 if not interface block array.
208	deUint32				m_flags;
209};
210
211class ShaderInterface
212{
213public:
214								ShaderInterface			(void);
215								~ShaderInterface		(void);
216
217	StructType&					allocStruct				(const char* name);
218	const StructType*			findStruct				(const char* name) const;
219	void						getNamedStructs			(std::vector<const StructType*>& structs) const;
220
221	UniformBlock&				allocBlock				(const char* name);
222
223	int							getNumUniformBlocks		(void) const	{ return (int)m_uniformBlocks.size();	}
224	const UniformBlock&			getUniformBlock			(int ndx) const	{ return *m_uniformBlocks[ndx];			}
225
226private:
227	std::vector<StructType*>	m_structs;
228	std::vector<UniformBlock*>	m_uniformBlocks;
229};
230
231class UniformLayout;
232
233} // ub
234
235class UniformBlockCase : public tcu::TestCase
236{
237public:
238	enum BufferMode
239	{
240		BUFFERMODE_SINGLE = 0,	//!< Single buffer shared between uniform blocks.
241		BUFFERMODE_PER_BLOCK,	//!< Per-block buffers
242
243		BUFFERMODE_LAST
244	};
245
246								UniformBlockCase			(tcu::TestContext& testCtx, glu::RenderContext& renderCtx, const char* name, const char* description, glu::GLSLVersion glslVersion, BufferMode bufferMode);
247								~UniformBlockCase			(void);
248
249	IterateResult				iterate						(void);
250
251protected:
252	bool						compareStd140Blocks			(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
253	bool						compareSharedBlocks			(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
254	bool						compareTypes				(const ub::UniformLayout& refLayout, const ub::UniformLayout& cmpLayout) const;
255	bool						checkLayoutIndices			(const ub::UniformLayout& layout) const;
256	bool						checkLayoutBounds			(const ub::UniformLayout& layout) const;
257	bool						checkIndexQueries			(deUint32 program, const ub::UniformLayout& layout) const;
258
259	bool						render						(deUint32 program) const;
260
261	glu::RenderContext&			m_renderCtx;
262	glu::GLSLVersion			m_glslVersion;
263	BufferMode					m_bufferMode;
264	ub::ShaderInterface			m_interface;
265};
266
267} // gls
268} // deqp
269
270#endif // _GLSUNIFORMBLOCKCASE_HPP
271