From f76b678bef3f97357ecd4b4c02081d0a22f54866 Mon Sep 17 00:00:00 2001 From: Kitchen Date: Mon, 25 Apr 2022 22:11:14 +0800 Subject: [PATCH] support Metal renderer to auto generate mipmap for render target (#2784) * support render target auto generate mipmap * move autoGenMipmap check to s_textureFormat table --- src/renderer_mtl.h | 7 ++ src/renderer_mtl.mm | 220 ++++++++++++++++++++++++++------------------ 2 files changed, 136 insertions(+), 91 deletions(-) diff --git a/src/renderer_mtl.h b/src/renderer_mtl.h index b8ddf4fd8..ce9716eca 100644 --- a/src/renderer_mtl.h +++ b/src/renderer_mtl.h @@ -125,6 +125,11 @@ namespace bgfx { namespace mtl destinationSlice:_destinationSlice destinationLevel:_destinationLevel destinationOrigin:_destinationOrigin]; } + void generateMipmapsForTexture(id _texture) + { + [m_obj generateMipmapsForTexture:_texture]; + } + #if BX_PLATFORM_OSX void synchronizeTexture(id _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; diff --git a/src/renderer_mtl.mm b/src/renderer_mtl.mm index 9121993df..259fdc3eb 100644 --- a/src/renderer_mtl.mm +++ b/src/renderer_mtl.mm @@ -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();