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 
30 namespace glu
31 {
32 class RenderContext;
33 }
34 
35 namespace deqp
36 {
37 namespace gls
38 {
39 
40 // Uniform block details.
41 namespace ub
42 {
43 
44 enum 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 
69 class StructType;
70 
71 class VarType
72 {
73 public:
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 
isBasicType(void) const81 	bool				isBasicType		(void) const	{ return m_type == TYPE_BASIC;	}
isArrayType(void) const82 	bool				isArrayType		(void) const	{ return m_type == TYPE_ARRAY;	}
isStructType(void) const83 	bool				isStructType	(void) const	{ return m_type == TYPE_STRUCT;	}
84 
getFlags(void) const85 	deUint32			getFlags		(void) const	{ return m_flags;					}
getBasicType(void) const86 	glu::DataType		getBasicType	(void) const	{ return m_data.basicType;			}
87 
getElementType(void) const88 	const VarType&		getElementType	(void) const	{ return *m_data.array.elementType;	}
getArraySize(void) const89 	int					getArraySize	(void) const	{ return m_data.array.size;			}
90 
getStruct(void) const91 	const StructType&	getStruct		(void) const	{ return *m_data.structPtr;			}
92 
93 	VarType&			operator=		(const VarType& other);
94 
95 private:
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 
Data(void)117 		Data (void)
118 		{
119 			array.elementType	= DE_NULL;
120 			array.size			= 0;
121 		};
122 	} m_data;
123 };
124 
125 class StructMember
126 {
127 public:
StructMember(const char * name,const VarType & type,deUint32 flags)128 						StructMember	(const char* name, const VarType& type, deUint32 flags) : m_name(name), m_type(type), m_flags(flags) {}
StructMember(void)129 						StructMember	(void) : m_flags(0) {}
130 
getName(void) const131 	const char*			getName			(void) const { return m_name.c_str();	}
getType(void) const132 	const VarType&		getType			(void) const { return m_type;			}
getFlags(void) const133 	deUint32			getFlags		(void) const { return m_flags;			}
134 
135 private:
136 	std::string			m_name;
137 	VarType				m_type;
138 	deUint32			m_flags;
139 };
140 
141 class StructType
142 {
143 public:
144 	typedef std::vector<StructMember>::iterator			Iterator;
145 	typedef std::vector<StructMember>::const_iterator	ConstIterator;
146 
StructType(const char * typeName)147 								StructType		(const char* typeName) : m_typeName(typeName) {}
~StructType(void)148 								~StructType		(void) {}
149 
getTypeName(void) const150 	const char*					getTypeName		(void) const	{ return m_typeName.empty() ? DE_NULL : m_typeName.c_str();	}
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 char* 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 char* name, const VarType& type, deUint32 flags = 0);
168 
getName(void) const169 	const char*		getName			(void) const { return m_name.c_str();	}
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 char* blockName);
186 
getBlockName(void) const187 	const char*				getBlockName		(void) const { return m_blockName.c_str();		}
getInstanceName(void) const188 	const char*				getInstanceName		(void) const { return m_instanceName.empty() ? DE_NULL : m_instanceName.c_str();	}
isArray(void) const189 	bool					isArray				(void) const { return m_arraySize > 0;			}
getArraySize(void) const190 	int						getArraySize		(void) const { return m_arraySize;				}
getFlags(void) const191 	deUint32				getFlags			(void) const { return m_flags;					}
192 
setInstanceName(const char * name)193 	void					setInstanceName		(const char* name)			{ m_instanceName = name;			}
setFlags(deUint32 flags)194 	void					setFlags			(deUint32 flags)			{ m_flags = flags;					}
setArraySize(int arraySize)195 	void					setArraySize		(int arraySize)				{ m_arraySize = arraySize;			}
addUniform(const Uniform & uniform)196 	void					addUniform			(const Uniform& uniform)	{ m_uniforms.push_back(uniform);	}
197 
begin(void)198 	inline Iterator			begin				(void)			{ return m_uniforms.begin();	}
begin(void) const199 	inline ConstIterator	begin				(void) const	{ return m_uniforms.begin();	}
end(void)200 	inline Iterator			end					(void)			{ return m_uniforms.end();		}
end(void) const201 	inline ConstIterator	end					(void) const	{ return m_uniforms.end();		}
202 
203 private:
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 
211 class ShaderInterface
212 {
213 public:
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 
getNumUniformBlocks(void) const223 	int							getNumUniformBlocks		(void) const	{ return (int)m_uniformBlocks.size();	}
getUniformBlock(int ndx) const224 	const UniformBlock&			getUniformBlock			(int ndx) const	{ return *m_uniformBlocks[ndx];			}
225 
226 private:
227 	std::vector<StructType*>	m_structs;
228 	std::vector<UniformBlock*>	m_uniformBlocks;
229 };
230 
231 class UniformLayout;
232 
233 } // ub
234 
235 class UniformBlockCase : public tcu::TestCase
236 {
237 public:
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 
251 protected:
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