A game about forced loneliness, made by TACStudios
1using System.Collections.Generic;
2using UnityEngine.Rendering;
3using UnityEngine.Rendering.RenderGraphModule;
4using UnityEngine.Rendering.RenderGraphModule.NativeRenderPassCompiler;
5
6class RenderGraphCompilationCache
7{
8 struct HashEntry<T>
9 {
10 public int hash;
11 public int lastFrameUsed;
12 public T compiledGraph;
13 }
14
15 DynamicArray<HashEntry<RenderGraph.CompiledGraph>> m_HashEntries = new();
16 DynamicArray<HashEntry<CompilerContextData>> m_NativeHashEntries = new();
17
18 Stack<RenderGraph.CompiledGraph> m_CompiledGraphPool = new();
19 Stack<CompilerContextData> m_NativeCompiledGraphPool = new();
20
21 static int HashEntryComparer<T>(HashEntry<T> a, HashEntry<T> b)
22 {
23 if (a.lastFrameUsed < b.lastFrameUsed)
24 return -1;
25 else if (a.lastFrameUsed > b.lastFrameUsed)
26 return 1;
27 else
28 return 0;
29 }
30
31 static DynamicArray<HashEntry<RenderGraph.CompiledGraph>>.SortComparer s_EntryComparer = HashEntryComparer<RenderGraph.CompiledGraph>;
32 static DynamicArray<HashEntry<CompilerContextData>>.SortComparer s_NativeEntryComparer = HashEntryComparer<CompilerContextData>;
33
34 const int k_CachedGraphCount = 20;
35
36 public RenderGraphCompilationCache()
37 {
38 for (int i = 0; i < k_CachedGraphCount; ++i)
39 {
40 m_CompiledGraphPool.Push(new RenderGraph.CompiledGraph());
41 m_NativeCompiledGraphPool.Push(new CompilerContextData(NativePassCompiler.k_EstimatedPassCount));
42 }
43 }
44
45 // Avoid GC in lambda.
46 static int s_Hash;
47
48 bool GetCompilationCache<T>(int hash, int frameIndex, out T outGraph, DynamicArray<HashEntry<T>> hashEntries, Stack<T> pool, DynamicArray<HashEntry<T>>.SortComparer comparer)
49 where T : RenderGraph.ICompiledGraph
50 {
51 s_Hash = hash;
52 int index = hashEntries.FindIndex(0, hashEntries.size, (value) => value.hash == s_Hash);
53 if (index != -1)
54 {
55 ref var entry = ref hashEntries[index];
56 outGraph = entry.compiledGraph;
57 entry.lastFrameUsed = frameIndex;
58 return true;
59 }
60 else
61 {
62 if (pool.Count != 0)
63 {
64 var newEntry = new HashEntry<T>()
65 {
66 hash = hash,
67 lastFrameUsed = frameIndex,
68 compiledGraph = pool.Pop()
69 };
70 hashEntries.Add(newEntry);
71 outGraph = newEntry.compiledGraph;
72 return false;
73 }
74 else
75 {
76 // Reuse the oldest one.
77 hashEntries.QuickSort(comparer);
78 ref var oldestEntry = ref hashEntries[0];
79 oldestEntry.hash = hash;
80 oldestEntry.lastFrameUsed = frameIndex;
81 oldestEntry.compiledGraph.Clear();
82
83 outGraph = oldestEntry.compiledGraph;
84 return false;
85 }
86 }
87 }
88
89 public bool GetCompilationCache(int hash, int frameIndex, out RenderGraph.CompiledGraph outGraph)
90 {
91 return GetCompilationCache(hash, frameIndex, out outGraph, m_HashEntries, m_CompiledGraphPool, s_EntryComparer);
92 }
93
94 public bool GetCompilationCache(int hash, int frameIndex, out CompilerContextData outGraph)
95 {
96 return GetCompilationCache(hash, frameIndex, out outGraph, m_NativeHashEntries, m_NativeCompiledGraphPool, s_NativeEntryComparer);
97 }
98
99 public void Clear()
100 {
101 for (int i = 0; i < m_HashEntries.size; ++i)
102 m_CompiledGraphPool.Push(m_HashEntries[i].compiledGraph);
103 m_HashEntries.Clear();
104
105 for (int i = 0; i < m_NativeHashEntries.size; ++i)
106 m_NativeCompiledGraphPool.Push(m_NativeHashEntries[i].compiledGraph);
107 m_NativeHashEntries.Clear();
108 }
109}