فهرست منبع

Updated spirv-cross.

Бранимир Караџић 5 سال پیش
والد
کامیت
c6b37def25

+ 2 - 0
3rdparty/spirv-cross/spirv_cpp.cpp

@@ -306,6 +306,8 @@ void CompilerCPP::emit_resources()
 
 string CompilerCPP::compile()
 {
+	ir.fixup_reserved_names();
+
 	// Do not deal with ES-isms like precision, older extensions and such.
 	options.es = false;
 	options.version = 450;

+ 3 - 2
3rdparty/spirv-cross/spirv_cross_containers.hpp

@@ -328,8 +328,9 @@ public:
 			size_t target_capacity = buffer_capacity;
 			if (target_capacity == 0)
 				target_capacity = 1;
-			if (target_capacity < N)
-				target_capacity = N;
+
+			// Weird parens works around macro issues on Windows if NOMINMAX is not used.
+			target_capacity = (std::max)(target_capacity, N);
 
 			// Need to ensure there is a POT value of target capacity which is larger than count,
 			// otherwise this will overflow.

+ 158 - 44
3rdparty/spirv-cross/spirv_cross_parsed_ir.cpp

@@ -74,6 +74,8 @@ ParsedIR &ParsedIR::operator=(ParsedIR &&other) SPIRV_CROSS_NOEXCEPT
 		source = other.source;
 		loop_iteration_depth_hard = other.loop_iteration_depth_hard;
 		loop_iteration_depth_soft = other.loop_iteration_depth_soft;
+
+		meta_needing_name_fixup = std::move(other.meta_needing_name_fixup);
 	}
 	return *this;
 }
@@ -106,6 +108,8 @@ ParsedIR &ParsedIR::operator=(const ParsedIR &other)
 		addressing_model = other.addressing_model;
 		memory_model = other.memory_model;
 
+		meta_needing_name_fixup = other.meta_needing_name_fixup;
+
 		// Very deliberate copying of IDs. There is no default copy constructor, nor a simple default constructor.
 		// Construct object first so we have the correct allocator set-up, then we can copy object into our new pool group.
 		ids.clear();
@@ -134,42 +138,146 @@ static bool is_alpha(char c)
 	return (c >= 'a' && c <= 'z') || (c >= 'A' && c <= 'Z');
 }
 
+static bool is_numeric(char c)
+{
+	return c >= '0' && c <= '9';
+}
+
 static bool is_alphanumeric(char c)
 {
-	return is_alpha(c) || (c >= '0' && c <= '9');
+	return is_alpha(c) || is_numeric(c);
 }
 
-static string ensure_valid_identifier(const string &name, bool member)
+static bool is_valid_identifier(const string &name)
 {
-	// Functions in glslangValidator are mangled with name(<mangled> stuff.
-	// Normally, we would never see '(' in any legal identifiers, so just strip them out.
-	auto str = name.substr(0, name.find('('));
+	if (name.empty())
+		return true;
+
+	if (is_numeric(name[0]))
+		return false;
+
+	for (auto c : name)
+		if (!is_alphanumeric(c) && c != '_')
+			return false;
+
+	bool saw_underscore = false;
+	// Two underscores in a row is not a valid identifier either.
+	// Technically reserved, but it's easier to treat it as invalid.
+	for (auto c : name)
+	{
+		bool is_underscore = c == '_';
+		if (is_underscore && saw_underscore)
+			return false;
+		saw_underscore = is_underscore;
+	}
+
+	return true;
+}
+
+static bool is_reserved_prefix(const string &name)
+{
+	// Generic reserved identifiers used by the implementation.
+	return name.compare(0, 3, "gl_", 3) == 0 ||
+	       // Ignore this case for now, might rewrite internal code to always use spv prefix.
+	       //name.compare(0, 11, "SPIRV_Cross", 11) == 0 ||
+	       name.compare(0, 3, "spv", 3) == 0;
+}
+
+static bool is_reserved_identifier(const string &name, bool member, bool allow_reserved_prefixes)
+{
+	if (!allow_reserved_prefixes && is_reserved_prefix(name))
+		return true;
+
+	if (member)
+	{
+		// Reserved member identifiers come in one form:
+		// _m[0-9]+$.
+		if (name.size() < 3)
+			return false;
 
-	for (uint32_t i = 0; i < str.size(); i++)
+		if (name.compare(0, 2, "_m", 2) != 0)
+			return false;
+
+		size_t index = 2;
+		while (index < name.size() && is_numeric(name[index]))
+			index++;
+
+		return index == name.size();
+	}
+	else
 	{
-		auto &c = str[i];
+		// Reserved non-member identifiers come in two forms:
+		// _[0-9]+$, used for temporaries which map directly to a SPIR-V ID.
+		// _[0-9]+_, used for auxillary temporaries which derived from a SPIR-V ID.
+		if (name.size() < 2)
+			return false;
+
+		if (name[0] != '_' || !is_numeric(name[1]))
+			return false;
+
+		size_t index = 2;
+		while (index < name.size() && is_numeric(name[index]))
+			index++;
+
+		return index == name.size() || (index < name.size() && name[index] == '_');
+	}
+}
+
+bool ParsedIR::is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes)
+{
+	return is_reserved_identifier(str, false, allow_reserved_prefixes);
+}
+
+static string make_unreserved_identifier(const string &name)
+{
+	if (is_reserved_prefix(name))
+		return "_RESERVED_IDENTIFIER_FIXUP_" + name;
+	else
+		return "_RESERVED_IDENTIFIER_FIXUP" + name;
+}
 
-		if (member)
+void ParsedIR::sanitize_underscores(std::string &str)
+{
+	// Compact adjacent underscores to make it valid.
+	auto dst = str.begin();
+	auto src = dst;
+	bool saw_underscore = false;
+	while (src != str.end())
+	{
+		bool is_underscore = *src == '_';
+		if (saw_underscore && is_underscore)
 		{
-			// _m<num> variables are reserved by the internal implementation,
-			// otherwise, make sure the name is a valid identifier.
-			if (i == 0)
-				c = is_alpha(c) ? c : '_';
-			else if (i == 2 && str[0] == '_' && str[1] == 'm')
-				c = is_alpha(c) ? c : '_';
-			else
-				c = is_alphanumeric(c) ? c : '_';
+			src++;
 		}
 		else
 		{
-			// _<num> variables are reserved by the internal implementation,
-			// otherwise, make sure the name is a valid identifier.
-			if (i == 0 || (str[0] == '_' && i == 1))
-				c = is_alpha(c) ? c : '_';
-			else
-				c = is_alphanumeric(c) ? c : '_';
+			if (dst != src)
+				*dst = *src;
+			dst++;
+			src++;
+			saw_underscore = is_underscore;
 		}
 	}
+	str.erase(dst, str.end());
+}
+
+static string ensure_valid_identifier(const string &name)
+{
+	// Functions in glslangValidator are mangled with name(<mangled> stuff.
+	// Normally, we would never see '(' in any legal identifiers, so just strip them out.
+	auto str = name.substr(0, name.find('('));
+
+	if (str.empty())
+		return str;
+
+	if (is_numeric(str[0]))
+		str[0] = '_';
+
+	for (auto &c : str)
+		if (!is_alphanumeric(c) && c != '_')
+			c = '_';
+
+	ParsedIR::sanitize_underscores(str);
 	return str;
 }
 
@@ -195,35 +303,41 @@ const string &ParsedIR::get_member_name(TypeID id, uint32_t index) const
 		return empty_string;
 }
 
-void ParsedIR::set_name(ID id, const string &name)
+void ParsedIR::sanitize_identifier(std::string &name, bool member, bool allow_reserved_prefixes)
 {
-	auto &str = meta[id].decoration.alias;
-	str.clear();
-
-	if (name.empty())
-		return;
+	if (!is_valid_identifier(name))
+		name = ensure_valid_identifier(name);
+	if (is_reserved_identifier(name, member, allow_reserved_prefixes))
+		name = make_unreserved_identifier(name);
+}
 
-	// Reserved for temporaries.
-	if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
-		return;
+void ParsedIR::fixup_reserved_names()
+{
+	for (uint32_t id : meta_needing_name_fixup)
+	{
+		auto &m = meta[id];
+		sanitize_identifier(m.decoration.alias, false, false);
+		for (auto &memb : m.members)
+			sanitize_identifier(memb.alias, true, false);
+	}
+	meta_needing_name_fixup.clear();
+}
 
-	str = ensure_valid_identifier(name, false);
+void ParsedIR::set_name(ID id, const string &name)
+{
+	auto &m = meta[id];
+	m.decoration.alias = name;
+	if (!is_valid_identifier(name) || is_reserved_identifier(name, false, false))
+		meta_needing_name_fixup.insert(id);
 }
 
 void ParsedIR::set_member_name(TypeID id, uint32_t index, const string &name)
 {
-	meta[id].members.resize(max(meta[id].members.size(), size_t(index) + 1));
-
-	auto &str = meta[id].members[index].alias;
-	str.clear();
-	if (name.empty())
-		return;
-
-	// Reserved for unnamed members.
-	if (name[0] == '_' && name.size() >= 3 && name[1] == 'm' && isdigit(name[2]))
-		return;
-
-	str = ensure_valid_identifier(name, true);
+	auto &m = meta[id];
+	m.members.resize(max(meta[id].members.size(), size_t(index) + 1));
+	m.members[index].alias = name;
+	if (!is_valid_identifier(name) || is_reserved_identifier(name, true, false))
+		meta_needing_name_fixup.insert(id);
 }
 
 void ParsedIR::set_decoration_string(ID id, Decoration decoration, const string &argument)

+ 8 - 0
3rdparty/spirv-cross/spirv_cross_parsed_ir.hpp

@@ -208,6 +208,12 @@ public:
 
 	void make_constant_null(uint32_t id, uint32_t type, bool add_to_typed_id_set);
 
+	void fixup_reserved_names();
+
+	static void sanitize_underscores(std::string &str);
+	static void sanitize_identifier(std::string &str, bool member, bool allow_reserved_prefixes);
+	static bool is_globally_reserved_identifier(std::string &str, bool allow_reserved_prefixes);
+
 private:
 	template <typename T>
 	T &get(uint32_t id)
@@ -225,6 +231,8 @@ private:
 	mutable uint32_t loop_iteration_depth_soft = 0;
 	std::string empty_string;
 	Bitset cleared_bitset;
+
+	std::unordered_set<uint32_t> meta_needing_name_fixup;
 };
 } // namespace SPIRV_CROSS_NAMESPACE
 

+ 43 - 48
3rdparty/spirv-cross/spirv_glsl.cpp

@@ -145,32 +145,6 @@ static BufferPackingStandard packing_to_substruct_packing(BufferPackingStandard
 	}
 }
 
-// Sanitizes underscores for GLSL where multiple underscores in a row are not allowed.
-string CompilerGLSL::sanitize_underscores(const string &str)
-{
-	string res;
-	res.reserve(str.size());
-
-	bool last_underscore = false;
-	for (auto c : str)
-	{
-		if (c == '_')
-		{
-			if (last_underscore)
-				continue;
-
-			res += c;
-			last_underscore = true;
-		}
-		else
-		{
-			res += c;
-			last_underscore = false;
-		}
-	}
-	return res;
-}
-
 void CompilerGLSL::init()
 {
 	if (ir.source.known)
@@ -529,6 +503,8 @@ void CompilerGLSL::find_static_extensions()
 
 string CompilerGLSL::compile()
 {
+	ir.fixup_reserved_names();
+
 	if (options.vulkan_semantics)
 		backend.allow_precision_qualifiers = true;
 	else
@@ -2150,7 +2126,7 @@ void CompilerGLSL::emit_flattened_io_block_member(const std::string &basename, c
 
 	// Sanitize underscores because joining the two identifiers might create more than 1 underscore in a row,
 	// which is not allowed.
-	flattened_name = sanitize_underscores(flattened_name);
+	ParsedIR::sanitize_underscores(flattened_name);
 
 	uint32_t last_index = indices.back();
 
@@ -2693,6 +2669,23 @@ bool CompilerGLSL::should_force_emit_builtin_block(StorageClass storage)
 	return should_force;
 }
 
+void CompilerGLSL::fixup_implicit_builtin_block_names()
+{
+	ir.for_each_typed_id<SPIRVariable>([&](uint32_t, SPIRVariable &var) {
+		auto &type = this->get<SPIRType>(var.basetype);
+		bool block = has_decoration(type.self, DecorationBlock);
+		if ((var.storage == StorageClassOutput || var.storage == StorageClassInput) && block &&
+		    is_builtin_variable(var))
+		{
+			// Make sure the array has a supported name in the code.
+			if (var.storage == StorageClassOutput)
+				set_name(var.self, "gl_out");
+			else if (var.storage == StorageClassInput)
+				set_name(var.self, "gl_in");
+		}
+	});
+}
+
 void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionModel model)
 {
 	Bitset emitted_builtins;
@@ -2874,12 +2867,6 @@ void CompilerGLSL::emit_declared_builtin_block(StorageClass storage, ExecutionMo
 
 	if (builtin_array)
 	{
-		// Make sure the array has a supported name in the code.
-		if (storage == StorageClassOutput)
-			set_name(block_var->self, "gl_out");
-		else if (storage == StorageClassInput)
-			set_name(block_var->self, "gl_in");
-
 		if (model == ExecutionModelTessellationControl && storage == StorageClassOutput)
 			end_scope_decl(join(to_name(block_var->self), "[", get_entry_point().output_vertices, "]"));
 		else
@@ -2936,6 +2923,18 @@ void CompilerGLSL::emit_resources()
 	if (!pls_inputs.empty() || !pls_outputs.empty())
 		emit_pls();
 
+	switch (execution.model)
+	{
+	case ExecutionModelGeometry:
+	case ExecutionModelTessellationControl:
+	case ExecutionModelTessellationEvaluation:
+		fixup_implicit_builtin_block_names();
+		break;
+
+	default:
+		break;
+	}
+
 	// Emit custom gl_PerVertex for SSO compatibility.
 	if (options.separate_shader_objects && !options.es && execution.model != ExecutionModelFragment)
 	{
@@ -7793,7 +7792,9 @@ void CompilerGLSL::prepare_access_chain_for_scalar_access(std::string &, const S
 
 string CompilerGLSL::to_flattened_struct_member(const string &basename, const SPIRType &type, uint32_t index)
 {
-	return sanitize_underscores(join(basename, "_", to_member_name(type, index)));
+	auto ret = join(basename, "_", to_member_name(type, index));
+	ParsedIR::sanitize_underscores(ret);
+	return ret;
 }
 
 string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32_t count, const SPIRType &target_type,
@@ -7837,7 +7838,9 @@ string CompilerGLSL::access_chain(uint32_t base, const uint32_t *indices, uint32
 		}
 
 		auto basename = to_flattened_access_chain_expression(base);
-		return sanitize_underscores(join(basename, "_", chain));
+		auto ret = join(basename, "_", chain);
+		ParsedIR::sanitize_underscores(ret);
+		return ret;
 	}
 	else
 	{
@@ -7895,7 +7898,8 @@ void CompilerGLSL::store_flattened_struct(const string &basename, uint32_t rhs_i
 	for (uint32_t i = 0; i < uint32_t(member_type->member_types.size()); i++)
 	{
 		sub_indices.back() = i;
-		auto lhs = sanitize_underscores(join(basename, "_", to_member_name(*member_type, i)));
+		auto lhs = join(basename, "_", to_member_name(*member_type, i));
+		ParsedIR::sanitize_underscores(lhs);
 
 		if (get<SPIRType>(member_type->member_types[i]).basetype == SPIRType::Struct)
 		{
@@ -11435,13 +11439,7 @@ void CompilerGLSL::add_member_name(SPIRType &type, uint32_t index)
 		if (name.empty())
 			return;
 
-		// Reserved for temporaries.
-		if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
-		{
-			name.clear();
-			return;
-		}
-
+		ParsedIR::sanitize_identifier(name, true, true);
 		update_name_cache(type.member_name_cache, name);
 	}
 }
@@ -12167,16 +12165,13 @@ void CompilerGLSL::add_variable(unordered_set<string> &variables_primary,
 	if (name.empty())
 		return;
 
-	// Reserved for temporaries.
-	if (name[0] == '_' && name.size() >= 2 && isdigit(name[1]))
+	ParsedIR::sanitize_underscores(name);
+	if (ParsedIR::is_globally_reserved_identifier(name, true))
 	{
 		name.clear();
 		return;
 	}
 
-	// Avoid double underscores.
-	name = sanitize_underscores(name);
-
 	update_name_cache(variables_primary, variables_secondary, name);
 }
 

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

@@ -487,6 +487,7 @@ protected:
 	void emit_buffer_reference_block(SPIRType &type, bool forward_declaration);
 	void emit_buffer_block_legacy(const SPIRVariable &var);
 	void emit_buffer_block_flattened(const SPIRVariable &type);
+	void fixup_implicit_builtin_block_names();
 	void emit_declared_builtin_block(spv::StorageClass storage, spv::ExecutionModel model);
 	bool should_force_emit_builtin_block(spv::StorageClass storage);
 	void emit_push_constant_block_vulkan(const SPIRVariable &var);
@@ -757,8 +758,6 @@ protected:
 
 	virtual void declare_undefined_values();
 
-	static std::string sanitize_underscores(const std::string &str);
-
 	bool can_use_io_location(spv::StorageClass storage, bool block);
 	const Instruction *get_next_instruction_in_block(const Instruction &instr);
 	static uint32_t mask_relevant_memory_semantics(uint32_t semantics);

+ 11 - 4
3rdparty/spirv-cross/spirv_hlsl.cpp

@@ -971,7 +971,9 @@ std::string CompilerHLSL::builtin_to_glsl(spv::BuiltIn builtin, spv::StorageClas
 
 		auto &var = get<SPIRVariable>(num_workgroups_builtin);
 		auto &type = get<SPIRType>(var.basetype);
-		return sanitize_underscores(join(to_name(num_workgroups_builtin), "_", get_member_name(type.self, 0)));
+		auto ret = join(to_name(num_workgroups_builtin), "_", get_member_name(type.self, 0));
+		ParsedIR::sanitize_underscores(ret);
+		return ret;
 	}
 	case BuiltInPointCoord:
 		// Crude hack, but there is no real alternative. This path is only enabled if point_coord_compat is set.
@@ -2076,7 +2078,9 @@ void CompilerHLSL::emit_buffer_block(const SPIRVariable &var)
 				add_member_name(type, i);
 				auto backup_name = get_member_name(type.self, i);
 				auto member_name = to_member_name(type, i);
-				set_member_name(type.self, i, sanitize_underscores(join(to_name(var.self), "_", member_name)));
+				member_name = join(to_name(var.self), "_", member_name);
+				ParsedIR::sanitize_underscores(member_name);
+				set_member_name(type.self, i, member_name);
 				emit_struct_member(type, member, i, "");
 				set_member_name(type.self, i, backup_name);
 				i++;
@@ -2157,8 +2161,9 @@ void CompilerHLSL::emit_push_constant_block(const SPIRVariable &var)
 					add_member_name(type, constant_index);
 					auto backup_name = get_member_name(type.self, i);
 					auto member_name = to_member_name(type, i);
-					set_member_name(type.self, constant_index,
-					                sanitize_underscores(join(to_name(var.self), "_", member_name)));
+					member_name = join(to_name(var.self), "_", member_name);
+					ParsedIR::sanitize_underscores(member_name);
+					set_member_name(type.self, constant_index, member_name);
 					emit_struct_member(type, member, i, "", layout.start);
 					set_member_name(type.self, constant_index, backup_name);
 
@@ -5590,6 +5595,8 @@ void CompilerHLSL::validate_shader_model()
 
 string CompilerHLSL::compile()
 {
+	ir.fixup_reserved_names();
+
 	// Do not deal with ES-isms like precision, older extensions and such.
 	options.es = false;
 	options.version = 450;

+ 8 - 6
3rdparty/spirv-cross/spirv_msl.cpp

@@ -589,7 +589,7 @@ void CompilerMSL::build_implicit_builtins()
 			uint_type_ptr_out.pointer = true;
 			uint_type_ptr_out.parent_type = get_uint_type_id();
 			uint_type_ptr_out.storage = StorageClassOutput;
-			
+
 			auto &ptr_out_type = set<SPIRType>(offset, uint_type_ptr_out);
 			ptr_out_type.self = get_uint_type_id();
 			set<SPIRVariable>(var_id, offset, StorageClassOutput);
@@ -1028,6 +1028,8 @@ void CompilerMSL::emit_entry_point_declarations()
 
 string CompilerMSL::compile()
 {
+	ir.fixup_reserved_names();
+
 	// Do not deal with GLES-isms like precision, older extensions and such.
 	options.vulkan_semantics = true;
 	options.es = false;
@@ -2684,7 +2686,7 @@ uint32_t CompilerMSL::add_interface_block(StorageClass storage, bool patch)
 					statement("device ", to_name(ir.default_entry_point), "_", ib_var_ref, "* gl_in = &",
 					          input_buffer_var_name, "[min(", to_expression(builtin_invocation_id_id), ".x / ",
 					          get_entry_point().output_vertices,
-							  ", spvIndirectParams[1] - 1) * spvIndirectParams[0]];");
+					          ", spvIndirectParams[1] - 1) * spvIndirectParams[0]];");
 				}
 				else
 				{
@@ -10555,7 +10557,7 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
 		else if (var.storage == StorageClassOutput && is_builtin_variable(var))
 		{
 			if (bi_type == BuiltInSampleMask && get_execution_model() == ExecutionModelFragment &&
-				msl_options.additional_fixed_sample_mask != 0xffffffff)
+			    msl_options.additional_fixed_sample_mask != 0xffffffff)
 			{
 				// If the additional fixed sample mask was set, we need to adjust the sample_mask
 				// output to reflect that. If the shader outputs the sample_mask itself too, we need
@@ -10563,15 +10565,15 @@ void CompilerMSL::fix_up_shader_inputs_outputs()
 				if (does_shader_write_sample_mask)
 				{
 					entry_func.fixup_hooks_out.push_back([=]() {
-						statement(to_expression(builtin_sample_mask_id), " &= ",
-							      msl_options.additional_fixed_sample_mask, ";");
+						statement(to_expression(builtin_sample_mask_id),
+						          " &= ", msl_options.additional_fixed_sample_mask, ";");
 					});
 				}
 				else
 				{
 					entry_func.fixup_hooks_out.push_back([=]() {
 						statement(to_expression(builtin_sample_mask_id), " = ",
-							      msl_options.additional_fixed_sample_mask, ";");
+						          msl_options.additional_fixed_sample_mask, ";");
 					});
 				}
 			}