Add support for ASTC textures on iOS / Metal (#1992)

This commit is contained in:
Ben Doherty
2020-01-02 11:35:23 -07:00
committed by GitHub
parent 36385a2432
commit 88fa93f1de
6 changed files with 90 additions and 31 deletions

View File

@@ -12,6 +12,7 @@ A new header is inserted each time a *tag* is created.
- Fixed incorrect punctual light binning (affected Metal and Vulkan backends).
- Fixed crash when using a Metal headless SwapChain with an Intel integrated GPU.
- cmgen now places KTX files directly in the specified deployment folder.
- Added support for ASTC textures on iOS with Metal backend.
## v1.4.3

View File

@@ -28,10 +28,16 @@ namespace backend {
size_t getFormatSize(TextureFormat format) noexcept;
/**
* For compressed texture formats, returns the number of horizontal pixels per block. Otherwise
* For compressed texture formats, returns the number of horizontal texels per block. Otherwise
* returns 0.
*/
size_t getBlockWidth(TextureFormat format) noexcept;
/**
* For compressed texture formats, returns the number of vertical texels per block. Otherwise
* returns 0.
*/
size_t getBlockHeight(TextureFormat format) noexcept;
} // namespace backend
} // namespace filament

View File

@@ -188,7 +188,6 @@ size_t getBlockWidth(TextureFormat format) noexcept {
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
return 5;
return 5;
case TextureFormat::RGBA_ASTC_6x5:
case TextureFormat::RGBA_ASTC_6x6:
@@ -225,6 +224,54 @@ size_t getBlockWidth(TextureFormat format) noexcept {
}
}
size_t getBlockHeight(TextureFormat format) noexcept {
switch (format) {
case TextureFormat::RGBA_ASTC_4x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
case TextureFormat::RGBA_ASTC_5x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
return 4;
case TextureFormat::RGBA_ASTC_5x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
case TextureFormat::RGBA_ASTC_6x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
case TextureFormat::RGBA_ASTC_8x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
case TextureFormat::RGBA_ASTC_10x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
return 5;
case TextureFormat::RGBA_ASTC_6x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
case TextureFormat::RGBA_ASTC_8x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
case TextureFormat::RGBA_ASTC_10x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
return 6;
case TextureFormat::RGBA_ASTC_8x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
case TextureFormat::RGBA_ASTC_10x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
return 8;
case TextureFormat::RGBA_ASTC_10x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
case TextureFormat::RGBA_ASTC_12x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
return 10;
case TextureFormat::RGBA_ASTC_12x12:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
return 12;
default:
// Most compressed formats use square blocks, only ASTC is special.
return getBlockWidth(format);
}
}
} // namespace backend
} // namespace filament

View File

@@ -239,34 +239,36 @@ constexpr inline MTLPixelFormat getMetalFormat(TextureFormat format) noexcept {
case TextureFormat::DXT1_RGB: return MTLPixelFormatInvalid;
#endif
case TextureFormat::RGBA_ASTC_4x4:
case TextureFormat::RGBA_ASTC_5x4:
case TextureFormat::RGBA_ASTC_5x5:
case TextureFormat::RGBA_ASTC_6x5:
case TextureFormat::RGBA_ASTC_6x6:
case TextureFormat::RGBA_ASTC_8x5:
case TextureFormat::RGBA_ASTC_8x6:
case TextureFormat::RGBA_ASTC_8x8:
case TextureFormat::RGBA_ASTC_10x5:
case TextureFormat::RGBA_ASTC_10x6:
case TextureFormat::RGBA_ASTC_10x8:
case TextureFormat::RGBA_ASTC_10x10:
case TextureFormat::RGBA_ASTC_12x10:
case TextureFormat::RGBA_ASTC_12x12:
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4:
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8:
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10:
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12:
#if defined(IOS)
case TextureFormat::RGBA_ASTC_4x4: return MTLPixelFormatASTC_4x4_HDR;
case TextureFormat::RGBA_ASTC_5x4: return MTLPixelFormatASTC_5x4_HDR;
case TextureFormat::RGBA_ASTC_5x5: return MTLPixelFormatASTC_5x5_HDR;
case TextureFormat::RGBA_ASTC_6x5: return MTLPixelFormatASTC_6x5_HDR;
case TextureFormat::RGBA_ASTC_6x6: return MTLPixelFormatASTC_6x6_HDR;
case TextureFormat::RGBA_ASTC_8x5: return MTLPixelFormatASTC_8x5_HDR;
case TextureFormat::RGBA_ASTC_8x6: return MTLPixelFormatASTC_8x6_HDR;
case TextureFormat::RGBA_ASTC_8x8: return MTLPixelFormatASTC_8x8_HDR;
case TextureFormat::RGBA_ASTC_10x5: return MTLPixelFormatASTC_10x5_HDR;
case TextureFormat::RGBA_ASTC_10x6: return MTLPixelFormatASTC_10x6_HDR;
case TextureFormat::RGBA_ASTC_10x8: return MTLPixelFormatASTC_10x8_HDR;
case TextureFormat::RGBA_ASTC_10x10: return MTLPixelFormatASTC_10x10_HDR;
case TextureFormat::RGBA_ASTC_12x10: return MTLPixelFormatASTC_12x10_HDR;
case TextureFormat::RGBA_ASTC_12x12: return MTLPixelFormatASTC_12x12_HDR;
case TextureFormat::SRGB8_ALPHA8_ASTC_4x4: return MTLPixelFormatASTC_4x4_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_5x4: return MTLPixelFormatASTC_5x4_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_5x5: return MTLPixelFormatASTC_5x5_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_6x5: return MTLPixelFormatASTC_6x5_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_6x6: return MTLPixelFormatASTC_6x6_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_8x5: return MTLPixelFormatASTC_8x5_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_8x6: return MTLPixelFormatASTC_8x6_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_8x8: return MTLPixelFormatASTC_8x8_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_10x5: return MTLPixelFormatASTC_10x5_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_10x6: return MTLPixelFormatASTC_10x6_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_10x8: return MTLPixelFormatASTC_10x8_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_10x10: return MTLPixelFormatASTC_10x10_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_12x10: return MTLPixelFormatASTC_12x10_sRGB;
case TextureFormat::SRGB8_ALPHA8_ASTC_12x12: return MTLPixelFormatASTC_12x12_sRGB;
#endif
default:
case TextureFormat::UNUSED:

View File

@@ -117,6 +117,7 @@ struct MetalTexture : public HwTexture {
id<MTLTexture> texture = nil;
uint8_t bytesPerElement; // The number of bytes per pixel, or block (for compressed texture formats).
uint8_t blockWidth; // The number of horizontal pixels per block (only for compressed texture formats).
uint8_t blockHeight; // The number of vertical pixels per block (only for compressed texture formats).
TextureReshaper reshaper;
MTLPixelFormat metalPixelFormat;
};

View File

@@ -214,6 +214,7 @@ MetalTexture::MetalTexture(MetalContext& context, backend::SamplerType target, u
bytesPerElement = static_cast<uint8_t>(getFormatSize(reshapedFormat));
assert(bytesPerElement > 0);
blockWidth = static_cast<uint8_t>(getBlockWidth(reshapedFormat));
blockHeight = static_cast<uint8_t>(getBlockHeight(reshapedFormat));
ASSERT_POSTCONDITION(metalPixelFormat != MTLPixelFormatInvalid, "Pixel format not supported.");
@@ -304,12 +305,13 @@ void MetalTexture::loadSlice(uint32_t level, uint32_t xoffset, uint32_t yoffset,
if (data.type == PixelDataType::COMPRESSED) {
assert(blockWidth > 0);
assert(blockHeight > 0);
// From https://developer.apple.com/documentation/metal/mtltexture/1515464-replaceregion:
// For an ordinary or packed pixel format, the stride, in bytes, between rows of source
// data. For a compressed pixel format, the stride is the number of bytes from the
// beginning of one row of blocks to the beginning of the next.
const NSUInteger blocksPerRow = std::ceil(width / (float) blockWidth);
const NSUInteger blocksPerCol = std::ceil(height / (float) blockWidth);
const NSUInteger blocksPerCol = std::ceil(height / (float) blockHeight);
bytesPerRow = bytesPerElement * blocksPerRow;
bytesPerSlice = bytesPerRow * blocksPerCol;
}