summaryrefslogtreecommitdiffstats
path: root/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp')
-rw-r--r--src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp308
1 files changed, 210 insertions, 98 deletions
diff --git a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
index 0c7f149ee6..905e634fd1 100644
--- a/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
+++ b/src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp
@@ -4,16 +4,20 @@
// found in the LICENSE file.
//
-#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
+#include "angle_gl.h"
+#include "compiler/translator/Cache.h"
+#include "compiler/translator/IntermTraverse.h"
#include "compiler/translator/SymbolTable.h"
+namespace sh
+{
+
class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser
{
public:
BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator)
- : TIntermTraverser(true, false, false),
- mEmulator(emulator)
+ : TIntermTraverser(true, false, false), mEmulator(emulator)
{
}
@@ -21,7 +25,8 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
{
if (visit == PreVisit)
{
- bool needToEmulate = mEmulator.SetFunctionCalled(node->getOp(), node->getOperand()->getType());
+ bool needToEmulate =
+ mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
if (needToEmulate)
node->setUseEmulatedFunction();
}
@@ -32,48 +37,23 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
{
if (visit == PreVisit)
{
- // Here we handle all the built-in functions instead of the ones we
+ // Here we handle all the built-in functions mapped to ops, not just the ones that are
// currently identified as problematic.
- switch (node->getOp())
+ if (node->isConstructor() || node->isFunctionCall())
{
- case EOpLessThan:
- case EOpGreaterThan:
- case EOpLessThanEqual:
- case EOpGreaterThanEqual:
- case EOpVectorEqual:
- case EOpVectorNotEqual:
- case EOpMod:
- case EOpPow:
- case EOpAtan:
- case EOpMin:
- case EOpMax:
- case EOpClamp:
- case EOpMix:
- case EOpStep:
- case EOpSmoothStep:
- case EOpDistance:
- case EOpDot:
- case EOpCross:
- case EOpFaceForward:
- case EOpReflect:
- case EOpRefract:
- case EOpOuterProduct:
- case EOpMul:
- break;
- default:
- return true;
+ return true;
}
const TIntermSequence &sequence = *(node->getSequence());
- bool needToEmulate = false;
- // Right now we only handle built-in functions with two or three parameters.
+ bool needToEmulate = false;
+ // Right now we only handle built-in functions with two to four parameters.
if (sequence.size() == 2)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
if (!param1 || !param2)
return true;
- needToEmulate = mEmulator.SetFunctionCalled(
- node->getOp(), param1->getType(), param2->getType());
+ needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+ param2->getType());
}
else if (sequence.size() == 3)
{
@@ -82,8 +62,20 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
TIntermTyped *param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
- needToEmulate = mEmulator.SetFunctionCalled(
- node->getOp(), param1->getType(), param2->getType(), param3->getType());
+ needToEmulate = mEmulator.setFunctionCalled(node->getOp(), param1->getType(),
+ param2->getType(), param3->getType());
+ }
+ else if (sequence.size() == 4)
+ {
+ TIntermTyped *param1 = sequence[0]->getAsTyped();
+ TIntermTyped *param2 = sequence[1]->getAsTyped();
+ TIntermTyped *param3 = sequence[2]->getAsTyped();
+ TIntermTyped *param4 = sequence[3]->getAsTyped();
+ if (!param1 || !param2 || !param3 || !param4)
+ return true;
+ needToEmulate =
+ mEmulator.setFunctionCalled(node->getOp(), param1->getType(), param2->getType(),
+ param3->getType(), param4->getType());
}
else
{
@@ -101,130 +93,245 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
};
BuiltInFunctionEmulator::BuiltInFunctionEmulator()
-{}
+{
+}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param,
- const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
- const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param1, param2)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param1, param2);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
}
-void BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, const TType *param1, const TType *param2,
- const TType *param3, const char *emulatedFunctionDefinition)
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+ const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const char *emulatedFunctionDefinition)
{
- mEmulatedFunctions[FunctionId(op, param1, param2, param3)] = std::string(emulatedFunctionDefinition);
+ FunctionId id(op, param1, param2);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ mFunctionDependencies[id] = dependency;
+ return id;
}
-bool BuiltInFunctionEmulator::IsOutputEmpty() const
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3, param4);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ return id;
+}
+
+FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
+ const FunctionId &dependency,
+ TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4,
+ const char *emulatedFunctionDefinition)
+{
+ FunctionId id(op, param1, param2, param3, param4);
+ mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
+ mFunctionDependencies[id] = dependency;
+ return id;
+}
+
+bool BuiltInFunctionEmulator::isOutputEmpty() const
{
return (mFunctions.size() == 0);
}
-void BuiltInFunctionEmulator::OutputEmulatedFunctions(TInfoSinkBase &out) const
+void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
{
- for (size_t i = 0; i < mFunctions.size(); ++i)
+ for (const auto &function : mFunctions)
{
- out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n";
+ const char *body = findEmulatedFunction(function);
+ ASSERT(body);
+ out << body;
+ out << "\n\n";
}
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType &param)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
{
- return SetFunctionCalled(FunctionId(op, &param));
+ return setFunctionCalled(FunctionId(op, &param));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType &param1, const TType &param2)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2)
{
- return SetFunctionCalled(FunctionId(op, &param1, &param2));
+ return setFunctionCalled(FunctionId(op, &param1, &param2));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op,
- const TType &param1, const TType &param2, const TType &param3)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3)
{
- return SetFunctionCalled(FunctionId(op, &param1, &param2, &param3));
+ return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
}
-bool BuiltInFunctionEmulator::SetFunctionCalled(const FunctionId &functionId)
+bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
+ const TType &param1,
+ const TType &param2,
+ const TType &param3,
+ const TType &param4)
{
- if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end())
+ return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
+}
+
+const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
+{
+ for (const auto &queryFunction : mQueryFunctions)
{
- for (size_t i = 0; i < mFunctions.size(); ++i)
+ const char *result = queryFunction(functionId);
+ if (result)
{
- if (mFunctions[i] == functionId)
- return true;
+ return result;
}
- // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
- // remain valid and constant.
- mFunctions.push_back(functionId.getCopy());
- return true;
}
- return false;
+
+ const auto &result = mEmulatedFunctions.find(functionId);
+ if (result != mEmulatedFunctions.end())
+ {
+ return result->second.c_str();
+ }
+
+ return nullptr;
+}
+
+bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
+{
+ if (!findEmulatedFunction(functionId))
+ {
+ return false;
+ }
+
+ for (size_t i = 0; i < mFunctions.size(); ++i)
+ {
+ if (mFunctions[i] == functionId)
+ return true;
+ }
+ // If the function depends on another, mark the dependency as called.
+ auto dependency = mFunctionDependencies.find(functionId);
+ if (dependency != mFunctionDependencies.end())
+ {
+ setFunctionCalled((*dependency).second);
+ }
+ // Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
+ // remain valid and constant.
+ mFunctions.push_back(functionId.getCopy());
+ return true;
}
-void BuiltInFunctionEmulator::MarkBuiltInFunctionsForEmulation(TIntermNode *root)
+void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
{
ASSERT(root);
- if (mEmulatedFunctions.empty())
+ if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
return;
BuiltInFunctionEmulationMarker marker(*this);
root->traverse(&marker);
}
-void BuiltInFunctionEmulator::Cleanup()
+void BuiltInFunctionEmulator::cleanup()
{
mFunctions.clear();
+ mFunctionDependencies.clear();
+}
+
+void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc)
+{
+ mQueryFunctions.push_back(queryFunc);
+}
+
+// static
+void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
+{
+ ASSERT(name[strlen(name) - 1] != '(');
+ out << name << "_emu";
}
-//static
-TString BuiltInFunctionEmulator::GetEmulatedFunctionName(
- const TString &name)
+FunctionId::FunctionId()
+ : mOp(EOpNull),
+ mParam1(TCache::getType(EbtVoid)),
+ mParam2(TCache::getType(EbtVoid)),
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
- ASSERT(name[name.length() - 1] == '(');
- return "webgl_" + name.substr(0, name.length() - 1) + "_emu(";
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param)
+FunctionId::FunctionId(TOperator op, const TType *param)
: mOp(op),
mParam1(param),
- mParam2(new TType(EbtVoid)),
- mParam3(new TType(EbtVoid))
+ mParam2(TCache::getType(EbtVoid)),
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
- mParam3(new TType(EbtVoid))
+ mParam3(TCache::getType(EbtVoid)),
+ mParam4(TCache::getType(EbtVoid))
{
}
-BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
- const TType *param1, const TType *param2, const TType *param3)
- : mOp(op),
- mParam1(param1),
- mParam2(param2),
- mParam3(param3)
+FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
+ : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid))
{
}
-bool BuiltInFunctionEmulator::FunctionId::operator==(const BuiltInFunctionEmulator::FunctionId &other) const
+FunctionId::FunctionId(TOperator op,
+ const TType *param1,
+ const TType *param2,
+ const TType *param3,
+ const TType *param4)
+ : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(param4)
{
- return (mOp == other.mOp &&
- *mParam1 == *other.mParam1 &&
- *mParam2 == *other.mParam2 &&
- *mParam3 == *other.mParam3);
}
-bool BuiltInFunctionEmulator::FunctionId::operator<(const BuiltInFunctionEmulator::FunctionId &other) const
+bool FunctionId::operator==(const FunctionId &other) const
+{
+ return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
+ *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
+}
+
+bool FunctionId::operator<(const FunctionId &other) const
{
if (mOp != other.mOp)
return mOp < other.mOp;
@@ -233,11 +340,16 @@ bool BuiltInFunctionEmulator::FunctionId::operator<(const BuiltInFunctionEmulato
if (*mParam2 != *other.mParam2)
return *mParam2 < *other.mParam2;
if (*mParam3 != *other.mParam3)
- return *mParam3 < *other.mParam3;
- return false; // all fields are equal
+ return *mParam3 < *other.mParam3;
+ if (*mParam4 != *other.mParam4)
+ return *mParam4 < *other.mParam4;
+ return false; // all fields are equal
}
-BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy() const
+FunctionId FunctionId::getCopy() const
{
- return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3));
+ return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
+ new TType(*mParam4));
}
+
+} // namespace sh