Commit 8c46ab11 by Jamie Madill

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