1 #ifndef _GLUVARTYPEUTIL_HPP
2 #define _GLUVARTYPEUTIL_HPP
3 /*-------------------------------------------------------------------------
4  * drawElements Quality Program OpenGL ES Utilities
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 Shader variable type utilities.
24  *//*--------------------------------------------------------------------*/
25 
26 #include "tcuDefs.hpp"
27 #include "gluVarType.hpp"
28 
29 #include <vector>
30 #include <string>
31 #include <iterator>
32 
33 namespace glu
34 {
35 
36 // Variable path tokenizer
37 
38 class VarTokenizer
39 {
40 public:
41 	enum Token
42 	{
43 		TOKEN_IDENTIFIER = 0,
44 		TOKEN_LEFT_BRACKET,
45 		TOKEN_RIGHT_BRACKET,
46 		TOKEN_PERIOD,
47 		TOKEN_NUMBER,
48 		TOKEN_END,
49 
50 		TOKEN_LAST
51 	};
52 
53 					VarTokenizer					(const char* str);
~VarTokenizer(void)54 					~VarTokenizer					(void) {}
55 
getToken(void) const56 	Token			getToken						(void) const { return m_token;															}
getIdentifier(void) const57 	std::string		getIdentifier					(void) const { return std::string(m_str+m_tokenStart, m_str+m_tokenStart+m_tokenLen);	}
58 	int				getNumber						(void) const;
getCurrentTokenStartLocation(void) const59 	int				getCurrentTokenStartLocation	(void) const { return m_tokenStart;														}
getCurrentTokenEndLocation(void) const60 	int				getCurrentTokenEndLocation		(void) const { return m_tokenStart + m_tokenLen;										}
61 	void			advance							(void);
62 
63 private:
64 	const char*		m_str;
65 
66 	Token			m_token;
67 	int				m_tokenStart;
68 	int				m_tokenLen;
69 };
70 
71 // VarType subtype path utilities.
72 
73 struct VarTypeComponent
74 {
75 	enum Type
76 	{
77 		STRUCT_MEMBER = 0,
78 		ARRAY_ELEMENT,
79 		MATRIX_COLUMN,
80 		VECTOR_COMPONENT,
81 
82 		TYPE_LAST
83 	};
84 
VarTypeComponentglu::VarTypeComponent85 				VarTypeComponent	(Type type_, int index_)	: type(type_), index(index_) {}
VarTypeComponentglu::VarTypeComponent86 				VarTypeComponent	(void)						: type(TYPE_LAST), index(0) {}
87 
operator ==glu::VarTypeComponent88 	bool		operator==			(const VarTypeComponent& other) const { return type == other.type && index == other.index; }
operator !=glu::VarTypeComponent89 	bool		operator!=			(const VarTypeComponent& other) const { return type != other.type || index != other.index; }
90 
91 	Type		type;
92 	int			index;
93 };
94 
95 typedef std::vector<VarTypeComponent> TypeComponentVector;
96 
97 // TypeComponentVector utilties.
98 
99 template <typename Iterator>
100 bool			isValidTypePath		(const VarType& type, Iterator begin, Iterator end);
101 
102 template <typename Iterator>
103 VarType			getVarType			(const VarType& type, Iterator begin, Iterator end);
104 
isValidTypePath(const VarType & type,const TypeComponentVector & path)105 inline bool		isValidTypePath		(const VarType& type, const TypeComponentVector& path) { return isValidTypePath(type, path.begin(), path.end()); }
getVarType(const VarType & type,const TypeComponentVector & path)106 inline VarType	getVarType			(const VarType& type, const TypeComponentVector& path) { return getVarType(type, path.begin(), path.end()); }
107 
108 std::string		parseVariableName	(const char* nameWithPath);
109 void			parseTypePath		(const char* nameWithPath, const VarType& type, TypeComponentVector& path);
110 
111 // Type path formatter.
112 
113 struct TypeAccessFormat
114 {
TypeAccessFormatglu::TypeAccessFormat115 	TypeAccessFormat (const VarType& type_, const TypeComponentVector& path_) : type(type_), path(path_) {}
116 
117 	const VarType&					type;
118 	const TypeComponentVector&		path;
119 };
120 
121 std::ostream&		operator<<		(std::ostream& str, const TypeAccessFormat& format);
122 
123 // Subtype path builder.
124 
125 class SubTypeAccess
126 {
127 public:
128 								SubTypeAccess		(const VarType& type);
129 
member(int ndx)130 	SubTypeAccess&				member				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access struct element.
element(int ndx)131 	SubTypeAccess&				element				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access array element.
column(int ndx)132 	SubTypeAccess&				column				(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access column.
component(int ndx)133 	SubTypeAccess&				component			(int ndx)	{ m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT,	ndx)); DE_ASSERT(isValid()); return *this; } //!< Access component.
parent(void)134 	SubTypeAccess&				parent				(void)		{ DE_ASSERT(!m_path.empty()); m_path.pop_back(); return *this; }
135 
member(int ndx) const136 	SubTypeAccess				member				(int ndx) const { return SubTypeAccess(*this).member(ndx);		}
element(int ndx) const137 	SubTypeAccess				element				(int ndx) const { return SubTypeAccess(*this).element(ndx);		}
column(int ndx) const138 	SubTypeAccess				column				(int ndx) const { return SubTypeAccess(*this).column(ndx);		}
component(int ndx) const139 	SubTypeAccess				component			(int ndx) const { return SubTypeAccess(*this).component(ndx);	}
parent(void) const140 	SubTypeAccess				parent				(void) const	{ return SubTypeAccess(*this).parent();			}
141 
isValid(void) const142 	bool						isValid				(void) const	{ return isValidTypePath(m_type, m_path);		}
getType(void) const143 	VarType						getType				(void) const	{ return getVarType(m_type, m_path);			}
getPath(void) const144 	const TypeComponentVector&	getPath				(void) const	{ return m_path;								}
145 
empty(void) const146 	bool						empty				(void) const { return m_path.empty(); }
147 
operator ==(const SubTypeAccess & other) const148 	bool						operator==			(const SubTypeAccess& other) const { return m_path == other.m_path && m_type == other.m_type; }
operator !=(const SubTypeAccess & other) const149 	bool						operator!=			(const SubTypeAccess& other) const { return m_path != other.m_path || m_type != other.m_type; }
150 
151 private:
152 	VarType						m_type;
153 	TypeComponentVector			m_path;
154 };
155 
156 // Subtype iterator.
157 
158 // \note VarType must be live during iterator usage.
159 template <class IsExpanded>
160 class SubTypeIterator : public std::iterator<std::forward_iterator_tag, VarType>
161 {
162 public:
begin(const VarType * type)163 	static SubTypeIterator<IsExpanded>	begin				(const VarType* type) { return SubTypeIterator(type);						}
end(const VarType * type)164 	static SubTypeIterator<IsExpanded>	end					(const VarType* type) { DE_UNREF(type); return SubTypeIterator(DE_NULL);	}
165 
operator ==(const SubTypeIterator<IsExpanded> & other) const166 	bool								operator==			(const SubTypeIterator<IsExpanded>& other) const { return m_type == other.m_type && m_path == other.m_path; }
operator !=(const SubTypeIterator<IsExpanded> & other) const167 	bool								operator!=			(const SubTypeIterator<IsExpanded>& other) const { return m_type != other.m_type || m_path != other.m_path; }
168 
169 	SubTypeIterator<IsExpanded>&		operator++			(void);
operator ++(int)170 	SubTypeIterator<IsExpanded>			operator++			(int)	{ SubTypeIterator<IsExpanded> copy(*this); ++(*this); return copy; }
171 
toStream(std::ostream & str) const172 	void								toStream			(std::ostream& str) const { str << TypeAccessFormat(*m_type, m_path); }
getType(void) const173 	VarType								getType				(void) const { return getVarType(*m_type, m_path.begin(), m_path.end()); }
getPath(void) const174 	const TypeComponentVector&			getPath				(void) const { return m_path; }
175 
operator *(void) const176 	VarType								operator*			(void) const { return getType(); }
177 
178 private:
179 										SubTypeIterator		(const VarType* type);
180 
181 	void								removeTraversed		(void);
182 	void								findNext			(void);
183 
184 	const VarType*						m_type;
185 	TypeComponentVector					m_path;
186 };
187 
operator ()glu::IsBasicType188 struct IsBasicType			{ bool operator() (const VarType& type) const { return type.isBasicType(); } };
operator ()glu::IsScalarType189 struct IsScalarType			{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalar(type.getBasicType()); } };
operator ()glu::IsVectorOrScalarType190 struct IsVectorOrScalarType	{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalarOrVector(type.getBasicType()); } };
191 
192 typedef SubTypeIterator<IsBasicType>			BasicTypeIterator;
193 typedef SubTypeIterator<IsVectorOrScalarType>	VectorTypeIterator;
194 typedef SubTypeIterator<IsScalarType>			ScalarTypeIterator;
195 
196 template <class IsExpanded>
operator <<(std::ostream & str,const SubTypeIterator<IsExpanded> & iter)197 std::ostream& operator<< (std::ostream& str, const SubTypeIterator<IsExpanded>& iter)
198 {
199 	iter.toStream(str);
200 	return str;
201 }
202 
203 template <class IsExpanded>
SubTypeIterator(const VarType * type)204 SubTypeIterator<IsExpanded>::SubTypeIterator (const VarType* type)
205 	: m_type(type)
206 {
207 	if (m_type)
208 		findNext();
209 }
210 
211 template <class IsExpanded>
operator ++(void)212 SubTypeIterator<IsExpanded>& SubTypeIterator<IsExpanded>::operator++ (void)
213 {
214 	if (!m_path.empty())
215 	{
216 		// Remove traversed nodes.
217 		removeTraversed();
218 
219 		if (!m_path.empty())
220 			findNext();
221 		else
222 			m_type = DE_NULL; // Unset type to signal end.
223 	}
224 	else
225 	{
226 		// First type was already expanded.
227 		DE_ASSERT(IsExpanded()(getVarType(*m_type, m_path)));
228 		m_type = DE_NULL;
229 	}
230 
231 	return *this;
232 }
233 
234 template <class IsExpanded>
removeTraversed(void)235 void SubTypeIterator<IsExpanded>::removeTraversed (void)
236 {
237 	DE_ASSERT(m_type && !m_path.empty());
238 
239 	// Pop traversed nodes.
240 	while (!m_path.empty())
241 	{
242 		VarTypeComponent&	curComp		= m_path.back();
243 		VarType				parentType	= getVarType(*m_type, m_path.begin(), m_path.end()-1);
244 
245 		if (curComp.type == VarTypeComponent::MATRIX_COLUMN)
246 		{
247 			DE_ASSERT(isDataTypeMatrix(parentType.getBasicType()));
248 			if (curComp.index+1 < getDataTypeMatrixNumColumns(parentType.getBasicType()))
249 				break;
250 		}
251 		else if (curComp.type == VarTypeComponent::VECTOR_COMPONENT)
252 		{
253 			DE_ASSERT(isDataTypeVector(parentType.getBasicType()));
254 			if (curComp.index+1 < getDataTypeScalarSize(parentType.getBasicType()))
255 				break;
256 		}
257 		else if (curComp.type == VarTypeComponent::ARRAY_ELEMENT)
258 		{
259 			DE_ASSERT(parentType.isArrayType());
260 			if (curComp.index+1 < parentType.getArraySize())
261 				break;
262 		}
263 		else if (curComp.type == VarTypeComponent::STRUCT_MEMBER)
264 		{
265 			DE_ASSERT(parentType.isStructType());
266 			if (curComp.index+1 < parentType.getStructPtr()->getNumMembers())
267 				break;
268 		}
269 
270 		m_path.pop_back();
271 	}
272 }
273 
274 template <class IsExpanded>
findNext(void)275 void SubTypeIterator<IsExpanded>::findNext (void)
276 {
277 	if (!m_path.empty())
278 	{
279 		// Increment child counter in current level.
280 		VarTypeComponent& curComp = m_path.back();
281 		curComp.index += 1;
282 	}
283 
284 	for (;;)
285 	{
286 		VarType curType = getVarType(*m_type, m_path);
287 
288 		if (IsExpanded()(curType))
289 			break;
290 
291 		// Recurse into child type.
292 		if (curType.isBasicType())
293 		{
294 			DataType basicType = curType.getBasicType();
295 
296 			if (isDataTypeMatrix(basicType))
297 				m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, 0));
298 			else if (isDataTypeVector(basicType))
299 				m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, 0));
300 			else
301 				DE_ASSERT(false); // Can't expand scalars - IsExpanded() is buggy.
302 		}
303 		else if (curType.isArrayType())
304 			m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, 0));
305 		else if (curType.isStructType())
306 			m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, 0));
307 		else
308 			DE_ASSERT(false);
309 	}
310 }
311 
312 template <typename Iterator>
isValidTypePath(const VarType & type,Iterator begin,Iterator end)313 bool isValidTypePath (const VarType& type, Iterator begin, Iterator end)
314 {
315 	const VarType*	curType		= &type;
316 	Iterator		pathIter	= begin;
317 
318 	// Process struct member and array element parts of path.
319 	while (pathIter != end)
320 	{
321 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
322 		{
323 			if (!curType->isStructType() || !de::inBounds(pathIter->index, 0, curType->getStructPtr()->getNumMembers()))
324 				return false;
325 
326 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
327 		}
328 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
329 		{
330 			if (!curType->isArrayType() || (curType->getArraySize() != VarType::UNSIZED_ARRAY && !de::inBounds(pathIter->index, 0, curType->getArraySize())))
331 				return false;
332 
333 			curType = &curType->getElementType();
334 		}
335 		else
336 			break;
337 
338 		++pathIter;
339 	}
340 
341 	if (pathIter != end)
342 	{
343 		DE_ASSERT(pathIter->type == VarTypeComponent::MATRIX_COLUMN || pathIter->type == VarTypeComponent::VECTOR_COMPONENT);
344 
345 		// Current type should be basic type.
346 		if (!curType->isBasicType())
347 			return false;
348 
349 		DataType basicType = curType->getBasicType();
350 
351 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
352 		{
353 			if (!isDataTypeMatrix(basicType))
354 				return false;
355 
356 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
357 			++pathIter;
358 		}
359 
360 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
361 		{
362 			if (!isDataTypeVector(basicType))
363 				return false;
364 
365 			basicType = getDataTypeScalarType(basicType);
366 			++pathIter;
367 		}
368 	}
369 
370 	return pathIter == end;
371 }
372 
373 template <typename Iterator>
getVarType(const VarType & type,Iterator begin,Iterator end)374 VarType getVarType (const VarType& type, Iterator begin, Iterator end)
375 {
376 	TCU_CHECK(isValidTypePath(type, begin, end));
377 
378 	const VarType*	curType		= &type;
379 	Iterator		pathIter	= begin;
380 
381 	// Process struct member and array element parts of path.
382 	while (pathIter != end)
383 	{
384 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
385 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
386 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
387 			curType = &curType->getElementType();
388 		else
389 			break;
390 
391 		++pathIter;
392 	}
393 
394 	if (pathIter != end)
395 	{
396 		DataType	basicType	= curType->getBasicType();
397 		Precision	precision	= curType->getPrecision();
398 
399 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
400 		{
401 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
402 			++pathIter;
403 		}
404 
405 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
406 		{
407 			basicType = getDataTypeScalarType(basicType);
408 			++pathIter;
409 		}
410 
411 		DE_ASSERT(pathIter == end);
412 		return VarType(basicType, precision);
413 	}
414 	else
415 		return VarType(*curType);
416 }
417 
418 } // glu
419 
420 #endif // _GLUVARTYPEUTIL_HPP
421