prepare for shader cache

This commit is contained in:
Samuliak 2024-08-14 11:57:01 +02:00
parent 13834ca9cb
commit 53efb9e5b2
3 changed files with 74 additions and 11 deletions

View file

@ -2,22 +2,40 @@
#include "Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
#include "Cafe/HW/Latte/Renderer/Metal/LatteToMtl.h"
#include "Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
#include "Cemu/FileCache/FileCache.h"
#include "config/ActiveSettings.h"
#include "Cemu/Logging/CemuLogging.h"
#include "Common/precompiled.h"
bool s_isLoadingShadersMtl{ false };
class FileCache* s_mslCache{nullptr};
extern std::atomic_int g_compiled_shaders_total;
extern std::atomic_int g_compiled_shaders_async;
RendererShaderMtl::RendererShaderMtl(MetalRenderer* mtlRenderer, ShaderType type, uint64 baseHash, uint64 auxHash, bool isGameShader, bool isGfxPackShader, const std::string& mslCode)
: RendererShader(type, baseHash, auxHash, isGameShader, isGfxPackShader), m_mtlr{mtlRenderer}
{
// Fragment functions are compiled just-in-time
if (LoadBinary())
return;
if (m_type == ShaderType::kFragment)
{
// Fragment functions are compiled just-in-time
m_mslCode = mslCode;
}
else
{
Compile(mslCode);
}
// Store the compiled shader in the cache
StoreBinary();
// Count shader compilation
if (!s_isLoadingShadersMtl)
g_compiled_shaders_total++;
}
RendererShaderMtl::~RendererShaderMtl()
@ -69,17 +87,29 @@ void RendererShaderMtl::CompileFragmentFunction(CachedFBOMtl* activeFBO)
void RendererShaderMtl::ShaderCacheLoading_begin(uint64 cacheTitleId)
{
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_begin not implemented!");
if (s_mslCache)
{
delete s_mslCache;
}
uint32 spirvCacheMagic = GeneratePrecompiledCacheId();
const std::string cacheFilename = fmt::format("{:016x}_msl.bin", cacheTitleId);
const fs::path cachePath = ActiveSettings::GetCachePath("shaderCache/precompiled/{}", cacheFilename);
s_mslCache = FileCache::Open(cachePath, true, spirvCacheMagic);
if (!s_mslCache)
cemuLog_log(LogType::Force, "Unable to open MSL cache {}", cacheFilename);
s_isLoadingShadersMtl = true;
}
void RendererShaderMtl::ShaderCacheLoading_end()
{
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_end not implemented!");
s_isLoadingShadersMtl = false;
}
void RendererShaderMtl::ShaderCacheLoading_Close()
{
cemuLog_log(LogType::MetalLogging, "RendererShaderMtl::ShaderCacheLoading_Close not implemented!");
delete s_mslCache;
g_compiled_shaders_total = 0;
g_compiled_shaders_async = 0;
}
void RendererShaderMtl::Compile(const std::string& mslCode)
@ -95,3 +125,33 @@ void RendererShaderMtl::Compile(const std::string& mslCode)
m_function = library->newFunction(NS::String::string("main0", NS::ASCIIStringEncoding));
library->release();
}
bool RendererShaderMtl::LoadBinary()
{
// HACK: since fragment functions are compiled just-in-time, we cannot load them from the cache
if (m_type == ShaderType::kFragment)
return false;
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
if (!s_mslCache->GetFile({h1, h2 }, m_binary))
return false;
// TODO: implement
return false;
return true;
}
void RendererShaderMtl::StoreBinary()
{
if (m_binary.size() == 0)
{
// TODO: retrieve the binary from the function
return;
}
uint64 h1, h2;
GenerateShaderPrecompiledCacheFilename(m_type, m_baseHash, m_auxHash, h1, h2);
s_mslCache->AddFileAsync({h1, h2 }, m_binary.data(), m_binary.size());
}