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); 54 ~VarTokenizer (void) {} 55 56 Token getToken (void) const { return m_token; } 57 std::string getIdentifier (void) const { return std::string(m_str+m_tokenStart, m_str+m_tokenStart+m_tokenLen); } 58 int getNumber (void) const; 59 int getCurrentTokenStartLocation (void) const { return m_tokenStart; } 60 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 TYPE_LAST 83 }; 84 85 VarTypeComponent (Type type_, int index_) : type(type_), index(index_) {} 86 VarTypeComponent (void) : type(TYPE_LAST), index(0) {} 87 88 bool operator== (const VarTypeComponent& other) const { return type == other.type && index == other.index; } 89 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 105 inline bool isValidTypePath (const VarType& type, const TypeComponentVector& path) { return isValidTypePath(type, path.begin(), path.end()); } 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 { 115 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 130 SubTypeAccess& member (int ndx) { m_path.push_back(VarTypeComponent(VarTypeComponent::STRUCT_MEMBER, ndx)); DE_ASSERT(isValid()); return *this; } //!< Access struct element. 131 SubTypeAccess& element (int ndx) { m_path.push_back(VarTypeComponent(VarTypeComponent::ARRAY_ELEMENT, ndx)); DE_ASSERT(isValid()); return *this; } //!< Access array element. 132 SubTypeAccess& column (int ndx) { m_path.push_back(VarTypeComponent(VarTypeComponent::MATRIX_COLUMN, ndx)); DE_ASSERT(isValid()); return *this; } //!< Access column. 133 SubTypeAccess& component (int ndx) { m_path.push_back(VarTypeComponent(VarTypeComponent::VECTOR_COMPONENT, ndx)); DE_ASSERT(isValid()); return *this; } //!< Access component. 134 SubTypeAccess& parent (void) { DE_ASSERT(!m_path.empty()); m_path.pop_back(); return *this; } 135 136 SubTypeAccess member (int ndx) const { return SubTypeAccess(*this).member(ndx); } 137 SubTypeAccess element (int ndx) const { return SubTypeAccess(*this).element(ndx); } 138 SubTypeAccess column (int ndx) const { return SubTypeAccess(*this).column(ndx); } 139 SubTypeAccess component (int ndx) const { return SubTypeAccess(*this).component(ndx); } 140 SubTypeAccess parent (void) const { return SubTypeAccess(*this).parent(); } 141 142 bool isValid (void) const { return isValidTypePath(m_type, m_path); } 143 VarType getType (void) const { return getVarType(m_type, m_path); } 144 const TypeComponentVector& getPath (void) const { return m_path; } 145 146 bool empty (void) const { return m_path.empty(); } 147 148 bool operator== (const SubTypeAccess& other) const { return m_path == other.m_path && m_type == other.m_type; } 149 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: 163 static SubTypeIterator<IsExpanded> begin (const VarType* type) { return SubTypeIterator(type); } 164 static SubTypeIterator<IsExpanded> end (const VarType* type) { DE_UNREF(type); return SubTypeIterator(DE_NULL); } 165 166 bool operator== (const SubTypeIterator<IsExpanded>& other) const { return m_type == other.m_type && m_path == other.m_path; } 167 bool operator!= (const SubTypeIterator<IsExpanded>& other) const { return m_type != other.m_type || m_path != other.m_path; } 168 169 SubTypeIterator<IsExpanded>& operator++ (void); 170 SubTypeIterator<IsExpanded> operator++ (int) { SubTypeIterator<IsExpanded> copy(*this); ++(*this); return copy; } 171 172 void toStream (std::ostream& str) const { str << TypeAccessFormat(*m_type, m_path); } 173 VarType getType (void) const { return getVarType(*m_type, m_path.begin(), m_path.end()); } 174 const TypeComponentVector& getPath (void) const { return m_path; } 175 176 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 188 struct IsBasicType { bool operator() (const VarType& type) const { return type.isBasicType(); } }; 189 struct IsScalarType { bool operator() (const VarType& type) const { return type.isBasicType() && isDataTypeScalar(type.getBasicType()); } }; 190 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> 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> 204 SubTypeIterator<IsExpanded>::SubTypeIterator (const VarType* type) 205 : m_type(type) 206 { 207 if (m_type) 208 findNext(); 209 } 210 211 template <class IsExpanded> 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> 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> 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> 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> 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