From bca32c43d0023ae298fc1a3e6235a0f50f3932cb Mon Sep 17 00:00:00 2001 From: Samuliak Date: Mon, 28 Oct 2024 16:38:17 +0100 Subject: [PATCH] refactor the way pipelines are stored --- .../Renderer/Metal/MetalPipelineCache.cpp | 53 ++++++++----------- .../Latte/Renderer/Metal/MetalPipelineCache.h | 4 +- .../Renderer/Metal/MetalPipelineCompiler.cpp | 13 +++-- .../Renderer/Metal/MetalPipelineCompiler.h | 10 +++- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 11 ++-- 5 files changed, 45 insertions(+), 46 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp index bc77e00f..58c432f5 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp @@ -15,6 +15,7 @@ #include "HW/Latte/ISA/LatteReg.h" #include "HW/Latte/Renderer/Metal/LatteToMtl.h" #include "HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h" +#include "HW/Latte/Renderer/Metal/MetalPipelineCompiler.h" #include "Metal/MTLRenderPipeline.hpp" #include "util/helpers/helpers.h" #include "config/ActiveSettings.h" @@ -34,32 +35,32 @@ MetalPipelineCache::MetalPipelineCache(class MetalRenderer* metalRenderer) : m_m MetalPipelineCache::~MetalPipelineCache() { - for (auto& [key, value] : m_pipelineCache) - value->release(); + for (auto& [key, pipelineObj] : m_pipelineCache) + { + pipelineObj->m_pipeline->release(); + delete pipelineObj; + } } -MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr) +PipelineObject* MetalPipelineCache::GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr) { uint64 hash = CalculatePipelineHash(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr); - auto it = m_pipelineCache.find(hash); - if (it != m_pipelineCache.end()) - return it->second; + PipelineObject*& pipelineObj = m_pipelineCache[hash]; + if (pipelineObj) + return pipelineObj; - MetalPipelineCompiler compiler(m_mtlr); + pipelineObj = new PipelineObject(); + + MetalPipelineCompiler compiler(m_mtlr, *pipelineObj); bool fbosMatch; compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr, fbosMatch); - bool attemptedCompilation = false; - MTL::RenderPipelineState* pipeline = compiler.Compile(false, true, true, attemptedCompilation); + compiler.Compile(false, true, true); // If FBOs don't match, it wouldn't be possible to reconstruct the pipeline from the cache - if (pipeline && fbosMatch) + if (fbosMatch) AddCurrentStateToCache(hash); - // Place the pipeline to the cache if the compilation was at least attempted - if (attemptedCompilation) - m_pipelineCache.insert({hash, pipeline}); - - return pipeline; + return pipelineObj; } uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr) @@ -358,32 +359,24 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span fileData) MetalAttachmentsInfo attachmentsInfo(*lcr, pixelShader); - MTL::RenderPipelineState* pipeline = nullptr; + PipelineObject* pipelineObject = new PipelineObject(); + // compile { - MetalPipelineCompiler pp(m_mtlr); + MetalPipelineCompiler pp(m_mtlr, *pipelineObject); bool fbosMatch; pp.InitFromState(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr, fbosMatch); cemu_assert_debug(fbosMatch); - //{ - // s_spinlockSharedInternal.lock(); - // delete lcr; - // delete cachedPipeline; - // s_spinlockSharedInternal.unlock(); - // return; - //} - bool attemptedCompilation = false; - pipeline = pp.Compile(true, true, false, attemptedCompilation); - cemu_assert_debug(attemptedCompilation); + pp.Compile(true, true, false); // destroy pp early } - // on success, calculate pipeline hash and flag as present in cache - if (pipeline) + // on success, cache the pipeline + if (pipelineObject->m_pipeline) { uint64 pipelineStateHash = CalculatePipelineHash(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr); m_pipelineCacheLock.lock(); - m_pipelineCache[pipelineStateHash] = pipeline; + m_pipelineCache[pipelineStateHash] = pipelineObject; m_pipelineCacheLock.unlock(); } diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h index b1307568..f4f5e963 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h @@ -12,7 +12,7 @@ public: MetalPipelineCache(class MetalRenderer* metalRenderer); ~MetalPipelineCache(); - MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr); + PipelineObject* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr); // Cache loading uint32 BeginLoading(uint64 cacheTitleId); // returns count of pipelines stored in cache @@ -27,7 +27,7 @@ public: private: class MetalRenderer* m_mtlr; - std::map m_pipelineCache; + std::map m_pipelineCache; FSpinlock m_pipelineCacheLock; std::thread* m_pipelineCacheStoreThread; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp index 6dd6087b..611d190d 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp @@ -327,7 +327,7 @@ void MetalPipelineCompiler::InitFromState(const LatteFetchShader* fetchShader, c InitFromStateRender(fetchShader, vertexShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr, fbosMatch); } -MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool showInOverlay, bool& attemptedCompilation) +bool MetalPipelineCompiler::Compile(bool forceCompile, bool isRenderThread, bool showInOverlay) { if (forceCompile) { @@ -343,11 +343,11 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool { // fail early if some shader stages are not compiled if (m_vertexShaderMtl && !m_vertexShaderMtl->IsCompiled()) - return nullptr; + return false; if (m_geometryShaderMtl && !m_geometryShaderMtl->IsCompiled()) - return nullptr; + return false; if (m_pixelShaderMtl && !m_pixelShaderMtl->IsCompiled()) - return nullptr; + return false; } // Compile @@ -403,10 +403,9 @@ MTL::RenderPipelineState* MetalPipelineCompiler::Compile(bool forceCompile, bool g_compiling_pipelines++; } - // Inform the pipeline cache that compilation was at least attempted - attemptedCompilation = true; + m_pipelineObj.m_pipeline = pipeline; - return pipeline; + return true; } void MetalPipelineCompiler::InitFromStateRender(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const MetalAttachmentsInfo& lastUsedAttachmentsInfo, const MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr, bool& fbosMatch) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h index e3fab932..d762d802 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h @@ -5,18 +5,24 @@ #include "Cafe/HW/Latte/ISA/LatteReg.h" #include "Cafe/HW/Latte/LegacyShaderDecompiler/LatteDecompiler.h" +struct PipelineObject +{ + MTL::RenderPipelineState* m_pipeline = nullptr; +}; + class MetalPipelineCompiler { public: - MetalPipelineCompiler(class MetalRenderer* metalRenderer) : m_mtlr{metalRenderer} {} + MetalPipelineCompiler(class MetalRenderer* metalRenderer, PipelineObject& pipelineObj) : m_mtlr{metalRenderer}, m_pipelineObj{pipelineObj} {} ~MetalPipelineCompiler(); void InitFromState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr, bool& fbosMatch); - MTL::RenderPipelineState* Compile(bool forceCompile, bool isRenderThread, bool showInOverlay, bool& attemptedCompilation); + bool Compile(bool forceCompile, bool isRenderThread, bool showInOverlay); private: class MetalRenderer* m_mtlr; + PipelineObject& m_pipelineObj; class RendererShaderMtl* m_vertexShaderMtl; class RendererShaderMtl* m_geometryShaderMtl; diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index e560c2c3..b3474744 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -23,6 +23,7 @@ #include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h" #include "Cafe/HW/Latte/Renderer/Metal/MetalLayerHandle.h" #include "Cafe/HW/Latte/Renderer/Renderer.h" +#include "HW/Latte/Renderer/Metal/MetalPipelineCompiler.h" #include "config/CemuConfig.h" #define IMGUI_IMPL_METAL_CPP @@ -1000,14 +1001,14 @@ void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 auto renderCommandEncoder = GetRenderCommandEncoder(); // Render pipeline state - MTL::RenderPipelineState* renderPipelineState = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO.m_attachmentsInfo, m_state.m_activeFBO.m_attachmentsInfo, LatteGPUState.contextNew); - if (!renderPipelineState) + PipelineObject* pipelineObj = m_pipelineCache->GetRenderPipelineState(fetchShader, vertexShader, geometryShader, pixelShader, m_state.m_lastUsedFBO.m_attachmentsInfo, m_state.m_activeFBO.m_attachmentsInfo, LatteGPUState.contextNew); + if (!pipelineObj->m_pipeline) return; - if (renderPipelineState != encoderState.m_renderPipelineState) + if (pipelineObj->m_pipeline != encoderState.m_renderPipelineState) { - renderCommandEncoder->setRenderPipelineState(renderPipelineState); - encoderState.m_renderPipelineState = renderPipelineState; + renderCommandEncoder->setRenderPipelineState(pipelineObj->m_pipeline); + encoderState.m_renderPipelineState = pipelineObj->m_pipeline; } // Depth stencil state