From ec339b0282cdcc72e0acebbdb3653668f6ef4085 Mon Sep 17 00:00:00 2001 From: Ben Doherty Date: Thu, 8 Apr 2021 10:38:59 -0700 Subject: [PATCH] Fix texture swizzling crash with older Nvidia GPUs (#3779) --- filament/backend/src/metal/MetalContext.h | 3 +++ filament/backend/src/metal/MetalDriver.mm | 19 ++++++++++++++----- filament/backend/src/metal/MetalHandles.mm | 5 ++++- 3 files changed, 21 insertions(+), 6 deletions(-) diff --git a/filament/backend/src/metal/MetalContext.h b/filament/backend/src/metal/MetalContext.h index dad842f009..42163c99be 100644 --- a/filament/backend/src/metal/MetalContext.h +++ b/filament/backend/src/metal/MetalContext.h @@ -51,6 +51,9 @@ struct MetalContext { id pendingCommandBuffer = nullptr; id currentRenderPassEncoder = nullptr; + // Supported features. + bool supportsTextureSwizzling = false; + // Tracks resources used by command buffers. MetalResourceTracker resourceTracker; diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index b6706f8334..5b5375d5e8 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -78,6 +78,19 @@ MetalDriver::MetalDriver(backend::MetalPlatform* platform) noexcept << [mContext->device.name cStringUsingEncoding:NSUTF8StringEncoding] << "'" << utils::io::endl; + // In order to support texture swizzling, the GPU needs to support it and the system be running + // macOS 10.15+ / iOS 13+. + mContext->supportsTextureSwizzling = false; + if (@available(macOS 10.15, iOS 13, *)) { +#if defined(IOS) + mContext->supportsTextureSwizzling = + [mContext->device supportsFeatureSet:MTLFeatureSet_iOS_GPUFamily1_v1]; +#else + mContext->supportsTextureSwizzling = + [mContext->device supportsFeatureSet:MTLFeatureSet_macOS_GPUFamily2_v1]; +#endif + } + mContext->commandQueue = [mContext->device newCommandQueue]; mContext->commandQueue.label = @"Filament"; mContext->pipelineStateCache.setDevice(mContext->device); @@ -588,11 +601,7 @@ bool MetalDriver::isTextureFormatSupported(TextureFormat format) { } bool MetalDriver::isTextureSwizzleSupported() { - if (@available(macOS 10.15, iOS 13, *)) { - return true; - } else { - return false; - } + return mContext->supportsTextureSwizzling; } bool MetalDriver::isTextureFormatMipmappable(TextureFormat format) { diff --git a/filament/backend/src/metal/MetalHandles.mm b/filament/backend/src/metal/MetalHandles.mm index 7f089257f9..0a799aec9c 100644 --- a/filament/backend/src/metal/MetalHandles.mm +++ b/filament/backend/src/metal/MetalHandles.mm @@ -502,7 +502,10 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le a == TextureSwizzle::CHANNEL_3; // If texture is nil, then it must be a SAMPLER_EXTERNAL texture. We'll ignore this case for now. // TODO: implement swizzling for external textures. - if (!isDefaultSwizzle && texture) { + if (!isDefaultSwizzle && texture && context.supportsTextureSwizzling) { + // Even though we've already checked context.supportsTextureSwizzling, we still need to + // guard these calls with @availability, otherwise the API usage will generate compiler + // warnings. if (@available(macOS 10.15, iOS 13, *)) { NSUInteger slices = texture.arrayLength; if (texture.textureType == MTLTextureTypeCube ||