support Metal renderer to auto generate mipmap for render target (#2784)

* support render target auto generate mipmap

* move autoGenMipmap check to s_textureFormat table
This commit is contained in:
Kitchen
2022-04-25 22:11:14 +08:00
committed by GitHub
parent 09d8c34e34
commit f76b678bef
2 changed files with 136 additions and 91 deletions

View File

@@ -125,6 +125,11 @@ namespace bgfx { namespace mtl
destinationSlice:_destinationSlice destinationLevel:_destinationLevel destinationOrigin:_destinationOrigin];
}
void generateMipmapsForTexture(id<MTLTexture> _texture)
{
[m_obj generateMipmapsForTexture:_texture];
}
#if BX_PLATFORM_OSX
void synchronizeTexture(id<MTLTexture> _texture, NSUInteger _slice, NSUInteger _level)
{
@@ -1075,6 +1080,8 @@ namespace bgfx { namespace mtl
void postReset();
uint16_t destroy();
void resolve();
SwapChainMtl* m_swapChain;
void* m_nwh;
uint32_t m_width;

View File

@@ -211,104 +211,109 @@ namespace bgfx { namespace mtl
{
MTLPixelFormat m_fmt;
MTLPixelFormat m_fmtSrgb;
// https://developer.apple.com/documentation/metal/mtlblitcommandencoder/1400748-generatemipmapsfortexture
// the metal api needed the texture format:
// Mipmap generation works only for textures with color-renderable and color-filterable pixel formats.
// follow: https://developer.apple.com/metal/Metal-Feature-Set-Tables.pdf, start from page 6
bool autoGenMipamp;
};
static TextureFormatInfo s_textureFormat[] =
{
{ MTLPixelFormat(130/*BC1_RGBA*/), MTLPixelFormat(131/*BC1_RGBA_sRGB*/) }, // BC1
{ MTLPixelFormat(132/*BC2_RGBA*/), MTLPixelFormat(133/*BC2_RGBA_sRGB*/) }, // BC2
{ MTLPixelFormat(134/*BC3_RGBA*/), MTLPixelFormat(135/*BC3_RGBA_sRGB*/) }, // BC3
{ MTLPixelFormat(140/*BC4_RUnorm*/), MTLPixelFormatInvalid }, // BC4
{ MTLPixelFormat(142/*BC5_RGUnorm*/), MTLPixelFormatInvalid }, // BC5
{ MTLPixelFormat(150/*BC6H_RGBFloat*/), MTLPixelFormatInvalid }, // BC6H
{ MTLPixelFormat(152/*BC7_RGBAUnorm*/), MTLPixelFormat(153/*BC7_RGBAUnorm_sRGB*/) }, // BC7
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ETC1
{ MTLPixelFormat(180/*ETC2_RGB8*/), MTLPixelFormat(181/*ETC2_RGB8_sRGB*/) }, // ETC2
{ MTLPixelFormat(178/*EAC_RGBA8*/), MTLPixelFormat(179/*EAC_RGBA8_sRGB*/) }, // ETC2A
{ MTLPixelFormat(182/*ETC2_RGB8A1*/), MTLPixelFormat(183/*ETC2_RGB8A1_sRGB*/) }, // ETC2A1
{ MTLPixelFormat(160/*PVRTC_RGB_2BPP*/), MTLPixelFormat(161/*PVRTC_RGB_2BPP_sRGB*/) }, // PTC12
{ MTLPixelFormat(162/*PVRTC_RGB_4BPP*/), MTLPixelFormat(163/*PVRTC_RGB_4BPP_sRGB*/) }, // PTC14
{ MTLPixelFormat(164/*PVRTC_RGBA_2BPP*/), MTLPixelFormat(165/*PVRTC_RGBA_2BPP_sRGB*/) }, // PTC12A
{ MTLPixelFormat(166/*PVRTC_RGBA_4BPP*/), MTLPixelFormat(167/*PVRTC_RGBA_4BPP_sRGB*/) }, // PTC14A
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC22
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // PTC24
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATC
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATCE
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ATCI
{ MTLPixelFormat(130/*BC1_RGBA*/), MTLPixelFormat(131/*BC1_RGBA_sRGB*/), false}, // BC1
{ MTLPixelFormat(132/*BC2_RGBA*/), MTLPixelFormat(133/*BC2_RGBA_sRGB*/), false}, // BC2
{ MTLPixelFormat(134/*BC3_RGBA*/), MTLPixelFormat(135/*BC3_RGBA_sRGB*/), false}, // BC3
{ MTLPixelFormat(140/*BC4_RUnorm*/), MTLPixelFormatInvalid, false}, // BC4
{ MTLPixelFormat(142/*BC5_RGUnorm*/), MTLPixelFormatInvalid, false}, // BC5
{ MTLPixelFormat(150/*BC6H_RGBFloat*/), MTLPixelFormatInvalid, false}, // BC6H
{ MTLPixelFormat(152/*BC7_RGBAUnorm*/), MTLPixelFormat(153/*BC7_RGBAUnorm_sRGB*/), false}, // BC7
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ETC1
{ MTLPixelFormat(180/*ETC2_RGB8*/), MTLPixelFormat(181/*ETC2_RGB8_sRGB*/), false}, // ETC2
{ MTLPixelFormat(178/*EAC_RGBA8*/), MTLPixelFormat(179/*EAC_RGBA8_sRGB*/), false}, // ETC2A
{ MTLPixelFormat(182/*ETC2_RGB8A1*/), MTLPixelFormat(183/*ETC2_RGB8A1_sRGB*/), false}, // ETC2A1
{ MTLPixelFormat(160/*PVRTC_RGB_2BPP*/), MTLPixelFormat(161/*PVRTC_RGB_2BPP_sRGB*/), false}, // PTC12
{ MTLPixelFormat(162/*PVRTC_RGB_4BPP*/), MTLPixelFormat(163/*PVRTC_RGB_4BPP_sRGB*/), false}, // PTC14
{ MTLPixelFormat(164/*PVRTC_RGBA_2BPP*/), MTLPixelFormat(165/*PVRTC_RGBA_2BPP_sRGB*/),false}, // PTC12A
{ MTLPixelFormat(166/*PVRTC_RGBA_4BPP*/), MTLPixelFormat(167/*PVRTC_RGBA_4BPP_sRGB*/),false}, // PTC14A
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // PTC22
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // PTC24
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ATC
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ATCE
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ATCI
#if BX_PLATFORM_IOS && !TARGET_OS_MACCATALYST
{ MTLPixelFormatASTC_4x4_LDR, MTLPixelFormatASTC_4x4_sRGB }, // ASTC4x4
{ MTLPixelFormatASTC_5x5_LDR, MTLPixelFormatASTC_5x5_sRGB }, // ASTC5x5
{ MTLPixelFormatASTC_6x6_LDR, MTLPixelFormatASTC_6x6_sRGB }, // ASTC6x6
{ MTLPixelFormatASTC_8x5_LDR, MTLPixelFormatASTC_8x5_sRGB }, // ASTC8x5
{ MTLPixelFormatASTC_8x6_LDR, MTLPixelFormatASTC_8x6_sRGB }, // ASTC8x6
{ MTLPixelFormatASTC_10x5_LDR, MTLPixelFormatASTC_10x5_sRGB }, // ASTC10x5
{ MTLPixelFormatASTC_4x4_LDR, MTLPixelFormatASTC_4x4_sRGB, false}, // ASTC4x4
{ MTLPixelFormatASTC_5x5_LDR, MTLPixelFormatASTC_5x5_sRGB, false}, // ASTC5x5
{ MTLPixelFormatASTC_6x6_LDR, MTLPixelFormatASTC_6x6_sRGB, false}, // ASTC6x6
{ MTLPixelFormatASTC_8x5_LDR, MTLPixelFormatASTC_8x5_sRGB, false}, // ASTC8x5
{ MTLPixelFormatASTC_8x6_LDR, MTLPixelFormatASTC_8x6_sRGB, false}, // ASTC8x6
{ MTLPixelFormatASTC_10x5_LDR, MTLPixelFormatASTC_10x5_sRGB, false}, // ASTC10x5
#else
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC4x4
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC5x5
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC6x6
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC8x5
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC8x6
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // ASTC10x5
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC4x4
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC5x5
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC6x6
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC8x5
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC8x6
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // ASTC10x5
#endif // BX_PLATFORM_IOS && !TARGET_OS_MACCATALYST
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // Unknown
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // R1
{ MTLPixelFormatA8Unorm, MTLPixelFormatInvalid }, // A8
{ MTLPixelFormatR8Unorm, MTLPixelFormat(11/*R8Unorm_sRGB*/) }, // R8
{ MTLPixelFormatR8Sint, MTLPixelFormatInvalid }, // R8I
{ MTLPixelFormatR8Uint, MTLPixelFormatInvalid }, // R8U
{ MTLPixelFormatR8Snorm, MTLPixelFormatInvalid }, // R8S
{ MTLPixelFormatR16Unorm, MTLPixelFormatInvalid }, // R16
{ MTLPixelFormatR16Sint, MTLPixelFormatInvalid }, // R16I
{ MTLPixelFormatR16Uint, MTLPixelFormatInvalid }, // R16U
{ MTLPixelFormatR16Float, MTLPixelFormatInvalid }, // R16F
{ MTLPixelFormatR16Snorm, MTLPixelFormatInvalid }, // R16S
{ MTLPixelFormatR32Sint, MTLPixelFormatInvalid }, // R32I
{ MTLPixelFormatR32Uint, MTLPixelFormatInvalid }, // R32U
{ MTLPixelFormatR32Float, MTLPixelFormatInvalid }, // R32F
{ MTLPixelFormatRG8Unorm, MTLPixelFormat(31/*RG8Unorm_sRGB*/) }, // RG8
{ MTLPixelFormatRG8Sint, MTLPixelFormatInvalid }, // RG8I
{ MTLPixelFormatRG8Uint, MTLPixelFormatInvalid }, // RG8U
{ MTLPixelFormatRG8Snorm, MTLPixelFormatInvalid }, // RG8S
{ MTLPixelFormatRG16Unorm, MTLPixelFormatInvalid }, // RG16
{ MTLPixelFormatRG16Sint, MTLPixelFormatInvalid }, // RG16I
{ MTLPixelFormatRG16Uint, MTLPixelFormatInvalid }, // RG16U
{ MTLPixelFormatRG16Float, MTLPixelFormatInvalid }, // RG16F
{ MTLPixelFormatRG16Snorm, MTLPixelFormatInvalid }, // RG16S
{ MTLPixelFormatRG32Sint, MTLPixelFormatInvalid }, // RG32I
{ MTLPixelFormatRG32Uint, MTLPixelFormatInvalid }, // RG32U
{ MTLPixelFormatRG32Float, MTLPixelFormatInvalid }, // RG32F
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // RGB8
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // RGB8I
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // RGB8U
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // RGB8S
{ MTLPixelFormatRGB9E5Float, MTLPixelFormatInvalid }, // RGB9E5F
{ MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB }, // BGRA8
{ MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB }, // RGBA8
{ MTLPixelFormatRGBA8Sint, MTLPixelFormatInvalid }, // RGBA8I
{ MTLPixelFormatRGBA8Uint, MTLPixelFormatInvalid }, // RGBA8U
{ MTLPixelFormatRGBA8Snorm, MTLPixelFormatInvalid }, // RGBA8S
{ MTLPixelFormatRGBA16Unorm, MTLPixelFormatInvalid }, // RGBA16
{ MTLPixelFormatRGBA16Sint, MTLPixelFormatInvalid }, // RGBA16I
{ MTLPixelFormatRGBA16Uint, MTLPixelFormatInvalid }, // RGBA16U
{ MTLPixelFormatRGBA16Float, MTLPixelFormatInvalid }, // RGBA16F
{ MTLPixelFormatRGBA16Snorm, MTLPixelFormatInvalid }, // RGBA16S
{ MTLPixelFormatRGBA32Sint, MTLPixelFormatInvalid }, // RGBA32I
{ MTLPixelFormatRGBA32Uint, MTLPixelFormatInvalid }, // RGBA32U
{ MTLPixelFormatRGBA32Float, MTLPixelFormatInvalid }, // RGBA32F
{ MTLPixelFormat(40/*B5G6R5Unorm*/), MTLPixelFormatInvalid }, // R5G6B5
{ MTLPixelFormat(42/*ABGR4Unorm*/), MTLPixelFormatInvalid }, // RGBA4
{ MTLPixelFormat(41/*A1BGR5Unorm*/), MTLPixelFormatInvalid }, // RGB5A1
{ MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid }, // RGB10A2
{ MTLPixelFormatRG11B10Float, MTLPixelFormatInvalid }, // RG11B10F
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid }, // UnknownDepth
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24
{ MTLPixelFormat(255/*Depth24Unorm_Stencil8*/), MTLPixelFormatInvalid }, // D24S8
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D16F
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D24F
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid }, // D32F
{ MTLPixelFormatStencil8, MTLPixelFormatInvalid }, // D0S8
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // Unknown
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // R1
{ MTLPixelFormatA8Unorm, MTLPixelFormatInvalid, false}, // A8
{ MTLPixelFormatR8Unorm, MTLPixelFormat(11/*R8Unorm_sRGB*/), true}, // R8
{ MTLPixelFormatR8Sint, MTLPixelFormatInvalid, false}, // R8I
{ MTLPixelFormatR8Uint, MTLPixelFormatInvalid, false}, // R8U
{ MTLPixelFormatR8Snorm, MTLPixelFormatInvalid, true}, // R8S
{ MTLPixelFormatR16Unorm, MTLPixelFormatInvalid, true}, // R16
{ MTLPixelFormatR16Sint, MTLPixelFormatInvalid, false}, // R16I
{ MTLPixelFormatR16Uint, MTLPixelFormatInvalid, false}, // R16U
{ MTLPixelFormatR16Float, MTLPixelFormatInvalid, true}, // R16F
{ MTLPixelFormatR16Snorm, MTLPixelFormatInvalid, true}, // R16S
{ MTLPixelFormatR32Sint, MTLPixelFormatInvalid, false}, // R32I
{ MTLPixelFormatR32Uint, MTLPixelFormatInvalid, false}, // R32U
{ MTLPixelFormatR32Float, MTLPixelFormatInvalid, false}, // R32F
{ MTLPixelFormatRG8Unorm, MTLPixelFormat(31/*RG8Unorm_sRGB*/), true}, // RG8
{ MTLPixelFormatRG8Sint, MTLPixelFormatInvalid, false}, // RG8I
{ MTLPixelFormatRG8Uint, MTLPixelFormatInvalid, false}, // RG8U
{ MTLPixelFormatRG8Snorm, MTLPixelFormatInvalid, true}, // RG8S
{ MTLPixelFormatRG16Unorm, MTLPixelFormatInvalid, true}, // RG16
{ MTLPixelFormatRG16Sint, MTLPixelFormatInvalid, false}, // RG16I
{ MTLPixelFormatRG16Uint, MTLPixelFormatInvalid, false}, // RG16U
{ MTLPixelFormatRG16Float, MTLPixelFormatInvalid, true}, // RG16F
{ MTLPixelFormatRG16Snorm, MTLPixelFormatInvalid, true}, // RG16S
{ MTLPixelFormatRG32Sint, MTLPixelFormatInvalid, false}, // RG32I
{ MTLPixelFormatRG32Uint, MTLPixelFormatInvalid, false}, // RG32U
{ MTLPixelFormatRG32Float, MTLPixelFormatInvalid, false}, // RG32F
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // RGB8
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // RGB8I
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // RGB8U
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // RGB8S
{ MTLPixelFormatRGB9E5Float, MTLPixelFormatInvalid, false}, // RGB9E5F
{ MTLPixelFormatBGRA8Unorm, MTLPixelFormatBGRA8Unorm_sRGB, false}, // BGRA8
{ MTLPixelFormatRGBA8Unorm, MTLPixelFormatRGBA8Unorm_sRGB, true}, // RGBA8
{ MTLPixelFormatRGBA8Sint, MTLPixelFormatInvalid, false}, // RGBA8I
{ MTLPixelFormatRGBA8Uint, MTLPixelFormatInvalid, false}, // RGBA8U
{ MTLPixelFormatRGBA8Snorm, MTLPixelFormatInvalid, true}, // RGBA8S
{ MTLPixelFormatRGBA16Unorm, MTLPixelFormatInvalid, true}, // RGBA16
{ MTLPixelFormatRGBA16Sint, MTLPixelFormatInvalid, false}, // RGBA16I
{ MTLPixelFormatRGBA16Uint, MTLPixelFormatInvalid, false}, // RGBA16U
{ MTLPixelFormatRGBA16Float, MTLPixelFormatInvalid, true}, // RGBA16F
{ MTLPixelFormatRGBA16Snorm, MTLPixelFormatInvalid, true}, // RGBA16S
{ MTLPixelFormatRGBA32Sint, MTLPixelFormatInvalid, true}, // RGBA32I
{ MTLPixelFormatRGBA32Uint, MTLPixelFormatInvalid, true}, // RGBA32U
{ MTLPixelFormatRGBA32Float, MTLPixelFormatInvalid, true}, // RGBA32F
{ MTLPixelFormat(40/*B5G6R5Unorm*/), MTLPixelFormatInvalid, true}, // R5G6B5
{ MTLPixelFormat(42/*ABGR4Unorm*/), MTLPixelFormatInvalid, true}, // RGBA4
{ MTLPixelFormat(41/*A1BGR5Unorm*/), MTLPixelFormatInvalid, true}, // RGB5A1
{ MTLPixelFormatRGB10A2Unorm, MTLPixelFormatInvalid, true}, // RGB10A2
{ MTLPixelFormatRG11B10Float, MTLPixelFormatInvalid, true}, // RG11B10F
{ MTLPixelFormatInvalid, MTLPixelFormatInvalid, false}, // UnknownDepth
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D16
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D24
{ MTLPixelFormat(255/*Depth24Unorm_Stencil8*/), MTLPixelFormatInvalid, false}, // D24S8
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D32
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D16F
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D24F
{ MTLPixelFormatDepth32Float, MTLPixelFormatInvalid, false}, // D32F
{ MTLPixelFormatStencil8, MTLPixelFormatInvalid, false}, // D0S8
};
BX_STATIC_ASSERT(TextureFormat::Count == BX_COUNTOF(s_textureFormat) );
@@ -690,6 +695,11 @@ BX_STATIC_ASSERT(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNa
;
}
support |= s_textureFormat[ii].autoGenMipamp
? BGFX_CAPS_FORMAT_TEXTURE_MIP_AUTOGEN
: 0
;
g_caps.formats[ii] = support;
}
@@ -1753,6 +1763,12 @@ BX_STATIC_ASSERT(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNa
void setFrameBuffer(RenderPassDescriptor _renderPassDescriptor, FrameBufferHandle _fbh, bool _msaa = true)
{
// reslove framebuffer
if (isValid(m_fbh) && m_fbh.idx != _fbh.idx)
{
FrameBufferMtl& frameBuffer = m_frameBuffers[m_fbh.idx];
frameBuffer.resolve();
}
if (!isValid(_fbh)
|| m_frameBuffers[_fbh.idx].m_swapChain)
{
@@ -3526,6 +3542,28 @@ BX_STATIC_ASSERT(BX_COUNTOF(s_accessNames) == Access::Count, "Invalid s_accessNa
return denseIdx;
}
void FrameBufferMtl::resolve()
{
BlitCommandEncoder bce = s_renderMtl->getBlitCommandEncoder();
for (uint32_t ii = 0; ii < m_num; ++ii)
{
if (0 != (m_colorAttachment[ii].resolve & BGFX_RESOLVE_AUTO_GEN_MIPS))
{
const TextureMtl& texture = s_renderMtl->m_textures[m_colorHandle[ii].idx];
const bool isRenderTarget = (texture.m_flags & BGFX_TEXTURE_RT_MASK);
const bool fmtSupport = 0 != (g_caps.formats[texture.m_textureFormat] & BGFX_CAPS_FORMAT_TEXTURE_MIP_AUTOGEN);
if (isRenderTarget
&& fmtSupport
&& texture.m_numMips > 1)
{
bce.generateMipmapsForTexture(texture.m_ptr);
}
}
}
s_renderMtl->endEncoding();
}
void CommandQueueMtl::init(Device _device)
{
m_commandQueue = _device.newCommandQueue();