OutputHLSL: Avoid using info sink stack as much as possible.
Due to how the traversers work, it might not be trivial to avoid the
info sink stack entirely, but minimize its use to keep the code as
functional as possible.
BUG=angleproject:958
Change-Id: I354313f10f496feea7c6a6f167b0617aeadbe5b0
Reviewed-on: https://chromium-review.googlesource.com/316412
Tryjob-Request: Jamie Madill <jmadill@chromium.org>
Reviewed-by: Geoff Lang <geofflang@chromium.org>
Reviewed-by: Corentin Wallez <cwallez@chromium.org>
Tested-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index a2309a9..36c423c 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -239,7 +239,7 @@
mInfoSinkStack.pop();
mInfoSinkStack.push(&mHeader);
- header(&builtInFunctionEmulator);
+ header(mHeader, &builtInFunctionEmulator);
mInfoSinkStack.pop();
objSink << mHeader.c_str();
@@ -334,10 +334,8 @@
return init;
}
-void OutputHLSL::header(const BuiltInFunctionEmulator *builtInFunctionEmulator)
+void OutputHLSL::header(TInfoSinkBase &out, const BuiltInFunctionEmulator *builtInFunctionEmulator)
{
- TInfoSinkBase &out = getInfoSink();
-
TString varyings;
TString attributes;
TString flaggedStructs;
@@ -1458,11 +1456,11 @@
{
if (op == EOpEqual)
{
- outputTriplet(visit, "(", " == ", ")", out);
+ outputTriplet(out, visit, "(", " == ", ")");
}
else
{
- outputTriplet(visit, "(", " != ", ")", out);
+ outputTriplet(out, visit, "(", " != ", ")");
}
}
else
@@ -1475,18 +1473,18 @@
if (type.isArray())
{
const TString &functionName = addArrayEqualityFunction(type);
- outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out);
+ outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
}
else if (type.getBasicType() == EbtStruct)
{
const TStructure &structure = *type.getStruct();
const TString &functionName = addStructEqualityFunction(structure);
- outputTriplet(visit, (functionName + "(").c_str(), ", ", ")", out);
+ outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
}
else
{
ASSERT(type.isMatrix() || type.isVector());
- outputTriplet(visit, "all(", " == ", ")", out);
+ outputTriplet(out, visit, "all(", " == ", ")");
}
}
}
@@ -1526,11 +1524,11 @@
ASSERT(rightAgg == nullptr || rightAgg->getOp() != EOpFunctionCall);
const TString &functionName = addArrayAssignmentFunction(node->getType());
- outputTriplet(visit, (functionName + "(").c_str(), ", ", ")");
+ outputTriplet(out, visit, (functionName + "(").c_str(), ", ", ")");
}
else
{
- outputTriplet(visit, "(", " = ", ")");
+ outputTriplet(out, visit, "(", " = ", ")");
}
break;
case EOpInitialize:
@@ -1573,11 +1571,21 @@
out << " = ";
}
break;
- case EOpAddAssign: outputTriplet(visit, "(", " += ", ")"); break;
- case EOpSubAssign: outputTriplet(visit, "(", " -= ", ")"); break;
- case EOpMulAssign: outputTriplet(visit, "(", " *= ", ")"); break;
- case EOpVectorTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
- case EOpMatrixTimesScalarAssign: outputTriplet(visit, "(", " *= ", ")"); break;
+ case EOpAddAssign:
+ outputTriplet(out, visit, "(", " += ", ")");
+ break;
+ case EOpSubAssign:
+ outputTriplet(out, visit, "(", " -= ", ")");
+ break;
+ case EOpMulAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
+ case EOpVectorTimesScalarAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
+ case EOpMatrixTimesScalarAssign:
+ outputTriplet(out, visit, "(", " *= ", ")");
+ break;
case EOpVectorTimesMatrixAssign:
if (visit == PreVisit)
{
@@ -1610,13 +1618,27 @@
out << "))))";
}
break;
- case EOpDivAssign: outputTriplet(visit, "(", " /= ", ")"); break;
- case EOpIModAssign: outputTriplet(visit, "(", " %= ", ")"); break;
- case EOpBitShiftLeftAssign: outputTriplet(visit, "(", " <<= ", ")"); break;
- case EOpBitShiftRightAssign: outputTriplet(visit, "(", " >>= ", ")"); break;
- case EOpBitwiseAndAssign: outputTriplet(visit, "(", " &= ", ")"); break;
- case EOpBitwiseXorAssign: outputTriplet(visit, "(", " ^= ", ")"); break;
- case EOpBitwiseOrAssign: outputTriplet(visit, "(", " |= ", ")"); break;
+ case EOpDivAssign:
+ outputTriplet(out, visit, "(", " /= ", ")");
+ break;
+ case EOpIModAssign:
+ outputTriplet(out, visit, "(", " %= ", ")");
+ break;
+ case EOpBitShiftLeftAssign:
+ outputTriplet(out, visit, "(", " <<= ", ")");
+ break;
+ case EOpBitShiftRightAssign:
+ outputTriplet(out, visit, "(", " >>= ", ")");
+ break;
+ case EOpBitwiseAndAssign:
+ outputTriplet(out, visit, "(", " &= ", ")");
+ break;
+ case EOpBitwiseXorAssign:
+ outputTriplet(out, visit, "(", " ^= ", ")");
+ break;
+ case EOpBitwiseOrAssign:
+ outputTriplet(out, visit, "(", " |= ", ")");
+ break;
case EOpIndexDirect:
{
const TType& leftType = node->getLeft()->getType();
@@ -1633,14 +1655,14 @@
}
else
{
- outputTriplet(visit, "", "[", "]");
+ outputTriplet(out, visit, "", "[", "]");
}
}
break;
case EOpIndexIndirect:
// We do not currently support indirect references to interface blocks
ASSERT(node->getLeft()->getBasicType() != EbtInterfaceBlock);
- outputTriplet(visit, "", "[", "]");
+ outputTriplet(out, visit, "", "[", "]");
break;
case EOpIndexDirectStruct:
if (visit == InVisit)
@@ -1700,42 +1722,80 @@
return false; // Fully processed
}
break;
- case EOpAdd: outputTriplet(visit, "(", " + ", ")"); break;
- case EOpSub: outputTriplet(visit, "(", " - ", ")"); break;
- case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
- case EOpDiv: outputTriplet(visit, "(", " / ", ")"); break;
- case EOpIMod: outputTriplet(visit, "(", " % ", ")"); break;
- case EOpBitShiftLeft: outputTriplet(visit, "(", " << ", ")"); break;
- case EOpBitShiftRight: outputTriplet(visit, "(", " >> ", ")"); break;
- case EOpBitwiseAnd: outputTriplet(visit, "(", " & ", ")"); break;
- case EOpBitwiseXor: outputTriplet(visit, "(", " ^ ", ")"); break;
- case EOpBitwiseOr: outputTriplet(visit, "(", " | ", ")"); break;
+ case EOpAdd:
+ outputTriplet(out, visit, "(", " + ", ")");
+ break;
+ case EOpSub:
+ outputTriplet(out, visit, "(", " - ", ")");
+ break;
+ case EOpMul:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpDiv:
+ outputTriplet(out, visit, "(", " / ", ")");
+ break;
+ case EOpIMod:
+ outputTriplet(out, visit, "(", " % ", ")");
+ break;
+ case EOpBitShiftLeft:
+ outputTriplet(out, visit, "(", " << ", ")");
+ break;
+ case EOpBitShiftRight:
+ outputTriplet(out, visit, "(", " >> ", ")");
+ break;
+ case EOpBitwiseAnd:
+ outputTriplet(out, visit, "(", " & ", ")");
+ break;
+ case EOpBitwiseXor:
+ outputTriplet(out, visit, "(", " ^ ", ")");
+ break;
+ case EOpBitwiseOr:
+ outputTriplet(out, visit, "(", " | ", ")");
+ break;
case EOpEqual:
case EOpNotEqual:
outputEqual(visit, node->getLeft()->getType(), node->getOp(), out);
break;
- case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
- case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
- case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
- case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
- case EOpVectorTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
- case EOpMatrixTimesScalar: outputTriplet(visit, "(", " * ", ")"); break;
- case EOpVectorTimesMatrix: outputTriplet(visit, "mul(", ", transpose(", "))"); break;
- case EOpMatrixTimesVector: outputTriplet(visit, "mul(transpose(", "), ", ")"); break;
- case EOpMatrixTimesMatrix: outputTriplet(visit, "transpose(mul(transpose(", "), transpose(", ")))"); break;
+ case EOpLessThan:
+ outputTriplet(out, visit, "(", " < ", ")");
+ break;
+ case EOpGreaterThan:
+ outputTriplet(out, visit, "(", " > ", ")");
+ break;
+ case EOpLessThanEqual:
+ outputTriplet(out, visit, "(", " <= ", ")");
+ break;
+ case EOpGreaterThanEqual:
+ outputTriplet(out, visit, "(", " >= ", ")");
+ break;
+ case EOpVectorTimesScalar:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpMatrixTimesScalar:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
+ case EOpVectorTimesMatrix:
+ outputTriplet(out, visit, "mul(", ", transpose(", "))");
+ break;
+ case EOpMatrixTimesVector:
+ outputTriplet(out, visit, "mul(transpose(", "), ", ")");
+ break;
+ case EOpMatrixTimesMatrix:
+ outputTriplet(out, visit, "transpose(mul(transpose(", "), transpose(", ")))");
+ break;
case EOpLogicalOr:
// HLSL doesn't short-circuit ||, so we assume that || affected by short-circuiting have been unfolded.
ASSERT(!node->getRight()->hasSideEffects());
- outputTriplet(visit, "(", " || ", ")");
+ outputTriplet(out, visit, "(", " || ", ")");
return true;
case EOpLogicalXor:
mUsesXor = true;
- outputTriplet(visit, "xor(", ", ", ")");
+ outputTriplet(out, visit, "xor(", ", ", ")");
break;
case EOpLogicalAnd:
// HLSL doesn't short-circuit &&, so we assume that && affected by short-circuiting have been unfolded.
ASSERT(!node->getRight()->hasSideEffects());
- outputTriplet(visit, "(", " && ", ")");
+ outputTriplet(out, visit, "(", " && ", ")");
return true;
default: UNREACHABLE();
}
@@ -1745,131 +1805,221 @@
bool OutputHLSL::visitUnary(Visit visit, TIntermUnary *node)
{
+ TInfoSinkBase &out = getInfoSink();
+
switch (node->getOp())
{
- case EOpNegative: outputTriplet(visit, "(-", "", ")"); break;
- case EOpPositive: outputTriplet(visit, "(+", "", ")"); break;
- case EOpVectorLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
- case EOpLogicalNot: outputTriplet(visit, "(!", "", ")"); break;
- case EOpBitwiseNot: outputTriplet(visit, "(~", "", ")"); break;
- case EOpPostIncrement: outputTriplet(visit, "(", "", "++)"); break;
- case EOpPostDecrement: outputTriplet(visit, "(", "", "--)"); break;
- case EOpPreIncrement: outputTriplet(visit, "(++", "", ")"); break;
- case EOpPreDecrement: outputTriplet(visit, "(--", "", ")"); break;
- case EOpRadians: outputTriplet(visit, "radians(", "", ")"); break;
- case EOpDegrees: outputTriplet(visit, "degrees(", "", ")"); break;
- case EOpSin: outputTriplet(visit, "sin(", "", ")"); break;
- case EOpCos: outputTriplet(visit, "cos(", "", ")"); break;
- case EOpTan: outputTriplet(visit, "tan(", "", ")"); break;
- case EOpAsin: outputTriplet(visit, "asin(", "", ")"); break;
- case EOpAcos: outputTriplet(visit, "acos(", "", ")"); break;
- case EOpAtan: outputTriplet(visit, "atan(", "", ")"); break;
- case EOpSinh: outputTriplet(visit, "sinh(", "", ")"); break;
- case EOpCosh: outputTriplet(visit, "cosh(", "", ")"); break;
- case EOpTanh: outputTriplet(visit, "tanh(", "", ")"); break;
+ case EOpNegative:
+ outputTriplet(out, visit, "(-", "", ")");
+ break;
+ case EOpPositive:
+ outputTriplet(out, visit, "(+", "", ")");
+ break;
+ case EOpVectorLogicalNot:
+ outputTriplet(out, visit, "(!", "", ")");
+ break;
+ case EOpLogicalNot:
+ outputTriplet(out, visit, "(!", "", ")");
+ break;
+ case EOpBitwiseNot:
+ outputTriplet(out, visit, "(~", "", ")");
+ break;
+ case EOpPostIncrement:
+ outputTriplet(out, visit, "(", "", "++)");
+ break;
+ case EOpPostDecrement:
+ outputTriplet(out, visit, "(", "", "--)");
+ break;
+ case EOpPreIncrement:
+ outputTriplet(out, visit, "(++", "", ")");
+ break;
+ case EOpPreDecrement:
+ outputTriplet(out, visit, "(--", "", ")");
+ break;
+ case EOpRadians:
+ outputTriplet(out, visit, "radians(", "", ")");
+ break;
+ case EOpDegrees:
+ outputTriplet(out, visit, "degrees(", "", ")");
+ break;
+ case EOpSin:
+ outputTriplet(out, visit, "sin(", "", ")");
+ break;
+ case EOpCos:
+ outputTriplet(out, visit, "cos(", "", ")");
+ break;
+ case EOpTan:
+ outputTriplet(out, visit, "tan(", "", ")");
+ break;
+ case EOpAsin:
+ outputTriplet(out, visit, "asin(", "", ")");
+ break;
+ case EOpAcos:
+ outputTriplet(out, visit, "acos(", "", ")");
+ break;
+ case EOpAtan:
+ outputTriplet(out, visit, "atan(", "", ")");
+ break;
+ case EOpSinh:
+ outputTriplet(out, visit, "sinh(", "", ")");
+ break;
+ case EOpCosh:
+ outputTriplet(out, visit, "cosh(", "", ")");
+ break;
+ case EOpTanh:
+ outputTriplet(out, visit, "tanh(", "", ")");
+ break;
case EOpAsinh:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "asinh(");
+ writeEmulatedFunctionTriplet(out, visit, "asinh(");
break;
case EOpAcosh:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "acosh(");
+ writeEmulatedFunctionTriplet(out, visit, "acosh(");
break;
case EOpAtanh:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "atanh(");
+ writeEmulatedFunctionTriplet(out, visit, "atanh(");
break;
- case EOpExp: outputTriplet(visit, "exp(", "", ")"); break;
- case EOpLog: outputTriplet(visit, "log(", "", ")"); break;
- case EOpExp2: outputTriplet(visit, "exp2(", "", ")"); break;
- case EOpLog2: outputTriplet(visit, "log2(", "", ")"); break;
- case EOpSqrt: outputTriplet(visit, "sqrt(", "", ")"); break;
- case EOpInverseSqrt: outputTriplet(visit, "rsqrt(", "", ")"); break;
- case EOpAbs: outputTriplet(visit, "abs(", "", ")"); break;
- case EOpSign: outputTriplet(visit, "sign(", "", ")"); break;
- case EOpFloor: outputTriplet(visit, "floor(", "", ")"); break;
- case EOpTrunc: outputTriplet(visit, "trunc(", "", ")"); break;
- case EOpRound: outputTriplet(visit, "round(", "", ")"); break;
+ case EOpExp:
+ outputTriplet(out, visit, "exp(", "", ")");
+ break;
+ case EOpLog:
+ outputTriplet(out, visit, "log(", "", ")");
+ break;
+ case EOpExp2:
+ outputTriplet(out, visit, "exp2(", "", ")");
+ break;
+ case EOpLog2:
+ outputTriplet(out, visit, "log2(", "", ")");
+ break;
+ case EOpSqrt:
+ outputTriplet(out, visit, "sqrt(", "", ")");
+ break;
+ case EOpInverseSqrt:
+ outputTriplet(out, visit, "rsqrt(", "", ")");
+ break;
+ case EOpAbs:
+ outputTriplet(out, visit, "abs(", "", ")");
+ break;
+ case EOpSign:
+ outputTriplet(out, visit, "sign(", "", ")");
+ break;
+ case EOpFloor:
+ outputTriplet(out, visit, "floor(", "", ")");
+ break;
+ case EOpTrunc:
+ outputTriplet(out, visit, "trunc(", "", ")");
+ break;
+ case EOpRound:
+ outputTriplet(out, visit, "round(", "", ")");
+ break;
case EOpRoundEven:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "roundEven(");
+ writeEmulatedFunctionTriplet(out, visit, "roundEven(");
break;
- case EOpCeil: outputTriplet(visit, "ceil(", "", ")"); break;
- case EOpFract: outputTriplet(visit, "frac(", "", ")"); break;
+ case EOpCeil:
+ outputTriplet(out, visit, "ceil(", "", ")");
+ break;
+ case EOpFract:
+ outputTriplet(out, visit, "frac(", "", ")");
+ break;
case EOpIsNan:
- outputTriplet(visit, "isnan(", "", ")");
+ outputTriplet(out, visit, "isnan(", "", ")");
mRequiresIEEEStrictCompiling = true;
break;
- case EOpIsInf: outputTriplet(visit, "isinf(", "", ")"); break;
- case EOpFloatBitsToInt: outputTriplet(visit, "asint(", "", ")"); break;
- case EOpFloatBitsToUint: outputTriplet(visit, "asuint(", "", ")"); break;
- case EOpIntBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break;
- case EOpUintBitsToFloat: outputTriplet(visit, "asfloat(", "", ")"); break;
+ case EOpIsInf:
+ outputTriplet(out, visit, "isinf(", "", ")");
+ break;
+ case EOpFloatBitsToInt:
+ outputTriplet(out, visit, "asint(", "", ")");
+ break;
+ case EOpFloatBitsToUint:
+ outputTriplet(out, visit, "asuint(", "", ")");
+ break;
+ case EOpIntBitsToFloat:
+ outputTriplet(out, visit, "asfloat(", "", ")");
+ break;
+ case EOpUintBitsToFloat:
+ outputTriplet(out, visit, "asfloat(", "", ")");
+ break;
case EOpPackSnorm2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "packSnorm2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "packSnorm2x16(");
break;
case EOpPackUnorm2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "packUnorm2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "packUnorm2x16(");
break;
case EOpPackHalf2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "packHalf2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "packHalf2x16(");
break;
case EOpUnpackSnorm2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "unpackSnorm2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "unpackSnorm2x16(");
break;
case EOpUnpackUnorm2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "unpackUnorm2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "unpackUnorm2x16(");
break;
case EOpUnpackHalf2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "unpackHalf2x16(");
+ writeEmulatedFunctionTriplet(out, visit, "unpackHalf2x16(");
break;
- case EOpLength: outputTriplet(visit, "length(", "", ")"); break;
- case EOpNormalize: outputTriplet(visit, "normalize(", "", ")"); break;
+ case EOpLength:
+ outputTriplet(out, visit, "length(", "", ")");
+ break;
+ case EOpNormalize:
+ outputTriplet(out, visit, "normalize(", "", ")");
+ break;
case EOpDFdx:
if(mInsideDiscontinuousLoop || mOutputLod0Function)
{
- outputTriplet(visit, "(", "", ", 0.0)");
+ outputTriplet(out, visit, "(", "", ", 0.0)");
}
else
{
- outputTriplet(visit, "ddx(", "", ")");
+ outputTriplet(out, visit, "ddx(", "", ")");
}
break;
case EOpDFdy:
if(mInsideDiscontinuousLoop || mOutputLod0Function)
{
- outputTriplet(visit, "(", "", ", 0.0)");
+ outputTriplet(out, visit, "(", "", ", 0.0)");
}
else
{
- outputTriplet(visit, "ddy(", "", ")");
+ outputTriplet(out, visit, "ddy(", "", ")");
}
break;
case EOpFwidth:
if(mInsideDiscontinuousLoop || mOutputLod0Function)
{
- outputTriplet(visit, "(", "", ", 0.0)");
+ outputTriplet(out, visit, "(", "", ", 0.0)");
}
else
{
- outputTriplet(visit, "fwidth(", "", ")");
+ outputTriplet(out, visit, "fwidth(", "", ")");
}
break;
- case EOpTranspose: outputTriplet(visit, "transpose(", "", ")"); break;
- case EOpDeterminant: outputTriplet(visit, "determinant(transpose(", "", "))"); break;
+ case EOpTranspose:
+ outputTriplet(out, visit, "transpose(", "", ")");
+ break;
+ case EOpDeterminant:
+ outputTriplet(out, visit, "determinant(transpose(", "", "))");
+ break;
case EOpInverse:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "inverse(");
+ writeEmulatedFunctionTriplet(out, visit, "inverse(");
break;
- case EOpAny: outputTriplet(visit, "any(", "", ")"); break;
- case EOpAll: outputTriplet(visit, "all(", "", ")"); break;
+ case EOpAny:
+ outputTriplet(out, visit, "any(", "", ")");
+ break;
+ case EOpAll:
+ outputTriplet(out, visit, "all(", "", ")");
+ break;
default: UNREACHABLE();
}
@@ -1886,13 +2036,13 @@
{
if (mInsideFunction)
{
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
out << "{\n";
}
for (TIntermSequence::iterator sit = node->getSequence()->begin(); sit != node->getSequence()->end(); sit++)
{
- outputLineDirective((*sit)->getLine().first_line);
+ outputLineDirective(out, (*sit)->getLine().first_line);
(*sit)->traverse(this);
@@ -1909,7 +2059,7 @@
if (mInsideFunction)
{
- outputLineDirective(node->getLine().last_line);
+ outputLineDirective(out, node->getLine().last_line);
out << "}\n";
}
@@ -2030,7 +2180,9 @@
return false;
}
break;
- case EOpComma: outputTriplet(visit, "(", ", ", ")"); break;
+ case EOpComma:
+ outputTriplet(out, visit, "(", ", ", ")");
+ break;
case EOpFunction:
{
ASSERT(mCurrentFunctionMetadata == nullptr);
@@ -2263,32 +2415,84 @@
return false;
}
break;
- case EOpParameters: outputTriplet(visit, "(", ", ", ")\n{\n"); break;
- case EOpConstructFloat: outputConstructor(visit, node->getType(), "vec1", node->getSequence()); break;
- case EOpConstructVec2: outputConstructor(visit, node->getType(), "vec2", node->getSequence()); break;
- case EOpConstructVec3: outputConstructor(visit, node->getType(), "vec3", node->getSequence()); break;
- case EOpConstructVec4: outputConstructor(visit, node->getType(), "vec4", node->getSequence()); break;
- case EOpConstructBool: outputConstructor(visit, node->getType(), "bvec1", node->getSequence()); break;
- case EOpConstructBVec2: outputConstructor(visit, node->getType(), "bvec2", node->getSequence()); break;
- case EOpConstructBVec3: outputConstructor(visit, node->getType(), "bvec3", node->getSequence()); break;
- case EOpConstructBVec4: outputConstructor(visit, node->getType(), "bvec4", node->getSequence()); break;
- case EOpConstructInt: outputConstructor(visit, node->getType(), "ivec1", node->getSequence()); break;
- case EOpConstructIVec2: outputConstructor(visit, node->getType(), "ivec2", node->getSequence()); break;
- case EOpConstructIVec3: outputConstructor(visit, node->getType(), "ivec3", node->getSequence()); break;
- case EOpConstructIVec4: outputConstructor(visit, node->getType(), "ivec4", node->getSequence()); break;
- case EOpConstructUInt: outputConstructor(visit, node->getType(), "uvec1", node->getSequence()); break;
- case EOpConstructUVec2: outputConstructor(visit, node->getType(), "uvec2", node->getSequence()); break;
- case EOpConstructUVec3: outputConstructor(visit, node->getType(), "uvec3", node->getSequence()); break;
- case EOpConstructUVec4: outputConstructor(visit, node->getType(), "uvec4", node->getSequence()); break;
- case EOpConstructMat2: outputConstructor(visit, node->getType(), "mat2", node->getSequence()); break;
- case EOpConstructMat2x3: outputConstructor(visit, node->getType(), "mat2x3", node->getSequence()); break;
- case EOpConstructMat2x4: outputConstructor(visit, node->getType(), "mat2x4", node->getSequence()); break;
- case EOpConstructMat3x2: outputConstructor(visit, node->getType(), "mat3x2", node->getSequence()); break;
- case EOpConstructMat3: outputConstructor(visit, node->getType(), "mat3", node->getSequence()); break;
- case EOpConstructMat3x4: outputConstructor(visit, node->getType(), "mat3x4", node->getSequence()); break;
- case EOpConstructMat4x2: outputConstructor(visit, node->getType(), "mat4x2", node->getSequence()); break;
- case EOpConstructMat4x3: outputConstructor(visit, node->getType(), "mat4x3", node->getSequence()); break;
- case EOpConstructMat4: outputConstructor(visit, node->getType(), "mat4", node->getSequence()); break;
+ case EOpParameters:
+ outputTriplet(out, visit, "(", ", ", ")\n{\n");
+ break;
+ case EOpConstructFloat:
+ outputConstructor(out, visit, node->getType(), "vec1", node->getSequence());
+ break;
+ case EOpConstructVec2:
+ outputConstructor(out, visit, node->getType(), "vec2", node->getSequence());
+ break;
+ case EOpConstructVec3:
+ outputConstructor(out, visit, node->getType(), "vec3", node->getSequence());
+ break;
+ case EOpConstructVec4:
+ outputConstructor(out, visit, node->getType(), "vec4", node->getSequence());
+ break;
+ case EOpConstructBool:
+ outputConstructor(out, visit, node->getType(), "bvec1", node->getSequence());
+ break;
+ case EOpConstructBVec2:
+ outputConstructor(out, visit, node->getType(), "bvec2", node->getSequence());
+ break;
+ case EOpConstructBVec3:
+ outputConstructor(out, visit, node->getType(), "bvec3", node->getSequence());
+ break;
+ case EOpConstructBVec4:
+ outputConstructor(out, visit, node->getType(), "bvec4", node->getSequence());
+ break;
+ case EOpConstructInt:
+ outputConstructor(out, visit, node->getType(), "ivec1", node->getSequence());
+ break;
+ case EOpConstructIVec2:
+ outputConstructor(out, visit, node->getType(), "ivec2", node->getSequence());
+ break;
+ case EOpConstructIVec3:
+ outputConstructor(out, visit, node->getType(), "ivec3", node->getSequence());
+ break;
+ case EOpConstructIVec4:
+ outputConstructor(out, visit, node->getType(), "ivec4", node->getSequence());
+ break;
+ case EOpConstructUInt:
+ outputConstructor(out, visit, node->getType(), "uvec1", node->getSequence());
+ break;
+ case EOpConstructUVec2:
+ outputConstructor(out, visit, node->getType(), "uvec2", node->getSequence());
+ break;
+ case EOpConstructUVec3:
+ outputConstructor(out, visit, node->getType(), "uvec3", node->getSequence());
+ break;
+ case EOpConstructUVec4:
+ outputConstructor(out, visit, node->getType(), "uvec4", node->getSequence());
+ break;
+ case EOpConstructMat2:
+ outputConstructor(out, visit, node->getType(), "mat2", node->getSequence());
+ break;
+ case EOpConstructMat2x3:
+ outputConstructor(out, visit, node->getType(), "mat2x3", node->getSequence());
+ break;
+ case EOpConstructMat2x4:
+ outputConstructor(out, visit, node->getType(), "mat2x4", node->getSequence());
+ break;
+ case EOpConstructMat3x2:
+ outputConstructor(out, visit, node->getType(), "mat3x2", node->getSequence());
+ break;
+ case EOpConstructMat3:
+ outputConstructor(out, visit, node->getType(), "mat3", node->getSequence());
+ break;
+ case EOpConstructMat3x4:
+ outputConstructor(out, visit, node->getType(), "mat3x4", node->getSequence());
+ break;
+ case EOpConstructMat4x2:
+ outputConstructor(out, visit, node->getType(), "mat4x2", node->getSequence());
+ break;
+ case EOpConstructMat4x3:
+ outputConstructor(out, visit, node->getType(), "mat4x3", node->getSequence());
+ break;
+ case EOpConstructMat4:
+ outputConstructor(out, visit, node->getType(), "mat4", node->getSequence());
+ break;
case EOpConstructStruct:
{
if (node->getType().isArray())
@@ -2297,29 +2501,51 @@
}
const TString &structName = StructNameString(*node->getType().getStruct());
mStructureHLSL->addConstructor(node->getType(), structName, node->getSequence());
- outputTriplet(visit, (structName + "_ctor(").c_str(), ", ", ")");
+ outputTriplet(out, visit, (structName + "_ctor(").c_str(), ", ", ")");
}
break;
- case EOpLessThan: outputTriplet(visit, "(", " < ", ")"); break;
- case EOpGreaterThan: outputTriplet(visit, "(", " > ", ")"); break;
- case EOpLessThanEqual: outputTriplet(visit, "(", " <= ", ")"); break;
- case EOpGreaterThanEqual: outputTriplet(visit, "(", " >= ", ")"); break;
- case EOpVectorEqual: outputTriplet(visit, "(", " == ", ")"); break;
- case EOpVectorNotEqual: outputTriplet(visit, "(", " != ", ")"); break;
+ case EOpLessThan:
+ outputTriplet(out, visit, "(", " < ", ")");
+ break;
+ case EOpGreaterThan:
+ outputTriplet(out, visit, "(", " > ", ")");
+ break;
+ case EOpLessThanEqual:
+ outputTriplet(out, visit, "(", " <= ", ")");
+ break;
+ case EOpGreaterThanEqual:
+ outputTriplet(out, visit, "(", " >= ", ")");
+ break;
+ case EOpVectorEqual:
+ outputTriplet(out, visit, "(", " == ", ")");
+ break;
+ case EOpVectorNotEqual:
+ outputTriplet(out, visit, "(", " != ", ")");
+ break;
case EOpMod:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "mod(");
+ writeEmulatedFunctionTriplet(out, visit, "mod(");
break;
- case EOpModf: outputTriplet(visit, "modf(", ", ", ")"); break;
- case EOpPow: outputTriplet(visit, "pow(", ", ", ")"); break;
+ case EOpModf:
+ outputTriplet(out, visit, "modf(", ", ", ")");
+ break;
+ case EOpPow:
+ outputTriplet(out, visit, "pow(", ", ", ")");
+ break;
case EOpAtan:
ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "atan(");
+ writeEmulatedFunctionTriplet(out, visit, "atan(");
break;
- case EOpMin: outputTriplet(visit, "min(", ", ", ")"); break;
- case EOpMax: outputTriplet(visit, "max(", ", ", ")"); break;
- case EOpClamp: outputTriplet(visit, "clamp(", ", ", ")"); break;
+ case EOpMin:
+ outputTriplet(out, visit, "min(", ", ", ")");
+ break;
+ case EOpMax:
+ outputTriplet(out, visit, "max(", ", ", ")");
+ break;
+ case EOpClamp:
+ outputTriplet(out, visit, "clamp(", ", ", ")");
+ break;
case EOpMix:
{
TIntermTyped *lastParamNode = (*(node->getSequence()))[2]->getAsTyped();
@@ -2328,47 +2554,61 @@
// There is no HLSL equivalent for ESSL3 built-in "genType mix (genType x, genType y, genBType a)",
// so use emulated version.
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "mix(");
+ writeEmulatedFunctionTriplet(out, visit, "mix(");
}
else
{
- outputTriplet(visit, "lerp(", ", ", ")");
+ outputTriplet(out, visit, "lerp(", ", ", ")");
}
}
break;
- case EOpStep: outputTriplet(visit, "step(", ", ", ")"); break;
- case EOpSmoothStep: outputTriplet(visit, "smoothstep(", ", ", ")"); break;
- case EOpDistance: outputTriplet(visit, "distance(", ", ", ")"); break;
- case EOpDot: outputTriplet(visit, "dot(", ", ", ")"); break;
- case EOpCross: outputTriplet(visit, "cross(", ", ", ")"); break;
+ case EOpStep:
+ outputTriplet(out, visit, "step(", ", ", ")");
+ break;
+ case EOpSmoothStep:
+ outputTriplet(out, visit, "smoothstep(", ", ", ")");
+ break;
+ case EOpDistance:
+ outputTriplet(out, visit, "distance(", ", ", ")");
+ break;
+ case EOpDot:
+ outputTriplet(out, visit, "dot(", ", ", ")");
+ break;
+ case EOpCross:
+ outputTriplet(out, visit, "cross(", ", ", ")");
+ break;
case EOpFaceForward:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "faceforward(");
+ writeEmulatedFunctionTriplet(out, visit, "faceforward(");
break;
- case EOpReflect: outputTriplet(visit, "reflect(", ", ", ")"); break;
- case EOpRefract: outputTriplet(visit, "refract(", ", ", ")"); break;
+ case EOpReflect:
+ outputTriplet(out, visit, "reflect(", ", ", ")");
+ break;
+ case EOpRefract:
+ outputTriplet(out, visit, "refract(", ", ", ")");
+ break;
case EOpOuterProduct:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(visit, "outerProduct(");
+ writeEmulatedFunctionTriplet(out, visit, "outerProduct(");
break;
- case EOpMul: outputTriplet(visit, "(", " * ", ")"); break;
+ case EOpMul:
+ outputTriplet(out, visit, "(", " * ", ")");
+ break;
default: UNREACHABLE();
}
return true;
}
-void OutputHLSL::writeSelection(TIntermSelection *node)
+void OutputHLSL::writeSelection(TInfoSinkBase &out, TIntermSelection *node)
{
- TInfoSinkBase &out = getInfoSink();
-
out << "if (";
node->getCondition()->traverse(this);
out << ")\n";
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
bool discard = false;
@@ -2389,20 +2629,20 @@
out << "{;}\n";
}
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
if (node->getFalseBlock())
{
out << "else\n";
- outputLineDirective(node->getFalseBlock()->getLine().first_line);
+ outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
// Either this is "else if" or the falseBlock child node will output braces.
ASSERT(IsSequence(node->getFalseBlock()) || node->getFalseBlock()->getAsSelectionNode() != nullptr);
node->getFalseBlock()->traverse(this);
- outputLineDirective(node->getFalseBlock()->getLine().first_line);
+ outputLineDirective(out, node->getFalseBlock()->getLine().first_line);
// Detect false discard
discard = (discard || FindDiscard::search(node->getFalseBlock()));
@@ -2434,37 +2674,40 @@
out << "FLATTEN ";
}
- writeSelection(node);
+ writeSelection(out, node);
return false;
}
bool OutputHLSL::visitSwitch(Visit visit, TIntermSwitch *node)
{
+ TInfoSinkBase &out = getInfoSink();
+
if (node->getStatementList())
{
node->setStatementList(RemoveSwitchFallThrough::removeFallThrough(node->getStatementList()));
- outputTriplet(visit, "switch (", ") ", "");
+ outputTriplet(out, visit, "switch (", ") ", "");
// The curly braces get written when visiting the statementList aggregate
}
else
{
// No statementList, so it won't output curly braces
- outputTriplet(visit, "switch (", ") {", "}\n");
+ outputTriplet(out, visit, "switch (", ") {", "}\n");
}
return true;
}
bool OutputHLSL::visitCase(Visit visit, TIntermCase *node)
{
+ TInfoSinkBase &out = getInfoSink();
+
if (node->hasCondition())
{
- outputTriplet(visit, "case (", "", "):\n");
+ outputTriplet(out, visit, "case (", "", "):\n");
return true;
}
else
{
- TInfoSinkBase &out = getInfoSink();
out << "default:\n";
return false;
}
@@ -2472,7 +2715,8 @@
void OutputHLSL::visitConstantUnion(TIntermConstantUnion *node)
{
- writeConstantUnion(node->getType(), node->getUnionArrayPointer());
+ TInfoSinkBase &out = getInfoSink();
+ writeConstantUnion(out, node->getType(), node->getUnionArrayPointer());
}
bool OutputHLSL::visitLoop(Visit visit, TIntermLoop *node)
@@ -2483,9 +2727,11 @@
mInsideDiscontinuousLoop = mInsideDiscontinuousLoop ||
mCurrentFunctionMetadata->mDiscontinuousLoops.count(node) > 0;
+ TInfoSinkBase &out = getInfoSink();
+
if (mOutputType == SH_HLSL9_OUTPUT)
{
- if (handleExcessiveLoop(node))
+ if (handleExcessiveLoop(out, node))
{
mInsideDiscontinuousLoop = wasDiscontinuous;
mNestedLoopDepth--;
@@ -2494,14 +2740,12 @@
}
}
- TInfoSinkBase &out = getInfoSink();
-
const char *unroll = mCurrentFunctionMetadata->hasGradientInCallGraph(node) ? "LOOP" : "";
if (node->getType() == ELoopDoWhile)
{
out << "{" << unroll << " do\n";
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
}
else
{
@@ -2528,7 +2772,7 @@
out << ")\n";
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
}
if (node->getBody())
@@ -2544,11 +2788,11 @@
out << "{;}\n";
}
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
if (node->getType() == ELoopDoWhile)
{
- outputLineDirective(node->getCondition()->getLine().first_line);
+ outputLineDirective(out, node->getCondition()->getLine().first_line);
out << "while(\n";
node->getCondition()->traverse(this);
@@ -2571,7 +2815,7 @@
switch (node->getFlowOp())
{
case EOpKill:
- outputTriplet(visit, "discard;\n", "", "");
+ outputTriplet(out, visit, "discard;\n", "", "");
break;
case EOpBreak:
if (visit == PreVisit)
@@ -2593,7 +2837,9 @@
}
}
break;
- case EOpContinue: outputTriplet(visit, "continue;\n", "", ""); break;
+ case EOpContinue:
+ outputTriplet(out, visit, "continue;\n", "", "");
+ break;
case EOpReturn:
if (visit == PreVisit)
{
@@ -2655,10 +2901,9 @@
// Handle loops with more than 254 iterations (unsupported by D3D9) by splitting them
// (The D3D documentation says 255 iterations, but the compiler complains at anything more than 254).
-bool OutputHLSL::handleExcessiveLoop(TIntermLoop *node)
+bool OutputHLSL::handleExcessiveLoop(TInfoSinkBase &out, TIntermLoop *node)
{
const int MAX_LOOP_ITERATIONS = 254;
- TInfoSinkBase &out = getInfoSink();
// Parse loops of the form:
// for(int index = initial; index [comparator] limit; index += increment)
@@ -2825,7 +3070,7 @@
out << increment;
out << ")\n";
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
out << "{\n";
if (node->getBody())
@@ -2833,7 +3078,7 @@
node->getBody()->traverse(this);
}
- outputLineDirective(node->getLine().first_line);
+ outputLineDirective(out, node->getLine().first_line);
out << ";}\n";
if (!firstLoopFragment)
@@ -2859,7 +3104,11 @@
return false; // Not handled as an excessive loop
}
-void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString, TInfoSinkBase &out)
+void OutputHLSL::outputTriplet(TInfoSinkBase &out,
+ Visit visit,
+ const char *preString,
+ const char *inString,
+ const char *postString)
{
if (visit == PreVisit)
{
@@ -2875,17 +3124,10 @@
}
}
-void OutputHLSL::outputTriplet(Visit visit, const char *preString, const char *inString, const char *postString)
-{
- outputTriplet(visit, preString, inString, postString, getInfoSink());
-}
-
-void OutputHLSL::outputLineDirective(int line)
+void OutputHLSL::outputLineDirective(TInfoSinkBase &out, int line)
{
if ((mCompileOptions & SH_LINE_DIRECTIVES) && (line > 0))
{
- TInfoSinkBase &out = getInfoSink();
-
out << "\n";
out << "#line " << line;
@@ -2942,13 +3184,16 @@
return "{" + string + "}";
}
-void OutputHLSL::outputConstructor(Visit visit, const TType &type, const char *name, const TIntermSequence *parameters)
+void OutputHLSL::outputConstructor(TInfoSinkBase &out,
+ Visit visit,
+ const TType &type,
+ const char *name,
+ const TIntermSequence *parameters)
{
if (type.isArray())
{
UNIMPLEMENTED();
}
- TInfoSinkBase &out = getInfoSink();
if (visit == PreVisit)
{
@@ -2966,11 +3211,10 @@
}
}
-const TConstantUnion *OutputHLSL::writeConstantUnion(const TType &type,
+const TConstantUnion *OutputHLSL::writeConstantUnion(TInfoSinkBase &out,
+ const TType &type,
const TConstantUnion *const constUnion)
{
- TInfoSinkBase &out = getInfoSink();
-
const TConstantUnion *constUnionIterated = constUnion;
const TStructure* structure = type.getStruct();
@@ -2983,7 +3227,7 @@
for (size_t i = 0; i < fields.size(); i++)
{
const TType *fieldType = fields[i]->type();
- constUnionIterated = writeConstantUnion(*fieldType, constUnionIterated);
+ constUnionIterated = writeConstantUnion(out, *fieldType, constUnionIterated);
if (i != fields.size() - 1)
{
@@ -3012,10 +3256,10 @@
return constUnionIterated;
}
-void OutputHLSL::writeEmulatedFunctionTriplet(Visit visit, const char *preStr)
+void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr)
{
TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr);
- outputTriplet(visit, preString.c_str(), ", ", ")");
+ outputTriplet(out, visit, preString.c_str(), ", ", ")");
}
bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out, TIntermSymbol *symbolNode, TIntermTyped *expression)
@@ -3130,8 +3374,7 @@
}
else if (selection != nullptr)
{
- ASSERT(mInfoSinkStack.top() == &out);
- writeSelection(selection);
+ writeSelection(out, selection);
}
else
{