Merge branch 'master' of https://github.com/KhronosGroup/SPIRV-Cross
This commit is contained in:
commit
804d5313fa
@ -26,7 +26,6 @@ vertex main0_out main0(main0_in in [[stage_in]], constant UBO& _16 [[buffer(0)]]
|
|||||||
main0_out out = {};
|
main0_out out = {};
|
||||||
out.gl_Position = _16.uMVP * in.aVertex;
|
out.gl_Position = _16.uMVP * in.aVertex;
|
||||||
out.vNormal = in.aNormal;
|
out.vNormal = in.aNormal;
|
||||||
out.gl_Position.y = -(out.gl_Position.y); // Invert Y-axis for Metal
|
|
||||||
return out;
|
return out;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -2397,8 +2397,10 @@ SPIREntryPoint &Compiler::get_entry_point()
|
|||||||
bool Compiler::interface_variable_exists_in_entry_point(uint32_t id) const
|
bool Compiler::interface_variable_exists_in_entry_point(uint32_t id) const
|
||||||
{
|
{
|
||||||
auto &var = get<SPIRVariable>(id);
|
auto &var = get<SPIRVariable>(id);
|
||||||
if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
|
if (var.storage != StorageClassInput && var.storage != StorageClassOutput &&
|
||||||
SPIRV_CROSS_THROW("Only Input and Output variables are part of a shader linking interface.");
|
var.storage != StorageClassUniformConstant)
|
||||||
|
throw CompilerError(
|
||||||
|
"Only Input, Output variables and Uniform constants are part of a shader linking interface.");
|
||||||
|
|
||||||
// This is to avoid potential problems with very old glslang versions which did
|
// This is to avoid potential problems with very old glslang versions which did
|
||||||
// not emit input/output interfaces properly.
|
// not emit input/output interfaces properly.
|
||||||
|
@ -29,6 +29,7 @@ CompilerMSL::CompilerMSL(vector<uint32_t> spirv_)
|
|||||||
options.vertex.fixup_clipspace = false;
|
options.vertex.fixup_clipspace = false;
|
||||||
|
|
||||||
populate_func_name_overrides();
|
populate_func_name_overrides();
|
||||||
|
populate_var_name_overrides();
|
||||||
}
|
}
|
||||||
|
|
||||||
// Populate the collection of function names that need to be overridden
|
// Populate the collection of function names that need to be overridden
|
||||||
@ -38,6 +39,12 @@ void CompilerMSL::populate_func_name_overrides()
|
|||||||
func_name_overrides["saturate"] = "saturate0";
|
func_name_overrides["saturate"] = "saturate0";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CompilerMSL::populate_var_name_overrides()
|
||||||
|
{
|
||||||
|
var_name_overrides["kernel"] = "kernel0";
|
||||||
|
var_name_overrides["bias"] = "bias0";
|
||||||
|
}
|
||||||
|
|
||||||
string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_vtx_attrs,
|
string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_vtx_attrs,
|
||||||
std::vector<MSLResourceBinding> *p_res_bindings)
|
std::vector<MSLResourceBinding> *p_res_bindings)
|
||||||
{
|
{
|
||||||
@ -47,6 +54,10 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
|||||||
// Remember the input parameters
|
// Remember the input parameters
|
||||||
msl_config = msl_cfg;
|
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();
|
vtx_attrs_by_location.clear();
|
||||||
if (p_vtx_attrs)
|
if (p_vtx_attrs)
|
||||||
for (auto &va : *p_vtx_attrs)
|
for (auto &va : *p_vtx_attrs)
|
||||||
@ -61,10 +72,11 @@ string CompilerMSL::compile(MSLConfiguration &msl_cfg, vector<MSLVertexAttr> *p_
|
|||||||
set_enabled_interface_variables(get_active_interface_variables());
|
set_enabled_interface_variables(get_active_interface_variables());
|
||||||
preprocess_op_codes();
|
preprocess_op_codes();
|
||||||
|
|
||||||
// Create structs to hold input and output variables
|
// Create structs to hold input, output and uniform variables
|
||||||
qual_pos_var_name = "";
|
qual_pos_var_name = "";
|
||||||
stage_in_var_id = add_interface_block(StorageClassInput);
|
stage_in_var_id = add_interface_block(StorageClassInput);
|
||||||
stage_out_var_id = add_interface_block(StorageClassOutput);
|
stage_out_var_id = add_interface_block(StorageClassOutput);
|
||||||
|
stage_uniforms_var_id = add_interface_block(StorageClassUniformConstant);
|
||||||
|
|
||||||
// Convert the use of global variables to recursively-passed function parameters
|
// Convert the use of global variables to recursively-passed function parameters
|
||||||
localize_global_variables();
|
localize_global_variables();
|
||||||
@ -158,9 +170,16 @@ void CompilerMSL::extract_global_variables_from_functions()
|
|||||||
auto &var = id.get<SPIRVariable>();
|
auto &var = id.get<SPIRVariable>();
|
||||||
if (var.storage == StorageClassInput || var.storage == StorageClassUniform ||
|
if (var.storage == StorageClassInput || var.storage == StorageClassUniform ||
|
||||||
var.storage == StorageClassUniformConstant || var.storage == StorageClassPushConstant)
|
var.storage == StorageClassUniformConstant || var.storage == StorageClassPushConstant)
|
||||||
|
{
|
||||||
global_var_ids.insert(var.self);
|
global_var_ids.insert(var.self);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Local vars that are declared in the main function and accessed directy by a function
|
||||||
|
auto &entry_func = get<SPIRFunction>(entry_point);
|
||||||
|
for (auto &var : entry_func.local_variables)
|
||||||
|
global_var_ids.insert(var);
|
||||||
|
|
||||||
std::unordered_set<uint32_t> added_arg_ids;
|
std::unordered_set<uint32_t> added_arg_ids;
|
||||||
std::unordered_set<uint32_t> processed_func_ids;
|
std::unordered_set<uint32_t> processed_func_ids;
|
||||||
@ -176,7 +195,11 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
|||||||
{
|
{
|
||||||
// Avoid processing a function more than once
|
// Avoid processing a function more than once
|
||||||
if (processed_func_ids.find(func_id) != processed_func_ids.end())
|
if (processed_func_ids.find(func_id) != processed_func_ids.end())
|
||||||
|
{
|
||||||
|
// Return function global variables
|
||||||
|
added_arg_ids = function_global_vars[func_id];
|
||||||
return;
|
return;
|
||||||
|
}
|
||||||
|
|
||||||
processed_func_ids.insert(func_id);
|
processed_func_ids.insert(func_id);
|
||||||
|
|
||||||
@ -199,6 +222,7 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
|||||||
uint32_t base_id = ops[2];
|
uint32_t base_id = ops[2];
|
||||||
if (global_var_ids.find(base_id) != global_var_ids.end())
|
if (global_var_ids.find(base_id) != global_var_ids.end())
|
||||||
added_arg_ids.insert(base_id);
|
added_arg_ids.insert(base_id);
|
||||||
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
case OpFunctionCall:
|
case OpFunctionCall:
|
||||||
@ -217,6 +241,8 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
function_global_vars[func_id] = added_arg_ids;
|
||||||
|
|
||||||
// Add the global variables as arguments to the function
|
// Add the global variables as arguments to the function
|
||||||
if (func_id != entry_point)
|
if (func_id != entry_point)
|
||||||
{
|
{
|
||||||
@ -312,6 +338,12 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
|||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
case StorageClassUniformConstant:
|
||||||
|
{
|
||||||
|
ib_var_ref = stage_uniform_var_name;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
default:
|
default:
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
@ -358,7 +390,11 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
|||||||
mbr_idx++;
|
mbr_idx++;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
else
|
else if (type.basetype == SPIRType::Boolean || type.basetype == SPIRType::Char ||
|
||||||
|
type.basetype == SPIRType::Int || type.basetype == SPIRType::UInt ||
|
||||||
|
type.basetype == SPIRType::Int64 || type.basetype == SPIRType::UInt64 ||
|
||||||
|
type.basetype == SPIRType::Float || type.basetype == SPIRType::Double ||
|
||||||
|
type.basetype == SPIRType::Boolean)
|
||||||
{
|
{
|
||||||
// Add a reference to the variable type to the interface struct.
|
// Add a reference to the variable type to the interface struct.
|
||||||
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
|
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
|
||||||
@ -375,7 +411,10 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
|||||||
// Copy the variable location from the original variable to the member
|
// Copy the variable location from the original variable to the member
|
||||||
auto &dec = meta[p_var->self].decoration;
|
auto &dec = meta[p_var->self].decoration;
|
||||||
uint32_t locn = dec.location;
|
uint32_t locn = dec.location;
|
||||||
|
if (get_decoration_mask(p_var->self) & (1ull << DecorationLocation))
|
||||||
|
{
|
||||||
set_member_decoration(ib_type_id, ib_mbr_idx, DecorationLocation, locn);
|
set_member_decoration(ib_type_id, ib_mbr_idx, DecorationLocation, locn);
|
||||||
|
}
|
||||||
mark_location_as_used_by_shader(locn, storage);
|
mark_location_as_used_by_shader(locn, storage);
|
||||||
|
|
||||||
// Mark the member as builtin if needed
|
// Mark the member as builtin if needed
|
||||||
@ -396,6 +435,15 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage)
|
|||||||
MemberSorter memberSorter(ib_type, meta[ib_type_id], sort_aspect);
|
MemberSorter memberSorter(ib_type, meta[ib_type_id], sort_aspect);
|
||||||
memberSorter.sort();
|
memberSorter.sort();
|
||||||
|
|
||||||
|
// Sort input or output variables alphabetical
|
||||||
|
auto &execution = get_entry_point();
|
||||||
|
if ((execution.model == ExecutionModelFragment && storage == StorageClassInput) ||
|
||||||
|
(execution.model == ExecutionModelVertex && storage == StorageClassOutput))
|
||||||
|
{
|
||||||
|
MemberSorter memberSorter(ib_type, meta[ib_type.self], MemberSorter::Alphabetical);
|
||||||
|
memberSorter.sort();
|
||||||
|
}
|
||||||
|
|
||||||
return ib_var_id;
|
return ib_var_id;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -481,6 +529,7 @@ void CompilerMSL::emit_resources()
|
|||||||
// Output interface blocks.
|
// Output interface blocks.
|
||||||
emit_interface_block(stage_in_var_id);
|
emit_interface_block(stage_in_var_id);
|
||||||
emit_interface_block(stage_out_var_id);
|
emit_interface_block(stage_out_var_id);
|
||||||
|
emit_interface_block(stage_uniforms_var_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
// Override for MSL-specific syntax instructions
|
// Override for MSL-specific syntax instructions
|
||||||
@ -627,6 +676,8 @@ void CompilerMSL::emit_interface_block(uint32_t ib_var_id)
|
|||||||
{
|
{
|
||||||
auto &ib_var = get<SPIRVariable>(ib_var_id);
|
auto &ib_var = get<SPIRVariable>(ib_var_id);
|
||||||
auto &ib_type = get<SPIRType>(ib_var.basetype);
|
auto &ib_type = get<SPIRType>(ib_var.basetype);
|
||||||
|
auto &m = meta.at(ib_type.self);
|
||||||
|
if (m.members.size() > 0)
|
||||||
emit_struct(ib_type);
|
emit_struct(ib_type);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@ -1069,9 +1120,8 @@ void CompilerMSL::emit_fixup()
|
|||||||
{
|
{
|
||||||
if (options.vertex.fixup_clipspace)
|
if (options.vertex.fixup_clipspace)
|
||||||
{
|
{
|
||||||
const char *suffix = backend.float_literal_suffix ? "f" : "";
|
statement(qual_pos_var_name, ".z = (", qual_pos_var_name, ".z + ", qual_pos_var_name,
|
||||||
statement(qual_pos_var_name, ".z = 2.0", suffix, " * ", qual_pos_var_name, ".z - ", qual_pos_var_name,
|
".w) * 0.5; // Adjust clip-space for Metal");
|
||||||
".w;", " // Adjust clip-space for Metal");
|
|
||||||
}
|
}
|
||||||
|
|
||||||
if (msl_config.flip_vert_y)
|
if (msl_config.flip_vert_y)
|
||||||
@ -1310,12 +1360,15 @@ string CompilerMSL::entry_point_args(bool append_comma)
|
|||||||
auto &type = get<SPIRType>(var.basetype);
|
auto &type = get<SPIRType>(var.basetype);
|
||||||
|
|
||||||
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
|
if ((var.storage == StorageClassUniform || var.storage == StorageClassUniformConstant ||
|
||||||
var.storage == StorageClassPushConstant) &&
|
var.storage == StorageClassPushConstant))
|
||||||
!is_hidden_variable(var))
|
|
||||||
{
|
{
|
||||||
switch (type.basetype)
|
switch (type.basetype)
|
||||||
{
|
{
|
||||||
case SPIRType::Struct:
|
case SPIRType::Struct:
|
||||||
|
{
|
||||||
|
auto &m = meta.at(type.self);
|
||||||
|
if (m.members.size() == 0)
|
||||||
|
break;
|
||||||
if (!ep_args.empty())
|
if (!ep_args.empty())
|
||||||
ep_args += ", ";
|
ep_args += ", ";
|
||||||
if ((meta[type.self].decoration.decoration_flags & (1ull << DecorationBufferBlock)) != 0 &&
|
if ((meta[type.self].decoration.decoration_flags & (1ull << DecorationBufferBlock)) != 0 &&
|
||||||
@ -1330,6 +1383,7 @@ string CompilerMSL::entry_point_args(bool append_comma)
|
|||||||
ep_args += type_to_glsl(type) + "& " + to_name(var.self);
|
ep_args += type_to_glsl(type) + "& " + to_name(var.self);
|
||||||
ep_args += " [[buffer(" + convert_to_string(get_metal_resource_index(var, type.basetype)) + ")]]";
|
ep_args += " [[buffer(" + convert_to_string(get_metal_resource_index(var, type.basetype)) + ")]]";
|
||||||
break;
|
break;
|
||||||
|
}
|
||||||
case SPIRType::Sampler:
|
case SPIRType::Sampler:
|
||||||
if (!ep_args.empty())
|
if (!ep_args.empty())
|
||||||
ep_args += ", ";
|
ep_args += ", ";
|
||||||
@ -1431,8 +1485,12 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
|
|||||||
auto &type = expression_type(arg.id);
|
auto &type = expression_type(arg.id);
|
||||||
bool constref = !type.pointer || arg.write_count == 0;
|
bool constref = !type.pointer || arg.write_count == 0;
|
||||||
|
|
||||||
|
// TODO: Check if this arg is an uniform pointer
|
||||||
|
bool pointer = type.storage == StorageClassUniformConstant;
|
||||||
|
|
||||||
auto &var = get<SPIRVariable>(arg.id);
|
auto &var = get<SPIRVariable>(arg.id);
|
||||||
return join(constref ? "const " : "", type_to_glsl(type), "& ", to_name(var.self), type_to_array_glsl(type));
|
return join(constref ? "const " : "", type_to_glsl(type), pointer ? " " : "& ", to_name(var.self),
|
||||||
|
type_to_array_glsl(type));
|
||||||
}
|
}
|
||||||
|
|
||||||
// If we're currently in the entry point function, and the object
|
// If we're currently in the entry point function, and the object
|
||||||
@ -1468,9 +1526,14 @@ string CompilerMSL::to_qualified_member_name(const SPIRType &type, uint32_t inde
|
|||||||
string CompilerMSL::ensure_valid_name(string name, string pfx)
|
string CompilerMSL::ensure_valid_name(string name, string pfx)
|
||||||
{
|
{
|
||||||
if (name.size() >= 2 && name[0] == '_' && isdigit(name[1]))
|
if (name.size() >= 2 && name[0] == '_' && isdigit(name[1]))
|
||||||
|
{
|
||||||
return join(pfx, name);
|
return join(pfx, name);
|
||||||
|
}
|
||||||
else
|
else
|
||||||
return name;
|
{
|
||||||
|
auto iter = var_name_overrides.find(name);
|
||||||
|
return (iter != var_name_overrides.end()) ? iter->second : name;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Returns an MSL string describing the SPIR-V type
|
// Returns an MSL string describing the SPIR-V type
|
||||||
@ -1861,6 +1924,8 @@ bool CompilerMSL::MemberSorter::operator()(uint32_t mbr_idx1, uint32_t mbr_idx2)
|
|||||||
case OffsetThenLocationReverse:
|
case OffsetThenLocationReverse:
|
||||||
return (mbr_meta1.offset < mbr_meta2.offset) ||
|
return (mbr_meta1.offset < mbr_meta2.offset) ||
|
||||||
((mbr_meta1.offset == mbr_meta2.offset) && (mbr_meta1.location > mbr_meta2.location));
|
((mbr_meta1.offset == mbr_meta2.offset) && (mbr_meta1.location > mbr_meta2.location));
|
||||||
|
case Alphabetical:
|
||||||
|
return mbr_meta1.alias > mbr_meta2.alias;
|
||||||
default:
|
default:
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
@ -29,9 +29,10 @@ namespace spirv_cross
|
|||||||
// Options for compiling to Metal Shading Language
|
// Options for compiling to Metal Shading Language
|
||||||
struct MSLConfiguration
|
struct MSLConfiguration
|
||||||
{
|
{
|
||||||
bool flip_vert_y = true;
|
bool flip_vert_y = false;
|
||||||
bool flip_frag_y = true;
|
bool flip_frag_y = false;
|
||||||
bool is_rendering_points = false;
|
bool is_rendering_points = false;
|
||||||
|
std::string entry_point_name;
|
||||||
};
|
};
|
||||||
|
|
||||||
// Defines MSL characteristics of a vertex attribute at a particular location.
|
// Defines MSL characteristics of a vertex attribute at a particular location.
|
||||||
@ -115,22 +116,26 @@ protected:
|
|||||||
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
|
uint32_t coord, uint32_t coord_components, uint32_t dref, uint32_t grad_x,
|
||||||
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
|
uint32_t grad_y, uint32_t lod, uint32_t coffset, uint32_t offset, uint32_t bias,
|
||||||
uint32_t comp, uint32_t sample, bool *p_forward) override;
|
uint32_t comp, uint32_t sample, bool *p_forward) override;
|
||||||
std::string clean_func_name(std::string func_name) override;
|
|
||||||
|
|
||||||
void preprocess_op_codes();
|
void preprocess_op_codes();
|
||||||
void emit_custom_functions();
|
void emit_custom_functions();
|
||||||
void localize_global_variables();
|
void localize_global_variables();
|
||||||
void extract_global_variables_from_functions();
|
void extract_global_variables_from_functions();
|
||||||
|
|
||||||
|
std::unordered_map<uint32_t, std::unordered_set<uint32_t>> function_global_vars;
|
||||||
void extract_global_variables_from_function(uint32_t func_id, std::unordered_set<uint32_t> &added_arg_ids,
|
void extract_global_variables_from_function(uint32_t func_id, std::unordered_set<uint32_t> &added_arg_ids,
|
||||||
std::unordered_set<uint32_t> &global_var_ids,
|
std::unordered_set<uint32_t> &global_var_ids,
|
||||||
std::unordered_set<uint32_t> &processed_func_ids);
|
std::unordered_set<uint32_t> &processed_func_ids);
|
||||||
uint32_t add_interface_block(spv::StorageClass storage);
|
uint32_t add_interface_block(spv::StorageClass storage);
|
||||||
void mark_location_as_used_by_shader(uint32_t location, spv::StorageClass storage);
|
void mark_location_as_used_by_shader(uint32_t location, spv::StorageClass storage);
|
||||||
|
|
||||||
void emit_resources();
|
void emit_resources();
|
||||||
void emit_interface_block(uint32_t ib_var_id);
|
void emit_interface_block(uint32_t ib_var_id);
|
||||||
void populate_func_name_overrides();
|
void populate_func_name_overrides();
|
||||||
|
void populate_var_name_overrides();
|
||||||
|
|
||||||
std::string func_type_decl(SPIRType &type);
|
std::string func_type_decl(SPIRType &type);
|
||||||
|
std::string clean_func_name(std::string func_name) override;
|
||||||
std::string entry_point_args(bool append_comma);
|
std::string entry_point_args(bool append_comma);
|
||||||
std::string get_entry_point_name();
|
std::string get_entry_point_name();
|
||||||
std::string to_qualified_member_name(const SPIRType &type, uint32_t index);
|
std::string to_qualified_member_name(const SPIRType &type, uint32_t index);
|
||||||
@ -148,15 +153,18 @@ protected:
|
|||||||
|
|
||||||
MSLConfiguration msl_config;
|
MSLConfiguration msl_config;
|
||||||
std::unordered_map<std::string, std::string> func_name_overrides;
|
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;
|
std::set<uint32_t> custom_function_ops;
|
||||||
std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_location;
|
std::unordered_map<uint32_t, MSLVertexAttr *> vtx_attrs_by_location;
|
||||||
std::vector<MSLResourceBinding *> resource_bindings;
|
std::vector<MSLResourceBinding *> resource_bindings;
|
||||||
MSLResourceBinding next_metal_resource_index;
|
MSLResourceBinding next_metal_resource_index;
|
||||||
uint32_t stage_in_var_id = 0;
|
uint32_t stage_in_var_id = 0;
|
||||||
uint32_t stage_out_var_id = 0;
|
uint32_t stage_out_var_id = 0;
|
||||||
|
uint32_t stage_uniforms_var_id = 0;
|
||||||
std::string qual_pos_var_name;
|
std::string qual_pos_var_name;
|
||||||
std::string stage_in_var_name = "in";
|
std::string stage_in_var_name = "in";
|
||||||
std::string stage_out_var_name = "out";
|
std::string stage_out_var_name = "out";
|
||||||
|
std::string stage_uniform_var_name = "uniforms";
|
||||||
std::string sampler_name_suffix = "Smplr";
|
std::string sampler_name_suffix = "Smplr";
|
||||||
|
|
||||||
// OpcodeHandler that handles several MSL preprocessing operations.
|
// OpcodeHandler that handles several MSL preprocessing operations.
|
||||||
@ -184,6 +192,7 @@ protected:
|
|||||||
LocationReverse,
|
LocationReverse,
|
||||||
Offset,
|
Offset,
|
||||||
OffsetThenLocationReverse,
|
OffsetThenLocationReverse,
|
||||||
|
Alphabetical
|
||||||
};
|
};
|
||||||
|
|
||||||
void sort();
|
void sort();
|
||||||
|
Loading…
Reference in New Issue
Block a user