Skip to content

Commit

Permalink
refactor the way pipelines are stored
Browse files Browse the repository at this point in the history
  • Loading branch information
SamoZ256 committed Oct 28, 2024
1 parent 665eb23 commit bca32c4
Show file tree
Hide file tree
Showing 5 changed files with 45 additions and 46 deletions.
53 changes: 23 additions & 30 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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"
Expand All @@ -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;

pipelineObj = new PipelineObject();

MetalPipelineCompiler compiler(m_mtlr);
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)
Expand Down Expand Up @@ -358,32 +359,24 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span<uint8> 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();
}

Expand Down
4 changes: 2 additions & 2 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h
Original file line number Diff line number Diff line change
Expand Up @@ -12,7 +12,7 @@ class MetalPipelineCache
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
Expand All @@ -27,7 +27,7 @@ class MetalPipelineCache
private:
class MetalRenderer* m_mtlr;

std::map<uint64, MTL::RenderPipelineState*> m_pipelineCache;
std::map<uint64, PipelineObject*> m_pipelineCache;
FSpinlock m_pipelineCacheLock;

std::thread* m_pipelineCacheStoreThread;
Expand Down
13 changes: 6 additions & 7 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand All @@ -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
Expand Down Expand Up @@ -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)
Expand Down
10 changes: 8 additions & 2 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalPipelineCompiler.h
Original file line number Diff line number Diff line change
Expand Up @@ -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;
Expand Down
11 changes: 6 additions & 5 deletions src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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
Expand Down

0 comments on commit bca32c4

Please sign in to comment.