From 53efb9e5b2bc5c4a34b4cdbd36e058cc1d7f2dda Mon Sep 17 00:00:00 2001 From: Samuliak Date: Wed, 14 Aug 2024 11:57:01 +0200 Subject: [PATCH] prepare for shader cache --- .../HW/Latte/Renderer/Metal/MetalRenderer.cpp | 13 ++-- .../Renderer/Metal/RendererShaderMtl.cpp | 68 +++++++++++++++++-- .../Latte/Renderer/Metal/RendererShaderMtl.h | 4 ++ 3 files changed, 74 insertions(+), 11 deletions(-) diff --git a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp index e55be3e2..b94f73bd 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/MetalRenderer.cpp @@ -665,22 +665,21 @@ void MetalRenderer::draw_beginSequence() if (!rasterizerEnable == false) m_state.m_skipDrawSequence = true; + + // TODO: is this even needed? + if (!m_state.m_activeFBO) + m_state.m_skipDrawSequence = true; } void MetalRenderer::draw_execute(uint32 baseVertex, uint32 baseInstance, uint32 instanceCount, uint32 count, MPTR indexDataMPTR, Latte::LATTE_VGT_DMA_INDEX_TYPE::E_INDEX_TYPE indexType, bool isFirst) { - //if (m_state.skipDrawSequence) + // TODO: uncomment + //if (m_state.m_skipDrawSequence) //{ // return; //} // Render pass - if (!m_state.m_activeFBO) - { - debug_printf("no active FBO, skipping draw\n"); - return; - } - auto renderCommandEncoder = GetRenderCommandEncoder(); // Shaders diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp index 18334052..08d036a0 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.cpp @@ -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()); +} diff --git a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h index f70db1bd..f788c145 100644 --- a/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h +++ b/src/Cafe/HW/Latte/Renderer/Metal/RendererShaderMtl.h @@ -58,7 +58,11 @@ private: MTL::Function* m_function = nullptr; + std::vector m_binary; std::string m_mslCode; void Compile(const std::string& mslCode); + + bool LoadBinary(); + void StoreBinary(); };