summaryrefslogtreecommitdiff
path: root/src/shader_recompiler/object_pool.h
diff options
context:
space:
mode:
authorGravatar bunnei2021-07-25 11:39:04 -0700
committerGravatar GitHub2021-07-25 11:39:04 -0700
commit98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f (patch)
tree816faa96c2c4d291825063433331a8ea4b3d08f1 /src/shader_recompiler/object_pool.h
parentMerge pull request #6699 from lat9nq/common-threads (diff)
parentshader: Support out of bound local memory reads and immediate writes (diff)
downloadyuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.gz
yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.tar.xz
yuzu-98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f.zip
Merge pull request #6585 from ameerj/hades
Shader Decompiler Rewrite
Diffstat (limited to 'src/shader_recompiler/object_pool.h')
-rw-r--r--src/shader_recompiler/object_pool.h104
1 files changed, 104 insertions, 0 deletions
diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h
new file mode 100644
index 000000000..f8b255b66
--- /dev/null
+++ b/src/shader_recompiler/object_pool.h
@@ -0,0 +1,104 @@
1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <memory>
8#include <type_traits>
9#include <utility>
10
11namespace Shader {
12
13template <typename T>
14requires std::is_destructible_v<T> class ObjectPool {
15public:
16 explicit ObjectPool(size_t chunk_size = 8192) : new_chunk_size{chunk_size} {
17 node = &chunks.emplace_back(new_chunk_size);
18 }
19
20 template <typename... Args>
21 requires std::is_constructible_v<T, Args...>[[nodiscard]] T* Create(Args&&... args) {
22 return std::construct_at(Memory(), std::forward<Args>(args)...);
23 }
24
25 void ReleaseContents() {
26 if (chunks.empty()) {
27 return;
28 }
29 Chunk& root{chunks.front()};
30 if (root.used_objects == root.num_objects) {
31 // Root chunk has been filled, squash allocations into it
32 const size_t total_objects{root.num_objects + new_chunk_size * (chunks.size() - 1)};
33 chunks.clear();
34 chunks.emplace_back(total_objects);
35 } else {
36 root.Release();
37 chunks.resize(1);
38 }
39 chunks.shrink_to_fit();
40 node = &chunks.front();
41 }
42
43private:
44 struct NonTrivialDummy {
45 NonTrivialDummy() noexcept {}
46 };
47
48 union Storage {
49 Storage() noexcept {}
50 ~Storage() noexcept {}
51
52 NonTrivialDummy dummy{};
53 T object;
54 };
55
56 struct Chunk {
57 explicit Chunk() = default;
58 explicit Chunk(size_t size)
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;
84 };
85
86 [[nodiscard]] T* Memory() {
87 Chunk* const chunk{FreeChunk()};
88 return &chunk->storage[chunk->used_objects++].object;
89 }
90
91 [[nodiscard]] Chunk* FreeChunk() {
92 if (node->used_objects != node->num_objects) {
93 return node;
94 }
95 node = &chunks.emplace_back(new_chunk_size);
96 return node;
97 }
98
99 Chunk* node{};
100 std::vector<Chunk> chunks;
101 size_t new_chunk_size{};
102};
103
104} // namespace Shader