Commit 35bcad42 by Jamie Madill Committed by Commit Bot

Optimize builtin function emulator class.

This refactor uses a generator to produce static arrays instead of using a bunch of std::map inserting statements. It speeds up shader translation because every shader compile would create and tear down this table. Currently it is implemented as a flat array, but in the future we could use compile-time hashing to implement faster lookup. BUG=chromium:697758 Change-Id: I689f7de4d9b2c8c76095bb313f4c040116fc61d2 Reviewed-on: https://chromium-review.googlesource.com/521226 Commit-Queue: Jamie Madill <jmadill@chromium.org> Reviewed-by: 's avatarCorentin Wallez <cwallez@chromium.org> Reviewed-by: 's avatarOlli Etuaho <oetuaho@nvidia.com>
parent a71a98ee
...@@ -78,6 +78,7 @@ ...@@ -78,6 +78,7 @@
'compiler/translator/NodeSearch.h', 'compiler/translator/NodeSearch.h',
'compiler/translator/Operator.cpp', 'compiler/translator/Operator.cpp',
'compiler/translator/Operator.h', 'compiler/translator/Operator.h',
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp', 'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h', 'compiler/translator/ParseContext.h',
'compiler/translator/PoolAlloc.cpp', 'compiler/translator/PoolAlloc.cpp',
...@@ -215,6 +216,7 @@ ...@@ -215,6 +216,7 @@
'compiler/translator/UniformHLSL.h', 'compiler/translator/UniformHLSL.h',
'compiler/translator/UtilsHLSL.cpp', 'compiler/translator/UtilsHLSL.cpp',
'compiler/translator/UtilsHLSL.h', 'compiler/translator/UtilsHLSL.h',
'compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp',
], ],
'angle_translator_lib_vulkan_sources': 'angle_translator_lib_vulkan_sources':
[ [
......
...@@ -95,8 +95,7 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator() ...@@ -95,8 +95,7 @@ BuiltInFunctionEmulator::BuiltInFunctionEmulator()
{ {
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction( FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
TOperator op,
const TType *param, const TType *param,
const char *emulatedFunctionDefinition) const char *emulatedFunctionDefinition)
{ {
...@@ -105,8 +104,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction ...@@ -105,8 +104,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction
return id; return id;
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction( FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
const char *emulatedFunctionDefinition) const char *emulatedFunctionDefinition)
...@@ -116,8 +114,8 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction ...@@ -116,8 +114,8 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction
return id; return id;
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
FunctionId dependency, const FunctionId &dependency,
TOperator op, TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
...@@ -129,8 +127,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction ...@@ -129,8 +127,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction
return id; return id;
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction( FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
const TType *param3, const TType *param3,
...@@ -141,8 +138,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction ...@@ -141,8 +138,7 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction
return id; return id;
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction( FunctionId BuiltInFunctionEmulator::addEmulatedFunction(TOperator op,
TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
const TType *param3, const TType *param3,
...@@ -154,8 +150,8 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction ...@@ -154,8 +150,8 @@ BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunction
return id; return id;
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency( FunctionId BuiltInFunctionEmulator::addEmulatedFunctionWithDependency(
FunctionId dependency, const FunctionId &dependency,
TOperator op, TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
...@@ -176,9 +172,12 @@ bool BuiltInFunctionEmulator::isOutputEmpty() const ...@@ -176,9 +172,12 @@ bool BuiltInFunctionEmulator::isOutputEmpty() const
void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const void BuiltInFunctionEmulator::outputEmulatedFunctions(TInfoSinkBase &out) const
{ {
for (size_t i = 0; i < mFunctions.size(); ++i) for (const auto &function : mFunctions)
{ {
out << mEmulatedFunctions.find(mFunctions[i])->second << "\n\n"; const char *body = findEmulatedFunction(function);
ASSERT(body);
out << body;
out << "\n\n";
} }
} }
...@@ -211,10 +210,33 @@ bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op, ...@@ -211,10 +210,33 @@ bool BuiltInFunctionEmulator::setFunctionCalled(TOperator op,
return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4)); return setFunctionCalled(FunctionId(op, &param1, &param2, &param3, &param4));
} }
const char *BuiltInFunctionEmulator::findEmulatedFunction(const FunctionId &functionId) const
{
for (const auto &queryFunction : mQueryFunctions)
{
const char *result = queryFunction(functionId);
if (result)
{
return result;
}
}
const auto &result = mEmulatedFunctions.find(functionId);
if (result != mEmulatedFunctions.end())
{
return result->second.c_str();
}
return nullptr;
}
bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
{ {
if (mEmulatedFunctions.find(functionId) != mEmulatedFunctions.end()) if (!findEmulatedFunction(functionId))
{ {
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] == functionId)
...@@ -230,15 +252,13 @@ bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId) ...@@ -230,15 +252,13 @@ bool BuiltInFunctionEmulator::setFunctionCalled(const FunctionId &functionId)
// remain valid and constant. // remain valid and constant.
mFunctions.push_back(functionId.getCopy()); mFunctions.push_back(functionId.getCopy());
return true; return true;
}
return false;
} }
void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root) void BuiltInFunctionEmulator::markBuiltInFunctionsForEmulation(TIntermNode *root)
{ {
ASSERT(root); ASSERT(root);
if (mEmulatedFunctions.empty()) if (mEmulatedFunctions.empty() && mQueryFunctions.empty())
return; return;
BuiltInFunctionEmulationMarker marker(*this); BuiltInFunctionEmulationMarker marker(*this);
...@@ -251,6 +271,11 @@ void BuiltInFunctionEmulator::cleanup() ...@@ -251,6 +271,11 @@ void BuiltInFunctionEmulator::cleanup()
mFunctionDependencies.clear(); mFunctionDependencies.clear();
} }
void BuiltInFunctionEmulator::addFunctionMap(BuiltinQueryFunc queryFunc)
{
mQueryFunctions.push_back(queryFunc);
}
// static // static
void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name) void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name)
{ {
...@@ -258,7 +283,7 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons ...@@ -258,7 +283,7 @@ void BuiltInFunctionEmulator::WriteEmulatedFunctionName(TInfoSinkBase &out, cons
out << "webgl_" << name << "_emu"; out << "webgl_" << name << "_emu";
} }
BuiltInFunctionEmulator::FunctionId::FunctionId() FunctionId::FunctionId()
: mOp(EOpNull), : mOp(EOpNull),
mParam1(TCache::getType(EbtVoid)), mParam1(TCache::getType(EbtVoid)),
mParam2(TCache::getType(EbtVoid)), mParam2(TCache::getType(EbtVoid)),
...@@ -267,7 +292,7 @@ BuiltInFunctionEmulator::FunctionId::FunctionId() ...@@ -267,7 +292,7 @@ BuiltInFunctionEmulator::FunctionId::FunctionId()
{ {
} }
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param) FunctionId::FunctionId(TOperator op, const TType *param)
: mOp(op), : mOp(op),
mParam1(param), mParam1(param),
mParam2(TCache::getType(EbtVoid)), mParam2(TCache::getType(EbtVoid)),
...@@ -276,9 +301,7 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param ...@@ -276,9 +301,7 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, const TType *param
{ {
} }
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2)
const TType *param1,
const TType *param2)
: mOp(op), : mOp(op),
mParam1(param1), mParam1(param1),
mParam2(param2), mParam2(param2),
...@@ -287,15 +310,12 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, ...@@ -287,15 +310,12 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
{ {
} }
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, FunctionId::FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3)
const TType *param1,
const TType *param2,
const TType *param3)
: mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid)) : mOp(op), mParam1(param1), mParam2(param2), mParam3(param3), mParam4(TCache::getType(EbtVoid))
{ {
} }
BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, FunctionId::FunctionId(TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
const TType *param3, const TType *param3,
...@@ -304,15 +324,13 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op, ...@@ -304,15 +324,13 @@ BuiltInFunctionEmulator::FunctionId::FunctionId(TOperator op,
{ {
} }
bool BuiltInFunctionEmulator::FunctionId::operator==( bool FunctionId::operator==(const FunctionId &other) const
const BuiltInFunctionEmulator::FunctionId &other) const
{ {
return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 && return (mOp == other.mOp && *mParam1 == *other.mParam1 && *mParam2 == *other.mParam2 &&
*mParam3 == *other.mParam3 && *mParam4 == *other.mParam4); *mParam3 == *other.mParam3 && *mParam4 == *other.mParam4);
} }
bool BuiltInFunctionEmulator::FunctionId::operator<( bool FunctionId::operator<(const FunctionId &other) const
const BuiltInFunctionEmulator::FunctionId &other) const
{ {
if (mOp != other.mOp) if (mOp != other.mOp)
return mOp < other.mOp; return mOp < other.mOp;
...@@ -327,7 +345,7 @@ bool BuiltInFunctionEmulator::FunctionId::operator<( ...@@ -327,7 +345,7 @@ bool BuiltInFunctionEmulator::FunctionId::operator<(
return false; // all fields are equal return false; // all fields are equal
} }
BuiltInFunctionEmulator::FunctionId BuiltInFunctionEmulator::FunctionId::getCopy() const FunctionId FunctionId::getCopy() const
{ {
return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3), return FunctionId(mOp, new TType(*mParam1), new TType(*mParam2), new TType(*mParam3),
new TType(*mParam4)); new TType(*mParam4));
......
...@@ -9,34 +9,35 @@ ...@@ -9,34 +9,35 @@
#include "compiler/translator/InfoSink.h" #include "compiler/translator/InfoSink.h"
#include "compiler/translator/IntermNode.h" #include "compiler/translator/IntermNode.h"
#include "compiler/translator/ParamType.h"
namespace sh namespace sh
{ {
// struct MiniFunctionId
// This class decides which built-in functions need to be replaced with the emulated ones. It can be
// used to work around driver bugs or implement functions that are not natively implemented on a
// specific platform.
//
class BuiltInFunctionEmulator
{ {
public: constexpr MiniFunctionId(TOperator op = EOpNull,
BuiltInFunctionEmulator(); ParamType paramType1 = ParamType::Void,
ParamType paramType2 = ParamType::Void,
void markBuiltInFunctionsForEmulation(TIntermNode *root); ParamType paramType3 = ParamType::Void,
ParamType paramType4 = ParamType::Void)
void cleanup(); : op(op),
paramType1(paramType1),
// "name" gets written as "webgl_name_emu". paramType2(paramType2),
static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name); paramType3(paramType3),
paramType4(paramType4)
bool isOutputEmpty() const; {
}
// Output function emulation definition. This should be before any other shader source. TOperator op;
void outputEmulatedFunctions(TInfoSinkBase &out) const; ParamType paramType1;
ParamType paramType2;
ParamType paramType3;
ParamType paramType4;
};
class FunctionId class FunctionId final
{ {
public: public:
FunctionId(); FunctionId();
FunctionId(TOperator op, const TType *param); FunctionId(TOperator op, const TType *param);
...@@ -57,6 +58,7 @@ class BuiltInFunctionEmulator ...@@ -57,6 +58,7 @@ class BuiltInFunctionEmulator
FunctionId getCopy() const; FunctionId getCopy() const;
private: private:
friend bool operator==(const MiniFunctionId &miniId, const FunctionId &functionId);
TOperator mOp; TOperator mOp;
// The memory that these TType objects use is freed by PoolAllocator. The // The memory that these TType objects use is freed by PoolAllocator. The
...@@ -66,7 +68,44 @@ class BuiltInFunctionEmulator ...@@ -66,7 +68,44 @@ class BuiltInFunctionEmulator
const TType *mParam2; const TType *mParam2;
const TType *mParam3; const TType *mParam3;
const TType *mParam4; 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
// used to work around driver bugs or implement functions that are not natively implemented on a
// specific platform.
//
class BuiltInFunctionEmulator
{
public:
BuiltInFunctionEmulator();
void markBuiltInFunctionsForEmulation(TIntermNode *root);
void cleanup();
// "name" gets written as "webgl_name_emu".
static void WriteEmulatedFunctionName(TInfoSinkBase &out, const char *name);
bool isOutputEmpty() const;
// Output function emulation definition. This should be before any other shader source.
void outputEmulatedFunctions(TInfoSinkBase &out) const;
// Add functions that need to be emulated. // Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op, FunctionId addEmulatedFunction(TOperator op,
...@@ -88,12 +127,12 @@ class BuiltInFunctionEmulator ...@@ -88,12 +127,12 @@ class BuiltInFunctionEmulator
const TType *param4, const TType *param4,
const char *emulatedFunctionDefinition); const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(FunctionId dependency, FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op, TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
const char *emulatedFunctionDefinition); const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(FunctionId dependency, FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op, TOperator op,
const TType *param1, const TType *param1,
const TType *param2, const TType *param2,
...@@ -101,6 +140,8 @@ class BuiltInFunctionEmulator ...@@ -101,6 +140,8 @@ class BuiltInFunctionEmulator
const TType *param4, const TType *param4,
const char *emulatedFunctionDefinition); const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc);
private: private:
class BuiltInFunctionEmulationMarker; class BuiltInFunctionEmulationMarker;
...@@ -121,6 +162,8 @@ class BuiltInFunctionEmulator ...@@ -121,6 +162,8 @@ class BuiltInFunctionEmulator
bool setFunctionCalled(const FunctionId &functionId); bool setFunctionCalled(const FunctionId &functionId);
const char *findEmulatedFunction(const FunctionId &functionId) const;
// Map from function id to emulated function definition // Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions; std::map<FunctionId, std::string> mEmulatedFunctions;
...@@ -130,6 +173,9 @@ class BuiltInFunctionEmulator ...@@ -130,6 +173,9 @@ class BuiltInFunctionEmulator
// Called function ids // Called function ids
std::vector<FunctionId> mFunctions; std::vector<FunctionId> mFunctions;
// Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions;
}; };
} // namespace sh } // namespace sh
......
//
// 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_
#!/usr/bin/python
# 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.
#
# gen_emulated_builtin_function_tables.py:
# Generator for the builtin function maps.
from datetime import date
import json
import os, sys
template_emulated_builtin_functions_hlsl = """// GENERATED FILE - DO NOT EDIT.
// Generated by {script_name} using data from {data_source_name}.
//
// Copyright {copyright_year} 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.
//
// emulated_builtin_functions_hlsl:
// HLSL code for emulating GLSL builtin functions not present in HLSL.
#include "compiler/translator/BuiltInFunctionEmulator.h"
namespace sh
{{
namespace
{{
constexpr std::pair<MiniFunctionId, const char *> g_hlslFunctions[] = {{
{emulated_functions}}};
}} // anonymous namespace
const char *FindHLSLFunction(const FunctionId &functionID)
{{
for (size_t index = 0; index < ArraySize(g_hlslFunctions); ++index)
{{
const auto &function = g_hlslFunctions[index];
if (function.first == functionID)
{{
return function.second;
}}
}}
return nullptr;
}}
}} // namespace sh
"""
def reject_duplicate_keys(pairs):
found_keys = {}
for key, value in pairs:
if key in found_keys:
raise ValueError("duplicate key: %r" % (key,))
else:
found_keys[key] = value
return found_keys
def load_json(path):
with open(path) as map_file:
file_data = map_file.read()
map_file.close()
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:]
input_script = "emulated_builtin_function_data_hlsl.json"
hlsl_json = load_json(input_script)
emulated_functions = []
def gen_emulated_function(data):
func = ""
if 'comment' in data:
func += "".join([ "// " + line + "\n" for line in data['comment'] ])
sig = data['return_type'] + ' webgl_' + data['op'] + '_emu(' + ', '.join(data['args']) + ')'
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"
if 'helper' in data:
func += '"' + '\\n"\n"'.join(data['helper']) + '\\n"\n'
func += '"' + '\\n"\n"'.join(body) + '\\n"\n'
func += "},\n"
return [ func ]
for item in hlsl_json:
emulated_functions += gen_emulated_function(item)
hlsl_fname = "emulated_builtin_functions_hlsl_autogen.cpp"
hlsl_gen = template_emulated_builtin_functions_hlsl.format(
script_name = sys.argv[0],
data_source_name = input_script,
copyright_year = date.today().year,
emulated_functions = "".join(emulated_functions))
with open(hlsl_fname, 'wt') as f:
f.write(hlsl_gen)
f.close()
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