From 9a69a755bc373f746d1992d61012a4e30eff03a6 Mon Sep 17 00:00:00 2001 From: Benjamin Doherty Date: Mon, 29 Apr 2019 17:01:50 -0700 Subject: [PATCH] Add Metal support --- filament/backend/src/metal/MetalDriver.mm | 15 ++----- filament/backend/src/metal/MetalHandles.h | 4 +- filament/backend/src/metal/MetalHandles.mm | 49 ++++++++-------------- 3 files changed, 24 insertions(+), 44 deletions(-) diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index 4c30f16d82..5ad6602749 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -157,7 +157,7 @@ void MetalDriver::createRenderTargetR(Handle rth, auto colorTexture = handle_cast(mHandleMap, color.handle); return colorTexture->texture; } else if (targetBufferFlags & TargetBufferFlags::COLOR) { - ASSERT_POSTCONDITION(false, "A color buffer is required for a render target."); + ASSERT_POSTCONDITION(false, "The COLOR flag was specified, but no color texture provided."); } return nil; }; @@ -167,20 +167,13 @@ void MetalDriver::createRenderTargetR(Handle rth, auto depthTexture = handle_cast(mHandleMap, depth.handle); return depthTexture->texture; } else if (targetBufferFlags & TargetBufferFlags::DEPTH) { - MTLTextureDescriptor *depthTextureDesc = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:MTLPixelFormatDepth32Float - width:width - height:height - mipmapped:NO]; - depthTextureDesc.usage = MTLTextureUsageRenderTarget; - depthTextureDesc.resourceOptions = MTLResourceStorageModePrivate; - return [[mContext->device newTextureWithDescriptor:depthTextureDesc] autorelease]; + ASSERT_POSTCONDITION(false, "The DEPTH flag was specified, but no depth texture provided."); } return nil; }; -// construct_handle(mHandleMap, rth, mContext, width, height, samples, format, -// getColorTexture(), getDepthTexture()); + construct_handle(mHandleMap, rth, mContext, width, height, samples, + getColorTexture(), getDepthTexture()); ASSERT_POSTCONDITION( !stencil.handle && !(targetBufferFlags & TargetBufferFlags::STENCIL), diff --git a/filament/backend/src/metal/MetalHandles.h b/filament/backend/src/metal/MetalHandles.h index 94c8620dfa..fa837d398c 100644 --- a/filament/backend/src/metal/MetalHandles.h +++ b/filament/backend/src/metal/MetalHandles.h @@ -143,7 +143,7 @@ struct MetalSamplerGroup : public HwSamplerGroup { class MetalRenderTarget : public HwRenderTarget { public: MetalRenderTarget(MetalContext* context, uint32_t width, uint32_t height, uint8_t samples, - TextureFormat format, id color, id depth); + id color, id depth); explicit MetalRenderTarget(MetalContext* context) : HwRenderTarget(0, 0), context(context), defaultRenderTarget(true) {} ~MetalRenderTarget(); @@ -158,7 +158,7 @@ public: id getDepthResolve(); private: - static id createMultisampledTexture(id device, TextureFormat format, + static id createMultisampledTexture(id device, MTLPixelFormat format, uint32_t width, uint32_t height, uint8_t samples); MetalContext* context; diff --git a/filament/backend/src/metal/MetalHandles.mm b/filament/backend/src/metal/MetalHandles.mm index 05e14f52a1..cb6c27037b 100644 --- a/filament/backend/src/metal/MetalHandles.mm +++ b/filament/backend/src/metal/MetalHandles.mm @@ -28,7 +28,7 @@ namespace backend { namespace metal { static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) { - int u = 0; + NSUInteger u = 0; if (usage & TextureUsage::COLOR_ATTACHMENT) { u |= MTLTextureUsageRenderTarget; } @@ -38,32 +38,22 @@ static inline MTLTextureUsage getMetalTextureUsage(TextureUsage usage) { if (usage & TextureUsage::STENCIL_ATTACHMENT) { u |= MTLTextureUsageRenderTarget; } - if (usage & TextureUsage::UPLOADABLE) { - u |= MTLTextureUsageShaderWrite; - } - if (usage & TextureUsage::SAMPLEABLE) { - u |= MTLTextureUsageShaderRead; - } + + // All textures can be blitted from, so they must have the UsageShaderRead flag. + u |= MTLTextureUsageShaderRead; + return MTLTextureUsage(u); } -static inline MTLStorageMode getMetalStorageMode(TextureFormat format) { - switch (format) { - // Depth textures must have a private storage mode. - case TextureFormat::DEPTH16: - case TextureFormat::DEPTH24: - case TextureFormat::DEPTH32F: - case TextureFormat::DEPTH24_STENCIL8: - case TextureFormat::DEPTH32F_STENCIL8: - return MTLStorageModePrivate; - - default: +static inline MTLStorageMode getMetalStorageMode(TextureUsage usage) { + if (usage & TextureUsage::UPLOADABLE) { #if defined(IOS) - return MTLStorageModeShared; + return MTLStorageModeShared; #else - return MTLStorageModeManaged; + return MTLStorageModeManaged; #endif } + return MTLStorageModePrivate; } MetalSwapChain::MetalSwapChain(id device, CAMetalLayer* nativeWindow) @@ -291,7 +281,7 @@ MetalTexture::MetalTexture(MetalContext& context, backend::SamplerType target, u descriptor.mipmapLevelCount = levels; descriptor.textureType = MTLTextureType2D; descriptor.usage = getMetalTextureUsage(usage); - descriptor.storageMode = getMetalStorageMode(format); + descriptor.storageMode = getMetalStorageMode(usage); texture = [context.device newTextureWithDescriptor:descriptor]; } else if (target == backend::SamplerType::SAMPLER_CUBEMAP) { ASSERT_POSTCONDITION(width == height, "Cubemap faces must be square."); @@ -300,7 +290,7 @@ MetalTexture::MetalTexture(MetalContext& context, backend::SamplerType target, u mipmapped:mipmapped]; descriptor.mipmapLevelCount = levels; descriptor.usage = getMetalTextureUsage(usage); - descriptor.storageMode = getMetalStorageMode(format); + descriptor.storageMode = getMetalStorageMode(usage); texture = [context.device newTextureWithDescriptor:descriptor]; } else if (target == backend::SamplerType::SAMPLER_EXTERNAL) { // If we're using external textures (CVPixelBufferRefs), we don't need to make any texture @@ -361,7 +351,7 @@ void MetalTexture::loadCubeImage(const PixelBufferDescriptor& data, const FaceOf } MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint32_t height, - uint8_t samples, TextureFormat format, id color, id depth) + uint8_t samples, id color, id depth) : HwRenderTarget(width, height), context(context), color(color), depth(depth), samples(samples) { [color retain]; @@ -369,11 +359,11 @@ MetalRenderTarget::MetalRenderTarget(MetalContext* context, uint32_t width, uint if (samples > 1) { multisampledColor = - createMultisampledTexture(context->device, format, width, height, samples); + createMultisampledTexture(context->device, color.pixelFormat, width, height, samples); if (depth != nil) { - multisampledDepth = createMultisampledTexture(context->device, TextureFormat::DEPTH32F, - width, height, samples); + multisampledDepth = createMultisampledTexture(context->device, depth.pixelFormat, width, + height, samples); } } } @@ -405,12 +395,9 @@ MetalRenderTarget::~MetalRenderTarget() { } id MetalRenderTarget::createMultisampledTexture(id device, - TextureFormat format, uint32_t width, uint32_t height, uint8_t samples) { - MTLPixelFormat metalFormat = getMetalFormat(format); - ASSERT_POSTCONDITION(metalFormat != MTLPixelFormatInvalid, "Pixel format not supported."); - + MTLPixelFormat format, uint32_t width, uint32_t height, uint8_t samples) { MTLTextureDescriptor* descriptor = - [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:metalFormat + [MTLTextureDescriptor texture2DDescriptorWithPixelFormat:format width:width height:height mipmapped:NO];