summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp553
1 files changed, 308 insertions, 245 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
index ef888aff11..153455c4f1 100644
--- a/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp
@@ -1,196 +1,115 @@
//
-// Copyright (c) 2002-2010 The ANGLE Project Authors. All rights reserved.
+// Copyright (c) 2002-2013 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file.
//
+#include "angle_gl.h"
#include "compiler/translator/VariableInfo.h"
+#include "compiler/translator/util.h"
+#include "common/utilities.h"
-namespace {
-
-TString arrayBrackets(int index)
-{
- TStringStream stream;
- stream << "[" << index << "]";
- return stream.str();
-}
-
-// Returns the data type for an attribute, uniform, or varying.
-ShDataType getVariableDataType(const TType& type)
-{
- switch (type.getBasicType()) {
- case EbtFloat:
- if (type.isMatrix()) {
- switch (type.getNominalSize()) {
- case 2: return SH_FLOAT_MAT2;
- case 3: return SH_FLOAT_MAT3;
- case 4: return SH_FLOAT_MAT4;
- default: UNREACHABLE();
- }
- } else if (type.isVector()) {
- switch (type.getNominalSize()) {
- case 2: return SH_FLOAT_VEC2;
- case 3: return SH_FLOAT_VEC3;
- case 4: return SH_FLOAT_VEC4;
- default: UNREACHABLE();
- }
- } else {
- return SH_FLOAT;
- }
- case EbtInt:
- if (type.isMatrix()) {
- UNREACHABLE();
- } else if (type.isVector()) {
- switch (type.getNominalSize()) {
- case 2: return SH_INT_VEC2;
- case 3: return SH_INT_VEC3;
- case 4: return SH_INT_VEC4;
- default: UNREACHABLE();
- }
- } else {
- return SH_INT;
- }
- case EbtBool:
- if (type.isMatrix()) {
- UNREACHABLE();
- } else if (type.isVector()) {
- switch (type.getNominalSize()) {
- case 2: return SH_BOOL_VEC2;
- case 3: return SH_BOOL_VEC3;
- case 4: return SH_BOOL_VEC4;
- default: UNREACHABLE();
- }
- } else {
- return SH_BOOL;
- }
- case EbtSampler2D: return SH_SAMPLER_2D;
- case EbtSamplerCube: return SH_SAMPLER_CUBE;
- case EbtSamplerExternalOES: return SH_SAMPLER_EXTERNAL_OES;
- case EbtSampler2DRect: return SH_SAMPLER_2D_RECT_ARB;
- default: UNREACHABLE();
- }
- return SH_NONE;
-}
-
-void getBuiltInVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList);
-void getUserDefinedVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList,
- ShHashFunction64 hashFunction);
+template <typename VarT>
+static void ExpandUserDefinedVariable(const VarT &variable,
+ const std::string &name,
+ const std::string &mappedName,
+ bool markStaticUse,
+ std::vector<VarT> *expanded);
// Returns info for an attribute, uniform, or varying.
-void getVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList,
- ShHashFunction64 hashFunction)
+template <typename VarT>
+static void ExpandVariable(const VarT &variable,
+ const std::string &name,
+ const std::string &mappedName,
+ bool markStaticUse,
+ std::vector<VarT> *expanded)
{
- if (type.getBasicType() == EbtStruct) {
- if (type.isArray()) {
- for (int i = 0; i < type.getArraySize(); ++i) {
- TString lname = name + arrayBrackets(i);
- TString lmappedName = mappedName + arrayBrackets(i);
- getUserDefinedVariableInfo(type, lname, lmappedName, infoList, hashFunction);
+ if (variable.isStruct())
+ {
+ if (variable.isArray())
+ {
+ for (size_t elementIndex = 0; elementIndex < variable.elementCount(); elementIndex++)
+ {
+ std::string lname = name + ArrayString(elementIndex);
+ std::string lmappedName = mappedName + ArrayString(elementIndex);
+ ExpandUserDefinedVariable(variable, lname, lmappedName, markStaticUse, expanded);
}
- } else {
- getUserDefinedVariableInfo(type, name, mappedName, infoList, hashFunction);
}
- } else {
- getBuiltInVariableInfo(type, name, mappedName, infoList);
+ else
+ {
+ ExpandUserDefinedVariable(variable, name, mappedName, markStaticUse, expanded);
+ }
}
-}
+ else
+ {
+ VarT expandedVar = variable;
-void getBuiltInVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList)
-{
- ASSERT(type.getBasicType() != EbtStruct);
-
- TVariableInfo varInfo;
- if (type.isArray()) {
- varInfo.name = (name + "[0]").c_str();
- varInfo.mappedName = (mappedName + "[0]").c_str();
- varInfo.size = type.getArraySize();
- varInfo.isArray = true;
- } else {
- varInfo.name = name.c_str();
- varInfo.mappedName = mappedName.c_str();
- varInfo.size = 1;
- varInfo.isArray = false;
+ expandedVar.name = name;
+ expandedVar.mappedName = mappedName;
+
+ // Mark all expanded fields as used if the parent is used
+ if (markStaticUse)
+ {
+ expandedVar.staticUse = true;
+ }
+
+ if (expandedVar.isArray())
+ {
+ expandedVar.name += "[0]";
+ expandedVar.mappedName += "[0]";
+ }
+
+ expanded->push_back(expandedVar);
}
- varInfo.precision = type.getPrecision();
- varInfo.type = getVariableDataType(type);
- infoList.push_back(varInfo);
}
-void getUserDefinedVariableInfo(const TType& type,
- const TString& name,
- const TString& mappedName,
- TVariableInfoList& infoList,
- ShHashFunction64 hashFunction)
+template <class VarT>
+static void ExpandUserDefinedVariable(const VarT &variable,
+ const std::string &name,
+ const std::string &mappedName,
+ bool markStaticUse,
+ std::vector<VarT> *expanded)
{
- ASSERT(type.getBasicType() == EbtStruct);
-
- const TFieldList& fields = type.getStruct()->fields();
- for (size_t i = 0; i < fields.size(); ++i) {
- const TType& fieldType = *(fields[i]->type());
- const TString& fieldName = fields[i]->name();
- getVariableInfo(fieldType,
- name + "." + fieldName,
- mappedName + "." + TIntermTraverser::hash(fieldName, hashFunction),
- infoList,
- hashFunction);
+ ASSERT(variable.isStruct());
+
+ const std::vector<VarT> &fields = variable.fields;
+
+ for (size_t fieldIndex = 0; fieldIndex < fields.size(); fieldIndex++)
+ {
+ const VarT &field = fields[fieldIndex];
+ ExpandVariable(field,
+ name + "." + field.name,
+ mappedName + "." + field.mappedName,
+ markStaticUse,
+ expanded);
}
}
-TVariableInfo* findVariable(const TType& type,
- const TString& name,
- TVariableInfoList& infoList)
+template <class VarT>
+static VarT *FindVariable(const TString &name,
+ std::vector<VarT> *infoList)
{
// TODO(zmo): optimize this function.
- TString myName = name;
- if (type.isArray())
- myName += "[0]";
- for (size_t ii = 0; ii < infoList.size(); ++ii)
+ for (size_t ii = 0; ii < infoList->size(); ++ii)
{
- if (infoList[ii].name.c_str() == myName)
- return &(infoList[ii]);
+ if ((*infoList)[ii].name.c_str() == name)
+ return &((*infoList)[ii]);
}
- return NULL;
-}
-
-} // namespace anonymous
-
-TVariableInfo::TVariableInfo()
- : type(SH_NONE),
- size(0),
- isArray(false),
- precision(EbpUndefined),
- staticUse(false)
-{
-}
-TVariableInfo::TVariableInfo(ShDataType type, int size)
- : type(type),
- size(size),
- isArray(false),
- precision(EbpUndefined),
- staticUse(false)
-{
+ return NULL;
}
-CollectVariables::CollectVariables(TVariableInfoList& attribs,
- TVariableInfoList& uniforms,
- TVariableInfoList& varyings,
+CollectVariables::CollectVariables(std::vector<sh::Attribute> *attribs,
+ std::vector<sh::Attribute> *outputVariables,
+ std::vector<sh::Uniform> *uniforms,
+ std::vector<sh::Varying> *varyings,
+ std::vector<sh::InterfaceBlock> *interfaceBlocks,
ShHashFunction64 hashFunction)
: mAttribs(attribs),
+ mOutputVariables(outputVariables),
mUniforms(uniforms),
mVaryings(varyings),
+ mInterfaceBlocks(interfaceBlocks),
mPointCoordAdded(false),
mFrontFacingAdded(false),
mFragCoordAdded(false),
@@ -203,110 +122,254 @@ CollectVariables::CollectVariables(TVariableInfoList& attribs,
// Also, gl_FragCoord, gl_PointCoord, and gl_FrontFacing count
// toward varying counting if they are statically used in a fragment
// shader.
-void CollectVariables::visitSymbol(TIntermSymbol* symbol)
+void CollectVariables::visitSymbol(TIntermSymbol *symbol)
{
ASSERT(symbol != NULL);
- TVariableInfo* var = NULL;
- switch (symbol->getQualifier())
+ sh::ShaderVariable *var = NULL;
+ const TString &symbolName = symbol->getSymbol();
+
+ if (sh::IsVarying(symbol->getQualifier()))
{
- case EvqVaryingOut:
- case EvqInvariantVaryingOut:
- case EvqVaryingIn:
- case EvqInvariantVaryingIn:
- var = findVariable(symbol->getType(), symbol->getSymbol(), mVaryings);
- break;
- case EvqUniform:
- var = findVariable(symbol->getType(), symbol->getSymbol(), mUniforms);
- break;
- case EvqFragCoord:
- if (!mFragCoordAdded) {
- TVariableInfo info;
- info.name = "gl_FragCoord";
- info.mappedName = "gl_FragCoord";
- info.type = SH_FLOAT_VEC4;
- info.size = 1;
- info.precision = EbpMedium; // Use mediump as it doesn't really matter.
- info.staticUse = true;
- mVaryings.push_back(info);
- mFragCoordAdded = true;
- }
- return;
- case EvqFrontFacing:
- if (!mFrontFacingAdded) {
- TVariableInfo info;
- info.name = "gl_FrontFacing";
- info.mappedName = "gl_FrontFacing";
- info.type = SH_BOOL;
- info.size = 1;
- info.precision = EbpUndefined;
- info.staticUse = true;
- mVaryings.push_back(info);
- mFrontFacingAdded = true;
- }
- return;
- case EvqPointCoord:
- if (!mPointCoordAdded) {
- TVariableInfo info;
- info.name = "gl_PointCoord";
- info.mappedName = "gl_PointCoord";
- info.type = SH_FLOAT_VEC2;
- info.size = 1;
- info.precision = EbpMedium; // Use mediump as it doesn't really matter.
- info.staticUse = true;
- mVaryings.push_back(info);
- mPointCoordAdded = true;
+ var = FindVariable(symbolName, mVaryings);
+ }
+ else if (symbol->getType() != EbtInterfaceBlock)
+ {
+ switch (symbol->getQualifier())
+ {
+ case EvqAttribute:
+ case EvqVertexIn:
+ var = FindVariable(symbolName, mAttribs);
+ break;
+ case EvqFragmentOut:
+ var = FindVariable(symbolName, mOutputVariables);
+ break;
+ case EvqUniform:
+ {
+ const TInterfaceBlock *interfaceBlock = symbol->getType().getInterfaceBlock();
+ if (interfaceBlock)
+ {
+ sh::InterfaceBlock *namedBlock = FindVariable(interfaceBlock->name(), mInterfaceBlocks);
+ ASSERT(namedBlock);
+ var = FindVariable(symbolName, &namedBlock->fields);
+
+ // Set static use on the parent interface block here
+ namedBlock->staticUse = true;
+ }
+ else
+ {
+ var = FindVariable(symbolName, mUniforms);
+ }
+
+ // It's an internal error to reference an undefined user uniform
+ ASSERT(symbolName.compare(0, 3, "gl_") == 0 || var);
+ }
+ break;
+ case EvqFragCoord:
+ if (!mFragCoordAdded)
+ {
+ sh::Varying info;
+ info.name = "gl_FragCoord";
+ info.mappedName = "gl_FragCoord";
+ info.type = GL_FLOAT_VEC4;
+ info.arraySize = 0;
+ info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings->push_back(info);
+ mFragCoordAdded = true;
+ }
+ return;
+ case EvqFrontFacing:
+ if (!mFrontFacingAdded)
+ {
+ sh::Varying info;
+ info.name = "gl_FrontFacing";
+ info.mappedName = "gl_FrontFacing";
+ info.type = GL_BOOL;
+ info.arraySize = 0;
+ info.precision = GL_NONE;
+ info.staticUse = true;
+ mVaryings->push_back(info);
+ mFrontFacingAdded = true;
+ }
+ return;
+ case EvqPointCoord:
+ if (!mPointCoordAdded)
+ {
+ sh::Varying info;
+ info.name = "gl_PointCoord";
+ info.mappedName = "gl_PointCoord";
+ info.type = GL_FLOAT_VEC2;
+ info.arraySize = 0;
+ info.precision = GL_MEDIUM_FLOAT; // Use mediump as it doesn't really matter.
+ info.staticUse = true;
+ mVaryings->push_back(info);
+ mPointCoordAdded = true;
+ }
+ return;
+ default:
+ break;
}
- return;
- default:
- break;
}
if (var)
+ {
var->staticUse = true;
+ }
+}
+
+template <typename VarT>
+class NameHashingTraverser : public sh::GetVariableTraverser<VarT>
+{
+ public:
+ NameHashingTraverser(std::vector<VarT> *output, ShHashFunction64 hashFunction)
+ : sh::GetVariableTraverser<VarT>(output),
+ mHashFunction(hashFunction)
+ {}
+
+ private:
+ void visitVariable(VarT *variable)
+ {
+ TString stringName = TString(variable->name.c_str());
+ variable->mappedName = TIntermTraverser::hash(stringName, mHashFunction).c_str();
+ }
+
+ ShHashFunction64 mHashFunction;
+};
+
+// Attributes, which cannot have struct fields, are a special case
+template <>
+void CollectVariables::visitVariable(const TIntermSymbol *variable,
+ std::vector<sh::Attribute> *infoList) const
+{
+ ASSERT(variable);
+ const TType &type = variable->getType();
+ ASSERT(!type.getStruct());
+
+ sh::Attribute attribute;
+
+ attribute.type = sh::GLVariableType(type);
+ attribute.precision = sh::GLVariablePrecision(type);
+ attribute.name = variable->getSymbol().c_str();
+ attribute.arraySize = static_cast<unsigned int>(type.getArraySize());
+ attribute.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
+ attribute.location = variable->getType().getLayoutQualifier().location;
+
+ infoList->push_back(attribute);
}
-bool CollectVariables::visitAggregate(Visit, TIntermAggregate* node)
+template <>
+void CollectVariables::visitVariable(const TIntermSymbol *variable,
+ std::vector<sh::InterfaceBlock> *infoList) const
+{
+ sh::InterfaceBlock interfaceBlock;
+ const TInterfaceBlock *blockType = variable->getType().getInterfaceBlock();
+
+ bool isRowMajor = (blockType->matrixPacking() == EmpRowMajor);
+
+ interfaceBlock.name = blockType->name().c_str();
+ interfaceBlock.mappedName = TIntermTraverser::hash(variable->getSymbol(), mHashFunction).c_str();
+ interfaceBlock.arraySize = variable->getArraySize();
+ interfaceBlock.isRowMajorLayout = isRowMajor;
+ interfaceBlock.layout = sh::GetBlockLayoutType(blockType->blockStorage());
+
+ ASSERT(blockType);
+ const TFieldList &blockFields = blockType->fields();
+
+ for (size_t fieldIndex = 0; fieldIndex < blockFields.size(); fieldIndex++)
+ {
+ const TField *field = blockFields[fieldIndex];
+ ASSERT(field);
+
+ sh::GetInterfaceBlockFieldTraverser traverser(&interfaceBlock.fields, isRowMajor);
+ traverser.traverse(*field->type(), field->name());
+ }
+
+ infoList->push_back(interfaceBlock);
+}
+
+template <typename VarT>
+void CollectVariables::visitVariable(const TIntermSymbol *variable,
+ std::vector<VarT> *infoList) const
+{
+ NameHashingTraverser<VarT> traverser(infoList, mHashFunction);
+ traverser.traverse(variable->getType(), variable->getSymbol());
+}
+
+template <typename VarT>
+void CollectVariables::visitInfoList(const TIntermSequence &sequence,
+ std::vector<VarT> *infoList) const
+{
+ for (size_t seqIndex = 0; seqIndex < sequence.size(); seqIndex++)
+ {
+ const TIntermSymbol *variable = sequence[seqIndex]->getAsSymbolNode();
+ // The only case in which the sequence will not contain a
+ // TIntermSymbol node is initialization. It will contain a
+ // TInterBinary node in that case. Since attributes, uniforms,
+ // and varyings cannot be initialized in a shader, we must have
+ // only TIntermSymbol nodes in the sequence.
+ ASSERT(variable != NULL);
+ visitVariable(variable, infoList);
+ }
+}
+
+bool CollectVariables::visitAggregate(Visit, TIntermAggregate *node)
{
bool visitChildren = true;
switch (node->getOp())
{
- case EOpDeclaration: {
- const TIntermSequence& sequence = node->getSequence();
- TQualifier qualifier = sequence.front()->getAsTyped()->getQualifier();
- if (qualifier == EvqAttribute || qualifier == EvqUniform ||
- qualifier == EvqVaryingIn || qualifier == EvqVaryingOut ||
- qualifier == EvqInvariantVaryingIn || qualifier == EvqInvariantVaryingOut)
+ case EOpDeclaration:
{
- TVariableInfoList& infoList = qualifier == EvqAttribute ? mAttribs :
- (qualifier == EvqUniform ? mUniforms : mVaryings);
- for (TIntermSequence::const_iterator i = sequence.begin();
- i != sequence.end(); ++i)
+ const TIntermSequence &sequence = *(node->getSequence());
+ const TIntermTyped &typedNode = *(sequence.front()->getAsTyped());
+ TQualifier qualifier = typedNode.getQualifier();
+
+ if (typedNode.getBasicType() == EbtInterfaceBlock)
{
- const TIntermSymbol* variable = (*i)->getAsSymbolNode();
- // The only case in which the sequence will not contain a
- // TIntermSymbol node is initialization. It will contain a
- // TInterBinary node in that case. Since attributes, uniforms,
- // and varyings cannot be initialized in a shader, we must have
- // only TIntermSymbol nodes in the sequence.
- ASSERT(variable != NULL);
- TString processedSymbol;
- if (mHashFunction == NULL)
- processedSymbol = variable->getSymbol();
- else
- processedSymbol = TIntermTraverser::hash(variable->getOriginalSymbol(), mHashFunction);
- getVariableInfo(variable->getType(),
- variable->getOriginalSymbol(),
- processedSymbol,
- infoList,
- mHashFunction);
- visitChildren = false;
+ visitInfoList(sequence, mInterfaceBlocks);
+ }
+ else if (qualifier == EvqAttribute || qualifier == EvqVertexIn ||
+ qualifier == EvqFragmentOut || qualifier == EvqUniform ||
+ sh::IsVarying(qualifier))
+ {
+ switch (qualifier)
+ {
+ case EvqAttribute:
+ case EvqVertexIn:
+ visitInfoList(sequence, mAttribs);
+ break;
+ case EvqFragmentOut:
+ visitInfoList(sequence, mOutputVariables);
+ break;
+ case EvqUniform:
+ visitInfoList(sequence, mUniforms);
+ break;
+ default:
+ visitInfoList(sequence, mVaryings);
+ break;
+ }
+
+ if (!sequence.empty())
+ {
+ visitChildren = false;
+ }
}
+ break;
}
- break;
- }
- default: break;
+ default: break;
}
return visitChildren;
}
+template <typename VarT>
+void ExpandVariables(const std::vector<VarT> &compact, std::vector<VarT> *expanded)
+{
+ for (size_t variableIndex = 0; variableIndex < compact.size(); variableIndex++)
+ {
+ const VarT &variable = compact[variableIndex];
+ ExpandVariable(variable, variable.name, variable.mappedName, variable.staticUse, expanded);
+ }
+}
+
+template void ExpandVariables(const std::vector<sh::Uniform> &, std::vector<sh::Uniform> *);
+template void ExpandVariables(const std::vector<sh::Varying> &, std::vector<sh::Varying> *);