diff options
author | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 12:59:44 +0300 |
---|---|---|
committer | Andrew Knight <andrew.knight@digia.com> | 2014-08-05 16:43:22 +0200 |
commit | a6a12d8c0fc918972c15268f749ecc7c90b95d6c (patch) | |
tree | cb6d986d30ef97e932ab51768854d5d9b46729d3 /src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp | |
parent | 14f9c09542bd6cc19430473da9ce4c68f239ec7d (diff) |
ANGLE: upgrade to 2.1~07d49ef5350a
This version of ANGLE provides partial ES3 support, numerous
bug fixes, and several potentially useful vendor extensions.
All patches have been rebased. The following changes are noted:
0000-General-fixes-for-ANGLE-2.1.patch
contains compile fixes for the new ANGLE
0004-Make-it-possible-to-link-ANGLE-statically-for-single.patch
has incorporated patch 0015.
0007-Make-DX9-DX11-mutually-exclusive.patch
has been removed as it was fixed upstream.
0007-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
has been moved up to fill the patch number gap.
0010-ANGLE-Enable-D3D11-for-feature-level-9-cards.patch
now contains patch 0014 and 0017.
0013-ANGLE-Allow-for-universal-program-binaries.patch
has been removed as it is no longer relevant.
0014-ANGLE-D3D11-Fix-internal-index-buffer-for-level-9-ha.patch
has been merged with patch 0010.
0015-ANGLE-Don-t-export-DLLMain-functions-for-static-buil.patch
has been merged with patch 0004.
0016-ANGLE-WinRT-Call-Trim-when-application-suspends.patch
has been removed and will be replaced by a follow-up patch using a
different technique.
0017-ANGLE-D3D11-Don-t-use-mipmaps-in-level-9-textures.patch
has been merged with patch 0010.
0018-ANGLE-WinRT-Create-swap-chain-using-physical-resolut.patch
has been removed and will be replaced by a follow-up patch extending
the EGL_ANGLE_window_fixed_size extension.
0019-Fix-ANGLE-build-with-Microsoft-Visual-Studio-14-CTP.patch
is now patch 0007.
[ChangeLog][Third-party libraries] ANGLE has been upgraded to
version 2.1, bringing partial support for OpenGL ES3 over
Direct3D 11, numerous bug fixes, and several new vendor extensions.
Change-Id: I6d95ce1480462d67228d83c1e5c74a1706b5b21c
Reviewed-by: Friedemann Kleint <Friedemann.Kleint@digia.com>
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp | 1094 |
1 files changed, 641 insertions, 453 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp index f2f0a3d6be..7839c04852 100644 --- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp +++ b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp @@ -1,5 +1,5 @@ // -// Copyright (c) 2002-2011 The ANGLE Project Authors. All rights reserved. +// Copyright (c) 2002-2014 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. // @@ -11,7 +11,7 @@ namespace { -TString arrayBrackets(const TType& type) +TString arrayBrackets(const TType &type) { ASSERT(type.isArray()); TInfoSinkBase out; @@ -19,13 +19,14 @@ TString arrayBrackets(const TType& type) return TString(out.c_str()); } -bool isSingleStatement(TIntermNode* node) { - if (const TIntermAggregate* aggregate = node->getAsAggregate()) +bool isSingleStatement(TIntermNode *node) +{ + if (const TIntermAggregate *aggregate = node->getAsAggregate()) { return (aggregate->getOp() != EOpFunction) && (aggregate->getOp() != EOpSequence); } - else if (const TIntermSelection* selection = node->getAsSelectionNode()) + else if (const TIntermSelection *selection = node->getAsSelectionNode()) { // Ternary operators are usually part of an assignment operator. // This handles those rare cases in which they are all by themselves. @@ -39,49 +40,61 @@ bool isSingleStatement(TIntermNode* node) { } } // namespace -TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase& objSink, +TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink, ShArrayIndexClampingStrategy clampingStrategy, ShHashFunction64 hashFunction, - NameMap& nameMap, - TSymbolTable& symbolTable) + NameMap &nameMap, + TSymbolTable &symbolTable, + int shaderVersion) : TIntermTraverser(true, true, true), mObjSink(objSink), mDeclaringVariables(false), mClampingStrategy(clampingStrategy), mHashFunction(hashFunction), mNameMap(nameMap), - mSymbolTable(symbolTable) + mSymbolTable(symbolTable), + mShaderVersion(shaderVersion) { } -void TOutputGLSLBase::writeTriplet(Visit visit, const char* preStr, const char* inStr, const char* postStr) +void TOutputGLSLBase::writeTriplet( + Visit visit, const char *preStr, const char *inStr, const char *postStr) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (visit == PreVisit && preStr) - { out << preStr; - } else if (visit == InVisit && inStr) - { out << inStr; - } else if (visit == PostVisit && postStr) - { out << postStr; - } } -void TOutputGLSLBase::writeVariableType(const TType& type) +void TOutputGLSLBase::writeBuiltInFunctionTriplet( + Visit visit, const char *preStr, bool useEmulatedFunction) +{ + TString preString = useEmulatedFunction ? + BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr) : preStr; + writeTriplet(visit, preString.c_str(), ", ", ")"); +} + +void TOutputGLSLBase::writeVariableType(const TType &type) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); TQualifier qualifier = type.getQualifier(); // TODO(alokp): Validate qualifier for variable declarations. - if ((qualifier != EvqTemporary) && (qualifier != EvqGlobal)) + if (qualifier != EvqTemporary && qualifier != EvqGlobal) out << type.getQualifierString() << " "; // Declare the struct if we have not done so already. - if ((type.getBasicType() == EbtStruct) && !structDeclared(type.getStruct())) + if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct())) { - declareStruct(type.getStruct()); + TStructure *structure = type.getStruct(); + + declareStruct(structure); + + if (!structure->name().empty()) + { + mDeclaredStructs.insert(structure->uniqueId()); + } } else { @@ -91,19 +104,19 @@ void TOutputGLSLBase::writeVariableType(const TType& type) } } -void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) +void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter) { - const TIntermSymbol* arg = (*iter)->getAsSymbolNode(); + const TIntermSymbol *arg = (*iter)->getAsSymbolNode(); ASSERT(arg != NULL); - const TType& type = arg->getType(); + const TType &type = arg->getType(); writeVariableType(type); - const TString& name = arg->getSymbol(); + const TString &name = arg->getSymbol(); if (!name.empty()) out << " " << hashName(name); if (type.isArray()) @@ -115,23 +128,24 @@ void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence& args) } } -const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, - const ConstantUnion* pConstUnion) +const ConstantUnion *TOutputGLSLBase::writeConstantUnion( + const TType &type, const ConstantUnion *pConstUnion) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (type.getBasicType() == EbtStruct) { - const TStructure* structure = type.getStruct(); + const TStructure *structure = type.getStruct(); out << hashName(structure->name()) << "("; - const TFieldList& fields = structure->fields(); + const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { - const TType* fieldType = fields[i]->type(); + const TType *fieldType = fields[i]->type(); ASSERT(fieldType != NULL); pConstUnion = writeConstantUnion(*fieldType, pConstUnion); - if (i != fields.size() - 1) out << ", "; + if (i != fields.size() - 1) + out << ", "; } out << ")"; } @@ -139,28 +153,37 @@ const ConstantUnion* TOutputGLSLBase::writeConstantUnion(const TType& type, { size_t size = type.getObjectSize(); bool writeType = size > 1; - if (writeType) out << getTypeName(type) << "("; + if (writeType) + out << getTypeName(type) << "("; for (size_t i = 0; i < size; ++i, ++pConstUnion) { switch (pConstUnion->getType()) { - case EbtFloat: out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); break; - case EbtInt: out << pConstUnion->getIConst(); break; - case EbtBool: out << pConstUnion->getBConst(); break; - default: UNREACHABLE(); + case EbtFloat: + out << std::min(FLT_MAX, std::max(-FLT_MAX, pConstUnion->getFConst())); + break; + case EbtInt: + out << pConstUnion->getIConst(); + break; + case EbtBool: + out << pConstUnion->getBConst(); + break; + default: UNREACHABLE(); } - if (i != size - 1) out << ", "; + if (i != size - 1) + out << ", "; } - if (writeType) out << ")"; + if (writeType) + out << ")"; } return pConstUnion; } -void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) +void TOutputGLSLBase::visitSymbol(TIntermSymbol *node) { - TInfoSinkBase& out = objSink(); - if (mLoopUnroll.NeedsToReplaceSymbolWithValue(node)) - out << mLoopUnroll.GetLoopIndexValue(node); + TInfoSinkBase &out = objSink(); + if (mLoopUnrollStack.needsToReplaceSymbolWithValue(node)) + out << mLoopUnrollStack.getLoopIndexValue(node); else out << hashVariableName(node->getSymbol()); @@ -168,240 +191,303 @@ void TOutputGLSLBase::visitSymbol(TIntermSymbol* node) out << arrayBrackets(node->getType()); } -void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion* node) +void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node) { writeConstantUnion(node->getType(), node->getUnionArrayPointer()); } -bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary* node) +bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node) { bool visitChildren = true; - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); switch (node->getOp()) { - case EOpInitialize: + case EOpInitialize: + if (visit == InVisit) + { + out << " = "; + // RHS of initialize is not being declared. + mDeclaringVariables = false; + } + break; + case EOpAssign: + writeTriplet(visit, "(", " = ", ")"); + break; + case EOpAddAssign: + writeTriplet(visit, "(", " += ", ")"); + break; + case EOpSubAssign: + writeTriplet(visit, "(", " -= ", ")"); + break; + case EOpDivAssign: + writeTriplet(visit, "(", " /= ", ")"); + break; + // Notice the fall-through. + case EOpMulAssign: + case EOpVectorTimesMatrixAssign: + case EOpVectorTimesScalarAssign: + case EOpMatrixTimesScalarAssign: + case EOpMatrixTimesMatrixAssign: + writeTriplet(visit, "(", " *= ", ")"); + break; + + case EOpIndexDirect: + writeTriplet(visit, NULL, "[", "]"); + break; + case EOpIndexIndirect: + if (node->getAddIndexClamp()) + { if (visit == InVisit) { - out << " = "; - // RHS of initialize is not being declared. - mDeclaringVariables = false; + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "[int(clamp(float("; + else + out << "[webgl_int_clamp("; } - break; - case EOpAssign: writeTriplet(visit, "(", " = ", ")"); break; - case EOpAddAssign: writeTriplet(visit, "(", " += ", ")"); break; - case EOpSubAssign: writeTriplet(visit, "(", " -= ", ")"); break; - case EOpDivAssign: writeTriplet(visit, "(", " /= ", ")"); break; - // Notice the fall-through. - case EOpMulAssign: - case EOpVectorTimesMatrixAssign: - case EOpVectorTimesScalarAssign: - case EOpMatrixTimesScalarAssign: - case EOpMatrixTimesMatrixAssign: - writeTriplet(visit, "(", " *= ", ")"); - break; - - case EOpIndexDirect: - writeTriplet(visit, NULL, "[", "]"); - break; - case EOpIndexIndirect: - if (node->getAddIndexClamp()) + else if (visit == PostVisit) { - if (visit == InVisit) + int maxSize; + TIntermTyped *left = node->getLeft(); + TType leftType = left->getType(); + + if (left->isArray()) { - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "[int(clamp(float("; - } else { - out << "[webgl_int_clamp("; - } + // The shader will fail validation if the array length is not > 0. + maxSize = leftType.getArraySize() - 1; } - else if (visit == PostVisit) + else { - int maxSize; - TIntermTyped *left = node->getLeft(); - TType leftType = left->getType(); - - if (left->isArray()) - { - // The shader will fail validation if the array length is not > 0. - maxSize = leftType.getArraySize() - 1; - } - else - { - maxSize = leftType.getNominalSize() - 1; - } - - if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) { - out << "), 0.0, float(" << maxSize << ")))]"; - } else { - out << ", 0, " << maxSize << ")]"; - } + maxSize = leftType.getNominalSize() - 1; } + + if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC) + out << "), 0.0, float(" << maxSize << ")))]"; + else + out << ", 0, " << maxSize << ")]"; } - else - { - writeTriplet(visit, NULL, "[", "]"); - } - break; - case EOpIndexDirectStruct: - if (visit == InVisit) - { - // Here we are writing out "foo.bar", where "foo" is struct - // and "bar" is field. In AST, it is represented as a binary - // node, where left child represents "foo" and right child "bar". - // The node itself represents ".". The struct field "bar" is - // actually stored as an index into TStructure::fields. - out << "."; - const TStructure* structure = node->getLeft()->getType().getStruct(); - const TIntermConstantUnion* index = node->getRight()->getAsConstantUnion(); - const TField* field = structure->fields()[index->getIConst(0)]; - - TString fieldName = field->name(); - if (!mSymbolTable.findBuiltIn(structure->name())) - fieldName = hashName(fieldName); - - out << fieldName; - visitChildren = false; - } - break; - case EOpVectorSwizzle: - if (visit == InVisit) + } + else + { + writeTriplet(visit, NULL, "[", "]"); + } + break; + case EOpIndexDirectStruct: + if (visit == InVisit) + { + // Here we are writing out "foo.bar", where "foo" is struct + // and "bar" is field. In AST, it is represented as a binary + // node, where left child represents "foo" and right child "bar". + // The node itself represents ".". The struct field "bar" is + // actually stored as an index into TStructure::fields. + out << "."; + const TStructure *structure = node->getLeft()->getType().getStruct(); + const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion(); + const TField *field = structure->fields()[index->getIConst(0)]; + + TString fieldName = field->name(); + if (!mSymbolTable.findBuiltIn(structure->name(), mShaderVersion)) + fieldName = hashName(fieldName); + + out << fieldName; + visitChildren = false; + } + break; + case EOpVectorSwizzle: + if (visit == InVisit) + { + out << "."; + TIntermAggregate *rightChild = node->getRight()->getAsAggregate(); + TIntermSequence *sequence = rightChild->getSequence(); + for (TIntermSequence::iterator sit = sequence->begin(); sit != sequence->end(); ++sit) { - out << "."; - TIntermAggregate* rightChild = node->getRight()->getAsAggregate(); - TIntermSequence& sequence = rightChild->getSequence(); - for (TIntermSequence::iterator sit = sequence.begin(); sit != sequence.end(); ++sit) + TIntermConstantUnion *element = (*sit)->getAsConstantUnion(); + ASSERT(element->getBasicType() == EbtInt); + ASSERT(element->getNominalSize() == 1); + const ConstantUnion& data = element->getUnionArrayPointer()[0]; + ASSERT(data.getType() == EbtInt); + switch (data.getIConst()) { - TIntermConstantUnion* element = (*sit)->getAsConstantUnion(); - ASSERT(element->getBasicType() == EbtInt); - ASSERT(element->getNominalSize() == 1); - const ConstantUnion& data = element->getUnionArrayPointer()[0]; - ASSERT(data.getType() == EbtInt); - switch (data.getIConst()) - { - case 0: out << "x"; break; - case 1: out << "y"; break; - case 2: out << "z"; break; - case 3: out << "w"; break; - default: UNREACHABLE(); break; - } + case 0: + out << "x"; + break; + case 1: + out << "y"; + break; + case 2: + out << "z"; + break; + case 3: + out << "w"; + break; + default: + UNREACHABLE(); } - visitChildren = false; } - break; - - case EOpAdd: writeTriplet(visit, "(", " + ", ")"); break; - case EOpSub: writeTriplet(visit, "(", " - ", ")"); break; - case EOpMul: writeTriplet(visit, "(", " * ", ")"); break; - case EOpDiv: writeTriplet(visit, "(", " / ", ")"); break; - case EOpMod: UNIMPLEMENTED(); break; - case EOpEqual: writeTriplet(visit, "(", " == ", ")"); break; - case EOpNotEqual: writeTriplet(visit, "(", " != ", ")"); break; - case EOpLessThan: writeTriplet(visit, "(", " < ", ")"); break; - case EOpGreaterThan: writeTriplet(visit, "(", " > ", ")"); break; - case EOpLessThanEqual: writeTriplet(visit, "(", " <= ", ")"); break; - case EOpGreaterThanEqual: writeTriplet(visit, "(", " >= ", ")"); break; - - // Notice the fall-through. - case EOpVectorTimesScalar: - case EOpVectorTimesMatrix: - case EOpMatrixTimesVector: - case EOpMatrixTimesScalar: - case EOpMatrixTimesMatrix: - writeTriplet(visit, "(", " * ", ")"); - break; - - case EOpLogicalOr: writeTriplet(visit, "(", " || ", ")"); break; - case EOpLogicalXor: writeTriplet(visit, "(", " ^^ ", ")"); break; - case EOpLogicalAnd: writeTriplet(visit, "(", " && ", ")"); break; - default: UNREACHABLE(); break; + visitChildren = false; + } + break; + + case EOpAdd: + writeTriplet(visit, "(", " + ", ")"); + break; + case EOpSub: + writeTriplet(visit, "(", " - ", ")"); + break; + case EOpMul: + writeTriplet(visit, "(", " * ", ")"); + break; + case EOpDiv: + writeTriplet(visit, "(", " / ", ")"); + break; + case EOpMod: + UNIMPLEMENTED(); + break; + case EOpEqual: + writeTriplet(visit, "(", " == ", ")"); + break; + case EOpNotEqual: + writeTriplet(visit, "(", " != ", ")"); + break; + case EOpLessThan: + writeTriplet(visit, "(", " < ", ")"); + break; + case EOpGreaterThan: + writeTriplet(visit, "(", " > ", ")"); + break; + case EOpLessThanEqual: + writeTriplet(visit, "(", " <= ", ")"); + break; + case EOpGreaterThanEqual: + writeTriplet(visit, "(", " >= ", ")"); + break; + + // Notice the fall-through. + case EOpVectorTimesScalar: + case EOpVectorTimesMatrix: + case EOpMatrixTimesVector: + case EOpMatrixTimesScalar: + case EOpMatrixTimesMatrix: + writeTriplet(visit, "(", " * ", ")"); + break; + + case EOpLogicalOr: + writeTriplet(visit, "(", " || ", ")"); + break; + case EOpLogicalXor: + writeTriplet(visit, "(", " ^^ ", ")"); + break; + case EOpLogicalAnd: + writeTriplet(visit, "(", " && ", ")"); + break; + default: + UNREACHABLE(); } return visitChildren; } -bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) +bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary *node) { TString preString; TString postString = ")"; switch (node->getOp()) { - case EOpNegative: preString = "(-"; break; - case EOpVectorLogicalNot: preString = "not("; break; - case EOpLogicalNot: preString = "(!"; break; - - case EOpPostIncrement: preString = "("; postString = "++)"; break; - case EOpPostDecrement: preString = "("; postString = "--)"; break; - case EOpPreIncrement: preString = "(++"; break; - case EOpPreDecrement: preString = "(--"; break; - - case EOpConvIntToBool: - case EOpConvFloatToBool: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "bool("; break; - case 2: preString = "bvec2("; break; - case 3: preString = "bvec3("; break; - case 4: preString = "bvec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvBoolToFloat: - case EOpConvIntToFloat: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "float("; break; - case 2: preString = "vec2("; break; - case 3: preString = "vec3("; break; - case 4: preString = "vec4("; break; - default: UNREACHABLE(); - } - break; - case EOpConvFloatToInt: - case EOpConvBoolToInt: - switch (node->getOperand()->getType().getNominalSize()) - { - case 1: preString = "int("; break; - case 2: preString = "ivec2("; break; - case 3: preString = "ivec3("; break; - case 4: preString = "ivec4("; break; - default: UNREACHABLE(); - } - break; - - case EOpRadians: preString = "radians("; break; - case EOpDegrees: preString = "degrees("; break; - case EOpSin: preString = "sin("; break; - case EOpCos: preString = "cos("; break; - case EOpTan: preString = "tan("; break; - case EOpAsin: preString = "asin("; break; - case EOpAcos: preString = "acos("; break; - case EOpAtan: preString = "atan("; break; - - case EOpExp: preString = "exp("; break; - case EOpLog: preString = "log("; break; - case EOpExp2: preString = "exp2("; break; - case EOpLog2: preString = "log2("; break; - case EOpSqrt: preString = "sqrt("; break; - case EOpInverseSqrt: preString = "inversesqrt("; break; - - case EOpAbs: preString = "abs("; break; - case EOpSign: preString = "sign("; break; - case EOpFloor: preString = "floor("; break; - case EOpCeil: preString = "ceil("; break; - case EOpFract: preString = "fract("; break; - - case EOpLength: preString = "length("; break; - case EOpNormalize: preString = "normalize("; break; - - case EOpDFdx: preString = "dFdx("; break; - case EOpDFdy: preString = "dFdy("; break; - case EOpFwidth: preString = "fwidth("; break; - - case EOpAny: preString = "any("; break; - case EOpAll: preString = "all("; break; - - default: UNREACHABLE(); break; + case EOpNegative: preString = "(-"; break; + case EOpVectorLogicalNot: preString = "not("; break; + case EOpLogicalNot: preString = "(!"; break; + + case EOpPostIncrement: preString = "("; postString = "++)"; break; + case EOpPostDecrement: preString = "("; postString = "--)"; break; + case EOpPreIncrement: preString = "(++"; break; + case EOpPreDecrement: preString = "(--"; break; + + case EOpRadians: + preString = "radians("; + break; + case EOpDegrees: + preString = "degrees("; + break; + case EOpSin: + preString = "sin("; + break; + case EOpCos: + preString = "cos("; + break; + case EOpTan: + preString = "tan("; + break; + case EOpAsin: + preString = "asin("; + break; + case EOpAcos: + preString = "acos("; + break; + case EOpAtan: + preString = "atan("; + break; + + case EOpExp: + preString = "exp("; + break; + case EOpLog: + preString = "log("; + break; + case EOpExp2: + preString = "exp2("; + break; + case EOpLog2: + preString = "log2("; + break; + case EOpSqrt: + preString = "sqrt("; + break; + case EOpInverseSqrt: + preString = "inversesqrt("; + break; + + case EOpAbs: + preString = "abs("; + break; + case EOpSign: + preString = "sign("; + break; + case EOpFloor: + preString = "floor("; + break; + case EOpCeil: + preString = "ceil("; + break; + case EOpFract: + preString = "fract("; + break; + + case EOpLength: + preString = "length("; + break; + case EOpNormalize: + preString = "normalize("; + break; + + case EOpDFdx: + preString = "dFdx("; + break; + case EOpDFdy: + preString = "dFdy("; + break; + case EOpFwidth: + preString = "fwidth("; + break; + + case EOpAny: + preString = "any("; + break; + case EOpAll: + preString = "all("; + break; + + default: + UNREACHABLE(); } if (visit == PreVisit && node->getUseEmulatedFunction()) @@ -411,9 +497,9 @@ bool TOutputGLSLBase::visitUnary(Visit visit, TIntermUnary* node) return true; } -bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) +bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection *node) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); if (node->usesTernaryOperator()) { @@ -448,202 +534,270 @@ bool TOutputGLSLBase::visitSelection(Visit visit, TIntermSelection* node) return false; } -bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate* node) +bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node) { bool visitChildren = true; - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); TString preString; - bool delayedWrite = false; + bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction()); switch (node->getOp()) { - case EOpSequence: { - // Scope the sequences except when at the global scope. - if (depth > 0) out << "{\n"; - - incrementDepth(node); - const TIntermSequence& sequence = node->getSequence(); - for (TIntermSequence::const_iterator iter = sequence.begin(); - iter != sequence.end(); ++iter) - { - TIntermNode* node = *iter; - ASSERT(node != NULL); - node->traverse(this); + case EOpSequence: + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "{\n"; + } - if (isSingleStatement(node)) - out << ";\n"; - } - decrementDepth(); + incrementDepth(node); + for (TIntermSequence::const_iterator iter = node->getSequence()->begin(); + iter != node->getSequence()->end(); ++iter) + { + TIntermNode *node = *iter; + ASSERT(node != NULL); + node->traverse(this); - // Scope the sequences except when at the global scope. - if (depth > 0) out << "}\n"; - visitChildren = false; - break; + if (isSingleStatement(node)) + out << ";\n"; } - case EOpPrototype: { - // Function declaration. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashName(node->getName()); - - out << "("; - writeFunctionParameters(node->getSequence()); - out << ")"; + decrementDepth(); - visitChildren = false; - break; - } - case EOpFunction: { - // Function definition. - ASSERT(visit == PreVisit); - writeVariableType(node->getType()); - out << " " << hashFunctionName(node->getName()); - - incrementDepth(node); - // Function definition node contains one or two children nodes - // representing function parameters and function body. The latter - // is not present in case of empty function bodies. - const TIntermSequence& sequence = node->getSequence(); - ASSERT((sequence.size() == 1) || (sequence.size() == 2)); - TIntermSequence::const_iterator seqIter = sequence.begin(); - - // Traverse function parameters. - TIntermAggregate* params = (*seqIter)->getAsAggregate(); - ASSERT(params != NULL); - ASSERT(params->getOp() == EOpParameters); - params->traverse(this); - - // Traverse function body. - TIntermAggregate* body = ++seqIter != sequence.end() ? - (*seqIter)->getAsAggregate() : NULL; - visitCodeBlock(body); - decrementDepth(); - - // Fully processed; no need to visit children. - visitChildren = false; - break; + // Scope the sequences except when at the global scope. + if (mDepth > 0) + { + out << "}\n"; } - case EOpFunctionCall: - // Function call. - if (visit == PreVisit) - { - out << hashFunctionName(node->getName()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - case EOpParameters: { - // Function parameters. - ASSERT(visit == PreVisit); - out << "("; - writeFunctionParameters(node->getSequence()); + visitChildren = false; + break; + case EOpPrototype: + // Function declaration. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashName(node->getName()); + + out << "("; + writeFunctionParameters(*(node->getSequence())); + out << ")"; + + visitChildren = false; + break; + case EOpFunction: { + // Function definition. + ASSERT(visit == PreVisit); + writeVariableType(node->getType()); + out << " " << hashFunctionName(node->getName()); + + incrementDepth(node); + // Function definition node contains one or two children nodes + // representing function parameters and function body. The latter + // is not present in case of empty function bodies. + const TIntermSequence &sequence = *(node->getSequence()); + ASSERT((sequence.size() == 1) || (sequence.size() == 2)); + TIntermSequence::const_iterator seqIter = sequence.begin(); + + // Traverse function parameters. + TIntermAggregate *params = (*seqIter)->getAsAggregate(); + ASSERT(params != NULL); + ASSERT(params->getOp() == EOpParameters); + params->traverse(this); + + // Traverse function body. + TIntermAggregate *body = ++seqIter != sequence.end() ? + (*seqIter)->getAsAggregate() : NULL; + visitCodeBlock(body); + decrementDepth(); + + // Fully processed; no need to visit children. + visitChildren = false; + break; + } + case EOpFunctionCall: + // Function call. + if (visit == PreVisit) + out << hashFunctionName(node->getName()) << "("; + else if (visit == InVisit) + out << ", "; + else out << ")"; - visitChildren = false; - break; + break; + case EOpParameters: + // Function parameters. + ASSERT(visit == PreVisit); + out << "("; + writeFunctionParameters(*(node->getSequence())); + out << ")"; + visitChildren = false; + break; + case EOpDeclaration: + // Variable declaration. + if (visit == PreVisit) + { + const TIntermSequence &sequence = *(node->getSequence()); + const TIntermTyped *variable = sequence.front()->getAsTyped(); + writeVariableType(variable->getType()); + out << " "; + mDeclaringVariables = true; } - case EOpDeclaration: { - // Variable declaration. - if (visit == PreVisit) - { - const TIntermSequence& sequence = node->getSequence(); - const TIntermTyped* variable = sequence.front()->getAsTyped(); - writeVariableType(variable->getType()); - out << " "; - mDeclaringVariables = true; - } - else if (visit == InVisit) - { - out << ", "; - mDeclaringVariables = true; - } - else - { - mDeclaringVariables = false; - } - break; + else if (visit == InVisit) + { + out << ", "; + mDeclaringVariables = true; } - case EOpConstructFloat: writeTriplet(visit, "float(", NULL, ")"); break; - case EOpConstructVec2: writeTriplet(visit, "vec2(", ", ", ")"); break; - case EOpConstructVec3: writeTriplet(visit, "vec3(", ", ", ")"); break; - case EOpConstructVec4: writeTriplet(visit, "vec4(", ", ", ")"); break; - case EOpConstructBool: writeTriplet(visit, "bool(", NULL, ")"); break; - case EOpConstructBVec2: writeTriplet(visit, "bvec2(", ", ", ")"); break; - case EOpConstructBVec3: writeTriplet(visit, "bvec3(", ", ", ")"); break; - case EOpConstructBVec4: writeTriplet(visit, "bvec4(", ", ", ")"); break; - case EOpConstructInt: writeTriplet(visit, "int(", NULL, ")"); break; - case EOpConstructIVec2: writeTriplet(visit, "ivec2(", ", ", ")"); break; - case EOpConstructIVec3: writeTriplet(visit, "ivec3(", ", ", ")"); break; - case EOpConstructIVec4: writeTriplet(visit, "ivec4(", ", ", ")"); break; - case EOpConstructMat2: writeTriplet(visit, "mat2(", ", ", ")"); break; - case EOpConstructMat3: writeTriplet(visit, "mat3(", ", ", ")"); break; - case EOpConstructMat4: writeTriplet(visit, "mat4(", ", ", ")"); break; - case EOpConstructStruct: - if (visit == PreVisit) - { - const TType& type = node->getType(); - ASSERT(type.getBasicType() == EbtStruct); - out << hashName(type.getStruct()->name()) << "("; - } - else if (visit == InVisit) - { - out << ", "; - } - else - { - out << ")"; - } - break; - - case EOpLessThan: preString = "lessThan("; delayedWrite = true; break; - case EOpGreaterThan: preString = "greaterThan("; delayedWrite = true; break; - case EOpLessThanEqual: preString = "lessThanEqual("; delayedWrite = true; break; - case EOpGreaterThanEqual: preString = "greaterThanEqual("; delayedWrite = true; break; - case EOpVectorEqual: preString = "equal("; delayedWrite = true; break; - case EOpVectorNotEqual: preString = "notEqual("; delayedWrite = true; break; - case EOpComma: writeTriplet(visit, NULL, ", ", NULL); break; - - case EOpMod: preString = "mod("; delayedWrite = true; break; - case EOpPow: preString = "pow("; delayedWrite = true; break; - case EOpAtan: preString = "atan("; delayedWrite = true; break; - case EOpMin: preString = "min("; delayedWrite = true; break; - case EOpMax: preString = "max("; delayedWrite = true; break; - case EOpClamp: preString = "clamp("; delayedWrite = true; break; - case EOpMix: preString = "mix("; delayedWrite = true; break; - case EOpStep: preString = "step("; delayedWrite = true; break; - case EOpSmoothStep: preString = "smoothstep("; delayedWrite = true; break; - - case EOpDistance: preString = "distance("; delayedWrite = true; break; - case EOpDot: preString = "dot("; delayedWrite = true; break; - case EOpCross: preString = "cross("; delayedWrite = true; break; - case EOpFaceForward: preString = "faceforward("; delayedWrite = true; break; - case EOpReflect: preString = "reflect("; delayedWrite = true; break; - case EOpRefract: preString = "refract("; delayedWrite = true; break; - case EOpMul: preString = "matrixCompMult("; delayedWrite = true; break; - - default: UNREACHABLE(); break; + else + { + mDeclaringVariables = false; + } + break; + case EOpConstructFloat: + writeTriplet(visit, "float(", NULL, ")"); + break; + case EOpConstructVec2: + writeBuiltInFunctionTriplet(visit, "vec2(", false); + break; + case EOpConstructVec3: + writeBuiltInFunctionTriplet(visit, "vec3(", false); + break; + case EOpConstructVec4: + writeBuiltInFunctionTriplet(visit, "vec4(", false); + break; + case EOpConstructBool: + writeTriplet(visit, "bool(", NULL, ")"); + break; + case EOpConstructBVec2: + writeBuiltInFunctionTriplet(visit, "bvec2(", false); + break; + case EOpConstructBVec3: + writeBuiltInFunctionTriplet(visit, "bvec3(", false); + break; + case EOpConstructBVec4: + writeBuiltInFunctionTriplet(visit, "bvec4(", false); + break; + case EOpConstructInt: + writeTriplet(visit, "int(", NULL, ")"); + break; + case EOpConstructIVec2: + writeBuiltInFunctionTriplet(visit, "ivec2(", false); + break; + case EOpConstructIVec3: + writeBuiltInFunctionTriplet(visit, "ivec3(", false); + break; + case EOpConstructIVec4: + writeBuiltInFunctionTriplet(visit, "ivec4(", false); + break; + case EOpConstructMat2: + writeBuiltInFunctionTriplet(visit, "mat2(", false); + break; + case EOpConstructMat3: + writeBuiltInFunctionTriplet(visit, "mat3(", false); + break; + case EOpConstructMat4: + writeBuiltInFunctionTriplet(visit, "mat4(", false); + break; + case EOpConstructStruct: + if (visit == PreVisit) + { + const TType &type = node->getType(); + ASSERT(type.getBasicType() == EbtStruct); + out << hashName(type.getStruct()->name()) << "("; + } + else if (visit == InVisit) + { + out << ", "; + } + else + { + out << ")"; + } + break; + + case EOpLessThan: + writeBuiltInFunctionTriplet(visit, "lessThan(", useEmulatedFunction); + break; + case EOpGreaterThan: + writeBuiltInFunctionTriplet(visit, "greaterThan(", useEmulatedFunction); + break; + case EOpLessThanEqual: + writeBuiltInFunctionTriplet(visit, "lessThanEqual(", useEmulatedFunction); + break; + case EOpGreaterThanEqual: + writeBuiltInFunctionTriplet(visit, "greaterThanEqual(", useEmulatedFunction); + break; + case EOpVectorEqual: + writeBuiltInFunctionTriplet(visit, "equal(", useEmulatedFunction); + break; + case EOpVectorNotEqual: + writeBuiltInFunctionTriplet(visit, "notEqual(", useEmulatedFunction); + break; + case EOpComma: + writeTriplet(visit, NULL, ", ", NULL); + break; + + case EOpMod: + writeBuiltInFunctionTriplet(visit, "mod(", useEmulatedFunction); + break; + case EOpPow: + writeBuiltInFunctionTriplet(visit, "pow(", useEmulatedFunction); + break; + case EOpAtan: + writeBuiltInFunctionTriplet(visit, "atan(", useEmulatedFunction); + break; + case EOpMin: + writeBuiltInFunctionTriplet(visit, "min(", useEmulatedFunction); + break; + case EOpMax: + writeBuiltInFunctionTriplet(visit, "max(", useEmulatedFunction); + break; + case EOpClamp: + writeBuiltInFunctionTriplet(visit, "clamp(", useEmulatedFunction); + break; + case EOpMix: + writeBuiltInFunctionTriplet(visit, "mix(", useEmulatedFunction); + break; + case EOpStep: + writeBuiltInFunctionTriplet(visit, "step(", useEmulatedFunction); + break; + case EOpSmoothStep: + writeBuiltInFunctionTriplet(visit, "smoothstep(", useEmulatedFunction); + break; + case EOpDistance: + writeBuiltInFunctionTriplet(visit, "distance(", useEmulatedFunction); + break; + case EOpDot: + writeBuiltInFunctionTriplet(visit, "dot(", useEmulatedFunction); + break; + case EOpCross: + writeBuiltInFunctionTriplet(visit, "cross(", useEmulatedFunction); + break; + case EOpFaceForward: + writeBuiltInFunctionTriplet(visit, "faceforward(", useEmulatedFunction); + break; + case EOpReflect: + writeBuiltInFunctionTriplet(visit, "reflect(", useEmulatedFunction); + break; + case EOpRefract: + writeBuiltInFunctionTriplet(visit, "refract(", useEmulatedFunction); + break; + case EOpMul: + writeBuiltInFunctionTriplet(visit, "matrixCompMult(", useEmulatedFunction); + break; + + default: + UNREACHABLE(); } - if (delayedWrite && visit == PreVisit && node->getUseEmulatedFunction()) - preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString); - if (delayedWrite) - writeTriplet(visit, preString.c_str(), ", ", ")"); return visitChildren; } -bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) +bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); incrementDepth(node); // Loop header. TLoopType loopType = node->getType(); if (loopType == ELoopFor) // for loop { - if (!node->getUnrollFlag()) { + if (!node->getUnrollFlag()) + { out << "for ("; if (node->getInit()) node->getInit()->traverse(this); @@ -657,6 +811,18 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) node->getExpression()->traverse(this); out << ")\n"; } + else + { + // Need to put a one-iteration loop here to handle break. + TIntermSequence *declSeq = + node->getInit()->getAsAggregate()->getSequence(); + TIntermSymbol *indexSymbol = + (*declSeq)[0]->getAsBinaryNode()->getLeft()->getAsSymbolNode(); + TString name = hashVariableName(indexSymbol->getSymbol()); + out << "for (int " << name << " = 0; " + << name << " < 1; " + << "++" << name << ")\n"; + } } else if (loopType == ELoopWhile) // while loop { @@ -674,15 +840,15 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) // Loop body. if (node->getUnrollFlag()) { - TLoopIndexInfo indexInfo; - mLoopUnroll.FillLoopIndexInfo(node, indexInfo); - mLoopUnroll.Push(indexInfo); - while (mLoopUnroll.SatisfiesLoopCondition()) + out << "{\n"; + mLoopUnrollStack.push(node); + while (mLoopUnrollStack.satisfiesLoopCondition()) { visitCodeBlock(node->getBody()); - mLoopUnroll.Step(); + mLoopUnrollStack.step(); } - mLoopUnroll.Pop(); + mLoopUnrollStack.pop(); + out << "}\n"; } else { @@ -704,21 +870,31 @@ bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop* node) return false; } -bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch* node) +bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node) { switch (node->getFlowOp()) { - case EOpKill: writeTriplet(visit, "discard", NULL, NULL); break; - case EOpBreak: writeTriplet(visit, "break", NULL, NULL); break; - case EOpContinue: writeTriplet(visit, "continue", NULL, NULL); break; - case EOpReturn: writeTriplet(visit, "return ", NULL, NULL); break; - default: UNREACHABLE(); break; + case EOpKill: + writeTriplet(visit, "discard", NULL, NULL); + break; + case EOpBreak: + writeTriplet(visit, "break", NULL, NULL); + break; + case EOpContinue: + writeTriplet(visit, "continue", NULL, NULL); + break; + case EOpReturn: + writeTriplet(visit, "return ", NULL, NULL); + break; + default: + UNREACHABLE(); } return true; } -void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { +void TOutputGLSLBase::visitCodeBlock(TIntermNode *node) +{ TInfoSinkBase &out = objSink(); if (node != NULL) { @@ -734,7 +910,7 @@ void TOutputGLSLBase::visitCodeBlock(TIntermNode* node) { } } -TString TOutputGLSLBase::getTypeName(const TType& type) +TString TOutputGLSLBase::getTypeName(const TType &type) { TInfoSinkBase out; if (type.isMatrix()) @@ -746,10 +922,17 @@ TString TOutputGLSLBase::getTypeName(const TType& type) { switch (type.getBasicType()) { - case EbtFloat: out << "vec"; break; - case EbtInt: out << "ivec"; break; - case EbtBool: out << "bvec"; break; - default: UNREACHABLE(); break; + case EbtFloat: + out << "vec"; + break; + case EbtInt: + out << "ivec"; + break; + case EbtBool: + out << "bvec"; + break; + default: + UNREACHABLE(); } out << type.getNominalSize(); } @@ -763,7 +946,7 @@ TString TOutputGLSLBase::getTypeName(const TType& type) return TString(out.c_str()); } -TString TOutputGLSLBase::hashName(const TString& name) +TString TOutputGLSLBase::hashName(const TString &name) { if (mHashFunction == NULL || name.empty()) return name; @@ -775,35 +958,41 @@ TString TOutputGLSLBase::hashName(const TString& name) return hashedName; } -TString TOutputGLSLBase::hashVariableName(const TString& name) +TString TOutputGLSLBase::hashVariableName(const TString &name) { - if (mSymbolTable.findBuiltIn(name) != NULL) + if (mSymbolTable.findBuiltIn(name, mShaderVersion) != NULL) return name; return hashName(name); } -TString TOutputGLSLBase::hashFunctionName(const TString& mangled_name) +TString TOutputGLSLBase::hashFunctionName(const TString &mangled_name) { TString name = TFunction::unmangleName(mangled_name); - if (mSymbolTable.findBuiltIn(mangled_name) != NULL || name == "main") - return name; + if (mSymbolTable.findBuiltIn(mangled_name, mShaderVersion) != NULL || name == "main") + return translateTextureFunction(name); return hashName(name); } -bool TOutputGLSLBase::structDeclared(const TStructure* structure) const +bool TOutputGLSLBase::structDeclared(const TStructure *structure) const { - return mDeclaredStructs.find(structure->name()) != mDeclaredStructs.end(); + ASSERT(structure); + if (structure->name().empty()) + { + return false; + } + + return (mDeclaredStructs.count(structure->uniqueId()) > 0); } -void TOutputGLSLBase::declareStruct(const TStructure* structure) +void TOutputGLSLBase::declareStruct(const TStructure *structure) { - TInfoSinkBase& out = objSink(); + TInfoSinkBase &out = objSink(); out << "struct " << hashName(structure->name()) << "{\n"; - const TFieldList& fields = structure->fields(); + const TFieldList &fields = structure->fields(); for (size_t i = 0; i < fields.size(); ++i) { - const TField* field = fields[i]; + const TField *field = fields[i]; if (writeVariablePrecision(field->type()->getPrecision())) out << " "; out << getTypeName(*field->type()) << " " << hashName(field->name()); @@ -812,6 +1001,5 @@ void TOutputGLSLBase::declareStruct(const TStructure* structure) out << ";\n"; } out << "}"; - - mDeclaredStructs.insert(structure->name()); } + |