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