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 = {
],
'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': {
'inputs': [
'src/compiler/translator/builtin_function_declarations.txt',
......
......@@ -68,7 +68,6 @@
'compiler/translator/Operator.h',
'compiler/translator/OutputTree.cpp',
'compiler/translator/OutputTree.h',
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h',
'compiler/translator/ParseContext_autogen.h',
......
......@@ -7,7 +7,7 @@
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "angle_gl.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
......@@ -23,10 +23,9 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
bool visitUnary(Visit visit, TIntermUnary *node) override
{
if (visit == PreVisit)
if (node->getFunction())
{
bool needToEmulate =
mEmulator.setFunctionCalled(node->getOp(), node->getOperand()->getType());
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
}
......@@ -35,56 +34,15 @@ class BuiltInFunctionEmulator::BuiltInFunctionEmulationMarker : public TIntermTr
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
// 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();
return true;
}
bool needToEmulate = mEmulator.setFunctionCalled(node->getFunction());
if (needToEmulate)
node->setUseEmulatedFunction();
return true;
}
......@@ -96,74 +54,19 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param,
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)
void BuiltInFunctionEmulator::addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3, param4);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
return id;
}
FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4,
void BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
const TSymbolUniqueId &dependency,
const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition)
{
FunctionId id(op, param1, param2, param3, param4);
mEmulatedFunctions[id] = std::string(emulatedFunctionDefinition);
mFunctionDependencies[id] = dependency;
return id;
mEmulatedFunctions[uniqueId.get()] = std::string(emulatedFunctionDefinition);
mFunctionDependencies[uniqueId.get()] = dependency.get();
}
bool BuiltInFunctionEmulator::isOutputEmpty() const
......@@ -182,47 +85,18 @@ void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
}
}
bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, const TType &param)
{
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
const char *BuiltInFunctionEmulator::findEmulatedFunction(int uniqueId) const
{
for (const auto &queryFunction : mQueryFunctions)
{
const char *result = queryFunction(functionId);
const char *result = queryFunction(uniqueId);
if (result)
{
return result;
}
}
const auto &result = mEmulatedFunctions.find(functionId);
const auto &result = mEmulatedFunctions.find(uniqueId);
if (result != mEmulatedFunctions.end())
{
return result->second.c_str();
......@@ -231,27 +105,31 @@ const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &func
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;
}
for (size_t i = 0; i < mFunctions.size(); ++i)
{
if (mFunctions[i] == functionId)
if (mFunctions[i] == uniqueId)
return true;
}
// 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())
{
setFunctionCalled((*dependency).second);
}
// Copy the functionId if it needs to be stored, to make sure that the TType pointers inside
// remain valid and constant.
mFunctions.push_back(functionId.getCopy());
mFunctions.push_back(uniqueId);
return true;
}
......@@ -284,76 +162,4 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons
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
......@@ -8,82 +8,15 @@
#define COMPILER_TRANSLATOR_BUILTINFUNCTIONEMULATOR_H_
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh
{
struct MiniFunctionId
{
constexpr MiniFunctionId(TOperator op = EOpNull,
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);
class TIntermNode;
class TFunction;
class TSymbolUniqueId;
FunctionId(const FunctionId &) = default;
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 &);
using BuiltinQueryFunc = const char *(int);
//
// This class decides which built-in functions need to be replaced with the emulated ones. It can be
......@@ -108,37 +41,12 @@ class BuiltInFunctionEmulator
void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op,
const TType *param,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunction(TOperator op,
const TType *param1,
const TType *param2,
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 addEmulatedFunction(const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
void addEmulatedFunctionWithDependency(const TSymbolUniqueId &dependency,
const TSymbolUniqueId &uniqueId,
const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc);
......@@ -148,31 +56,20 @@ class BuiltInFunctionEmulator
// 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
// call needs to be replaced with an emulated one.
bool setFunctionCalled(TOperator op, const TType &param);
bool setFunctionCalled(TOperator op, const TType &param1, const TType &param2);
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);
bool setFunctionCalled(const TFunction *function);
bool setFunctionCalled(int uniqueId);
const char *findEmulatedFunction(const FunctionId &functionId) const;
const char *findEmulatedFunction(int uniqueId) const;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
// Map from function unique id to emulated function definition
std::map<int, std::string> mEmulatedFunctions;
// Map from dependent functions to their dependencies. This structure allows each function to
// have at most one dependency.
std::map<FunctionId, FunctionId> mFunctionDependencies;
std::map<int, int> mFunctionDependencies;
// Called function ids
std::vector<FunctionId> mFunctions;
std::vector<int> mFunctions;
// Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions;
......
......@@ -7,9 +7,8 @@
#include "compiler/translator/BuiltInFunctionEmulatorGLSL.h"
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
......@@ -19,8 +18,7 @@ void InitBuiltInAbsFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *e
{
if (shaderType == GL_VERTEX_SHADER)
{
const TType *int1 = StaticType::GetBasic<EbtInt>();
emu->addEmulatedFunction(EOpAbs, int1, "int abs_emu(int x) { return x * sign(x); }");
emu->addEmulatedFunction(BuiltInId::abs_Int1, "int abs_emu(int x) { return x * sign(x); }");
}
}
......@@ -31,17 +29,12 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130)
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.
emu->addEmulatedFunction(
EOpIsnan, float1,
BuiltInId::isnan_Float1,
"bool isnan_emu(float x) { return (x > 0.0 || x < 0.0) ? false : x != 0.0; }");
emu->addEmulatedFunction(
EOpIsnan, float2,
BuiltInId::isnan_Float2,
"bvec2 isnan_emu(vec2 x)\n"
"{\n"
" bvec2 isnan;\n"
......@@ -52,7 +45,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float3,
BuiltInId::isnan_Float3,
"bvec3 isnan_emu(vec3 x)\n"
"{\n"
" bvec3 isnan;\n"
......@@ -63,7 +56,7 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
" return isnan;\n"
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float4,
BuiltInId::isnan_Float4,
"bvec4 isnan_emu(vec4 x)\n"
"{\n"
" bvec4 isnan;\n"
......@@ -77,27 +70,21 @@ void InitBuiltInIsnanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator
void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *emu)
{
const TType *float1 = StaticType::GetBasic<EbtFloat>();
auto floatFuncId = emu->addEmulatedFunction(
EOpAtan, float1, float1,
"emu_precision float atan_emu(emu_precision float y, emu_precision "
"float x)\n"
"{\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"
"}\n");
static const std::array<const TType *, 5> floatVecs = {
nullptr,
nullptr,
StaticType::GetBasic<EbtFloat, 2>(),
StaticType::GetBasic<EbtFloat, 3>(),
StaticType::GetBasic<EbtFloat, 4>(),
emu->addEmulatedFunction(BuiltInId::atan_Float1_Float1,
"emu_precision float atan_emu(emu_precision float y, emu_precision "
"float x)\n"
"{\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"
"}\n");
static const std::array<TSymbolUniqueId, 4> ids = {
BuiltInId::atan_Float1_Float1, BuiltInId::atan_Float2_Float2, BuiltInId::atan_Float3_Float3,
BuiltInId::atan_Float4_Float4,
};
for (int dim = 2; dim <= 4; ++dim)
{
const TType *floatVec = floatVecs[dim];
std::stringstream ss;
ss << "emu_precision vec" << dim << " atan_emu(emu_precision vec" << dim
<< " y, emu_precision vec" << dim << " x)\n"
......@@ -114,7 +101,7 @@ void InitBuiltInAtanFunctionEmulatorForGLSLWorkarounds(BuiltInFunctionEmulator *
}
ss << ");\n"
"}\n";
emu->addEmulatedFunctionWithDependency(floatFuncId, EOpAtan, floatVec, floatVec,
emu->addEmulatedFunctionWithDependency(BuiltInId::atan_Float1_Float1, ids[dim - 1],
ss.str().c_str());
}
}
......@@ -127,11 +114,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// Emulate packUnorm2x16 and unpackUnorm2x16 (GLSL 4.10)
if (targetGLSLVersion < GLSL_VERSION_410)
{
const TType *float2 = StaticType::GetBasic<EbtFloat, 2>();
const TType *uint1 = StaticType::GetBasic<EbtUInt>();
// clang-format off
emu->addEmulatedFunction(EOpPackUnorm2x16, float2,
emu->addEmulatedFunction(BuiltInId::packUnorm2x16_Float2,
"uint packUnorm2x16_emu(vec2 v)\n"
"{\n"
" int x = int(round(clamp(v.x, 0.0, 1.0) * 65535.0));\n"
......@@ -139,7 +123,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackUnorm2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackUnorm2x16_UInt1,
"vec2 unpackUnorm2x16_emu(uint u)\n"
"{\n"
" float x = float(u & 0xFFFFu) / 65535.0;\n"
......@@ -153,11 +137,8 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
// by using floatBitsToInt, floatBitsToUint, intBitsToFloat, and uintBitsToFloat (GLSL 3.30).
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
emu->addEmulatedFunction(EOpPackSnorm2x16, float2,
emu->addEmulatedFunction(BuiltInId::packSnorm2x16_Float2,
"uint packSnorm2x16_emu(vec2 v)\n"
"{\n"
" #if defined(GL_ARB_shading_language_packing)\n"
......@@ -168,7 +149,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return uint((y << 16) | (x & 0xFFFF));\n"
" #endif\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackSnorm2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackSnorm2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n"
" float fromSnorm(uint x)\n"
" {\n"
......@@ -189,7 +170,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
"}\n");
// Functions uint f32tof16(float val) and float f16tof32(uint val) are
// 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"
" uint f32tof16(float val)\n"
" {\n"
......@@ -236,7 +217,7 @@ void InitBuiltInFunctionEmulatorForGLSLMissingFunctions(BuiltInFunctionEmulator
" return (y << 16) | x;\n"
" #endif\n"
"}\n");
emu->addEmulatedFunction(EOpUnpackHalf2x16, uint1,
emu->addEmulatedFunction(BuiltInId::unpackHalf2x16_UInt1,
"#if !defined(GL_ARB_shading_language_packing)\n"
" float f16tof32(uint val)\n"
" {\n"
......
......@@ -4,17 +4,17 @@
// found in the LICENSE file.
//
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "angle_gl.h"
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/BuiltInFunctionEmulatorHLSL.h"
#include "compiler/translator/SymbolTable.h"
#include "compiler/translator/VersionGLSL.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
// Defined in emulated_builtin_functions_hlsl_autogen.cpp.
const char *FindHLSLFunction(const FunctionId &functionID);
const char *FindHLSLFunction(int uniqueId);
void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator *emu,
int targetGLSLVersion)
......@@ -22,12 +22,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
if (targetGLSLVersion < GLSL_VERSION_130)
return;
TType *float1 = new TType(EbtFloat);
TType *float2 = new TType(EbtFloat, 2);
TType *float3 = new TType(EbtFloat, 3);
TType *float4 = new TType(EbtFloat, 4);
emu->addEmulatedFunction(EOpIsnan, float1,
emu->addEmulatedFunction(BuiltInId::isnan_Float1,
"bool isnan_emu(float x)\n"
"{\n"
" return (x > 0.0 || x < 0.0) ? false : x != 0.0;\n"
......@@ -35,7 +30,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"\n");
emu->addEmulatedFunction(
EOpIsnan, float2,
BuiltInId::isnan_Float2,
"bool2 isnan_emu(float2 x)\n"
"{\n"
" bool2 isnan;\n"
......@@ -47,7 +42,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float3,
BuiltInId::isnan_Float3,
"bool3 isnan_emu(float3 x)\n"
"{\n"
" bool3 isnan;\n"
......@@ -59,7 +54,7 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
"}\n");
emu->addEmulatedFunction(
EOpIsnan, float4,
BuiltInId::isnan_Float4,
"bool4 isnan_emu(float4 x)\n"
"{\n"
" bool4 isnan;\n"
......@@ -73,43 +68,35 @@ void InitBuiltInIsnanFunctionEmulatorForHLSLWorkarounds(BuiltInFunctionEmulator
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);
// (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:
// a <= 0xffff, d <= 0xffff, ((a * c) >> 16) <= 0xffff and 0xffff * 0xffff + 0xffff = 0xffff0000
FunctionId umulExtendedUint1 = emu->addEmulatedFunction(
EOpUmulExtended, uint1, uint1, uint1, uint1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
emu->addEmulatedFunction(BuiltInId::umulExtended_UInt1_UInt1_UInt1_UInt1,
"void umulExtended_emu(uint x, uint y, out uint msb, out uint lsb)\n"
"{\n"
" lsb = x * y;\n"
" uint a = (x & 0xffffu);\n"
" uint b = (x >> 16);\n"
" uint c = (y & 0xffffu);\n"
" uint d = (y >> 16);\n"
" uint ad = a * d + ((a * c) >> 16);\n"
" uint bc = b * c;\n"
" uint carry = uint(ad > (0xffffffffu - bc));\n"
" msb = ((ad + bc) >> 16) + (carry << 16) + b * d;\n"
"}\n");
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"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" umulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
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"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -117,7 +104,8 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" umulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
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"
"{\n"
" umulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -130,8 +118,9 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
// result needs to be negative.
// 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.
FunctionId imulExtendedInt1 = emu->addEmulatedFunctionWithDependency(
umulExtendedUint1, EOpImulExtended, int1, int1, int1, int1,
emu->addEmulatedFunctionWithDependency(
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"
"{\n"
" uint unsignedMsb;\n"
......@@ -156,14 +145,14 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" }\n"
"}\n");
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"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
" imulExtended_emu(x.y, y.y, msb.y, lsb.y);\n"
"}\n");
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"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......@@ -171,7 +160,7 @@ void InitBuiltInFunctionEmulatorForHLSL(BuiltInFunctionEmulator *emu)
" imulExtended_emu(x.z, y.z, msb.z, lsb.z);\n"
"}\n");
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"
"{\n"
" imulExtended_emu(x.x, y.x, msb.x, lsb.x);\n"
......
......@@ -588,7 +588,7 @@ bool TCompiler::checkAndSimplifyAST(TIntermBlock *root,
if (compileOptions & SH_REMOVE_POW_WITH_CONSTANT_EXPONENT)
{
RemovePow(root);
RemovePow(root, &symbolTable);
}
if (compileOptions & SH_REGENERATE_STRUCT_NAMES)
......
......@@ -809,7 +809,9 @@ TIntermBinary::TIntermBinary(const TIntermBinary &node)
}
TIntermUnary::TIntermUnary(const TIntermUnary &node)
: TIntermOperator(node), mUseEmulatedFunction(node.mUseEmulatedFunction)
: TIntermOperator(node),
mUseEmulatedFunction(node.mUseEmulatedFunction),
mFunction(node.mFunction)
{
TIntermTyped *operandCopy = node.mOperand->deepCopy();
ASSERT(operandCopy != nullptr);
......@@ -1049,8 +1051,8 @@ TIntermSwizzle::TIntermSwizzle(TIntermTyped *operand, const TVector<int> &swizzl
promote();
}
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false)
TIntermUnary::TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function)
: TIntermOperator(op), mOperand(operand), mUseEmulatedFunction(false), mFunction(function)
{
promote();
}
......
......@@ -505,7 +505,7 @@ class TIntermBinary : public TIntermOperator
class TIntermUnary : public TIntermOperator
{
public:
TIntermUnary(TOperator op, TIntermTyped *operand);
TIntermUnary(TOperator op, TIntermTyped *operand, const TFunction *function);
TIntermTyped *deepCopy() const override { return new TIntermUnary(*this); }
......@@ -518,6 +518,8 @@ class TIntermUnary : public TIntermOperator
TIntermTyped *getOperand() { return mOperand; }
TIntermTyped *fold(TDiagnostics *diagnostics) override;
const TFunction *getFunction() const { return mFunction; }
void setUseEmulatedFunction() { mUseEmulatedFunction = true; }
bool getUseEmulatedFunction() { return mUseEmulatedFunction; }
......@@ -528,6 +530,8 @@ class TIntermUnary : public TIntermOperator
// to work around driver bugs.
bool mUseEmulatedFunction;
const TFunction *const mFunction;
private:
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)
TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *child,
const TSourceLoc &loc)
const TSourceLoc &loc,
const TFunction *func)
{
ASSERT(child != nullptr);
......@@ -4907,7 +4908,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
}
markStaticReadIfSymbol(child);
TIntermUnary *node = new TIntermUnary(op, child);
TIntermUnary *node = new TIntermUnary(op, child, func);
node->setLine(loc);
return node->fold(mDiagnostics);
......@@ -4916,7 +4917,7 @@ TIntermTyped *TParseContext::createUnaryMath(TOperator op,
TIntermTyped *TParseContext::addUnaryMath(TOperator op, TIntermTyped *child, const TSourceLoc &loc)
{
ASSERT(op != EOpNull);
TIntermTyped *node = createUnaryMath(op, child, loc);
TIntermTyped *node = createUnaryMath(op, child, loc, nullptr);
if (node == nullptr)
{
return child;
......@@ -5779,7 +5780,7 @@ TIntermTyped *TParseContext::addMethod(TFunctionLookup *fnCall, const TSourceLoc
}
else
{
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode);
TIntermUnary *node = new TIntermUnary(EOpArrayLength, thisNode, nullptr);
node->setLine(loc);
return node->fold(mDiagnostics);
}
......@@ -5837,7 +5838,8 @@ TIntermTyped *TParseContext::addNonConstructorFunctionCall(TFunctionLookup *fnCa
{
// Treat it like a built-in unary operator.
TIntermNode *unaryParamNode = fnCall->arguments().front();
TIntermTyped *callNode = createUnaryMath(op, unaryParamNode->getAsTyped(), loc);
TIntermTyped *callNode =
createUnaryMath(op, unaryParamNode->getAsTyped(), loc, fnCandidate);
ASSERT(callNode != nullptr);
return callNode;
}
......
......@@ -549,7 +549,10 @@ class TParseContext : angle::NonCopyable
TIntermTyped *left,
TIntermTyped *right,
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 *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().
TSymbolUniqueId &TSymbolUniqueId::operator=(const TSymbolUniqueId &) = default;
int TSymbolUniqueId::get() const
{
return mId;
}
bool TSymbolUniqueId::operator==(const TSymbolUniqueId &other) const
{
return mId == other.mId;
......
......@@ -25,7 +25,7 @@ class TSymbolUniqueId
TSymbolUniqueId &operator=(const TSymbolUniqueId &);
bool operator==(const TSymbolUniqueId &) const;
int get() const;
constexpr int get() const { return mId; }
private:
friend class TSymbolTable;
......
cc849405cb2fd922f9a269ab6594cb9b
\ No newline at end of file
e7cb1a4f677413aec61815b10019f608
\ No newline at end of file
......@@ -2,7 +2,7 @@
// Generated by gen_emulated_builtin_function_tables.py using data from
// 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
// found in the LICENSE file.
//
......@@ -10,6 +10,7 @@
// HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{
......@@ -19,51 +20,52 @@ namespace
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;
};
constexpr FunctionPair g_hlslFunctions[] = {
{{EOpMod, ParamType::Float1, ParamType::Float1},
{BuiltInId::mod_Float1_Float1,
"float mod_emu(float x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float2},
{BuiltInId::mod_Float2_Float2,
"float2 mod_emu(float2 x, float2 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float2, ParamType::Float1},
{BuiltInId::mod_Float2_Float1,
"float2 mod_emu(float2 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float3},
{BuiltInId::mod_Float3_Float3,
"float3 mod_emu(float3 x, float3 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float3, ParamType::Float1},
{BuiltInId::mod_Float3_Float1,
"float3 mod_emu(float3 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float4},
{BuiltInId::mod_Float4_Float4,
"float4 mod_emu(float4 x, float4 y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpMod, ParamType::Float4, ParamType::Float1},
{BuiltInId::mod_Float4_Float1,
"float4 mod_emu(float4 x, float y)\n"
"{\n"
" return x - y * floor(x / y);\n"
"}\n"},
{{EOpFrexp, ParamType::Float1, ParamType::Int1},
{BuiltInId::frexp_Float1_Int1,
"float frexp_emu(float x, out int exp)\n"
"{\n"
" float fexp;\n"
......@@ -71,7 +73,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float2, ParamType::Int2},
{BuiltInId::frexp_Float2_Int2,
"float2 frexp_emu(float2 x, out int2 exp)\n"
"{\n"
" float2 fexp;\n"
......@@ -79,7 +81,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int2(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float3, ParamType::Int3},
{BuiltInId::frexp_Float3_Int3,
"float3 frexp_emu(float3 x, out int3 exp)\n"
"{\n"
" float3 fexp;\n"
......@@ -87,7 +89,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int3(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpFrexp, ParamType::Float4, ParamType::Int4},
{BuiltInId::frexp_Float4_Int4,
"float4 frexp_emu(float4 x, out int4 exp)\n"
"{\n"
" float4 fexp;\n"
......@@ -95,27 +97,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
" exp = int4(fexp);\n"
" return mantissa;\n"
"}\n"},
{{EOpLdexp, ParamType::Float1, ParamType::Int1},
{BuiltInId::ldexp_Float1_Int1,
"float ldexp_emu(float x, int exp)\n"
"{\n"
" return ldexp(x, float(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float2, ParamType::Int2},
{BuiltInId::ldexp_Float2_Int2,
"float2 ldexp_emu(float2 x, int2 exp)\n"
"{\n"
" return ldexp(x, float2(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float3, ParamType::Int3},
{BuiltInId::ldexp_Float3_Int3,
"float3 ldexp_emu(float3 x, int3 exp)\n"
"{\n"
" return ldexp(x, float3(exp));\n"
"}\n"},
{{EOpLdexp, ParamType::Float4, ParamType::Int4},
{BuiltInId::ldexp_Float4_Int4,
"float4 ldexp_emu(float4 x, int4 exp)\n"
"{\n"
" return ldexp(x, float4(exp));\n"
"}\n"},
{{EOpFaceforward, ParamType::Float1, ParamType::Float1, ParamType::Float1},
{BuiltInId::faceforward_Float1_Float1_Float1,
"float faceforward_emu(float N, float I, float Nref)\n"
"{\n"
" if(dot(Nref, I) >= 0)\n"
......@@ -127,7 +129,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
......@@ -139,7 +141,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
......@@ -151,7 +153,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return 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"
"{\n"
" if(dot(Nref, I) >= 0)\n"
......@@ -163,20 +165,20 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return N;\n"
" }\n"
"}\n"},
{{EOpAtan, ParamType::Float1, ParamType::Float1},
{BuiltInId::atan_Float1_Float1,
"float atan_emu(float y, float x)\n"
"{\n"
" if(x == 0 && y == 0) x = 1;\n"
" return atan2(y, x);\n"
"}\n"},
{{EOpAtan, ParamType::Float2, ParamType::Float2},
{BuiltInId::atan_Float2_Float2,
"float2 atan_emu(float2 y, float2 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 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"
"}\n"},
{{EOpAtan, ParamType::Float3, ParamType::Float3},
{BuiltInId::atan_Float3_Float3,
"float3 atan_emu(float3 y, float3 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
......@@ -184,7 +186,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" 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"
"}\n"},
{{EOpAtan, ParamType::Float4, ParamType::Float4},
{BuiltInId::atan_Float4_Float4,
"float4 atan_emu(float4 y, float4 x)\n"
"{\n"
" if(x[0] == 0 && y[0] == 0) x[0] = 1;\n"
......@@ -194,72 +196,72 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(atan2(y[0], x[0]), atan2(y[1], x[1]), atan2(y[2], \n"
" x[2]), atan2(y[3], x[3]));\n"
"}\n"},
{{EOpAsinh, ParamType::Float1},
{BuiltInId::asinh_Float1,
"float asinh_emu(in float x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float2},
{BuiltInId::asinh_Float2,
"float2 asinh_emu(in float2 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float3},
{BuiltInId::asinh_Float3,
"float3 asinh_emu(in float3 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAsinh, ParamType::Float4},
{BuiltInId::asinh_Float4,
"float4 asinh_emu(in float4 x)\n"
"{\n"
" return log(x + sqrt(pow(x, 2.0) + 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float1},
{BuiltInId::acosh_Float1,
"float acosh_emu(in float x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float2},
{BuiltInId::acosh_Float2,
"float2 acosh_emu(in float2 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float3},
{BuiltInId::acosh_Float3,
"float3 acosh_emu(in float3 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAcosh, ParamType::Float4},
{BuiltInId::acosh_Float4,
"float4 acosh_emu(in float4 x)\n"
"{\n"
" return log(x + sqrt(x + 1.0) * sqrt(x - 1.0));\n"
"}\n"},
{{EOpAtanh, ParamType::Float1},
{BuiltInId::atanh_Float1,
"float atanh_emu(in float x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float2},
{BuiltInId::atanh_Float2,
"float2 atanh_emu(in float2 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float3},
{BuiltInId::atanh_Float3,
"float3 atanh_emu(in float3 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpAtanh, ParamType::Float4},
{BuiltInId::atanh_Float4,
"float4 atanh_emu(in float4 x)\n"
"{\n"
" return 0.5 * log((1.0 + x) / (1.0 - x));\n"
"}\n"},
{{EOpRoundEven, ParamType::Float1},
{BuiltInId::roundEven_Float1,
"float roundEven_emu(in float x)\n"
"{\n"
" return (frac(x) == 0.5 && trunc(x) % 2.0 == 0.0) ? trunc(x) : round(x);\n"
"}\n"},
{{EOpRoundEven, ParamType::Float2},
{BuiltInId::roundEven_Float2,
"float2 roundEven_emu(in float2 x)\n"
"{\n"
" float2 v;\n"
......@@ -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"
" return v;\n"
"}\n"},
{{EOpRoundEven, ParamType::Float3},
{BuiltInId::roundEven_Float3,
"float3 roundEven_emu(in float3 x)\n"
"{\n"
" float3 v;\n"
......@@ -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"
" return v;\n"
"}\n"},
{{EOpRoundEven, ParamType::Float4},
{BuiltInId::roundEven_Float4,
"float4 roundEven_emu(in float4 x)\n"
"{\n"
" float4 v;\n"
......@@ -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"
" return v;\n"
"}\n"},
{{EOpPackSnorm2x16, ParamType::Float2},
{BuiltInId::packSnorm2x16_Float2,
"int webgl_toSnorm16(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 32767.0));\n"
"}\n"
......@@ -296,7 +298,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" int y = webgl_toSnorm16(v.y);\n"
" return (asuint(y) << 16) | (asuint(x) & 0xffffu);\n"
"}\n"},
{{EOpPackUnorm2x16, ParamType::Float2},
{BuiltInId::packUnorm2x16_Float2,
"uint webgl_toUnorm16(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 65535.0));\n"
"}\n"
......@@ -306,14 +308,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint y = webgl_toUnorm16(v.y);\n"
" return (y << 16) | x;\n"
"}\n"},
{{EOpPackHalf2x16, ParamType::Float2},
{BuiltInId::packHalf2x16_Float2,
"uint packHalf2x16_emu(in float2 v)\n"
"{\n"
" uint x = f32tof16(v.x);\n"
" uint y = f32tof16(v.y);\n"
" return (y << 16) | x;\n"
"}\n"},
{{EOpUnpackSnorm2x16, ParamType::Uint1},
{BuiltInId::unpackSnorm2x16_UInt1,
"float webgl_fromSnorm16(in uint x) {\n"
" int xi = asint(x & 0x7fffu) - asint(x & 0x8000u);\n"
" return clamp(float(xi) / 32767.0, -1.0, 1.0);\n"
......@@ -324,7 +326,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u;\n"
" return float2(webgl_fromSnorm16(x), webgl_fromSnorm16(y));\n"
"}\n"},
{{EOpUnpackUnorm2x16, ParamType::Uint1},
{BuiltInId::unpackUnorm2x16_UInt1,
"float webgl_fromUnorm16(in uint x) {\n"
" return float(x) / 65535.0;\n"
"}\n"
......@@ -334,14 +336,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint x = u & 0xffffu;\n"
" return float2(webgl_fromUnorm16(x), webgl_fromUnorm16(y));\n"
"}\n"},
{{EOpUnpackHalf2x16, ParamType::Uint1},
{BuiltInId::unpackHalf2x16_UInt1,
"float2 unpackHalf2x16_emu(in uint u)\n"
"{\n"
" uint y = (u >> 16);\n"
" uint x = u & 0xffffu;\n"
" return float2(f16tof32(x), f16tof32(y));\n"
"}\n"},
{{EOpPackSnorm4x8, ParamType::Float4},
{BuiltInId::packSnorm4x8_Float4,
"int webgl_toSnorm8(in float x) {\n"
" return int(round(clamp(x, -1.0, 1.0) * 127.0));\n"
"}\n"
......@@ -354,7 +356,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return ((asuint(w) & 0xffu) << 24) | ((asuint(z) & 0xffu) << 16) \n"
" | ((asuint(y) & 0xffu) << 8) | (asuint(x) & 0xffu);\n"
"}\n"},
{{EOpPackUnorm4x8, ParamType::Float4},
{BuiltInId::packUnorm4x8_Float4,
"uint webgl_toUnorm8(in float x) {\n"
" return uint(round(clamp(x, 0.0, 1.0) * 255.0));\n"
"}\n"
......@@ -366,7 +368,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint w = webgl_toUnorm8(v.w);\n"
" return (w << 24) | (z << 16) | (y << 8) | x;\n"
"}\n"},
{{EOpUnpackSnorm4x8, ParamType::Uint1},
{BuiltInId::unpackSnorm4x8_UInt1,
"float webgl_fromSnorm8(in uint x) {\n"
" int xi = asint(x & 0x7fu) - asint(x & 0x80u);\n"
" return clamp(float(xi) / 127.0, -1.0, 1.0);\n"
......@@ -380,7 +382,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" return float4(webgl_fromSnorm8(x), webgl_fromSnorm8(y), \n"
" webgl_fromSnorm8(z), webgl_fromSnorm8(w));\n"
"}\n"},
{{EOpUnpackUnorm4x8, ParamType::Uint1},
{BuiltInId::unpackUnorm4x8_UInt1,
"float webgl_fromUnorm8(in uint x) {\n"
" return float(x) / 255.0;\n"
"}\n"
......@@ -402,47 +404,47 @@ constexpr FunctionPair g_hlslFunctions[] = {
// 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
// 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"
"{\n"
" return mul(float2x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float3},
{BuiltInId::outerProduct_Float3_Float3,
"float3x3 outerProduct_emu(in float3 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x3(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float4},
{BuiltInId::outerProduct_Float4_Float4,
"float4x4 outerProduct_emu(in float4 c, in float4 r)\n"
"{\n"
" return mul(float4x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float2},
{BuiltInId::outerProduct_Float3_Float2,
"float2x3 outerProduct_emu(in float3 c, in float2 r)\n"
"{\n"
" return mul(float2x1(r), float1x3(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float3},
{BuiltInId::outerProduct_Float2_Float3,
"float3x2 outerProduct_emu(in float2 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float2},
{BuiltInId::outerProduct_Float4_Float2,
"float2x4 outerProduct_emu(in float4 c, in float2 r)\n"
"{\n"
" return mul(float2x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float2, ParamType::Float4},
{BuiltInId::outerProduct_Float2_Float4,
"float4x2 outerProduct_emu(in float2 c, in float4 r)\n"
"{\n"
" return mul(float4x1(r), float1x2(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float4, ParamType::Float3},
{BuiltInId::outerProduct_Float4_Float3,
"float3x4 outerProduct_emu(in float4 c, in float3 r)\n"
"{\n"
" return mul(float3x1(r), float1x4(c));\n"
"}\n"},
{{EOpOuterProduct, ParamType::Float3, ParamType::Float4},
{BuiltInId::outerProduct_Float3_Float4,
"float4x3 outerProduct_emu(in float3 c, in float4 r)\n"
"{\n"
" return mul(float4x1(r), float1x3(c));\n"
......@@ -458,14 +460,14 @@ constexpr FunctionPair g_hlslFunctions[] = {
// 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
// for singular or poorly-conditioned matrices.
{{EOpInverse, ParamType::Mat2},
{BuiltInId::inverse_Float2x2,
"float2x2 inverse_emu(in float2x2 m)\n"
"{\n"
" float2x2 cof = { m[1][1], -m[0][1], -m[1][0], m[0][0] };\n"
" return cof / determinant(transpose(m));\n"
"}\n"},
// cofAB is the cofactor for column A and row B.
{{EOpInverse, ParamType::Mat3},
{BuiltInId::inverse_Float3x3,
"float3x3 inverse_emu(in float3x3 m)\n"
"{\n"
" float cof00 = m[1][1] * m[2][2] - m[2][1] * m[1][2];\n"
......@@ -480,7 +482,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" float3x3 cof = { cof00, cof10, cof20, cof01, cof11, cof21, cof02, cof12, cof22 };\n"
" return cof / determinant(transpose(m));\n"
"}\n"},
{{EOpInverse, ParamType::Mat4},
{BuiltInId::inverse_Float4x4,
"float4x4 inverse_emu(in float4x4 m)\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"
......@@ -556,27 +558,27 @@ constexpr FunctionPair g_hlslFunctions[] = {
// 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.
{{EOpMix, ParamType::Float1, ParamType::Float1, ParamType::Bool1},
{BuiltInId::mix_Float1_Float1_Bool1,
"float mix_emu(float x, float y, bool a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float2, ParamType::Float2, ParamType::Bool2},
{BuiltInId::mix_Float2_Float2_Bool2,
"float2 mix_emu(float2 x, float2 y, bool2 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float3, ParamType::Float3, ParamType::Bool3},
{BuiltInId::mix_Float3_Float3_Bool3,
"float3 mix_emu(float3 x, float3 y, bool3 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpMix, ParamType::Float4, ParamType::Float4, ParamType::Bool4},
{BuiltInId::mix_Float4_Float4_Bool4,
"float4 mix_emu(float4 x, float4 y, bool4 a)\n"
"{\n"
" return a ? y : x;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint1, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt1_Int1_Int1,
"uint bitfieldExtract_emu(uint value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -587,7 +589,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint2, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt2_Int1_Int1,
"uint2 bitfieldExtract_emu(uint2 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -598,7 +600,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint3, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt3_Int1_Int1,
"uint3 bitfieldExtract_emu(uint3 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -609,7 +611,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Uint4, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_UInt4_Int1_Int1,
"uint4 bitfieldExtract_emu(uint4 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -620,7 +622,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint mask = ((maskMsb - 1u) | maskMsb) << offset;\n"
" return (value & mask) >> offset;\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int1, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int1_Int1_Int1,
"int bitfieldExtract_emu(int value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -637,7 +639,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int2, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int2_Int1_Int1,
"int2 bitfieldExtract_emu(int2 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -654,7 +656,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int3, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int3_Int1_Int1,
"int3 bitfieldExtract_emu(int3 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -671,7 +673,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\n"
"}\n"},
{{EOpBitfieldExtract, ParamType::Int4, ParamType::Int1, ParamType::Int1},
{BuiltInId::bitfieldExtract_Int4_Int1_Int1,
"int4 bitfieldExtract_emu(int4 value, int offset, int bits)\n"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -688,7 +690,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" }\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -700,7 +702,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -712,7 +714,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -724,7 +726,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -736,7 +738,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" uint baseMask = ~insertMask;\n"
" return (base & baseMask) | ((insert << offset) & insertMask);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -750,7 +752,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -764,7 +766,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -778,7 +780,7 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" if (offset < 0 || bits <= 0 || offset >= 32 || bits > 32 || offset + bits > 32)\n"
......@@ -792,71 +794,71 @@ constexpr FunctionPair g_hlslFunctions[] = {
" insertMask);\n"
" return asint(resultUnsigned);\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"
"{\n"
" carry = uint(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint2(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint3(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" carry = uint4(x > (0xffffffffu - y));\n"
" return x + y;\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"
"{\n"
" borrow = uint(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint2(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint3(x < y);\n"
" return x - y;\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"
"{\n"
" borrow = uint4(x < y);\n"
" return x - y;\n"
"}\n"},
// We emulate tanh just to avoid overflow on large arguments.
{{EOpTanh, ParamType::Float1},
{BuiltInId::tanh_Float1,
"float tanh_emu(float x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float2},
{BuiltInId::tanh_Float2,
"float2 tanh_emu(float2 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float3},
{BuiltInId::tanh_Float3,
"float3 tanh_emu(float3 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
"}\n"},
{{EOpTanh, ParamType::Float4},
{BuiltInId::tanh_Float4,
"float4 tanh_emu(float4 x)\n"
"{\n"
" return (abs(x) > 15.0) ? sign(x) : tanh(x);\n"
......@@ -864,12 +866,12 @@ constexpr FunctionPair g_hlslFunctions[] = {
};
} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID)
const char *FindHLSLFunction(int uniqueId)
{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{
const auto &function = g_hlslFunctions[index];
if (function.id == functionID)
if (function.id == uniqueId)
{
return function.body;
}
......
......@@ -68,7 +68,7 @@ TEST(ImmutableStringTest, ScriptGeneratedHashesMatch)
"""
# 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.
// Generated by {script_name} using data from {variable_data_source_name} and
// {function_data_source_name}.
......@@ -83,11 +83,21 @@ template_builtin_header = """// GENERATED FILE - DO NOT EDIT.
#ifndef COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#define COMPILER_TRANSLATOR_TREEUTIL_BUILTIN_AUTOGEN_H_
#include "compiler/translator/SymbolUniqueId.h"
namespace sh
{{
class TVariable;
class BuiltInId
{{
public:
{builtin_id_declarations}
}}; // class BuiltInId
namespace BuiltInVariable
{{
......@@ -144,23 +154,15 @@ template_symboltable_cpp = """// GENERATED FILE - DO NOT EDIT.
#include "compiler/translator/SymbolTable.h"
#include "angle_gl.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
#include "compiler/translator/ImmutableString.h"
#include "compiler/translator/StaticType.h"
#include "compiler/translator/Symbol.h"
#include "compiler/translator/SymbolUniqueId.h"
#include "compiler/translator/SymbolTable.h"
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
// have these definitions without an initializer. C++17 should eventually remove the need for this.
{builtin_id_definitions}
......@@ -455,6 +457,13 @@ class TType:
mangled_name += get_basic_mangled_name(self.data['basic'])
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):
return self.data['primarySize'] > 1 and self.data['secondarySize'] == 1
......@@ -758,6 +767,12 @@ def get_function_mangled_name(function_name, parameters):
mangled_name += param.get_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 = []
for basic_type in basic_types_enumeration:
primary_sizes = [1]
......@@ -966,10 +981,13 @@ def process_single_function_group(condition, group_name, group):
template_args['param_count'] = len(parameters)
template_args['return_type'] = function_props['returnType'].get_statictype_string()
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_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))
template_builtin_id_definition = 'constexpr const TSymbolUniqueId BuiltInId::{human_readable_name};'
builtin_id_definitions.append(template_builtin_id_definition.format(**template_args))
parameters_list = []
for param in parameters:
......@@ -998,7 +1016,7 @@ def process_single_function_group(condition, group_name, group):
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)
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))
# 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.
// HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h"
#include "compiler/translator/tree_util/BuiltIn_autogen.h"
namespace sh
{{
......@@ -30,11 +31,11 @@ namespace
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;
}};
......@@ -42,12 +43,12 @@ constexpr FunctionPair g_hlslFunctions[] = {{
{emulated_functions}}};
}} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID)
const char *FindHLSLFunction(int uniqueId)
{{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{{
const auto &function = g_hlslFunctions[index];
if (function.id == functionID)
if (function.id == uniqueId)
{{
return function.body;
}}
......@@ -74,26 +75,18 @@ def load_json(path):
return json.loads(file_data, object_pairs_hook=reject_duplicate_keys)
def enum_type(arg):
# handle 'argtype argname' and 'out argtype argname'
chunks = arg.split(' ')
arg_type = chunks[0]
if len(chunks) == 3:
arg_type = chunks[1]
if arg_type == "float2x2":
return "Mat2"
elif arg_type == "float3x3":
return "Mat3"
elif arg_type == "float4x4":
return "Mat4"
suffix = ""
if not arg_type[-1].isdigit():
suffix = '1'
return arg_type.capitalize() + suffix
def caps(op):
return op[0].upper() + op[1:]
# handle 'argtype argname' and 'out argtype argname'
chunks = arg.split(' ')
arg_type = chunks[0]
if len(chunks) == 3:
arg_type = chunks[1]
suffix = ""
if not arg_type[-1].isdigit():
suffix = '1'
if arg_type[0:4] == 'uint':
return 'UI' + arg_type[2:] + suffix
return arg_type.capitalize() + suffix
input_script = "emulated_builtin_function_data_hlsl.json"
hlsl_json = load_json(input_script)
......@@ -109,7 +102,7 @@ def gen_emulated_function(data):
body = [ sig, '{' ] + [' ' + line for line in data['body']] + ['}']
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:
func += '"' + '\\n"\n"'.join(data['helper']) + '\\n"\n'
func += '"' + '\\n"\n"'.join(body) + '\\n"\n'
......
......@@ -114,7 +114,8 @@ void AddArrayZeroInitForLoop(const TIntermTyped *initializedNode,
TIntermConstantUnion *arraySizeNode = CreateIndexNode(initializedNode->getOutermostArraySize());
TIntermBinary *indexSmallerThanSize =
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();
TIntermSequence *forLoopBodySeq = forLoopBody->getSequence();
......
......@@ -11,6 +11,7 @@
#include "compiler/translator/tree_ops/RemovePow.h"
#include "compiler/translator/InfoSink.h"
#include "compiler/translator/tree_util/IntermNode_util.h"
#include "compiler/translator/tree_util/IntermTraverse.h"
namespace sh
......@@ -34,7 +35,7 @@ bool IsProblematicPow(TIntermTyped *node)
class RemovePowTraverser : public TIntermTraverser
{
public:
RemovePowTraverser();
RemovePowTraverser(TSymbolTable *symbolTable);
bool visitAggregate(Visit visit, TIntermAggregate *node) override;
......@@ -45,8 +46,8 @@ class RemovePowTraverser : public TIntermTraverser
bool mNeedAnotherIteration;
};
RemovePowTraverser::RemovePowTraverser()
: TIntermTraverser(true, false, false), mNeedAnotherIteration(false)
RemovePowTraverser::RemovePowTraverser(TSymbolTable *symbolTable)
: TIntermTraverser(true, false, false, symbolTable), mNeedAnotherIteration(false)
{
}
......@@ -57,14 +58,18 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
TIntermTyped *x = node->getSequence()->at(0)->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());
TOperator op = TIntermBinary::GetMulOpBasedOnOperands(y->getType(), log->getType());
TIntermBinary *mul = new TIntermBinary(op, y, log);
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());
queueReplacement(exp, OriginalNode::IS_DROPPED);
......@@ -82,9 +87,9 @@ bool RemovePowTraverser::visitAggregate(Visit visit, TIntermAggregate *node)
} // 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.
do
{
......
......@@ -14,8 +14,9 @@
namespace sh
{
class TIntermNode;
class TSymbolTable;
void RemovePow(TIntermNode *root);
void RemovePow(TIntermNode *root, TSymbolTable *symbolTable);
} // namespace sh
#endif // COMPILER_TRANSLATOR_TREEOPS_REMOVEPOW_H_
......@@ -96,7 +96,7 @@ class DoWhileRewriter : public TIntermTraverser
breakBlock->getSequence()->push_back(breakStatement);
TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, loop->getCondition());
new TIntermUnary(EOpLogicalNot, loop->getCondition(), nullptr);
TIntermIfElse *innerIf = new TIntermIfElse(negatedCondition, breakBlock, nullptr);
......
......@@ -92,7 +92,8 @@ TIntermNode *ElseBlockRewriter::rewriteIfElse(TIntermIfElse *ifElse)
}
TIntermSymbol *conditionSymbolElse = CreateTempSymbolNode(conditionVariable);
TIntermUnary *negatedCondition = new TIntermUnary(EOpLogicalNot, conditionSymbolElse);
TIntermUnary *negatedCondition =
new TIntermUnary(EOpLogicalNot, conditionSymbolElse, nullptr);
TIntermIfElse *falseIfElse =
new TIntermIfElse(negatedCondition, ifElse->getFalseBlock(), negatedElse);
falseBlock = EnsureBlock(falseIfElse);
......
......@@ -75,7 +75,7 @@ bool Traverser::visitUnary(Visit visit, TIntermUnary *node)
// Potential problem case detected, apply workaround: -(int) -> ~(int) + 1.
// ~(int)
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr);
TIntermUnary *bitwiseNot = new TIntermUnary(EOpBitwiseNot, opr, nullptr);
bitwiseNot->setLine(opr->getLine());
// Constant 1 (or 1u)
......@@ -109,4 +109,4 @@ void RewriteUnaryMinusOperatorInt(TIntermNode *root)
Traverser::Apply(root);
}
} // namespace sh
\ No newline at end of file
} // namespace sh
......@@ -88,7 +88,7 @@ bool UnfoldShortCircuitTraverser::visitBinary(Visit visit, TIntermBinary *node)
CreateTempAssignmentNode(resultVariable, node->getRight()));
TIntermUnary *notTempSymbol =
new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable));
new TIntermUnary(EOpLogicalNot, CreateTempSymbolNode(resultVariable), nullptr);
TIntermIfElse *ifNode = new TIntermIfElse(notTempSymbol, assignRightBlock, nullptr);
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,
TOperator op = fn->getBuiltInOp();
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);
}
......
......@@ -196,7 +196,7 @@ TEST_F(IntermNodeTest, DeepCopyUnaryNode)
{
TType type(EbtFloat, EbpHigh);
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol());
TIntermUnary *original = new TIntermUnary(EOpPreIncrement, createTestSymbol(), nullptr);
original->setLine(getTestSourceLoc());
TIntermTyped *copyTyped = original->deepCopy();
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