diff --git a/filament/backend/src/metal/MetalDriver.mm b/filament/backend/src/metal/MetalDriver.mm index 049839c4ad..0515965844 100644 --- a/filament/backend/src/metal/MetalDriver.mm +++ b/filament/backend/src/metal/MetalDriver.mm @@ -176,7 +176,8 @@ void MetalDriver::createTextureR(Handle th, SamplerType target, uint8 TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage) { construct_handle(mHandleMap, th, *mContext, target, levels, format, samples, - width, height, depth, usage); + width, height, depth, usage, TextureSwizzle::CHANNEL_0, TextureSwizzle::CHANNEL_1, + TextureSwizzle::CHANNEL_2, TextureSwizzle::CHANNEL_3); } void MetalDriver::createTextureSwizzledR(Handle th, SamplerType target, uint8_t levels, @@ -184,8 +185,7 @@ void MetalDriver::createTextureSwizzledR(Handle th, SamplerType targe uint32_t depth, TextureUsage usage, TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) { construct_handle(mHandleMap, th, *mContext, target, levels, format, samples, - width, height, depth, usage); - // TODO: implement texture swizzle + width, height, depth, usage, r, g, b, a); } void MetalDriver::importTextureR(Handle th, intptr_t i, @@ -551,7 +551,11 @@ bool MetalDriver::isTextureFormatSupported(TextureFormat format) { } bool MetalDriver::isTextureSwizzleSupported() { - return false; + if (@available(macOS 10.15, iOS 13, *)) { + return true; + } else { + return false; + } } bool MetalDriver::isTextureFormatMipmappable(TextureFormat format) { diff --git a/filament/backend/src/metal/MetalEnums.h b/filament/backend/src/metal/MetalEnums.h index b22a66067c..cef91ce9b1 100644 --- a/filament/backend/src/metal/MetalEnums.h +++ b/filament/backend/src/metal/MetalEnums.h @@ -419,6 +419,31 @@ constexpr inline MTLCompareFunction getCompareFunction(SamplerCompareFunc compar } } +API_AVAILABLE(macos(10.15), ios(13.0)) +MTLTextureSwizzle getSwizzle(TextureSwizzle swizzle) { + switch (swizzle) { + case TextureSwizzle::SUBSTITUTE_ZERO: + return MTLTextureSwizzleZero; + case TextureSwizzle::SUBSTITUTE_ONE: + return MTLTextureSwizzleOne; + case TextureSwizzle::CHANNEL_0: + return MTLTextureSwizzleRed; + case TextureSwizzle::CHANNEL_1: + return MTLTextureSwizzleGreen; + case TextureSwizzle::CHANNEL_2: + return MTLTextureSwizzleBlue; + case TextureSwizzle::CHANNEL_3: + return MTLTextureSwizzleAlpha; + } +} + +API_AVAILABLE(macos(10.15), ios(13.0)) +MTLTextureSwizzleChannels getSwizzleChannels(TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, + TextureSwizzle a) { + return MTLTextureSwizzleChannelsMake(getSwizzle(r), getSwizzle(g), getSwizzle(b), + getSwizzle(a)); +} + } // namespace backend } // namespace filament diff --git a/filament/backend/src/metal/MetalHandles.h b/filament/backend/src/metal/MetalHandles.h index 8d2587138d..787a7cfc4c 100644 --- a/filament/backend/src/metal/MetalHandles.h +++ b/filament/backend/src/metal/MetalHandles.h @@ -158,7 +158,8 @@ struct MetalProgram : public HwProgram { struct MetalTexture : public HwTexture { MetalTexture(MetalContext& context, SamplerType target, uint8_t levels, TextureFormat format, - uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage) + uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, TextureUsage usage, + TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) noexcept; // Constructor for importing an id outside of Filament. diff --git a/filament/backend/src/metal/MetalHandles.mm b/filament/backend/src/metal/MetalHandles.mm index 5a2c67961f..c755edede9 100644 --- a/filament/backend/src/metal/MetalHandles.mm +++ b/filament/backend/src/metal/MetalHandles.mm @@ -416,7 +416,8 @@ static MTLPixelFormat decidePixelFormat(id device, TextureFormat form MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t levels, TextureFormat format, uint8_t samples, uint32_t width, uint32_t height, uint32_t depth, - TextureUsage usage) noexcept + TextureUsage usage, TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, + TextureSwizzle a) noexcept : HwTexture(target, levels, samples, width, height, depth, format, usage), context(context), externalImage(context), reshaper(format) { @@ -467,6 +468,12 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le } }; + auto setUpSwizzle = [r, g, b, a](MTLTextureDescriptor* descriptor) { + if (@available(macOS 10.15, iOS 13, *)) { + descriptor.swizzle = getSwizzleChannels(r, g, b, a); + } + }; + MTLTextureDescriptor* descriptor; switch (target) { case SamplerType::SAMPLER_2D: @@ -481,6 +488,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le descriptor.sampleCount = multisampled ? samples : 1; descriptor.usage = getMetalTextureUsage(usage); descriptor.storageMode = MTLStorageModePrivate; + setUpSwizzle(descriptor); texture = [context.device newTextureWithDescriptor:descriptor]; ASSERT_POSTCONDITION(texture != nil, "Could not create Metal texture. Out of memory?"); break; @@ -493,6 +501,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le descriptor.mipmapLevelCount = levels; descriptor.usage = getMetalTextureUsage(usage); descriptor.storageMode = MTLStorageModePrivate; + setUpSwizzle(descriptor); texture = [context.device newTextureWithDescriptor:descriptor]; ASSERT_POSTCONDITION(texture != nil, "Could not create Metal texture. Out of memory?"); break; @@ -506,6 +515,7 @@ MetalTexture::MetalTexture(MetalContext& context, SamplerType target, uint8_t le descriptor.mipmapLevelCount = levels; descriptor.usage = getMetalTextureUsage(usage); descriptor.storageMode = MTLStorageModePrivate; + setUpSwizzle(descriptor); texture = [context.device newTextureWithDescriptor:descriptor]; ASSERT_POSTCONDITION(texture != nil, "Could not create Metal texture. Out of memory?"); break;