Commit 5fec7ab2 by Olli Etuaho Committed by Commit Bot

Identify functions by unique id in BuiltInFunctionEmulator

Now that unique ids of all builtins are compile-time constants, we can use them to look up functions in BuiltInFunctionEmulator. This is simpler than using a custom struct with the name and parameters for identifying functions. This requires that we store a reference to a TFunction in those TIntermUnary nodes that were created based on a function. This decreases shader_translator binary size by about 6 KB on Windows. BUG=angleproject:2267 BUG=chromium:823856 TEST=angle_unittests Change-Id: Idd5a00c772c6f26dd36fdbbfbe161d22ab27c2fe Reviewed-on: https://chromium-review.googlesource.com/995372Reviewed-by: 's avatarJamie Madill <jmadill@chromium.org> Commit-Queue: Olli Etuaho <oetuaho@nvidia.com>
parent f3614370
...@@ -156,6 +156,15 @@ generators = { ...@@ -156,6 +156,15 @@ generators = {
], ],
'script': 'src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py', 'script': 'src/libANGLE/renderer/vulkan/gen_vk_mandatory_format_support_table.py',
}, },
'Emulated HLSL functions': {
'inputs': [
'src/compiler/translator/emulated_builtin_function_data_hlsl.json'
],
'outputs': [
'src/compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp'
],
'script': 'src/compiler/translator/gen_emulated_builtin_function_tables.py'
},
'ESSL static builtins': { 'ESSL static builtins': {
'inputs': [ 'inputs': [
'src/compiler/translator/builtin_function_declarations.txt', 'src/compiler/translator/builtin_function_declarations.txt',
......
...@@ -68,7 +68,6 @@ ...@@ -68,7 +68,6 @@
'compiler/translator/Operator.h', 'compiler/translator/Operator.h',
'compiler/translator/OutputTree.cpp', 'compiler/translator/OutputTree.cpp',
'compiler/translator/OutputTree.h', 'compiler/translator/OutputTree.h',
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp', 'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h', 'compiler/translator/ParseContext.h',
'compiler/translator/ParseContext_autogen.h', 'compiler/translator/ParseContext_autogen.h',
......
...@@ -7,7 +7,7 @@ ...@@ -7,7 +7,7 @@
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
...@@ -23,10 +23,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr ...@@ -23,10 +23,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitUnary(Visit visit, TIntermUnary *node) override bool visitUnary(Visit visit, TIntermUnary *node) override
{ {
if (visit == PreVisit) if (node->getFunction())
{ {
bool needToEmulate = bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
if (needToEmulate) if (needToEmulate)
node->setUseEmulatedFunction(); node->setUseEmulatedFunction();
} }
...@@ -35,56 +34,15 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr ...@@ -35,56 +34,15 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitAggregate(Visit visit, TIntermAggregate *node) override bool visitAggregate(Visit visit, TIntermAggregate *node) override
{ {
if (visit == PreVisit) // Here we handle all the built-in functions mapped to ops, not just the ones that are
// currently identified as problematic.
if (node->isConstructor() || node->isFunctionCall())
{ {
// Here we handle all the built-in functions mapped to ops, not just the ones that are return true;
// currently identified as problematic.
if (node->isConstructor() || node->isFunctionCall())
{
return true;
}
const TIntermSequence &sequence = *(node->getSequence());
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());
}
else if (sequence.size() == 3)
{
TIntermTyped *param1 = sequence[0]->getAsTyped();
TIntermTyped *param2 = sequence[1]->getAsTyped();
TIntermTyped *param3 = sequence[2]->getAsTyped();
if (!param1 || !param2 || !param3)
return true;
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
{
return true;
}
if (needToEmulate)
node->setUseEmulatedFunction();
} }
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
return true; return true;
} }
...@@ -96,74 +54,19 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator() ...@@ -96,74 +54,19 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{ {
} }
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const TType *param, const char *emulatedFunctionDefinition)
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
mFunctionDependencies[id] = dependency;
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition)
{ {
FunctionId id(op, param1, param2, param3); mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
} }
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op, void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const TType *param1, const TSymbolUniqueId &dependency,
const TType *param2, const TSymbolUniqueId &uniqueId,
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) const char *emulatedFunctionDefinition)
{ {
FunctionId id(op, param1, param2, param3, param4); mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition); mFunctionDependencies[uniqueId.get()] = dependency.get();
mFunctionDependencies[id] = dependency;
return id;
} }
bool BuiltInFunctionEmulator::isOutputEmpty() const bool BuiltInFunctionEmulator::isOutputEmpty() const
...@@ -182,47 +85,18 @@ void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const ...@@ -182,47 +85,18 @@ void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
} }
} }
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param) const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
{
return setFunctionCalled(FunctionId(op, &param));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2)
{
return setFunctionCalled(FunctionId(op, &param1, &param2));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3)
{
return setFunctionCalled(FunctionId(op, &param1, &param2, &param3));
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4)
{
return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
}
const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
{ {
for (const auto &queryFunction : mQueryFunctions) for (const auto &queryFunction : mQueryFunctions)
{ {
const char *result = queryFunction(functionId); const char *result = queryFunction(uniqueId);
if (result) if (result)
{ {
return result; return result;
} }
} }
const auto &result = mEmulatedFunctions.find(functionId); const auto &result = mEmulatedFunctions.find(uniqueId);
if (result != mEmulatedFunctions.end()) if (result != mEmulatedFunctions.end())
{ {
return result->second.c_str(); return result->second.c_str();
...@@ -231,27 +105,31 @@ const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &func ...@@ -231,27 +105,31 @@ const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &func
return nullptr; return nullptr;
} }
bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) bool BuiltInFunctionEmulator::setFunctionCalled(const TFunction *function)
{
ASSERT(function != nullptr);
return setFunctionCalled(function->uniqueId().get());
}
bool BuiltInFunctionEmulator::setFunctionCalled(int uniqueId)
{ {
if (!findEmulatedFunction(functionId)) if (!findEmulatedFunction(uniqueId))
{ {
return false; return false;
} }
for (size_t i = 0; i < mFunctions.size(); ++i) for (size_t i = 0; i < mFunctions.size(); ++i)
{ {
if (mFunctions[i] == functionId) if (mFunctions[i] == uniqueId)
return true; return true;
} }
// If the function depends on another, mark the dependency as called. // If the function depends on another, mark the dependency as called.
auto dependency = mFunctionDependencies.find(functionId); auto dependency = mFunctionDependencies.find(uniqueId);
if (dependency != mFunctionDependencies.end()) if (dependency != mFunctionDependencies.end())
{ {
setFunctionCalled((*dependency).second); setFunctionCalled((*dependency).second);
} }
// Copy the functionId if it needs to be stored, to make sure that the TType pointers inside mFunctions.push_back(uniqueId);
// remain valid and constant.
mFunctions.push_back(functionId.getCopy());
return true; return true;
} }
...@@ -284,76 +162,4 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons ...@@ -284,76 +162,4 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons
out << name << "_emu"; out << name << "_emu";
} }
FunctionId::FunctionId()
: mOp(EOpNull),
mParam1(StaticType::GetBasic<EbtVoid>()),
mParam2(StaticType::GetBasic<EbtVoid>()),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param)
: mOp(op),
mParam1(param),
mParam2(StaticType::GetBasic<EbtVoid>()),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(StaticType::GetBasic<EbtVoid>()),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
: mOp(op),
mParam1(param1),
mParam2(param2),
mParam3(param3),
mParam4(StaticType::GetBasic<EbtVoid>())
{
}
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)
{
}
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;
if (*mParam1 != *other.mParam1)
return *mParam1 < *other.mParam1;
if (*mParam2 != *other.mParam2)
return *mParam2 < *other.mParam2;
if (*mParam3 != *other.mParam3)
return *mParam3 < *other.mParam3;
if (*mParam4 != *other.mParam4)
return *mParam4 < *other.mParam4;
return false; // all fields are equal
}
FunctionId FunctionId::getCopy() const
{
return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
new TType(*mParam4));
}
} // namespace sh } // namespace sh
...@@ -8,82 +8,15 @@ ...@@ -8,82 +8,15 @@
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_ #define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh namespace sh
{ {
struct MiniFunctionId class TIntermNode;
{ class TFunction;
constexpr MiniFunctionId(TOperator op = EOpNull, class TSymbolUniqueId;
ParamType paramType1 = ParamType::Void,
ParamType paramType2 = ParamType::Void,
ParamType paramType3 = ParamType::Void,
ParamType paramType4 = ParamType::Void)
: op(op),
paramType1(paramType1),
paramType2(paramType2),
paramType3(paramType3),
paramType4(paramType4)
{
}
TOperator op;
ParamType paramType1;
ParamType paramType2;
ParamType paramType3;
ParamType paramType4;
};
class FunctionId final
{
public:
FunctionId();
FunctionId(TOperator op, const TType *param);
FunctionId(TOperator op, const TType *param1, const TType *param2);
FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
FunctionId(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4);
FunctionId(const FunctionId &) = default; using BuiltinQueryFunc = const char *(int);
FunctionId &operator=(const FunctionId &) = default;
bool operator==(const FunctionId &other) const;
bool operator<(const FunctionId &other) const;
FunctionId getCopy() const;
private:
friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
TOperator mOp;
// The memory that these TType objects use is freed by PoolAllocator. The
// BuiltInFunctionEmulator's lifetime can extend until after the memory pool is freed, but
// that's not an issue since this class never destructs these objects.
const TType *mParam1;
const TType *mParam2;
const TType *mParam3;
const TType *mParam4;
};
inline bool operator==(ParamType paramType, const TType *type)
{
return SameParamType(paramType, type->getBasicType(), type->getNominalSize(),
type->getSecondarySize());
}
inline bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId)
{
return miniId.op == functionId.mOp && miniId.paramType1 == functionId.mParam1 &&
miniId.paramType2 == functionId.mParam2 && miniId.paramType3 == functionId.mParam3 &&
miniId.paramType4 == functionId.mParam4;
}
using BuiltinQueryFunc = const char *(const FunctionId &);
// //
// This class decides which built-in functions need to be replaced with the emulated ones. It can be // This class decides which built-in functions need to be replaced with the emulated ones. It can be
...@@ -108,37 +41,12 @@ class BuiltInFunctionEmulator ...@@ -108,37 +41,12 @@ class BuiltInFunctionEmulator
void outputEmulatedFunctions(TInfoSinkBase &out) const; void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated. // Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op, void addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const TType *param, const char *emulatedFunctionDefinition);
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op, void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
const TType *param1, const TSymbolUniqueId &uniqueId,
const TType *param2, const char *emulatedFunctionDefinition);
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc); void addFunctionMap(BuiltinQueryFunc queryFunc);
...@@ -148,31 +56,20 @@ class BuiltInFunctionEmulator ...@@ -148,31 +56,20 @@ class BuiltInFunctionEmulator
// Records that a function is called by the shader and might need to be emulated. If the // Records that a function is called by the shader and might need to be emulated. If the
// function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function // function is not in mEmulatedFunctions, this becomes a no-op. Returns true if the function
// call needs to be replaced with an emulated one. // call needs to be replaced with an emulated one.
bool setFunctionCalled(TOperator op, const TType &param); bool setFunctionCalled(const TFunction *function);
bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2); bool setFunctionCalled(int uniqueId);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3);
bool setFunctionCalled(TOperator op,
const TType &param1,
const TType &param2,
const TType &param3,
const TType &param4);
bool setFunctionCalled(const FunctionId &functionId);
const char *findEmulatedFunction(const FunctionId &functionId) const; const char *findEmulatedFunction(int uniqueId) const;
// Map from function id to emulated function definition // Map from function unique id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions; std::map<int, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to // Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency. // have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies; std::map<int, int> mFunctionDependencies;
// Called function ids // Called function ids
std::vector<FunctionId> mFunctions; std::vector<int> mFunctions;
// Constexpr function tables. // Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions; std::vector<BuiltinQueryFunc *> mQueryFunctions;
......
...@@ -7,9 +7,8 @@ ...@@ -7,9 +7,8 @@
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h" #include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
...@@ -19,8 +18,7 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e ...@@ -19,8 +18,7 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e
{ {
if (shaderType == GL_VERTEX_SHADER) if (shaderType == GL_VERTEX_SHADER)
{ {
const TType *int1 = StaticType::GetBasic<EbtInt>(); emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
} }
} }
...@@ -31,17 +29,12 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator ...@@ -31,17 +29,12 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130) if (targetGLSLVersion < GLSL_VERSION_130)
return; return;
const TType *float1 = StaticType::GetBasic<EbtFloat>();
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *float3 = StaticType::GetBasic<EbtFloat, 3>();
const TType *float4 = StaticType::GetBasic<EbtFloat, 4>();
// !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false. // !(x > 0.0 || x < 0.0 || x == 0.0) will be optimized and always equal to false.
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float1, BuiltInId::isnan_Float1,
"bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }"); "bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float2, BuiltInId::isnan_Float2,
"bvec2 isnan_emu(vec2 x)\n" "bvec2 isnan_emu(vec2 x)\n"
"{\n" "{\n"
" bvec2 isnan;\n" " bvec2 isnan;\n"
...@@ -52,7 +45,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator ...@@ -52,7 +45,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n" " return isnan;\n"
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float3, BuiltInId::isnan_Float3,
"bvec3 isnan_emu(vec3 x)\n" "bvec3 isnan_emu(vec3 x)\n"
"{\n" "{\n"
" bvec3 isnan;\n" " bvec3 isnan;\n"
...@@ -63,7 +56,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator ...@@ -63,7 +56,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n" " return isnan;\n"
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float4, BuiltInId::isnan_Float4,
"bvec4 isnan_emu(vec4 x)\n" "bvec4 isnan_emu(vec4 x)\n"
"{\n" "{\n"
" bvec4 isnan;\n" " bvec4 isnan;\n"
...@@ -77,27 +70,21 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator ...@@ -77,27 +70,21 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu) void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
{ {
const TType *float1 = StaticType::GetBasic<EbtFloat>(); emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
auto floatFuncId = emu->addEmulatedFunction( "emu_precision float atan_emu(emu_precision float y, emu_precision "
EOpAtan, float1, float1, "float x)\n"
"emu_precision float atan_emu(emu_precision float y, emu_precision " "{\n"
"float x)\n" " if (x > 0.0) return atan(y / x);\n"
"{\n" " else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n"
" if (x > 0.0) return atan(y / x);\n" " else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n"
" else if (x < 0.0 && y >= 0.0) return atan(y / x) + 3.14159265;\n" " else return 1.57079632 * sign(y);\n"
" else if (x < 0.0 && y < 0.0) return atan(y / x) - 3.14159265;\n" "}\n");
" else return 1.57079632 * sign(y);\n" static const std::array<TSymbolUniqueId, 4> ids = {
"}\n"); BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
static const std::array<const TType *, 5> floatVecs = { BuiltInId::atan_Float4_Float4,
nullptr,
nullptr,
StaticType::GetBasic<EbtFloat, 2>(),
StaticType::GetBasic<EbtFloat, 3>(),
StaticType::GetBasic<EbtFloat, 4>(),
}; };
for (int dim = 2; dim <= 4; ++dim) for (int dim = 2; dim <= 4; ++dim)
{ {
const TType *floatVec = floatVecs[dim];
std::stringstream ss; std::stringstream ss;
ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
<< " y, emu_precision vec" << dim << " x)\n" << " y, emu_precision vec" << dim << " x)\n"
...@@ -114,7 +101,7 @@ void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator * ...@@ -114,7 +101,7 @@ void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *
} }
ss << ");\n" ss << ");\n"
"}\n"; "}\n";
emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec, emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
ss.str().c_str()); ss.str().c_str());
} }
} }
...@@ -127,11 +114,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -127,11 +114,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10) // Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
if (targetGLSLVersion < GLSL_VERSION_410) if (targetGLSLVersion < GLSL_VERSION_410)
{ {
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off // clang-format off
emu->addEmulatedFunction(EOpPackUnorm2x16, float2, emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
"uint packUnorm2x16_emu(vec2 v)\n" "uint packUnorm2x16_emu(vec2 v)\n"
"{\n" "{\n"
" int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n" " int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
...@@ -139,7 +123,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -139,7 +123,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n" " return uint((y << 16) | (x & 0xFFFF));\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
"vec2 unpackUnorm2x16_emu(uint u)\n" "vec2 unpackUnorm2x16_emu(uint u)\n"
"{\n" "{\n"
" float x = float(u & 0xFFFFu) / 65535.0;\n" " float x = float(u & 0xFFFFu) / 65535.0;\n"
...@@ -153,11 +137,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -153,11 +137,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30). // by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420) if (targetGLSLVersion >= GLSL_VERSION_330 && targetGLSLVersion < GLSL_VERSION_420)
{ {
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off // clang-format off
emu->addEmulatedFunction(EOpPackSnorm2x16, float2, emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
"uint packSnorm2x16_emu(vec2 v)\n" "uint packSnorm2x16_emu(vec2 v)\n"
"{\n" "{\n"
" #if defined(GL_ARB_shading_language_packing)\n" " #if defined(GL_ARB_shading_language_packing)\n"
...@@ -168,7 +149,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -168,7 +149,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n" " return uint((y << 16) | (x & 0xFFFF));\n"
" #endif\n" " #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" float fromSnorm(uint x)\n" " float fromSnorm(uint x)\n"
" {\n" " {\n"
...@@ -189,7 +170,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -189,7 +170,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
"}\n"); "}\n");
// Functions uint f32tof16(float val) and float f16tof32(uint val) are // Functions uint f32tof16(float val) and float f16tof32(uint val) are
// based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL". // based on the OpenGL redbook Appendix Session "Floating-Point Formats Used in OpenGL".
emu->addEmulatedFunction(EOpPackHalf2x16, float2, emu->addEmulatedFunction(BuiltInId::packHalf2x16_Float2,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" uint f32tof16(float val)\n" " uint f32tof16(float val)\n"
" {\n" " {\n"
...@@ -236,7 +217,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator ...@@ -236,7 +217,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
" #endif\n" " #endif\n"
"}\n"); "}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1, emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n" "#if !defined(GL_ARB_shading_language_packing)\n"
" float f16tof32(uint val)\n" " float f16tof32(uint val)\n"
" {\n" " {\n"
......
...@@ -4,17 +4,17 @@ ...@@ -4,17 +4,17 @@
// found in the LICENSE file. // found in the LICENSE file.
// //
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h" #include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
// Defined in emulated_builtin_functions_hlsl_autogen.cpp. // Defined in emulated_builtin_functions_hlsl_autogen.cpp.
const char *FindHLSLFunction(const FunctionId &functionID); const char *FindHLSLFunction(int uniqueId);
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu, void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion) int targetGLSLVersion)
...@@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator ...@@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130) if (targetGLSLVersion < GLSL_VERSION_130)
return; return;
TType *float1 = new TType(EbtFloat); emu->addEmulatedFunction(BuiltInId::isnan_Float1,
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsnan, float1,
"bool isnan_emu(float x)\n" "bool isnan_emu(float x)\n"
"{\n" "{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n" " return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
...@@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator ...@@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"\n"); "\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float2, BuiltInId::isnan_Float2,
"bool2 isnan_emu(float2 x)\n" "bool2 isnan_emu(float2 x)\n"
"{\n" "{\n"
" bool2 isnan;\n" " bool2 isnan;\n"
...@@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator ...@@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float3, BuiltInId::isnan_Float3,
"bool3 isnan_emu(float3 x)\n" "bool3 isnan_emu(float3 x)\n"
"{\n" "{\n"
" bool3 isnan;\n" " bool3 isnan;\n"
...@@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator ...@@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n"); "}\n");
emu->addEmulatedFunction( emu->addEmulatedFunction(
EOpIsnan, float4, BuiltInId::isnan_Float4,
"bool4 isnan_emu(float4 x)\n" "bool4 isnan_emu(float4 x)\n"
"{\n" "{\n"
" bool4 isnan;\n" " bool4 isnan;\n"
...@@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator ...@@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
{ {
TType *int1 = new TType(EbtInt);
TType *int2 = new TType(EbtInt, 2);
TType *int3 = new TType(EbtInt, 3);
TType *int4 = new TType(EbtInt, 4);
TType *uint1 = new TType(EbtUInt);
TType *uint2 = new TType(EbtUInt, 2);
TType *uint3 = new TType(EbtUInt, 3);
TType *uint4 = new TType(EbtUInt, 4);
emu->addFunctionMap(FindHLSLFunction); emu->addFunctionMap(FindHLSLFunction);
// (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32 // (a + b2^16) * (c + d2^16) = ac + (ad + bc) * 2^16 + bd * 2^32
// Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because: // Also note that below, a * d + ((a * c) >> 16) is guaranteed not to overflow, because:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000 // a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
FunctionId umulExtendedUint1 = emu->addEmulatedFunction( emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
EOpUmulExtended, uint1, uint1, uint1, uint1, "void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n" "{\n"
"{\n" " lsb = x * y;\n"
" lsb = x * y;\n" " uint a = (x & 0xffffu);\n"
" uint a = (x & 0xffffu);\n" " uint b = (x >> 16);\n"
" uint b = (x >> 16);\n" " uint c = (y & 0xffffu);\n"
" uint c = (y & 0xffffu);\n" " uint d = (y >> 16);\n"
" uint d = (y >> 16);\n" " uint ad = a * d + ((a * c) >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n" " uint bc = b * c;\n"
" uint bc = b * c;\n" " uint carry = uint(ad > (0xffffffffu - bc));\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n" " msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n" "}\n");
"}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint2, uint2, uint2, uint2, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt2_UInt2_UInt2_UInt2,
"void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n" "void umulExtended_emu(uint2 x, uint2 y, out uint2 msb, out uint2 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" " umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint3, uint3, uint3, uint3, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt3_UInt3_UInt3_UInt3,
"void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n" "void umulExtended_emu(uint3 x, uint3 y, out uint3 msb, out uint3 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
...@@ -117,7 +104,8 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) ...@@ -117,7 +104,8 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" " umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpUmulExtended, uint4, uint4, uint4, uint4, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::umulExtended_UInt4_UInt4_UInt4_UInt4,
"void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n" "void umulExtended_emu(uint4 x, uint4 y, out uint4 msb, out uint4 lsb)\n"
"{\n" "{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
...@@ -130,8 +118,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) ...@@ -130,8 +118,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
// result needs to be negative. // result needs to be negative.
// TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is // TODO(oetuaho): Note that this code doesn't take one edge case into account, where x or y is
// -2^31. abs(-2^31) is undefined. // -2^31. abs(-2^31) is undefined.
FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1, BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
BuiltInId::imulExtended_Int1_Int1_Int1_Int1,
"void imulExtended_emu(int x, int y, out int msb, out int lsb)\n" "void imulExtended_emu(int x, int y, out int msb, out int lsb)\n"
"{\n" "{\n"
" uint unsignedMsb;\n" " uint unsignedMsb;\n"
...@@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) ...@@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" }\n" " }\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int2, int2, int2, int2, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int2_Int2_Int2_Int2,
"void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n" "void imulExtended_emu(int2 x, int2 y, out int2 msb, out int2 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n" " imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int3, int3, int3, int3, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int3_Int3_Int3_Int3,
"void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n" "void imulExtended_emu(int3 x, int3 y, out int3 msb, out int3 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
...@@ -171,7 +160,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu) ...@@ -171,7 +160,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n" " imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n"); "}\n");
emu->addEmulatedFunctionWithDependency( emu->addEmulatedFunctionWithDependency(
imulExtendedInt1, EOpImulExtended, int4, int4, int4, int4, BuiltInId::imulExtended_Int1_Int1_Int1_Int1, BuiltInId::imulExtended_Int4_Int4_Int4_Int4,
"void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n" "void imulExtended_emu(int4 x, int4 y, out int4 msb, out int4 lsb)\n"
"{\n" "{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n" " imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......
...@@ -588,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root, ...@@ -588,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT) if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
{ {
RemovePow(root); RemovePow(root, &symbolTable);
} }
if (compileOptions & SH_REGENERATE_STRUCT_NAMES) if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
......
...@@ -809,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node) ...@@ -809,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node)
} }
TIntermUnary::TIntermUnary(const TIntermUnary &node) TIntermUnary::TIntermUnary(const TIntermUnary &node)
: TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction) : TIntermOperator(node),
mUseEmulatedFunction(node.mUseEmulatedFunction),
mFunction(node.mFunction)
{ {
TIntermTyped *operandCopy = node.mOperand->deepCopy(); TIntermTyped *operandCopy = node.mOperand->deepCopy();
ASSERT(operandCopy != nullptr); ASSERT(operandCopy != nullptr);
...@@ -1049,8 +1051,8 @@ TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzl ...@@ -1049,8 +1051,8 @@ TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzl
promote(); promote();
} }
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand) TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false) : TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
{ {
promote(); promote();
} }
......
...@@ -505,7 +505,7 @@ class TIntermBinary : public TIntermOperator ...@@ -505,7 +505,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator class TIntermUnary : public TIntermOperator
{ {
public: public:
TIntermUnary(TOperator op, TIntermTyped *operand); TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); } TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
...@@ -518,6 +518,8 @@ class TIntermUnary : public TIntermOperator ...@@ -518,6 +518,8 @@ class TIntermUnary : public TIntermOperator
TIntermTyped *getOperand() { return mOperand; } TIntermTyped *getOperand() { return mOperand; }
TIntermTyped *fold(TDiagnostics *diagnostics) override; TIntermTyped *fold(TDiagnostics *diagnostics) override;
const TFunction *getFunction() const { return mFunction; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; } void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; } bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
...@@ -528,6 +530,8 @@ class TIntermUnary : public TIntermOperator ...@@ -528,6 +530,8 @@ class TIntermUnary : public TIntermOperator
// to work around driver bugs. // to work around driver bugs.
bool mUseEmulatedFunction; bool mUseEmulatedFunction;
const TFunction *const mFunction;
private: private:
void promote(); void promote();
......
//
// Copyright 2017 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.
//
// ParamType:
// Helper type for built-in function emulator tables. Defines types for parameters.
#ifndef COMPILER_TRANSLATOR_PARAMTYPE_H_
#define COMPILER_TRANSLATOR_PARAMTYPE_H_
#include "common/angleutils.h"
#include "compiler/translator/BaseTypes.h"
namespace sh
{
enum class ParamType : uint8_t
{
Void,
Bool1,
Bool2,
Bool3,
Bool4,
Float1,
Float2,
Float3,
Float4,
Int1,
Int2,
Int3,
Int4,
Mat2,
Mat3,
Mat4,
Uint1,
Uint2,
Uint3,
Uint4,
Last,
};
struct ParamTypeInfo
{
ParamType self;
TBasicType basicType;
int primarySize;
int secondarySize;
};
constexpr ParamTypeInfo g_ParamTypeInfo[] = {
{ParamType::Void, EbtVoid, 1, 1}, {ParamType::Bool1, EbtBool, 1, 1},
{ParamType::Bool2, EbtBool, 2, 1}, {ParamType::Bool3, EbtBool, 3, 1},
{ParamType::Bool4, EbtBool, 4, 1}, {ParamType::Float1, EbtFloat, 1, 1},
{ParamType::Float2, EbtFloat, 2, 1}, {ParamType::Float3, EbtFloat, 3, 1},
{ParamType::Float4, EbtFloat, 4, 1}, {ParamType::Int1, EbtInt, 1, 1},
{ParamType::Int2, EbtInt, 2, 1}, {ParamType::Int3, EbtInt, 3, 1},
{ParamType::Int4, EbtInt, 4, 1}, {ParamType::Mat2, EbtFloat, 2, 2},
{ParamType::Mat3, EbtFloat, 3, 3}, {ParamType::Mat4, EbtFloat, 4, 4},
{ParamType::Uint1, EbtUInt, 1, 1}, {ParamType::Uint2, EbtUInt, 2, 1},
{ParamType::Uint3, EbtUInt, 3, 1}, {ParamType::Uint4, EbtUInt, 4, 1},
};
constexpr size_t ParamTypeIndex(ParamType paramType)
{
return static_cast<size_t>(paramType);
}
constexpr size_t NumParamTypes()
{
return ParamTypeIndex(ParamType::Last);
}
static_assert(ArraySize(g_ParamTypeInfo) == NumParamTypes(), "Invalid array size");
constexpr TBasicType GetBasicType(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].basicType;
}
constexpr int GetPrimarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].primarySize;
}
constexpr int GetSecondarySize(ParamType paramType)
{
return g_ParamTypeInfo[ParamTypeIndex(paramType)].secondarySize;
}
constexpr bool SameParamType(ParamType paramType,
TBasicType basicType,
int primarySize,
int secondarySize)
{
return GetBasicType(paramType) == basicType && primarySize == GetPrimarySize(paramType) &&
secondarySize == GetSecondarySize(paramType);
}
} // namespace sh
#endif // COMPILER_TRANSLATOR_PARAMTYPE_H_
...@@ -4859,7 +4859,8 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc) ...@@ -4859,7 +4859,8 @@ TIntermCase *TParseContext::addDefault(const TSourceLoc &loc)
TIntermTyped *TParseContext::createUnaryMath(TOperator op, TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child, TIntermTyped *child,
const TSourceLoc &loc) const TSourceLoc &loc,
const TFunction *func)
{ {
ASSERT(child != nullptr); ASSERT(child != nullptr);
...@@ -4907,7 +4908,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4907,7 +4908,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
} }
markStaticReadIfSymbol(child); markStaticReadIfSymbol(child);
TIntermUnary *node = new TIntermUnary(op, child); TIntermUnary *node = new TIntermUnary(op, child, func);
node->setLine(loc); node->setLine(loc);
return node->fold(mDiagnostics); return node->fold(mDiagnostics);
...@@ -4916,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op, ...@@ -4916,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc) TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{ {
ASSERT(op != EOpNull); ASSERT(op != EOpNull);
TIntermTyped *node = createUnaryMath(op, child, loc); TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr) if (node == nullptr)
{ {
return child; return child;
...@@ -5779,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc ...@@ -5779,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc
} }
else else
{ {
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode); TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
node->setLine(loc); node->setLine(loc);
return node->fold(mDiagnostics); return node->fold(mDiagnostics);
} }
...@@ -5837,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa ...@@ -5837,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
{ {
// Treat it like a built-in unary operator. // Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = fnCall->arguments().front(); TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc); TIntermTyped *callNode =
createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
ASSERT(callNode != nullptr); ASSERT(callNode != nullptr);
return callNode; return callNode;
} }
......
...@@ -549,7 +549,10 @@ class TParseContext : angle::NonCopyable ...@@ -549,7 +549,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left, TIntermTyped *left,
TIntermTyped *right, TIntermTyped *right,
const TSourceLoc &loc); const TSourceLoc &loc);
TIntermTyped *createUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc); TIntermTyped *createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc,
const TFunction *func);
TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc); TIntermTyped *addMethod(TFunctionLookup *fnCall, const TSourceLoc &loc);
TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line); TIntermTyped *addConstructor(TFunctionLookup *fnCall, const TSourceLoc &line);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -22,11 +22,6 @@ TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId(). ...@@ -22,11 +22,6 @@ TSymbolUniqueId::TSymbolUniqueId(const TSymbol &symbol) : mId(symbol.uniqueId().
TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default; TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default;
int TSymbolUniqueId::get() const
{
return mId;
}
bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const
{ {
return mId == other.mId; return mId == other.mId;
......
...@@ -25,7 +25,7 @@ class TSymbolUniqueId ...@@ -25,7 +25,7 @@ class TSymbolUniqueId
TSymbolUniqueId &operator=(const TSymbolUniqueId &); TSymbolUniqueId &operator=(const TSymbolUniqueId &);
bool operator==(const TSymbolUniqueId &) const; bool operator==(const TSymbolUniqueId &) const;
int get() const; constexpr int get() const { return mId; }
private: private:
friend class TSymbolTable; friend class TSymbolTable;
......
cc849405cb2fd922f9a269ab6594cb9b e7cb1a4f677413aec61815b10019f608
\ No newline at end of file \ No newline at end of file
...@@ -2,7 +2,7 @@ ...@@ -2,7 +2,7 @@
// Generated by gen_emulated_builtin_function_tables.py using data from // Generated by gen_emulated_builtin_function_tables.py using data from
// emulated_builtin_function_data_hlsl.json. // emulated_builtin_function_data_hlsl.json.
// //
// Copyright 2017 The ANGLE Project Authors. All rights reserved. // Copyright 2018 The ANGLE Project Authors. All rights reserved.
// Use of this source code is governed by a BSD-style license that can be // Use of this source code is governed by a BSD-style license that can be
// found in the LICENSE file. // found in the LICENSE file.
// //
...@@ -10,6 +10,7 @@ ...@@ -10,6 +10,7 @@
// HLSL code for emulating GLSL builtin functions not present in HLSL. // HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{ {
...@@ -19,51 +20,52 @@ namespace ...@@ -19,51 +20,52 @@ namespace
struct FunctionPair struct FunctionPair
{ {
constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn) constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn)
: id(idIn.get()), body(bodyIn)
{ {
} }
MiniFunctionId id; int id;
const char *body; const char *body;
}; };
constexpr FunctionPair g_hlslFunctions[] = { constexpr FunctionPair g_hlslFunctions[] = {
{{EOpMod, ParamType::Float1, ParamType::Float1}, {BuiltInId::mod_Float1_Float1,
"float mod_emu(float x, float y)\n" "float mod_emu(float x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float2}, {BuiltInId::mod_Float2_Float2,
"float2 mod_emu(float2 x, float2 y)\n" "float2 mod_emu(float2 x, float2 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float1}, {BuiltInId::mod_Float2_Float1,
"float2 mod_emu(float2 x, float y)\n" "float2 mod_emu(float2 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float3}, {BuiltInId::mod_Float3_Float3,
"float3 mod_emu(float3 x, float3 y)\n" "float3 mod_emu(float3 x, float3 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float1}, {BuiltInId::mod_Float3_Float1,
"float3 mod_emu(float3 x, float y)\n" "float3 mod_emu(float3 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float4}, {BuiltInId::mod_Float4_Float4,
"float4 mod_emu(float4 x, float4 y)\n" "float4 mod_emu(float4 x, float4 y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float1}, {BuiltInId::mod_Float4_Float1,
"float4 mod_emu(float4 x, float y)\n" "float4 mod_emu(float4 x, float y)\n"
"{\n" "{\n"
" return x - y * floor(x / y);\n" " return x - y * floor(x / y);\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float1, ParamType::Int1}, {BuiltInId::frexp_Float1_Int1,
"float frexp_emu(float x, out int exp)\n" "float frexp_emu(float x, out int exp)\n"
"{\n" "{\n"
" float fexp;\n" " float fexp;\n"
...@@ -71,7 +73,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -71,7 +73,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int(fexp);\n" " exp = int(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float2, ParamType::Int2}, {BuiltInId::frexp_Float2_Int2,
"float2 frexp_emu(float2 x, out int2 exp)\n" "float2 frexp_emu(float2 x, out int2 exp)\n"
"{\n" "{\n"
" float2 fexp;\n" " float2 fexp;\n"
...@@ -79,7 +81,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -79,7 +81,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int2(fexp);\n" " exp = int2(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float3, ParamType::Int3}, {BuiltInId::frexp_Float3_Int3,
"float3 frexp_emu(float3 x, out int3 exp)\n" "float3 frexp_emu(float3 x, out int3 exp)\n"
"{\n" "{\n"
" float3 fexp;\n" " float3 fexp;\n"
...@@ -87,7 +89,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -87,7 +89,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int3(fexp);\n" " exp = int3(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpFrexp, ParamType::Float4, ParamType::Int4}, {BuiltInId::frexp_Float4_Int4,
"float4 frexp_emu(float4 x, out int4 exp)\n" "float4 frexp_emu(float4 x, out int4 exp)\n"
"{\n" "{\n"
" float4 fexp;\n" " float4 fexp;\n"
...@@ -95,27 +97,27 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -95,27 +97,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int4(fexp);\n" " exp = int4(fexp);\n"
" return mantissa;\n" " return mantissa;\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float1, ParamType::Int1}, {BuiltInId::ldexp_Float1_Int1,
"float ldexp_emu(float x, int exp)\n" "float ldexp_emu(float x, int exp)\n"
"{\n" "{\n"
" return ldexp(x, float(exp));\n" " return ldexp(x, float(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float2, ParamType::Int2}, {BuiltInId::ldexp_Float2_Int2,
"float2 ldexp_emu(float2 x, int2 exp)\n" "float2 ldexp_emu(float2 x, int2 exp)\n"
"{\n" "{\n"
" return ldexp(x, float2(exp));\n" " return ldexp(x, float2(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float3, ParamType::Int3}, {BuiltInId::ldexp_Float3_Int3,
"float3 ldexp_emu(float3 x, int3 exp)\n" "float3 ldexp_emu(float3 x, int3 exp)\n"
"{\n" "{\n"
" return ldexp(x, float3(exp));\n" " return ldexp(x, float3(exp));\n"
"}\n"}, "}\n"},
{{EOpLdexp, ParamType::Float4, ParamType::Int4}, {BuiltInId::ldexp_Float4_Int4,
"float4 ldexp_emu(float4 x, int4 exp)\n" "float4 ldexp_emu(float4 x, int4 exp)\n"
"{\n" "{\n"
" return ldexp(x, float4(exp));\n" " return ldexp(x, float4(exp));\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1}, {BuiltInId::faceforward_Float1_Float1_Float1,
"float faceforward_emu(float N, float I, float Nref)\n" "float faceforward_emu(float N, float I, float Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
...@@ -127,7 +129,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -127,7 +129,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float2, ParamType::Float2, ParamType::Float2}, {BuiltInId::faceforward_Float2_Float2_Float2,
"float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n" "float2 faceforward_emu(float2 N, float2 I, float2 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
...@@ -139,7 +141,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -139,7 +141,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float3, ParamType::Float3, ParamType::Float3}, {BuiltInId::faceforward_Float3_Float3_Float3,
"float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n" "float3 faceforward_emu(float3 N, float3 I, float3 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
...@@ -151,7 +153,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -151,7 +153,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpFaceforward, ParamType::Float4, ParamType::Float4, ParamType::Float4}, {BuiltInId::faceforward_Float4_Float4_Float4,
"float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n" "float4 faceforward_emu(float4 N, float4 I, float4 Nref)\n"
"{\n" "{\n"
" if(dot(Nref, I) >= 0)\n" " if(dot(Nref, I) >= 0)\n"
...@@ -163,20 +165,20 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -163,20 +165,20 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n" " return N;\n"
" }\n" " }\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float1, ParamType::Float1}, {BuiltInId::atan_Float1_Float1,
"float atan_emu(float y, float x)\n" "float atan_emu(float y, float x)\n"
"{\n" "{\n"
" if(x == 0 && y == 0) x = 1;\n" " if(x == 0 && y == 0) x = 1;\n"
" return atan2(y, x);\n" " return atan2(y, x);\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float2, ParamType::Float2}, {BuiltInId::atan_Float2_Float2,
"float2 atan_emu(float2 y, float2 x)\n" "float2 atan_emu(float2 y, float2 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
" if(x[1] == 0 && y[1] == 0) x[1] = 1;\n" " if(x[1] == 0 && y[1] == 0) x[1] = 1;\n"
" return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n" " return float2(atan2(y[0], x[0]), atan2(y[1], x[1]));\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float3, ParamType::Float3}, {BuiltInId::atan_Float3_Float3,
"float3 atan_emu(float3 y, float3 x)\n" "float3 atan_emu(float3 y, float3 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
...@@ -184,7 +186,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -184,7 +186,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" if(x[2] == 0 && y[2] == 0) x[2] = 1;\n" " if(x[2] == 0 && y[2] == 0) x[2] = 1;\n"
" return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n" " return float3(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], x[2]));\n"
"}\n"}, "}\n"},
{{EOpAtan, ParamType::Float4, ParamType::Float4}, {BuiltInId::atan_Float4_Float4,
"float4 atan_emu(float4 y, float4 x)\n" "float4 atan_emu(float4 y, float4 x)\n"
"{\n" "{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n" " if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
...@@ -194,72 +196,72 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -194,72 +196,72 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n" " return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n"
" x[2]), atan2(y[3], x[3]));\n" " x[2]), atan2(y[3], x[3]));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float1}, {BuiltInId::asinh_Float1,
"float asinh_emu(in float x)\n" "float asinh_emu(in float x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float2}, {BuiltInId::asinh_Float2,
"float2 asinh_emu(in float2 x)\n" "float2 asinh_emu(in float2 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float3}, {BuiltInId::asinh_Float3,
"float3 asinh_emu(in float3 x)\n" "float3 asinh_emu(in float3 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAsinh, ParamType::Float4}, {BuiltInId::asinh_Float4,
"float4 asinh_emu(in float4 x)\n" "float4 asinh_emu(in float4 x)\n"
"{\n" "{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n" " return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float1}, {BuiltInId::acosh_Float1,
"float acosh_emu(in float x)\n" "float acosh_emu(in float x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float2}, {BuiltInId::acosh_Float2,
"float2 acosh_emu(in float2 x)\n" "float2 acosh_emu(in float2 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float3}, {BuiltInId::acosh_Float3,
"float3 acosh_emu(in float3 x)\n" "float3 acosh_emu(in float3 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAcosh, ParamType::Float4}, {BuiltInId::acosh_Float4,
"float4 acosh_emu(in float4 x)\n" "float4 acosh_emu(in float4 x)\n"
"{\n" "{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n" " return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float1}, {BuiltInId::atanh_Float1,
"float atanh_emu(in float x)\n" "float atanh_emu(in float x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float2}, {BuiltInId::atanh_Float2,
"float2 atanh_emu(in float2 x)\n" "float2 atanh_emu(in float2 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float3}, {BuiltInId::atanh_Float3,
"float3 atanh_emu(in float3 x)\n" "float3 atanh_emu(in float3 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpAtanh, ParamType::Float4}, {BuiltInId::atanh_Float4,
"float4 atanh_emu(in float4 x)\n" "float4 atanh_emu(in float4 x)\n"
"{\n" "{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n" " return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float1}, {BuiltInId::roundEven_Float1,
"float roundEven_emu(in float x)\n" "float roundEven_emu(in float x)\n"
"{\n" "{\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n" " return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float2}, {BuiltInId::roundEven_Float2,
"float2 roundEven_emu(in float2 x)\n" "float2 roundEven_emu(in float2 x)\n"
"{\n" "{\n"
" float2 v;\n" " float2 v;\n"
...@@ -267,7 +269,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -267,7 +269,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n" " v[1] = (frac(x[1]) == 0.5 && trunc(x[1]) % 2.0 == 0.0) ? trunc(x[1]) : round(x[1]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float3}, {BuiltInId::roundEven_Float3,
"float3 roundEven_emu(in float3 x)\n" "float3 roundEven_emu(in float3 x)\n"
"{\n" "{\n"
" float3 v;\n" " float3 v;\n"
...@@ -276,7 +278,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -276,7 +278,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n" " v[2] = (frac(x[2]) == 0.5 && trunc(x[2]) % 2.0 == 0.0) ? trunc(x[2]) : round(x[2]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpRoundEven, ParamType::Float4}, {BuiltInId::roundEven_Float4,
"float4 roundEven_emu(in float4 x)\n" "float4 roundEven_emu(in float4 x)\n"
"{\n" "{\n"
" float4 v;\n" " float4 v;\n"
...@@ -286,7 +288,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -286,7 +288,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n" " v[3] = (frac(x[3]) == 0.5 && trunc(x[3]) % 2.0 == 0.0) ? trunc(x[3]) : round(x[3]);\n"
" return v;\n" " return v;\n"
"}\n"}, "}\n"},
{{EOpPackSnorm2x16, ParamType::Float2}, {BuiltInId::packSnorm2x16_Float2,
"int webgl_toSnorm16(in float x) {\n" "int webgl_toSnorm16(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n" " return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n" "}\n"
...@@ -296,7 +298,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -296,7 +298,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" int y = webgl_toSnorm16(v.y);\n" " int y = webgl_toSnorm16(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n" " return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n"}, "}\n"},
{{EOpPackUnorm2x16, ParamType::Float2}, {BuiltInId::packUnorm2x16_Float2,
"uint webgl_toUnorm16(in float x) {\n" "uint webgl_toUnorm16(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n" " return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n" "}\n"
...@@ -306,14 +308,14 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -306,14 +308,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint y = webgl_toUnorm16(v.y);\n" " uint y = webgl_toUnorm16(v.y);\n"
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
"}\n"}, "}\n"},
{{EOpPackHalf2x16, ParamType::Float2}, {BuiltInId::packHalf2x16_Float2,
"uint packHalf2x16_emu(in float2 v)\n" "uint packHalf2x16_emu(in float2 v)\n"
"{\n" "{\n"
" uint x = f32tof16(v.x);\n" " uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n" " uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n" " return (y << 16) | x;\n"
"}\n"}, "}\n"},
{{EOpUnpackSnorm2x16, ParamType::Uint1}, {BuiltInId::unpackSnorm2x16_UInt1,
"float webgl_fromSnorm16(in uint x) {\n" "float webgl_fromSnorm16(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n" " int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n" " return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
...@@ -324,7 +326,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -324,7 +326,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u;\n" " uint x = u;\n"
" return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n" " return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
"}\n"}, "}\n"},
{{EOpUnpackUnorm2x16, ParamType::Uint1}, {BuiltInId::unpackUnorm2x16_UInt1,
"float webgl_fromUnorm16(in uint x) {\n" "float webgl_fromUnorm16(in uint x) {\n"
" return float(x) / 65535.0;\n" " return float(x) / 65535.0;\n"
"}\n" "}\n"
...@@ -334,14 +336,14 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -334,14 +336,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u & 0xffffu;\n" " uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n" " return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
"}\n"}, "}\n"},
{{EOpUnpackHalf2x16, ParamType::Uint1}, {BuiltInId::unpackHalf2x16_UInt1,
"float2 unpackHalf2x16_emu(in uint u)\n" "float2 unpackHalf2x16_emu(in uint u)\n"
"{\n" "{\n"
" uint y = (u >> 16);\n" " uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n" " uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n" " return float2(f16tof32(x), f16tof32(y));\n"
"}\n"}, "}\n"},
{{EOpPackSnorm4x8, ParamType::Float4}, {BuiltInId::packSnorm4x8_Float4,
"int webgl_toSnorm8(in float x) {\n" "int webgl_toSnorm8(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 127.0));\n" " return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
"}\n" "}\n"
...@@ -354,7 +356,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -354,7 +356,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n" " return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
" | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n" " | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
"}\n"}, "}\n"},
{{EOpPackUnorm4x8, ParamType::Float4}, {BuiltInId::packUnorm4x8_Float4,
"uint webgl_toUnorm8(in float x) {\n" "uint webgl_toUnorm8(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n" " return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
"}\n" "}\n"
...@@ -366,7 +368,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -366,7 +368,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint w = webgl_toUnorm8(v.w);\n" " uint w = webgl_toUnorm8(v.w);\n"
" return (w << 24) | (z << 16) | (y << 8) | x;\n" " return (w << 24) | (z << 16) | (y << 8) | x;\n"
"}\n"}, "}\n"},
{{EOpUnpackSnorm4x8, ParamType::Uint1}, {BuiltInId::unpackSnorm4x8_UInt1,
"float webgl_fromSnorm8(in uint x) {\n" "float webgl_fromSnorm8(in uint x) {\n"
" int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n" " int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
" return clamp(float(xi) / 127.0, -1.0, 1.0);\n" " return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
...@@ -380,7 +382,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -380,7 +382,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n" " return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n"
" webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n" " webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
"}\n"}, "}\n"},
{{EOpUnpackUnorm4x8, ParamType::Uint1}, {BuiltInId::unpackUnorm4x8_UInt1,
"float webgl_fromUnorm8(in uint x) {\n" "float webgl_fromUnorm8(in uint x) {\n"
" return float(x) / 255.0;\n" " return float(x) / 255.0;\n"
"}\n" "}\n"
...@@ -402,47 +404,47 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -402,47 +404,47 @@ constexpr FunctionPair g_hlslFunctions[] = {
// transpose(r) and transpose(c) are in a sense free, since to get the // transpose(r) and transpose(c) are in a sense free, since to get the
// transpose of r, we simply can build a column matrix out of the original // transpose of r, we simply can build a column matrix out of the original
// vector instead of a row matrix. // vector instead of a row matrix.
{{EOpOuterProduct, ParamType::Float2, ParamType::Float2}, {BuiltInId::outerProduct_Float2_Float2,
"float2x2 outerProduct_emu(in float2 c, in float2 r)\n" "float2x2 outerProduct_emu(in float2 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x2(c));\n" " return mul(float2x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float3}, {BuiltInId::outerProduct_Float3_Float3,
"float3x3 outerProduct_emu(in float3 c, in float3 r)\n" "float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x3(c));\n" " return mul(float3x1(r), float1x3(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float4}, {BuiltInId::outerProduct_Float4_Float4,
"float4x4 outerProduct_emu(in float4 c, in float4 r)\n" "float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x4(c));\n" " return mul(float4x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float2}, {BuiltInId::outerProduct_Float3_Float2,
"float2x3 outerProduct_emu(in float3 c, in float2 r)\n" "float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x3(c));\n" " return mul(float2x1(r), float1x3(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float3}, {BuiltInId::outerProduct_Float2_Float3,
"float3x2 outerProduct_emu(in float2 c, in float3 r)\n" "float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x2(c));\n" " return mul(float3x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float2}, {BuiltInId::outerProduct_Float4_Float2,
"float2x4 outerProduct_emu(in float4 c, in float2 r)\n" "float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
"{\n" "{\n"
" return mul(float2x1(r), float1x4(c));\n" " return mul(float2x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float4}, {BuiltInId::outerProduct_Float2_Float4,
"float4x2 outerProduct_emu(in float2 c, in float4 r)\n" "float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x2(c));\n" " return mul(float4x1(r), float1x2(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float3}, {BuiltInId::outerProduct_Float4_Float3,
"float3x4 outerProduct_emu(in float4 c, in float3 r)\n" "float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
"{\n" "{\n"
" return mul(float3x1(r), float1x4(c));\n" " return mul(float3x1(r), float1x4(c));\n"
"}\n"}, "}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float4}, {BuiltInId::outerProduct_Float3_Float4,
"float4x3 outerProduct_emu(in float3 c, in float4 r)\n" "float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
"{\n" "{\n"
" return mul(float4x1(r), float1x3(c));\n" " return mul(float4x1(r), float1x3(c));\n"
...@@ -458,14 +460,14 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -458,14 +460,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
// which happens to be the cofactor matrix. That's stored in 'cof'. // which happens to be the cofactor matrix. That's stored in 'cof'.
// We don't need to care about divide-by-zero since results are undefined // We don't need to care about divide-by-zero since results are undefined
// for singular or poorly-conditioned matrices. // for singular or poorly-conditioned matrices.
{{EOpInverse, ParamType::Mat2}, {BuiltInId::inverse_Float2x2,
"float2x2 inverse_emu(in float2x2 m)\n" "float2x2 inverse_emu(in float2x2 m)\n"
"{\n" "{\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n" " float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n" " return cof / determinant(transpose(m));\n"
"}\n"}, "}\n"},
// cofAB is the cofactor for column A and row B. // cofAB is the cofactor for column A and row B.
{{EOpInverse, ParamType::Mat3}, {BuiltInId::inverse_Float3x3,
"float3x3 inverse_emu(in float3x3 m)\n" "float3x3 inverse_emu(in float3x3 m)\n"
"{\n" "{\n"
" float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n" " float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
...@@ -480,7 +482,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -480,7 +482,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n" " float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
" return cof / determinant(transpose(m));\n" " return cof / determinant(transpose(m));\n"
"}\n"}, "}\n"},
{{EOpInverse, ParamType::Mat4}, {BuiltInId::inverse_Float4x4,
"float4x4 inverse_emu(in float4x4 m)\n" "float4x4 inverse_emu(in float4x4 m)\n"
"{\n" "{\n"
" float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n" " float cof00 = m[1][1] * m[2][2] * m[3][3] + m[2][1] * m[3][2] * m[1][3] + m[3][1] * \n"
...@@ -556,27 +558,27 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -556,27 +558,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
// comes from. For a component of 'a' that is false, the corresponding component of 'x' is // comes from. For a component of 'a' that is false, the corresponding component of 'x' is
// returned. For a component of 'a' that is true, the corresponding component of 'y' is // returned. For a component of 'a' that is true, the corresponding component of 'y' is
// returned. // returned.
{{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1}, {BuiltInId::mix_Float1_Float1_Bool1,
"float mix_emu(float x, float y, bool a)\n" "float mix_emu(float x, float y, bool a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2}, {BuiltInId::mix_Float2_Float2_Bool2,
"float2 mix_emu(float2 x, float2 y, bool2 a)\n" "float2 mix_emu(float2 x, float2 y, bool2 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3}, {BuiltInId::mix_Float3_Float3_Bool3,
"float3 mix_emu(float3 x, float3 y, bool3 a)\n" "float3 mix_emu(float3 x, float3 y, bool3 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4}, {BuiltInId::mix_Float4_Float4_Bool4,
"float4 mix_emu(float4 x, float4 y, bool4 a)\n" "float4 mix_emu(float4 x, float4 y, bool4 a)\n"
"{\n" "{\n"
" return a ? y : x;\n" " return a ? y : x;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt1_Int1_Int1,
"uint bitfieldExtract_emu(uint value, int offset, int bits)\n" "uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -587,7 +589,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -587,7 +589,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt2_Int1_Int1,
"uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n" "uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -598,7 +600,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -598,7 +600,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt3_Int1_Int1,
"uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n" "uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -609,7 +611,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -609,7 +611,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_UInt4_Int1_Int1,
"uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n" "uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -620,7 +622,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -620,7 +622,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n" " uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n" " return (value & mask) >> offset;\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int1_Int1_Int1,
"int bitfieldExtract_emu(int value, int offset, int bits)\n" "int bitfieldExtract_emu(int value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -637,7 +639,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -637,7 +639,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int2_Int1_Int1,
"int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n" "int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -654,7 +656,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -654,7 +656,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int3_Int1_Int1,
"int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n" "int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -671,7 +673,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -671,7 +673,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldExtract_Int4_Int1_Int1,
"int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n" "int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -688,7 +690,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -688,7 +690,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n" " }\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint1, ParamType::Uint1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt1_UInt1_Int1_Int1,
"uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n" "uint bitfieldInsert_emu(uint base, uint insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -700,7 +702,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -700,7 +702,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint2, ParamType::Uint2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt2_UInt2_Int1_Int1,
"uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n" "uint2 bitfieldInsert_emu(uint2 base, uint2 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -712,7 +714,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -712,7 +714,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint3, ParamType::Uint3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt3_UInt3_Int1_Int1,
"uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n" "uint3 bitfieldInsert_emu(uint3 base, uint3 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -724,7 +726,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -724,7 +726,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Uint4, ParamType::Uint4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_UInt4_UInt4_Int1_Int1,
"uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n" "uint4 bitfieldInsert_emu(uint4 base, uint4 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -736,7 +738,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -736,7 +738,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n" " uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\n" " return (base & baseMask) | ((insert << offset) & insertMask);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int1, ParamType::Int1, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int1_Int1_Int1_Int1,
"int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n" "int bitfieldInsert_emu(int base, int insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -750,7 +752,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -750,7 +752,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int2, ParamType::Int2, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int2_Int2_Int1_Int1,
"int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n" "int2 bitfieldInsert_emu(int2 base, int2 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -764,7 +766,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -764,7 +766,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int3, ParamType::Int3, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int3_Int3_Int1_Int1,
"int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n" "int3 bitfieldInsert_emu(int3 base, int3 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -778,7 +780,7 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -778,7 +780,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpBitfieldInsert, ParamType::Int4, ParamType::Int4, ParamType::Int1, ParamType::Int1}, {BuiltInId::bitfieldInsert_Int4_Int4_Int1_Int1,
"int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n" "int4 bitfieldInsert_emu(int4 base, int4 insert, int offset, int bits)\n"
"{\n" "{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n" " if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
...@@ -792,71 +794,71 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -792,71 +794,71 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n" " insertMask);\n"
" return asint(resultUnsigned);\n" " return asint(resultUnsigned);\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, {BuiltInId::uaddCarry_UInt1_UInt1_UInt1,
"uint uaddCarry_emu(uint x, uint y, out uint carry)\n" "uint uaddCarry_emu(uint x, uint y, out uint carry)\n"
"{\n" "{\n"
" carry = uint(x > (0xffffffffu - y));\n" " carry = uint(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, {BuiltInId::uaddCarry_UInt2_UInt2_UInt2,
"uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n" "uint2 uaddCarry_emu(uint2 x, uint2 y, out uint2 carry)\n"
"{\n" "{\n"
" carry = uint2(x > (0xffffffffu - y));\n" " carry = uint2(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, {BuiltInId::uaddCarry_UInt3_UInt3_UInt3,
"uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n" "uint3 uaddCarry_emu(uint3 x, uint3 y, out uint3 carry)\n"
"{\n" "{\n"
" carry = uint3(x > (0xffffffffu - y));\n" " carry = uint3(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUaddCarry, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, {BuiltInId::uaddCarry_UInt4_UInt4_UInt4,
"uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n" "uint4 uaddCarry_emu(uint4 x, uint4 y, out uint4 carry)\n"
"{\n" "{\n"
" carry = uint4(x > (0xffffffffu - y));\n" " carry = uint4(x > (0xffffffffu - y));\n"
" return x + y;\n" " return x + y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint1, ParamType::Uint1, ParamType::Uint1}, {BuiltInId::usubBorrow_UInt1_UInt1_UInt1,
"uint usubBorrow_emu(uint x, uint y, out uint borrow)\n" "uint usubBorrow_emu(uint x, uint y, out uint borrow)\n"
"{\n" "{\n"
" borrow = uint(x < y);\n" " borrow = uint(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint2, ParamType::Uint2, ParamType::Uint2}, {BuiltInId::usubBorrow_UInt2_UInt2_UInt2,
"uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n" "uint2 usubBorrow_emu(uint2 x, uint2 y, out uint2 borrow)\n"
"{\n" "{\n"
" borrow = uint2(x < y);\n" " borrow = uint2(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint3, ParamType::Uint3, ParamType::Uint3}, {BuiltInId::usubBorrow_UInt3_UInt3_UInt3,
"uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n" "uint3 usubBorrow_emu(uint3 x, uint3 y, out uint3 borrow)\n"
"{\n" "{\n"
" borrow = uint3(x < y);\n" " borrow = uint3(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
{{EOpUsubBorrow, ParamType::Uint4, ParamType::Uint4, ParamType::Uint4}, {BuiltInId::usubBorrow_UInt4_UInt4_UInt4,
"uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n" "uint4 usubBorrow_emu(uint4 x, uint4 y, out uint4 borrow)\n"
"{\n" "{\n"
" borrow = uint4(x < y);\n" " borrow = uint4(x < y);\n"
" return x - y;\n" " return x - y;\n"
"}\n"}, "}\n"},
// We emulate tanh just to avoid overflow on large arguments. // We emulate tanh just to avoid overflow on large arguments.
{{EOpTanh, ParamType::Float1}, {BuiltInId::tanh_Float1,
"float tanh_emu(float x)\n" "float tanh_emu(float x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float2}, {BuiltInId::tanh_Float2,
"float2 tanh_emu(float2 x)\n" "float2 tanh_emu(float2 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float3}, {BuiltInId::tanh_Float3,
"float3 tanh_emu(float3 x)\n" "float3 tanh_emu(float3 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"}, "}\n"},
{{EOpTanh, ParamType::Float4}, {BuiltInId::tanh_Float4,
"float4 tanh_emu(float4 x)\n" "float4 tanh_emu(float4 x)\n"
"{\n" "{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n" " return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
...@@ -864,12 +866,12 @@ constexpr FunctionPair g_hlslFunctions[] = { ...@@ -864,12 +866,12 @@ constexpr FunctionPair g_hlslFunctions[] = {
}; };
} // anonymous namespace } // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID) const char *FindHLSLFunction(int uniqueId)
{ {
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{ {
const auto &function = g_hlslFunctions[index]; const auto &function = g_hlslFunctions[index];
if (function.id == functionID) if (function.id == uniqueId)
{ {
return function.body; return function.body;
} }
......
...@@ -68,7 +68,7 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch) ...@@ -68,7 +68,7 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch)
""" """
# The header file has a "get" function for each variable. They are used in traversers. # The header file has a "get" function for each variable. They are used in traversers.
# Note that we don't currently include get_function_declarations, as they are unused. # It also declares id values of built-ins with human readable names, so they can be used to identify built-ins.
template_builtin_header = """// GENERATED FILE - DO NOT EDIT. template_builtin_header = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {variable_data_source_name} and // Generated by {script_name} using data from {variable_data_source_name} and
// {function_data_source_name}. // {function_data_source_name}.
...@@ -83,11 +83,21 @@ template_builtin_header = """// GENERATED FILE - DO NOT EDIT. ...@@ -83,11 +83,21 @@ template_builtin_header = """// GENERATED FILE - DO NOT EDIT.
#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ #ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_ #define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#include "compiler/translator/SymbolUniqueId.h"
namespace sh namespace sh
{{ {{
class TVariable; class TVariable;
class BuiltInId
{{
public:
{builtin_id_declarations}
}}; // class BuiltInId
namespace BuiltInVariable namespace BuiltInVariable
{{ {{
...@@ -144,23 +154,15 @@ template_symboltable_cpp = """// GENERATED FILE - DO NOT EDIT. ...@@ -144,23 +154,15 @@ template_symboltable_cpp = """// GENERATED FILE - DO NOT EDIT.
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
#include "angle_gl.h" #include "angle_gl.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/ImmutableString.h" #include "compiler/translator/ImmutableString.h"
#include "compiler/translator/StaticType.h" #include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h" #include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/SymbolTable.h" #include "compiler/translator/SymbolTable.h"
namespace sh namespace sh
{{ {{
class BuiltInId
{{
public:
{builtin_id_declarations}
}}; // namespace BuiltInId
// Since some of the BuiltInId declarations are used outside of constexpr expressions, we need to // Since some of the BuiltInId declarations are used outside of constexpr expressions, we need to
// have these definitions without an initializer. C++17 should eventually remove the need for this. // have these definitions without an initializer. C++17 should eventually remove the need for this.
{builtin_id_definitions} {builtin_id_definitions}
...@@ -455,6 +457,13 @@ class TType: ...@@ -455,6 +457,13 @@ class TType:
mangled_name += get_basic_mangled_name(self.data['basic']) mangled_name += get_basic_mangled_name(self.data['basic'])
return mangled_name return mangled_name
def get_human_readable_name(self):
name = self.data['basic']
name += str(self.data['primarySize'])
if self.data['secondarySize'] > 1:
name += 'x' + str(self.data['secondarySize'])
return name
def is_vector(self): def is_vector(self):
return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1 return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1
...@@ -758,6 +767,12 @@ def get_function_mangled_name(function_name, parameters): ...@@ -758,6 +767,12 @@ def get_function_mangled_name(function_name, parameters):
mangled_name += param.get_mangled_name() mangled_name += param.get_mangled_name()
return mangled_name return mangled_name
def get_function_human_readable_name(function_name, parameters):
name = function_name
for param in parameters:
name += '_' + param.get_human_readable_name()
return name
ttype_mangled_name_variants = [] ttype_mangled_name_variants = []
for basic_type in basic_types_enumeration: for basic_type in basic_types_enumeration:
primary_sizes = [1] primary_sizes = [1]
...@@ -966,10 +981,13 @@ def process_single_function_group(condition, group_name, group): ...@@ -966,10 +981,13 @@ def process_single_function_group(condition, group_name, group):
template_args['param_count'] = len(parameters) template_args['param_count'] = len(parameters)
template_args['return_type'] = function_props['returnType'].get_statictype_string() template_args['return_type'] = function_props['returnType'].get_statictype_string()
template_args['mangled_name'] = get_function_mangled_name(function_name, parameters) template_args['mangled_name'] = get_function_mangled_name(function_name, parameters)
template_args['human_readable_name'] = get_function_human_readable_name(template_args['name_with_suffix'], parameters)
template_args['mangled_name_length'] = len(template_args['mangled_name']) template_args['mangled_name_length'] = len(template_args['mangled_name'])
template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {unique_name} = TSymbolUniqueId({id});' template_builtin_id_declaration = ' static constexpr const TSymbolUniqueId {human_readable_name} = TSymbolUniqueId({id});'
builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args)) builtin_id_declarations.append(template_builtin_id_declaration.format(**template_args))
template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{human_readable_name};'
builtin_id_definitions.append(template_builtin_id_definition.format(**template_args))
parameters_list = [] parameters_list = []
for param in parameters: for param in parameters:
...@@ -998,7 +1016,7 @@ def process_single_function_group(condition, group_name, group): ...@@ -998,7 +1016,7 @@ def process_single_function_group(condition, group_name, group):
template_parameter_list_declaration = 'constexpr const TVariable **{parameters_var_name} = nullptr;' template_parameter_list_declaration = 'constexpr const TVariable **{parameters_var_name} = nullptr;'
parameter_declarations[template_args['parameters_var_name']] = template_parameter_list_declaration.format(**template_args) parameter_declarations[template_args['parameters_var_name']] = template_parameter_list_declaration.format(**template_args)
template_function_declaration = 'constexpr const TFunction kFunction_{unique_name}(BuiltInId::{unique_name}, BuiltInName::{name_with_suffix}, TExtension::{extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, EOp{op}, {known_to_not_have_side_effects});' template_function_declaration = 'constexpr const TFunction kFunction_{unique_name}(BuiltInId::{human_readable_name}, BuiltInName::{name_with_suffix}, TExtension::{extension}, BuiltInParameters::{parameters_var_name}, {param_count}, {return_type}, EOp{op}, {known_to_not_have_side_effects});'
function_declarations.append(template_function_declaration.format(**template_args)) function_declarations.append(template_function_declaration.format(**template_args))
# If we can make sure that there's no other mangled name with the same length, function # If we can make sure that there's no other mangled name with the same length, function
......
...@@ -21,6 +21,7 @@ template_emulated_builtin_functions_hlsl = """// GENERATED FILE - DO NOT EDIT. ...@@ -21,6 +21,7 @@ template_emulated_builtin_functions_hlsl = """// GENERATED FILE - DO NOT EDIT.
// HLSL code for emulating GLSL builtin functions not present in HLSL. // HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h" #include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh namespace sh
{{ {{
...@@ -30,11 +31,11 @@ namespace ...@@ -30,11 +31,11 @@ namespace
struct FunctionPair struct FunctionPair
{{ {{
constexpr FunctionPair(const MiniFunctionId &idIn, const char *bodyIn) : id(idIn), body(bodyIn) constexpr FunctionPair(const TSymbolUniqueId &idIn, const char *bodyIn) : id(idIn.get()), body(bodyIn)
{{ {{
}} }}
MiniFunctionId id; int id;
const char *body; const char *body;
}}; }};
...@@ -42,12 +43,12 @@ constexpr FunctionPair g_hlslFunctions[] = {{ ...@@ -42,12 +43,12 @@ constexpr FunctionPair g_hlslFunctions[] = {{
{emulated_functions}}}; {emulated_functions}}};
}} // anonymous namespace }} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID) const char *FindHLSLFunction(int uniqueId)
{{ {{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index) for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{{ {{
const auto &function = g_hlslFunctions[index]; const auto &function = g_hlslFunctions[index];
if (function.id == functionID) if (function.id == uniqueId)
{{ {{
return function.body; return function.body;
}} }}
...@@ -74,26 +75,18 @@ def load_json(path): ...@@ -74,26 +75,18 @@ def load_json(path):
return json.loads(file_data, object_pairs_hook=reject_duplicate_keys) return json.loads(file_data, object_pairs_hook=reject_duplicate_keys)
def enum_type(arg): def enum_type(arg):
# handle 'argtype argname' and 'out argtype argname' # handle 'argtype argname' and 'out argtype argname'
chunks = arg.split(' ') chunks = arg.split(' ')
arg_type = chunks[0] arg_type = chunks[0]
if len(chunks) == 3: if len(chunks) == 3:
arg_type = chunks[1] arg_type = chunks[1]
if arg_type == "float2x2": suffix = ""
return "Mat2" if not arg_type[-1].isdigit():
elif arg_type == "float3x3": suffix = '1'
return "Mat3" if arg_type[0:4] == 'uint':
elif arg_type == "float4x4": return 'UI' + arg_type[2:] + suffix
return "Mat4" return arg_type.capitalize() + suffix
suffix = ""
if not arg_type[-1].isdigit():
suffix = '1'
return arg_type.capitalize() + suffix
def caps(op):
return op[0].upper() + op[1:]
input_script = "emulated_builtin_function_data_hlsl.json" input_script = "emulated_builtin_function_data_hlsl.json"
hlsl_json = load_json(input_script) hlsl_json = load_json(input_script)
...@@ -109,7 +102,7 @@ def gen_emulated_function(data): ...@@ -109,7 +102,7 @@ def gen_emulated_function(data):
body = [ sig, '{' ] + [' ' + line for line in data['body']] + ['}'] body = [ sig, '{' ] + [' ' + line for line in data['body']] + ['}']
func += "{\n" func += "{\n"
func += "{ EOp" + caps(data['op']) + ", " + ", ".join("ParamType::" + enum_type(arg) for arg in data['args']) + " },\n" func += "BuiltInId::" + data['op'] + "_" + "_".join([enum_type(arg) for arg in data['args']]) + ",\n"
if 'helper' in data: if 'helper' in data:
func += '"' + '\\n"\n"'.join(data['helper']) + '\\n"\n' func += '"' + '\\n"\n"'.join(data['helper']) + '\\n"\n'
func += '"' + '\\n"\n"'.join(body) + '\\n"\n' func += '"' + '\\n"\n"'.join(body) + '\\n"\n'
......
...@@ -114,7 +114,8 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode, ...@@ -114,7 +114,8 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize()); TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
TIntermBinary *indexSmallerThanSize = TIntermBinary *indexSmallerThanSize =
new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode); new TIntermBinary(EOpLessThan, indexSymbolNode->deepCopy(), arraySizeNode);
TIntermUnary *indexIncrement = new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy()); TIntermUnary *indexIncrement =
new TIntermUnary(EOpPreIncrement, indexSymbolNode->deepCopy(), nullptr);
TIntermBlock *forLoopBody = new TIntermBlock(); TIntermBlock *forLoopBody = new TIntermBlock();
TIntermSequence *forLoopBodySeq = forLoopBody->getSequence(); TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
......
...@@ -11,6 +11,7 @@ ...@@ -11,6 +11,7 @@
#include "compiler/translator/tree_ops/RemovePow.h" #include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h" #include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh namespace sh
...@@ -34,7 +35,7 @@ bool IsProblematicPow(TIntermTyped *node) ...@@ -34,7 +35,7 @@ bool IsProblematicPow(TIntermTyped *node)
class RemovePowTraverser : public TIntermTraverser class RemovePowTraverser : public TIntermTraverser
{ {
public: public:
RemovePowTraverser(); RemovePowTraverser(TSymbolTable *symbolTable);
bool visitAggregate(Visit visit, TIntermAggregate *node) override; bool visitAggregate(Visit visit, TIntermAggregate *node) override;
...@@ -45,8 +46,8 @@ class RemovePowTraverser : public TIntermTraverser ...@@ -45,8 +46,8 @@ class RemovePowTraverser : public TIntermTraverser
bool mNeedAnotherIteration; bool mNeedAnotherIteration;
}; };
RemovePowTraverser::RemovePowTraverser() RemovePowTraverser::RemovePowTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false), mNeedAnotherIteration(false) : TIntermTraverser(true, false, false, symbolTable), mNeedAnotherIteration(false)
{ {
} }
...@@ -57,14 +58,18 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -57,14 +58,18 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *x = node->getSequence()->at(0)->getAsTyped(); TIntermTyped *x = node->getSequence()->at(0)->getAsTyped();
TIntermTyped *y = node->getSequence()->at(1)->getAsTyped(); TIntermTyped *y = node->getSequence()->at(1)->getAsTyped();
TIntermUnary *log = new TIntermUnary(EOpLog2, x); TIntermSequence *logArgs = new TIntermSequence();
logArgs->push_back(x);
TIntermTyped *log = CreateBuiltInFunctionCallNode("log2", logArgs, *mSymbolTable, 100);
log->setLine(node->getLine()); log->setLine(node->getLine());
TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType()); TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
TIntermBinary *mul = new TIntermBinary(op, y, log); TIntermBinary *mul = new TIntermBinary(op, y, log);
mul->setLine(node->getLine()); mul->setLine(node->getLine());
TIntermUnary *exp = new TIntermUnary(EOpExp2, mul); TIntermSequence *expArgs = new TIntermSequence();
expArgs->push_back(mul);
TIntermTyped *exp = CreateBuiltInFunctionCallNode("exp2", expArgs, *mSymbolTable, 100);
exp->setLine(node->getLine()); exp->setLine(node->getLine());
queueReplacement(exp, OriginalNode::IS_DROPPED); queueReplacement(exp, OriginalNode::IS_DROPPED);
...@@ -82,9 +87,9 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node) ...@@ -82,9 +87,9 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
} // namespace } // namespace
void RemovePow(TIntermNode *root) void RemovePow(TIntermNode *root, TSymbolTable *symbolTable)
{ {
RemovePowTraverser traverser; RemovePowTraverser traverser(symbolTable);
// Iterate as necessary, and reset the traverser between iterations. // Iterate as necessary, and reset the traverser between iterations.
do do
{ {
......
...@@ -14,8 +14,9 @@ ...@@ -14,8 +14,9 @@
namespace sh namespace sh
{ {
class TIntermNode; class TIntermNode;
class TSymbolTable;
void RemovePow(TIntermNode *root); void RemovePow(TIntermNode *root, TSymbolTable *symbolTable);
} // namespace sh } // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEPOW_H_ #endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEPOW_H_
...@@ -96,7 +96,7 @@ class DoWhileRewriter : public TIntermTraverser ...@@ -96,7 +96,7 @@ class DoWhileRewriter : public TIntermTraverser
breakBlock->getSequence()->push_back(breakStatement); breakBlock->getSequence()->push_back(breakStatement);
TIntermUnary *negatedCondition = TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, loop->getCondition()); new TIntermUnary(EOpLogicalNot, loop->getCondition(), nullptr);
TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr); TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
......
...@@ -92,7 +92,8 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse) ...@@ -92,7 +92,8 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
} }
TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable); TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable);
TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse); TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, conditionSymbolElse, nullptr);
TIntermIfElse *falseIfElse = TIntermIfElse *falseIfElse =
new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse); new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
falseBlock = EnsureBlock(falseIfElse); falseBlock = EnsureBlock(falseIfElse);
......
...@@ -75,7 +75,7 @@ bool Traverser::visitUnary(Visit visit, TIntermUnary *node) ...@@ -75,7 +75,7 @@ bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
// Potential problem case detected, apply workaround: -(int) -> ~(int) + 1. // Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
// ~(int) // ~(int)
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr); TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr, nullptr);
bitwiseNot->setLine(opr->getLine()); bitwiseNot->setLine(opr->getLine());
// Constant 1 (or 1u) // Constant 1 (or 1u)
...@@ -109,4 +109,4 @@ void RewriteUnaryMinusOperatorInt(TIntermNode *root) ...@@ -109,4 +109,4 @@ void RewriteUnaryMinusOperatorInt(TIntermNode *root)
Traverser::Apply(root); Traverser::Apply(root);
} }
} // namespace sh } // namespace sh
\ No newline at end of file
...@@ -88,7 +88,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node) ...@@ -88,7 +88,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
CreateTempAssignmentNode(resultVariable, node->getRight())); CreateTempAssignmentNode(resultVariable, node->getRight()));
TIntermUnary *notTempSymbol = TIntermUnary *notTempSymbol =
new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable)); new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable), nullptr);
TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr); TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
insertions.push_back(ifNode); insertions.push_back(ifNode);
......
This source diff could not be displayed because it is too large. You can view the blob instead.
...@@ -261,7 +261,7 @@ TIntermTyped *CreateBuiltInFunctionCallNode(const char *name, ...@@ -261,7 +261,7 @@ TIntermTyped *CreateBuiltInFunctionCallNode(const char *name,
TOperator op = fn->getBuiltInOp(); TOperator op = fn->getBuiltInOp();
if (op != EOpCallBuiltInFunction && arguments->size() == 1) if (op != EOpCallBuiltInFunction && arguments->size() == 1)
{ {
return new TIntermUnary(op, arguments->at(0)->getAsTyped()); return new TIntermUnary(op, arguments->at(0)->getAsTyped(), fn);
} }
return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments); return TIntermAggregate::CreateBuiltInFunctionCall(*fn, arguments);
} }
......
...@@ -196,7 +196,7 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode) ...@@ -196,7 +196,7 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode)
{ {
TType type(EbtFloat, EbpHigh); TType type(EbtFloat, EbpHigh);
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol()); TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol(), nullptr);
original->setLine(getTestSourceLoc()); original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy(); TIntermTyped *copyTyped = original->deepCopy();
TIntermUnary *copy = copyTyped->getAsUnaryNode(); TIntermUnary *copy = copyTyped->getAsUnaryNode();
......
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