Add support for ASTC textures on iOS / Metal (#1992)
This commit is contained in:
@@ -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
|
||||
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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
|
||||
|
||||
@@ -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:
|
||||
|
||||
@@ -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;
|
||||
};
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user