mirror of
https://github.com/bkaradzic/bgfx.git
synced 2026-02-17 20:52:36 +01:00
Updated spirv-cross.
This commit is contained in:
16
3rdparty/spirv-cross/main.cpp
vendored
16
3rdparty/spirv-cross/main.cpp
vendored
@@ -658,10 +658,12 @@ struct CLIArguments
|
||||
bool msl_emulate_subgroups = false;
|
||||
uint32_t msl_fixed_subgroup_size = 0;
|
||||
bool msl_force_sample_rate_shading = false;
|
||||
const char *msl_combined_sampler_suffix = nullptr;
|
||||
bool glsl_emit_push_constant_as_ubo = false;
|
||||
bool glsl_emit_ubo_as_plain_uniforms = false;
|
||||
bool glsl_force_flattened_io_blocks = false;
|
||||
SmallVector<pair<uint32_t, uint32_t>> glsl_ext_framebuffer_fetch;
|
||||
bool glsl_ext_framebuffer_fetch_noncoherent = false;
|
||||
bool vulkan_glsl_disable_ext_samplerless_texture_functions = false;
|
||||
bool emit_line_directives = false;
|
||||
bool enable_storage_image_qualifier_deduction = true;
|
||||
@@ -754,6 +756,7 @@ static void print_help_glsl()
|
||||
"\t[--glsl-emit-ubo-as-plain-uniforms]:\n\t\tInstead of emitting UBOs, emit them as plain uniform structs.\n"
|
||||
"\t[--glsl-remap-ext-framebuffer-fetch input-attachment color-location]:\n\t\tRemaps an input attachment to use GL_EXT_shader_framebuffer_fetch.\n"
|
||||
"\t\tgl_LastFragData[location] is read from. The attachment to read from must be declared as an output in the shader.\n"
|
||||
"\t[--glsl-ext-framebuffer-fetch-noncoherent]:\n\t\tUses noncoherent qualifier for framebuffer fetch.\n"
|
||||
"\t[--vulkan-glsl-disable-ext-samplerless-texture-functions]:\n\t\tDo not allow use of GL_EXT_samperless_texture_functions, even in Vulkan GLSL.\n"
|
||||
"\t\tUse of texelFetch and similar might have to create dummy samplers to work around it.\n"
|
||||
"\t[--combined-samplers-inherit-bindings]:\n\t\tInherit binding information from the textures when building combined image samplers from separate textures and samplers.\n"
|
||||
@@ -882,7 +885,8 @@ static void print_help_msl()
|
||||
"\t\tIntended for Vulkan Portability implementations where VK_EXT_subgroup_size_control is not supported or disabled.\n"
|
||||
"\t\tIf 0, assume variable subgroup size as actually exposed by Metal.\n"
|
||||
"\t[--msl-force-sample-rate-shading]:\n\t\tForce fragment shaders to run per sample.\n"
|
||||
"\t\tThis adds a [[sample_id]] parameter if none is already present.\n");
|
||||
"\t\tThis adds a [[sample_id]] parameter if none is already present.\n"
|
||||
"\t[--msl-combined-sampler-suffix <suffix>]:\n\t\tUses a custom suffix for combined samplers.\n");
|
||||
// clang-format on
|
||||
}
|
||||
|
||||
@@ -1145,6 +1149,8 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
||||
msl_comp->add_inline_uniform_block(v.first, v.second);
|
||||
for (auto &v : args.msl_shader_inputs)
|
||||
msl_comp->add_msl_shader_input(v);
|
||||
if (args.msl_combined_sampler_suffix)
|
||||
msl_comp->set_combined_sampler_suffix(args.msl_combined_sampler_suffix);
|
||||
}
|
||||
else if (args.hlsl)
|
||||
compiler.reset(new CompilerHLSL(move(spirv_parser.get_parsed_ir())));
|
||||
@@ -1279,7 +1285,7 @@ static string compile_iteration(const CLIArguments &args, std::vector<uint32_t>
|
||||
compiler->set_common_options(opts);
|
||||
|
||||
for (auto &fetch : args.glsl_ext_framebuffer_fetch)
|
||||
compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second);
|
||||
compiler->remap_ext_framebuffer_fetch(fetch.first, fetch.second, !args.glsl_ext_framebuffer_fetch_noncoherent);
|
||||
|
||||
// Set HLSL specific options.
|
||||
if (args.hlsl)
|
||||
@@ -1469,6 +1475,9 @@ static int main_inner(int argc, char *argv[])
|
||||
uint32_t color_attachment = parser.next_uint();
|
||||
args.glsl_ext_framebuffer_fetch.push_back({ input_index, color_attachment });
|
||||
});
|
||||
cbs.add("--glsl-ext-framebuffer-fetch-noncoherent", [&args](CLIParser &) {
|
||||
args.glsl_ext_framebuffer_fetch_noncoherent = true;
|
||||
});
|
||||
cbs.add("--vulkan-glsl-disable-ext-samplerless-texture-functions",
|
||||
[&args](CLIParser &) { args.vulkan_glsl_disable_ext_samplerless_texture_functions = true; });
|
||||
cbs.add("--disable-storage-image-qualifier-deduction",
|
||||
@@ -1572,6 +1581,9 @@ static int main_inner(int argc, char *argv[])
|
||||
cbs.add("--msl-fixed-subgroup-size",
|
||||
[&args](CLIParser &parser) { args.msl_fixed_subgroup_size = parser.next_uint(); });
|
||||
cbs.add("--msl-force-sample-rate-shading", [&args](CLIParser &) { args.msl_force_sample_rate_shading = true; });
|
||||
cbs.add("--msl-combined-sampler-suffix", [&args](CLIParser &parser) {
|
||||
args.msl_combined_sampler_suffix = parser.next_string();
|
||||
});
|
||||
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();
|
||||
|
||||
65
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
65
3rdparty/spirv-cross/spirv_glsl.cpp
vendored
@@ -359,10 +359,26 @@ void CompilerGLSL::remap_pls_variables()
|
||||
}
|
||||
}
|
||||
|
||||
void CompilerGLSL::remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location)
|
||||
void CompilerGLSL::remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location, bool coherent)
|
||||
{
|
||||
subpass_to_framebuffer_fetch_attachment.push_back({ input_attachment_index, color_location });
|
||||
inout_color_attachments.insert(color_location);
|
||||
inout_color_attachments.push_back({ color_location, coherent });
|
||||
}
|
||||
|
||||
bool CompilerGLSL::location_is_framebuffer_fetch(uint32_t location) const
|
||||
{
|
||||
return std::find_if(begin(inout_color_attachments), end(inout_color_attachments),
|
||||
[&](const std::pair<uint32_t, bool> &elem) {
|
||||
return elem.first == location;
|
||||
}) != end(inout_color_attachments);
|
||||
}
|
||||
|
||||
bool CompilerGLSL::location_is_non_coherent_framebuffer_fetch(uint32_t location) const
|
||||
{
|
||||
return std::find_if(begin(inout_color_attachments), end(inout_color_attachments),
|
||||
[&](const std::pair<uint32_t, bool> &elem) {
|
||||
return elem.first == location && !elem.second;
|
||||
}) != end(inout_color_attachments);
|
||||
}
|
||||
|
||||
void CompilerGLSL::find_static_extensions()
|
||||
@@ -484,7 +500,22 @@ void CompilerGLSL::find_static_extensions()
|
||||
SPIRV_CROSS_THROW("Can only use GL_EXT_shader_framebuffer_fetch in fragment shaders.");
|
||||
if (options.vulkan_semantics)
|
||||
SPIRV_CROSS_THROW("Cannot use EXT_shader_framebuffer_fetch in Vulkan GLSL.");
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch");
|
||||
|
||||
bool has_coherent = false;
|
||||
bool has_incoherent = false;
|
||||
|
||||
for (auto &att : inout_color_attachments)
|
||||
{
|
||||
if (att.second)
|
||||
has_coherent = true;
|
||||
else
|
||||
has_incoherent = true;
|
||||
}
|
||||
|
||||
if (has_coherent)
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch");
|
||||
if (has_incoherent)
|
||||
require_extension_internal("GL_EXT_shader_framebuffer_fetch_non_coherent");
|
||||
}
|
||||
|
||||
if (options.separate_shader_objects && !options.es && options.version < 410)
|
||||
@@ -1693,6 +1724,12 @@ string CompilerGLSL::layout_for_variable(const SPIRVariable &var)
|
||||
attr.push_back(join("location = ", get_decoration(var.self, DecorationLocation)));
|
||||
}
|
||||
|
||||
if (get_execution_model() == ExecutionModelFragment && var.storage == StorageClassOutput &&
|
||||
location_is_non_coherent_framebuffer_fetch(get_decoration(var.self, DecorationLocation)))
|
||||
{
|
||||
attr.push_back("noncoherent");
|
||||
}
|
||||
|
||||
// Transform feedback
|
||||
bool uses_enhanced_layouts = false;
|
||||
if (is_block && var.storage == StorageClassOutput)
|
||||
@@ -2234,7 +2271,9 @@ const char *CompilerGLSL::to_storage_qualifiers_glsl(const SPIRVariable &var)
|
||||
return "varying "; // Fragment outputs are renamed so they never hit this case.
|
||||
else if (execution.model == ExecutionModelFragment && var.storage == StorageClassOutput)
|
||||
{
|
||||
if (inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
uint32_t loc = get_decoration(var.self, DecorationLocation);
|
||||
bool is_inout = location_is_framebuffer_fetch(loc);
|
||||
if (is_inout)
|
||||
return "inout ";
|
||||
else
|
||||
return "out ";
|
||||
@@ -3405,7 +3444,7 @@ void CompilerGLSL::emit_resources()
|
||||
|
||||
// Unused output I/O variables might still be required to implement framebuffer fetch.
|
||||
if (var.storage == StorageClassOutput && !is_legacy() &&
|
||||
inout_color_attachments.count(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
location_is_framebuffer_fetch(get_decoration(var.self, DecorationLocation)) != 0)
|
||||
{
|
||||
is_hidden = false;
|
||||
}
|
||||
@@ -4909,7 +4948,13 @@ string CompilerGLSL::convert_float_to_string(const SPIRConstant &c, uint32_t col
|
||||
|
||||
char print_buffer[32];
|
||||
sprintf(print_buffer, "0x%xu", c.scalar(col, row));
|
||||
res = join(bitcast_glsl_op(out_type, in_type), "(", print_buffer, ")");
|
||||
|
||||
const char *comment = "inf";
|
||||
if (float_value == -numeric_limits<float>::infinity())
|
||||
comment = "-inf";
|
||||
else if (std::isnan(float_value))
|
||||
comment = "nan";
|
||||
res = join(bitcast_glsl_op(out_type, in_type), "(", print_buffer, " /* ", comment, " */)");
|
||||
}
|
||||
else
|
||||
{
|
||||
@@ -4976,7 +5021,13 @@ std::string CompilerGLSL::convert_double_to_string(const SPIRConstant &c, uint32
|
||||
char print_buffer[64];
|
||||
sprintf(print_buffer, "0x%llx%s", static_cast<unsigned long long>(u64_value),
|
||||
backend.long_long_literal_suffix ? "ull" : "ul");
|
||||
res = join(bitcast_glsl_op(out_type, in_type), "(", print_buffer, ")");
|
||||
|
||||
const char *comment = "inf";
|
||||
if (double_value == -numeric_limits<double>::infinity())
|
||||
comment = "-inf";
|
||||
else if (std::isnan(double_value))
|
||||
comment = "nan";
|
||||
res = join(bitcast_glsl_op(out_type, in_type), "(", print_buffer, " /* ", comment, " */)");
|
||||
}
|
||||
else
|
||||
{
|
||||
|
||||
7
3rdparty/spirv-cross/spirv_glsl.hpp
vendored
7
3rdparty/spirv-cross/spirv_glsl.hpp
vendored
@@ -178,7 +178,8 @@ public:
|
||||
|
||||
// Redirect a subpassInput reading from input_attachment_index to instead load its value from
|
||||
// the color attachment at location = color_location. Requires ESSL.
|
||||
void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location);
|
||||
// If coherent, uses GL_EXT_shader_framebuffer_fetch, if not, uses noncoherent variant.
|
||||
void remap_ext_framebuffer_fetch(uint32_t input_attachment_index, uint32_t color_location, bool coherent);
|
||||
|
||||
explicit CompilerGLSL(std::vector<uint32_t> spirv_)
|
||||
: Compiler(std::move(spirv_))
|
||||
@@ -858,7 +859,9 @@ protected:
|
||||
|
||||
// GL_EXT_shader_framebuffer_fetch support.
|
||||
std::vector<std::pair<uint32_t, uint32_t>> subpass_to_framebuffer_fetch_attachment;
|
||||
std::unordered_set<uint32_t> inout_color_attachments;
|
||||
std::vector<std::pair<uint32_t, bool>> inout_color_attachments;
|
||||
bool location_is_framebuffer_fetch(uint32_t location) const;
|
||||
bool location_is_non_coherent_framebuffer_fetch(uint32_t location) const;
|
||||
bool subpass_input_is_framebuffer_fetch(uint32_t id) const;
|
||||
void emit_inout_fragment_outputs_copy_to_subpass_inputs();
|
||||
const SPIRVariable *find_subpass_input_by_attachment_index(uint32_t index) const;
|
||||
|
||||
234
3rdparty/spirv-cross/spirv_msl.cpp
vendored
234
3rdparty/spirv-cross/spirv_msl.cpp
vendored
@@ -1991,6 +1991,92 @@ uint32_t CompilerMSL::build_msl_interpolant_type(uint32_t type_id, bool is_noper
|
||||
return new_type_id;
|
||||
}
|
||||
|
||||
bool CompilerMSL::add_component_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
|
||||
SPIRVariable &var,
|
||||
const SPIRType &type,
|
||||
InterfaceBlockMeta &meta)
|
||||
{
|
||||
// Deal with Component decorations.
|
||||
const InterfaceBlockMeta::LocationMeta *location_meta = nullptr;
|
||||
uint32_t location = ~0u;
|
||||
if (has_decoration(var.self, DecorationLocation))
|
||||
{
|
||||
location = get_decoration(var.self, DecorationLocation);
|
||||
auto location_meta_itr = meta.location_meta.find(location);
|
||||
if (location_meta_itr != end(meta.location_meta))
|
||||
location_meta = &location_meta_itr->second;
|
||||
}
|
||||
|
||||
// Check if we need to pad fragment output to match a certain number of components.
|
||||
if (location_meta)
|
||||
{
|
||||
bool pad_fragment_output = has_decoration(var.self, DecorationLocation) &&
|
||||
msl_options.pad_fragment_output_components &&
|
||||
get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput;
|
||||
|
||||
auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
|
||||
uint32_t start_component = get_decoration(var.self, DecorationComponent);
|
||||
uint32_t type_components = type.vecsize;
|
||||
uint32_t num_components = location_meta->num_components;
|
||||
|
||||
if (pad_fragment_output)
|
||||
{
|
||||
uint32_t locn = get_decoration(var.self, DecorationLocation);
|
||||
num_components = std::max(num_components, get_target_components_for_fragment_location(locn));
|
||||
}
|
||||
|
||||
// We have already declared an IO block member as m_location_N.
|
||||
// Just emit an early-declared variable and fixup as needed.
|
||||
// Arrays need to be unrolled here since each location might need a different number of components.
|
||||
entry_func.add_local_variable(var.self);
|
||||
vars_needing_early_declaration.push_back(var.self);
|
||||
|
||||
if (var.storage == StorageClassInput)
|
||||
{
|
||||
entry_func.fixup_hooks_in.push_back([=, &type, &var]() {
|
||||
if (!type.array.empty())
|
||||
{
|
||||
uint32_t array_size = to_array_size_literal(type);
|
||||
for (uint32_t loc_off = 0; loc_off < array_size; loc_off++)
|
||||
{
|
||||
statement(to_name(var.self), "[", loc_off, "]", " = ", ib_var_ref,
|
||||
".m_location_", location + loc_off,
|
||||
vector_swizzle(type_components, start_component), ";");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(to_name(var.self), " = ", ib_var_ref, ".m_location_", location,
|
||||
vector_swizzle(type_components, start_component), ";");
|
||||
}
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
entry_func.fixup_hooks_out.push_back([=, &type, &var]() {
|
||||
if (!type.array.empty())
|
||||
{
|
||||
uint32_t array_size = to_array_size_literal(type);
|
||||
for (uint32_t loc_off = 0; loc_off < array_size; loc_off++)
|
||||
{
|
||||
statement(ib_var_ref, ".m_location_", location + loc_off,
|
||||
vector_swizzle(type_components, start_component), " = ",
|
||||
to_name(var.self), "[", loc_off, "];");
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
statement(ib_var_ref, ".m_location_", location,
|
||||
vector_swizzle(type_components, start_component), " = ", to_name(var.self), ";");
|
||||
}
|
||||
});
|
||||
}
|
||||
return true;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
}
|
||||
|
||||
void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, const string &ib_var_ref,
|
||||
SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta)
|
||||
{
|
||||
@@ -2019,65 +2105,14 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
|
||||
auto &entry_func = get<SPIRFunction>(ir.default_entry_point);
|
||||
|
||||
// Deal with Component decorations.
|
||||
InterfaceBlockMeta::LocationMeta *location_meta = nullptr;
|
||||
if (has_decoration(var.self, DecorationLocation))
|
||||
{
|
||||
auto location_meta_itr = meta.location_meta.find(get_decoration(var.self, DecorationLocation));
|
||||
if (location_meta_itr != end(meta.location_meta))
|
||||
location_meta = &location_meta_itr->second;
|
||||
}
|
||||
if (add_component_variable_to_interface_block(storage, ib_var_ref, var, type, meta))
|
||||
return;
|
||||
|
||||
bool pad_fragment_output = has_decoration(var.self, DecorationLocation) &&
|
||||
msl_options.pad_fragment_output_components &&
|
||||
get_entry_point().model == ExecutionModelFragment && storage == StorageClassOutput;
|
||||
|
||||
// Check if we need to pad fragment output to match a certain number of components.
|
||||
if (location_meta)
|
||||
{
|
||||
start_component = get_decoration(var.self, DecorationComponent);
|
||||
uint32_t num_components = location_meta->num_components;
|
||||
if (pad_fragment_output)
|
||||
{
|
||||
uint32_t locn = get_decoration(var.self, DecorationLocation);
|
||||
num_components = std::max(num_components, get_target_components_for_fragment_location(locn));
|
||||
}
|
||||
|
||||
if (location_meta->ib_index != ~0u)
|
||||
{
|
||||
// We have already declared the variable. Just emit an early-declared variable and fixup as needed.
|
||||
entry_func.add_local_variable(var.self);
|
||||
vars_needing_early_declaration.push_back(var.self);
|
||||
|
||||
if (var.storage == StorageClassInput)
|
||||
{
|
||||
uint32_t ib_index = location_meta->ib_index;
|
||||
entry_func.fixup_hooks_in.push_back([=, &var]() {
|
||||
statement(to_name(var.self), " = ", ib_var_ref, ".", to_member_name(ib_type, ib_index),
|
||||
vector_swizzle(type_components, start_component), ";");
|
||||
});
|
||||
}
|
||||
else
|
||||
{
|
||||
uint32_t ib_index = location_meta->ib_index;
|
||||
entry_func.fixup_hooks_out.push_back([=, &var]() {
|
||||
statement(ib_var_ref, ".", to_member_name(ib_type, ib_index),
|
||||
vector_swizzle(type_components, start_component), " = ", to_name(var.self), ";");
|
||||
});
|
||||
}
|
||||
return;
|
||||
}
|
||||
else
|
||||
{
|
||||
location_meta->ib_index = uint32_t(ib_type.member_types.size());
|
||||
type_id = build_extended_vector_type(type_id, num_components);
|
||||
if (var.storage == StorageClassInput)
|
||||
padded_input = true;
|
||||
else
|
||||
padded_output = true;
|
||||
}
|
||||
}
|
||||
else if (pad_fragment_output)
|
||||
if (pad_fragment_output)
|
||||
{
|
||||
uint32_t locn = get_decoration(var.self, DecorationLocation);
|
||||
target_components = get_target_components_for_fragment_location(locn);
|
||||
@@ -2169,11 +2204,8 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
uint32_t locn = get_decoration(var.self, DecorationLocation);
|
||||
if (storage == StorageClassInput)
|
||||
{
|
||||
type_id = ensure_correct_input_type(var.basetype, locn,
|
||||
location_meta ? location_meta->num_components : 0,
|
||||
meta.strip_array);
|
||||
if (!location_meta)
|
||||
var.basetype = type_id;
|
||||
type_id = ensure_correct_input_type(var.basetype, locn, 0, meta.strip_array);
|
||||
var.basetype = type_id;
|
||||
|
||||
type_id = get_pointee_type_id(type_id);
|
||||
if (meta.strip_array && is_array(get<SPIRType>(type_id)))
|
||||
@@ -2193,13 +2225,10 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
mark_location_as_used_by_shader(locn, type, storage);
|
||||
}
|
||||
|
||||
if (!location_meta)
|
||||
if (get_decoration_bitset(var.self).get(DecorationComponent))
|
||||
{
|
||||
if (get_decoration_bitset(var.self).get(DecorationComponent))
|
||||
{
|
||||
uint32_t component = get_decoration(var.self, DecorationComponent);
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationComponent, component);
|
||||
}
|
||||
uint32_t component = get_decoration(var.self, DecorationComponent);
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationComponent, component);
|
||||
}
|
||||
|
||||
if (get_decoration_bitset(var.self).get(DecorationIndex))
|
||||
@@ -2229,10 +2258,7 @@ void CompilerMSL::add_plain_variable_to_interface_block(StorageClass storage, co
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
// If we have location meta, there is no unique OrigID. We won't need it, since we flatten/unflatten
|
||||
// the variable to stack anyways here.
|
||||
if (!location_meta)
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
|
||||
set_extended_member_decoration(ib_type.self, ib_mbr_idx, SPIRVCrossDecorationInterfaceOrigID, var.self);
|
||||
}
|
||||
|
||||
void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage, const string &ib_var_ref,
|
||||
@@ -2243,6 +2269,9 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
auto &var_type = meta.strip_array ? get_variable_element_type(var) : get_variable_data_type(var);
|
||||
uint32_t elem_cnt = 0;
|
||||
|
||||
if (add_component_variable_to_interface_block(storage, ib_var_ref, var, var_type, meta))
|
||||
return;
|
||||
|
||||
if (is_matrix(var_type))
|
||||
{
|
||||
if (is_array(var_type))
|
||||
@@ -2339,6 +2368,7 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
if (get_decoration_bitset(var.self).get(DecorationLocation))
|
||||
{
|
||||
uint32_t locn = get_decoration(var.self, DecorationLocation) + i;
|
||||
uint32_t comp = get_decoration(var.self, DecorationComponent);
|
||||
if (storage == StorageClassInput)
|
||||
{
|
||||
var.basetype = ensure_correct_input_type(var.basetype, locn, 0, meta.strip_array);
|
||||
@@ -2349,6 +2379,8 @@ void CompilerMSL::add_composite_variable_to_interface_block(StorageClass storage
|
||||
ib_type.member_types[ib_mbr_idx] = mbr_type_id;
|
||||
}
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, locn);
|
||||
if (comp)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationComponent, comp);
|
||||
mark_location_as_used_by_shader(locn, *usable_type, storage);
|
||||
}
|
||||
else if (is_builtin && is_tessellation_shader() && inputs_by_builtin.count(builtin))
|
||||
@@ -3319,7 +3351,6 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
||||
// Need to deal specially with DecorationComponent.
|
||||
// Multiple variables can alias the same Location, and try to make sure each location is declared only once.
|
||||
// We will swizzle data in and out to make this work.
|
||||
// We only need to consider plain variables here, not composites.
|
||||
// This is only relevant for vertex inputs and fragment outputs.
|
||||
// Technically tessellation as well, but it is too complicated to support.
|
||||
uint32_t component = get_decoration(var_id, DecorationComponent);
|
||||
@@ -3329,8 +3360,22 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
||||
SPIRV_CROSS_THROW("Component decoration is not supported in tessellation shaders.");
|
||||
else if (pack_components)
|
||||
{
|
||||
auto &location_meta = meta.location_meta[location];
|
||||
location_meta.num_components = std::max(location_meta.num_components, component + type.vecsize);
|
||||
uint32_t array_size = 1;
|
||||
if (!type.array.empty())
|
||||
array_size = to_array_size_literal(type);
|
||||
|
||||
for (uint32_t location_offset = 0; location_offset < array_size; location_offset++)
|
||||
{
|
||||
auto &location_meta = meta.location_meta[location + location_offset];
|
||||
location_meta.num_components = std::max(location_meta.num_components, component + type.vecsize);
|
||||
|
||||
// For variables sharing location, decorations and base type must match.
|
||||
location_meta.base_type_id = type.self;
|
||||
location_meta.flat = has_decoration(var.self, DecorationFlat);
|
||||
location_meta.noperspective = has_decoration(var.self, DecorationNoPerspective);
|
||||
location_meta.centroid = has_decoration(var.self, DecorationCentroid);
|
||||
location_meta.sample = has_decoration(var.self, DecorationSample);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -3579,6 +3624,31 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
|
||||
}
|
||||
}
|
||||
|
||||
// When multiple variables need to access same location,
|
||||
// unroll locations one by one and we will flatten output or input as necessary.
|
||||
for (auto &loc : meta.location_meta)
|
||||
{
|
||||
uint32_t location = loc.first;
|
||||
auto &location_meta = loc.second;
|
||||
|
||||
uint32_t ib_mbr_idx = uint32_t(ib_type.member_types.size());
|
||||
uint32_t type_id = build_extended_vector_type(location_meta.base_type_id, location_meta.num_components);
|
||||
ib_type.member_types.push_back(type_id);
|
||||
|
||||
set_member_name(ib_type.self, ib_mbr_idx, join("m_location_", location));
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationLocation, location);
|
||||
mark_location_as_used_by_shader(location, get<SPIRType>(type_id), storage);
|
||||
|
||||
if (location_meta.flat)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationFlat);
|
||||
if (location_meta.noperspective)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationNoPerspective);
|
||||
if (location_meta.centroid)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationCentroid);
|
||||
if (location_meta.sample)
|
||||
set_member_decoration(ib_type.self, ib_mbr_idx, DecorationSample);
|
||||
}
|
||||
|
||||
// Sort the members of the structure by their locations.
|
||||
MemberSorter member_sorter(ib_type, ir.meta[ib_type_id], MemberSorter::LocationThenBuiltInType);
|
||||
member_sorter.sort();
|
||||
@@ -7075,7 +7145,17 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l
|
||||
uint32_t const_mbr_id = next_id++;
|
||||
uint32_t index = get_extended_decoration(ops[2], SPIRVCrossDecorationInterfaceMemberIndex);
|
||||
|
||||
if (flatten_composites || is_block)
|
||||
// If we have a pointer chain expression, and we are no longer pointing to a composite
|
||||
// object, we are in the clear. There is no longer a need to flatten anything.
|
||||
bool further_access_chain_is_trivial = false;
|
||||
if (ptr_is_chain && flatten_composites)
|
||||
{
|
||||
auto &ptr_type = expression_type(ptr);
|
||||
if (!is_array(ptr_type) && !is_matrix(ptr_type) && ptr_type.basetype != SPIRType::Struct)
|
||||
further_access_chain_is_trivial = true;
|
||||
}
|
||||
|
||||
if (!further_access_chain_is_trivial && (flatten_composites || is_block))
|
||||
{
|
||||
uint32_t i = first_non_array_index;
|
||||
auto *type = &get_variable_element_type(*var);
|
||||
@@ -7191,7 +7271,11 @@ bool CompilerMSL::emit_tessellation_access_chain(const uint32_t *ops, uint32_t l
|
||||
// First one is the gl_in/gl_out struct itself, then an index into that array.
|
||||
// If we have traversed further, we use a normal access chain formulation.
|
||||
auto *ptr_expr = maybe_get<SPIRExpression>(ptr);
|
||||
if (flatten_composites && ptr_expr && ptr_expr->implied_read_expressions.size() == 2)
|
||||
bool split_access_chain_formulation = flatten_composites && ptr_expr &&
|
||||
ptr_expr->implied_read_expressions.size() == 2 &&
|
||||
!further_access_chain_is_trivial;
|
||||
|
||||
if (split_access_chain_formulation)
|
||||
{
|
||||
e = join(to_expression(ptr),
|
||||
access_chain_internal(stage_var_id, indices.data(), uint32_t(indices.size()),
|
||||
@@ -15112,6 +15196,8 @@ bool CompilerMSL::MemberSorter::operator()(uint32_t mbr_idx1, uint32_t mbr_idx2)
|
||||
return mbr_meta2.builtin;
|
||||
else if (mbr_meta1.builtin)
|
||||
return mbr_meta1.builtin_type < mbr_meta2.builtin_type;
|
||||
else if (mbr_meta1.location == mbr_meta2.location)
|
||||
return mbr_meta1.component < mbr_meta2.component;
|
||||
else
|
||||
return mbr_meta1.location < mbr_meta2.location;
|
||||
}
|
||||
|
||||
9
3rdparty/spirv-cross/spirv_msl.hpp
vendored
9
3rdparty/spirv-cross/spirv_msl.hpp
vendored
@@ -799,8 +799,12 @@ protected:
|
||||
{
|
||||
struct LocationMeta
|
||||
{
|
||||
uint32_t base_type_id = 0;
|
||||
uint32_t num_components = 0;
|
||||
uint32_t ib_index = ~0u;
|
||||
bool flat = false;
|
||||
bool noperspective = false;
|
||||
bool centroid = false;
|
||||
bool sample = false;
|
||||
};
|
||||
std::unordered_map<uint32_t, LocationMeta> location_meta;
|
||||
bool strip_array = false;
|
||||
@@ -815,6 +819,9 @@ protected:
|
||||
SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta);
|
||||
void add_plain_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
|
||||
SPIRType &ib_type, SPIRVariable &var, InterfaceBlockMeta &meta);
|
||||
bool add_component_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
|
||||
SPIRVariable &var, const SPIRType &type,
|
||||
InterfaceBlockMeta &meta);
|
||||
void add_plain_member_variable_to_interface_block(spv::StorageClass storage, const std::string &ib_var_ref,
|
||||
SPIRType &ib_type, SPIRVariable &var, uint32_t index,
|
||||
InterfaceBlockMeta &meta);
|
||||
|
||||
Reference in New Issue
Block a user