From ca256eb764d8c08d5c54029821aedffe8dd1465c Mon Sep 17 00:00:00 2001 From: Samuliak Date: Mon, 19 Aug 2024 16:40:36 +0200 Subject: [PATCH] check for pixel format support --- .../Latte/Renderer/Metal/LatteTextureMtl.cpp | 4 +-- .../Renderer/Metal/LatteTextureViewMtl.cpp | 4 +-- .../HW/Latte/Renderer/Metal/LatteToMtl.cpp | 33 ++++++++++++++++++- src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h | 8 ++--- .../HW/Latte/Renderer/Metal/MetalCommon.h | 19 ++++++++++- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 1 + .../HW/Latte/Renderer/Metal/MetalRenderer.h | 6 ++++ 7 files changed, 64 insertions(+), 11 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp index eeeee0ba..c588a21e 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureMtl.cpp @@ -73,8 +73,8 @@ LatteTextureMtl::LatteTextureMtl(class MetalRenderer* mtlRenderer, Latte::E_DIM desc->setArrayLength(effectiveBaseDepth); } - auto formatInfo = GetMtlPixelFormatInfo(format, isDepth); - desc->setPixelFormat(formatInfo.pixelFormat); + auto pixelFormat = GetMtlPixelFormat(format, isDepth, m_mtlr->GetPixelFormatSupport()); + desc->setPixelFormat(pixelFormat); // HACK: even though the textures are never written to from a shader, we still need to use `ShaderWrite` usage to prevent pink lines over the screen MTL::TextureUsage usage = MTL::TextureUsageShaderRead | MTL::TextureUsageShaderWrite; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp index adb77643..0607370b 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteTextureViewMtl.cpp @@ -127,8 +127,8 @@ MTL::Texture* LatteTextureViewMtl::CreateSwizzledView(uint32 gpuSamplerSwizzle) swizzle.blue = GetMtlTextureSwizzle(compSelB); swizzle.alpha = GetMtlTextureSwizzle(compSelA); - auto formatInfo = GetMtlPixelFormatInfo(format, m_baseTexture->IsDepth()); - MTL::Texture* texture = m_baseTexture->GetTexture()->newTextureView(formatInfo.pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount), swizzle); + auto pixelFormat = GetMtlPixelFormat(format, m_baseTexture->IsDepth(), m_mtlr->GetPixelFormatSupport()); + MTL::Texture* texture = m_baseTexture->GetTexture()->newTextureView(pixelFormat, textureType, NS::Range::Make(baseLevel, levelCount), NS::Range::Make(baseLayer, layerCount), swizzle); return texture; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp index 704cf883..771aa059 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.cpp @@ -1,6 +1,7 @@ #include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h" #include "Common/precompiled.h" #include "Metal/MTLDepthStencil.hpp" +#include "Metal/MTLPixelFormat.hpp" #include "Metal/MTLRenderCommandEncoder.hpp" #include "Metal/MTLRenderPipeline.hpp" #include "Metal/MTLSampler.hpp" @@ -74,7 +75,6 @@ std::map MTL_COLOR_FORMAT_TABLE = { }; std::map MTL_DEPTH_FORMAT_TABLE = { - // TODO: one of these 2 formats is not supported on Apple silicon {Latte::E_GX2SURFFMT::D24_S8_UNORM, {MTL::PixelFormatDepth24Unorm_Stencil8, MetalDataType::NONE, 4, {1, 1}, true}}, {Latte::E_GX2SURFFMT::D24_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, MetalDataType::NONE, 4, {1, 1}, true}}, {Latte::E_GX2SURFFMT::D32_S8_FLOAT, {MTL::PixelFormatDepth32Float_Stencil8, MetalDataType::NONE, 5, {1, 1}, true}}, @@ -105,6 +105,37 @@ const MetalPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format, boo return formatInfo; } +MTL::PixelFormat GetMtlPixelFormat(Latte::E_GX2SURFFMT format, bool isDepth, const MetalPixelFormatSupport& pixelFormatSupport) +{ + auto pixelFormat = GetMtlPixelFormatInfo(format, isDepth).pixelFormat; + + if (!pixelFormatSupport.m_supportsR8Unorm_sRGB && pixelFormat == MTL::PixelFormatR8Unorm_sRGB) + pixelFormat = MTL::PixelFormatRGBA8Unorm_sRGB; + + if (!pixelFormatSupport.m_supportsRG8Unorm_sRGB && pixelFormat == MTL::PixelFormatRG8Unorm_sRGB) + pixelFormat = MTL::PixelFormatRGBA8Unorm_sRGB; + + if (!pixelFormatSupport.m_supportsPacked16BitFormats) + { + switch (pixelFormat) + { + case MTL::PixelFormatB5G6R5Unorm: + case MTL::PixelFormatA1BGR5Unorm: + case MTL::PixelFormatABGR4Unorm: + case MTL::PixelFormatBGR5A1Unorm: + pixelFormat = MTL::PixelFormatRGBA8Unorm; + break; + default: + break; + } + } + + if (!pixelFormatSupport.m_supportsDepth24Unorm_Stencil8 && pixelFormat == MTL::PixelFormatDepth24Unorm_Stencil8) + pixelFormat = MTL::PixelFormatDepth32Float_Stencil8; + + return pixelFormat; +} + inline uint32 CeilDivide(uint32 a, uint32 b) { return (a + b - 1) / b; } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h index 5fcd2d22..cc0c5e02 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h @@ -1,15 +1,11 @@ #pragma once -#include +#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/ISA/LatteReg.h" #include "Cafe/HW/Latte/Core/LatteConst.h" //#include "Cafe/HW/Latte/Core/FetchShader.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" -#include "Metal/MTLDepthStencil.hpp" -#include "Metal/MTLRenderPipeline.hpp" -#include "Metal/MTLSampler.hpp" -#include "Metal/MTLTexture.hpp" struct Uvec2 { uint32 x; @@ -34,6 +30,8 @@ struct MetalPixelFormatInfo { const MetalPixelFormatInfo GetMtlPixelFormatInfo(Latte::E_GX2SURFFMT format, bool isDepth); +MTL::PixelFormat GetMtlPixelFormat(Latte::E_GX2SURFFMT format, bool isDepth, const MetalPixelFormatSupport& pixelFormatSupport); + size_t GetMtlTextureBytesPerRow(Latte::E_GX2SURFFMT format, bool isDepth, uint32 width); size_t GetMtlTextureBytesPerImage(Latte::E_GX2SURFFMT format, bool isDepth, uint32 height, size_t bytesPerRow); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h index 19ac7ab7..926af5f4 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalCommon.h @@ -1,8 +1,25 @@ #pragma once -#include "Foundation/NSString.hpp" +#include #include +struct MetalPixelFormatSupport +{ + bool m_supportsR8Unorm_sRGB; + bool m_supportsRG8Unorm_sRGB; + bool m_supportsPacked16BitFormats; + bool m_supportsDepth24Unorm_Stencil8; + + MetalPixelFormatSupport() = default; + MetalPixelFormatSupport(MTL::Device* device) + { + m_supportsR8Unorm_sRGB = device->supportsFamily(MTL::GPUFamilyApple1); + m_supportsRG8Unorm_sRGB = device->supportsFamily(MTL::GPUFamilyApple1); + m_supportsPacked16BitFormats = device->supportsFamily(MTL::GPUFamilyApple1); + m_supportsDepth24Unorm_Stencil8 = device->supportsFamily(MTL::GPUFamilyMac2); + } +}; + #define MAX_MTL_BUFFERS 31 // Buffer index 30 is reserved for the support buffer, buffer indices 27-29 are reserved for the helper shaders #define GET_MTL_VERTEX_BUFFER_INDEX(index) (MAX_MTL_BUFFERS - index - 5) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index fc4f9836..f5a11118 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -36,6 +36,7 @@ MetalRenderer::MetalRenderer() // Feature support m_hasUnifiedMemory = m_device->hasUnifiedMemory(); m_isAppleGPU = m_device->supportsFamily(MTL::GPUFamilyApple1); + m_pixelFormatSupport = MetalPixelFormatSupport(m_device); // Resources MTL::SamplerDescriptor* samplerDescriptor = MTL::SamplerDescriptor::alloc()->init(); diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h index 49d4af83..4ea13fb2 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h @@ -371,6 +371,11 @@ public: return m_isAppleGPU; } + const MetalPixelFormatSupport& GetPixelFormatSupport() const + { + return m_pixelFormatSupport; + } + MTL::StorageMode GetOptimalTextureStorageMode() const { return (m_isAppleGPU ? MTL::StorageModeShared : MTL::StorageModePrivate); @@ -397,6 +402,7 @@ private: // Feature support bool m_hasUnifiedMemory; bool m_isAppleGPU; + MetalPixelFormatSupport m_pixelFormatSupport; // Managers and caches class MetalMemoryManager* m_memoryManager;