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 {
56 }
57
getToken(void) const58 Token getToken(void) const
59 {
60 return m_token;
61 }
getIdentifier(void) const62 std::string getIdentifier(void) const
63 {
64 return std::string(m_str + m_tokenStart, m_str + m_tokenStart + m_tokenLen);
65 }
66 int getNumber(void) const;
getCurrentTokenStartLocation(void) const67 int getCurrentTokenStartLocation(void) const
68 {
69 return m_tokenStart;
70 }
getCurrentTokenEndLocation(void) const71 int getCurrentTokenEndLocation(void) const
72 {
73 return m_tokenStart + m_tokenLen;
74 }
75 void advance(void);
76
77 private:
78 const char *m_str;
79
80 Token m_token;
81 int m_tokenStart;
82 int m_tokenLen;
83 };
84
85 // VarType subtype path utilities.
86
87 struct VarTypeComponent
88 {
89 enum Type
90 {
91 STRUCT_MEMBER = 0,
92 ARRAY_ELEMENT,
93 MATRIX_COLUMN,
94 VECTOR_COMPONENT,
95
96 VTCTYPE_LAST
97 };
98
VarTypeComponentglu::VarTypeComponent99 VarTypeComponent(Type type_, int index_) : type(type_), index(index_)
100 {
101 }
VarTypeComponentglu::VarTypeComponent102 VarTypeComponent(void) : type(VTCTYPE_LAST), index(0)
103 {
104 }
105
operator ==glu::VarTypeComponent106 bool operator==(const VarTypeComponent &other) const
107 {
108 return type == other.type && index == other.index;
109 }
operator !=glu::VarTypeComponent110 bool operator!=(const VarTypeComponent &other) const
111 {
112 return type != other.type || index != other.index;
113 }
114
115 Type type;
116 int index;
117 };
118
119 typedef std::vector<VarTypeComponent> TypeComponentVector;
120
121 // TypeComponentVector utilties.
122
123 template <typename Iterator>
124 bool isValidTypePath(const VarType &type, Iterator begin, Iterator end);
125
126 template <typename Iterator>
127 VarType getVarType(const VarType &type, Iterator begin, Iterator end);
128
isValidTypePath(const VarType & type,const TypeComponentVector & path)129 inline bool isValidTypePath(const VarType &type, const TypeComponentVector &path)
130 {
131 return isValidTypePath(type, path.begin(), path.end());
132 }
getVarType(const VarType & type,const TypeComponentVector & path)133 inline VarType getVarType(const VarType &type, const TypeComponentVector &path)
134 {
135 return getVarType(type, path.begin(), path.end());
136 }
137
138 std::string parseVariableName(const char *nameWithPath);
139 void parseTypePath(const char *nameWithPath, const VarType &type, TypeComponentVector &path);
140
141 // Type path formatter.
142
143 struct TypeAccessFormat
144 {
TypeAccessFormatglu::TypeAccessFormat145 TypeAccessFormat(const VarType &type_, const TypeComponentVector &path_) : type(type_), path(path_)
146 {
147 }
148
149 const VarType &type;
150 const TypeComponentVector &path;
151 };
152
153 std::ostream &operator<<(std::ostream &str, const TypeAccessFormat &format);
154
155 // Subtype path builder.
156
157 class SubTypeAccess
158 {
159 public:
160 SubTypeAccess(const VarType &type);
161
member(int ndx)162 SubTypeAccess &member(int ndx)
163 {
164 m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx));
165 DE_ASSERT(isValid());
166 return *this;
167 } //!< Access struct element.
element(int ndx)168 SubTypeAccess &element(int ndx)
169 {
170 m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx));
171 DE_ASSERT(isValid());
172 return *this;
173 } //!< Access array element.
column(int ndx)174 SubTypeAccess &column(int ndx)
175 {
176 m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx));
177 DE_ASSERT(isValid());
178 return *this;
179 } //!< Access column.
component(int ndx)180 SubTypeAccess &component(int ndx)
181 {
182 m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx));
183 DE_ASSERT(isValid());
184 return *this;
185 } //!< Access component.
parent(void)186 SubTypeAccess &parent(void)
187 {
188 DE_ASSERT(!m_path.empty());
189 m_path.pop_back();
190 return *this;
191 }
192
member(int ndx) const193 SubTypeAccess member(int ndx) const
194 {
195 return SubTypeAccess(*this).member(ndx);
196 }
element(int ndx) const197 SubTypeAccess element(int ndx) const
198 {
199 return SubTypeAccess(*this).element(ndx);
200 }
column(int ndx) const201 SubTypeAccess column(int ndx) const
202 {
203 return SubTypeAccess(*this).column(ndx);
204 }
component(int ndx) const205 SubTypeAccess component(int ndx) const
206 {
207 return SubTypeAccess(*this).component(ndx);
208 }
parent(void) const209 SubTypeAccess parent(void) const
210 {
211 return SubTypeAccess(*this).parent();
212 }
213
isValid(void) const214 bool isValid(void) const
215 {
216 return isValidTypePath(m_type, m_path);
217 }
getType(void) const218 VarType getType(void) const
219 {
220 return getVarType(m_type, m_path);
221 }
getPath(void) const222 const TypeComponentVector &getPath(void) const
223 {
224 return m_path;
225 }
226
empty(void) const227 bool empty(void) const
228 {
229 return m_path.empty();
230 }
231
operator ==(const SubTypeAccess & other) const232 bool operator==(const SubTypeAccess &other) const
233 {
234 return m_path == other.m_path && m_type == other.m_type;
235 }
operator !=(const SubTypeAccess & other) const236 bool operator!=(const SubTypeAccess &other) const
237 {
238 return m_path != other.m_path || m_type != other.m_type;
239 }
240
241 private:
242 VarType m_type;
243 TypeComponentVector m_path;
244 };
245
246 // Subtype iterator.
247
248 // \note VarType must be live during iterator usage.
249 template <class IsExpanded>
250 class SubTypeIterator
251 {
252 public:
253 using iterator_category = std::forward_iterator_tag;
254 using value_type = VarType;
255 using difference_type = std::ptrdiff_t;
256 using pointer = VarType *;
257 using reference = VarType &;
258
begin(const VarType * type)259 static SubTypeIterator<IsExpanded> begin(const VarType *type)
260 {
261 return SubTypeIterator(type);
262 }
end(const VarType * type)263 static SubTypeIterator<IsExpanded> end(const VarType *type)
264 {
265 DE_UNREF(type);
266 return SubTypeIterator(DE_NULL);
267 }
268
operator ==(const SubTypeIterator<IsExpanded> & other) const269 bool operator==(const SubTypeIterator<IsExpanded> &other) const
270 {
271 return m_type == other.m_type && m_path == other.m_path;
272 }
operator !=(const SubTypeIterator<IsExpanded> & other) const273 bool operator!=(const SubTypeIterator<IsExpanded> &other) const
274 {
275 return m_type != other.m_type || m_path != other.m_path;
276 }
277
278 SubTypeIterator<IsExpanded> &operator++(void);
operator ++(int)279 SubTypeIterator<IsExpanded> operator++(int)
280 {
281 SubTypeIterator<IsExpanded> copy(*this);
282 ++(*this);
283 return copy;
284 }
285
toStream(std::ostream & str) const286 void toStream(std::ostream &str) const
287 {
288 str << TypeAccessFormat(*m_type, m_path);
289 }
getType(void) const290 VarType getType(void) const
291 {
292 return getVarType(*m_type, m_path.begin(), m_path.end());
293 }
getPath(void) const294 const TypeComponentVector &getPath(void) const
295 {
296 return m_path;
297 }
298
operator *(void) const299 VarType operator*(void) const
300 {
301 return getType();
302 }
303
304 private:
305 SubTypeIterator(const VarType *type);
306
307 void removeTraversed(void);
308 void findNext(void);
309
310 const VarType *m_type;
311 TypeComponentVector m_path;
312 };
313
314 struct IsBasicType
315 {
operator ()glu::IsBasicType316 bool operator()(const VarType &type) const
317 {
318 return type.isBasicType();
319 }
320 };
321 struct IsScalarType
322 {
operator ()glu::IsScalarType323 bool operator()(const VarType &type) const
324 {
325 return type.isBasicType() && isDataTypeScalar(type.getBasicType());
326 }
327 };
328 struct IsVectorOrScalarType
329 {
operator ()glu::IsVectorOrScalarType330 bool operator()(const VarType &type) const
331 {
332 return type.isBasicType() && isDataTypeScalarOrVector(type.getBasicType());
333 }
334 };
335
336 typedef SubTypeIterator<IsBasicType> BasicTypeIterator;
337 typedef SubTypeIterator<IsVectorOrScalarType> VectorTypeIterator;
338 typedef SubTypeIterator<IsScalarType> ScalarTypeIterator;
339
340 template <class IsExpanded>
operator <<(std::ostream & str,const SubTypeIterator<IsExpanded> & iter)341 std::ostream &operator<<(std::ostream &str, const SubTypeIterator<IsExpanded> &iter)
342 {
343 iter.toStream(str);
344 return str;
345 }
346
347 template <class IsExpanded>
SubTypeIterator(const VarType * type)348 SubTypeIterator<IsExpanded>::SubTypeIterator(const VarType *type) : m_type(type)
349 {
350 if (m_type)
351 findNext();
352 }
353
354 template <class IsExpanded>
operator ++(void)355 SubTypeIterator<IsExpanded> &SubTypeIterator<IsExpanded>::operator++(void)
356 {
357 if (!m_path.empty())
358 {
359 // Remove traversed nodes.
360 removeTraversed();
361
362 if (!m_path.empty())
363 findNext();
364 else
365 m_type = DE_NULL; // Unset type to signal end.
366 }
367 else
368 {
369 // First type was already expanded.
370 DE_ASSERT(IsExpanded()(getVarType(*m_type, m_path)));
371 m_type = DE_NULL;
372 }
373
374 return *this;
375 }
376
377 template <class IsExpanded>
removeTraversed(void)378 void SubTypeIterator<IsExpanded>::removeTraversed(void)
379 {
380 DE_ASSERT(m_type && !m_path.empty());
381
382 // Pop traversed nodes.
383 while (!m_path.empty())
384 {
385 VarTypeComponent &curComp = m_path.back();
386 VarType parentType = getVarType(*m_type, m_path.begin(), m_path.end() - 1);
387
388 if (curComp.type == VarTypeComponent::MATRIX_COLUMN)
389 {
390 DE_ASSERT(isDataTypeMatrix(parentType.getBasicType()));
391 if (curComp.index + 1 < getDataTypeMatrixNumColumns(parentType.getBasicType()))
392 break;
393 }
394 else if (curComp.type == VarTypeComponent::VECTOR_COMPONENT)
395 {
396 DE_ASSERT(isDataTypeVector(parentType.getBasicType()));
397 if (curComp.index + 1 < getDataTypeScalarSize(parentType.getBasicType()))
398 break;
399 }
400 else if (curComp.type == VarTypeComponent::ARRAY_ELEMENT)
401 {
402 DE_ASSERT(parentType.isArrayType());
403 if (curComp.index + 1 < parentType.getArraySize())
404 break;
405 }
406 else if (curComp.type == VarTypeComponent::STRUCT_MEMBER)
407 {
408 DE_ASSERT(parentType.isStructType());
409 if (curComp.index + 1 < parentType.getStructPtr()->getNumMembers())
410 break;
411 }
412
413 m_path.pop_back();
414 }
415 }
416
417 template <class IsExpanded>
findNext(void)418 void SubTypeIterator<IsExpanded>::findNext(void)
419 {
420 if (!m_path.empty())
421 {
422 // Increment child counter in current level.
423 VarTypeComponent &curComp = m_path.back();
424 curComp.index += 1;
425 }
426
427 for (;;)
428 {
429 VarType curType = getVarType(*m_type, m_path);
430
431 if (IsExpanded()(curType))
432 break;
433
434 // Recurse into child type.
435 if (curType.isBasicType())
436 {
437 DataType basicType = curType.getBasicType();
438
439 if (isDataTypeMatrix(basicType))
440 m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, 0));
441 else if (isDataTypeVector(basicType))
442 m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, 0));
443 else
444 DE_ASSERT(false); // Can't expand scalars - IsExpanded() is buggy.
445 }
446 else if (curType.isArrayType())
447 m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, 0));
448 else if (curType.isStructType())
449 m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, 0));
450 else
451 DE_ASSERT(false);
452 }
453 }
454
455 template <typename Iterator>
isValidTypePath(const VarType & type,Iterator begin,Iterator end)456 bool isValidTypePath(const VarType &type, Iterator begin, Iterator end)
457 {
458 const VarType *curType = &type;
459 Iterator pathIter = begin;
460
461 // Process struct member and array element parts of path.
462 while (pathIter != end)
463 {
464 if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
465 {
466 if (!curType->isStructType() || !de::inBounds(pathIter->index, 0, curType->getStructPtr()->getNumMembers()))
467 return false;
468
469 curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
470 }
471 else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
472 {
473 if (!curType->isArrayType() || (curType->getArraySize() != VarType::UNSIZED_ARRAY &&
474 !de::inBounds(pathIter->index, 0, curType->getArraySize())))
475 return false;
476
477 curType = &curType->getElementType();
478 }
479 else
480 break;
481
482 ++pathIter;
483 }
484
485 if (pathIter != end)
486 {
487 DE_ASSERT(pathIter->type == VarTypeComponent::MATRIX_COLUMN ||
488 pathIter->type == VarTypeComponent::VECTOR_COMPONENT);
489
490 // Current type should be basic type.
491 if (!curType->isBasicType())
492 return false;
493
494 DataType basicType = curType->getBasicType();
495
496 if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
497 {
498 if (!isDataTypeMatrix(basicType))
499 return false;
500
501 basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
502 ++pathIter;
503 }
504
505 if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
506 {
507 if (!isDataTypeVector(basicType))
508 return false;
509
510 basicType = getDataTypeScalarType(basicType);
511 ++pathIter;
512 }
513 }
514
515 return pathIter == end;
516 }
517
518 template <typename Iterator>
getVarType(const VarType & type,Iterator begin,Iterator end)519 VarType getVarType(const VarType &type, Iterator begin, Iterator end)
520 {
521 TCU_CHECK(isValidTypePath(type, begin, end));
522
523 const VarType *curType = &type;
524 Iterator pathIter = begin;
525
526 // Process struct member and array element parts of path.
527 while (pathIter != end)
528 {
529 if (pathIter->type == VarTypeComponent::STRUCT_MEMBER)
530 curType = &curType->getStructPtr()->getMember(pathIter->index).getType();
531 else if (pathIter->type == VarTypeComponent::ARRAY_ELEMENT)
532 curType = &curType->getElementType();
533 else
534 break;
535
536 ++pathIter;
537 }
538
539 if (pathIter != end)
540 {
541 DataType basicType = curType->getBasicType();
542 Precision precision = curType->getPrecision();
543
544 if (pathIter->type == VarTypeComponent::MATRIX_COLUMN)
545 {
546 basicType = getDataTypeFloatVec(getDataTypeMatrixNumRows(basicType));
547 ++pathIter;
548 }
549
550 if (pathIter != end && pathIter->type == VarTypeComponent::VECTOR_COMPONENT)
551 {
552 basicType = getDataTypeScalarType(basicType);
553 ++pathIter;
554 }
555
556 DE_ASSERT(pathIter == end);
557 return VarType(basicType, precision);
558 }
559 else
560 return VarType(*curType);
561 }
562
563 } // namespace glu
564
565 #endif // _GLUVARTYPEUTIL_HPP
566