From 03388977ab460097f08e74f5fab01f715fa474c1 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?=D0=91=D1=80=D0=B0=D0=BD=D0=B8=D0=BC=D0=B8=D1=80=20=D0=9A?= =?UTF-8?q?=D0=B0=D1=80=D0=B0=D1=9F=D0=B8=D1=9B?= Date: Thu, 23 Dec 2021 19:15:30 -0800 Subject: [PATCH] Updated spirv-cross. --- 3rdparty/spirv-cross/spirv_glsl.cpp | 54 +++++++++++++++++---------- 3rdparty/spirv-cross/spirv_glsl.hpp | 1 + 3rdparty/spirv-cross/spirv_msl.cpp | 1 + 3rdparty/spirv-cross/spirv_parser.cpp | 2 +- 4 files changed, 38 insertions(+), 20 deletions(-) diff --git a/3rdparty/spirv-cross/spirv_glsl.cpp b/3rdparty/spirv-cross/spirv_glsl.cpp index 5c21518f3..cdc1c6b6e 100644 --- a/3rdparty/spirv-cross/spirv_glsl.cpp +++ b/3rdparty/spirv-cross/spirv_glsl.cpp @@ -3565,6 +3565,11 @@ void CompilerGLSL::emit_resources() (var.storage == StorageClassInput || var.storage == StorageClassOutput) && interface_variable_exists_in_entry_point(var.self) && !is_hidden) { + if (options.es && get_execution_model() == ExecutionModelVertex && var.storage == StorageClassInput && + type.array.size() == 1) + { + SPIRV_CROSS_THROW("OpenGL ES doesn't support array input variables in vertex shader."); + } emit_interface_block(var); emitted = true; } @@ -14768,13 +14773,13 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) case SPIRBlock::MultiSelect: { auto &type = expression_type(block.condition); - bool unsigned_case = - type.basetype == SPIRType::UInt || type.basetype == SPIRType::UShort || type.basetype == SPIRType::UByte; + bool unsigned_case = type.basetype == SPIRType::UInt || type.basetype == SPIRType::UShort || + type.basetype == SPIRType::UByte || type.basetype == SPIRType::UInt64; if (block.merge == SPIRBlock::MergeNone) SPIRV_CROSS_THROW("Switch statement is not structured"); - if (type.basetype == SPIRType::UInt64 || type.basetype == SPIRType::Int64) + if (!backend.support_64bit_switch && (type.basetype == SPIRType::UInt64 || type.basetype == SPIRType::Int64)) { // SPIR-V spec suggests this is allowed, but we cannot support it in higher level languages. SPIRV_CROSS_THROW("Cannot use 64-bit switch selectors."); @@ -14783,6 +14788,10 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) const char *label_suffix = ""; if (type.basetype == SPIRType::UInt && backend.uint32_t_literal_suffix) label_suffix = "u"; + else if (type.basetype == SPIRType::Int64 && backend.support_64bit_switch) + label_suffix = "l"; + else if (type.basetype == SPIRType::UInt64 && backend.support_64bit_switch) + label_suffix = "ul"; else if (type.basetype == SPIRType::UShort) label_suffix = backend.uint16_t_literal_suffix; else if (type.basetype == SPIRType::Short) @@ -14795,9 +14804,9 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) statement("bool _", block.self, "_ladder_break = false;"); // Find all unique case constructs. - unordered_map> case_constructs; + unordered_map> case_constructs; SmallVector block_declaration_order; - SmallVector literals_to_merge; + SmallVector literals_to_merge; // If a switch case branches to the default block for some reason, we can just remove that literal from consideration // and let the default: block handle it. @@ -14806,21 +14815,17 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) auto &cases = get_case_list(block); for (auto &c : cases) { - // It's safe to cast to uint32_t since we actually do a check - // previously that we're not using uint64_t as the switch selector. - auto case_value = static_cast(c.value); - if (c.block != block.next_block && c.block != block.default_block) { if (!case_constructs.count(c.block)) block_declaration_order.push_back(c.block); - case_constructs[c.block].push_back(case_value); + case_constructs[c.block].push_back(c.value); } else if (c.block == block.next_block && block.default_block != block.next_block) { // We might have to flush phi inside specific case labels. // If we can piggyback on default:, do so instead. - literals_to_merge.push_back(case_value); + literals_to_merge.push_back(c.value); } } @@ -14865,11 +14870,22 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) size_t num_blocks = block_declaration_order.size(); - const auto to_case_label = [](uint32_t literal, bool is_unsigned_case) -> string { - return is_unsigned_case ? convert_to_string(literal) : convert_to_string(int32_t(literal)); + const auto to_case_label = [](uint64_t literal, uint32_t width, bool is_unsigned_case) -> string + { + if (is_unsigned_case) + return convert_to_string(literal); + + // For smaller cases, the literals are compiled as 32 bit wide + // literals so we don't need to care for all sizes specifically. + if (width <= 32) + { + return convert_to_string(int64_t(int32_t(literal))); + } + + return convert_to_string(int64_t(literal)); }; - const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector &labels, + const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector &labels, const char *suffix) -> string { string ret; size_t count = labels.size(); @@ -14911,7 +14927,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) auto &negative_literals = case_constructs[block_declaration_order[j]]; for (auto &case_label : negative_literals) conditions.push_back(join(to_enclosed_expression(block.condition), - " != ", to_case_label(case_label, unsigned_case))); + " != ", to_case_label(case_label, type.width, unsigned_case))); } statement("if (", merge(conditions, " && "), ")"); @@ -14925,7 +14941,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) conditions.reserve(literals.size()); for (auto &case_label : literals) conditions.push_back(join(to_enclosed_expression(block.condition), - " == ", to_case_label(case_label, unsigned_case))); + " == ", to_case_label(case_label, type.width, unsigned_case))); statement("if (", merge(conditions, " || "), ")"); begin_scope(); flush_phi(block.self, target_block); @@ -14940,7 +14956,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) // If there is only one default block, and no cases, this is a case where SPIRV-opt decided to emulate // non-structured exits with the help of a switch block. // This is buggy on FXC, so just emit the logical equivalent of a do { } while(false), which is more idiomatic. - bool degenerate_switch = block.default_block != block.merge_block && block.cases_32bit.empty(); + bool degenerate_switch = block.default_block != block.merge_block && cases.empty(); if (degenerate_switch || is_legacy_es()) { @@ -14989,7 +15005,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) for (auto &case_literal : literals) { // The case label value must be sign-extended properly in SPIR-V, so we can assume 32-bit values here. - statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":"); + statement("case ", to_case_label(case_literal, type.width, unsigned_case), label_suffix, ":"); } } } @@ -15027,7 +15043,7 @@ void CompilerGLSL::emit_block_chain(SPIRBlock &block) if ((header_merge_requires_phi && need_fallthrough_block) || !literals_to_merge.empty()) { for (auto &case_literal : literals_to_merge) - statement("case ", to_case_label(case_literal, unsigned_case), label_suffix, ":"); + statement("case ", to_case_label(case_literal, type.width, unsigned_case), label_suffix, ":"); if (block.default_block == block.next_block) { diff --git a/3rdparty/spirv-cross/spirv_glsl.hpp b/3rdparty/spirv-cross/spirv_glsl.hpp index 523624429..b34ed9930 100644 --- a/3rdparty/spirv-cross/spirv_glsl.hpp +++ b/3rdparty/spirv-cross/spirv_glsl.hpp @@ -586,6 +586,7 @@ protected: bool needs_row_major_load_workaround = false; bool support_pointer_to_pointer = false; bool support_precise_qualifier = false; + bool support_64bit_switch = false; } backend; void emit_struct(SPIRType &type); diff --git a/3rdparty/spirv-cross/spirv_msl.cpp b/3rdparty/spirv-cross/spirv_msl.cpp index fabf2e9cc..ffa69bfe7 100644 --- a/3rdparty/spirv-cross/spirv_msl.cpp +++ b/3rdparty/spirv-cross/spirv_msl.cpp @@ -1355,6 +1355,7 @@ string CompilerMSL::compile() backend.nonuniform_qualifier = ""; backend.support_small_type_sampling_result = true; backend.supports_empty_struct = true; + backend.support_64bit_switch = true; // Allow Metal to use the array template unless we force it off. backend.can_return_array = !msl_options.force_native_arrays; diff --git a/3rdparty/spirv-cross/spirv_parser.cpp b/3rdparty/spirv-cross/spirv_parser.cpp index da39367db..4faf3ca08 100644 --- a/3rdparty/spirv-cross/spirv_parser.cpp +++ b/3rdparty/spirv-cross/spirv_parser.cpp @@ -1029,7 +1029,7 @@ void Parser::parse(const Instruction &instruction) { for (uint32_t i = 2; i + 3 <= length; i += 3) { - uint64_t value = (static_cast(ops[i]) << 32) | ops[i + 1]; + uint64_t value = (static_cast(ops[i + 1]) << 32) | ops[i]; current_block->cases_64bit.push_back({ value, ops[i + 2] }); } }