Browse Source

Updated spirv-cross.

Бранимир Караџић 6 days ago
parent
commit
3d59e16fd7

+ 8 - 0
3rdparty/spirv-cross/spirv_cross.cpp

@@ -742,6 +742,14 @@ bool Compiler::is_physical_pointer(const SPIRType &type) const
 	return type.op == OpTypePointer && type.storage == StorageClassPhysicalStorageBuffer;
 }
 
+bool Compiler::is_physical_or_buffer_pointer(const SPIRType &type) const
+{
+	return type.op == OpTypePointer &&
+	       (type.storage == StorageClassPhysicalStorageBuffer || type.storage == StorageClassUniform ||
+	        type.storage == StorageClassStorageBuffer || type.storage == StorageClassWorkgroup ||
+	        type.storage == StorageClassPushConstant);
+}
+
 bool Compiler::is_physical_pointer_to_buffer_block(const SPIRType &type) const
 {
 	return is_physical_pointer(type) && get_pointee_type(type).self == type.parent_type &&

+ 1 - 0
3rdparty/spirv-cross/spirv_cross.hpp

@@ -694,6 +694,7 @@ protected:
 	bool is_array(const SPIRType &type) const;
 	bool is_pointer(const SPIRType &type) const;
 	bool is_physical_pointer(const SPIRType &type) const;
+	bool is_physical_or_buffer_pointer(const SPIRType &type) const;
 	bool is_physical_pointer_to_buffer_block(const SPIRType &type) const;
 	static bool is_runtime_size_array(const SPIRType &type);
 	uint32_t expression_type_id(uint32_t id) const;

+ 53 - 9
3rdparty/spirv-cross/spirv_glsl.cpp

@@ -5051,10 +5051,10 @@ void CompilerGLSL::emit_polyfills(uint32_t polyfills, bool relaxed)
 // Returns a string representation of the ID, usable as a function arg.
 // Default is to simply return the expression representation fo the arg ID.
 // Subclasses may override to modify the return value.
-string CompilerGLSL::to_func_call_arg(const SPIRFunction::Parameter &, uint32_t id)
+string CompilerGLSL::to_func_call_arg(const SPIRFunction::Parameter &arg, uint32_t id)
 {
 	// BDA expects pointers through function interface.
-	if (is_physical_pointer(expression_type(id)))
+	if (!arg.alias_global_variable && is_physical_or_buffer_pointer(expression_type(id)))
 		return to_pointer_expression(id);
 
 	// Make sure that we use the name of the original variable, and not the parameter alias.
@@ -6896,6 +6896,16 @@ void CompilerGLSL::emit_uninitialized_temporary(uint32_t result_type, uint32_t r
 	}
 }
 
+bool CompilerGLSL::can_declare_inline_temporary(uint32_t id) const
+{
+	if (!block_temporary_hoisting && current_continue_block && !hoisted_temporaries.count(id))
+		return false;
+	if (hoisted_temporaries.count(id))
+		return false;
+
+	return true;
+}
+
 string CompilerGLSL::declare_temporary(uint32_t result_type, uint32_t result_id)
 {
 	auto &type = get<SPIRType>(result_type);
@@ -6973,6 +6983,42 @@ SPIRExpression &CompilerGLSL::emit_op(uint32_t result_type, uint32_t result_id,
 	}
 }
 
+void CompilerGLSL::emit_transposed_op(uint32_t result_type, uint32_t result_id, const string &rhs, bool forwarding)
+{
+	if (forwarding && (forced_temporaries.find(result_id) == end(forced_temporaries)))
+	{
+		// Just forward it without temporary.
+		// If the forward is trivial, we do not force flushing to temporary for this expression.
+		forwarded_temporaries.insert(result_id);
+		auto &e = set<SPIRExpression>(result_id, rhs, result_type, true);
+		e.need_transpose = true;
+	}
+	else if (can_declare_inline_temporary(result_id))
+	{
+		// If expression isn't immutable, bind it to a temporary and make the new temporary immutable (they always are).
+		// Since the expression is transposed, we have to ensure the temporary is the transposed type.
+
+		auto &transposed_type_id = extra_sub_expressions[result_id];
+		if (!transposed_type_id)
+		{
+			auto dummy_type = get<SPIRType>(result_type);
+			std::swap(dummy_type.columns, dummy_type.vecsize);
+			transposed_type_id = ir.increase_bound_by(1);
+			set<SPIRType>(transposed_type_id, dummy_type);
+		}
+
+		statement(declare_temporary(transposed_type_id, result_id), rhs, ";");
+		auto &e = set<SPIRExpression>(result_id, to_name(result_id), result_type, true);
+		e.need_transpose = true;
+	}
+	else
+	{
+		// If we cannot declare the temporary because it's already been hoisted, we don't have the
+		// chance to override the temporary type ourselves. Just transpose() the expression.
+		emit_op(result_type, result_id, join("transpose(", rhs, ")"), forwarding);
+	}
+}
+
 void CompilerGLSL::emit_unary_op(uint32_t result_type, uint32_t result_id, uint32_t op0, const char *op)
 {
 	bool forward = should_forward(op0);
@@ -11581,7 +11627,7 @@ bool CompilerGLSL::should_dereference(uint32_t id)
 	// If id is a variable but not a phi variable, we should not dereference it.
 	// BDA passed around as parameters are always pointers.
 	if (auto *var = maybe_get<SPIRVariable>(id))
-		return (var->parameter && is_physical_pointer(type)) || var->phi_variable;
+		return (var->parameter && is_physical_or_buffer_pointer(type)) || var->phi_variable;
 
 	if (auto *expr = maybe_get<SPIRExpression>(id))
 	{
@@ -11617,8 +11663,8 @@ bool CompilerGLSL::should_dereference(uint32_t id)
 bool CompilerGLSL::should_dereference_caller_param(uint32_t id)
 {
 	const auto &type = expression_type(id);
-	// BDA is always passed around as pointers.
-	if (is_physical_pointer(type))
+	// BDA is always passed around as pointers. Similarly, we need to pass variable buffer pointers as pointers.
+	if (is_physical_or_buffer_pointer(type))
 		return false;
 
 	return should_dereference(id);
@@ -13507,8 +13553,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
 			auto expr = join(enclose_expression(to_unpacked_row_major_matrix_expression(ops[3])), " * ",
 			                 enclose_expression(to_unpacked_row_major_matrix_expression(ops[2])));
 			bool forward = should_forward(ops[2]) && should_forward(ops[3]);
-			auto &e = emit_op(ops[0], ops[1], expr, forward);
-			e.need_transpose = true;
+			emit_transposed_op(ops[0], ops[1], expr, forward);
 			a->need_transpose = true;
 			b->need_transpose = true;
 			inherit_expression_dependencies(ops[1], ops[2]);
@@ -13531,8 +13576,7 @@ void CompilerGLSL::emit_instruction(const Instruction &instruction)
 			auto expr = join(enclose_expression(to_unpacked_row_major_matrix_expression(ops[2])), " * ",
 			                 to_enclosed_unpacked_expression(ops[3]));
 			bool forward = should_forward(ops[2]) && should_forward(ops[3]);
-			auto &e = emit_op(ops[0], ops[1], expr, forward);
-			e.need_transpose = true;
+			emit_transposed_op(ops[0], ops[1], expr, forward);
 			a->need_transpose = true;
 			inherit_expression_dependencies(ops[1], ops[2]);
 			inherit_expression_dependencies(ops[1], ops[3]);

+ 2 - 0
3rdparty/spirv-cross/spirv_glsl.hpp

@@ -763,6 +763,7 @@ protected:
 	bool expression_read_implies_multiple_reads(uint32_t id) const;
 	SPIRExpression &emit_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs,
 	                        bool suppress_usage_tracking = false);
+	void emit_transposed_op(uint32_t result_type, uint32_t result_id, const std::string &rhs, bool forward_rhs);
 
 	void access_chain_internal_append_index(std::string &expr, uint32_t base, const SPIRType *type,
 	                                        AccessChainFlags flags, bool &access_chain_is_arrayed, uint32_t index);
@@ -805,6 +806,7 @@ protected:
 	const char *index_to_swizzle(uint32_t index);
 	std::string remap_swizzle(const SPIRType &result_type, uint32_t input_components, const std::string &expr);
 	std::string declare_temporary(uint32_t type, uint32_t id);
+	bool can_declare_inline_temporary(uint32_t id) const;
 	void emit_uninitialized_temporary(uint32_t type, uint32_t id);
 	SPIRExpression &emit_uninitialized_temporary_expression(uint32_t type, uint32_t id);
 	virtual void append_global_func_args(const SPIRFunction &func, uint32_t index, SmallVector<std::string> &arglist);

+ 36 - 5
3rdparty/spirv-cross/spirv_hlsl.cpp

@@ -491,9 +491,9 @@ string CompilerHLSL::type_to_glsl(const SPIRType &type, uint32_t id)
 		case SPIRType::Double:
 			return join("double", type.vecsize);
 		case SPIRType::Int64:
-			return join("i64vec", type.vecsize);
+			return join("int64_t", type.vecsize);
 		case SPIRType::UInt64:
-			return join("u64vec", type.vecsize);
+			return join("uint64_t", type.vecsize);
 		default:
 			return "???";
 		}
@@ -1595,6 +1595,7 @@ void CompilerHLSL::replace_illegal_names()
 		"Texture3D", "TextureCube", "TextureCubeArray", "true", "typedef", "triangle",
 		"triangleadj", "TriangleStream", "uint", "uniform", "unorm", "unsigned",
 		"vector", "vertexfragment", "VertexShader", "vertices", "void", "volatile", "while",
+		"signed",
 	};
 
 	CompilerGLSL::replace_illegal_names(keywords);
@@ -1709,9 +1710,11 @@ void CompilerHLSL::emit_resources()
 		ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
 			auto &type = this->get<SPIRType>(var.basetype);
 
+			bool is_hidden = is_hidden_io_variable(var);
+
 			if (var.storage != StorageClassFunction && !var.remapped_variable && type.pointer &&
 			   (var.storage == StorageClassInput || var.storage == StorageClassOutput) && !is_builtin_variable(var) &&
-			   interface_variable_exists_in_entry_point(var.self))
+			   interface_variable_exists_in_entry_point(var.self) && !is_hidden)
 			{
 				// Builtin variables are handled separately.
 				emit_interface_block_globally(var);
@@ -1747,8 +1750,10 @@ void CompilerHLSL::emit_resources()
 		if (var.storage != StorageClassInput && var.storage != StorageClassOutput)
 			return;
 
+		bool is_hidden = is_hidden_io_variable(var);
+
 		if (!var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
-		    interface_variable_exists_in_entry_point(var.self))
+		    interface_variable_exists_in_entry_point(var.self) && !is_hidden)
 		{
 			if (block)
 			{
@@ -3482,10 +3487,12 @@ void CompilerHLSL::emit_hlsl_entry_point()
 		if (var.storage != StorageClassInput)
 			return;
 
+		bool is_hidden = is_hidden_io_variable(var);
+
 		bool need_matrix_unroll = var.storage == StorageClassInput && execution.model == ExecutionModelVertex;
 
 		if (!var.remapped_variable && type.pointer && !is_builtin_variable(var) &&
-		    interface_variable_exists_in_entry_point(var.self))
+		    interface_variable_exists_in_entry_point(var.self) && !is_hidden)
 		{
 			if (block)
 			{
@@ -7119,6 +7126,30 @@ bool CompilerHLSL::is_hlsl_force_storage_buffer_as_uav(ID id) const
 	return (force_uav_buffer_bindings.find({ desc_set, binding }) != force_uav_buffer_bindings.end());
 }
 
+bool CompilerHLSL::is_hidden_io_variable(const SPIRVariable &var) const
+{
+	if (!is_hidden_variable(var))
+		return false;
+
+	// It is too risky to remove stage IO variables that are linkable since it affects link compatibility.
+	// For vertex inputs and fragment outputs, it's less of a concern and we want reflection data
+	// to match reality.
+
+	bool is_external_linkage =
+			(get_execution_model() == ExecutionModelVertex && var.storage == StorageClassInput) ||
+			(get_execution_model() == ExecutionModelFragment && var.storage == StorageClassOutput);
+
+	if (!is_external_linkage)
+		return false;
+
+	// Unused output I/O variables might still be required to implement framebuffer fetch.
+	if (var.storage == StorageClassOutput && !is_legacy() &&
+	    location_is_framebuffer_fetch(get_decoration(var.self, DecorationLocation)) != 0)
+		return false;
+
+	return true;
+}
+
 void CompilerHLSL::set_hlsl_force_storage_buffer_as_uav(uint32_t desc_set, uint32_t binding)
 {
 	SetBindingPair pair = { desc_set, binding };

+ 1 - 0
3rdparty/spirv-cross/spirv_hlsl.hpp

@@ -298,6 +298,7 @@ private:
 	SPIRType::BaseType get_builtin_basetype(BuiltIn builtin, SPIRType::BaseType default_type) override;
 
 	bool is_hlsl_force_storage_buffer_as_uav(ID id) const;
+	bool is_hidden_io_variable(const SPIRVariable &var) const;
 
 	Options hlsl_options;
 

+ 63 - 28
3rdparty/spirv-cross/spirv_msl.cpp

@@ -1514,7 +1514,7 @@ void CompilerMSL::emit_entry_point_declarations()
 		if (is_array(type))
 		{
 			is_using_builtin_array = true;
-			statement(get_argument_address_space(var), " ", type_to_glsl(type), "* ", to_restrict(var_id, true), name,
+			statement(get_variable_address_space(var), " ", type_to_glsl(type), "* ", to_restrict(var_id, true), name,
 			          type_to_array_glsl(type, var_id), " =");
 
 			uint32_t array_size = get_resource_array_size(type, var_id);
@@ -1525,8 +1525,8 @@ void CompilerMSL::emit_entry_point_declarations()
 
 			for (uint32_t i = 0; i < array_size; i++)
 			{
-				statement("(", get_argument_address_space(var), " ", type_to_glsl(type), "* ",
-				          to_restrict(var_id, false), ")((", get_argument_address_space(var), " char* ",
+				statement("(", get_variable_address_space(var), " ", type_to_glsl(type), "* ",
+				          to_restrict(var_id, false), ")((", get_variable_address_space(var), " char* ",
 				          to_restrict(var_id, false), ")", to_name(arg_id), ".", dynamic_buffer.second.mbr_name,
 				          "[", i, "]", " + ", to_name(dynamic_offsets_buffer_id), "[", base_index + i, "]),");
 			}
@@ -1537,9 +1537,9 @@ void CompilerMSL::emit_entry_point_declarations()
 		}
 		else
 		{
-			statement(get_argument_address_space(var), " auto& ", to_restrict(var_id, true), name, " = *(",
-			          get_argument_address_space(var), " ", type_to_glsl(type), "* ", to_restrict(var_id, false), ")((",
-			          get_argument_address_space(var), " char* ", to_restrict(var_id, false), ")", to_name(arg_id), ".",
+			statement(get_variable_address_space(var), " auto& ", to_restrict(var_id, true), name, " = *(",
+			          get_variable_address_space(var), " ", type_to_glsl(type), "* ", to_restrict(var_id, false), ")((",
+			          get_variable_address_space(var), " char* ", to_restrict(var_id, false), ")", to_name(arg_id), ".",
 			          dynamic_buffer.second.mbr_name, " + ", to_name(dynamic_offsets_buffer_id), "[", base_index, "]);");
 		}
 	}
@@ -1594,7 +1594,7 @@ void CompilerMSL::emit_entry_point_declarations()
 				statement("spvDescriptorArray<sampler> ", name, "Smplr {", resource_name, "Smplr};");
 				break;
 			case SPIRType::Struct:
-				statement("spvDescriptorArray<", get_argument_address_space(var), " ", type_to_glsl(buffer_type), "*> ",
+				statement("spvDescriptorArray<", get_variable_address_space(var), " ", type_to_glsl(buffer_type), "*> ",
 				          name, " {", resource_name, "};");
 				break;
 			default:
@@ -1605,7 +1605,7 @@ void CompilerMSL::emit_entry_point_declarations()
 		else if (!type.array.empty() && type.basetype == SPIRType::Struct)
 		{
 			// Emit only buffer arrays here.
-			statement(get_argument_address_space(var), " ", type_to_glsl(buffer_type), "* ",
+			statement(get_variable_address_space(var), " ", type_to_glsl(buffer_type), "* ",
 			          to_restrict(var.self, true), name, "[] =");
 			begin_scope();
 			uint32_t array_size = get_resource_array_size(type, var.self);
@@ -1629,7 +1629,7 @@ void CompilerMSL::emit_entry_point_declarations()
 			continue;
 
 		const auto &type = get_variable_data_type(var);
-		auto addr_space = get_argument_address_space(var);
+		auto addr_space = get_variable_address_space(var);
 		// This resource name has already been added.
 		auto name = to_name(var_id);
 
@@ -10158,8 +10158,7 @@ void CompilerMSL::emit_instruction(const Instruction &instruction)
 			         enclose_expression(to_unpacked_row_major_matrix_expression(ops[2])), ")");
 
 			bool forward = should_forward(ops[2]) && should_forward(ops[3]);
-			auto &e = emit_op(ops[0], ops[1], expr, forward);
-			e.need_transpose = true;
+			emit_transposed_op(ops[0], ops[1], expr, forward);
 			a->need_transpose = true;
 			b->need_transpose = true;
 			inherit_expression_dependencies(ops[1], ops[2]);
@@ -11141,7 +11140,7 @@ void CompilerMSL::emit_atomic_func_op(uint32_t result_type, uint32_t result_id,
 		}
 		else if (var && ptr_type.storage != StorageClassPhysicalStorageBuffer)
 		{
-			exp += get_argument_address_space(*var);
+			exp += get_variable_address_space(*var);
 		}
 		else
 		{
@@ -14034,11 +14033,17 @@ bool CompilerMSL::uses_explicit_early_fragment_test()
 }
 
 // In MSL, address space qualifiers are required for all pointer or reference variables
-string CompilerMSL::get_argument_address_space(const SPIRVariable &argument)
+string CompilerMSL::get_variable_address_space(const SPIRVariable &argument)
 {
 	const auto &type = get<SPIRType>(argument.basetype);
-	// BDA is always passed around by value. There is no storage class for the argument itself.
-	if (is_physical_pointer(type))
+	return get_type_address_space(type, argument.self, true);
+}
+
+string CompilerMSL::get_leaf_argument_address_space(const SPIRVariable &argument)
+{
+	const auto &type = get<SPIRType>(argument.basetype);
+	// BDA and variable buffer pointer is always passed around by (pointer) value. There is no storage class for the argument itself.
+	if (is_physical_or_buffer_pointer(type))
 		return "";
 	return get_type_address_space(type, argument.self, true);
 }
@@ -14115,6 +14120,7 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id, bo
 		}
 		else if (!argument)
 		{
+			// This is used for helper UBOs we insert ourselves.
 			addr_space = "constant";
 		}
 		else if (type_is_msl_framebuffer_fetch(type))
@@ -14122,6 +14128,7 @@ string CompilerMSL::get_type_address_space(const SPIRType &type, uint32_t id, bo
 			// Subpass inputs are passed around by value.
 			addr_space = "";
 		}
+
 		break;
 
 	case StorageClassFunction:
@@ -14638,7 +14645,7 @@ string CompilerMSL::entry_point_args_argument_buffer(bool append_comma)
 
 		claimed_bindings.set(buffer_binding);
 
-		ep_args += get_argument_address_space(var) + " ";
+		ep_args += get_variable_address_space(var) + " ";
 
 		if (recursive_inputs.count(type.self))
 			ep_args += string("void* ") + to_restrict(id, true) + to_name(id) + "_vp";
@@ -14852,7 +14859,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
 				// Declare the primary alias as void*
 				if (!ep_args.empty())
 					ep_args += ", ";
-				ep_args += get_argument_address_space(var) + " void* " + primary_name;
+				ep_args += get_variable_address_space(var) + " void* " + primary_name;
 				ep_args += " [[buffer(" + convert_to_string(r.index) + ")";
 				if (interlocked_resources.count(var_id))
 					ep_args += ", raster_order_group(0)";
@@ -14900,7 +14907,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
 				{
 					if (!ep_args.empty())
 						ep_args += ", ";
-					ep_args += get_argument_address_space(var) + " " + type_to_glsl(type) + "* " +
+					ep_args += get_variable_address_space(var) + " " + type_to_glsl(type) + "* " +
 							   to_restrict(var_id, true) + r.name + "_" + convert_to_string(i);
 					ep_args += " [[buffer(" + convert_to_string(r.index + i) + ")";
 					if (interlocked_resources.count(var_id))
@@ -14913,7 +14920,7 @@ void CompilerMSL::entry_point_args_discrete_descriptors(string &ep_args)
 			{
 				if (!ep_args.empty())
 					ep_args += ", ";
-				ep_args += get_argument_address_space(var) + " ";
+				ep_args += get_variable_address_space(var) + " ";
 
 				if (recursive_inputs.count(type.self))
 					ep_args += string("void* ") + to_restrict(var_id, true) + r.name + "_vp";
@@ -15105,7 +15112,7 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
 		{
 			recursive_inputs.insert(type.self);
 			entry_func.fixup_hooks_in.push_back([this, &type, &var, var_id]() {
-				auto addr_space = get_argument_address_space(var);
+				auto addr_space = get_variable_address_space(var);
 				auto var_name = to_name(var_id);
 				statement(addr_space, " auto& ", to_restrict(var_id, true), var_name,
 				          " = *(", addr_space, " ", type_to_glsl(type), "*)", var_name, "_vp;");
@@ -15802,7 +15809,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
 
 	// Physical pointer types are passed by pointer, not reference.
 	auto &data_type = get_variable_data_type(var);
-	bool passed_by_value = is_physical_pointer(var_type);
+	bool passed_by_value = arg.alias_global_variable ? false : is_physical_or_buffer_pointer(var_type);
 	auto &type = passed_by_value ? var_type : data_type;
 
 	// If we need to modify the name of the variable, make sure we use the original variable.
@@ -15845,7 +15852,7 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
 	                              spv_function_implementations.count(SPVFuncImplDynamicImageSampler);
 
 	// Allow Metal to use the array<T> template to make arrays a value type
-	string address_space = get_argument_address_space(var);
+	string address_space = arg.alias_global_variable ? get_variable_address_space(var) : get_leaf_argument_address_space(var);
 	bool builtin = has_decoration(var.self, DecorationBuiltIn);
 	auto builtin_type = BuiltIn(get_decoration(arg.id, DecorationBuiltIn));
 
@@ -15942,10 +15949,29 @@ string CompilerMSL::argument_decl(const SPIRFunction::Parameter &arg)
 		}
 		else
 		{
-			if (!address_space.empty())
-				decl = join(address_space, " ", decl);
-			decl += " ";
-			decl += to_expression(name_id);
+			// Variable pointer to array is kinda awkward ...
+			bool pointer_to_logical_buffer_array =
+					!is_physical_pointer(type) && is_pointer(type) &&
+					has_decoration(type.parent_type, DecorationArrayStride);
+
+			if (pointer_to_logical_buffer_array)
+			{
+				decl.pop_back();
+				decl += " (*";
+				decl += to_expression(name_id);
+				decl += ")";
+				bool old_is_using_builtin_array = is_using_builtin_array;
+				is_using_builtin_array = true;
+				decl += type_to_array_glsl(type, name_id);
+				is_using_builtin_array = old_is_using_builtin_array;
+			}
+			else
+			{
+				if (!address_space.empty())
+					decl = join(address_space, " ", decl);
+				decl += " ";
+				decl += to_expression(name_id);
+			}
 		}
 	}
 	else if (is_array(type) && !type_is_image)
@@ -16252,6 +16278,7 @@ const std::unordered_set<std::string> &CompilerMSL::get_reserved_keyword_set()
 		"quad_broadcast",
 		"thread",
 		"threadgroup",
+		"signed",
 	};
 
 	return keywords;
@@ -16395,6 +16422,7 @@ const std::unordered_set<std::string> &CompilerMSL::get_illegal_func_names()
 		"uint16",
 		"float8",
 		"float16",
+		"signed",
 	};
 
 	return illegal_func_names;
@@ -16563,8 +16591,11 @@ string CompilerMSL::type_to_glsl(const SPIRType &type, uint32_t id, bool member)
 			// the C-style nesting works right.
 			// FIXME: This is somewhat of a hack.
 			bool old_is_using_builtin_array = is_using_builtin_array;
+			bool pointer_to_buffer_array = is_pointer(type) && has_decoration(type.parent_type, DecorationArrayStride);
 			if (is_physical_pointer(type))
 				is_using_builtin_array = false;
+			else if (pointer_to_buffer_array)
+				is_using_builtin_array = true;
 
 			type_name = join(type_address_space, " ", type_to_glsl(*p_parent_type, id));
 
@@ -17930,7 +17961,10 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
 		{
 			// thread_execution_width is an alias for threads_per_simdgroup, and it's only available since 1.0,
 			// but not in fragment.
-			return "thread_execution_width";
+            if (msl_options.supports_msl_version(3, 0))
+                return "threads_per_simdgroup";
+            else
+                return "thread_execution_width";
 		}
 
 	case BuiltInNumSubgroups:
@@ -17960,6 +17994,7 @@ string CompilerMSL::builtin_qualifier(BuiltIn builtin)
 			return "thread_index_in_simdgroup";
 		}
 		else if (execution.model == ExecutionModelKernel || execution.model == ExecutionModelGLCompute ||
+                 execution.model == ExecutionModelTaskEXT || execution.model == ExecutionModelMeshEXT ||
 		         execution.model == ExecutionModelTessellationControl ||
 		         (execution.model == ExecutionModelVertex && msl_options.vertex_for_tessellation))
 		{
@@ -19898,7 +19933,7 @@ void CompilerMSL::analyze_argument_buffers()
 		{
 			recursive_inputs.insert(type_id);
 			auto &entry_func = this->get<SPIRFunction>(ir.default_entry_point);
-			auto addr_space = get_argument_address_space(buffer_var);
+			auto addr_space = get_variable_address_space(buffer_var);
 			entry_func.fixup_hooks_in.push_back([this, addr_space, buffer_name, buffer_type_name]() {
 				statement(addr_space, " auto& ", buffer_name, " = *(", addr_space, " ", buffer_type_name, "*)", buffer_name, "_vp;");
 			});

+ 3 - 1
3rdparty/spirv-cross/spirv_msl.hpp

@@ -1126,7 +1126,9 @@ protected:
 	void mark_struct_members_packed(const SPIRType &type);
 	void ensure_member_packing_rules_msl(SPIRType &ib_type, uint32_t index);
 	bool validate_member_packing_rules_msl(const SPIRType &type, uint32_t index) const;
-	std::string get_argument_address_space(const SPIRVariable &argument);
+	std::string get_variable_address_space(const SPIRVariable &argument);
+	// Special case of get_variable_address_space which is only used for leaf functions.
+	std::string get_leaf_argument_address_space(const SPIRVariable &argument);
 	std::string get_type_address_space(const SPIRType &type, uint32_t id, bool argument = false);
 	bool decoration_flags_signal_volatile(const Bitset &flags) const;
 	bool decoration_flags_signal_coherent(const Bitset &flags) const;