diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/VariableInfo.cpp | 553 |
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> *); |