1
1
#include " Cafe/HW/Latte/Renderer/Metal/MetalCommon.h"
2
2
#include " Cafe/HW/Latte/Renderer/Metal/MetalPipelineCache.h"
3
3
#include " Cafe/HW/Latte/Renderer/Metal/MetalRenderer.h"
4
+ #include " Foundation/NSObject.hpp"
4
5
#include " HW/Latte/Renderer/Metal/CachedFBOMtl.h"
5
6
#include " HW/Latte/Renderer/Metal/LatteToMtl.h"
6
7
#include " HW/Latte/Renderer/Metal/RendererShaderMtl.h"
7
8
#include " HW/Latte/Renderer/Metal/LatteTextureViewMtl.h"
8
9
9
10
#include " HW/Latte/Core/FetchShader.h"
10
11
#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
+ }
11
35
12
36
MetalPipelineCache::~MetalPipelineCache ()
13
37
{
@@ -16,6 +40,17 @@ MetalPipelineCache::~MetalPipelineCache()
16
40
pair.second ->release ();
17
41
}
18
42
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 ();
19
54
}
20
55
21
56
MTL::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
151
186
}
152
187
}
153
188
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
158
198
if (error)
159
199
{
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++;
163
216
}
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 ();
164
224
165
225
return pipeline;
166
226
}
@@ -238,3 +298,60 @@ uint64 MetalPipelineCache::CalculatePipelineHash(const LatteFetchShader* fetchSh
238
298
239
299
return stateHash;
240
300
}
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