1 /*------------------------------------------------------------------------- 2 * drawElements Quality Program OpenGL ES Utilities 3 * ------------------------------------------------ 4 * 5 * Copyright 2014 The Android Open Source Project 6 * 7 * Licensed under the Apache License, Version 2.0 (the "License"); 8 * you may not use this file except in compliance with the License. 9 * You may obtain a copy of the License at 10 * 11 * http://www.apache.org/licenses/LICENSE-2.0 12 * 13 * Unless required by applicable law or agreed to in writing, software 14 * distributed under the License is distributed on an "AS IS" BASIS, 15 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 16 * See the License for the specific language governing permissions and 17 * limitations under the License. 18 * 19 *//*! 20 * \file 21 * \brief Shader variable type. 22 *//*--------------------------------------------------------------------*/ 23 24 #include "gluVarType.hpp" 25 #include "deStringUtil.hpp" 26 27 namespace glu 28 { 29 30 VarType::VarType (void) 31 : m_type(TYPE_LAST) 32 { 33 } 34 35 VarType::VarType (const VarType& other) 36 : m_type(TYPE_LAST) 37 { 38 *this = other; 39 } 40 41 VarType::VarType (DataType basicType, Precision precision) 42 : m_type(TYPE_BASIC) 43 { 44 m_data.basic.type = basicType; 45 m_data.basic.precision = precision; 46 } 47 48 VarType::VarType (const VarType& elementType, int arraySize) 49 : m_type(TYPE_ARRAY) 50 { 51 DE_ASSERT(arraySize >= 0 || arraySize == UNSIZED_ARRAY); 52 m_data.array.size = arraySize; 53 m_data.array.elementType = new VarType(elementType); 54 } 55 56 VarType::VarType (const StructType* structPtr) 57 : m_type(TYPE_STRUCT) 58 { 59 m_data.structPtr = structPtr; 60 } 61 62 VarType::~VarType (void) 63 { 64 if (m_type == TYPE_ARRAY) 65 delete m_data.array.elementType; 66 } 67 68 VarType& VarType::operator= (const VarType& other) 69 { 70 if (this == &other) 71 return *this; // Self-assignment. 72 73 if (m_type == TYPE_ARRAY) 74 delete m_data.array.elementType; 75 76 m_type = other.m_type; 77 m_data = Data(); 78 79 if (m_type == TYPE_ARRAY) 80 { 81 m_data.array.elementType = new VarType(*other.m_data.array.elementType); 82 m_data.array.size = other.m_data.array.size; 83 } 84 else 85 m_data = other.m_data; 86 87 return *this; 88 } 89 90 int VarType::getScalarSize (void) const 91 { 92 switch (m_type) 93 { 94 case TYPE_BASIC: return glu::getDataTypeScalarSize(m_data.basic.type); 95 case TYPE_ARRAY: return m_data.array.elementType->getScalarSize()*m_data.array.size; 96 97 case TYPE_STRUCT: 98 { 99 int size = 0; 100 for (StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++) 101 size += iter->getType().getScalarSize(); 102 return size; 103 } 104 105 default: 106 DE_ASSERT(false); 107 return 0; 108 } 109 } 110 111 bool VarType::operator== (const VarType& other) const 112 { 113 if (m_type != other.m_type) 114 return false; 115 116 switch (m_type) 117 { 118 case TYPE_BASIC: 119 return m_data.basic.type == other.m_data.basic.type && 120 m_data.basic.precision == other.m_data.basic.precision; 121 122 case TYPE_ARRAY: 123 return *m_data.array.elementType == *other.m_data.array.elementType && 124 m_data.array.size == other.m_data.array.size; 125 126 case TYPE_STRUCT: 127 return m_data.structPtr == other.m_data.structPtr; 128 129 default: 130 DE_ASSERT(false); 131 return 0; 132 } 133 } 134 135 bool VarType::operator!= (const VarType& other) const 136 { 137 return !(*this == other); 138 } 139 140 // StructMember implementation 141 142 bool StructMember::operator== (const StructMember& other) const 143 { 144 return (m_name == other.m_name) && (m_type == other.m_type); 145 } 146 147 bool StructMember::operator!= (const StructMember& other) const 148 { 149 return !(*this == other); 150 } 151 152 // StructType implementation. 153 154 void StructType::addMember (const char* name, const VarType& type) 155 { 156 m_members.push_back(StructMember(name, type)); 157 } 158 159 bool StructType::operator== (const StructType& other) const 160 { 161 return (m_typeName == other.m_typeName) && (m_members == other.m_members); 162 } 163 164 bool StructType::operator!= (const StructType& other) const 165 { 166 return !(*this == other); 167 } 168 169 const char* getStorageName (Storage storage) 170 { 171 static const char* const s_names[] = { "in", "out", "const", "uniform", "buffer" }; 172 173 return de::getSizedArrayElement<STORAGE_LAST>(s_names, storage); 174 } 175 176 const char* getInterpolationName (Interpolation interpolation) 177 { 178 static const char* const s_names[] = { "smooth", "flat", "centroid" }; 179 180 return de::getSizedArrayElement<INTERPOLATION_LAST>(s_names, interpolation); 181 } 182 183 const char* getFormatLayoutName (FormatLayout layout) 184 { 185 static const char* s_names[] = 186 { 187 "rgba32f", // FORMATLAYOUT_RGBA32F 188 "rgba16f", // FORMATLAYOUT_RGBA16F 189 "r32f", // FORMATLAYOUT_R32F 190 "rgba8", // FORMATLAYOUT_RGBA8 191 "rgba8_snorm", // FORMATLAYOUT_RGBA8_SNORM 192 "rgba32i", // FORMATLAYOUT_RGBA32I 193 "rgba16i", // FORMATLAYOUT_RGBA16I 194 "rgba8i", // FORMATLAYOUT_RGBA8I 195 "r32i", // FORMATLAYOUT_R32I 196 "rgba32ui", // FORMATLAYOUT_RGBA32UI 197 "rgba16ui", // FORMATLAYOUT_RGBA16UI 198 "rgba8ui", // FORMATLAYOUT_RGBA8UI 199 "r32ui", // FORMATLAYOUT_R32UI 200 }; 201 202 return de::getSizedArrayElement<FORMATLAYOUT_LAST>(s_names, layout); 203 } 204 205 const char* getMemoryAccessQualifierName (MemoryAccessQualifier qualifier) 206 { 207 switch (qualifier) 208 { 209 case MEMORYACCESSQUALIFIER_COHERENT_BIT: return "coherent"; 210 case MEMORYACCESSQUALIFIER_VOLATILE_BIT: return "volatile"; 211 case MEMORYACCESSQUALIFIER_RESTRICT_BIT: return "restrict"; 212 case MEMORYACCESSQUALIFIER_READONLY_BIT: return "readonly"; 213 case MEMORYACCESSQUALIFIER_WRITEONLY_BIT: return "writeonly"; 214 default: 215 DE_ASSERT(false); 216 return DE_NULL; 217 } 218 } 219 220 const char* getMatrixOrderName (MatrixOrder qualifier) 221 { 222 static const char* s_names[] = 223 { 224 "column_major", // MATRIXORDER_COLUMN_MAJOR 225 "row_major", // MATRIXORDER_ROW_MAJOR 226 }; 227 228 return de::getSizedArrayElement<MATRIXORDER_LAST>(s_names, qualifier); 229 } 230 231 // Layout Implementation 232 233 Layout::Layout (int location_, int binding_, int offset_, FormatLayout format_, MatrixOrder matrixOrder_) 234 : location (location_) 235 , binding (binding_) 236 , offset (offset_) 237 , format (format_) 238 , matrixOrder (matrixOrder_) 239 { 240 } 241 242 bool Layout::operator== (const Layout& other) const 243 { 244 return location == other.location && 245 binding == other.binding && 246 offset == other.offset && 247 format == other.format && 248 matrixOrder == other.matrixOrder; 249 } 250 251 bool Layout::operator!= (const Layout& other) const 252 { 253 return !(*this == other); 254 } 255 256 // VariableDeclaration Implementation 257 258 VariableDeclaration::VariableDeclaration (const VarType& varType_, const std::string& name_, Storage storage_, Interpolation interpolation_, const Layout& layout_, deUint32 memoryAccessQualifierBits_) 259 : layout (layout_) 260 , interpolation (interpolation_) 261 , storage (storage_) 262 , varType (varType_) 263 , memoryAccessQualifierBits (memoryAccessQualifierBits_) 264 , name (name_) 265 { 266 } 267 268 bool VariableDeclaration::operator== (const VariableDeclaration& other) const 269 { 270 return layout == other.layout && 271 interpolation == other.interpolation && 272 storage == other.storage && 273 varType == other.varType && 274 memoryAccessQualifierBits == other.memoryAccessQualifierBits && 275 name == other.name; 276 } 277 278 bool VariableDeclaration::operator!= (const VariableDeclaration& other) const 279 { 280 return !(*this == other); 281 } 282 283 // InterfaceBlock Implementation 284 285 InterfaceBlock::InterfaceBlock (void) 286 : layout (Layout()) 287 , storage (glu::STORAGE_LAST) 288 , memoryAccessQualifierFlags (0) 289 { 290 } 291 292 // Declaration utilties. 293 294 std::ostream& operator<< (std::ostream& str, const Layout& layout) 295 { 296 std::vector<std::string> layoutDeclarationList; 297 298 if (layout.location != -1) 299 layoutDeclarationList.push_back("location=" + de::toString(layout.location)); 300 301 if (layout.binding != -1) 302 layoutDeclarationList.push_back("binding=" + de::toString(layout.binding)); 303 304 if (layout.offset != -1) 305 layoutDeclarationList.push_back("offset=" + de::toString(layout.offset)); 306 307 if (layout.format != FORMATLAYOUT_LAST) 308 layoutDeclarationList.push_back(getFormatLayoutName(layout.format)); 309 310 if (layout.matrixOrder != MATRIXORDER_LAST) 311 layoutDeclarationList.push_back(getMatrixOrderName(layout.matrixOrder)); 312 313 if (!layoutDeclarationList.empty()) 314 { 315 str << "layout(" << layoutDeclarationList[0]; 316 317 for (int layoutNdx = 1; layoutNdx < (int)layoutDeclarationList.size(); ++layoutNdx) 318 str << ", " << layoutDeclarationList[layoutNdx]; 319 320 str << ")"; 321 } 322 323 return str; 324 } 325 326 std::ostream& operator<< (std::ostream& str, const VariableDeclaration& decl) 327 { 328 if (decl.layout != Layout()) 329 str << decl.layout << " "; 330 331 for (int bitNdx = 0; (1 << bitNdx) & MEMORYACCESSQUALIFIER_MASK; ++bitNdx) 332 if (decl.memoryAccessQualifierBits & (1 << bitNdx)) 333 str << getMemoryAccessQualifierName((glu::MemoryAccessQualifier)(1 << bitNdx)) << " "; 334 335 if (decl.interpolation != INTERPOLATION_LAST) 336 str << getInterpolationName(decl.interpolation) << " "; 337 338 if (decl.storage != STORAGE_LAST) 339 str << getStorageName(decl.storage) << " "; 340 341 str << declare(decl.varType, decl.name); 342 343 return str; 344 } 345 346 namespace decl 347 { 348 349 std::ostream& operator<< (std::ostream& str, const Indent& indent) 350 { 351 for (int i = 0; i < indent.level; i++) 352 str << "\t"; 353 return str; 354 } 355 356 std::ostream& operator<< (std::ostream& str, const DeclareVariable& decl) 357 { 358 const VarType& type = decl.varType; 359 const VarType* curType = &type; 360 std::vector<int> arraySizes; 361 362 // Handle arrays. 363 while (curType->isArrayType()) 364 { 365 arraySizes.push_back(curType->getArraySize()); 366 curType = &curType->getElementType(); 367 } 368 369 if (curType->isBasicType()) 370 { 371 if (curType->getPrecision() != PRECISION_LAST) 372 str << glu::getPrecisionName(curType->getPrecision()) << " "; 373 str << glu::getDataTypeName(curType->getBasicType()); 374 } 375 else if (curType->isStructType()) 376 { 377 const StructType* structPtr = curType->getStructPtr(); 378 379 if (structPtr->hasTypeName()) 380 str << structPtr->getTypeName(); 381 else 382 str << declare(structPtr, decl.indentLevel); // Generate inline declaration. 383 } 384 else 385 DE_ASSERT(false); 386 387 str << " " << decl.name; 388 389 // Print array sizes. 390 for (std::vector<int>::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++) 391 { 392 const int arrSize = *sizeIter; 393 if (arrSize == VarType::UNSIZED_ARRAY) 394 str << "[]"; 395 else 396 str << "[" << arrSize << "]"; 397 } 398 399 return str; 400 } 401 402 std::ostream& operator<< (std::ostream& str, const DeclareStructTypePtr& decl) 403 { 404 str << "struct"; 405 406 // Type name is optional. 407 if (decl.structPtr->hasTypeName()) 408 str << " " << decl.structPtr->getTypeName(); 409 410 str << "\n" << indent(decl.indentLevel) << "{\n"; 411 412 for (StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++) 413 { 414 str << indent(decl.indentLevel+1); 415 str << declare(memberIter->getType(), memberIter->getName(), decl.indentLevel+1) << ";\n"; 416 } 417 418 str << indent(decl.indentLevel) << "}"; 419 420 return str; 421 } 422 423 std::ostream& operator<< (std::ostream& str, const DeclareStructType& decl) 424 { 425 return str << declare(&decl.structType, decl.indentLevel); 426 } 427 428 } // decl 429 } // glu 430