From ef4dfcecd6aec7492825f6743848c7d6149eb86c Mon Sep 17 00:00:00 2001 From: Ben Doherty Date: Thu, 21 Oct 2021 11:27:05 -0700 Subject: [PATCH] Metal: support framebuffer fetch on M1 devices (#4735) --- filament/backend/src/metal/MetalDriver.mm | 20 +++++++++++--------- filament/backend/src/metal/MetalHandles.mm | 3 +-- libs/filamat/src/GLSLPostProcessor.cpp | 10 ++++++++-- 3 files changed, 20 insertions(+), 13 deletions(-) diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index ac30da6bb6..f111dc613a 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -64,16 +64,19 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept initializeSupportedGpuFamilies(mContext); - utils::slog.d << "Supported GPU families: " << utils::io::endl; + utils::slog.v << "Supported GPU families: " << utils::io::endl; if (mContext->highestSupportedGpuFamily.common > 0) { - utils::slog.d << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl; + utils::slog.v << " MTLGPUFamilyCommon" << (int) mContext->highestSupportedGpuFamily.common << utils::io::endl; } if (mContext->highestSupportedGpuFamily.apple > 0) { - utils::slog.d << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl; + utils::slog.v << " MTLGPUFamilyApple" << (int) mContext->highestSupportedGpuFamily.apple << utils::io::endl; } if (mContext->highestSupportedGpuFamily.mac > 0) { - utils::slog.d << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl; + utils::slog.v << " MTLGPUFamilyMac" << (int) mContext->highestSupportedGpuFamily.mac << utils::io::endl; } + utils::slog.v << "Features:" << utils::io::endl; + utils::slog.v << " readWriteTextureSupport: " << + (bool) mContext->device.readWriteTextureSupport << utils::io::endl; // In order to support texture swizzling, the GPU needs to support it and the system be running // iOS 13+. @@ -650,11 +653,10 @@ bool MetalDriver::isRenderTargetFormatSupported(TextureFormat format) { } bool MetalDriver::isFrameBufferFetchSupported() { -#if defined(IOS) && !defined(FILAMENT_IOS_SIMULATOR) - return true; -#else - return false; -#endif + // FrameBuffer fetch is achievable via "programmable blending" in Metal, and only supported on + // Apple GPUs with readWriteTextureSupport. + return mContext->highestSupportedGpuFamily.apple >= 1 && + mContext->device.readWriteTextureSupport; } bool MetalDriver::isFrameBufferFetchMultiSampleSupported() { diff --git a/filament/backend/src/metal/MetalHandles.mm b/filament/backend/src/metal/MetalHandles.mm index 2e3dad5636..88133e15bb 100644 --- a/filament/backend/src/metal/MetalHandles.mm +++ b/filament/backend/src/metal/MetalHandles.mm @@ -352,8 +352,7 @@ MetalProgram::MetalProgram(id device, const Program& program) noexcep length:source.size() encoding:NSUTF8StringEncoding]; NSError* error = nil; - MTLCompileOptions* options = [MTLCompileOptions new]; - options.languageVersion = MTLLanguageVersion1_1; + // When options is nil, Metal uses the most recent language version available. id library = [device newLibraryWithSource:objcSource options:nil error:&error]; diff --git a/libs/filamat/src/GLSLPostProcessor.cpp b/libs/filamat/src/GLSLPostProcessor.cpp index 6c9de50f25..30d0f967f8 100644 --- a/libs/filamat/src/GLSLPostProcessor.cpp +++ b/libs/filamat/src/GLSLPostProcessor.cpp @@ -121,10 +121,16 @@ void GLSLPostProcessor::spirvToToMsl(const SpirvBlob *spirv, std::string *outMsl CompilerMSL::Options mslOptions = {}; mslOptions.platform = platform, - mslOptions.msl_version = CompilerMSL::Options::make_msl_version(1, 1); + mslOptions.msl_version = config.shaderModel == filament::backend::ShaderModel::GL_ES_30 ? + CompilerMSL::Options::make_msl_version(2, 0) : CompilerMSL::Options::make_msl_version(2, 2); - if (config.shaderModel == filament::backend::ShaderModel::GL_ES_30) { + if (config.hasFramebufferFetch) { mslOptions.use_framebuffer_fetch_subpasses = true; + // On macOS, framebuffer fetch is only available starting with MSL 2.3. Filament will only + // use framebuffer fetch materials on devices that support it. + if (config.shaderModel == filament::backend::ShaderModel::GL_CORE_41) { + mslOptions.msl_version = CompilerMSL::Options::make_msl_version(2, 3); + } } mslCompiler.set_msl_options(mslOptions);