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 : 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