• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 		VTCTYPE_LAST
83 	};
84 
VarTypeComponentglu::VarTypeComponent85 				VarTypeComponent	(Type type_, int index_)	: type(type_), index(index_) {}
VarTypeComponentglu::VarTypeComponent86 				VarTypeComponent	(void)						: type(VTCTYPE_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
161 {
162 public:
163 	using iterator_category = std::forward_iterator_tag;
164 	using value_type = VarType;
165 	using difference_type = std::ptrdiff_t;
166 	using pointer = VarType*;
167 	using reference = VarType&;
168 
begin(const VarType * type)169 	static SubTypeIterator<IsExpanded>	begin				(const VarType* type) { return SubTypeIterator(type);						}
end(const VarType * type)170 	static SubTypeIterator<IsExpanded>	end					(const VarType* type) { DE_UNREF(type); return SubTypeIterator(DE_NULL);	}
171 
operator ==(const SubTypeIterator<IsExpanded> & other) const172 	bool								operator==			(const SubTypeIterator<IsExpanded>& other) const { return m_type == other.m_type && m_path == other.m_path; }
operator !=(const SubTypeIterator<IsExpanded> & other) const173 	bool								operator!=			(const SubTypeIterator<IsExpanded>& other) const { return m_type != other.m_type || m_path != other.m_path; }
174 
175 	SubTypeIterator<IsExpanded>&		operator++			(void);
operator ++(int)176 	SubTypeIterator<IsExpanded>			operator++			(int)	{ SubTypeIterator<IsExpanded> copy(*this); ++(*this); return copy; }
177 
toStream(std::ostream & str) const178 	void								toStream			(std::ostream& str) const { str << TypeAccessFormat(*m_type, m_path); }
getType(void) const179 	VarType								getType				(void) const { return getVarType(*m_type, m_path.begin(), m_path.end()); }
getPath(void) const180 	const TypeComponentVector&			getPath				(void) const { return m_path; }
181 
operator *(void) const182 	VarType								operator*			(void) const { return getType(); }
183 
184 private:
185 										SubTypeIterator		(const VarType* type);
186 
187 	void								removeTraversed		(void);
188 	void								findNext			(void);
189 
190 	const VarType*						m_type;
191 	TypeComponentVector					m_path;
192 };
193 
operator ()glu::IsBasicType194 struct IsBasicType			{ bool operator() (const VarType& type) const { return type.isBasicType(); } };
operator ()glu::IsScalarType195 struct IsScalarType			{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalar(type.getBasicType()); } };
operator ()glu::IsVectorOrScalarType196 struct IsVectorOrScalarType	{ bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalarOrVector(type.getBasicType()); } };
197 
198 typedef SubTypeIterator<IsBasicType>			BasicTypeIterator;
199 typedef SubTypeIterator<IsVectorOrScalarType>	VectorTypeIterator;
200 typedef SubTypeIterator<IsScalarType>			ScalarTypeIterator;
201 
202 template <class IsExpanded>
operator <<(std::ostream & str,const SubTypeIterator<IsExpanded> & iter)203 std::ostream& operator<< (std::ostream& str, const SubTypeIterator<IsExpanded>& iter)
204 {
205 	iter.toStream(str);
206 	return str;
207 }
208 
209 template <class IsExpanded>
SubTypeIterator(const VarType * type)210 SubTypeIterator<IsExpanded>::SubTypeIterator (const VarType* type)
211 	: m_type(type)
212 {
213 	if (m_type)
214 		findNext();
215 }
216 
217 template <class IsExpanded>
operator ++(void)218 SubTypeIterator<IsExpanded>& SubTypeIterator<IsExpanded>::operator++ (void)
219 {
220 	if (!m_path.empty())
221 	{
222 		// Remove traversed nodes.
223 		removeTraversed();
224 
225 		if (!m_path.empty())
226 			findNext();
227 		else
228 			m_type = DE_NULL; // Unset type to signal end.
229 	}
230 	else
231 	{
232 		// First type was already expanded.
233 		DE_ASSERT(IsExpanded()(getVarType(*m_type, m_path)));
234 		m_type = DE_NULL;
235 	}
236 
237 	return *this;
238 }
239 
240 template <class IsExpanded>
removeTraversed(void)241 void SubTypeIterator<IsExpanded>::removeTraversed (void)
242 {
243 	DE_ASSERT(m_type && !m_path.empty());
244 
245 	// Pop traversed nodes.
246 	while (!m_path.empty())
247 	{
248 		VarTypeComponent&	curComp		= m_path.back();
249 		VarType				parentType	= getVarType(*m_type, m_path.begin(), m_path.end()-1);
250 
251 		if (curComp.type == VarTypeComponent::MATRIX_COLUMN)
252 		{
253 			DE_ASSERT(isDataTypeMatrix(parentType.getBasicType()));
254 			if (curComp.index+1 < getDataTypeMatrixNumColumns(parentType.getBasicType()))
255 				break;
256 		}
257 		else if (curComp.type == VarTypeComponent::VECTOR_COMPONENT)
258 		{
259 			DE_ASSERT(isDataTypeVector(parentType.getBasicType()));
260 			if (curComp.index+1 < getDataTypeScalarSize(parentType.getBasicType()))
261 				break;
262 		}
263 		else if (curComp.type == VarTypeComponent::ARRAY_ELEMENT)
264 		{
265 			DE_ASSERT(parentType.isArrayType());
266 			if (curComp.index+1 < parentType.getArraySize())
267 				break;
268 		}
269 		else if (curComp.type == VarTypeComponent::STRUCT_MEMBER)
270 		{
271 			DE_ASSERT(parentType.isStructType());
272 			if (curComp.index+1 < parentType.getStructPtr()->getNumMembers())
273 				break;
274 		}
275 
276 		m_path.pop_back();
277 	}
278 }
279 
280 template <class IsExpanded>
findNext(void)281 void SubTypeIterator<IsExpanded>::findNext (void)
282 {
283 	if (!m_path.empty())
284 	{
285 		// Increment child counter in current level.
286 		VarTypeComponent& curComp = m_path.back();
287 		curComp.index += 1;
288 	}
289 
290 	for (;;)
291 	{
292 		VarType curType = getVarType(*m_type, m_path);
293 
294 		if (IsExpanded()(curType))
295 			break;
296 
297 		// Recurse into child type.
298 		if (curType.isBasicType())
299 		{
300 			DataType basicType = curType.getBasicType();
301 
302 			if (isDataTypeMatrix(basicType))
303 				m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, 0));
304 			else if (isDataTypeVector(basicType))
305 				m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, 0));
306 			else
307 				DE_ASSERT(false); // Can't expand scalars - IsExpanded() is buggy.
308 		}
309 		else if (curType.isArrayType())
310 			m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, 0));
311 		else if (curType.isStructType())
312 			m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, 0));
313 		else
314 			DE_ASSERT(false);
315 	}
316 }
317 
318 template <typename Iterator>
isValidTypePath(const VarType & type,Iterator begin,Iterator end)319 bool isValidTypePath (const VarType& type, Iterator begin, Iterator end)
320 {
321 	const VarType*	curType		= &type;
322 	Iterator		pathIter	= begin;
323 
324 	// Process struct member and array element parts of path.
325 	while (pathIter != end)
326 	{
327 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
328 		{
329 			if (!curType->isStructType() || !de::inBounds(pathIter->index, 0, curType->getStructPtr()->getNumMembers()))
330 				return false;
331 
332 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
333 		}
334 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
335 		{
336 			if (!curType->isArrayType() || (curType->getArraySize() != VarType::UNSIZED_ARRAY && !de::inBounds(pathIter->index, 0, curType->getArraySize())))
337 				return false;
338 
339 			curType = &curType->getElementType();
340 		}
341 		else
342 			break;
343 
344 		++pathIter;
345 	}
346 
347 	if (pathIter != end)
348 	{
349 		DE_ASSERT(pathIter->type == VarTypeComponent::MATRIX_COLUMN || pathIter->type == VarTypeComponent::VECTOR_COMPONENT);
350 
351 		// Current type should be basic type.
352 		if (!curType->isBasicType())
353 			return false;
354 
355 		DataType basicType = curType->getBasicType();
356 
357 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
358 		{
359 			if (!isDataTypeMatrix(basicType))
360 				return false;
361 
362 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
363 			++pathIter;
364 		}
365 
366 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
367 		{
368 			if (!isDataTypeVector(basicType))
369 				return false;
370 
371 			basicType = getDataTypeScalarType(basicType);
372 			++pathIter;
373 		}
374 	}
375 
376 	return pathIter == end;
377 }
378 
379 template <typename Iterator>
getVarType(const VarType & type,Iterator begin,Iterator end)380 VarType getVarType (const VarType& type, Iterator begin, Iterator end)
381 {
382 	TCU_CHECK(isValidTypePath(type, begin, end));
383 
384 	const VarType*	curType		= &type;
385 	Iterator		pathIter	= begin;
386 
387 	// Process struct member and array element parts of path.
388 	while (pathIter != end)
389 	{
390 		if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
391 			curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
392 		else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
393 			curType = &curType->getElementType();
394 		else
395 			break;
396 
397 		++pathIter;
398 	}
399 
400 	if (pathIter != end)
401 	{
402 		DataType	basicType	= curType->getBasicType();
403 		Precision	precision	= curType->getPrecision();
404 
405 		if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
406 		{
407 			basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
408 			++pathIter;
409 		}
410 
411 		if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
412 		{
413 			basicType = getDataTypeScalarType(basicType);
414 			++pathIter;
415 		}
416 
417 		DE_ASSERT(pathIter == end);
418 		return VarType(basicType, precision);
419 	}
420 	else
421 		return VarType(*curType);
422 }
423 
424 } // glu
425 
426 #endif // _GLUVARTYPEUTIL_HPP
427