diff options
Diffstat (limited to 'src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp')
-rw-r--r-- | src/3rdparty/angle/src/compiler/translator/BuiltInFunctionEmulator.cpp | 308 |
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 ¶m) +bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType ¶m) { - return SetFunctionCalled(FunctionId(op, ¶m)); + return setFunctionCalled(FunctionId(op, ¶m)); } -bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, const TType ¶m1, const TType ¶m2) +bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, + const TType ¶m1, + const TType ¶m2) { - return SetFunctionCalled(FunctionId(op, ¶m1, ¶m2)); + return setFunctionCalled(FunctionId(op, ¶m1, ¶m2)); } -bool BuiltInFunctionEmulator::SetFunctionCalled(TOperator op, - const TType ¶m1, const TType ¶m2, const TType ¶m3) +bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, + const TType ¶m1, + const TType ¶m2, + const TType ¶m3) { - return SetFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3)); + return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3)); } -bool BuiltInFunctionEmulator::SetFunctionCalled(const FunctionId &functionId) +bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, + const TType ¶m1, + const TType ¶m2, + const TType ¶m3, + const TType ¶m4) { - if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end()) + return setFunctionCalled(FunctionId(op, ¶m1, ¶m2, ¶m3, ¶m4)); +} + +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 |