Browse Source

Updated spirv-cross.

Бранимир Караџић 4 years ago
parent
commit
03388977ab

+ 35 - 19
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<uint32_t, SmallVector<uint32_t>> case_constructs;
+		unordered_map<uint32_t, SmallVector<uint64_t>> case_constructs;
 		SmallVector<uint32_t> block_declaration_order;
-		SmallVector<uint32_t> literals_to_merge;
+		SmallVector<uint64_t> 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<uint32_t>(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<uint32_t> &labels,
+		const auto to_legacy_case_label = [&](uint32_t condition, const SmallVector<uint64_t> &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)
 			{

+ 1 - 0
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);

+ 1 - 0
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<T> template unless we force it off.
 	backend.can_return_array = !msl_options.force_native_arrays;

+ 1 - 1
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<uint64_t>(ops[i]) << 32) | ops[i + 1];
+				uint64_t value = (static_cast<uint64_t>(ops[i + 1]) << 32) | ops[i];
 				current_block->cases_64bit.push_back({ value, ops[i + 2] });
 			}
 		}