diff options
| author | 2021-07-25 11:39:04 -0700 | |
|---|---|---|
| committer | 2021-07-25 11:39:04 -0700 | |
| commit | 98b26b6e126d4775fdf3f773fe8a8ac808a8ff8f (patch) | |
| tree | 816faa96c2c4d291825063433331a8ea4b3d08f1 /src/shader_recompiler/object_pool.h | |
| parent | Merge pull request #6699 from lat9nq/common-threads (diff) | |
| parent | shader: Support out of bound local memory reads and immediate writes (diff) | |
| download | yuzu-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.h | 104 |
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 | |||
| 11 | namespace Shader { | ||
| 12 | |||
| 13 | template <typename T> | ||
| 14 | requires std::is_destructible_v<T> class ObjectPool { | ||
| 15 | public: | ||
| 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 | |||
| 43 | private: | ||
| 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 | ||