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 " 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 " 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 " 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" 
308+ 	const  fs::path cachePath = ActiveSettings::GetCachePath (" shaderCache/precompiled/{}" 
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 " 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 " localizedDescription ()->utf8String ());
355+         error->release ();
356+     }
357+ }
0 commit comments