Use GetOperatorString when writing GLSL unary built-in calls
GetOperatorString is now used when writing GLSL for built-in calls
that fall under TIntermUnary. Component-wise not TOperator enum is
renamed for consistency.
This also cleans up some unnecessary creation of string objects when
writing built-in functions.
BUG=angleproject:1682
TEST=angle_unittests, angle_end2end_tests, WebGL conformance tests
Change-Id: I89b2ef222bf5af479d4977417f320789b58ace85
Reviewed-on: https://chromium-review.googlesource.com/424552
Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
Reviewed-by: Jamie Madill <jmadill@chromium.org>
diff --git a/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/compiler/translator/BuiltInFunctionEmulator.cpp
index 38e8ea7..57e5ba2 100644
--- a/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -228,10 +228,10 @@
}
// static
-TString BuiltInFunctionEmulator::GetEmulatedFunctionName(const TString &name)
+void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
{
- ASSERT(name[name.length() - 1] == '(');
- return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
+ ASSERT(name[strlen(name) - 1] != '(');
+ out << "webgl_" << name << "_emu";
}
BuiltInFunctionEmulator::FunctionId::FunctionId()
diff --git a/src/compiler/translator/BuiltInFunctionEmulator.h b/src/compiler/translator/BuiltInFunctionEmulator.h
index 137a2c5..620fd89 100644
--- a/src/compiler/translator/BuiltInFunctionEmulator.h
+++ b/src/compiler/translator/BuiltInFunctionEmulator.h
@@ -27,8 +27,8 @@
void Cleanup();
- // "name(" becomes "webgl_name_emu(".
- static TString GetEmulatedFunctionName(const TString &name);
+ // "name" gets written as "webgl_name_emu".
+ static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
bool IsOutputEmpty() const;
diff --git a/src/compiler/translator/EmulatePrecision.cpp b/src/compiler/translator/EmulatePrecision.cpp
index ec95ead..780728b 100644
--- a/src/compiler/translator/EmulatePrecision.cpp
+++ b/src/compiler/translator/EmulatePrecision.cpp
@@ -676,12 +676,12 @@
switch (node->getOp())
{
case EOpNegative:
- case EOpVectorLogicalNot:
case EOpLogicalNot:
case EOpPostIncrement:
case EOpPostDecrement:
case EOpPreIncrement:
case EOpPreDecrement:
+ case EOpLogicalNotComponentWise:
break;
default:
if (canRoundFloat(node->getType()) && visit == PreVisit)
diff --git a/src/compiler/translator/Initialize.cpp b/src/compiler/translator/Initialize.cpp
index aa47fbf..b369223 100644
--- a/src/compiler/translator/Initialize.cpp
+++ b/src/compiler/translator/Initialize.cpp
@@ -272,7 +272,7 @@
bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAny, bool1, "any", bvec);
symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpAll, bool1, "all", bvec);
- symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpVectorLogicalNot, bvec, "not", bvec);
+ symbolTable.insertBuiltIn(COMMON_BUILTINS, EOpLogicalNotComponentWise, bvec, "not", bvec);
const TType *sampler2D = TCache::getType(EbtSampler2D);
const TType *samplerCube = TCache::getType(EbtSamplerCube);
diff --git a/src/compiler/translator/IntermNode.cpp b/src/compiler/translator/IntermNode.cpp
index 9888c5b..61fcb40 100644
--- a/src/compiler/translator/IntermNode.cpp
+++ b/src/compiler/translator/IntermNode.cpp
@@ -2123,7 +2123,7 @@
}
break;
- case EOpVectorLogicalNot:
+ case EOpLogicalNotComponentWise:
ASSERT(getType().getBasicType() == EbtBool);
resultArray[i].setBConst(!operandArray[i].getBConst());
break;
diff --git a/src/compiler/translator/Operator.cpp b/src/compiler/translator/Operator.cpp
index 99127c0..9044340 100644
--- a/src/compiler/translator/Operator.cpp
+++ b/src/compiler/translator/Operator.cpp
@@ -18,8 +18,6 @@
return "+";
case EOpLogicalNot:
return "!";
- case EOpVectorLogicalNot:
- return "not";
case EOpBitwiseNot:
return "~";
@@ -251,6 +249,8 @@
return "any";
case EOpAll:
return "all";
+ case EOpLogicalNotComponentWise:
+ return "not";
case EOpKill:
return "kill";
diff --git a/src/compiler/translator/Operator.h b/src/compiler/translator/Operator.h
index b88773e..0415070 100644
--- a/src/compiler/translator/Operator.h
+++ b/src/compiler/translator/Operator.h
@@ -25,7 +25,6 @@
EOpNegative,
EOpPositive,
EOpLogicalNot,
- EOpVectorLogicalNot,
EOpBitwiseNot,
EOpPostIncrement,
@@ -34,7 +33,8 @@
EOpPreDecrement,
//
- // binary operations
+ // binary operations (ones with special GLSL syntax are used in TIntermBinary nodes, others in
+ // TIntermAggregate nodes)
//
EOpAdd,
@@ -82,7 +82,7 @@
EOpIndexDirectInterfaceBlock,
//
- // Built-in functions potentially mapped to operators
+ // Built-in functions mapped to operators (either unary or with multiple parameters)
//
EOpRadians,
@@ -161,6 +161,7 @@
EOpAny,
EOpAll,
+ EOpLogicalNotComponentWise,
//
// Branch
diff --git a/src/compiler/translator/OutputGLSLBase.cpp b/src/compiler/translator/OutputGLSLBase.cpp
index 790a1bf..e7684ed 100644
--- a/src/compiler/translator/OutputGLSLBase.cpp
+++ b/src/compiler/translator/OutputGLSLBase.cpp
@@ -143,13 +143,24 @@
TOperator op,
bool useEmulatedFunction)
{
- TString opStr(GetOperatorString(op));
- opStr += "(";
- if (useEmulatedFunction)
+ TInfoSinkBase &out = objSink();
+ if (visit == PreVisit)
{
- opStr = BuiltInFunctionEmulator::GetEmulatedFunctionName(opStr);
+ const char *opStr(GetOperatorString(op));
+ if (useEmulatedFunction)
+ {
+ BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+ }
+ else
+ {
+ out << opStr;
+ }
+ out << "(";
}
- writeTriplet(visit, opStr.c_str(), ", ", ")");
+ else
+ {
+ writeTriplet(visit, nullptr, ", ", ")");
+ }
}
void TOutputGLSLBase::writeLayoutQualifier(const TType &type)
@@ -641,9 +652,6 @@
case EOpPositive:
preString = "(+";
break;
- case EOpVectorLogicalNot:
- preString = "not(";
- break;
case EOpLogicalNot:
preString = "(!";
break;
@@ -667,171 +675,62 @@
break;
case EOpRadians:
- preString = "radians(";
- break;
case EOpDegrees:
- preString = "degrees(";
- break;
case EOpSin:
- preString = "sin(";
- break;
case EOpCos:
- preString = "cos(";
- break;
case EOpTan:
- preString = "tan(";
- break;
case EOpAsin:
- preString = "asin(";
- break;
case EOpAcos:
- preString = "acos(";
- break;
case EOpAtan:
- preString = "atan(";
- break;
-
case EOpSinh:
- preString = "sinh(";
- break;
case EOpCosh:
- preString = "cosh(";
- break;
case EOpTanh:
- preString = "tanh(";
- break;
case EOpAsinh:
- preString = "asinh(";
- break;
case EOpAcosh:
- preString = "acosh(";
- break;
case EOpAtanh:
- preString = "atanh(";
- break;
-
case EOpExp:
- preString = "exp(";
- break;
case EOpLog:
- preString = "log(";
- break;
case EOpExp2:
- preString = "exp2(";
- break;
case EOpLog2:
- preString = "log2(";
- break;
case EOpSqrt:
- preString = "sqrt(";
- break;
case EOpInverseSqrt:
- preString = "inversesqrt(";
- break;
-
case EOpAbs:
- preString = "abs(";
- break;
case EOpSign:
- preString = "sign(";
- break;
case EOpFloor:
- preString = "floor(";
- break;
case EOpTrunc:
- preString = "trunc(";
- break;
case EOpRound:
- preString = "round(";
- break;
case EOpRoundEven:
- preString = "roundEven(";
- break;
case EOpCeil:
- preString = "ceil(";
- break;
case EOpFract:
- preString = "fract(";
- break;
case EOpIsNan:
- preString = "isnan(";
- break;
case EOpIsInf:
- preString = "isinf(";
- break;
-
case EOpFloatBitsToInt:
- preString = "floatBitsToInt(";
- break;
case EOpFloatBitsToUint:
- preString = "floatBitsToUint(";
- break;
case EOpIntBitsToFloat:
- preString = "intBitsToFloat(";
- break;
case EOpUintBitsToFloat:
- preString = "uintBitsToFloat(";
- break;
-
case EOpPackSnorm2x16:
- preString = "packSnorm2x16(";
- break;
case EOpPackUnorm2x16:
- preString = "packUnorm2x16(";
- break;
case EOpPackHalf2x16:
- preString = "packHalf2x16(";
- break;
case EOpUnpackSnorm2x16:
- preString = "unpackSnorm2x16(";
- break;
case EOpUnpackUnorm2x16:
- preString = "unpackUnorm2x16(";
- break;
case EOpUnpackHalf2x16:
- preString = "unpackHalf2x16(";
- break;
-
case EOpLength:
- preString = "length(";
- break;
case EOpNormalize:
- preString = "normalize(";
- break;
-
case EOpDFdx:
- preString = "dFdx(";
- break;
case EOpDFdy:
- preString = "dFdy(";
- break;
case EOpFwidth:
- preString = "fwidth(";
- break;
-
case EOpTranspose:
- preString = "transpose(";
- break;
case EOpDeterminant:
- preString = "determinant(";
- break;
case EOpInverse:
- preString = "inverse(";
- break;
-
case EOpAny:
- preString = "any(";
- break;
case EOpAll:
- preString = "all(";
- break;
-
+ case EOpLogicalNotComponentWise:
+ writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
+ return true;
default:
UNREACHABLE();
}
- if (visit == PreVisit && node->getUseEmulatedFunction())
- preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preString);
writeTriplet(visit, preString.c_str(), NULL, postString.c_str());
return true;
@@ -976,7 +875,6 @@
{
bool visitChildren = true;
TInfoSinkBase &out = objSink();
- bool useEmulatedFunction = (visit == PreVisit && node->getUseEmulatedFunction());
switch (node->getOp())
{
case EOpPrototype:
@@ -1074,7 +972,7 @@
case EOpMemoryBarrierImage:
case EOpMemoryBarrierShared:
case EOpGroupMemoryBarrier:
- writeBuiltInFunctionTriplet(visit, node->getOp(), useEmulatedFunction);
+ writeBuiltInFunctionTriplet(visit, node->getOp(), node->getUseEmulatedFunction());
break;
default:
UNREACHABLE();
diff --git a/src/compiler/translator/OutputHLSL.cpp b/src/compiler/translator/OutputHLSL.cpp
index 1e08490..eda90a0 100644
--- a/src/compiler/translator/OutputHLSL.cpp
+++ b/src/compiler/translator/OutputHLSL.cpp
@@ -1199,9 +1199,6 @@
case EOpPositive:
outputTriplet(out, visit, "(+", "", ")");
break;
- case EOpVectorLogicalNot:
- outputTriplet(out, visit, "(!", "", ")");
- break;
case EOpLogicalNot:
outputTriplet(out, visit, "(!", "", ")");
break;
@@ -1254,16 +1251,10 @@
outputTriplet(out, visit, "tanh(", "", ")");
break;
case EOpAsinh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "asinh(");
- break;
case EOpAcosh:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "acosh(");
- break;
case EOpAtanh:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "atanh(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpExp:
outputTriplet(out, visit, "exp(", "", ")");
@@ -1300,7 +1291,7 @@
break;
case EOpRoundEven:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "roundEven(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpCeil:
outputTriplet(out, visit, "ceil(", "", ")");
@@ -1310,7 +1301,7 @@
break;
case EOpIsNan:
if (node->getUseEmulatedFunction())
- writeEmulatedFunctionTriplet(out, visit, "isnan(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
else
outputTriplet(out, visit, "isnan(", "", ")");
mRequiresIEEEStrictCompiling = true;
@@ -1331,28 +1322,13 @@
outputTriplet(out, visit, "asfloat(", "", ")");
break;
case EOpPackSnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packSnorm2x16(");
- break;
case EOpPackUnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packUnorm2x16(");
- break;
case EOpPackHalf2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "packHalf2x16(");
- break;
case EOpUnpackSnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackSnorm2x16(");
- break;
case EOpUnpackUnorm2x16:
- ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackUnorm2x16(");
- break;
case EOpUnpackHalf2x16:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "unpackHalf2x16(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpLength:
outputTriplet(out, visit, "length(", "", ")");
@@ -1398,7 +1374,7 @@
break;
case EOpInverse:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "inverse(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpAny:
@@ -1407,6 +1383,9 @@
case EOpAll:
outputTriplet(out, visit, "all(", "", ")");
break;
+ case EOpLogicalNotComponentWise:
+ outputTriplet(out, visit, "(!", "", ")");
+ break;
default:
UNREACHABLE();
}
@@ -1866,7 +1845,7 @@
break;
case EOpMod:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "mod(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpModf:
outputTriplet(out, visit, "modf(", ", ", ")");
@@ -1877,7 +1856,7 @@
case EOpAtan:
ASSERT(node->getSequence()->size() == 2); // atan(x) is a unary operator
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "atan(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpMin:
outputTriplet(out, visit, "min(", ", ", ")");
@@ -1897,7 +1876,7 @@
// y, genBType a)",
// so use emulated version.
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "mix(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
}
else
{
@@ -1922,7 +1901,7 @@
break;
case EOpFaceForward:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "faceforward(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpReflect:
outputTriplet(out, visit, "reflect(", ", ", ")");
@@ -1932,7 +1911,7 @@
break;
case EOpOuterProduct:
ASSERT(node->getUseEmulatedFunction());
- writeEmulatedFunctionTriplet(out, visit, "outerProduct(");
+ writeEmulatedFunctionTriplet(out, visit, node->getOp());
break;
case EOpMulMatrixComponentWise:
outputTriplet(out, visit, "(", " * ", ")");
@@ -2634,10 +2613,18 @@
return constUnionIterated;
}
-void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr)
+void OutputHLSL::writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op)
{
- TString preString = BuiltInFunctionEmulator::GetEmulatedFunctionName(preStr);
- outputTriplet(out, visit, preString.c_str(), ", ", ")");
+ if (visit == PreVisit)
+ {
+ const char *opStr = GetOperatorString(op);
+ BuiltInFunctionEmulator::WriteEmulatedFunctionName(out, opStr);
+ out << "(";
+ }
+ else
+ {
+ outputTriplet(out, visit, nullptr, ", ", ")");
+ }
}
bool OutputHLSL::writeSameSymbolInitializer(TInfoSinkBase &out,
diff --git a/src/compiler/translator/OutputHLSL.h b/src/compiler/translator/OutputHLSL.h
index cd4c64b..0c7d482 100644
--- a/src/compiler/translator/OutputHLSL.h
+++ b/src/compiler/translator/OutputHLSL.h
@@ -109,7 +109,7 @@
void outputEqual(Visit visit, const TType &type, TOperator op, TInfoSinkBase &out);
- void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, const char *preStr);
+ void writeEmulatedFunctionTriplet(TInfoSinkBase &out, Visit visit, TOperator op);
void makeFlaggedStructMaps(const std::vector<TIntermTyped *> &flaggedStructs);
// Returns true if it found a 'same symbol' initializer (initializer that references the
@@ -122,7 +122,6 @@
TIntermSymbol *symbolNode,
TIntermTyped *expression);
- void writeDeferredGlobalInitializers(TInfoSinkBase &out);
void writeIfElse(TInfoSinkBase &out, TIntermIfElse *node);
// Returns the function name
diff --git a/src/compiler/translator/intermOut.cpp b/src/compiler/translator/intermOut.cpp
index e2b33cd..088448b 100644
--- a/src/compiler/translator/intermOut.cpp
+++ b/src/compiler/translator/intermOut.cpp
@@ -300,9 +300,8 @@
case EOpPositive:
out << "Positive sign";
break;
- case EOpVectorLogicalNot:
case EOpLogicalNot:
- out << "Negate conditional";
+ out << "negation";
break;
case EOpBitwiseNot:
out << "bit-wise not";
@@ -474,6 +473,9 @@
case EOpAll:
out << "all";
break;
+ case EOpLogicalNotComponentWise:
+ out << "component-wise not";
+ break;
default:
out.prefix(SH_ERROR);