Updated spirv-cross.

This commit is contained in:
Бранимир Караџић
2020-10-17 22:52:04 -07:00
parent d99a5b2f91
commit 3a63498275
7 changed files with 185 additions and 36 deletions

View File

@@ -563,6 +563,8 @@ struct CLIArguments
bool msl_vertex_for_tessellation = false;
uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
bool msl_arrayed_subpass_input = false;
uint32_t msl_r32ui_linear_texture_alignment = 4;
uint32_t msl_r32ui_alignment_constant_id = 65535;
bool glsl_emit_push_constant_as_ubo = false;
bool glsl_emit_ubo_as_plain_uniforms = false;
bool glsl_force_flattened_io_blocks = false;
@@ -768,7 +770,11 @@ static void print_help_msl()
"\t[--msl-additional-fixed-sample-mask <mask>]:\n"
"\t\tSet an additional fixed sample mask. If the shader outputs a sample mask, then the final sample mask will be a bitwise AND of the two.\n"
"\t[--msl-arrayed-subpass-input]:\n\t\tAssume that images of dimension SubpassData have multiple layers. Layered input attachments are accessed relative to BuiltInLayer.\n"
"\t\tThis option has no effect if multiview is also enabled.\n");
"\t\tThis option has no effect if multiview is also enabled.\n"
"\t[--msl-r32ui-linear-texture-align <alignment>]:\n\t\tThe required alignment of linear textures of format MTLPixelFormatR32Uint.\n"
"\t\tThis is used to align the row stride for atomic accesses to such images.\n"
"\t[--msl-r32ui-linear-texture-align-constant-id <id>]:\n\t\tThe function constant ID to use for the linear texture alignment.\n"
"\t\tOn MSL 1.2 or later, you can override the alignment by setting this function constant.\n");
// clang-format on
}
@@ -1007,6 +1013,8 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
msl_opts.vertex_for_tessellation = args.msl_vertex_for_tessellation;
msl_opts.additional_fixed_sample_mask = args.msl_additional_fixed_sample_mask;
msl_opts.arrayed_subpass_input = args.msl_arrayed_subpass_input;
msl_opts.r32ui_linear_texture_alignment = args.msl_r32ui_linear_texture_alignment;
msl_opts.r32ui_alignment_constant_id = args.msl_r32ui_alignment_constant_id;
msl_comp->set_msl_options(msl_opts);
for (auto &v : args.msl_discrete_descriptor_sets)
msl_comp->add_discrete_descriptor_set(v);
@@ -1427,6 +1435,10 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl-additional-fixed-sample-mask",
[&args](CLIParser &parser) { args.msl_additional_fixed_sample_mask = parser.next_hex_uint(); });
cbs.add("--msl-arrayed-subpass-input", [&args](CLIParser &) { args.msl_arrayed_subpass_input = true; });
cbs.add("--msl-r32ui-linear-texture-align",
[&args](CLIParser &parser) { args.msl_r32ui_linear_texture_alignment = parser.next_uint(); });
cbs.add("--msl-r32ui-linear-texture-align-constant-id",
[&args](CLIParser &parser) { args.msl_r32ui_alignment_constant_id = parser.next_uint(); });
cbs.add("--extension", [&args](CLIParser &parser) { args.extensions.push_back(parser.next_string()); });
cbs.add("--rename-entry-point", [&args](CLIParser &parser) {
auto old_name = parser.next_string();

View File

@@ -666,6 +666,14 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT:
options->msl.arrayed_subpass_input = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT:
options->msl.r32ui_linear_texture_alignment = value;
break;
case SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID:
options->msl.r32ui_alignment_constant_id = value;
break;
#endif
default:
@@ -1239,6 +1247,42 @@ spvc_bool spvc_compiler_msl_is_resource_used(spvc_compiler compiler, SpvExecutio
#endif
}
spvc_result spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler, const char *suffix)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
msl.set_combined_sampler_suffix(suffix);
return SPVC_SUCCESS;
#else
(void)suffix;
compiler->context->report_error("MSL function used on a non-MSL backend.");
return SPVC_ERROR_INVALID_ARGUMENT;
#endif
}
const char *spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler)
{
#if SPIRV_CROSS_C_API_MSL
if (compiler->backend != SPVC_BACKEND_MSL)
{
compiler->context->report_error("MSL function used on a non-MSL backend.");
return "";
}
auto &msl = *static_cast<CompilerMSL *>(compiler->compiler.get());
return msl.get_combined_sampler_suffix();
#else
compiler->context->report_error("MSL function used on a non-MSL backend.");
return "";
#endif
}
#if SPIRV_CROSS_C_API_MSL
static void spvc_convert_msl_sampler(MSLConstexprSampler &samp, const spvc_msl_constexpr_sampler *sampler)
{

View File

@@ -33,7 +33,7 @@ extern "C" {
/* Bumped if ABI or API breaks backwards compatibility. */
#define SPVC_C_API_VERSION_MAJOR 0
/* Bumped if APIs or enumerations are added in a backwards compatible way. */
#define SPVC_C_API_VERSION_MINOR 39
#define SPVC_C_API_VERSION_MINOR 41
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@@ -638,6 +638,8 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING = 67 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT = 68 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_R32UI_LINEAR_TEXTURE_ALIGNMENT = 69 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_MSL_R32UI_ALIGNMENT_CONSTANT_ID = 70 | SPVC_COMPILER_OPTION_MSL_BIT,
SPVC_COMPILER_OPTION_INT_MAX = 0x7fffffff
} spvc_compiler_option;
@@ -767,6 +769,9 @@ SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_dynamic_buffer(spvc_compiler c
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_add_inline_uniform_block(spvc_compiler compiler, unsigned desc_set, unsigned binding);
SPVC_PUBLIC_API spvc_result spvc_compiler_msl_set_combined_sampler_suffix(spvc_compiler compiler, const char *suffix);
SPVC_PUBLIC_API const char *spvc_compiler_msl_get_combined_sampler_suffix(spvc_compiler compiler);
/*
* Reflect resources.
* Maps almost 1:1 to C++ API.

View File

@@ -9313,8 +9313,8 @@ void CompilerGLSL::emit_store_statement(uint32_t lhs_expression, uint32_t rhs_ex
auto lhs = to_dereferenced_expression(lhs_expression);
// We might need to bitcast in order to store to a builtin.
bitcast_to_builtin_store(lhs_expression, rhs, expression_type(rhs_expression));
// We might need to cast in order to store to a builtin.
cast_to_builtin_store(lhs_expression, rhs, expression_type(rhs_expression));
// Tries to optimize assignments like "<lhs> = <lhs> op expr".
// While this is purely cosmetic, this is important for legacy ESSL where loop
@@ -9477,8 +9477,8 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
if (expr_type.vecsize > type.vecsize)
expr = enclose_expression(expr + vector_swizzle(type.vecsize, 0));
// We might need to bitcast in order to load from a builtin.
bitcast_from_builtin_load(ptr, expr, type);
// We might need to cast in order to load from a builtin.
cast_from_builtin_load(ptr, expr, type);
// We might be trying to load a gl_Position[N], where we should be
// doing float4[](gl_in[i].gl_Position, ...) instead.
@@ -12040,18 +12040,11 @@ bool CompilerGLSL::is_non_native_row_major_matrix(uint32_t id)
if (backend.native_row_major_matrix && !is_legacy())
return false;
// Non-matrix or column-major matrix types do not need to be converted.
if (!has_decoration(id, DecorationRowMajor))
return false;
// Only square row-major matrices can be converted at this time.
// Converting non-square matrices will require defining custom GLSL function that
// swaps matrix elements while retaining the original dimensional form of the matrix.
const auto type = expression_type(id);
if (type.columns != type.vecsize)
SPIRV_CROSS_THROW("Row-major matrices must be square on this platform.");
return true;
auto *e = maybe_get<SPIRExpression>(id);
if (e)
return e->need_transpose;
else
return has_decoration(id, DecorationRowMajor);
}
// Checks whether the member is a row_major matrix that requires conversion before use
@@ -14484,7 +14477,7 @@ void CompilerGLSL::unroll_array_from_complex_load(uint32_t target_id, uint32_t s
}
}
void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
void CompilerGLSL::cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
{
auto *var = maybe_get_backing_variable(source_id);
if (var)
@@ -14536,7 +14529,7 @@ void CompilerGLSL::bitcast_from_builtin_load(uint32_t source_id, std::string &ex
expr = bitcast_expression(expr_type, expected_type, expr);
}
void CompilerGLSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
void CompilerGLSL::cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
{
// Only interested in standalone builtin variables.
if (!has_decoration(target_id, DecorationBuiltIn))

View File

@@ -854,9 +854,9 @@ protected:
// Builtins in GLSL are always specific signedness, but the SPIR-V can declare them
// as either unsigned or signed.
// Sometimes we will need to automatically perform bitcasts on load and store to make this work.
virtual void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
// Sometimes we will need to automatically perform casts on load and store to make this work.
virtual void cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type);
virtual void cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type);
void unroll_array_from_complex_load(uint32_t target_id, uint32_t source_id, std::string &expr);
void convert_non_uniform_expression(const SPIRType &type, std::string &expr);

View File

@@ -1120,7 +1120,7 @@ string CompilerMSL::compile()
backend.basic_int16_type = "short";
backend.basic_uint16_type = "ushort";
backend.discard_literal = "discard_fragment()";
backend.demote_literal = "unsupported-demote";
backend.demote_literal = "discard_fragment()";
backend.boolean_mix_function = "select";
backend.swizzle_is_function = false;
backend.shared_is_implied = false;
@@ -4194,8 +4194,25 @@ void CompilerMSL::emit_custom_functions()
// Emulate texture2D atomic operations
case SPVFuncImplImage2DAtomicCoords:
{
if (msl_options.supports_msl_version(1, 2))
{
statement("// The required alignment of a linear texture of R32Uint format.");
statement("constant uint spvLinearTextureAlignmentOverride [[function_constant(",
msl_options.r32ui_alignment_constant_id, ")]];");
statement("constant uint spvLinearTextureAlignment = ",
"is_function_constant_defined(spvLinearTextureAlignmentOverride) ? ",
"spvLinearTextureAlignmentOverride : ", msl_options.r32ui_linear_texture_alignment, ";");
}
else
{
statement("// The required alignment of a linear texture of R32Uint format.");
statement("constant uint spvLinearTextureAlignment = ", msl_options.r32ui_linear_texture_alignment,
";");
}
statement("// Returns buffer coords corresponding to 2D texture coords for emulating 2D texture atomics");
statement("#define spvImage2DAtomicCoord(tc, tex) (((tex).get_width() * (tc).x) + (tc).y)");
statement("#define spvImage2DAtomicCoord(tc, tex) (((((tex).get_width() + ",
" spvLinearTextureAlignment / 4 - 1) & ~(",
" spvLinearTextureAlignment / 4 - 1)) * (tc).y) + (tc).x)");
statement("");
break;
}
@@ -7117,11 +7134,18 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
break;
}
// SPV_EXT_demote_to_helper_invocation
case OpDemoteToHelperInvocationEXT:
if (!msl_options.supports_msl_version(2, 3))
SPIRV_CROSS_THROW("discard_fragment() does not formally have demote semantics until MSL 2.3.");
CompilerGLSL::emit_instruction(instruction);
break;
case OpIsHelperInvocationEXT:
if (msl_options.is_ios())
SPIRV_CROSS_THROW("simd_is_helper_thread() is only supported on macOS.");
if (msl_options.is_ios() && !msl_options.supports_msl_version(2, 3))
SPIRV_CROSS_THROW("simd_is_helper_thread() requires MSL 2.3 on iOS.");
else if (msl_options.is_macos() && !msl_options.supports_msl_version(2, 1))
SPIRV_CROSS_THROW("simd_is_helper_thread() requires version 2.1 on macOS.");
SPIRV_CROSS_THROW("simd_is_helper_thread() requires MSL 2.1 on macOS.");
emit_op(ops[0], ops[1], "simd_is_helper_thread()", false);
break;
@@ -10192,7 +10216,10 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
{
ep_args += ", device atomic_" + type_to_glsl(get<SPIRType>(basetype.image.type), 0);
ep_args += "* " + r.name + "_atomic";
ep_args += " [[buffer(" + convert_to_string(r.secondary_index) + ")]]";
ep_args += " [[buffer(" + convert_to_string(r.secondary_index) + ")";
if (interlocked_resources.count(var_id))
ep_args += ", raster_order_group(0)";
ep_args += "]]";
}
break;
}
@@ -13272,7 +13299,7 @@ void CompilerMSL::remap_constexpr_sampler_by_binding(uint32_t desc_set, uint32_t
constexpr_samplers_by_binding[{ desc_set, binding }] = sampler;
}
void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
void CompilerMSL::cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type)
{
auto *var = maybe_get_backing_variable(source_id);
if (var)
@@ -13284,6 +13311,7 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
auto builtin = static_cast<BuiltIn>(get_decoration(source_id, DecorationBuiltIn));
auto expected_type = expr_type.basetype;
auto expected_width = expr_type.width;
switch (builtin)
{
case BuiltInGlobalInvocationId:
@@ -13304,12 +13332,16 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
case BuiltInBaseInstance:
case BuiltInBaseVertex:
expected_type = SPIRType::UInt;
expected_width = 32;
break;
case BuiltInTessLevelInner:
case BuiltInTessLevelOuter:
if (get_execution_model() == ExecutionModelTessellationControl)
{
expected_type = SPIRType::Half;
expected_width = 16;
}
break;
default:
@@ -13317,7 +13349,17 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
}
if (expected_type != expr_type.basetype)
expr = bitcast_expression(expr_type, expected_type, expr);
{
if (expected_width != expr_type.width)
{
// These are of different widths, so we cannot do a straight bitcast.
expr = join(type_to_glsl(expr_type), "(", expr, ")");
}
else
{
expr = bitcast_expression(expr_type, expected_type, expr);
}
}
if (builtin == BuiltInTessCoord && get_entry_point().flags.get(ExecutionModeQuads) && expr_type.vecsize == 3)
{
@@ -13327,7 +13369,7 @@ void CompilerMSL::bitcast_from_builtin_load(uint32_t source_id, std::string &exp
}
}
void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
void CompilerMSL::cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type)
{
auto *var = maybe_get_backing_variable(target_id);
if (var)
@@ -13339,6 +13381,7 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
auto builtin = static_cast<BuiltIn>(get_decoration(target_id, DecorationBuiltIn));
auto expected_type = expr_type.basetype;
auto expected_width = expr_type.width;
switch (builtin)
{
case BuiltInLayer:
@@ -13347,11 +13390,13 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
case BuiltInPrimitiveId:
case BuiltInViewIndex:
expected_type = SPIRType::UInt;
expected_width = 32;
break;
case BuiltInTessLevelInner:
case BuiltInTessLevelOuter:
expected_type = SPIRType::Half;
expected_width = 16;
break;
default:
@@ -13360,10 +13405,13 @@ void CompilerMSL::bitcast_to_builtin_store(uint32_t target_id, std::string &expr
if (expected_type != expr_type.basetype)
{
if (expected_type == SPIRType::Half && expr_type.basetype == SPIRType::Float)
if (expected_width != expr_type.width)
{
// These are of different widths, so we cannot do a straight bitcast.
expr = join("half(", expr, ")");
auto type = expr_type;
type.basetype = expected_type;
type.width = expected_width;
expr = join(type_to_glsl(type), "(", expr, ")");
}
else
{
@@ -13500,6 +13548,14 @@ void CompilerMSL::analyze_argument_buffers()
add_resource_name(var_id);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id), type.basetype, get_metal_resource_index(var, type.basetype), 0 });
// Emulate texture2D atomic operations
if (atomic_image_vars.count(var.self))
{
uint32_t buffer_resource_index = get_metal_resource_index(var, SPIRType::AtomicCounter, 0);
resources_in_set[desc_set].push_back(
{ &var, to_name(var_id) + "_atomic", SPIRType::Struct, buffer_resource_index, 0 });
}
}
}
@@ -13675,6 +13731,30 @@ void CompilerMSL::analyze_argument_buffers()
buffer_type.member_types.push_back(get_variable_data_type_id(var));
set_qualified_name(var.self, join(to_name(buffer_variable_id), ".", mbr_name));
}
else if (atomic_image_vars.count(var.self))
{
// Emulate texture2D atomic operations.
// Don't set the qualified name: it's already set for this variable,
// and the code that references the buffer manually appends "_atomic"
// to the name.
uint32_t offset = ir.increase_bound_by(2);
uint32_t atomic_type_id = offset;
uint32_t type_ptr_id = offset + 1;
SPIRType atomic_type;
atomic_type.basetype = SPIRType::AtomicCounter;
atomic_type.width = 32;
atomic_type.vecsize = 1;
set<SPIRType>(atomic_type_id, atomic_type);
atomic_type.pointer = true;
atomic_type.parent_type = atomic_type_id;
atomic_type.storage = StorageClassStorageBuffer;
auto &atomic_ptr_type = set<SPIRType>(type_ptr_id, atomic_type);
atomic_ptr_type.self = atomic_type_id;
buffer_type.member_types.push_back(type_ptr_id);
}
else
{
// Resources will be declared as pointers not references, so automatically dereference as appropriate.
@@ -13712,3 +13792,13 @@ bool CompilerMSL::using_builtin_array() const
{
return msl_options.force_native_arrays || is_using_builtin_array;
}
void CompilerMSL::set_combined_sampler_suffix(const char *suffix)
{
sampler_name_suffix = suffix;
}
const char *CompilerMSL::get_combined_sampler_suffix() const
{
return sampler_name_suffix.c_str();
}

View File

@@ -268,6 +268,8 @@ public:
Platform platform = macOS;
uint32_t msl_version = make_msl_version(1, 2);
uint32_t texel_buffer_texture_width = 4096; // Width of 2D Metal textures used as 1D texel buffers
uint32_t r32ui_linear_texture_alignment = 4;
uint32_t r32ui_alignment_constant_id = 65535;
uint32_t swizzle_buffer_index = 30;
uint32_t indirect_params_buffer_index = 29;
uint32_t shader_output_buffer_index = 28;
@@ -556,6 +558,9 @@ public:
// to use for a particular location. The default is 4 if number of components is not overridden.
void set_fragment_output_components(uint32_t location, uint32_t components);
void set_combined_sampler_suffix(const char *suffix);
const char *get_combined_sampler_suffix() const;
protected:
// An enum of SPIR-V functions that are implemented in additional
// source code that is added to the shader if necessary.
@@ -842,8 +847,8 @@ protected:
bool does_shader_write_sample_mask = false;
void bitcast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void bitcast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
void cast_to_builtin_store(uint32_t target_id, std::string &expr, const SPIRType &expr_type) override;
void cast_from_builtin_load(uint32_t source_id, std::string &expr, const SPIRType &expr_type) override;
void emit_store_statement(uint32_t lhs_expression, uint32_t rhs_expression) override;
void analyze_sampled_image_usage();