store loaded pipelines

This commit is contained in:
Samuliak 2024-10-15 17:47:47 +02:00
parent cd21d957b3
commit 944cc8be7d
No known key found for this signature in database
2 changed files with 20 additions and 48 deletions

View File

@ -14,6 +14,7 @@
#include "HW/Latte/ISA/LatteReg.h" #include "HW/Latte/ISA/LatteReg.h"
#include "HW/Latte/Renderer/Metal/LatteToMtl.h" #include "HW/Latte/Renderer/Metal/LatteToMtl.h"
#include "HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h" #include "HW/Latte/Renderer/Metal/MetalAttachmentsInfo.h"
#include "Metal/MTLRenderPipeline.hpp"
#include "util/helpers/helpers.h" #include "util/helpers/helpers.h"
#include "config/ActiveSettings.h" #include "config/ActiveSettings.h"
#include <openssl/sha.h> #include <openssl/sha.h>
@ -49,8 +50,7 @@ MTL::RenderPipelineState* MetalPipelineCache::GetRenderPipelineState(const Latte
compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr); compiler.InitFromState(fetchShader, vertexShader, geometryShader, pixelShader, lastUsedAttachmentsInfo, activeAttachmentsInfo, lcr);
pipeline = compiler.Compile(false, true); pipeline = compiler.Compile(false, true);
if (!HasPipelineCached(vertexShader->baseHash, hash)) AddCurrentStateToCache(hash);
AddCurrentStateToCache(vertexShader->baseHash, hash);
return pipeline; return pipeline;
} }
@ -351,6 +351,7 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span<uint8> fileData)
MetalAttachmentsInfo attachmentsInfo(*lcr, pixelShader); MetalAttachmentsInfo attachmentsInfo(*lcr, pixelShader);
MTL::RenderPipelineState* pipeline = nullptr;
// compile // compile
{ {
MetalPipelineCompiler pp(m_mtlr); MetalPipelineCompiler pp(m_mtlr);
@ -362,15 +363,18 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span<uint8> fileData)
// s_spinlockSharedInternal.unlock(); // s_spinlockSharedInternal.unlock();
// return; // return;
//} //}
pp.Compile(true, true); pipeline = pp.Compile(true, true);
// destroy pp early // destroy pp early
} }
// on success, calculate pipeline hash and flag as present in cache // on success, calculate pipeline hash and flag as present in cache
uint64 pipelineBaseHash = vertexShader->baseHash; if (pipeline)
uint64 pipelineStateHash = CalculatePipelineHash(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr); {
m_pipelineIsCachedLock.lock(); uint64 pipelineStateHash = CalculatePipelineHash(vertexShader->compatibleFetchShader, vertexShader, geometryShader, pixelShader, attachmentsInfo, attachmentsInfo, *lcr);
m_pipelineIsCached.emplace(pipelineBaseHash, pipelineStateHash); m_pipelineCacheLock.lock();
m_pipelineIsCachedLock.unlock(); m_pipelineCache[pipelineStateHash] = pipeline;
m_pipelineCacheLock.unlock();
}
// clean up // clean up
s_spinlockSharedInternal.lock(); s_spinlockSharedInternal.lock();
@ -379,17 +383,10 @@ void MetalPipelineCache::LoadPipelineFromCache(std::span<uint8> fileData)
s_spinlockSharedInternal.unlock(); s_spinlockSharedInternal.unlock();
} }
bool MetalPipelineCache::HasPipelineCached(uint64 baseHash, uint64 pipelineStateHash)
{
PipelineHash ph(baseHash, pipelineStateHash);
return m_pipelineIsCached.find(ph) != m_pipelineIsCached.end();
}
ConcurrentQueue<CachedPipeline*> g_mtlPipelineCachingQueue; ConcurrentQueue<CachedPipeline*> g_mtlPipelineCachingQueue;
void MetalPipelineCache::AddCurrentStateToCache(uint64 baseHash, uint64 pipelineStateHash) void MetalPipelineCache::AddCurrentStateToCache(uint64 pipelineStateHash)
{ {
m_pipelineIsCached.emplace(baseHash, pipelineStateHash);
if (!m_pipelineCacheStoreThread) if (!m_pipelineCacheStoreThread)
{ {
m_pipelineCacheStoreThread = new std::thread(&MetalPipelineCache::WorkerThread, this); m_pipelineCacheStoreThread = new std::thread(&MetalPipelineCache::WorkerThread, this);

View File

@ -7,29 +7,6 @@
// TODO: binary archives // TODO: binary archives
class MetalPipelineCache class MetalPipelineCache
{ {
private:
struct PipelineHash
{
PipelineHash(uint64 h0, uint64 h1) : h0(h0), h1(h1) {};
uint64 h0;
uint64 h1;
bool operator==(const PipelineHash& r) const
{
return h0 == r.h0 && h1 == r.h1;
}
struct HashFunc
{
size_t operator()(const PipelineHash& v) const
{
static_assert(sizeof(uint64) == sizeof(size_t));
return v.h0 ^ v.h1;
}
};
};
public: public:
static MetalPipelineCache& GetInstance(); static MetalPipelineCache& GetInstance();
@ -45,13 +22,6 @@ public:
void LoadPipelineFromCache(std::span<uint8> fileData); void LoadPipelineFromCache(std::span<uint8> fileData);
void Close(); // called on title exit void Close(); // called on title exit
bool HasPipelineCached(uint64 baseHash, uint64 pipelineStateHash);
void AddCurrentStateToCache(uint64 baseHash, uint64 pipelineStateHash);
// pipeline serialization for file
bool SerializePipeline(class MemStreamWriter& memWriter, struct CachedPipeline& cachedPipeline);
bool DeserializePipeline(class MemStreamReader& memReader, struct CachedPipeline& cachedPipeline);
// Debug // Debug
size_t GetPipelineCacheSize() const { return m_pipelineCache.size(); } size_t GetPipelineCacheSize() const { return m_pipelineCache.size(); }
@ -59,11 +29,10 @@ private:
class MetalRenderer* m_mtlr; class MetalRenderer* m_mtlr;
std::map<uint64, MTL::RenderPipelineState*> m_pipelineCache; std::map<uint64, MTL::RenderPipelineState*> m_pipelineCache;
FSpinlock m_pipelineCacheLock;
std::thread* m_pipelineCacheStoreThread; std::thread* m_pipelineCacheStoreThread;
std::unordered_set<PipelineHash, PipelineHash::HashFunc> m_pipelineIsCached;
FSpinlock m_pipelineIsCachedLock;
class FileCache* s_cache; class FileCache* s_cache;
std::atomic_uint32_t m_numCompilationThreads{ 0 }; std::atomic_uint32_t m_numCompilationThreads{ 0 };
@ -72,6 +41,12 @@ private:
static uint64 CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr); static uint64 CalculatePipelineHash(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, const class MetalAttachmentsInfo& lastUsedAttachmentsInfo, const class MetalAttachmentsInfo& activeAttachmentsInfo, const LatteContextRegister& lcr);
void AddCurrentStateToCache(uint64 pipelineStateHash);
// pipeline serialization for file
bool SerializePipeline(class MemStreamWriter& memWriter, struct CachedPipeline& cachedPipeline);
bool DeserializePipeline(class MemStreamReader& memReader, struct CachedPipeline& cachedPipeline);
int CompilerThread(); int CompilerThread();
void WorkerThread(); void WorkerThread();
}; };