From d21e9a432661b161d94cd4ee90804a4a9b122fe0 Mon Sep 17 00:00:00 2001 From: Ben Fletcher Date: Thu, 9 Feb 2023 22:16:04 -0800 Subject: [PATCH] rhi: Allow Metal shaders written in MSL versions greater than 2.0 The current rhi implementation only supports shaders written in MSL 1.2 or 2.0. The QtShaderTools/qsb tooling supports generation of shaders in newer MSL versions. This patch determines the platform's supported MSL versions at runtime, then selects the MSL shader with the highest supported version number from the available baked shaders. Change-Id: I5e3c0429179d1a5532a81df9ccbfe4db8c99c77a Reviewed-by: Laszlo Agocs --- src/gui/rhi/qrhimetal.mm | 47 ++++++++++++++++++++++++++++++---------- 1 file changed, 36 insertions(+), 11 deletions(-) diff --git a/src/gui/rhi/qrhimetal.mm b/src/gui/rhi/qrhimetal.mm index cf9112fe548..07b9a2af09a 100644 --- a/src/gui/rhi/qrhimetal.mm +++ b/src/gui/rhi/qrhimetal.mm @@ -4387,15 +4387,39 @@ static inline MTLTessellationPartitionMode toMetalTessellationPartitionMode(QSha } } +static inline MTLLanguageVersion toMetalLanguageVersion(const QShaderVersion &version) +{ + int v = version.version(); + return MTLLanguageVersion(((v / 10) << 16) + (v % 10)); +} + id QRhiMetalData::createMetalLib(const QShader &shader, QShader::Variant shaderVariant, QString *error, QByteArray *entryPoint, QShaderKey *activeKey) { - QShaderKey key = { QShader::MetalLibShader, 20, shaderVariant }; - QShaderCode mtllib = shader.shader(key); - if (mtllib.shader().isEmpty()) { - key.setSourceVersion(12); - mtllib = shader.shader(key); + QVarLengthArray versions; + if (@available(macOS 13, iOS 16, *)) + versions << 30; + if (@available(macOS 12, iOS 15, *)) + versions << 24; + if (@available(macOS 11, iOS 14, *)) + versions << 23; + if (@available(macOS 10.15, iOS 13, *)) + versions << 22; + if (@available(macOS 10.14, iOS 12, *)) + versions << 21; + versions << 20 << 12; + + const QList shaders = shader.availableShaders(); + + QShaderKey key; + + for (const int &version : versions) { + key = { QShader::Source::MetalLibShader, version, shaderVariant }; + if (shaders.contains(key)) + break; } + + QShaderCode mtllib = shader.shader(key); if (!mtllib.shader().isEmpty()) { dispatch_data_t data = dispatch_data_create(mtllib.shader().constData(), size_t(mtllib.shader().size()), @@ -4414,12 +4438,13 @@ id QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var } } - key = { QShader::MslShader, 20, shaderVariant }; - QShaderCode mslSource = shader.shader(key); - if (mslSource.shader().isEmpty()) { - key.setSourceVersion(12); - mslSource = shader.shader(key); + for (const int &version : versions) { + key = { QShader::Source::MslShader, version, shaderVariant }; + if (shaders.contains(key)) + break; } + + QShaderCode mslSource = shader.shader(key); if (mslSource.shader().isEmpty()) { qWarning() << "No MSL 2.0 or 1.2 code found in baked shader" << shader; return nil; @@ -4427,7 +4452,7 @@ id QRhiMetalData::createMetalLib(const QShader &shader, QShader::Var NSString *src = [NSString stringWithUTF8String: mslSource.shader().constData()]; MTLCompileOptions *opts = [[MTLCompileOptions alloc] init]; - opts.languageVersion = key.sourceVersion() == 20 ? MTLLanguageVersion2_0 : MTLLanguageVersion1_2; + opts.languageVersion = toMetalLanguageVersion(key.sourceVersion()); NSError *err = nil; id lib = [dev newLibraryWithSource: src options: opts error: &err]; [opts release];