فهرست منبع

Add Metal Shading Language version options to shaderc. Reference version options from: https://developer.apple.com/documentation/metal/mtllanguageversion?language=objc (#3213)

Add configuration options for MSL compiler based on MSL version and Platform
Configure MSL->SPIR-V version configuration based on when ray tracing types become available
Set default metal compiler option to be metal 1.2, which is the default version assigned in the current SPIRV-Cross being used
pheonix 1 سال پیش
والد
کامیت
c00e4395b0
2فایلهای تغییر یافته به همراه144 افزوده شده و 20 حذف شده
  1. 42 9
      tools/shaderc/shaderc.cpp
  2. 102 11
      tools/shaderc/shaderc_metal.cpp

+ 42 - 9
tools/shaderc/shaderc.cpp

@@ -77,6 +77,25 @@ namespace bgfx
 	// 4.3    430      vhdgf+c
 	// 4.4    440
 	//
+	// Metal Shading Language (MSL) profile naming convention:
+	//  metal<MSL version>-<SPIR-V version>
+	//
+	// See section "Compiler Options Controlling the Language Version" from the
+	// MSL spec for the correlation between MSL version and platform OS version:
+	//	https://developer.apple.com/metal/Metal-Shading-Language-Specification.pdf
+	//
+	// MSL version | SPIR-V version | shaderc encoding
+	//    1.0      |       1.0      |      1000         (deprecated)
+	//    1.1      |       1.0      |      1110
+	//    1.2      |       1.0      |      1210
+	//    2.0      |       1.1      |      2011
+	//    2.1      |       1.1      |      2111
+	//    2.2      |       1.1      |      2211
+	//    2.3      |       1.4      |      2314
+	//    2.4      |       1.4      |      2414
+	//    3.0      |       1.4      |      3014
+	//    3.1      |       1.4      |      3114
+	//
 	// SPIR-V profile naming convention:
 	//  spirv<SPIR-V version>-<Vulkan version>
 	//
@@ -102,7 +121,17 @@ namespace bgfx
 		{  ShadingLang::ESSL,  320,    "320_es"     },
 		{  ShadingLang::HLSL,  400,    "s_4_0"      },
 		{  ShadingLang::HLSL,  500,    "s_5_0"      },
-		{  ShadingLang::Metal, 1000,   "metal"      },
+		{  ShadingLang::Metal, 1210,   "metal"      },
+		{  ShadingLang::Metal, 1000,   "metal10-10" },
+		{  ShadingLang::Metal, 1110,   "metal11-10" },
+		{  ShadingLang::Metal, 1210,   "metal12-10" },
+		{  ShadingLang::Metal, 2011,   "metal20-11" },
+		{  ShadingLang::Metal, 2111,   "metal21-11" },
+		{  ShadingLang::Metal, 2211,   "metal22-11" },
+		{  ShadingLang::Metal, 2314,   "metal23-14" },
+		{  ShadingLang::Metal, 2414,   "metal24-14" },
+		{  ShadingLang::Metal, 3014,   "metal30-14" },
+		{  ShadingLang::Metal, 3114,   "metal31-14" },
 		{  ShadingLang::PSSL,  1000,   "pssl"       },
 		{  ShadingLang::SpirV, 1010,   "spirv"      },
 		{  ShadingLang::SpirV, 1010,   "spirv10-10" },
@@ -1187,14 +1216,18 @@ namespace bgfx
 		else if (0 == bx::strCmpI(platform, "ios") )
 		{
 			preprocessor.setDefine("BX_PLATFORM_IOS=1");
-			if (profile->lang == ShadingLang::Metal)
-			{
-				preprocessor.setDefine("BGFX_SHADER_LANGUAGE_METAL=1");
-			}
-			else
+			if (profile->lang != ShadingLang::Metal)
 			{
 				preprocessor.setDefine(glslDefine);
 			}
+			char temp[32];
+			bx::snprintf(
+				temp
+				, sizeof(temp)
+				, "BGFX_SHADER_LANGUAGE_METAL=%d"
+				, (profile->lang == ShadingLang::Metal) ? profile->id : 0
+			);
+			preprocessor.setDefine(temp);
 		}
 		else if (0 == bx::strCmpI(platform, "linux") )
 		{
@@ -1517,7 +1550,7 @@ namespace bgfx
 			}
 			else if (profile->lang == ShadingLang::Metal)
 			{
-				compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), input, _shaderWriter, _messageWriter);
+				compiled = compileMetalShader(_options, profile->id, input, _shaderWriter, _messageWriter);
 			}
 			else if (profile->lang == ShadingLang::SpirV)
 			{
@@ -1674,7 +1707,7 @@ namespace bgfx
 
 							if (profile->lang == ShadingLang::Metal)
 							{
-								compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), code, _shaderWriter, _messageWriter);
+								compiled = compileMetalShader(_options, profile->id, code, _shaderWriter, _messageWriter);
 							}
 							else if (profile->lang == ShadingLang::SpirV)
 							{
@@ -2580,7 +2613,7 @@ namespace bgfx
 
 							if (profile->lang == ShadingLang::Metal)
 							{
-								compiled = compileMetalShader(_options, BX_MAKEFOURCC('M', 'T', 'L', 0), code, _shaderWriter, _messageWriter);
+								compiled = compileMetalShader(_options, profile->id, code, _shaderWriter, _messageWriter);
 							}
 							else if (profile->lang == ShadingLang::SpirV)
 							{

+ 102 - 11
tools/shaderc/shaderc_metal.cpp

@@ -266,6 +266,90 @@ namespace bgfx { namespace metal
 		return size;
 	}
 
+	static spv_target_env getSpirvTargetVersion(uint32_t _version, bx::WriterI* _messageWriter)
+	{
+		bx::ErrorAssert err;
+
+		switch (_version)
+		{
+		case 1000:
+		case 1110:
+		case 1210:
+			return SPV_ENV_VULKAN_1_0;
+		case 2011:
+		case 2111:
+		case 2211:
+			return SPV_ENV_VULKAN_1_1;
+		case 2314:
+		case 2414:
+		case 3014:
+		case 3114:
+			return SPV_ENV_VULKAN_1_1_SPIRV_1_4;
+		default:
+			bx::write(_messageWriter, &err, "Warning: Unknown SPIR-V version requested. Returning SPV_ENV_VULKAN_1_0 as default.\n");
+			return SPV_ENV_VULKAN_1_0;
+		}
+	}
+
+	static glslang::EShTargetLanguageVersion getGlslangTargetSpirvVersion(uint32_t _version, bx::WriterI* _messageWriter)
+	{
+		bx::ErrorAssert err;
+
+		switch (_version)
+		{
+		case 1000:
+		case 1110:
+		case 1210:
+			return glslang::EShTargetSpv_1_0;
+		case 2011:
+		case 2111:
+		case 2211:
+			return glslang::EShTargetSpv_1_1;
+		case 2314:
+		case 2414:
+		case 3014:
+		case 3114:
+			return glslang::EShTargetSpv_1_4;
+		default:
+			bx::write(_messageWriter, &err, "Warning: Unknown SPIR-V version requested. Returning EShTargetSpv_1_0 as default.\n");
+			return glslang::EShTargetSpv_1_0;
+		}
+	}
+
+	static spirv_cross::CompilerMSL::Options::Platform getMslPlatform(const std::string& _platform)
+	{
+		return "ios" == _platform
+			? spirv_cross::CompilerMSL::Options::Platform::iOS
+			: spirv_cross::CompilerMSL::Options::Platform::macOS;
+	}
+
+	static void getMSLVersion(const uint32_t _version, uint32_t& _major, uint32_t& _minor, bx::WriterI* _messageWriter)
+	{
+		bx::ErrorAssert err;
+
+		_major = _version / 1000;
+		_minor = (_version / 100) % 10;
+
+		switch (_version)
+		{
+		case 1000:
+		case 1110:
+		case 1210:
+		case 2011:
+		case 2111:
+		case 2211:
+		case 2314:
+		case 2414:
+		case 3014:
+		case 3114:
+			return;
+		default:
+			bx::write(_messageWriter, &err, "Warning: Unknown MSL version requested. Returning 1.0 as default.\n");
+			_major = 1;
+			_minor = 0;
+		}
+	}
+
 	static bool compile(const Options& _options, uint32_t _version, const std::string& _code, bx::WriterI* _shaderWriter, bx::WriterI* _messageWriter, bool _firstPass)
 	{
 		BX_UNUSED(_version);
@@ -294,6 +378,7 @@ namespace bgfx { namespace metal
 
 		shader->setEntryPoint("main");
 		shader->setAutoMapBindings(true);
+		shader->setEnvTarget(glslang::EShTargetSpv, getGlslangTargetSpirvVersion(_version, _messageWriter));
 		const int textureBindingOffset = 16;
 		shader->setShiftBinding(glslang::EResTexture, textureBindingOffset);
 		shader->setShiftBinding(glslang::EResSampler, textureBindingOffset);
@@ -503,7 +588,7 @@ namespace bgfx { namespace metal
 
 				glslang::GlslangToSpv(*intermediate, spirv, &options);
 
-				spvtools::Optimizer opt(SPV_ENV_VULKAN_1_0);
+				spvtools::Optimizer opt(getSpirvTargetVersion(_version, _messageWriter));
 
 				auto print_msg_to_stderr = [_messageWriter, &messageErr](
 					  spv_message_level_t
@@ -536,7 +621,7 @@ namespace bgfx { namespace metal
 				{
 					if (g_verbose)
 					{
-						glslang::SpirvToolsDisassemble(std::cout, spirv, SPV_ENV_VULKAN_1_0);
+						glslang::SpirvToolsDisassemble(std::cout, spirv, getSpirvTargetVersion(_version, _messageWriter));
 					}
 
 					spirv_cross::CompilerReflection refl(spirv);
@@ -566,10 +651,23 @@ namespace bgfx { namespace metal
 
 					bx::Error err;
 
-					if (_version == BX_MAKEFOURCC('M', 'T', 'L', 0) )
 					{
 						spirv_cross::CompilerMSL msl(std::move(spirv) );
 
+						// Configure MSL cross compiler
+						spirv_cross::CompilerMSL::Options mslOptions = msl.get_msl_options();
+						{
+							// - Platform
+							mslOptions.platform = getMslPlatform(_options.platform);
+
+							// - MSL Version
+							uint32_t major, minor;
+							getMSLVersion(_version, major, minor, _messageWriter);
+							mslOptions.set_msl_version(major, minor);
+
+						}
+						msl.set_msl_options(mslOptions);
+
 						auto executionModel = msl.get_execution_model();
 						spirv_cross::MSLResourceBinding newBinding;
 						newBinding.stage = executionModel;
@@ -683,14 +781,7 @@ namespace bgfx { namespace metal
 						uint8_t nul = 0;
 						bx::write(_shaderWriter, nul, &err);
 					}
-					else
-					{
-						uint32_t shaderSize = (uint32_t)spirv.size() * sizeof(uint32_t);
-						bx::write(_shaderWriter, shaderSize, &err);
-						bx::write(_shaderWriter, spirv.data(), shaderSize, &err);
-						uint8_t nul = 0;
-						bx::write(_shaderWriter, nul, &err);
-					}
+
 					//
 					const uint8_t numAttr = (uint8_t)program->getNumLiveAttributes();
 					bx::write(_shaderWriter, numAttr, &err);