blob: 0050432b44d92d2aad1987ba166468e7aee0c318 [file] [log] [blame]
/*-------------------------------------------------------------------------
* 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_, 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