Merge pull request #539 from KhronosGroup/fix-533
Add support for constexpr samplers in MSL.
This commit is contained in:
Коммит
2804d9acd7
50
main.cpp
50
main.cpp
|
@ -487,21 +487,41 @@ struct CLIArguments
|
|||
|
||||
static void print_help()
|
||||
{
|
||||
fprintf(stderr, "Usage: spirv-cross [--output <output path>] [SPIR-V file] [--es] [--no-es] "
|
||||
"[--version <GLSL version>] [--dump-resources] [--help] [--force-temporary] "
|
||||
"[--vulkan-semantics] [--flatten-ubo] [--fixup-clipspace] [--flip-vert-y] [--iterations iter] "
|
||||
"[--cpp] [--cpp-interface-name <name>] "
|
||||
"[--msl] [--msl-version <MMmmpp>]"
|
||||
"[--hlsl] [--shader-model] [--hlsl-enable-compat] "
|
||||
"[--separate-shader-objects]"
|
||||
"[--pls-in format input-name] [--pls-out format output-name] [--remap source_name target_name "
|
||||
"components] [--extension ext] [--entry name] [--stage <stage (vert, frag, geom, tesc, tese, "
|
||||
"comp)>] [--remove-unused-variables] "
|
||||
"[--flatten-multidimensional-arrays] [--no-420pack-extension] "
|
||||
"[--remap-variable-type <variable_name> <new_variable_type>] "
|
||||
"[--rename-interface-variable <in|out> <location> <new_variable_name>] "
|
||||
"[--set-hlsl-vertex-input-semantic <location> <semantic>] "
|
||||
"[--rename-entry-point <old> <new> <stage>] "
|
||||
fprintf(stderr, "Usage: spirv-cross\n"
|
||||
"\t[--output <output path>]\n"
|
||||
"\t[SPIR-V file]\n"
|
||||
"\t[--es]\n"
|
||||
"\t[--no-es]\n"
|
||||
"\t[--version <GLSL version>]\n"
|
||||
"\t[--dump-resources]\n"
|
||||
"\t[--help]\n"
|
||||
"\t[--force-temporary]\n"
|
||||
"\t[--vulkan-semantics]\n"
|
||||
"\t[--flatten-ubo]\n"
|
||||
"\t[--fixup-clipspace]\n"
|
||||
"\t[--flip-vert-y]\n"
|
||||
"\t[--iterations iter]\n"
|
||||
"\t[--cpp]\n"
|
||||
"\t[--cpp-interface-name <name>]\n"
|
||||
"\t[--msl]\n"
|
||||
"\t[--msl-version <MMmmpp>]\n"
|
||||
"\t[--hlsl]\n"
|
||||
"\t[--shader-model]\n"
|
||||
"\t[--hlsl-enable-compat]\n"
|
||||
"\t[--separate-shader-objects]\n"
|
||||
"\t[--pls-in format input-name]\n"
|
||||
"\t[--pls-out format output-name]\n"
|
||||
"\t[--remap source_name target_name components]\n"
|
||||
"\t[--extension ext]\n"
|
||||
"\t[--entry name]\n"
|
||||
"\t[--stage <stage (vert, frag, geom, tesc, tese comp)>]\n"
|
||||
"\t[--remove-unused-variables]\n"
|
||||
"\t[--flatten-multidimensional-arrays]\n"
|
||||
"\t[--no-420pack-extension]\n"
|
||||
"\t[--remap-variable-type <variable_name> <new_variable_type>]\n"
|
||||
"\t[--rename-interface-variable <in|out> <location> <new_variable_name>]\n"
|
||||
"\t[--set-hlsl-vertex-input-semantic <location> <semantic>]\n"
|
||||
"\t[--rename-entry-point <old> <new> <stage>]\n"
|
||||
"\n");
|
||||
}
|
||||
|
||||
|
|
|
@ -1715,6 +1715,10 @@ void CompilerGLSL::emit_specialization_constant(const SPIRConstant &constant)
|
|||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::emit_entry_point_declarations()
|
||||
{
|
||||
}
|
||||
|
||||
void CompilerGLSL::replace_illegal_names()
|
||||
{
|
||||
// clang-format off
|
||||
|
@ -8718,6 +8722,9 @@ void CompilerGLSL::emit_function(SPIRFunction &func, const Bitset &return_flags)
|
|||
emit_function_prototype(func, return_flags);
|
||||
begin_scope();
|
||||
|
||||
if (func.self == entry_point)
|
||||
emit_entry_point_declarations();
|
||||
|
||||
current_function = &func;
|
||||
auto &entry_block = get<SPIRBlock>(func.entry_block);
|
||||
|
||||
|
|
|
@ -475,6 +475,7 @@ protected:
|
|||
bool check_atomic_image(uint32_t id);
|
||||
|
||||
virtual void replace_illegal_names();
|
||||
virtual void emit_entry_point_declarations();
|
||||
|
||||
void replace_fragment_output(SPIRVariable &var);
|
||||
void replace_fragment_outputs();
|
||||
|
|
163
spirv_msl.cpp
163
spirv_msl.cpp
|
@ -104,6 +104,152 @@ void CompilerMSL::build_implicit_builtins()
|
|||
}
|
||||
}
|
||||
|
||||
static string create_sampler_address(const char *prefix, MSLSamplerAddress addr)
|
||||
{
|
||||
switch (addr)
|
||||
{
|
||||
case MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE:
|
||||
return join(prefix, "address::clamp_to_edge");
|
||||
case MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO:
|
||||
return join(prefix, "address::clamp_to_zero");
|
||||
case MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER:
|
||||
return join(prefix, "address::clamp_to_border");
|
||||
case MSL_SAMPLER_ADDRESS_REPEAT:
|
||||
return join(prefix, "address::repeat");
|
||||
case MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT:
|
||||
return join(prefix, "address::mirrored_repeat");
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid sampler addressing mode.");
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerMSL::emit_entry_point_declarations()
|
||||
{
|
||||
// FIXME: Get test coverage here ...
|
||||
|
||||
// Emit constexpr samplers here.
|
||||
for (auto &samp : constexpr_samplers)
|
||||
{
|
||||
auto &var = get<SPIRVariable>(samp.first);
|
||||
auto &type = get<SPIRType>(var.basetype);
|
||||
if (type.basetype == SPIRType::Sampler)
|
||||
add_resource_name(samp.first);
|
||||
|
||||
vector<string> args;
|
||||
auto &s = samp.second;
|
||||
|
||||
if (s.coord != MSL_SAMPLER_COORD_NORMALIZED)
|
||||
args.push_back("coord::pixel");
|
||||
|
||||
if (s.min_filter == s.mag_filter)
|
||||
{
|
||||
if (s.min_filter != MSL_SAMPLER_FILTER_NEAREST)
|
||||
args.push_back("filter::linear");
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.min_filter != MSL_SAMPLER_FILTER_NEAREST)
|
||||
args.push_back("min_filter::linear");
|
||||
if (s.mag_filter != MSL_SAMPLER_FILTER_NEAREST)
|
||||
args.push_back("mag_filter::linear");
|
||||
}
|
||||
|
||||
switch (s.mip_filter)
|
||||
{
|
||||
case MSL_SAMPLER_MIP_FILTER_NONE:
|
||||
// Default
|
||||
break;
|
||||
case MSL_SAMPLER_MIP_FILTER_NEAREST:
|
||||
args.push_back("mip_filter::nearest");
|
||||
break;
|
||||
case MSL_SAMPLER_MIP_FILTER_LINEAR:
|
||||
args.push_back("mip_filter::linear");
|
||||
break;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid mip filter.");
|
||||
}
|
||||
|
||||
if (s.s_address == s.t_address && s.s_address == s.r_address)
|
||||
{
|
||||
if (s.s_address != MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE)
|
||||
args.push_back(create_sampler_address("", s.s_address));
|
||||
}
|
||||
else
|
||||
{
|
||||
if (s.s_address != MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE)
|
||||
args.push_back(create_sampler_address("s_", s.s_address));
|
||||
if (s.t_address != MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE)
|
||||
args.push_back(create_sampler_address("t_", s.t_address));
|
||||
if (s.r_address != MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE)
|
||||
args.push_back(create_sampler_address("r_", s.r_address));
|
||||
}
|
||||
|
||||
if (s.compare_enable)
|
||||
{
|
||||
switch (s.compare_func)
|
||||
{
|
||||
case MSL_SAMPLER_COMPARE_FUNC_ALWAYS:
|
||||
args.push_back("compare_func::always");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_NEVER:
|
||||
args.push_back("compare_func::never");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_EQUAL:
|
||||
args.push_back("compare_func::equal");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL:
|
||||
args.push_back("compare_func::not_equal");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_LESS:
|
||||
args.push_back("compare_func::less");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL:
|
||||
args.push_back("compare_func::less_equal");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_GREATER:
|
||||
args.push_back("compare_func::greater");
|
||||
break;
|
||||
case MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL:
|
||||
args.push_back("compare_func::greater_equal");
|
||||
break;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid sampler compare function.");
|
||||
}
|
||||
}
|
||||
|
||||
if (s.s_address == MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER || s.t_address == MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER ||
|
||||
s.r_address == MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER)
|
||||
{
|
||||
switch (s.border_color)
|
||||
{
|
||||
case MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK:
|
||||
args.push_back("border_color::opaque_black");
|
||||
break;
|
||||
case MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE:
|
||||
args.push_back("border_color::opaque_white");
|
||||
break;
|
||||
case MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK:
|
||||
args.push_back("border_color::transparent_black");
|
||||
break;
|
||||
default:
|
||||
SPIRV_CROSS_THROW("Invalid sampler border color.");
|
||||
}
|
||||
}
|
||||
|
||||
if (s.anisotropy_enable)
|
||||
args.push_back(join("max_anisotropy(", s.max_anisotropy, ")"));
|
||||
if (s.lod_clamp_enable)
|
||||
{
|
||||
args.push_back(
|
||||
join("lod_clamp(", convert_to_string(s.lod_clamp_min), ", ", convert_to_string(s.lod_clamp_max), ")"));
|
||||
}
|
||||
|
||||
statement("constexpr sampler ",
|
||||
type.basetype == SPIRType::SampledImage ? to_sampler_expression(samp.first) : to_name(samp.first),
|
||||
"(", merge(args), ");");
|
||||
}
|
||||
}
|
||||
|
||||
string CompilerMSL::compile()
|
||||
{
|
||||
// Force a classic "C" locale, reverts when function returns
|
||||
|
@ -3076,12 +3222,15 @@ string CompilerMSL::entry_point_args(bool append_comma)
|
|||
resources.push_back(
|
||||
{ &id, to_name(var_id), SPIRType::Image, get_metal_resource_index(var, SPIRType::Image) });
|
||||
|
||||
if (type.image.dim != DimBuffer)
|
||||
if (type.image.dim != DimBuffer && constexpr_samplers.count(var_id) == 0)
|
||||
{
|
||||
resources.push_back({ &id, to_sampler_expression(var_id), SPIRType::Sampler,
|
||||
get_metal_resource_index(var, SPIRType::Sampler) });
|
||||
}
|
||||
}
|
||||
else
|
||||
else if (constexpr_samplers.count(var_id) == 0)
|
||||
{
|
||||
// constexpr samplers are not declared as resources.
|
||||
resources.push_back(
|
||||
{ &id, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype) });
|
||||
}
|
||||
|
@ -4087,3 +4236,13 @@ CompilerMSL::MemberSorter::MemberSorter(SPIRType &t, Meta &m, SortAspect sa)
|
|||
// Ensure enough meta info is available
|
||||
meta.members.resize(max(type.member_types.size(), meta.members.size()));
|
||||
}
|
||||
|
||||
void CompilerMSL::remap_constexpr_sampler(uint32_t id, const spirv_cross::MSLConstexprSampler &sampler)
|
||||
{
|
||||
auto &type = get<SPIRType>(get<SPIRVariable>(id).basetype);
|
||||
if (type.basetype != SPIRType::SampledImage && type.basetype != SPIRType::Sampler)
|
||||
SPIRV_CROSS_THROW("Can only remap SampledImage and Sampler type.");
|
||||
if (!type.array.empty())
|
||||
SPIRV_CROSS_THROW("Can not remap array of samplers.");
|
||||
constexpr_samplers[id] = sampler;
|
||||
}
|
||||
|
|
|
@ -59,6 +59,73 @@ struct MSLResourceBinding
|
|||
bool used_by_shader = false;
|
||||
};
|
||||
|
||||
enum MSLSamplerCoord
|
||||
{
|
||||
MSL_SAMPLER_COORD_NORMALIZED,
|
||||
MSL_SAMPLER_COORD_PIXEL
|
||||
};
|
||||
|
||||
enum MSLSamplerFilter
|
||||
{
|
||||
MSL_SAMPLER_FILTER_NEAREST,
|
||||
MSL_SAMPLER_FILTER_LINEAR
|
||||
};
|
||||
|
||||
enum MSLSamplerMipFilter
|
||||
{
|
||||
MSL_SAMPLER_MIP_FILTER_NONE,
|
||||
MSL_SAMPLER_MIP_FILTER_NEAREST,
|
||||
MSL_SAMPLER_MIP_FILTER_LINEAR,
|
||||
};
|
||||
|
||||
enum MSLSamplerAddress
|
||||
{
|
||||
MSL_SAMPLER_ADDRESS_CLAMP_TO_ZERO,
|
||||
MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE,
|
||||
MSL_SAMPLER_ADDRESS_CLAMP_TO_BORDER,
|
||||
MSL_SAMPLER_ADDRESS_REPEAT,
|
||||
MSL_SAMPLER_ADDRESS_MIRRORED_REPEAT
|
||||
};
|
||||
|
||||
enum MSLSamplerCompareFunc
|
||||
{
|
||||
MSL_SAMPLER_COMPARE_FUNC_NEVER,
|
||||
MSL_SAMPLER_COMPARE_FUNC_LESS,
|
||||
MSL_SAMPLER_COMPARE_FUNC_LESS_EQUAL,
|
||||
MSL_SAMPLER_COMPARE_FUNC_GREATER,
|
||||
MSL_SAMPLER_COMPARE_FUNC_GREATER_EQUAL,
|
||||
MSL_SAMPLER_COMPARE_FUNC_EQUAL,
|
||||
MSL_SAMPLER_COMPARE_FUNC_NOT_EQUAL,
|
||||
MSL_SAMPLER_COMPARE_FUNC_ALWAYS
|
||||
};
|
||||
|
||||
enum MSLSamplerBorderColor
|
||||
{
|
||||
MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK,
|
||||
MSL_SAMPLER_BORDER_COLOR_OPAQUE_BLACK,
|
||||
MSL_SAMPLER_BORDER_COLOR_OPAQUE_WHITE
|
||||
};
|
||||
|
||||
struct MSLConstexprSampler
|
||||
{
|
||||
MSLSamplerCoord coord = MSL_SAMPLER_COORD_NORMALIZED;
|
||||
MSLSamplerFilter min_filter = MSL_SAMPLER_FILTER_NEAREST;
|
||||
MSLSamplerFilter mag_filter = MSL_SAMPLER_FILTER_NEAREST;
|
||||
MSLSamplerMipFilter mip_filter = MSL_SAMPLER_MIP_FILTER_NONE;
|
||||
MSLSamplerAddress s_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
|
||||
MSLSamplerAddress t_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
|
||||
MSLSamplerAddress r_address = MSL_SAMPLER_ADDRESS_CLAMP_TO_EDGE;
|
||||
MSLSamplerCompareFunc compare_func = MSL_SAMPLER_COMPARE_FUNC_NEVER;
|
||||
MSLSamplerBorderColor border_color = MSL_SAMPLER_BORDER_COLOR_TRANSPARENT_BLACK;
|
||||
float lod_clamp_min = 0.0f;
|
||||
float lod_clamp_max = 1000.0f;
|
||||
int max_anisotropy = 1;
|
||||
|
||||
bool compare_enable = false;
|
||||
bool lod_clamp_enable = false;
|
||||
bool anisotropy_enable = false;
|
||||
};
|
||||
|
||||
// Tracks the type ID and member index of a struct member
|
||||
using MSLStructMemberKey = uint64_t;
|
||||
|
||||
|
@ -191,6 +258,14 @@ public:
|
|||
std::string compile(MSLConfiguration &msl_cfg, std::vector<MSLVertexAttr> *p_vtx_attrs = nullptr,
|
||||
std::vector<MSLResourceBinding> *p_res_bindings = nullptr);
|
||||
|
||||
// Remap a sampler with ID to a constexpr sampler.
|
||||
// Older iOS targets must use constexpr samplers in certain cases (PCF),
|
||||
// so a static sampler must be used.
|
||||
// The sampler will not consume a binding, but be declared in the entry point as a constexpr sampler.
|
||||
// This can be used on both combined image/samplers (sampler2D) or standalone samplers.
|
||||
// The remapped sampler must not be an array of samplers.
|
||||
void remap_constexpr_sampler(uint32_t id, const MSLConstexprSampler &sampler);
|
||||
|
||||
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,
|
||||
|
@ -284,6 +359,7 @@ protected:
|
|||
void emit_barrier(uint32_t id_exe_scope, uint32_t id_mem_scope, uint32_t id_mem_sem);
|
||||
void emit_array_copy(const std::string &lhs, uint32_t rhs_id) override;
|
||||
void build_implicit_builtins();
|
||||
void emit_entry_point_declarations() override;
|
||||
uint32_t builtin_frag_coord_id = 0;
|
||||
|
||||
Options msl_options;
|
||||
|
@ -307,6 +383,8 @@ protected:
|
|||
std::string sampler_name_suffix = "Smplr";
|
||||
spv::Op previous_instruction_opcode = spv::OpNop;
|
||||
|
||||
std::unordered_map<uint32_t, MSLConstexprSampler> constexpr_samplers;
|
||||
|
||||
// OpcodeHandler that handles several MSL preprocessing operations.
|
||||
struct OpCodePreprocessor : OpcodeHandler
|
||||
{
|
||||
|
|
Загрузка…
Ссылка в новой задаче