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 <laszlo.agocs@qt.io>
This commit is contained in:
Ben Fletcher 2023-02-09 22:16:04 -08:00
parent 870a3011ed
commit d21e9a4326

View File

@ -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<MTLLibrary> 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<int, 8> 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<QShaderKey> 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<MTLLibrary> 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<MTLLibrary> 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<MTLLibrary> lib = [dev newLibraryWithSource: src options: opts error: &err];
[opts release];