/*-------------------------------------------------------------------------
|
* 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<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_, 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<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);
|
}
|
|
} // decl
|
} // glu
|