11#include " Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
22#include " Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h"
33#include " Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
4+ #include " Foundation/NSObject.hpp"
45#include " HW/Latte/Renderer/Metal/CachedFBOMtl.h"
56#include " HW/Latte/Renderer/Metal/LatteToMtl.h"
67#include " HW/Latte/Renderer/Metal/RendererShaderMtl.h"
78#include " HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
89
910#include " HW/Latte/Core/FetchShader.h"
1011#include " HW/Latte/ISA/RegDefines.h"
12+ #include " config/ActiveSettings.h"
13+
14+ #define INVALID_TITLE_ID 0xFFFFFFFFFFFFFFFF
15+
16+ uint64 s_cacheTitleId = INVALID_TITLE_ID;
17+
18+ extern std::atomic_int g_compiled_shaders_total;
19+ extern std::atomic_int g_compiled_shaders_async;
20+
21+ void MetalPipelineCache::ShaderCacheLoading_begin (uint64 cacheTitleId)
22+ {
23+ s_cacheTitleId = cacheTitleId;
24+ }
25+
26+ void MetalPipelineCache::ShaderCacheLoading_end ()
27+ {
28+ }
29+
30+ void MetalPipelineCache::ShaderCacheLoading_Close ()
31+ {
32+ g_compiled_shaders_total = 0 ;
33+ g_compiled_shaders_async = 0 ;
34+ }
1135
1236MetalPipelineCache::~MetalPipelineCache ()
1337{
@@ -16,6 +40,17 @@ MetalPipelineCache::~MetalPipelineCache()
1640 pair.second ->release ();
1741 }
1842 m_pipelineCache.clear ();
43+
44+ NS::Error* error = nullptr ;
45+ m_binaryArchive->serializeToURL (m_binaryArchiveURL, &error);
46+ if (error)
47+ {
48+ debug_printf (" failed to serialize binary archive: %s\n " , error->localizedDescription ()->utf8String ());
49+ error->release ();
50+ }
51+ m_binaryArchive->release ();
52+
53+ m_binaryArchiveURL->release ();
1954}
2055
2156MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState (const LatteFetchShader* fetchShader, const LatteDecompilerShader* vertexShader, const LatteDecompilerShader* pixelShader, CachedFBOMtl* activeFBO, const LatteContextRegister& lcr)
@@ -151,16 +186,41 @@ MTL::RenderPipelineState* MetalPipelineCache::GetPipelineState(const LatteFetchS
151186 }
152187 }
153188
154- NS::Error* error = nullptr ;
155- pipeline = m_mtlr->GetDevice ()->newRenderPipelineState (desc, &error);
156- desc->release ();
157- vertexDescriptor->release ();
189+ LoadBinary (desc);
190+
191+ NS::Error* error = nullptr ;
192+ pipeline = m_mtlr->GetDevice ()->newRenderPipelineState (desc, MTL::PipelineOptionFailOnBinaryArchiveMiss, nullptr , &error);
193+
194+ // static uint32 oldPipelineCount = 0;
195+ // static uint32 newPipelineCount = 0;
196+
197+ // Pipeline wasn't found in the binary archive, we need to compile it
158198 if (error)
159199 {
160- debug_printf (" error creating render pipeline state: %s\n " , error->localizedDescription ()->utf8String ());
161- error->release ();
162- return nullptr ;
200+ desc->setBinaryArchives (nullptr );
201+
202+ error->release ();
203+ error = nullptr ;
204+ pipeline = m_mtlr->GetDevice ()->newRenderPipelineState (desc, &error);
205+ if (error)
206+ {
207+ debug_printf (" error creating render pipeline state: %s\n " , error->localizedDescription ()->utf8String ());
208+ error->release ();
209+ }
210+ else
211+ {
212+ SaveBinary (desc);
213+ }
214+
215+ // newPipelineCount++;
163216 }
217+ // else
218+ // {
219+ // oldPipelineCount++;
220+ // }
221+ // debug_printf("%u pipelines were found in the binary archive, %u new were created\n", oldPipelineCount, newPipelineCount);
222+ desc->release ();
223+ vertexDescriptor->release ();
164224
165225 return pipeline;
166226}
@@ -238,3 +298,60 @@ uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchSh
238298
239299 return stateHash;
240300}
301+
302+ void MetalPipelineCache::TryLoadBinaryArchive ()
303+ {
304+ if (m_binaryArchive || s_cacheTitleId == INVALID_TITLE_ID)
305+ return ;
306+
307+ const std::string cacheFilename = fmt::format (" {:016x}_mtl_pipelines.bin" , s_cacheTitleId);
308+ const fs::path cachePath = ActiveSettings::GetCachePath (" shaderCache/precompiled/{}" , cacheFilename);
309+ m_binaryArchiveURL = NS::URL::fileURLWithPath (NS::String::string ((const char *)cachePath.generic_u8string ().c_str (), NS::ASCIIStringEncoding));
310+
311+ MTL::BinaryArchiveDescriptor* desc = MTL::BinaryArchiveDescriptor::alloc ()->init ();
312+ desc->setUrl (m_binaryArchiveURL);
313+
314+ NS::Error* error = nullptr ;
315+ m_binaryArchive = m_mtlr->GetDevice ()->newBinaryArchive (desc, &error);
316+ if (error)
317+ {
318+ desc->setUrl (nullptr );
319+
320+ error->release ();
321+ error = nullptr ;
322+ m_binaryArchive = m_mtlr->GetDevice ()->newBinaryArchive (desc, &error);
323+ if (error)
324+ {
325+ debug_printf (" failed to create binary archive: %s\n " , error->localizedDescription ()->utf8String ());
326+ error->release ();
327+ }
328+ }
329+ desc->release ();
330+ }
331+
332+ void MetalPipelineCache::LoadBinary (MTL::RenderPipelineDescriptor* desc)
333+ {
334+ TryLoadBinaryArchive ();
335+
336+ if (!m_binaryArchive)
337+ return ;
338+
339+ NS::Object* binArchives[] = {m_binaryArchive};
340+ auto binaryArchives = NS::Array::alloc ()->init (binArchives, 1 );
341+ desc->setBinaryArchives (binaryArchives);
342+ binaryArchives->release ();
343+ }
344+
345+ void MetalPipelineCache::SaveBinary (MTL::RenderPipelineDescriptor* desc)
346+ {
347+ if (!m_binaryArchive)
348+ return ;
349+
350+ NS::Error* error = nullptr ;
351+ m_binaryArchive->addRenderPipelineFunctions (desc, &error);
352+ if (error)
353+ {
354+ debug_printf (" error saving render pipeline functions: %s\n " , error->localizedDescription ()->utf8String ());
355+ error->release ();
356+ }
357+ }
0 commit comments