From fba6745981f9fcf23289b55a748ddd5558adbf1d Mon Sep 17 00:00:00 2001 From: pheonix Date: Mon, 26 Feb 2024 23:08:51 -0800 Subject: [PATCH] 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 --- tools/shaderc/shaderc.cpp | 51 +++++++++++--- tools/shaderc/shaderc_metal.cpp | 113 ++++++++++++++++++++++++++++---- 2 files changed, 144 insertions(+), 20 deletions(-) diff --git a/tools/shaderc/shaderc.cpp b/tools/shaderc/shaderc.cpp index 8bff192699..bc9f1ade14 100644 --- a/tools/shaderc/shaderc.cpp +++ b/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- + // + // 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- // @@ -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) { diff --git a/tools/shaderc/shaderc_metal.cpp b/tools/shaderc/shaderc_metal.cpp index 48d73f83db..22125f198d 100644 --- a/tools/shaderc/shaderc_metal.cpp +++ b/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);