Implement Metal texture swizzling (#3720)

This commit is contained in:
Ben Doherty
2021-03-30 15:38:55 -07:00
committed by GitHub
parent 625c4d8968
commit d11f3f7d5a
4 changed files with 46 additions and 6 deletions

View File

@@ -176,7 +176,8 @@ void MetalDriver::createTextureR(Handle<HwTexture> th, SamplerType target, uint8
TextureFormat format, uint8_t samples, uint32_t width, uint32_t height,
uint32_t depth, TextureUsage usage) {
construct_handle<MetalTexture>(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<HwTexture> th, SamplerType target, uint8_t levels,
@@ -184,8 +185,7 @@ void MetalDriver::createTextureSwizzledR(Handle<HwTexture> th, SamplerType targe
uint32_t depth, TextureUsage usage,
TextureSwizzle r, TextureSwizzle g, TextureSwizzle b, TextureSwizzle a) {
construct_handle<MetalTexture>(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<HwTexture> 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) {

View File

@@ -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

View File

@@ -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<MTLTexture> outside of Filament.

View File

@@ -416,7 +416,8 @@ static MTLPixelFormat decidePixelFormat(id<MTLDevice> 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;