Updated spirv-cross.

This commit is contained in:
Бранимир Караџић 2020-09-05 11:33:56 -07:00
parent 765b7b02eb
commit 248d56709e
8 changed files with 219 additions and 56 deletions

View File

@ -549,6 +549,7 @@ struct CLIArguments
bool msl_invariant_float_math = false;
bool msl_emulate_cube_array = false;
bool msl_multiview = false;
bool msl_multiview_layered_rendering = true;
bool msl_view_index_from_device_index = false;
bool msl_dispatch_base = false;
bool msl_decoration_binding = false;
@ -561,6 +562,7 @@ struct CLIArguments
bool msl_multi_patch_workgroup = false;
bool msl_vertex_for_tessellation = false;
uint32_t msl_additional_fixed_sample_mask = 0xffffffff;
bool msl_arrayed_subpass_input = false;
bool glsl_emit_push_constant_as_ubo = false;
bool glsl_emit_ubo_as_plain_uniforms = false;
bool glsl_force_flattened_io_blocks = false;
@ -732,6 +734,8 @@ static void print_help_msl()
"\t[--msl-device-argument-buffer <descriptor set index>]:\n\t\tUse device address space to hold indirect argument buffers instead of constant.\n"
"\t\tComes up when trying to support argument buffers which are larger than 64 KiB.\n"
"\t[--msl-multiview]:\n\t\tEnable SPV_KHR_multiview emulation.\n"
"\t[--msl-multiview-no-layered-rendering]:\n\t\tDon't set [[render_target_array_index]] in multiview shaders.\n"
"\t\tUseful for devices which don't support layered rendering. Only effective when --msl-multiview is enabled.\n"
"\t[--msl-view-index-from-device-index]:\n\t\tTreat the view index as the device index instead.\n"
"\t\tFor multi-GPU rendering.\n"
"\t[--msl-dispatch-base]:\n\t\tAdd support for vkCmdDispatchBase() or similar APIs.\n"
@ -762,7 +766,9 @@ static void print_help_msl()
"\t[--msl-vertex-for-tessellation]:\n\t\tWhen handling a vertex shader, marks it as one that will be used with a new-style tessellation control shader.\n"
"\t\tThe vertex shader is output to MSL as a compute kernel which outputs vertices to the buffer in the order they are received, rather than in index order as with --msl-capture-output normally.\n"
"\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\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");
// clang-format on
}
@ -987,6 +993,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
msl_opts.argument_buffers = args.msl_argument_buffers;
msl_opts.texture_buffer_native = args.msl_texture_buffer_native;
msl_opts.multiview = args.msl_multiview;
msl_opts.multiview_layered_rendering = args.msl_multiview_layered_rendering;
msl_opts.view_index_from_device_index = args.msl_view_index_from_device_index;
msl_opts.dispatch_base = args.msl_dispatch_base;
msl_opts.enable_decoration_binding = args.msl_decoration_binding;
@ -999,6 +1006,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
msl_opts.multi_patch_workgroup = args.msl_multi_patch_workgroup;
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_comp->set_msl_options(msl_opts);
for (auto &v : args.msl_discrete_descriptor_sets)
msl_comp->add_discrete_descriptor_set(v);
@ -1366,6 +1374,8 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl-invariant-float-math", [&args](CLIParser &) { args.msl_invariant_float_math = true; });
cbs.add("--msl-emulate-cube-array", [&args](CLIParser &) { args.msl_emulate_cube_array = true; });
cbs.add("--msl-multiview", [&args](CLIParser &) { args.msl_multiview = true; });
cbs.add("--msl-multiview-no-layered-rendering",
[&args](CLIParser &) { args.msl_multiview_layered_rendering = false; });
cbs.add("--msl-view-index-from-device-index",
[&args](CLIParser &) { args.msl_view_index_from_device_index = true; });
cbs.add("--msl-dispatch-base", [&args](CLIParser &) { args.msl_dispatch_base = true; });
@ -1416,6 +1426,7 @@ static int main_inner(int argc, char *argv[])
cbs.add("--msl-vertex-for-tessellation", [&args](CLIParser &) { args.msl_vertex_for_tessellation = true; });
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("--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

@ -658,6 +658,14 @@ spvc_result spvc_compiler_options_set_uint(spvc_compiler_options options, spvc_c
case SPVC_COMPILER_OPTION_MSL_VERTEX_INDEX_TYPE:
options->msl.vertex_index_type = static_cast<CompilerMSL::Options::IndexType>(value);
break;
case SPVC_COMPILER_OPTION_MSL_MULTIVIEW_LAYERED_RENDERING:
options->msl.multiview_layered_rendering = value != 0;
break;
case SPVC_COMPILER_OPTION_MSL_ARRAYED_SUBPASS_INPUT:
options->msl.arrayed_subpass_input = value != 0;
break;
#endif
default:

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 37
#define SPVC_C_API_VERSION_MINOR 39
/* Bumped if internal implementation details change. */
#define SPVC_C_API_VERSION_PATCH 0
@ -636,6 +636,9 @@ typedef enum spvc_compiler_option
SPVC_COMPILER_OPTION_GLSL_FORCE_FLATTENED_IO_BLOCKS = 66 | SPVC_COMPILER_OPTION_GLSL_BIT,
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_INT_MAX = 0x7fffffff
} spvc_compiler_option;

View File

@ -2881,11 +2881,16 @@ void CompilerGLSL::declare_undefined_values()
{
bool emitted = false;
ir.for_each_typed_id<SPIRUndef>([&](uint32_t, const SPIRUndef &undef) {
auto &type = this->get<SPIRType>(undef.basetype);
// OpUndef can be void for some reason ...
if (type.basetype == SPIRType::Void)
return;
string initializer;
if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get<SPIRType>(undef.basetype)))
if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
initializer = join(" = ", to_zero_initialized_expression(undef.basetype));
statement(variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self), initializer,
statement(variable_decl(type, to_name(undef.self), undef.self), initializer,
";");
emitted = true;
});
@ -9280,7 +9285,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
statement(declare_temporary(result_type, id), to_expression(vec), ";");
set<SPIRExpression>(id, to_name(id), result_type, true);
auto chain = access_chain_internal(id, &index, 1, 0, nullptr);
statement(chain, " = ", to_expression(comp), ";");
statement(chain, " = ", to_unpacked_expression(comp), ";");
break;
}
@ -9382,7 +9387,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
statement(declare_temporary(result_type, id), to_expression(composite), ";");
set<SPIRExpression>(id, to_name(id), result_type, true);
auto chain = access_chain_internal(id, elems, length, ACCESS_CHAIN_INDEX_IS_LITERAL_BIT, nullptr);
statement(chain, " = ", to_expression(obj), ";");
statement(chain, " = ", to_unpacked_expression(obj), ";");
break;
}
@ -9395,7 +9400,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
{
flush_variable_declaration(lhs);
flush_variable_declaration(rhs);
statement(to_expression(lhs), " = ", to_expression(rhs), ";");
statement(to_expression(lhs), " = ", to_unpacked_expression(rhs), ";");
register_write(lhs);
}
break;

View File

@ -1220,11 +1220,16 @@ void CompilerHLSL::declare_undefined_values()
{
bool emitted = false;
ir.for_each_typed_id<SPIRUndef>([&](uint32_t, const SPIRUndef &undef) {
auto &type = this->get<SPIRType>(undef.basetype);
// OpUndef can be void for some reason ...
if (type.basetype == SPIRType::Void)
return;
string initializer;
if (options.force_zero_initialized_variables && type_can_zero_initialize(this->get<SPIRType>(undef.basetype)))
if (options.force_zero_initialized_variables && type_can_zero_initialize(type))
initializer = join(" = ", to_zero_initialized_expression(undef.basetype));
statement("static ", variable_decl(this->get<SPIRType>(undef.basetype), to_name(undef.self), undef.self),
statement("static ", variable_decl(type, to_name(undef.self), undef.self),
initializer, ";");
emitted = true;
});

View File

@ -146,6 +146,7 @@ void CompilerMSL::build_implicit_builtins()
bool need_subgroup_ge_mask = !msl_options.is_ios() && (active_input_builtins.get(BuiltInSubgroupGeMask) ||
active_input_builtins.get(BuiltInSubgroupGtMask));
bool need_multiview = get_execution_model() == ExecutionModelVertex && !msl_options.view_index_from_device_index &&
msl_options.multiview_layered_rendering &&
(msl_options.multiview || active_input_builtins.get(BuiltInViewIndex));
bool need_dispatch_base =
msl_options.dispatch_base && get_execution_model() == ExecutionModelGLCompute &&
@ -172,6 +173,7 @@ void CompilerMSL::build_implicit_builtins()
bool has_subgroup_invocation_id = false;
bool has_subgroup_size = false;
bool has_view_idx = false;
bool has_layer = false;
uint32_t workgroup_id_type = 0;
// FIXME: Investigate the fact that there are no checks for the entry point interface variables.
@ -195,12 +197,32 @@ void CompilerMSL::build_implicit_builtins()
if (var.storage != StorageClassInput)
return;
if (need_subpass_input && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) &&
builtin == BuiltInFragCoord)
if (need_subpass_input && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses))
{
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var.self);
builtin_frag_coord_id = var.self;
has_frag_coord = true;
switch (builtin)
{
case BuiltInFragCoord:
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var.self);
builtin_frag_coord_id = var.self;
has_frag_coord = true;
break;
case BuiltInLayer:
if (!msl_options.arrayed_subpass_input || msl_options.multiview)
break;
mark_implicit_builtin(StorageClassInput, BuiltInLayer, var.self);
builtin_layer_id = var.self;
has_layer = true;
break;
case BuiltInViewIndex:
if (!msl_options.multiview)
break;
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var.self);
builtin_view_idx_id = var.self;
has_view_idx = true;
break;
default:
break;
}
}
if (need_sample_pos && builtin == BuiltInSampleId)
@ -282,6 +304,12 @@ void CompilerMSL::build_implicit_builtins()
mark_implicit_builtin(StorageClassInput, BuiltInInstanceIndex, var.self);
has_instance_idx = true;
break;
case BuiltInBaseInstance:
// If a non-zero base instance is used, we need to adjust for it when calculating the view index.
builtin_base_instance_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInBaseInstance, var.self);
has_base_instance = true;
break;
case BuiltInViewIndex:
builtin_view_idx_id = var.self;
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var.self);
@ -301,33 +329,79 @@ void CompilerMSL::build_implicit_builtins()
});
// Use Metal's native frame-buffer fetch API for subpass inputs.
if (!has_frag_coord && (!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) &&
need_subpass_input)
if ((!has_frag_coord || (msl_options.multiview && !has_view_idx) ||
(msl_options.arrayed_subpass_input && !msl_options.multiview && !has_layer)) &&
(!msl_options.is_ios() || !msl_options.ios_use_framebuffer_fetch_subpasses) && need_subpass_input)
{
uint32_t offset = ir.increase_bound_by(3);
uint32_t type_id = offset;
uint32_t type_ptr_id = offset + 1;
uint32_t var_id = offset + 2;
if (!has_frag_coord)
{
uint32_t offset = ir.increase_bound_by(3);
uint32_t type_id = offset;
uint32_t type_ptr_id = offset + 1;
uint32_t var_id = offset + 2;
// Create gl_FragCoord.
SPIRType vec4_type;
vec4_type.basetype = SPIRType::Float;
vec4_type.width = 32;
vec4_type.vecsize = 4;
set<SPIRType>(type_id, vec4_type);
// Create gl_FragCoord.
SPIRType vec4_type;
vec4_type.basetype = SPIRType::Float;
vec4_type.width = 32;
vec4_type.vecsize = 4;
set<SPIRType>(type_id, vec4_type);
SPIRType vec4_type_ptr;
vec4_type_ptr = vec4_type;
vec4_type_ptr.pointer = true;
vec4_type_ptr.parent_type = type_id;
vec4_type_ptr.storage = StorageClassInput;
auto &ptr_type = set<SPIRType>(type_ptr_id, vec4_type_ptr);
ptr_type.self = type_id;
SPIRType vec4_type_ptr;
vec4_type_ptr = vec4_type;
vec4_type_ptr.pointer = true;
vec4_type_ptr.parent_type = type_id;
vec4_type_ptr.storage = StorageClassInput;
auto &ptr_type = set<SPIRType>(type_ptr_id, vec4_type_ptr);
ptr_type.self = type_id;
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
set_decoration(var_id, DecorationBuiltIn, BuiltInFragCoord);
builtin_frag_coord_id = var_id;
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var_id);
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
set_decoration(var_id, DecorationBuiltIn, BuiltInFragCoord);
builtin_frag_coord_id = var_id;
mark_implicit_builtin(StorageClassInput, BuiltInFragCoord, var_id);
}
if (!has_layer && msl_options.arrayed_subpass_input && !msl_options.multiview)
{
uint32_t offset = ir.increase_bound_by(2);
uint32_t type_ptr_id = offset;
uint32_t var_id = offset + 1;
// Create gl_Layer.
SPIRType uint_type_ptr;
uint_type_ptr = get_uint_type();
uint_type_ptr.pointer = true;
uint_type_ptr.parent_type = get_uint_type_id();
uint_type_ptr.storage = StorageClassInput;
auto &ptr_type = set<SPIRType>(type_ptr_id, uint_type_ptr);
ptr_type.self = get_uint_type_id();
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
set_decoration(var_id, DecorationBuiltIn, BuiltInLayer);
builtin_layer_id = var_id;
mark_implicit_builtin(StorageClassInput, BuiltInLayer, var_id);
}
if (!has_view_idx && msl_options.multiview)
{
uint32_t offset = ir.increase_bound_by(2);
uint32_t type_ptr_id = offset;
uint32_t var_id = offset + 1;
// Create gl_ViewIndex.
SPIRType uint_type_ptr;
uint_type_ptr = get_uint_type();
uint_type_ptr.pointer = true;
uint_type_ptr.parent_type = get_uint_type_id();
uint_type_ptr.storage = StorageClassInput;
auto &ptr_type = set<SPIRType>(type_ptr_id, uint_type_ptr);
ptr_type.self = get_uint_type_id();
set<SPIRVariable>(var_id, type_ptr_id, StorageClassInput);
set_decoration(var_id, DecorationBuiltIn, BuiltInViewIndex);
builtin_view_idx_id = var_id;
mark_implicit_builtin(StorageClassInput, BuiltInViewIndex, var_id);
}
}
if (!has_sample_id && need_sample_pos)
@ -352,7 +426,7 @@ void CompilerMSL::build_implicit_builtins()
}
if ((need_vertex_params && (!has_vertex_idx || !has_base_vertex || !has_instance_idx || !has_base_instance)) ||
(need_multiview && (!has_instance_idx || !has_view_idx)))
(need_multiview && (!has_instance_idx || !has_base_instance || !has_view_idx)))
{
uint32_t type_ptr_id = ir.increase_bound_by(1);
@ -397,7 +471,7 @@ void CompilerMSL::build_implicit_builtins()
mark_implicit_builtin(StorageClassInput, BuiltInInstanceIndex, var_id);
}
if (need_vertex_params && !has_base_instance)
if (!has_base_instance) // Needed by both multiview and tessellation
{
uint32_t var_id = ir.increase_bound_by(1);
@ -1303,6 +1377,18 @@ void CompilerMSL::extract_global_variables_from_function(uint32_t func_id, std::
// Implicitly reads gl_FragCoord.
assert(builtin_frag_coord_id != 0);
added_arg_ids.insert(builtin_frag_coord_id);
if (msl_options.multiview)
{
// Implicitly reads gl_ViewIndex.
assert(builtin_view_idx_id != 0);
added_arg_ids.insert(builtin_view_idx_id);
}
else if (msl_options.arrayed_subpass_input)
{
// Implicitly reads gl_Layer.
assert(builtin_layer_id != 0);
added_arg_ids.insert(builtin_layer_id);
}
}
break;
@ -3904,7 +3990,7 @@ void CompilerMSL::emit_custom_templates()
// otherwise they will cause problems when linked together in a single Metallib.
void CompilerMSL::emit_custom_functions()
{
for (uint32_t i = SPVFuncImplArrayCopyMultidimMax; i >= 2; i--)
for (uint32_t i = kArrayCopyMultidimMax; i >= 2; i--)
if (spv_function_implementations.count(static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + i)))
spv_function_implementations.insert(static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + i - 1));
@ -5339,6 +5425,10 @@ void CompilerMSL::declare_undefined_values()
bool emitted = false;
ir.for_each_typed_id<SPIRUndef>([&](uint32_t, SPIRUndef &undef) {
auto &type = this->get<SPIRType>(undef.basetype);
// OpUndef can be void for some reason ...
if (type.basetype == SPIRType::Void)
return;
statement("constant ", variable_decl(type, to_name(undef.self), undef.self), " = {};");
emitted = true;
});
@ -7198,7 +7288,7 @@ void CompilerMSL::emit_array_copy(const string &lhs, uint32_t rhs_id, StorageCla
// if this is the only use of array copies in our shader.
if (type.array.size() > 1)
{
if (type.array.size() > SPVFuncImplArrayCopyMultidimMax)
if (type.array.size() > kArrayCopyMultidimMax)
SPIRV_CROSS_THROW("Cannot support this many dimensions for arrays of arrays.");
auto func = static_cast<SPVFuncImpl>(SPVFuncImplArrayCopyMultidimBase + type.array.size());
add_spv_func_and_recompile(func);
@ -8100,10 +8190,8 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
case DimSubpassData:
// If we're using Metal's native frame-buffer fetch API for subpass inputs,
// this path will not be hit.
if (imgtype.image.ms)
tex_coords = "uint2(gl_FragCoord.xy)";
else
tex_coords = join("uint2(gl_FragCoord.xy), 0");
tex_coords = "uint2(gl_FragCoord.xy)";
alt_coord_component = 2;
break;
case Dim2D:
@ -8220,12 +8308,30 @@ string CompilerMSL::to_function_args(const TextureFunctionArguments &args, bool
{
// Special case for cube arrays, face and layer are packed in one dimension.
if (imgtype.image.dim == DimCube && args.base.is_fetch)
{
farg_str += ", uint(" + to_extract_component_expression(args.coord, 2) + ") / 6u";
}
else
{
farg_str +=
", uint(" +
round_fp_tex_coords(to_extract_component_expression(args.coord, alt_coord_component), coord_is_fp) +
")";
if (imgtype.image.dim == DimSubpassData)
{
if (msl_options.multiview)
farg_str += " + gl_ViewIndex";
else if (msl_options.arrayed_subpass_input)
farg_str += " + gl_Layer";
}
}
}
else if (imgtype.image.dim == DimSubpassData)
{
if (msl_options.multiview)
farg_str += ", gl_ViewIndex";
else if (msl_options.arrayed_subpass_input)
farg_str += ", gl_Layer";
}
}
@ -9236,7 +9342,7 @@ string CompilerMSL::member_attribute_qualifier(const SPIRType &type, uint32_t in
switch (builtin)
{
case BuiltInViewIndex:
if (!msl_options.multiview)
if (!msl_options.multiview || !msl_options.multiview_layered_rendering)
break;
/* fallthrough */
case BuiltInFrontFacing:
@ -9654,7 +9760,8 @@ bool CompilerMSL::is_direct_input_builtin(BuiltIn bi_type)
case BuiltInBaryCoordNoPerspNV:
return false;
case BuiltInViewIndex:
return get_execution_model() == ExecutionModelFragment && msl_options.multiview;
return get_execution_model() == ExecutionModelFragment && msl_options.multiview &&
msl_options.multiview_layered_rendering;
// Any stage function in
case BuiltInDeviceIndex:
case BuiltInSubgroupEqMask:
@ -10424,6 +10531,15 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
// Since every physical device is rendering a different view,
// there's no need for layered rendering here.
}
else if (!msl_options.multiview_layered_rendering)
{
// In this case, the views are rendered one at a time. The view index, then,
// is just the first part of the "view mask".
entry_func.fixup_hooks_in.push_back([=]() {
statement("const ", builtin_type_decl(bi_type), " ", to_expression(var_id), " = ",
to_expression(view_mask_buffer_id), "[0];");
});
}
else if (get_execution_model() == ExecutionModelFragment)
{
// Because we adjusted the view index in the vertex shader, we have to
@ -10438,10 +10554,13 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
// the view index in the instance index.
entry_func.fixup_hooks_in.push_back([=]() {
statement(builtin_type_decl(bi_type), " ", to_expression(var_id), " = ",
to_expression(view_mask_buffer_id), "[0] + ", to_expression(builtin_instance_idx_id),
" % ", to_expression(view_mask_buffer_id), "[1];");
statement(to_expression(builtin_instance_idx_id), " /= ", to_expression(view_mask_buffer_id),
"[1];");
to_expression(view_mask_buffer_id), "[0] + (", to_expression(builtin_instance_idx_id),
" - ", to_expression(builtin_base_instance_id), ") % ",
to_expression(view_mask_buffer_id), "[1];");
statement(to_expression(builtin_instance_idx_id), " = (",
to_expression(builtin_instance_idx_id), " - ",
to_expression(builtin_base_instance_id), ") / ", to_expression(view_mask_buffer_id),
"[1] + ", to_expression(builtin_base_instance_id), ";");
});
// In addition to setting the variable itself, we also need to
// set the render_target_array_index with it on output. We have to
@ -11556,6 +11675,9 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
case Dim1D:
case Dim2D:
case DimSubpassData:
{
bool subpass_array =
img_type.dim == DimSubpassData && (msl_options.multiview || msl_options.arrayed_subpass_input);
if (img_type.dim == Dim1D && !msl_options.texture_1D_as_2D)
{
// Use a native Metal 1D texture
@ -11570,7 +11692,7 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
img_type_4.vecsize = 4;
return type_to_glsl(img_type_4);
}
if (img_type.ms && img_type.arrayed)
if (img_type.ms && (img_type.arrayed || subpass_array))
{
if (!msl_options.supports_msl_version(2, 1))
SPIRV_CROSS_THROW("Multisampled array textures are supported from 2.1.");
@ -11578,11 +11700,12 @@ string CompilerMSL::image_type_glsl(const SPIRType &type, uint32_t id)
}
else if (img_type.ms)
img_type_name += "texture2d_ms";
else if (img_type.arrayed)
else if (img_type.arrayed || subpass_array)
img_type_name += "texture2d_array";
else
img_type_name += "texture2d";
break;
}
case Dim3D:
img_type_name += "texture3d";
break;

View File

@ -249,6 +249,9 @@ static const uint32_t kArgumentBufferBinding = ~(3u);
static const uint32_t kMaxArgumentBuffers = 8;
// The arbitrary maximum for the nesting of array of array copies.
static const uint32_t kArrayCopyMultidimMax = 6;
// Decompiles SPIR-V to Metal Shading Language
class CompilerMSL : public CompilerGLSL
{
@ -290,6 +293,7 @@ public:
bool swizzle_texture_samples = false;
bool tess_domain_origin_lower_left = false;
bool multiview = false;
bool multiview_layered_rendering = true;
bool view_index_from_device_index = false;
bool dispatch_base = false;
bool texture_1D_as_2D = false;
@ -347,6 +351,12 @@ public:
// to index the output buffer.
bool vertex_for_tessellation = false;
// Assume that SubpassData images have multiple layers. Layered input attachments
// are addressed relative to the Layer output from the vertex pipeline. This option
// has no effect with multiview, since all input attachments are assumed to be layered
// and will be addressed using the current ViewIndex.
bool arrayed_subpass_input = false;
enum class IndexType
{
None = 0,
@ -614,8 +624,6 @@ protected:
SPVFuncImplConvertYCbCrBT601,
SPVFuncImplConvertYCbCrBT2020,
SPVFuncImplDynamicImageSampler,
SPVFuncImplArrayCopyMultidimMax = 6
};
// If the underlying resource has been used for comparison then duplicate loads of that resource must be too

View File

@ -647,7 +647,7 @@ void CompilerReflection::emit_specialization_constants()
return;
json_stream->emit_json_key_array("specialization_constants");
for (const auto spec_const : specialization_constants)
for (const auto &spec_const : specialization_constants)
{
auto &c = get<SPIRConstant>(spec_const.id);
auto type = get<SPIRType>(c.constant_type);