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