/*------------------------------------------------------------------------- * drawElements Quality Program OpenGL ES Utilities * ------------------------------------------------ * * Copyright 2014 The Android Open Source Project * * Licensed under the Apache License, Version 2.0 (the "License"); * you may not use this file except in compliance with the License. * You may obtain a copy of the License at * * http://www.apache.org/licenses/LICENSE-2.0 * * Unless required by applicable law or agreed to in writing, software * distributed under the License is distributed on an "AS IS" BASIS, * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. * See the License for the specific language governing permissions and * limitations under the License. * *//*! * \file * \brief Shader variable type. *//*--------------------------------------------------------------------*/ #include "gluVarType.hpp" #include "deStringUtil.hpp" #include "deArrayUtil.hpp" namespace glu { VarType::VarType (void) : m_type(TYPE_LAST) { } VarType::VarType (const VarType& other) : m_type(TYPE_LAST) { *this = other; } VarType::VarType (DataType basicType, Precision precision) : m_type(TYPE_BASIC) { m_data.basic.type = basicType; m_data.basic.precision = precision; } VarType::VarType (const VarType& elementType, int arraySize) : m_type(TYPE_ARRAY) { DE_ASSERT(arraySize >= 0 || arraySize == UNSIZED_ARRAY); m_data.array.size = arraySize; m_data.array.elementType = new VarType(elementType); } VarType::VarType (const StructType* structPtr) : m_type(TYPE_STRUCT) { m_data.structPtr = structPtr; } VarType::~VarType (void) { if (m_type == TYPE_ARRAY) delete m_data.array.elementType; } VarType& VarType::operator= (const VarType& other) { if (this == &other) return *this; // Self-assignment. VarType *oldElementType = m_type == TYPE_ARRAY ? m_data.array.elementType : DE_NULL; m_type = other.m_type; m_data = Data(); if (m_type == TYPE_ARRAY) { m_data.array.elementType = new VarType(*other.m_data.array.elementType); m_data.array.size = other.m_data.array.size; } else m_data = other.m_data; delete oldElementType; return *this; } int VarType::getScalarSize (void) const { switch (m_type) { case TYPE_BASIC: return glu::getDataTypeScalarSize(m_data.basic.type); case TYPE_ARRAY: return m_data.array.elementType->getScalarSize()*m_data.array.size; case TYPE_STRUCT: { int size = 0; for (StructType::ConstIterator iter = m_data.structPtr->begin(); iter != m_data.structPtr->end(); iter++) size += iter->getType().getScalarSize(); return size; } default: DE_ASSERT(false); return 0; } } bool VarType::operator== (const VarType& other) const { if (m_type != other.m_type) return false; switch (m_type) { case TYPE_BASIC: return m_data.basic.type == other.m_data.basic.type && m_data.basic.precision == other.m_data.basic.precision; case TYPE_ARRAY: return *m_data.array.elementType == *other.m_data.array.elementType && m_data.array.size == other.m_data.array.size; case TYPE_STRUCT: return m_data.structPtr == other.m_data.structPtr; default: DE_ASSERT(false); return 0; } } bool VarType::operator!= (const VarType& other) const { return !(*this == other); } // StructMember implementation bool StructMember::operator== (const StructMember& other) const { return (m_name == other.m_name) && (m_type == other.m_type); } bool StructMember::operator!= (const StructMember& other) const { return !(*this == other); } // StructType implementation. void StructType::addMember (const char* name, const VarType& type) { m_members.push_back(StructMember(name, type)); } bool StructType::operator== (const StructType& other) const { return (m_typeName == other.m_typeName) && (m_members == other.m_members); } bool StructType::operator!= (const StructType& other) const { return !(*this == other); } const char* getStorageName (Storage storage) { static const char* const s_names[] = { "in", "out", "const", "uniform", "buffer", "patch in", "patch out" }; return de::getSizedArrayElement(s_names, storage); } const char* getInterpolationName (Interpolation interpolation) { static const char* const s_names[] = { "smooth", "flat", "centroid" }; return de::getSizedArrayElement(s_names, interpolation); } const char* getFormatLayoutName (FormatLayout layout) { static const char* s_names[] = { "rgba32f", // FORMATLAYOUT_RGBA32F "rgba16f", // FORMATLAYOUT_RGBA16F "r32f", // FORMATLAYOUT_R32F "rgba8", // FORMATLAYOUT_RGBA8 "rgba8_snorm", // FORMATLAYOUT_RGBA8_SNORM "rgba32i", // FORMATLAYOUT_RGBA32I "rgba16i", // FORMATLAYOUT_RGBA16I "rgba8i", // FORMATLAYOUT_RGBA8I "r32i", // FORMATLAYOUT_R32I "rgba32ui", // FORMATLAYOUT_RGBA32UI "rgba16ui", // FORMATLAYOUT_RGBA16UI "rgba8ui", // FORMATLAYOUT_RGBA8UI "r32ui", // FORMATLAYOUT_R32UI }; return de::getSizedArrayElement(s_names, layout); } const char* getMemoryAccessQualifierName (MemoryAccessQualifier qualifier) { switch (qualifier) { case MEMORYACCESSQUALIFIER_COHERENT_BIT: return "coherent"; case MEMORYACCESSQUALIFIER_VOLATILE_BIT: return "volatile"; case MEMORYACCESSQUALIFIER_RESTRICT_BIT: return "restrict"; case MEMORYACCESSQUALIFIER_READONLY_BIT: return "readonly"; case MEMORYACCESSQUALIFIER_WRITEONLY_BIT: return "writeonly"; default: DE_ASSERT(false); return DE_NULL; } } const char* getMatrixOrderName (MatrixOrder qualifier) { static const char* s_names[] = { "column_major", // MATRIXORDER_COLUMN_MAJOR "row_major", // MATRIXORDER_ROW_MAJOR }; return de::getSizedArrayElement(s_names, qualifier); } // Layout Implementation Layout::Layout (int location_, int binding_, int offset_, FormatLayout format_, MatrixOrder matrixOrder_) : location (location_) , binding (binding_) , offset (offset_) , format (format_) , matrixOrder (matrixOrder_) { } bool Layout::operator== (const Layout& other) const { return location == other.location && binding == other.binding && offset == other.offset && format == other.format && matrixOrder == other.matrixOrder; } bool Layout::operator!= (const Layout& other) const { return !(*this == other); } // VariableDeclaration Implementation VariableDeclaration::VariableDeclaration (const VarType& varType_, const std::string& name_, Storage storage_, Interpolation interpolation_, const Layout& layout_, deUint32 memoryAccessQualifierBits_) : layout (layout_) , interpolation (interpolation_) , storage (storage_) , varType (varType_) , memoryAccessQualifierBits (memoryAccessQualifierBits_) , name (name_) { } bool VariableDeclaration::operator== (const VariableDeclaration& other) const { return layout == other.layout && interpolation == other.interpolation && storage == other.storage && varType == other.varType && memoryAccessQualifierBits == other.memoryAccessQualifierBits && name == other.name; } bool VariableDeclaration::operator!= (const VariableDeclaration& other) const { return !(*this == other); } // InterfaceBlock Implementation InterfaceBlock::InterfaceBlock (void) : layout (Layout()) , storage (glu::STORAGE_LAST) , memoryAccessQualifierFlags (0) { } // Declaration utilties. std::ostream& operator<< (std::ostream& str, const Layout& layout) { std::vector layoutDeclarationList; if (layout.location != -1) layoutDeclarationList.push_back("location=" + de::toString(layout.location)); if (layout.binding != -1) layoutDeclarationList.push_back("binding=" + de::toString(layout.binding)); if (layout.offset != -1) layoutDeclarationList.push_back("offset=" + de::toString(layout.offset)); if (layout.format != FORMATLAYOUT_LAST) layoutDeclarationList.push_back(getFormatLayoutName(layout.format)); if (layout.matrixOrder != MATRIXORDER_LAST) layoutDeclarationList.push_back(getMatrixOrderName(layout.matrixOrder)); if (!layoutDeclarationList.empty()) { str << "layout(" << layoutDeclarationList[0]; for (int layoutNdx = 1; layoutNdx < (int)layoutDeclarationList.size(); ++layoutNdx) str << ", " << layoutDeclarationList[layoutNdx]; str << ")"; } return str; } std::ostream& operator<< (std::ostream& str, const VariableDeclaration& decl) { if (decl.layout != Layout()) str << decl.layout << " "; for (int bitNdx = 0; (1 << bitNdx) & MEMORYACCESSQUALIFIER_MASK; ++bitNdx) if (decl.memoryAccessQualifierBits & (1 << bitNdx)) str << getMemoryAccessQualifierName((glu::MemoryAccessQualifier)(1 << bitNdx)) << " "; if (decl.interpolation != INTERPOLATION_LAST) str << getInterpolationName(decl.interpolation) << " "; if (decl.storage != STORAGE_LAST) str << getStorageName(decl.storage) << " "; str << declare(decl.varType, decl.name); return str; } namespace decl { std::ostream& operator<< (std::ostream& str, const Indent& indent) { for (int i = 0; i < indent.level; i++) str << "\t"; return str; } std::ostream& operator<< (std::ostream& str, const DeclareVariable& decl) { const VarType& type = decl.varType; const VarType* curType = &type; std::vector arraySizes; // Handle arrays. while (curType->isArrayType()) { arraySizes.push_back(curType->getArraySize()); curType = &curType->getElementType(); } if (curType->isBasicType()) { if (curType->getPrecision() != PRECISION_LAST && !glu::isDataTypeFloat16OrVec(curType->getBasicType())) str << glu::getPrecisionName(curType->getPrecision()) << " "; str << glu::getDataTypeName(curType->getBasicType()); } else if (curType->isStructType()) { const StructType* structPtr = curType->getStructPtr(); if (structPtr->hasTypeName()) str << structPtr->getTypeName(); else str << declare(structPtr, decl.indentLevel); // Generate inline declaration. } else DE_ASSERT(false); str << " " << decl.name; // Print array sizes. for (std::vector::const_iterator sizeIter = arraySizes.begin(); sizeIter != arraySizes.end(); sizeIter++) { const int arrSize = *sizeIter; if (arrSize == VarType::UNSIZED_ARRAY) str << "[]"; else str << "[" << arrSize << "]"; } return str; } std::ostream& operator<< (std::ostream& str, const DeclareStructTypePtr& decl) { str << "struct"; // Type name is optional. if (decl.structPtr->hasTypeName()) str << " " << decl.structPtr->getTypeName(); str << "\n" << indent(decl.indentLevel) << "{\n"; for (StructType::ConstIterator memberIter = decl.structPtr->begin(); memberIter != decl.structPtr->end(); memberIter++) { str << indent(decl.indentLevel+1); str << declare(memberIter->getType(), memberIter->getName(), decl.indentLevel+1) << ";\n"; } str << indent(decl.indentLevel) << "}"; return str; } std::ostream& operator<< (std::ostream& str, const DeclareStructType& decl) { return str << declare(&decl.structType, decl.indentLevel); } } // decl } // glu