diff options
Diffstat (limited to 'gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp')
-rw-r--r-- | gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp | 161 |
1 files changed, 161 insertions, 0 deletions
diff --git a/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp new file mode 100644 index 0000000000..34b43365cf --- /dev/null +++ b/gfx/angle/checkout/src/compiler/translator/BuiltInFunctionEmulator.cpp @@ -0,0 +1,161 @@ +// +// Copyright 2002 The ANGLE Project Authors. All rights reserved. +// Use of this source code is governed by a BSD-style license that can be +// found in the LICENSE file. +// + +#include "compiler/translator/BuiltInFunctionEmulator.h" +#include "angle_gl.h" +#include "compiler/translator/Symbol.h" +#include "compiler/translator/tree_util/IntermTraverse.h" + +namespace sh +{ + +class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTraverser +{ + public: + BuiltInFunctionEmulationMarker(BuiltInFunctionEmulator &emulator) + : TIntermTraverser(true, false, false), mEmulator(emulator) + {} + + bool visitUnary(Visit visit, TIntermUnary *node) override + { + if (node->getFunction()) + { + bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction()); + if (needToEmulate) + node->setUseEmulatedFunction(); + } + return true; + } + + bool visitAggregate(Visit visit, TIntermAggregate *node) override + { + // Here we handle all the math built-in functions, not just the ones that are currently + // identified as problematic. + if (!BuiltInGroup::IsMath(node->getOp())) + { + return true; + } + bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction()); + if (needToEmulate) + node->setUseEmulatedFunction(); + return true; + } + + private: + BuiltInFunctionEmulator &mEmulator; +}; + +BuiltInFunctionEmulator::BuiltInFunctionEmulator() {} + +void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition) +{ + mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition); +} + +void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( + const TSymbolUniqueId &dependency, + const TSymbolUniqueId &uniqueId, + const char *emulatedFunctionDefinition) +{ + mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition); + mFunctionDependencies[uniqueId.get()] = dependency.get(); +} + +bool BuiltInFunctionEmulator::isOutputEmpty() const +{ + return (mFunctions.size() == 0); +} + +void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const +{ + for (const auto &function : mFunctions) + { + const char *body = findEmulatedFunction(function); + ASSERT(body); + out << body; + out << "\n\n"; + } +} + +const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const +{ + for (const auto &queryFunction : mQueryFunctions) + { + const char *result = queryFunction(uniqueId); + if (result) + { + return result; + } + } + + const auto &result = mEmulatedFunctions.find(uniqueId); + if (result != mEmulatedFunctions.end()) + { + return result->second.c_str(); + } + + return nullptr; +} + +bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function) +{ + ASSERT(function != nullptr); + return setFunctionCalled(function->uniqueId().get()); +} + +bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId) +{ + if (!findEmulatedFunction(uniqueId)) + { + return false; + } + + for (size_t i = 0; i < mFunctions.size(); ++i) + { + if (mFunctions[i] == uniqueId) + return true; + } + // If the function depends on another, mark the dependency as called. + auto dependency = mFunctionDependencies.find(uniqueId); + if (dependency != mFunctionDependencies.end()) + { + setFunctionCalled((*dependency).second); + } + mFunctions.push_back(uniqueId); + return true; +} + +void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root) +{ + ASSERT(root); + + if (mEmulatedFunctions.empty() && mQueryFunctions.empty()) + return; + + BuiltInFunctionEmulationMarker marker(*this); + root->traverse(&marker); +} + +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"; +} + +} // namespace sh |