From 6b47d4f61e503a7f3e43c5894e593003882917f9 Mon Sep 17 00:00:00 2001 From: Samuliak Date: Tue, 15 Oct 2024 07:48:59 +0200 Subject: [PATCH] implement pipeline cache serializing --- src/Cafe/HW/Latte/Core/LatteShaderCache.cpp | 32 +++++++--- .../Renderer/Metal/MetalPipelineCache.cpp | 62 ++++++++++++------- .../Latte/Renderer/Metal/MetalPipelineCache.h | 7 ++- 3 files changed, 66 insertions(+), 35 deletions(-) diff --git a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp index cdb41184..126dcc50 100644 --- a/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp +++ b/src/Cafe/HW/Latte/Core/LatteShaderCache.cpp @@ -64,7 +64,7 @@ FileCache* s_shaderCacheGeneric = nullptr; // contains hardware and version inde #define SHADER_CACHE_TYPE_PIXEL (2) bool LatteShaderCache_readSeparableShader(uint8* shaderInfoData, sint32 shaderInfoSize); -void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId); +void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId); bool LatteShaderCache_updatePipelineLoadingProgress(); void LatteShaderCache_ShowProgress(const std::function & loadUpdateFunc, bool isPipelines); @@ -347,9 +347,9 @@ void LatteShaderCache_Load() cemuLog_log(LogType::Force, "Shader cache loaded with {} shaders. Commited mem {}MB. Took {}ms", numLoadedShaders, (sint32)(memCommited/1024/1024), timeLoad); #endif LatteShaderCache_finish(); - // if Vulkan then also load pipeline cache - if (g_renderer->GetType() == RendererAPI::Vulkan) - LatteShaderCache_LoadVulkanPipelineCache(cacheTitleId); + // if Vulkan or Metal then also load pipeline cache + if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal) + LatteShaderCache_LoadPipelineCache(cacheTitleId); g_renderer->BeginFrame(true); @@ -504,13 +504,18 @@ void LatteShaderCache_ShowProgress(const std::function & loadUpdateF } } -void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId) +void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId) { - auto& pipelineCache = VulkanPipelineStableCache::GetInstance(); - g_shaderCacheLoaderState.pipelineFileCount = pipelineCache.BeginLoading(cacheTitleId); + if (g_renderer->GetType() == RendererAPI::Vulkan) + g_shaderCacheLoaderState.pipelineFileCount = VulkanPipelineStableCache::GetInstance().BeginLoading(cacheTitleId); + else if (g_renderer->GetType() == RendererAPI::Metal) + g_shaderCacheLoaderState.pipelineFileCount = MetalPipelineCache::GetInstance().BeginLoading(cacheTitleId); g_shaderCacheLoaderState.loadedPipelines = 0; LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true); - pipelineCache.EndLoading(); + if (g_renderer->GetType() == RendererAPI::Vulkan) + VulkanPipelineStableCache::GetInstance().EndLoading(); + else if (g_renderer->GetType() == RendererAPI::Metal) + MetalPipelineCache::GetInstance().EndLoading(); if(Latte_GetStopSignal()) LatteThread_Exit(); } @@ -518,7 +523,12 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId) bool LatteShaderCache_updatePipelineLoadingProgress() { uint32 pipelinesMissingShaders = 0; - return VulkanPipelineStableCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); + if (g_renderer->GetType() == RendererAPI::Vulkan) + return VulkanPipelineStableCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); + else if (g_renderer->GetType() == RendererAPI::Metal) + return MetalPipelineCache::GetInstance().UpdateLoading(g_shaderCacheLoaderState.loadedPipelines, pipelinesMissingShaders); + + return false; } uint64 LatteShaderCache_getShaderNameInTransferableCache(uint64 baseHash, uint32 shaderType) @@ -783,9 +793,11 @@ void LatteShaderCache_Close() else if (g_renderer->GetType() == RendererAPI::Metal) RendererShaderMtl::ShaderCacheLoading_Close(); - // if Vulkan then also close pipeline cache + // if Vulkan or Metal then also close pipeline cache if (g_renderer->GetType() == RendererAPI::Vulkan) VulkanPipelineStableCache::GetInstance().Close(); + else if (g_renderer->GetType() == RendererAPI::Metal) + MetalPipelineCache::GetInstance().Close(); } #include diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp index ea95c266..2922d70c 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp @@ -15,6 +15,43 @@ #include "config/ActiveSettings.h" #include +MetalPipelineCache* g_mtlPipelineCache = nullptr; + +MetalPipelineCache& MetalPipelineCache::GetInstance() +{ + return *g_mtlPipelineCache; +} + +MetalPipelineCache::MetalPipelineCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} +{ + g_mtlPipelineCache = this; +} + +MetalPipelineCache::~MetalPipelineCache() +{ + for (auto& [key, value] : m_pipelineCache) + { + value->release(); + } +} + +MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) +{ + uint64 hash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr); + auto& pipeline = m_pipelineCache[hash]; + if (pipeline) + return pipeline; + + MetalPipelineCompiler compiler(m_mtlr); + compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr); + pipeline = compiler.Compile(false, true); + + if (!HasPipelineCached(vertexShader->baseHash, hash)) + AddCurrentStateToCache(vertexShader->baseHash, hash); + + return pipeline; +} + uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) { // Hash @@ -117,27 +154,6 @@ uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchSh return stateHash; } -MetalPipelineCache::~MetalPipelineCache() -{ - for (auto& [key, value] : m_pipelineCache) - { - value->release(); - } -} - -MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr) -{ - auto& pipeline = m_pipelineCache[CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr)]; - if (pipeline) - return pipeline; - - MetalPipelineCompiler compiler(m_mtlr); - compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedFBO, activeFBO, lcr); - pipeline = compiler.Compile(false, true); - - return pipeline; -} - struct { uint32 pipelineLoadIndex; @@ -181,7 +197,7 @@ uint32 MetalPipelineCache::BeginLoading(uint64 cacheTitleId) s_cache = FileCache::Open(pathCacheFile, true, LatteShaderCache_getPipelineCacheExtraVersion(cacheTitleId)); if (!s_cache) { - cemuLog_log(LogType::Force, "Failed to open or create Vulkan pipeline cache file: {}", _pathToUtf8(pathCacheFile)); + cemuLog_log(LogType::Force, "Failed to open or create Metal pipeline cache file: {}", _pathToUtf8(pathCacheFile)); return 0; } else @@ -436,7 +452,7 @@ bool MetalPipelineCache::DeserializePipeline(MemStreamReader& memReader, CachedP // version if (memReader.readBE() != 1) { - cemuLog_log(LogType::Force, "Cached Vulkan pipeline corrupted or has unknown version"); + cemuLog_log(LogType::Force, "Cached Metal pipeline corrupted or has unknown version"); return false; } // shader hashes diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h index 5e6d476f..59f61a15 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h @@ -7,7 +7,7 @@ // TODO: binary archives class MetalPipelineCache { -public: +private: struct PipelineHash { PipelineHash(uint64 h0, uint64 h1) : h0(h0), h1(h1) {}; @@ -30,7 +30,10 @@ public: }; }; - MetalPipelineCache(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {} +public: + static MetalPipelineCache& GetInstance(); + + MetalPipelineCache(class MetalRenderer* metalRenderer); ~MetalPipelineCache(); MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);