xref: /aosp_15_r20/external/deqp/framework/opengl/gluVarTypeUtil.hpp (revision 35238bce31c2a825756842865a792f8cf7f89930)
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