A game about forced loneliness, made by TACStudios
1using System;
2using System.Collections.Generic;
3
4namespace UnityEngine.Rendering.RenderGraphModule
5{
6 /// <summary>
7 /// Helper class provided in the RenderGraphContext to all Render Passes.
8 /// It allows you to do temporary allocations of various objects during a Render Pass.
9 /// </summary>
10 public sealed class RenderGraphObjectPool
11 {
12 // Only used to clear all existing pools at once from here when needed
13 static DynamicArray<SharedObjectPoolBase> s_AllocatedPools = new DynamicArray<SharedObjectPoolBase>();
14
15 // Non abstract class instead of an interface to store it in a DynamicArray
16 class SharedObjectPoolBase
17 {
18 public SharedObjectPoolBase() {}
19 public virtual void Clear() {}
20 }
21
22 class SharedObjectPool<T> : SharedObjectPoolBase where T : class, new()
23 {
24 private static readonly Pool.ObjectPool<T> s_Pool = AllocatePool();
25
26 private static Pool.ObjectPool<T> AllocatePool()
27 {
28 var newPool = new Pool.ObjectPool<T>(() => new T(), null, null);
29 // Storing instance to clear the static pool of the same type if needed
30 s_AllocatedPools.Add(new SharedObjectPool<T>());
31 return newPool;
32 }
33
34 /// <summary>
35 /// Clear the pool using SharedObjectPool instance.
36 /// </summary>
37 /// <returns></returns>
38 public override void Clear()
39 {
40 s_Pool.Clear();
41 }
42
43 /// <summary>
44 /// Get a new instance from the pool.
45 /// </summary>
46 /// <returns></returns>
47 public static T Get() => s_Pool.Get();
48
49 /// <summary>
50 /// Release an object to the pool.
51 /// </summary>
52 /// <param name="toRelease">instance to release.</param>
53 public static void Release(T toRelease) => s_Pool.Release(toRelease);
54 }
55
56
57 Dictionary<(Type, int), Stack<object>> m_ArrayPool = new Dictionary<(Type, int), Stack<object>>();
58 List<(object, (Type, int))> m_AllocatedArrays = new List<(object, (Type, int))>();
59 List<MaterialPropertyBlock> m_AllocatedMaterialPropertyBlocks = new List<MaterialPropertyBlock>();
60
61 internal RenderGraphObjectPool() { }
62
63 /// <summary>
64 /// Allocate a temporary typed array of a specific size.
65 /// Unity releases the array at the end of the Render Pass.
66 /// </summary>
67 /// <typeparam name="T">Type of the array to be allocated.</typeparam>
68 /// <param name="size">Number of element in the array.</param>
69 /// <returns>A new array of type T with size number of elements.</returns>
70 public T[] GetTempArray<T>(int size)
71 {
72 if (!m_ArrayPool.TryGetValue((typeof(T), size), out var stack))
73 {
74 stack = new Stack<object>();
75 m_ArrayPool.Add((typeof(T), size), stack);
76 }
77
78 var result = stack.Count > 0 ? (T[])stack.Pop() : new T[size];
79 m_AllocatedArrays.Add((result, (typeof(T), size)));
80 return result;
81 }
82
83 /// <summary>
84 /// Allocate a temporary MaterialPropertyBlock for the Render Pass.
85 /// </summary>
86 /// <returns>A new clean MaterialPropertyBlock.</returns>
87 public MaterialPropertyBlock GetTempMaterialPropertyBlock()
88 {
89 var result = SharedObjectPool<MaterialPropertyBlock>.Get();
90 result.Clear();
91 m_AllocatedMaterialPropertyBlocks.Add(result);
92 return result;
93 }
94
95 internal void ReleaseAllTempAlloc()
96 {
97 foreach (var arrayDesc in m_AllocatedArrays)
98 {
99 bool result = m_ArrayPool.TryGetValue(arrayDesc.Item2, out var stack);
100 Debug.Assert(result, "Correct stack type should always be allocated.");
101 stack.Push(arrayDesc.Item1);
102 }
103
104 m_AllocatedArrays.Clear();
105
106 foreach (var mpb in m_AllocatedMaterialPropertyBlocks)
107 {
108 SharedObjectPool<MaterialPropertyBlock>.Release(mpb);
109 }
110
111 m_AllocatedMaterialPropertyBlocks.Clear();
112 }
113
114 // Regular pooling API. Only internal use for now
115 internal T Get<T>() where T : class, new()
116 {
117 return SharedObjectPool<T>.Get();
118 }
119
120 internal void Release<T>(T value) where T : class, new()
121 {
122 SharedObjectPool<T>.Release(value);
123 }
124
125 internal void Cleanup()
126 {
127 m_AllocatedArrays.Clear();
128 m_AllocatedMaterialPropertyBlocks.Clear();
129 m_ArrayPool.Clear();
130
131 // Removing all objects in the pools
132 foreach (var pool in s_AllocatedPools)
133 pool.Clear();
134 }
135 }
136}