summaryrefslogtreecommitdiff
path: root/src/shader_recompiler
diff options
context:
space:
mode:
Diffstat (limited to 'src/shader_recompiler')
-rw-r--r--src/shader_recompiler/frontend/ir/structured_control_flow.cpp10
-rw-r--r--src/shader_recompiler/main.cpp22
-rw-r--r--src/shader_recompiler/object_pool.h84
3 files changed, 66 insertions, 50 deletions
diff --git a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp
index 2e9ce2525..d145095d1 100644
--- a/src/shader_recompiler/frontend/ir/structured_control_flow.cpp
+++ b/src/shader_recompiler/frontend/ir/structured_control_flow.cpp
@@ -269,7 +269,7 @@ bool SearchNode(const Tree& tree, ConstNode stmt, size_t& offset) {
269 269
270class GotoPass { 270class GotoPass {
271public: 271public:
272 explicit GotoPass(std::span<Block* const> blocks, ObjectPool<Statement, 64>& stmt_pool) 272 explicit GotoPass(std::span<Block* const> blocks, ObjectPool<Statement>& stmt_pool)
273 : pool{stmt_pool} { 273 : pool{stmt_pool} {
274 std::vector gotos{BuildUnorderedTreeGetGotos(blocks)}; 274 std::vector gotos{BuildUnorderedTreeGetGotos(blocks)};
275 fmt::print(stdout, "BEFORE\n{}\n", DumpTree(root_stmt.children)); 275 fmt::print(stdout, "BEFORE\n{}\n", DumpTree(root_stmt.children));
@@ -554,7 +554,7 @@ private:
554 return offset; 554 return offset;
555 } 555 }
556 556
557 ObjectPool<Statement, 64>& pool; 557 ObjectPool<Statement>& pool;
558 Statement root_stmt{FunctionTag{}}; 558 Statement root_stmt{FunctionTag{}};
559}; 559};
560 560
@@ -589,7 +589,7 @@ Block* TryFindForwardBlock(const Statement& stmt) {
589class TranslatePass { 589class TranslatePass {
590public: 590public:
591 TranslatePass(ObjectPool<Inst>& inst_pool_, ObjectPool<Block>& block_pool_, 591 TranslatePass(ObjectPool<Inst>& inst_pool_, ObjectPool<Block>& block_pool_,
592 ObjectPool<Statement, 64>& stmt_pool_, Statement& root_stmt, 592 ObjectPool<Statement>& stmt_pool_, Statement& root_stmt,
593 const std::function<void(IR::Block*)>& func_, BlockList& block_list_) 593 const std::function<void(IR::Block*)>& func_, BlockList& block_list_)
594 : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, func{func_}, 594 : stmt_pool{stmt_pool_}, inst_pool{inst_pool_}, block_pool{block_pool_}, func{func_},
595 block_list{block_list_} { 595 block_list{block_list_} {
@@ -720,7 +720,7 @@ private:
720 return block; 720 return block;
721 } 721 }
722 722
723 ObjectPool<Statement, 64>& stmt_pool; 723 ObjectPool<Statement>& stmt_pool;
724 ObjectPool<Inst>& inst_pool; 724 ObjectPool<Inst>& inst_pool;
725 ObjectPool<Block>& block_pool; 725 ObjectPool<Block>& block_pool;
726 const std::function<void(IR::Block*)>& func; 726 const std::function<void(IR::Block*)>& func;
@@ -731,7 +731,7 @@ private:
731BlockList VisitAST(ObjectPool<Inst>& inst_pool, ObjectPool<Block>& block_pool, 731BlockList VisitAST(ObjectPool<Inst>& inst_pool, ObjectPool<Block>& block_pool,
732 std::span<Block* const> unordered_blocks, 732 std::span<Block* const> unordered_blocks,
733 const std::function<void(Block*)>& func) { 733 const std::function<void(Block*)>& func) {
734 ObjectPool<Statement, 64> stmt_pool; 734 ObjectPool<Statement> stmt_pool{64};
735 GotoPass goto_pass{unordered_blocks, stmt_pool}; 735 GotoPass goto_pass{unordered_blocks, stmt_pool};
736 BlockList block_list; 736 BlockList block_list;
737 TranslatePass translate_pass{inst_pool, block_pool, stmt_pool, goto_pass.RootStatement(), 737 TranslatePass translate_pass{inst_pool, block_pool, stmt_pool, goto_pass.RootStatement(),
diff --git a/src/shader_recompiler/main.cpp b/src/shader_recompiler/main.cpp
index 3b110af61..216345e91 100644
--- a/src/shader_recompiler/main.cpp
+++ b/src/shader_recompiler/main.cpp
@@ -37,7 +37,7 @@ void RunDatabase() {
37 ForEachFile("D:\\Shaders\\Database", [&](const std::filesystem::path& path) { 37 ForEachFile("D:\\Shaders\\Database", [&](const std::filesystem::path& path) {
38 map.emplace_back(std::make_unique<FileEnvironment>(path.string().c_str())); 38 map.emplace_back(std::make_unique<FileEnvironment>(path.string().c_str()));
39 }); 39 });
40 auto block_pool{std::make_unique<ObjectPool<Flow::Block>>()}; 40 ObjectPool<Flow::Block> block_pool;
41 using namespace std::chrono; 41 using namespace std::chrono;
42 auto t0 = high_resolution_clock::now(); 42 auto t0 = high_resolution_clock::now();
43 int N = 1; 43 int N = 1;
@@ -48,8 +48,8 @@ void RunDatabase() {
48 // fmt::print(stdout, "Decoding {}\n", path.string()); 48 // fmt::print(stdout, "Decoding {}\n", path.string());
49 49
50 const Location start_address{0}; 50 const Location start_address{0};
51 block_pool->ReleaseContents(); 51 block_pool.ReleaseContents();
52 Flow::CFG cfg{*env, *block_pool, start_address}; 52 Flow::CFG cfg{*env, block_pool, start_address};
53 // fmt::print(stdout, "{}\n", cfg->Dot()); 53 // fmt::print(stdout, "{}\n", cfg->Dot());
54 // IR::Program program{env, cfg}; 54 // IR::Program program{env, cfg};
55 // Optimize(program); 55 // Optimize(program);
@@ -63,18 +63,18 @@ void RunDatabase() {
63int main() { 63int main() {
64 // RunDatabase(); 64 // RunDatabase();
65 65
66 auto flow_block_pool{std::make_unique<ObjectPool<Flow::Block>>()}; 66 ObjectPool<Flow::Block> flow_block_pool;
67 auto inst_pool{std::make_unique<ObjectPool<IR::Inst>>()}; 67 ObjectPool<IR::Inst> inst_pool;
68 auto block_pool{std::make_unique<ObjectPool<IR::Block>>()}; 68 ObjectPool<IR::Block> block_pool;
69 69
70 // FileEnvironment env{"D:\\Shaders\\Database\\Oninaki\\CS8F146B41DB6BD826.bin"}; 70 // FileEnvironment env{"D:\\Shaders\\Database\\Oninaki\\CS8F146B41DB6BD826.bin"};
71 FileEnvironment env{"D:\\Shaders\\shader.bin"}; 71 FileEnvironment env{"D:\\Shaders\\shader.bin"};
72 block_pool->ReleaseContents(); 72 block_pool.ReleaseContents();
73 inst_pool->ReleaseContents(); 73 inst_pool.ReleaseContents();
74 flow_block_pool->ReleaseContents(); 74 flow_block_pool.ReleaseContents();
75 Flow::CFG cfg{env, *flow_block_pool, 0}; 75 Flow::CFG cfg{env, flow_block_pool, 0};
76 fmt::print(stdout, "{}\n", cfg.Dot()); 76 fmt::print(stdout, "{}\n", cfg.Dot());
77 IR::Program program{TranslateProgram(*inst_pool, *block_pool, env, cfg)}; 77 IR::Program program{TranslateProgram(inst_pool, block_pool, env, cfg)};
78 fmt::print(stdout, "{}\n", IR::DumpProgram(program)); 78 fmt::print(stdout, "{}\n", IR::DumpProgram(program));
79 Backend::SPIRV::EmitSPIRV spirv{program}; 79 Backend::SPIRV::EmitSPIRV spirv{program};
80} 80}
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