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 @@
'compiler/translator/NodeSearch.h',
'compiler/translator/Operator.cpp',
'compiler/translator/Operator.h',
'compiler/translator/ParamType.h',
'compiler/translator/ParseContext.cpp',
'compiler/translator/ParseContext.h',
'compiler/translator/PoolAlloc.cpp',
......@@ -215,6 +216,7 @@
'compiler/translator/UniformHLSL.h',
'compiler/translator/UtilsHLSL.cpp',
'compiler/translator/UtilsHLSL.h',
'compiler/translator/emulated_builtin_functions_hlsl_autogen.cpp',
],
'angle_translator_lib_vulkan_sources':
[
......
......@@ -9,10 +9,82 @@
#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);
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 &);
//
// 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
......@@ -35,39 +107,6 @@ class BuiltInFunctionEmulator
// Output function emulation definition. This should be before any other shader source.
void outputEmulatedFunctions(TInfoSinkBase &out) const;
class FunctionId
{
public:
FunctionId();
FunctionId(TOperator op, const TType *param);
FunctionId(TOperator op, const TType *param1, const TType *param2);
FunctionId(TOperator op, const TType *param1, const TType *param2, const TType *param3);
FunctionId(TOperator op,
const TType *param1,
const TType *param2,
const TType *param3,
const TType *param4);
FunctionId(const FunctionId &) = default;
FunctionId &operator=(const FunctionId &) = default;
bool operator==(const FunctionId &other) const;
bool operator<(const FunctionId &other) const;
FunctionId getCopy() const;
private:
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;
};
// Add functions that need to be emulated.
FunctionId addEmulatedFunction(TOperator op,
const TType *param,
......@@ -88,12 +127,12 @@ class BuiltInFunctionEmulator
const TType *param4,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(FunctionId dependency,
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
const char *emulatedFunctionDefinition);
FunctionId addEmulatedFunctionWithDependency(FunctionId dependency,
FunctionId addEmulatedFunctionWithDependency(const FunctionId &dependency,
TOperator op,
const TType *param1,
const TType *param2,
......@@ -101,6 +140,8 @@ class BuiltInFunctionEmulator
const TType *param4,
const char *emulatedFunctionDefinition);
void addFunctionMap(BuiltinQueryFunc queryFunc);
private:
class BuiltInFunctionEmulationMarker;
......@@ -121,6 +162,8 @@ class BuiltInFunctionEmulator
bool setFunctionCalled(const FunctionId &functionId);
const char *findEmulatedFunction(const FunctionId &functionId) const;
// Map from function id to emulated function definition
std::map<FunctionId, std::string> mEmulatedFunctions;
......@@ -130,6 +173,9 @@ class BuiltInFunctionEmulator
// Called function ids
std::vector<FunctionId> mFunctions;
// Constexpr function tables.
std::vector<BuiltinQueryFunc *> mQueryFunctions;
};
} // 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