Skip to content

Commit

Permalink
Add Metal Shading Language version options to shaderc. Reference vers…
Browse files Browse the repository at this point in the history
…ion options from: https://developer.apple.com/documentation/metal/mtllanguageversion?language=objc (bkaradzic#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
  • Loading branch information
phniix authored and Michael Pekar committed Mar 2, 2024
1 parent 7c20233 commit fba6745
Show file tree
Hide file tree
Showing 2 changed files with 144 additions and 20 deletions.
51 changes: 42 additions & 9 deletions tools/shaderc/shaderc.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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>
//
Expand All @@ -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" },
Expand Down Expand Up @@ -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") )
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down Expand Up @@ -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)
{
Expand Down
113 changes: 102 additions & 11 deletions tools/shaderc/shaderc_metal.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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);
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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
Expand Down Expand Up @@ -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);
Expand Down Expand Up @@ -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;
Expand Down Expand Up @@ -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);
Expand Down

0 comments on commit fba6745

Please sign in to comment.