CompilerMSL options access and UBO alignment test case.
CompilerMSL accesses options using same design pattern as CompilerGLSL and CompilerHLSL. CompilerMSL support setting VA & rez binding specs via either constructor or compile() method overload. CompilerMSL support single UBO packing and padding in single pass. spriv_cross app (main.cpp) supports turning off UBO packing and padding via command line option. Add MSL UBO alignment test shader.
This commit is contained in:
parent
dc69427402
commit
5550c87b1f
9
main.cpp
9
main.cpp
@ -433,6 +433,7 @@ struct CLIArguments
|
||||
uint32_t iterations = 1;
|
||||
bool cpp = false;
|
||||
bool metal = false;
|
||||
bool msl_pack_ubos = true;
|
||||
bool hlsl = false;
|
||||
bool vulkan_semantics = false;
|
||||
bool remove_unused = false;
|
||||
@ -566,6 +567,7 @@ int main(int argc, char *argv[])
|
||||
cbs.add("--cpp", [&args](CLIParser &) { args.cpp = true; });
|
||||
cbs.add("--cpp-interface-name", [&args](CLIParser &parser) { args.cpp_interface_name = parser.next_string(); });
|
||||
cbs.add("--metal", [&args](CLIParser &) { args.metal = true; });
|
||||
cbs.add("--msl-no-pack-ubos", [&args](CLIParser &) { args.msl_pack_ubos = false; });
|
||||
cbs.add("--hlsl", [&args](CLIParser &) { args.hlsl = true; });
|
||||
cbs.add("--vulkan-semantics", [&args](CLIParser &) { args.vulkan_semantics = true; });
|
||||
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
|
||||
@ -631,7 +633,14 @@ int main(int argc, char *argv[])
|
||||
static_cast<CompilerCPP *>(compiler.get())->set_interface_name(args.cpp_interface_name);
|
||||
}
|
||||
else if (args.metal)
|
||||
{
|
||||
compiler = unique_ptr<CompilerMSL>(new CompilerMSL(read_spirv_file(args.input)));
|
||||
|
||||
auto *msl_comp = static_cast<CompilerMSL *>(compiler.get());
|
||||
auto msl_opts = msl_comp->get_options();
|
||||
msl_opts.pad_and_pack_uniform_structs = args.msl_pack_ubos;
|
||||
msl_comp->set_options(msl_opts);
|
||||
}
|
||||
else if (args.hlsl)
|
||||
compiler = unique_ptr<CompilerHLSL>(new CompilerHLSL(read_spirv_file(args.input)));
|
||||
else
|
||||
|
@ -10,7 +10,7 @@ struct UBO
|
||||
float2 B1;
|
||||
float C0;
|
||||
float3 C1;
|
||||
float3 D0;
|
||||
packed_float3 D0;
|
||||
float D1;
|
||||
float E0;
|
||||
float E1;
|
||||
@ -40,7 +40,7 @@ vertex main0_out main0(constant UBO& _22 [[buffer(0)]])
|
||||
out.oA = _22.A;
|
||||
out.oB = float4(_22.B0, _22.B1);
|
||||
out.oC = float4(_22.C0, _22.C1);
|
||||
out.oD = float4(_22.D0, _22.D1);
|
||||
out.oD = float4(float3(_22.D0), _22.D1);
|
||||
out.oE = float4(_22.E0, _22.E1, _22.E2, _22.E3);
|
||||
out.oF = float4(_22.F0, _22.F1, _22.F2);
|
||||
return out;
|
||||
|
39
reference/shaders-msl/vert/ubo.alignment.vert
Normal file
39
reference/shaders-msl/vert/ubo.alignment.vert
Normal file
@ -0,0 +1,39 @@
|
||||
#include <metal_stdlib>
|
||||
#include <simd/simd.h>
|
||||
|
||||
using namespace metal;
|
||||
|
||||
struct UBO
|
||||
{
|
||||
float4x4 mvp;
|
||||
float2 targSize;
|
||||
char pad2[8];
|
||||
packed_float3 color;
|
||||
float opacity;
|
||||
};
|
||||
|
||||
struct main0_in
|
||||
{
|
||||
float4 aVertex [[attribute(0)]];
|
||||
float3 aNormal [[attribute(1)]];
|
||||
};
|
||||
|
||||
struct main0_out
|
||||
{
|
||||
float2 vSize [[user(locn0)]];
|
||||
float3 vNormal [[user(locn1)]];
|
||||
float3 vColor [[user(locn2)]];
|
||||
float4 gl_Position [[position]];
|
||||
float gl_PointSize;
|
||||
};
|
||||
|
||||
vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _18 [[buffer(0)]])
|
||||
{
|
||||
main0_out out = {};
|
||||
out.gl_Position = _18.mvp * in.aVertex;
|
||||
out.vNormal = in.aNormal;
|
||||
out.vColor = float3(_18.color) * _18.opacity;
|
||||
out.vSize = _18.targSize * _18.opacity;
|
||||
return out;
|
||||
}
|
||||
|
23
shaders-msl/vert/ubo.alignment.vert
Normal file
23
shaders-msl/vert/ubo.alignment.vert
Normal file
@ -0,0 +1,23 @@
|
||||
#version 310 es
|
||||
|
||||
layout(binding = 0, std140) uniform UBO
|
||||
{
|
||||
mat4 mvp;
|
||||
vec2 targSize;
|
||||
vec3 color; // vec3 following vec2 should cause MSL to add pad if float3 is packed
|
||||
float opacity; // Single float following vec3 should cause MSL float3 to pack
|
||||
};
|
||||
|
||||
in vec4 aVertex;
|
||||
in vec3 aNormal;
|
||||
out vec3 vNormal;
|
||||
out vec3 vColor;
|
||||
out vec2 vSize;
|
||||
|
||||
void main()
|
||||
{
|
||||
gl_Position = mvp * aVertex;
|
||||
vNormal = aNormal;
|
||||
vColor = color * opacity;
|
||||
vSize = targSize * opacity;
|
||||
}
|
143
spirv_msl.cpp
143
spirv_msl.cpp
@ -27,13 +27,20 @@ using namespace std;
|
||||
|
||||
static const uint32_t k_unknown_location = ~0;
|
||||
|
||||
CompilerMSL::CompilerMSL(vector<uint32_t> spirv_)
|
||||
CompilerMSL::CompilerMSL(vector<uint32_t> spirv_, vector<MSLVertexAttr> *p_vtx_attrs,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings)
|
||||
: CompilerGLSL(move(spirv_))
|
||||
{
|
||||
options.vertex.fixup_clipspace = false;
|
||||
|
||||
populate_func_name_overrides();
|
||||
populate_var_name_overrides();
|
||||
|
||||
if (p_vtx_attrs)
|
||||
for (auto &va : *p_vtx_attrs)
|
||||
vtx_attrs_by_location[va.location] = &va;
|
||||
|
||||
if (p_res_bindings)
|
||||
for (auto &rb : *p_res_bindings)
|
||||
resource_bindings.push_back(&rb);
|
||||
}
|
||||
|
||||
// Populate the collection of function names that need to be overridden
|
||||
@ -49,32 +56,18 @@ void CompilerMSL::populate_var_name_overrides()
|
||||
var_name_overrides["bias"] = "bias0";
|
||||
}
|
||||
|
||||
string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_vtx_attrs,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings)
|
||||
string CompilerMSL::compile()
|
||||
{
|
||||
// Force a classic "C" locale, reverts when function returns
|
||||
ClassicLocale classic_locale;
|
||||
|
||||
// Remember the input parameters
|
||||
msl_config = msl_cfg;
|
||||
|
||||
// Set main function name if it was explicitly set
|
||||
if (!msl_config.entry_point_name.empty())
|
||||
set_name(entry_point, msl_config.entry_point_name);
|
||||
|
||||
vtx_attrs_by_location.clear();
|
||||
if (p_vtx_attrs)
|
||||
for (auto &va : *p_vtx_attrs)
|
||||
vtx_attrs_by_location[va.location] = &va;
|
||||
if (!options.entry_point_name.empty())
|
||||
set_name(entry_point, options.entry_point_name);
|
||||
|
||||
non_stage_in_input_var_ids.clear();
|
||||
struct_member_padding.clear();
|
||||
|
||||
resource_bindings.clear();
|
||||
if (p_res_bindings)
|
||||
for (auto &rb : *p_res_bindings)
|
||||
resource_bindings.push_back(&rb);
|
||||
|
||||
// Preprocess OpCodes to extract the need to output additional header content
|
||||
set_enabled_interface_variables(get_active_interface_variables());
|
||||
preprocess_op_codes();
|
||||
@ -90,8 +83,9 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
||||
extract_global_variables_from_functions();
|
||||
|
||||
// Do not deal with GLES-isms like precision, older extensions and such.
|
||||
options.es = false;
|
||||
options.version = 120;
|
||||
CompilerGLSL::options.es = false;
|
||||
CompilerGLSL::options.version = 120;
|
||||
CompilerGLSL::options.vertex.fixup_clipspace = false;
|
||||
backend.float_literal_suffix = false;
|
||||
backend.uint32_t_literal_suffix = true;
|
||||
backend.basic_int_type = "int";
|
||||
@ -125,10 +119,30 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
||||
return buffer->str();
|
||||
}
|
||||
|
||||
string CompilerMSL::compile()
|
||||
string CompilerMSL::compile(vector<MSLVertexAttr> *p_vtx_attrs, std::vector<MSLResourceBinding> *p_res_bindings)
|
||||
{
|
||||
MSLConfiguration default_msl_cfg;
|
||||
return compile(default_msl_cfg, nullptr, nullptr);
|
||||
if (p_vtx_attrs)
|
||||
{
|
||||
vtx_attrs_by_location.clear();
|
||||
for (auto &va : *p_vtx_attrs)
|
||||
vtx_attrs_by_location[va.location] = &va;
|
||||
}
|
||||
|
||||
if (p_res_bindings)
|
||||
{
|
||||
resource_bindings.clear();
|
||||
for (auto &rb : *p_res_bindings)
|
||||
resource_bindings.push_back(&rb);
|
||||
}
|
||||
|
||||
return compile();
|
||||
}
|
||||
|
||||
string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_vtx_attrs,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings)
|
||||
{
|
||||
options = msl_cfg;
|
||||
return compile(p_vtx_attrs, p_res_bindings);
|
||||
}
|
||||
|
||||
// Register the need to output any custom functions.
|
||||
@ -577,8 +591,10 @@ uint32_t CompilerMSL::get_input_buffer_block_var_id(uint32_t msl_buffer)
|
||||
return ib_var_id;
|
||||
}
|
||||
|
||||
// Sort the members of the struct type by offset, and pad & pack
|
||||
// members where needed to align MSL members with SPIR-V offsets.
|
||||
// Sort the members of the struct type by offset, and pack and then pad members where needed
|
||||
// to align MSL members with SPIR-V offsets. The struct members are iterated twice. Packing
|
||||
// occurs first, followed by padding, because packing a member reduces both its size and its
|
||||
// natural alignment, possibly requiring a padding member to be added ahead of it.
|
||||
void CompilerMSL::align_struct(SPIRType &ib_type)
|
||||
{
|
||||
uint32_t &ib_type_id = ib_type.self;
|
||||
@ -590,42 +606,51 @@ void CompilerMSL::align_struct(SPIRType &ib_type)
|
||||
|
||||
uint32_t curr_offset = 0;
|
||||
uint32_t mbr_cnt = uint32_t(ib_type.member_types.size());
|
||||
|
||||
// Test the alignment of each member, and if a member should be closer to the previous
|
||||
// member than the default spacing expects, it is likely that the previous member is in
|
||||
// a packed format. If so, and the previous member is packable, pack it.
|
||||
// For example...this applies to any 3-element vector that is followed by a scalar.
|
||||
for (uint32_t mbr_idx = 0; mbr_idx < mbr_cnt; mbr_idx++)
|
||||
{
|
||||
// Align current offset to the current member's default alignment.
|
||||
size_t align_mask = get_declared_struct_member_alignment(ib_type, mbr_idx) - 1;
|
||||
curr_offset = uint32_t((curr_offset + align_mask) & ~align_mask);
|
||||
|
||||
// Test member alignment and, if it needs to be adjusted, depending on which direction,
|
||||
// either pad the current member by adding a dummy padding member that will be declared
|
||||
// before the current member, or mark the previous member as packed, so that it will
|
||||
// consume less space, and the current member can move forward.
|
||||
// There is a situation where, in packing the previous member, the alignment of
|
||||
// that member will change, necessitating the addition of a padding member before it.
|
||||
// This is taken care of automatically because this compiler is multipass. The first
|
||||
// pass will mark the packed member, and the second pass will insert a padding member.
|
||||
// If we ever move to a single-pass design, this will break.
|
||||
// Fetch the member offset as declared in the SPIRV.
|
||||
uint32_t mbr_offset = get_member_decoration(ib_type_id, mbr_idx, DecorationOffset);
|
||||
int32_t gap = (int32_t)mbr_offset - (int32_t)curr_offset;
|
||||
if (gap > 0)
|
||||
if (curr_offset > mbr_offset)
|
||||
{
|
||||
// Since MSL and SPIR-V have slightly different struct member alignment and
|
||||
// size rules, we'll pad to standard C-packing rules. If the member is farther
|
||||
// away than C-packing, expects, add an inert padding member before the the member.
|
||||
MSLStructMemberKey key = get_struct_member_key(ib_type_id, mbr_idx);
|
||||
struct_member_padding[key] = gap;
|
||||
}
|
||||
else if (gap < 0)
|
||||
{
|
||||
// If this member should be closer to the previous member than the default
|
||||
// spacing expects, it is likely that the previous member is in a packed format.
|
||||
// If so, and the previous member is packable, pack it.
|
||||
// For example...this applies to any 3-element packed vector.
|
||||
uint32_t prev_mbr_idx = mbr_idx - 1;
|
||||
if (is_member_packable(ib_type, prev_mbr_idx))
|
||||
set_member_decoration(ib_type_id, prev_mbr_idx, DecorationCPacked);
|
||||
}
|
||||
|
||||
// Increment the current offset to be positioned immediately after the current member.
|
||||
curr_offset = mbr_offset + uint32_t(get_declared_struct_member_size(ib_type, mbr_idx));
|
||||
}
|
||||
|
||||
// Test the alignment of each member, and if a member is positioned farther than its
|
||||
// alignment and the end of the previous member, add a dummy padding member that will
|
||||
// be added before the current member when the delaration of this struct is emitted.
|
||||
for (uint32_t mbr_idx = 0; mbr_idx < mbr_cnt; mbr_idx++)
|
||||
{
|
||||
// Align current offset to the current member's default alignment.
|
||||
size_t align_mask = get_declared_struct_member_alignment(ib_type, mbr_idx) - 1;
|
||||
curr_offset = uint32_t((curr_offset + align_mask) & ~align_mask);
|
||||
|
||||
// Fetch the member offset as declared in the SPIRV.
|
||||
uint32_t mbr_offset = get_member_decoration(ib_type_id, mbr_idx, DecorationOffset);
|
||||
if (mbr_offset > curr_offset)
|
||||
{
|
||||
// Since MSL and SPIR-V have slightly different struct member alignment and
|
||||
// size rules, we'll pad to standard C-packing rules. If the member is farther
|
||||
// away than C-packing, expects, add an inert padding member before the the member.
|
||||
MSLStructMemberKey key = get_struct_member_key(ib_type_id, mbr_idx);
|
||||
struct_member_padding[key] = mbr_offset - curr_offset;
|
||||
}
|
||||
|
||||
// Increment the current offset to be positioned immediately after the current member.
|
||||
curr_offset = mbr_offset + uint32_t(get_declared_struct_member_size(ib_type, mbr_idx));
|
||||
}
|
||||
}
|
||||
@ -733,7 +758,7 @@ void CompilerMSL::emit_resources()
|
||||
(has_decoration(type.self, DecorationBlock) || has_decoration(type.self, DecorationBufferBlock)) &&
|
||||
!is_hidden_variable(var))
|
||||
{
|
||||
if (msl_config.pad_and_pack_uniform_structs)
|
||||
if (options.pad_and_pack_uniform_structs)
|
||||
align_struct(type);
|
||||
|
||||
emit_struct(type);
|
||||
@ -1028,7 +1053,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
break;
|
||||
|
||||
case Dim2D:
|
||||
if (msl_config.flip_frag_y)
|
||||
if (options.flip_frag_y)
|
||||
{
|
||||
string coord_x = coord_expr + ".x";
|
||||
string coord_y = coord_expr + ".y";
|
||||
@ -1051,7 +1076,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
break;
|
||||
|
||||
case Dim3D:
|
||||
if (msl_config.flip_frag_y)
|
||||
if (options.flip_frag_y)
|
||||
{
|
||||
string coord_x = coord_expr + ".x";
|
||||
string coord_y = coord_expr + ".y";
|
||||
@ -1075,7 +1100,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
break;
|
||||
|
||||
case DimCube:
|
||||
if (msl_config.flip_frag_y)
|
||||
if (options.flip_frag_y)
|
||||
{
|
||||
string coord_x = coord_expr + ".x";
|
||||
string coord_y = coord_expr + ".y";
|
||||
@ -1196,7 +1221,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
switch (imgtype.image.dim)
|
||||
{
|
||||
case Dim2D:
|
||||
if (msl_config.flip_frag_y)
|
||||
if (options.flip_frag_y)
|
||||
{
|
||||
string coord_x = offset_expr + ".x";
|
||||
string coord_y = offset_expr + ".y";
|
||||
@ -1212,7 +1237,7 @@ string CompilerMSL::to_function_args(uint32_t img, const SPIRType &imgtype, bool
|
||||
break;
|
||||
|
||||
case Dim3D:
|
||||
if (msl_config.flip_frag_y)
|
||||
if (options.flip_frag_y)
|
||||
{
|
||||
string coord_x = offset_expr + ".x";
|
||||
string coord_y = offset_expr + ".y";
|
||||
@ -1321,13 +1346,13 @@ void CompilerMSL::emit_fixup()
|
||||
|
||||
if ((execution.model == ExecutionModelVertex) && stage_out_var_id && !qual_pos_var_name.empty())
|
||||
{
|
||||
if (options.vertex.fixup_clipspace)
|
||||
if (CompilerGLSL::options.vertex.fixup_clipspace)
|
||||
{
|
||||
statement(qual_pos_var_name, ".z = (", qual_pos_var_name, ".z + ", qual_pos_var_name,
|
||||
".w) * 0.5; // Adjust clip-space for Metal");
|
||||
}
|
||||
|
||||
if (msl_config.flip_vert_y)
|
||||
if (options.flip_vert_y)
|
||||
statement(qual_pos_var_name, ".y = -(", qual_pos_var_name, ".y);", " // Invert Y-axis for Metal");
|
||||
}
|
||||
}
|
||||
@ -1392,7 +1417,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
|
||||
return " /* [[clip_distance]] built-in not yet supported under Metal. */";
|
||||
|
||||
case BuiltInPointSize: // Must output only if really rendering points
|
||||
return msl_config.is_rendering_points ? (string(" [[") + builtin_qualifier(builtin) + "]]") : "";
|
||||
return options.is_rendering_points ? (string(" [[") + builtin_qualifier(builtin) + "]]") : "";
|
||||
|
||||
case BuiltInPosition:
|
||||
case BuiltInLayer:
|
||||
|
@ -27,15 +27,8 @@
|
||||
namespace spirv_cross
|
||||
{
|
||||
|
||||
// Options for compiling to Metal Shading Language
|
||||
struct MSLConfiguration
|
||||
{
|
||||
bool flip_vert_y = false;
|
||||
bool flip_frag_y = false;
|
||||
bool is_rendering_points = false;
|
||||
bool pad_and_pack_uniform_structs = false;
|
||||
std::string entry_point_name;
|
||||
};
|
||||
// Deprecated legacy syntax
|
||||
#define MSLConfiguration CompilerMSL::Options
|
||||
|
||||
// Defines MSL characteristics of a vertex attribute at a particular location.
|
||||
// The used_by_shader flag is set to true during compilation of SPIR-V to MSL
|
||||
@ -83,11 +76,28 @@ static const uint32_t kPushConstBinding = 0;
|
||||
class CompilerMSL : public CompilerGLSL
|
||||
{
|
||||
public:
|
||||
// Constructs an instance to compile the SPIR-V code into Metal Shading Language.
|
||||
CompilerMSL(std::vector<uint32_t> spirv);
|
||||
// Options for compiling to Metal Shading Language
|
||||
struct Options
|
||||
{
|
||||
bool flip_vert_y = false;
|
||||
bool flip_frag_y = false;
|
||||
bool is_rendering_points = false;
|
||||
bool pad_and_pack_uniform_structs = false;
|
||||
std::string entry_point_name;
|
||||
};
|
||||
|
||||
// Compiles the SPIR-V code into Metal Shading Language using the specified configuration parameters.
|
||||
// - msl_cfg indicates some general configuration for directing the compilation.
|
||||
const Options &get_options() const
|
||||
{
|
||||
return options;
|
||||
}
|
||||
|
||||
void set_options(Options &opts)
|
||||
{
|
||||
options = opts;
|
||||
}
|
||||
|
||||
// Constructs an instance to compile the SPIR-V code into Metal Shading Language,
|
||||
// using the configuration parameters, if provided:
|
||||
// - p_vtx_attrs is an optional list of vertex attribute bindings used to match
|
||||
// vertex content locations to MSL attributes. If vertex attributes are provided,
|
||||
// the compiler will set the used_by_shader flag to true in any vertex attribute
|
||||
@ -96,12 +106,22 @@ public:
|
||||
// texture or sampler index to use for a particular SPIR-V description set
|
||||
// and binding. If resource bindings are provided, the compiler will set the
|
||||
// used_by_shader flag to true in any resource binding actually used by the MSL code.
|
||||
CompilerMSL(std::vector<uint32_t> spirv, std::vector<MSLVertexAttr> *p_vtx_attrs = nullptr,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings = nullptr);
|
||||
|
||||
// Compiles the SPIR-V code into Metal Shading Language.
|
||||
std::string compile() override;
|
||||
|
||||
// Compiles the SPIR-V code into Metal Shading Language, overriding configuration parameters.
|
||||
// Any of the parameters here may be null to indicate that the configuration provided in the
|
||||
// constructor should be used. They are not declared as optional to avoid a conflict with the
|
||||
// inherited and overridden zero-parameter compile() function.
|
||||
std::string compile(std::vector<MSLVertexAttr> *p_vtx_attrs, std::vector<MSLResourceBinding> *p_res_bindings);
|
||||
|
||||
// This legacy method is deprecated.
|
||||
std::string compile(MSLConfiguration &msl_cfg, std::vector<MSLVertexAttr> *p_vtx_attrs = nullptr,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings = nullptr);
|
||||
|
||||
// Compiles the SPIR-V code into Metal Shading Language using default configuration parameters.
|
||||
std::string compile() override;
|
||||
|
||||
protected:
|
||||
void emit_instruction(const Instruction &instr) override;
|
||||
void emit_glsl_op(uint32_t result_type, uint32_t result_id, uint32_t op, const uint32_t *args,
|
||||
@ -174,7 +194,7 @@ protected:
|
||||
bool is_member_packable(SPIRType &ib_type, uint32_t index);
|
||||
MSLStructMemberKey get_struct_member_key(uint32_t type_id, uint32_t index);
|
||||
|
||||
MSLConfiguration msl_config;
|
||||
Options options;
|
||||
std::unordered_map<std::string, std::string> func_name_overrides;
|
||||
std::unordered_map<std::string, std::string> var_name_overrides;
|
||||
std::set<uint32_t> custom_function_ops;
|
||||
|
Loading…
Reference in New Issue
Block a user