summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/object_pool.h
diff options
context:
space:
mode:
authorGravatar ReinUsesLisp2021-02-15 00:09:11 -0300
committerGravatar ameerj2021-07-22 21:51:22 -0400
commitd5d468cf2cbe235ee149dbd37951389d2a7e61da (patch)
treee99fe0e09c130d6171add858f6e9520d6b3948d5 /src/shader_recompiler/object_pool.h
parentshader: Fix tracking (diff)
downloadyuzu-d5d468cf2cbe235ee149dbd37951389d2a7e61da.tar.gz
yuzu-d5d468cf2cbe235ee149dbd37951389d2a7e61da.tar.xz
yuzu-d5d468cf2cbe235ee149dbd37951389d2a7e61da.zip
shader: Improve object pool
Diffstat (limited to 'src/shader_recompiler/object_pool.h')
-rw-r--r--src/shader_recompiler/object_pool.h84
1 files changed, 50 insertions, 34 deletions
diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h
index a573add32..f78813b5f 100644
--- a/src/shader_recompiler/object_pool.h
+++ b/src/shader_recompiler/object_pool.h
@@ -10,19 +10,11 @@
10 10
11namespace Shader { 11namespace Shader {
12 12
13template <typename T, size_t chunk_size = 8192> 13template <typename T>
14requires std::is_destructible_v<T> class ObjectPool { 14requires std::is_destructible_v<T> class ObjectPool {
15public: 15public:
16 ~ObjectPool() { 16 explicit ObjectPool(size_t chunk_size = 8192) : new_chunk_size{chunk_size} {
17 std::unique_ptr<Chunk> tree_owner; 17 node = &chunks.emplace_back(new_chunk_size);
18 Chunk* chunk{&root};
19 while (chunk) {
20 for (size_t obj_id = chunk->free_objects; obj_id < chunk_size; ++obj_id) {
21 chunk->storage[obj_id].object.~T();
22 }
23 tree_owner = std::move(chunk->next);
24 chunk = tree_owner.get();
25 }
26 } 18 }
27 19
28 template <typename... Args> 20 template <typename... Args>
@@ -31,17 +23,21 @@ public:
31 } 23 }
32 24
33 void ReleaseContents() { 25 void ReleaseContents() {
34 Chunk* chunk{&root}; 26 if (chunks.empty()) {
35 while (chunk) { 27 return;
36 if (chunk->free_objects == chunk_size) { 28 }
37 break; 29 Chunk& root{chunks.front()};
38 } 30 if (root.used_objects == root.num_objects) {
39 for (; chunk->free_objects < chunk_size; ++chunk->free_objects) { 31 // Root chunk has been filled, squash allocations into it
40 chunk->storage[chunk->free_objects].object.~T(); 32 const size_t total_objects{root.num_objects + new_chunk_size * (chunks.size() - 1)};
41 } 33 chunks.clear();
42 chunk = chunk->next.get(); 34 chunks.emplace_back(total_objects);
35 chunks.shrink_to_fit();
36 } else {
37 root.Release();
38 chunks.resize(1);
39 chunks.shrink_to_fit();
43 } 40 }
44 node = &root;
45 } 41 }
46 42
47private: 43private:
@@ -58,31 +54,51 @@ private:
58 }; 54 };
59 55
60 struct Chunk { 56 struct Chunk {
61 size_t free_objects = chunk_size; 57 explicit Chunk() = default;
62 std::array<Storage, chunk_size> storage; 58 explicit Chunk(size_t size)
63 std::unique_ptr<Chunk> next; 59 : num_objects{size}, storage{std::make_unique<Storage[]>(size)} {}
60
61 Chunk& operator=(Chunk&& rhs) noexcept {
62 Release();
63 used_objects = std::exchange(rhs.used_objects, 0);
64 num_objects = std::exchange(rhs.num_objects, 0);
65 storage = std::move(rhs.storage);
66 }
67
68 Chunk(Chunk&& rhs) noexcept
69 : used_objects{std::exchange(rhs.used_objects, 0)},
70 num_objects{std::exchange(rhs.num_objects, 0)}, storage{std::move(rhs.storage)} {}
71
72 ~Chunk() {
73 Release();
74 }
75
76 void Release() {
77 std::destroy_n(storage.get(), used_objects);
78 used_objects = 0;
79 }
80
81 size_t used_objects{};
82 size_t num_objects{};
83 std::unique_ptr<Storage[]> storage;
64 }; 84 };
65 85
66 [[nodiscard]] T* Memory() { 86 [[nodiscard]] T* Memory() {
67 Chunk* const chunk{FreeChunk()}; 87 Chunk* const chunk{FreeChunk()};
68 return &chunk->storage[--chunk->free_objects].object; 88 return &chunk->storage[chunk->used_objects++].object;
69 } 89 }
70 90
71 [[nodiscard]] Chunk* FreeChunk() { 91 [[nodiscard]] Chunk* FreeChunk() {
72 if (node->free_objects > 0) { 92 if (node->used_objects != node->num_objects) {
73 return node;
74 }
75 if (node->next) {
76 node = node->next.get();
77 return node; 93 return node;
78 } 94 }
79 node->next = std::make_unique<Chunk>(); 95 node = &chunks.emplace_back(new_chunk_size);
80 node = node->next.get();
81 return node; 96 return node;
82 } 97 }
83 98
84 Chunk* node{&root}; 99 Chunk* node{};
85 Chunk root; 100 std::vector<Chunk> chunks;
101 size_t new_chunk_size{};
86}; 102};
87 103
88} // namespace Shader 104} // namespace Shader