mirror of
https://github.com/cemu-project/Cemu.git
synced 2025-07-05 14:31:17 +12:00
implement pipeline cache serializing
This commit is contained in:
parent
e9e510d2cd
commit
6b47d4f61e
3 changed files with 66 additions and 35 deletions
|
@ -64,7 +64,7 @@ FileCache* s_shaderCacheGeneric = nullptr; // contains hardware and version inde
|
||||||
#define SHADER_CACHE_TYPE_PIXEL (2)
|
#define SHADER_CACHE_TYPE_PIXEL (2)
|
||||||
|
|
||||||
bool LatteShaderCache_readSeparableShader(uint8* shaderInfoData, sint32 shaderInfoSize);
|
bool LatteShaderCache_readSeparableShader(uint8* shaderInfoData, sint32 shaderInfoSize);
|
||||||
void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId);
|
void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId);
|
||||||
bool LatteShaderCache_updatePipelineLoadingProgress();
|
bool LatteShaderCache_updatePipelineLoadingProgress();
|
||||||
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateFunc, bool isPipelines);
|
void LatteShaderCache_ShowProgress(const std::function <bool(void)>& 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);
|
cemuLog_log(LogType::Force, "Shader cache loaded with {} shaders. Commited mem {}MB. Took {}ms", numLoadedShaders, (sint32)(memCommited/1024/1024), timeLoad);
|
||||||
#endif
|
#endif
|
||||||
LatteShaderCache_finish();
|
LatteShaderCache_finish();
|
||||||
// if Vulkan then also load pipeline cache
|
// if Vulkan or Metal then also load pipeline cache
|
||||||
if (g_renderer->GetType() == RendererAPI::Vulkan)
|
if (g_renderer->GetType() == RendererAPI::Vulkan || g_renderer->GetType() == RendererAPI::Metal)
|
||||||
LatteShaderCache_LoadVulkanPipelineCache(cacheTitleId);
|
LatteShaderCache_LoadPipelineCache(cacheTitleId);
|
||||||
|
|
||||||
|
|
||||||
g_renderer->BeginFrame(true);
|
g_renderer->BeginFrame(true);
|
||||||
|
@ -504,13 +504,18 @@ void LatteShaderCache_ShowProgress(const std::function <bool(void)>& loadUpdateF
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId)
|
void LatteShaderCache_LoadPipelineCache(uint64 cacheTitleId)
|
||||||
{
|
{
|
||||||
auto& pipelineCache = VulkanPipelineStableCache::GetInstance();
|
if (g_renderer->GetType() == RendererAPI::Vulkan)
|
||||||
g_shaderCacheLoaderState.pipelineFileCount = pipelineCache.BeginLoading(cacheTitleId);
|
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;
|
g_shaderCacheLoaderState.loadedPipelines = 0;
|
||||||
LatteShaderCache_ShowProgress(LatteShaderCache_updatePipelineLoadingProgress, true);
|
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())
|
if(Latte_GetStopSignal())
|
||||||
LatteThread_Exit();
|
LatteThread_Exit();
|
||||||
}
|
}
|
||||||
|
@ -518,7 +523,12 @@ void LatteShaderCache_LoadVulkanPipelineCache(uint64 cacheTitleId)
|
||||||
bool LatteShaderCache_updatePipelineLoadingProgress()
|
bool LatteShaderCache_updatePipelineLoadingProgress()
|
||||||
{
|
{
|
||||||
uint32 pipelinesMissingShaders = 0;
|
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)
|
uint64 LatteShaderCache_getShaderNameInTransferableCache(uint64 baseHash, uint32 shaderType)
|
||||||
|
@ -783,9 +793,11 @@ void LatteShaderCache_Close()
|
||||||
else if (g_renderer->GetType() == RendererAPI::Metal)
|
else if (g_renderer->GetType() == RendererAPI::Metal)
|
||||||
RendererShaderMtl::ShaderCacheLoading_Close();
|
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)
|
if (g_renderer->GetType() == RendererAPI::Vulkan)
|
||||||
VulkanPipelineStableCache::GetInstance().Close();
|
VulkanPipelineStableCache::GetInstance().Close();
|
||||||
|
else if (g_renderer->GetType() == RendererAPI::Metal)
|
||||||
|
MetalPipelineCache::GetInstance().Close();
|
||||||
}
|
}
|
||||||
|
|
||||||
#include <wx/msgdlg.h>
|
#include <wx/msgdlg.h>
|
||||||
|
|
|
@ -15,6 +15,43 @@
|
||||||
#include "config/ActiveSettings.h"
|
#include "config/ActiveSettings.h"
|
||||||
#include <openssl/sha.h>
|
#include <openssl/sha.h>
|
||||||
|
|
||||||
|
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)
|
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
|
// Hash
|
||||||
|
@ -117,27 +154,6 @@ uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchSh
|
||||||
return stateHash;
|
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
|
struct
|
||||||
{
|
{
|
||||||
uint32 pipelineLoadIndex;
|
uint32 pipelineLoadIndex;
|
||||||
|
@ -181,7 +197,7 @@ uint32 MetalPipelineCache::BeginLoading(uint64 cacheTitleId)
|
||||||
s_cache = FileCache::Open(pathCacheFile, true, LatteShaderCache_getPipelineCacheExtraVersion(cacheTitleId));
|
s_cache = FileCache::Open(pathCacheFile, true, LatteShaderCache_getPipelineCacheExtraVersion(cacheTitleId));
|
||||||
if (!s_cache)
|
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;
|
return 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -436,7 +452,7 @@ bool MetalPipelineCache::DeserializePipeline(MemStreamReader& memReader, CachedP
|
||||||
// version
|
// version
|
||||||
if (memReader.readBE<uint8>() != 1)
|
if (memReader.readBE<uint8>() != 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;
|
return false;
|
||||||
}
|
}
|
||||||
// shader hashes
|
// shader hashes
|
||||||
|
|
|
@ -7,7 +7,7 @@
|
||||||
// TODO: binary archives
|
// TODO: binary archives
|
||||||
class MetalPipelineCache
|
class MetalPipelineCache
|
||||||
{
|
{
|
||||||
public:
|
private:
|
||||||
struct PipelineHash
|
struct PipelineHash
|
||||||
{
|
{
|
||||||
PipelineHash(uint64 h0, uint64 h1) : h0(h0), h1(h1) {};
|
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();
|
~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);
|
MTL::RenderPipelineState* GetRenderPipelineState(const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* geometryShader, const LatteDecompilerShader* pixelShader, class CachedFBOMtl* lastUsedFBO, class CachedFBOMtl* activeFBO, const LatteContextRegister& lcr);
|
||||||
|
|
Loading…
Add table
Add a link
Reference in a new issue