| /*------------------------------------------------------------------------- |
| * 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(VARTYPE_LAST) |
| { |
| } |
| |
| VarType::VarType(const VarType &other) : m_type(VARTYPE_LAST) |
| { |
| *this = other; |
| } |
| |
| VarType::VarType(DataType basicType, Precision precision) : m_type(VARTYPE_BASIC) |
| { |
| m_data.basic.type = basicType; |
| m_data.basic.precision = precision; |
| } |
| |
| VarType::VarType(const VarType &elementType, int arraySize) : m_type(VARTYPE_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(VARTYPE_STRUCT) |
| { |
| m_data.structPtr = structPtr; |
| } |
| |
| VarType::~VarType(void) |
| { |
| if (m_type == VARTYPE_ARRAY) |
| delete m_data.array.elementType; |
| } |
| |
| VarType &VarType::operator=(const VarType &other) |
| { |
| if (this == &other) |
| return *this; // Self-assignment. |
| |
| VarType *oldElementType = m_type == VARTYPE_ARRAY ? m_data.array.elementType : DE_NULL; |
| |
| m_type = other.m_type; |
| m_data = Data(); |
| |
| if (m_type == VARTYPE_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 VARTYPE_BASIC: |
| return glu::getDataTypeScalarSize(m_data.basic.type); |
| case VARTYPE_ARRAY: |
| return m_data.array.elementType->getScalarSize() * m_data.array.size; |
| |
| case VARTYPE_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 VARTYPE_BASIC: |
| return m_data.basic.type == other.m_data.basic.type && m_data.basic.precision == other.m_data.basic.precision; |
| |
| case VARTYPE_ARRAY: |
| return *m_data.array.elementType == *other.m_data.array.elementType && |
| m_data.array.size == other.m_data.array.size; |
| |
| case VARTYPE_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<STORAGE_LAST>(s_names, storage); |
| } |
| |
| const char *getInterpolationName(Interpolation interpolation) |
| { |
| static const char *const s_names[] = {"smooth", "flat", "centroid"}; |
| |
| return de::getSizedArrayElement<INTERPOLATION_LAST>(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<FORMATLAYOUT_LAST>(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<MATRIXORDER_LAST>(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_, |
| uint32_t 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<std::string> 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<int> 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<int>::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); |
| } |
| |
| } // namespace decl |
| } // namespace glu |