summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp1357
1 files changed, 0 insertions, 1357 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp b/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
deleted file mode 100644
index edaf2ebebf..0000000000
--- a/src/3rdparty/angle/src/compiler/translator/OutputGLSLBase.cpp
+++ /dev/null
@@ -1,1357 +0,0 @@
-//
-// 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.
-//
-
-#include "compiler/translator/OutputGLSLBase.h"
-
-#include "angle_gl.h"
-#include "common/debug.h"
-#include "common/mathutil.h"
-#include "compiler/translator/Compiler.h"
-#include "compiler/translator/util.h"
-
-#include <cfloat>
-
-namespace sh
-{
-
-namespace
-{
-
-bool isSingleStatement(TIntermNode *node)
-{
- if (node->getAsFunctionDefinition())
- {
- return false;
- }
- else if (node->getAsBlock())
- {
- return false;
- }
- else if (node->getAsIfElseNode())
- {
- return false;
- }
- else if (node->getAsLoopNode())
- {
- return false;
- }
- else if (node->getAsSwitchNode())
- {
- return false;
- }
- else if (node->getAsCaseNode())
- {
- return false;
- }
- return true;
-}
-
-class CommaSeparatedListItemPrefixGenerator
-{
- public:
- CommaSeparatedListItemPrefixGenerator() : mFirst(true) {}
- private:
- bool mFirst;
-
- friend TInfoSinkBase &operator<<(TInfoSinkBase &out,
- CommaSeparatedListItemPrefixGenerator &gen);
-};
-
-TInfoSinkBase &operator<<(TInfoSinkBase &out, CommaSeparatedListItemPrefixGenerator &gen)
-{
- if (gen.mFirst)
- {
- gen.mFirst = false;
- }
- else
- {
- out << ", ";
- }
- return out;
-}
-
-} // namespace
-
-TOutputGLSLBase::TOutputGLSLBase(TInfoSinkBase &objSink,
- ShArrayIndexClampingStrategy clampingStrategy,
- ShHashFunction64 hashFunction,
- NameMap &nameMap,
- TSymbolTable *symbolTable,
- sh::GLenum shaderType,
- int shaderVersion,
- ShShaderOutput output,
- ShCompileOptions compileOptions)
- : TIntermTraverser(true, true, true, symbolTable),
- mObjSink(objSink),
- mDeclaringVariable(false),
- mClampingStrategy(clampingStrategy),
- mHashFunction(hashFunction),
- mNameMap(nameMap),
- mShaderType(shaderType),
- mShaderVersion(shaderVersion),
- mOutput(output),
- mCompileOptions(compileOptions)
-{
-}
-
-void TOutputGLSLBase::writeInvariantQualifier(const TType &type)
-{
- if (!sh::RemoveInvariant(mShaderType, mShaderVersion, mOutput, mCompileOptions))
- {
- TInfoSinkBase &out = objSink();
- out << "invariant ";
- }
-}
-
-void TOutputGLSLBase::writeFloat(TInfoSinkBase &out, float f)
-{
- if ((gl::isInf(f) || gl::isNaN(f)) && mShaderVersion >= 300)
- {
- out << "uintBitsToFloat(" << gl::bitCast<uint32_t>(f) << "u)";
- }
- else
- {
- out << std::min(FLT_MAX, std::max(-FLT_MAX, f));
- }
-}
-
-void TOutputGLSLBase::writeTriplet(Visit visit,
- const char *preStr,
- const char *inStr,
- const char *postStr)
-{
- 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::writeBuiltInFunctionTriplet(Visit visit,
- TOperator op,
- bool useEmulatedFunction)
-{
- TInfoSinkBase &out = objSink();
- if (visit == PreVisit)
- {
- const char *opStr(GetOperatorString(op));
- if (useEmulatedFunction)
- {
- BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
- }
- else
- {
- out << opStr;
- }
- out << "(";
- }
- else
- {
- writeTriplet(visit, nullptr, ", ", ")");
- }
-}
-
-void TOutputGLSLBase::writeLayoutQualifier(TIntermTyped *variable)
-{
- const TType &type = variable->getType();
-
- if (!NeedsToWriteLayoutQualifier(type))
- {
- return;
- }
-
- TInfoSinkBase &out = objSink();
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
- out << "layout(";
-
- CommaSeparatedListItemPrefixGenerator listItemPrefix;
-
- if (type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
- IsVarying(type.getQualifier()))
- {
- if (layoutQualifier.location >= 0)
- {
- out << listItemPrefix << "location = " << layoutQualifier.location;
- }
- }
-
- if (type.getQualifier() == EvqFragmentOut)
- {
- if (layoutQualifier.yuv == true)
- {
- out << listItemPrefix << "yuv";
- }
- }
-
- if (IsOpaqueType(type.getBasicType()))
- {
- if (layoutQualifier.binding >= 0)
- {
- out << listItemPrefix << "binding = " << layoutQualifier.binding;
- }
- }
-
- if (IsImage(type.getBasicType()))
- {
- if (layoutQualifier.imageInternalFormat != EiifUnspecified)
- {
- ASSERT(type.getQualifier() == EvqTemporary || type.getQualifier() == EvqUniform);
- out << listItemPrefix
- << getImageInternalFormatString(layoutQualifier.imageInternalFormat);
- }
- }
-
- if (IsAtomicCounter(type.getBasicType()))
- {
- out << listItemPrefix << "offset = " << layoutQualifier.offset;
- }
-
- out << ") ";
-}
-
-const char *TOutputGLSLBase::mapQualifierToString(TQualifier qualifier)
-{
- if (sh::IsGLSL410OrOlder(mOutput) && mShaderVersion >= 300 &&
- (mCompileOptions & SH_REMOVE_INVARIANT_AND_CENTROID_FOR_ESSL3) != 0)
- {
- switch (qualifier)
- {
- // The return string is consistent with sh::getQualifierString() from
- // BaseTypes.h minus the "centroid" keyword.
- case EvqCentroid:
- return "";
- case EvqCentroidIn:
- return "smooth in";
- case EvqCentroidOut:
- return "smooth out";
- default:
- break;
- }
- }
- if (sh::IsGLSL130OrNewer(mOutput))
- {
- switch (qualifier)
- {
- case EvqAttribute:
- return "in";
- case EvqVaryingIn:
- return "in";
- case EvqVaryingOut:
- return "out";
- default:
- break;
- }
- }
- return sh::getQualifierString(qualifier);
-}
-
-void TOutputGLSLBase::writeVariableType(const TType &type)
-{
- TQualifier qualifier = type.getQualifier();
- TInfoSinkBase &out = objSink();
- if (type.isInvariant())
- {
- writeInvariantQualifier(type);
- }
- if (type.getBasicType() == EbtInterfaceBlock)
- {
- TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- declareInterfaceBlockLayout(interfaceBlock);
- }
- if (qualifier != EvqTemporary && qualifier != EvqGlobal)
- {
- const char *qualifierString = mapQualifierToString(qualifier);
- if (qualifierString && qualifierString[0] != '\0')
- {
- out << qualifierString << " ";
- }
- }
-
- const TMemoryQualifier &memoryQualifier = type.getMemoryQualifier();
- if (memoryQualifier.readonly)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "readonly ";
- }
-
- if (memoryQualifier.writeonly)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "writeonly ";
- }
-
- if (memoryQualifier.coherent)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "coherent ";
- }
-
- if (memoryQualifier.restrictQualifier)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "restrict ";
- }
-
- if (memoryQualifier.volatileQualifier)
- {
- ASSERT(IsImage(type.getBasicType()));
- out << "volatile ";
- }
-
- // Declare the struct if we have not done so already.
- if (type.getBasicType() == EbtStruct && !structDeclared(type.getStruct()))
- {
- const TStructure *structure = type.getStruct();
-
- declareStruct(structure);
-
- if (!structure->name().empty())
- {
- mDeclaredStructs.insert(structure->uniqueId());
- }
- }
- else if (type.getBasicType() == EbtInterfaceBlock)
- {
- TInterfaceBlock *interfaceBlock = type.getInterfaceBlock();
- declareInterfaceBlock(interfaceBlock);
- }
- else
- {
- if (writeVariablePrecision(type.getPrecision()))
- out << " ";
- out << getTypeName(type);
- }
-}
-
-void TOutputGLSLBase::writeFunctionParameters(const TIntermSequence &args)
-{
- TInfoSinkBase &out = objSink();
- for (TIntermSequence::const_iterator iter = args.begin(); iter != args.end(); ++iter)
- {
- const TIntermSymbol *arg = (*iter)->getAsSymbolNode();
- ASSERT(arg != nullptr);
-
- const TType &type = arg->getType();
- writeVariableType(type);
-
- if (!arg->getName().getString().empty())
- out << " " << hashName(arg->getName());
- if (type.isArray())
- out << ArrayString(type);
-
- // Put a comma if this is not the last argument.
- if (iter != args.end() - 1)
- out << ", ";
- }
-}
-
-const TConstantUnion *TOutputGLSLBase::writeConstantUnion(const TType &type,
- const TConstantUnion *pConstUnion)
-{
- TInfoSinkBase &out = objSink();
-
- if (type.getBasicType() == EbtStruct)
- {
- const TStructure *structure = type.getStruct();
- out << hashName(TName(structure->name())) << "(";
-
- const TFieldList &fields = structure->fields();
- for (size_t i = 0; i < fields.size(); ++i)
- {
- const TType *fieldType = fields[i]->type();
- ASSERT(fieldType != nullptr);
- pConstUnion = writeConstantUnion(*fieldType, pConstUnion);
- if (i != fields.size() - 1)
- out << ", ";
- }
- out << ")";
- }
- else
- {
- size_t size = type.getObjectSize();
- bool writeType = size > 1;
- if (writeType)
- out << getTypeName(type) << "(";
- for (size_t i = 0; i < size; ++i, ++pConstUnion)
- {
- switch (pConstUnion->getType())
- {
- case EbtFloat:
- writeFloat(out, pConstUnion->getFConst());
- break;
- case EbtInt:
- out << pConstUnion->getIConst();
- break;
- case EbtUInt:
- out << pConstUnion->getUConst() << "u";
- break;
- case EbtBool:
- out << pConstUnion->getBConst();
- break;
- case EbtYuvCscStandardEXT:
- out << getYuvCscStandardEXTString(pConstUnion->getYuvCscStandardEXTConst());
- break;
- default:
- UNREACHABLE();
- }
- if (i != size - 1)
- out << ", ";
- }
- if (writeType)
- out << ")";
- }
- return pConstUnion;
-}
-
-void TOutputGLSLBase::writeConstructorTriplet(Visit visit, const TType &type)
-{
- TInfoSinkBase &out = objSink();
- if (visit == PreVisit)
- {
- if (type.isArray())
- {
- out << getTypeName(type);
- out << ArrayString(type);
- out << "(";
- }
- else
- {
- out << getTypeName(type) << "(";
- }
- }
- else
- {
- writeTriplet(visit, nullptr, ", ", ")");
- }
-}
-
-void TOutputGLSLBase::visitSymbol(TIntermSymbol *node)
-{
- TInfoSinkBase &out = objSink();
- out << hashVariableName(node->getName());
-
- if (mDeclaringVariable && node->getType().isArray())
- out << ArrayString(node->getType());
-}
-
-void TOutputGLSLBase::visitConstantUnion(TIntermConstantUnion *node)
-{
- writeConstantUnion(node->getType(), node->getUnionArrayPointer());
-}
-
-bool TOutputGLSLBase::visitSwizzle(Visit visit, TIntermSwizzle *node)
-{
- TInfoSinkBase &out = objSink();
- if (visit == PostVisit)
- {
- out << ".";
- node->writeOffsetsAsXYZW(&out);
- }
- return true;
-}
-
-bool TOutputGLSLBase::visitBinary(Visit visit, TIntermBinary *node)
-{
- bool visitChildren = true;
- TInfoSinkBase &out = objSink();
- switch (node->getOp())
- {
- case EOpComma:
- writeTriplet(visit, "(", ", ", ")");
- break;
- case EOpInitialize:
- if (visit == InVisit)
- {
- out << " = ";
- // RHS of initialize is not being declared.
- mDeclaringVariable = false;
- }
- break;
- case EOpAssign:
- writeTriplet(visit, "(", " = ", ")");
- break;
- case EOpAddAssign:
- writeTriplet(visit, "(", " += ", ")");
- break;
- case EOpSubAssign:
- writeTriplet(visit, "(", " -= ", ")");
- break;
- case EOpDivAssign:
- writeTriplet(visit, "(", " /= ", ")");
- break;
- case EOpIModAssign:
- writeTriplet(visit, "(", " %= ", ")");
- break;
- // Notice the fall-through.
- case EOpMulAssign:
- case EOpVectorTimesMatrixAssign:
- case EOpVectorTimesScalarAssign:
- case EOpMatrixTimesScalarAssign:
- case EOpMatrixTimesMatrixAssign:
- writeTriplet(visit, "(", " *= ", ")");
- break;
- case EOpBitShiftLeftAssign:
- writeTriplet(visit, "(", " <<= ", ")");
- break;
- case EOpBitShiftRightAssign:
- writeTriplet(visit, "(", " >>= ", ")");
- break;
- case EOpBitwiseAndAssign:
- writeTriplet(visit, "(", " &= ", ")");
- break;
- case EOpBitwiseXorAssign:
- writeTriplet(visit, "(", " ^= ", ")");
- break;
- case EOpBitwiseOrAssign:
- writeTriplet(visit, "(", " |= ", ")");
- break;
-
- case EOpIndexDirect:
- writeTriplet(visit, nullptr, "[", "]");
- break;
- case EOpIndexIndirect:
- if (node->getAddIndexClamp())
- {
- if (visit == InVisit)
- {
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "[int(clamp(float(";
- else
- out << "[webgl_int_clamp(";
- }
- else if (visit == PostVisit)
- {
- TIntermTyped *left = node->getLeft();
- TType leftType = left->getType();
-
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << "), 0.0, float(";
- else
- out << ", 0, ";
-
- if (leftType.isUnsizedArray())
- {
- // For runtime-sized arrays in ESSL 3.10 we need to call the length method
- // to get the length to clamp against. See ESSL 3.10 section 4.1.9. Note
- // that a runtime-sized array expression is guaranteed not to have side
- // effects, so it's fine to add the expression to the output twice.
- ASSERT(mShaderVersion >= 310);
- ASSERT(!left->hasSideEffects());
- left->traverse(this);
- out << ".length() - 1";
- }
- else
- {
- int maxSize;
- if (leftType.isArray())
- {
- maxSize = static_cast<int>(leftType.getOutermostArraySize()) - 1;
- }
- else
- {
- maxSize = leftType.getNominalSize() - 1;
- }
- out << maxSize;
- }
- if (mClampingStrategy == SH_CLAMP_WITH_CLAMP_INTRINSIC)
- out << ")))]";
- else
- out << ")]";
- }
- }
- else
- {
- writeTriplet(visit, nullptr, "[", "]");
- }
- 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(TName(fieldName));
-
- out << fieldName;
- visitChildren = false;
- }
- break;
- case EOpIndexDirectInterfaceBlock:
- if (visit == InVisit)
- {
- out << ".";
- const TInterfaceBlock *interfaceBlock =
- node->getLeft()->getType().getInterfaceBlock();
- const TIntermConstantUnion *index = node->getRight()->getAsConstantUnion();
- const TField *field = interfaceBlock->fields()[index->getIConst(0)];
-
- TString fieldName = field->name();
- if (!mSymbolTable->findBuiltIn(interfaceBlock->name(), mShaderVersion))
- {
- fieldName = hashName(TName(fieldName));
- }
- else
- {
- ASSERT(interfaceBlock->name() == "gl_PerVertex");
- }
-
- out << fieldName;
- visitChildren = false;
- }
- break;
-
- case EOpAdd:
- writeTriplet(visit, "(", " + ", ")");
- break;
- case EOpSub:
- writeTriplet(visit, "(", " - ", ")");
- break;
- case EOpMul:
- writeTriplet(visit, "(", " * ", ")");
- break;
- case EOpDiv:
- writeTriplet(visit, "(", " / ", ")");
- break;
- case EOpIMod:
- writeTriplet(visit, "(", " % ", ")");
- break;
- case EOpBitShiftLeft:
- writeTriplet(visit, "(", " << ", ")");
- break;
- case EOpBitShiftRight:
- writeTriplet(visit, "(", " >> ", ")");
- break;
- case EOpBitwiseAnd:
- writeTriplet(visit, "(", " & ", ")");
- break;
- case EOpBitwiseXor:
- writeTriplet(visit, "(", " ^ ", ")");
- break;
- case EOpBitwiseOr:
- writeTriplet(visit, "(", " | ", ")");
- 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)
-{
- TString preString;
- TString postString = ")";
-
- switch (node->getOp())
- {
- case EOpNegative:
- preString = "(-";
- break;
- case EOpPositive:
- preString = "(+";
- break;
- case EOpLogicalNot:
- preString = "(!";
- break;
- case EOpBitwiseNot:
- preString = "(~";
- break;
-
- case EOpPostIncrement:
- preString = "(";
- postString = "++)";
- break;
- case EOpPostDecrement:
- preString = "(";
- postString = "--)";
- break;
- case EOpPreIncrement:
- preString = "(++";
- break;
- case EOpPreDecrement:
- preString = "(--";
- break;
- case EOpArrayLength:
- preString = "((";
- postString = ").length())";
- break;
-
- case EOpRadians:
- case EOpDegrees:
- case EOpSin:
- case EOpCos:
- case EOpTan:
- case EOpAsin:
- case EOpAcos:
- case EOpAtan:
- case EOpSinh:
- case EOpCosh:
- case EOpTanh:
- case EOpAsinh:
- case EOpAcosh:
- case EOpAtanh:
- case EOpExp:
- case EOpLog:
- case EOpExp2:
- case EOpLog2:
- case EOpSqrt:
- case EOpInverseSqrt:
- case EOpAbs:
- case EOpSign:
- case EOpFloor:
- case EOpTrunc:
- case EOpRound:
- case EOpRoundEven:
- case EOpCeil:
- case EOpFract:
- case EOpIsNan:
- case EOpIsInf:
- case EOpFloatBitsToInt:
- case EOpFloatBitsToUint:
- case EOpIntBitsToFloat:
- case EOpUintBitsToFloat:
- case EOpPackSnorm2x16:
- case EOpPackUnorm2x16:
- case EOpPackHalf2x16:
- case EOpUnpackSnorm2x16:
- case EOpUnpackUnorm2x16:
- case EOpUnpackHalf2x16:
- case EOpPackUnorm4x8:
- case EOpPackSnorm4x8:
- case EOpUnpackUnorm4x8:
- case EOpUnpackSnorm4x8:
- case EOpLength:
- case EOpNormalize:
- case EOpDFdx:
- case EOpDFdy:
- case EOpFwidth:
- case EOpTranspose:
- case EOpDeterminant:
- case EOpInverse:
- case EOpAny:
- case EOpAll:
- case EOpLogicalNotComponentWise:
- case EOpBitfieldReverse:
- case EOpBitCount:
- case EOpFindLSB:
- case EOpFindMSB:
- writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
- return true;
- default:
- UNREACHABLE();
- }
-
- writeTriplet(visit, preString.c_str(), nullptr, postString.c_str());
-
- return true;
-}
-
-bool TOutputGLSLBase::visitTernary(Visit visit, TIntermTernary *node)
-{
- TInfoSinkBase &out = objSink();
- // Notice two brackets at the beginning and end. The outer ones
- // encapsulate the whole ternary expression. This preserves the
- // order of precedence when ternary expressions are used in a
- // compound expression, i.e., c = 2 * (a < b ? 1 : 2).
- out << "((";
- node->getCondition()->traverse(this);
- out << ") ? (";
- node->getTrueExpression()->traverse(this);
- out << ") : (";
- node->getFalseExpression()->traverse(this);
- out << "))";
- return false;
-}
-
-bool TOutputGLSLBase::visitIfElse(Visit visit, TIntermIfElse *node)
-{
- TInfoSinkBase &out = objSink();
-
- out << "if (";
- node->getCondition()->traverse(this);
- out << ")\n";
-
- visitCodeBlock(node->getTrueBlock());
-
- if (node->getFalseBlock())
- {
- out << "else\n";
- visitCodeBlock(node->getFalseBlock());
- }
- return false;
-}
-
-bool TOutputGLSLBase::visitSwitch(Visit visit, TIntermSwitch *node)
-{
- ASSERT(node->getStatementList());
- writeTriplet(visit, "switch (", ") ", nullptr);
- // The curly braces get written when visiting the statementList aggregate
- return true;
-}
-
-bool TOutputGLSLBase::visitCase(Visit visit, TIntermCase *node)
-{
- if (node->hasCondition())
- {
- writeTriplet(visit, "case (", nullptr, "):\n");
- return true;
- }
- else
- {
- TInfoSinkBase &out = objSink();
- out << "default:\n";
- return false;
- }
-}
-
-bool TOutputGLSLBase::visitBlock(Visit visit, TIntermBlock *node)
-{
- TInfoSinkBase &out = objSink();
- // Scope the blocks except when at the global scope.
- if (mDepth > 0)
- {
- out << "{\n";
- }
-
- for (TIntermSequence::const_iterator iter = node->getSequence()->begin();
- iter != node->getSequence()->end(); ++iter)
- {
- TIntermNode *curNode = *iter;
- ASSERT(curNode != nullptr);
- curNode->traverse(this);
-
- if (isSingleStatement(curNode))
- out << ";\n";
- }
-
- // Scope the blocks except when at the global scope.
- if (mDepth > 0)
- {
- out << "}\n";
- }
- return false;
-}
-
-bool TOutputGLSLBase::visitFunctionDefinition(Visit visit, TIntermFunctionDefinition *node)
-{
- TIntermFunctionPrototype *prototype = node->getFunctionPrototype();
- prototype->traverse(this);
- visitCodeBlock(node->getBody());
-
- // Fully processed; no need to visit children.
- return false;
-}
-
-bool TOutputGLSLBase::visitInvariantDeclaration(Visit visit, TIntermInvariantDeclaration *node)
-{
- TInfoSinkBase &out = objSink();
- ASSERT(visit == PreVisit);
- const TIntermSymbol *symbol = node->getSymbol();
- out << "invariant " << hashVariableName(symbol->getName());
- return false;
-}
-
-bool TOutputGLSLBase::visitFunctionPrototype(Visit visit, TIntermFunctionPrototype *node)
-{
- TInfoSinkBase &out = objSink();
- ASSERT(visit == PreVisit);
-
- const TType &type = node->getType();
- writeVariableType(type);
- if (type.isArray())
- out << ArrayString(type);
-
- out << " " << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
-
- out << "(";
- writeFunctionParameters(*(node->getSequence()));
- out << ")";
-
- return false;
-}
-
-bool TOutputGLSLBase::visitAggregate(Visit visit, TIntermAggregate *node)
-{
- bool visitChildren = true;
- TInfoSinkBase &out = objSink();
- switch (node->getOp())
- {
- case EOpCallFunctionInAST:
- case EOpCallInternalRawFunction:
- case EOpCallBuiltInFunction:
- // Function call.
- if (visit == PreVisit)
- {
- if (node->getOp() == EOpCallBuiltInFunction)
- {
- out << translateTextureFunction(node->getFunctionSymbolInfo()->getName());
- }
- else
- {
- out << hashFunctionNameIfNeeded(*node->getFunctionSymbolInfo());
- }
- out << "(";
- }
- else if (visit == InVisit)
- out << ", ";
- else
- out << ")";
- break;
- case EOpConstruct:
- writeConstructorTriplet(visit, node->getType());
- break;
-
- case EOpEqualComponentWise:
- case EOpNotEqualComponentWise:
- case EOpLessThanComponentWise:
- case EOpGreaterThanComponentWise:
- case EOpLessThanEqualComponentWise:
- case EOpGreaterThanEqualComponentWise:
- case EOpMod:
- case EOpModf:
- case EOpPow:
- case EOpAtan:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpFrexp:
- case EOpLdexp:
- case EOpDistance:
- case EOpDot:
- case EOpCross:
- case EOpFaceforward:
- case EOpReflect:
- case EOpRefract:
- case EOpMulMatrixComponentWise:
- case EOpOuterProduct:
- case EOpBitfieldExtract:
- case EOpBitfieldInsert:
- case EOpUaddCarry:
- case EOpUsubBorrow:
- case EOpUmulExtended:
- case EOpImulExtended:
- case EOpBarrier:
- case EOpMemoryBarrier:
- case EOpMemoryBarrierAtomicCounter:
- case EOpMemoryBarrierBuffer:
- case EOpMemoryBarrierImage:
- case EOpMemoryBarrierShared:
- case EOpGroupMemoryBarrier:
- case EOpEmitVertex:
- case EOpEndPrimitive:
- writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
- break;
- default:
- UNREACHABLE();
- }
- return visitChildren;
-}
-
-bool TOutputGLSLBase::visitDeclaration(Visit visit, TIntermDeclaration *node)
-{
- TInfoSinkBase &out = objSink();
-
- // Variable declaration.
- if (visit == PreVisit)
- {
- const TIntermSequence &sequence = *(node->getSequence());
- TIntermTyped *variable = sequence.front()->getAsTyped();
- writeLayoutQualifier(variable);
- writeVariableType(variable->getType());
- if (variable->getAsSymbolNode() == nullptr ||
- !variable->getAsSymbolNode()->getSymbol().empty())
- {
- out << " ";
- }
- mDeclaringVariable = true;
- }
- else if (visit == InVisit)
- {
- UNREACHABLE();
- }
- else
- {
- mDeclaringVariable = false;
- }
- return true;
-}
-
-bool TOutputGLSLBase::visitLoop(Visit visit, TIntermLoop *node)
-{
- TInfoSinkBase &out = objSink();
-
- TLoopType loopType = node->getType();
-
- if (loopType == ELoopFor) // for loop
- {
- out << "for (";
- if (node->getInit())
- node->getInit()->traverse(this);
- out << "; ";
-
- if (node->getCondition())
- node->getCondition()->traverse(this);
- out << "; ";
-
- if (node->getExpression())
- node->getExpression()->traverse(this);
- out << ")\n";
-
- visitCodeBlock(node->getBody());
- }
- else if (loopType == ELoopWhile) // while loop
- {
- out << "while (";
- ASSERT(node->getCondition() != nullptr);
- node->getCondition()->traverse(this);
- out << ")\n";
-
- visitCodeBlock(node->getBody());
- }
- else // do-while loop
- {
- ASSERT(loopType == ELoopDoWhile);
- out << "do\n";
-
- visitCodeBlock(node->getBody());
-
- out << "while (";
- ASSERT(node->getCondition() != nullptr);
- node->getCondition()->traverse(this);
- out << ");\n";
- }
-
- // No need to visit children. They have been already processed in
- // this function.
- return false;
-}
-
-bool TOutputGLSLBase::visitBranch(Visit visit, TIntermBranch *node)
-{
- switch (node->getFlowOp())
- {
- case EOpKill:
- writeTriplet(visit, "discard", nullptr, nullptr);
- break;
- case EOpBreak:
- writeTriplet(visit, "break", nullptr, nullptr);
- break;
- case EOpContinue:
- writeTriplet(visit, "continue", nullptr, nullptr);
- break;
- case EOpReturn:
- writeTriplet(visit, "return ", nullptr, nullptr);
- break;
- default:
- UNREACHABLE();
- }
-
- return true;
-}
-
-void TOutputGLSLBase::visitCodeBlock(TIntermBlock *node)
-{
- TInfoSinkBase &out = objSink();
- if (node != nullptr)
- {
- node->traverse(this);
- // Single statements not part of a sequence need to be terminated
- // with semi-colon.
- if (isSingleStatement(node))
- out << ";\n";
- }
- else
- {
- out << "{\n}\n"; // Empty code block.
- }
-}
-
-TString TOutputGLSLBase::getTypeName(const TType &type)
-{
- return GetTypeName(type, mHashFunction, &mNameMap);
-}
-
-TString TOutputGLSLBase::hashName(const TName &name)
-{
- return HashName(name, mHashFunction, &mNameMap);
-}
-
-TString TOutputGLSLBase::hashVariableName(const TName &name)
-{
- if (mSymbolTable->findBuiltIn(name.getString(), mShaderVersion) != nullptr ||
- name.getString().substr(0, 3) == "gl_")
- {
- if (mCompileOptions & SH_TRANSLATE_VIEWID_OVR_TO_UNIFORM &&
- name.getString() == "gl_ViewID_OVR")
- {
- TName uniformName(TString("ViewID_OVR"));
- uniformName.setInternal(true);
- return hashName(uniformName);
- }
- return name.getString();
- }
- return hashName(name);
-}
-
-TString TOutputGLSLBase::hashFunctionNameIfNeeded(const TFunctionSymbolInfo &info)
-{
- if (info.isMain())
- {
- return info.getName();
- }
- else
- {
- return hashName(info.getNameObj());
- }
-}
-
-bool TOutputGLSLBase::structDeclared(const TStructure *structure) const
-{
- ASSERT(structure);
- if (structure->name().empty())
- {
- return false;
- }
-
- return (mDeclaredStructs.count(structure->uniqueId()) > 0);
-}
-
-void TOutputGLSLBase::declareStruct(const TStructure *structure)
-{
- TInfoSinkBase &out = objSink();
-
- out << "struct " << hashName(TName(structure->name())) << "{\n";
- const TFieldList &fields = structure->fields();
- for (size_t i = 0; i < fields.size(); ++i)
- {
- const TField *field = fields[i];
- if (writeVariablePrecision(field->type()->getPrecision()))
- out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
- if (field->type()->isArray())
- out << ArrayString(*field->type());
- out << ";\n";
- }
- out << "}";
-}
-
-void TOutputGLSLBase::declareInterfaceBlockLayout(const TInterfaceBlock *interfaceBlock)
-{
- TInfoSinkBase &out = objSink();
-
- out << "layout(";
-
- switch (interfaceBlock->blockStorage())
- {
- case EbsUnspecified:
- case EbsShared:
- // Default block storage is shared.
- out << "shared";
- break;
-
- case EbsPacked:
- out << "packed";
- break;
-
- case EbsStd140:
- out << "std140";
- break;
-
- case EbsStd430:
- out << "std430";
- break;
-
- default:
- UNREACHABLE();
- break;
- }
-
- out << ", ";
-
- if (interfaceBlock->blockBinding() > 0)
- {
- out << "binding = " << interfaceBlock->blockBinding();
- out << ", ";
- }
-
- switch (interfaceBlock->matrixPacking())
- {
- case EmpUnspecified:
- case EmpColumnMajor:
- // Default matrix packing is column major.
- out << "column_major";
- break;
-
- case EmpRowMajor:
- out << "row_major";
- break;
-
- default:
- UNREACHABLE();
- break;
- }
-
- out << ") ";
-}
-
-void TOutputGLSLBase::declareInterfaceBlock(const TInterfaceBlock *interfaceBlock)
-{
- TInfoSinkBase &out = objSink();
-
- out << hashName(TName(interfaceBlock->name())) << "{\n";
- const TFieldList &fields = interfaceBlock->fields();
- for (size_t i = 0; i < fields.size(); ++i)
- {
- const TField *field = fields[i];
- if (writeVariablePrecision(field->type()->getPrecision()))
- out << " ";
- out << getTypeName(*field->type()) << " " << hashName(TName(field->name()));
- if (field->type()->isArray())
- out << ArrayString(*field->type());
- out << ";\n";
- }
- out << "}";
-}
-
-void WriteGeometryShaderLayoutQualifiers(TInfoSinkBase &out,
- sh::TLayoutPrimitiveType inputPrimitive,
- int invocations,
- sh::TLayoutPrimitiveType outputPrimitive,
- int maxVertices)
-{
- // Omit 'invocations = 1'
- if (inputPrimitive != EptUndefined || invocations > 1)
- {
- out << "layout (";
-
- if (inputPrimitive != EptUndefined)
- {
- out << getGeometryShaderPrimitiveTypeString(inputPrimitive);
- }
-
- if (invocations > 1)
- {
- if (inputPrimitive != EptUndefined)
- {
- out << ", ";
- }
- out << "invocations = " << invocations;
- }
- out << ") in;\n";
- }
-
- if (outputPrimitive != EptUndefined || maxVertices != -1)
- {
- out << "layout (";
-
- if (outputPrimitive != EptUndefined)
- {
- out << getGeometryShaderPrimitiveTypeString(outputPrimitive);
- }
-
- if (maxVertices != -1)
- {
- if (outputPrimitive != EptUndefined)
- {
- out << ", ";
- }
- out << "max_vertices = " << maxVertices;
- }
- out << ") out;\n";
- }
-}
-
-// If SH_SCALARIZE_VEC_AND_MAT_CONSTRUCTOR_ARGS is enabled, layout qualifiers are spilled whenever
-// variables with specified layout qualifiers are copied. Additional checks are needed against the
-// type and storage qualifier of the variable to verify that layout qualifiers have to be outputted.
-// TODO (mradev): Fix layout qualifier spilling in ScalarizeVecAndMatConstructorArgs and remove
-// NeedsToWriteLayoutQualifier.
-bool NeedsToWriteLayoutQualifier(const TType &type)
-{
- if (type.getBasicType() == EbtInterfaceBlock)
- {
- return false;
- }
-
- const TLayoutQualifier &layoutQualifier = type.getLayoutQualifier();
-
- if ((type.getQualifier() == EvqFragmentOut || type.getQualifier() == EvqVertexIn ||
- IsVarying(type.getQualifier())) &&
- layoutQualifier.location >= 0)
- {
- return true;
- }
-
- if (type.getQualifier() == EvqFragmentOut && layoutQualifier.yuv == true)
- {
- return true;
- }
-
- if (IsOpaqueType(type.getBasicType()) && layoutQualifier.binding != -1)
- {
- return true;
- }
-
- if (IsImage(type.getBasicType()) && layoutQualifier.imageInternalFormat != EiifUnspecified)
- {
- return true;
- }
- return false;
-}
-
-} // namespace sh