shader: Add pools and rename files
This commit is contained in:
		| @@ -1,4 +1,5 @@ | |||||||
| add_executable(shader_recompiler | add_executable(shader_recompiler | ||||||
|  |     backend/spirv/emit_spirv.h | ||||||
|     environment.h |     environment.h | ||||||
|     exception.h |     exception.h | ||||||
|     file_environment.cpp |     file_environment.cpp | ||||||
| @@ -17,10 +18,12 @@ add_executable(shader_recompiler | |||||||
|     frontend/ir/ir_emitter.h |     frontend/ir/ir_emitter.h | ||||||
|     frontend/ir/microinstruction.cpp |     frontend/ir/microinstruction.cpp | ||||||
|     frontend/ir/microinstruction.h |     frontend/ir/microinstruction.h | ||||||
|     frontend/ir/opcode.cpp |     frontend/ir/opcodes.cpp | ||||||
|     frontend/ir/opcode.h |     frontend/ir/opcodes.h | ||||||
|     frontend/ir/opcode.inc |     frontend/ir/opcodes.inc | ||||||
|     frontend/ir/pred.h |     frontend/ir/pred.h | ||||||
|  |     frontend/ir/program.cpp | ||||||
|  |     frontend/ir/program.h | ||||||
|     frontend/ir/reg.h |     frontend/ir/reg.h | ||||||
|     frontend/ir/type.cpp |     frontend/ir/type.cpp | ||||||
|     frontend/ir/type.h |     frontend/ir/type.h | ||||||
| @@ -33,8 +36,8 @@ add_executable(shader_recompiler | |||||||
|     frontend/maxwell/instruction.h |     frontend/maxwell/instruction.h | ||||||
|     frontend/maxwell/location.h |     frontend/maxwell/location.h | ||||||
|     frontend/maxwell/maxwell.inc |     frontend/maxwell/maxwell.inc | ||||||
|     frontend/maxwell/opcode.cpp |     frontend/maxwell/opcodes.cpp | ||||||
|     frontend/maxwell/opcode.h |     frontend/maxwell/opcodes.h | ||||||
|     frontend/maxwell/program.cpp |     frontend/maxwell/program.cpp | ||||||
|     frontend/maxwell/program.h |     frontend/maxwell/program.h | ||||||
|     frontend/maxwell/termination_code.cpp |     frontend/maxwell/termination_code.cpp | ||||||
| @@ -67,6 +70,7 @@ add_executable(shader_recompiler | |||||||
|     ir_opt/ssa_rewrite_pass.cpp |     ir_opt/ssa_rewrite_pass.cpp | ||||||
|     ir_opt/verification_pass.cpp |     ir_opt/verification_pass.cpp | ||||||
|     main.cpp |     main.cpp | ||||||
|  |     object_pool.h | ||||||
| ) | ) | ||||||
| target_link_libraries(shader_recompiler PRIVATE fmt::fmt) | target_link_libraries(shader_recompiler PRIVATE fmt::fmt) | ||||||
|  |  | ||||||
|   | |||||||
							
								
								
									
										21
									
								
								src/shader_recompiler/backend/spirv/emit_spirv.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/shader_recompiler/backend/spirv/emit_spirv.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
|  | #include "shader_recompiler/frontend/ir/program.h" | ||||||
|  |  | ||||||
|  | namespace Shader::Backend::SPIRV { | ||||||
|  |  | ||||||
|  | class EmitSPIRV { | ||||||
|  | public: | ||||||
|  | private: | ||||||
|  |     // Microinstruction emitters | ||||||
|  | #define OPCODE(name, result_type, ...) void Emit##name(EmitContext& ctx, IR::Inst* inst); | ||||||
|  | #include "shader_recompiler/frontend/ir/opcodes.inc" | ||||||
|  | #undef OPCODE | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace Shader::Backend::SPIRV | ||||||
| @@ -14,7 +14,8 @@ | |||||||
|  |  | ||||||
| namespace Shader::IR { | namespace Shader::IR { | ||||||
|  |  | ||||||
| Block::Block(u32 begin, u32 end) : location_begin{begin}, location_end{end} {} | Block::Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end) | ||||||
|  |     : inst_pool{&inst_pool_}, location_begin{begin}, location_end{end} {} | ||||||
|  |  | ||||||
| Block::~Block() = default; | Block::~Block() = default; | ||||||
|  |  | ||||||
| @@ -24,7 +25,7 @@ void Block::AppendNewInst(Opcode op, std::initializer_list<Value> args) { | |||||||
|  |  | ||||||
| Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op, | Block::iterator Block::PrependNewInst(iterator insertion_point, Opcode op, | ||||||
|                                       std::initializer_list<Value> args, u64 flags) { |                                       std::initializer_list<Value> args, u64 flags) { | ||||||
|     Inst* const inst{std::construct_at(instruction_alloc_pool.allocate(), op, flags)}; |     Inst* const inst{inst_pool->Create(op, flags)}; | ||||||
|     const auto result_it{instructions.insert(insertion_point, *inst)}; |     const auto result_it{instructions.insert(insertion_point, *inst)}; | ||||||
|  |  | ||||||
|     if (inst->NumArgs() != args.size()) { |     if (inst->NumArgs() != args.size()) { | ||||||
|   | |||||||
| @@ -10,9 +10,9 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| #include <boost/intrusive/list.hpp> | #include <boost/intrusive/list.hpp> | ||||||
| #include <boost/pool/pool_alloc.hpp> |  | ||||||
|  |  | ||||||
| #include "shader_recompiler/frontend/ir/microinstruction.h" | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
|  | #include "shader_recompiler/object_pool.h" | ||||||
|  |  | ||||||
| namespace Shader::IR { | namespace Shader::IR { | ||||||
|  |  | ||||||
| @@ -25,7 +25,7 @@ public: | |||||||
|     using reverse_iterator = InstructionList::reverse_iterator; |     using reverse_iterator = InstructionList::reverse_iterator; | ||||||
|     using const_reverse_iterator = InstructionList::const_reverse_iterator; |     using const_reverse_iterator = InstructionList::const_reverse_iterator; | ||||||
|  |  | ||||||
|     explicit Block(u32 begin, u32 end); |     explicit Block(ObjectPool<Inst>& inst_pool_, u32 begin, u32 end); | ||||||
|     ~Block(); |     ~Block(); | ||||||
|  |  | ||||||
|     Block(const Block&) = delete; |     Block(const Block&) = delete; | ||||||
| @@ -119,6 +119,8 @@ public: | |||||||
|     } |     } | ||||||
|  |  | ||||||
| private: | private: | ||||||
|  |     /// Memory pool for instruction list | ||||||
|  |     ObjectPool<Inst>* inst_pool; | ||||||
|     /// Starting location of this block |     /// Starting location of this block | ||||||
|     u32 location_begin; |     u32 location_begin; | ||||||
|     /// End location of this block |     /// End location of this block | ||||||
| @@ -127,11 +129,6 @@ private: | |||||||
|     /// List of instructions in this block |     /// List of instructions in this block | ||||||
|     InstructionList instructions; |     InstructionList instructions; | ||||||
|  |  | ||||||
|     /// Memory pool for instruction list |  | ||||||
|     boost::fast_pool_allocator<Inst, boost::default_user_allocator_malloc_free, |  | ||||||
|                                boost::details::pool::null_mutex> |  | ||||||
|         instruction_alloc_pool; |  | ||||||
|  |  | ||||||
|     /// Block immediate predecessors |     /// Block immediate predecessors | ||||||
|     std::vector<IR::Block*> imm_predecessors; |     std::vector<IR::Block*> imm_predecessors; | ||||||
| }; | }; | ||||||
|   | |||||||
| @@ -4,22 +4,14 @@ | |||||||
|  |  | ||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include <memory> | #include <boost/container/small_vector.hpp> | ||||||
| #include <vector> |  | ||||||
|  |  | ||||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | #include "shader_recompiler/frontend/ir/basic_block.h" | ||||||
|  |  | ||||||
| namespace Shader::IR { | namespace Shader::IR { | ||||||
|  |  | ||||||
| struct Function { | struct Function { | ||||||
|     struct InplaceDelete { |     boost::container::small_vector<Block*, 16> blocks; | ||||||
|         void operator()(IR::Block* block) const noexcept { |  | ||||||
|             std::destroy_at(block); |  | ||||||
|         } |  | ||||||
|     }; |  | ||||||
|     using UniqueBlock = std::unique_ptr<IR::Block, InplaceDelete>; |  | ||||||
|  |  | ||||||
|     std::vector<UniqueBlock> blocks; |  | ||||||
| }; | }; | ||||||
|  |  | ||||||
| } // namespace Shader::IR | } // namespace Shader::IR | ||||||
|   | |||||||
| @@ -13,7 +13,7 @@ | |||||||
| #include <boost/intrusive/list.hpp> | #include <boost/intrusive/list.hpp> | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/frontend/ir/opcode.h" | #include "shader_recompiler/frontend/ir/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/ir/type.h" | #include "shader_recompiler/frontend/ir/type.h" | ||||||
| #include "shader_recompiler/frontend/ir/value.h" | #include "shader_recompiler/frontend/ir/value.h" | ||||||
|  |  | ||||||
|   | |||||||
| @@ -7,7 +7,7 @@ | |||||||
| #include <string_view> | #include <string_view> | ||||||
| 
 | 
 | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/ir/opcode.h" | #include "shader_recompiler/frontend/ir/opcodes.h" | ||||||
| 
 | 
 | ||||||
| namespace Shader::IR { | namespace Shader::IR { | ||||||
| namespace { | namespace { | ||||||
| @@ -26,7 +26,7 @@ constexpr std::array META_TABLE{ | |||||||
|         .type{type_token},                                                                         \ |         .type{type_token},                                                                         \ | ||||||
|         .arg_types{__VA_ARGS__},                                                                   \ |         .arg_types{__VA_ARGS__},                                                                   \ | ||||||
|     }, |     }, | ||||||
| #include "opcode.inc" | #include "opcodes.inc" | ||||||
| #undef OPCODE | #undef OPCODE | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
| @@ -14,7 +14,7 @@ namespace Shader::IR { | |||||||
| 
 | 
 | ||||||
| enum class Opcode { | enum class Opcode { | ||||||
| #define OPCODE(name, ...) name, | #define OPCODE(name, ...) name, | ||||||
| #include "opcode.inc" | #include "opcodes.inc" | ||||||
| #undef OPCODE | #undef OPCODE | ||||||
| }; | }; | ||||||
| 
 | 
 | ||||||
							
								
								
									
										38
									
								
								src/shader_recompiler/frontend/ir/program.cpp
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										38
									
								
								src/shader_recompiler/frontend/ir/program.cpp
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,38 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <map> | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | #include <fmt/format.h> | ||||||
|  |  | ||||||
|  | #include "shader_recompiler/frontend/ir/function.h" | ||||||
|  | #include "shader_recompiler/frontend/ir/program.h" | ||||||
|  |  | ||||||
|  | namespace Shader::IR { | ||||||
|  |  | ||||||
|  | std::string DumpProgram(const Program& program) { | ||||||
|  |     size_t index{0}; | ||||||
|  |     std::map<const IR::Inst*, size_t> inst_to_index; | ||||||
|  |     std::map<const IR::Block*, size_t> block_to_index; | ||||||
|  |  | ||||||
|  |     for (const IR::Function& function : program.functions) { | ||||||
|  |         for (const IR::Block* const block : function.blocks) { | ||||||
|  |             block_to_index.emplace(block, index); | ||||||
|  |             ++index; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     std::string ret; | ||||||
|  |     for (const IR::Function& function : program.functions) { | ||||||
|  |         ret += fmt::format("Function\n"); | ||||||
|  |         for (const auto& block : function.blocks) { | ||||||
|  |             ret += IR::DumpBlock(*block, block_to_index, inst_to_index, index) + '\n'; | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |     return ret; | ||||||
|  | } | ||||||
|  |  | ||||||
|  | } // namespace Shader::IR | ||||||
							
								
								
									
										21
									
								
								src/shader_recompiler/frontend/ir/program.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										21
									
								
								src/shader_recompiler/frontend/ir/program.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,21 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <string> | ||||||
|  |  | ||||||
|  | #include <boost/container/small_vector.hpp> | ||||||
|  |  | ||||||
|  | #include "shader_recompiler/frontend/ir/function.h" | ||||||
|  |  | ||||||
|  | namespace Shader::IR { | ||||||
|  |  | ||||||
|  | struct Program { | ||||||
|  |     boost::container::small_vector<Function, 1> functions; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | [[nodiscard]] std::string DumpProgram(const Program& program); | ||||||
|  |  | ||||||
|  | } // namespace Shader::IR | ||||||
| @@ -3,7 +3,7 @@ | |||||||
| // Refer to the license.txt file included. | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
| #include "shader_recompiler/frontend/ir/microinstruction.h" | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
| #include "shader_recompiler/frontend/ir/opcode.h" | #include "shader_recompiler/frontend/ir/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/ir/value.h" | #include "shader_recompiler/frontend/ir/value.h" | ||||||
|  |  | ||||||
| namespace Shader::IR { | namespace Shader::IR { | ||||||
|   | |||||||
| @@ -16,7 +16,7 @@ | |||||||
| #include "shader_recompiler/frontend/ir/condition.h" | #include "shader_recompiler/frontend/ir/condition.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/instruction.h" | #include "shader_recompiler/frontend/maxwell/instruction.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/location.h" | #include "shader_recompiler/frontend/maxwell/location.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell::Flow { | namespace Shader::Maxwell::Flow { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -11,7 +11,7 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/decode.h" | #include "shader_recompiler/frontend/maxwell/decode.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
| namespace { | namespace { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #pragma once | #pragma once | ||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|  |  | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #include <array> | #include <array> | ||||||
| 
 | 
 | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| 
 | 
 | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
| namespace { | namespace { | ||||||
| @@ -5,6 +5,7 @@ | |||||||
| #include <algorithm> | #include <algorithm> | ||||||
| #include <memory> | #include <memory> | ||||||
|  |  | ||||||
|  | #include "shader_recompiler/frontend/ir/basic_block.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/program.h" | #include "shader_recompiler/frontend/maxwell/program.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/termination_code.h" | #include "shader_recompiler/frontend/maxwell/termination_code.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/translate.h" | #include "shader_recompiler/frontend/maxwell/translate/translate.h" | ||||||
| @@ -12,17 +13,18 @@ | |||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
| namespace { | namespace { | ||||||
| void TranslateCode(Environment& env, const Flow::Function& cfg_function, IR::Function& function, | void TranslateCode(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, | ||||||
|                    std::span<IR::Block*> block_map, IR::Block* block_memory) { |                    Environment& env, const Flow::Function& cfg_function, IR::Function& function, | ||||||
|  |                    std::span<IR::Block*> block_map) { | ||||||
|     const size_t num_blocks{cfg_function.blocks.size()}; |     const size_t num_blocks{cfg_function.blocks.size()}; | ||||||
|     function.blocks.reserve(num_blocks); |     function.blocks.reserve(num_blocks); | ||||||
|  |  | ||||||
|     for (const Flow::BlockId block_id : cfg_function.blocks) { |     for (const Flow::BlockId block_id : cfg_function.blocks) { | ||||||
|         const Flow::Block& flow_block{cfg_function.blocks_data[block_id]}; |         const Flow::Block& flow_block{cfg_function.blocks_data[block_id]}; | ||||||
|  |  | ||||||
|         function.blocks.emplace_back(std::construct_at(block_memory, Translate(env, flow_block))); |         IR::Block* const ir_block{block_pool.Create(Translate(inst_pool, env, flow_block))}; | ||||||
|         block_map[flow_block.id] = function.blocks.back().get(); |         block_map[flow_block.id] = ir_block; | ||||||
|         ++block_memory; |         function.blocks.emplace_back(ir_block); | ||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| @@ -34,21 +36,24 @@ void EmitTerminationInsts(const Flow::Function& cfg_function, | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| void TranslateFunction(Environment& env, const Flow::Function& cfg_function, IR::Function& function, | void TranslateFunction(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, | ||||||
|                        IR::Block* block_memory) { |                        Environment& env, const Flow::Function& cfg_function, | ||||||
|  |                        IR::Function& function) { | ||||||
|     std::vector<IR::Block*> block_map; |     std::vector<IR::Block*> block_map; | ||||||
|     block_map.resize(cfg_function.blocks_data.size()); |     block_map.resize(cfg_function.blocks_data.size()); | ||||||
|  |  | ||||||
|     TranslateCode(env, cfg_function, function, block_map, block_memory); |     TranslateCode(inst_pool, block_pool, env, cfg_function, function, block_map); | ||||||
|     EmitTerminationInsts(cfg_function, block_map); |     EmitTerminationInsts(cfg_function, block_map); | ||||||
| } | } | ||||||
| } // Anonymous namespace | } // Anonymous namespace | ||||||
|  |  | ||||||
| Program::Program(Environment& env, const Flow::CFG& cfg) { | IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, ObjectPool<IR::Block>& block_pool, | ||||||
|  |                              Environment& env, const Flow::CFG& cfg) { | ||||||
|  |     IR::Program program; | ||||||
|  |     auto& functions{program.functions}; | ||||||
|     functions.reserve(cfg.Functions().size()); |     functions.reserve(cfg.Functions().size()); | ||||||
|     for (const Flow::Function& cfg_function : cfg.Functions()) { |     for (const Flow::Function& cfg_function : cfg.Functions()) { | ||||||
|         TranslateFunction(env, cfg_function, functions.emplace_back(), |         TranslateFunction(inst_pool, block_pool, env, cfg_function, functions.emplace_back()); | ||||||
|                           block_alloc_pool.allocate(cfg_function.blocks.size())); |  | ||||||
|     } |     } | ||||||
|     std::ranges::for_each(functions, Optimization::SsaRewritePass); |     std::ranges::for_each(functions, Optimization::SsaRewritePass); | ||||||
|     for (IR::Function& function : functions) { |     for (IR::Function& function : functions) { | ||||||
| @@ -59,27 +64,7 @@ Program::Program(Environment& env, const Flow::CFG& cfg) { | |||||||
|         Optimization::VerificationPass(function); |         Optimization::VerificationPass(function); | ||||||
|     } |     } | ||||||
|     //*/ |     //*/ | ||||||
| } |     return program; | ||||||
|  |  | ||||||
| std::string DumpProgram(const Program& program) { |  | ||||||
|     size_t index{0}; |  | ||||||
|     std::map<const IR::Inst*, size_t> inst_to_index; |  | ||||||
|     std::map<const IR::Block*, size_t> block_to_index; |  | ||||||
|  |  | ||||||
|     for (const IR::Function& function : program.functions) { |  | ||||||
|         for (const auto& block : function.blocks) { |  | ||||||
|             block_to_index.emplace(block.get(), index); |  | ||||||
|             ++index; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     std::string ret; |  | ||||||
|     for (const IR::Function& function : program.functions) { |  | ||||||
|         ret += fmt::format("Function\n"); |  | ||||||
|         for (const auto& block : function.blocks) { |  | ||||||
|             ret += IR::DumpBlock(*block, block_to_index, inst_to_index, index) + '\n'; |  | ||||||
|         } |  | ||||||
|     } |  | ||||||
|     return ret; |  | ||||||
| } | } | ||||||
|  |  | ||||||
| } // namespace Shader::Maxwell | } // namespace Shader::Maxwell | ||||||
|   | |||||||
| @@ -9,28 +9,16 @@ | |||||||
| #include <vector> | #include <vector> | ||||||
|  |  | ||||||
| #include <boost/container/small_vector.hpp> | #include <boost/container/small_vector.hpp> | ||||||
| #include <boost/pool/pool_alloc.hpp> |  | ||||||
|  |  | ||||||
| #include "shader_recompiler/environment.h" | #include "shader_recompiler/environment.h" | ||||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | #include "shader_recompiler/frontend/ir/program.h" | ||||||
| #include "shader_recompiler/frontend/ir/function.h" |  | ||||||
| #include "shader_recompiler/frontend/maxwell/control_flow.h" | #include "shader_recompiler/frontend/maxwell/control_flow.h" | ||||||
|  | #include "shader_recompiler/object_pool.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|  |  | ||||||
| class Program { | [[nodiscard]] IR::Program TranslateProgram(ObjectPool<IR::Inst>& inst_pool, | ||||||
|     friend std::string DumpProgram(const Program& program); |                                            ObjectPool<IR::Block>& block_pool, Environment& env, | ||||||
|  |                                            const Flow::CFG& cfg); | ||||||
| public: |  | ||||||
|     explicit Program(Environment& env, const Flow::CFG& cfg); |  | ||||||
|  |  | ||||||
| private: |  | ||||||
|     boost::pool_allocator<IR::Block, boost::default_user_allocator_new_delete, |  | ||||||
|                           boost::details::pool::null_mutex> |  | ||||||
|         block_alloc_pool; |  | ||||||
|     boost::container::small_vector<IR::Function, 1> functions; |  | ||||||
| }; |  | ||||||
|  |  | ||||||
| [[nodiscard]] std::string DumpProgram(const Program& program); |  | ||||||
|  |  | ||||||
| } // namespace Shader::Maxwell | } // namespace Shader::Maxwell | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -6,7 +6,7 @@ | |||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/ir/ir_emitter.h" | #include "shader_recompiler/frontend/ir/ir_emitter.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -5,7 +5,7 @@ | |||||||
| #include "common/bit_field.h" | #include "common/bit_field.h" | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -4,7 +4,7 @@ | |||||||
|  |  | ||||||
| #include "common/common_types.h" | #include "common/common_types.h" | ||||||
| #include "shader_recompiler/exception.h" | #include "shader_recompiler/exception.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/opcode.h" | #include "shader_recompiler/frontend/maxwell/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | #include "shader_recompiler/frontend/maxwell/translate/impl/impl.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|   | |||||||
| @@ -23,8 +23,9 @@ static void Invoke(TranslatorVisitor& visitor, Location pc, u64 insn) { | |||||||
|     } |     } | ||||||
| } | } | ||||||
|  |  | ||||||
| IR::Block Translate(Environment& env, const Flow::Block& flow_block) { | IR::Block Translate(ObjectPool<IR::Inst>& inst_pool, Environment& env, | ||||||
|     IR::Block block{flow_block.begin.Offset(), flow_block.end.Offset()}; |                     const Flow::Block& flow_block) { | ||||||
|  |     IR::Block block{inst_pool, flow_block.begin.Offset(), flow_block.end.Offset()}; | ||||||
|     TranslatorVisitor visitor{env, block}; |     TranslatorVisitor visitor{env, block}; | ||||||
|  |  | ||||||
|     const Location pc_end{flow_block.end}; |     const Location pc_end{flow_block.end}; | ||||||
|   | |||||||
| @@ -6,11 +6,14 @@ | |||||||
|  |  | ||||||
| #include "shader_recompiler/environment.h" | #include "shader_recompiler/environment.h" | ||||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | #include "shader_recompiler/frontend/ir/basic_block.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/location.h" | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
| #include "shader_recompiler/frontend/maxwell/control_flow.h" | #include "shader_recompiler/frontend/maxwell/control_flow.h" | ||||||
|  | #include "shader_recompiler/frontend/maxwell/location.h" | ||||||
|  | #include "shader_recompiler/object_pool.h" | ||||||
|  |  | ||||||
| namespace Shader::Maxwell { | namespace Shader::Maxwell { | ||||||
|  |  | ||||||
| [[nodiscard]] IR::Block Translate(Environment& env, const Flow::Block& flow_block); | [[nodiscard]] IR::Block Translate(ObjectPool<IR::Inst>& inst_pool, Environment& env, | ||||||
|  |                                   const Flow::Block& flow_block); | ||||||
|  |  | ||||||
| } // namespace Shader::Maxwell | } // namespace Shader::Maxwell | ||||||
|   | |||||||
| @@ -19,7 +19,7 @@ | |||||||
| #include "shader_recompiler/frontend/ir/basic_block.h" | #include "shader_recompiler/frontend/ir/basic_block.h" | ||||||
| #include "shader_recompiler/frontend/ir/function.h" | #include "shader_recompiler/frontend/ir/function.h" | ||||||
| #include "shader_recompiler/frontend/ir/microinstruction.h" | #include "shader_recompiler/frontend/ir/microinstruction.h" | ||||||
| #include "shader_recompiler/frontend/ir/opcode.h" | #include "shader_recompiler/frontend/ir/opcodes.h" | ||||||
| #include "shader_recompiler/frontend/ir/pred.h" | #include "shader_recompiler/frontend/ir/pred.h" | ||||||
| #include "shader_recompiler/frontend/ir/reg.h" | #include "shader_recompiler/frontend/ir/reg.h" | ||||||
| #include "shader_recompiler/ir_opt/passes.h" | #include "shader_recompiler/ir_opt/passes.h" | ||||||
| @@ -150,52 +150,52 @@ private: | |||||||
|  |  | ||||||
| void SsaRewritePass(IR::Function& function) { | void SsaRewritePass(IR::Function& function) { | ||||||
|     Pass pass; |     Pass pass; | ||||||
|     for (const auto& block : function.blocks) { |     for (IR::Block* const block : function.blocks) { | ||||||
|         for (IR::Inst& inst : block->Instructions()) { |         for (IR::Inst& inst : block->Instructions()) { | ||||||
|             switch (inst.Opcode()) { |             switch (inst.Opcode()) { | ||||||
|             case IR::Opcode::SetRegister: |             case IR::Opcode::SetRegister: | ||||||
|                 if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { |                 if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { | ||||||
|                     pass.WriteVariable(reg, block.get(), inst.Arg(1)); |                     pass.WriteVariable(reg, block, inst.Arg(1)); | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::SetPred: |             case IR::Opcode::SetPred: | ||||||
|                 if (const IR::Pred pred{inst.Arg(0).Pred()}; pred != IR::Pred::PT) { |                 if (const IR::Pred pred{inst.Arg(0).Pred()}; pred != IR::Pred::PT) { | ||||||
|                     pass.WriteVariable(pred, block.get(), inst.Arg(1)); |                     pass.WriteVariable(pred, block, inst.Arg(1)); | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::SetZFlag: |             case IR::Opcode::SetZFlag: | ||||||
|                 pass.WriteVariable(ZeroFlagTag{}, block.get(), inst.Arg(0)); |                 pass.WriteVariable(ZeroFlagTag{}, block, inst.Arg(0)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::SetSFlag: |             case IR::Opcode::SetSFlag: | ||||||
|                 pass.WriteVariable(SignFlagTag{}, block.get(), inst.Arg(0)); |                 pass.WriteVariable(SignFlagTag{}, block, inst.Arg(0)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::SetCFlag: |             case IR::Opcode::SetCFlag: | ||||||
|                 pass.WriteVariable(CarryFlagTag{}, block.get(), inst.Arg(0)); |                 pass.WriteVariable(CarryFlagTag{}, block, inst.Arg(0)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::SetOFlag: |             case IR::Opcode::SetOFlag: | ||||||
|                 pass.WriteVariable(OverflowFlagTag{}, block.get(), inst.Arg(0)); |                 pass.WriteVariable(OverflowFlagTag{}, block, inst.Arg(0)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetRegister: |             case IR::Opcode::GetRegister: | ||||||
|                 if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { |                 if (const IR::Reg reg{inst.Arg(0).Reg()}; reg != IR::Reg::RZ) { | ||||||
|                     inst.ReplaceUsesWith(pass.ReadVariable(reg, block.get())); |                     inst.ReplaceUsesWith(pass.ReadVariable(reg, block)); | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetPred: |             case IR::Opcode::GetPred: | ||||||
|                 if (const IR::Pred pred{inst.Arg(0).Pred()}; pred != IR::Pred::PT) { |                 if (const IR::Pred pred{inst.Arg(0).Pred()}; pred != IR::Pred::PT) { | ||||||
|                     inst.ReplaceUsesWith(pass.ReadVariable(pred, block.get())); |                     inst.ReplaceUsesWith(pass.ReadVariable(pred, block)); | ||||||
|                 } |                 } | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetZFlag: |             case IR::Opcode::GetZFlag: | ||||||
|                 inst.ReplaceUsesWith(pass.ReadVariable(ZeroFlagTag{}, block.get())); |                 inst.ReplaceUsesWith(pass.ReadVariable(ZeroFlagTag{}, block)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetSFlag: |             case IR::Opcode::GetSFlag: | ||||||
|                 inst.ReplaceUsesWith(pass.ReadVariable(SignFlagTag{}, block.get())); |                 inst.ReplaceUsesWith(pass.ReadVariable(SignFlagTag{}, block)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetCFlag: |             case IR::Opcode::GetCFlag: | ||||||
|                 inst.ReplaceUsesWith(pass.ReadVariable(CarryFlagTag{}, block.get())); |                 inst.ReplaceUsesWith(pass.ReadVariable(CarryFlagTag{}, block)); | ||||||
|                 break; |                 break; | ||||||
|             case IR::Opcode::GetOFlag: |             case IR::Opcode::GetOFlag: | ||||||
|                 inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block.get())); |                 inst.ReplaceUsesWith(pass.ReadVariable(OverflowFlagTag{}, block)); | ||||||
|                 break; |                 break; | ||||||
|             default: |             default: | ||||||
|                 break; |                 break; | ||||||
|   | |||||||
| @@ -56,6 +56,13 @@ int main() { | |||||||
|     auto cfg{std::make_unique<Flow::CFG>(env, 0)}; |     auto cfg{std::make_unique<Flow::CFG>(env, 0)}; | ||||||
|     // fmt::print(stdout, "{}\n", cfg->Dot()); |     // fmt::print(stdout, "{}\n", cfg->Dot()); | ||||||
|  |  | ||||||
|     Program program{env, *cfg}; |     auto inst_pool{std::make_unique<ObjectPool<IR::Inst>>()}; | ||||||
|     fmt::print(stdout, "{}\n", DumpProgram(program)); |     auto block_pool{std::make_unique<ObjectPool<IR::Block>>()}; | ||||||
|  |  | ||||||
|  |     for (int i = 0; i < 8192 * 4; ++i) { | ||||||
|  |         void(inst_pool->Create(IR::Opcode::Void, 0)); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     IR::Program program{TranslateProgram(*inst_pool, *block_pool, env, *cfg)}; | ||||||
|  |     fmt::print(stdout, "{}\n", IR::DumpProgram(program)); | ||||||
| } | } | ||||||
|   | |||||||
							
								
								
									
										89
									
								
								src/shader_recompiler/object_pool.h
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										89
									
								
								src/shader_recompiler/object_pool.h
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,89 @@ | |||||||
|  | // Copyright 2021 yuzu Emulator Project | ||||||
|  | // Licensed under GPLv2 or any later version | ||||||
|  | // Refer to the license.txt file included. | ||||||
|  |  | ||||||
|  | #pragma once | ||||||
|  |  | ||||||
|  | #include <memory> | ||||||
|  | #include <type_traits> | ||||||
|  |  | ||||||
|  | namespace Shader { | ||||||
|  |  | ||||||
|  | template <typename T, size_t chunk_size = 8192> | ||||||
|  | requires std::is_destructible_v<T> class ObjectPool { | ||||||
|  | public: | ||||||
|  |     ~ObjectPool() { | ||||||
|  |         std::unique_ptr<Chunk> tree_owner; | ||||||
|  |         Chunk* chunk{&root}; | ||||||
|  |         while (chunk) { | ||||||
|  |             for (size_t obj_id = chunk->free_objects; obj_id < chunk_size; ++obj_id) { | ||||||
|  |                 chunk->storage[obj_id].object.~T(); | ||||||
|  |             } | ||||||
|  |             tree_owner = std::move(chunk->next); | ||||||
|  |             chunk = tree_owner.get(); | ||||||
|  |         } | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     template <typename... Args> | ||||||
|  |     requires std::is_constructible_v<T, Args...> [[nodiscard]] T* Create(Args&&... args) { | ||||||
|  |         return std::construct_at(Memory(), std::forward<Args>(args)...); | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     void ReleaseContents() { | ||||||
|  |         Chunk* chunk{&root}; | ||||||
|  |         if (chunk) { | ||||||
|  |             const size_t free_objects{chunk->free_objects}; | ||||||
|  |             if (free_objects == chunk_size) { | ||||||
|  |                 break; | ||||||
|  |             } | ||||||
|  |             chunk->free_objects = chunk_size; | ||||||
|  |             for (size_t obj_id = free_objects; obj_id < chunk_size; ++obj_id) { | ||||||
|  |                 chunk->storage[obj_id].object.~T(); | ||||||
|  |             } | ||||||
|  |             chunk = chunk->next.get(); | ||||||
|  |         } | ||||||
|  |         node = &root; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  | private: | ||||||
|  |     struct NonTrivialDummy { | ||||||
|  |         NonTrivialDummy() noexcept {} | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     union Storage { | ||||||
|  |         Storage() noexcept {} | ||||||
|  |         ~Storage() noexcept {} | ||||||
|  |  | ||||||
|  |         NonTrivialDummy dummy{}; | ||||||
|  |         T object; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     struct Chunk { | ||||||
|  |         size_t free_objects = chunk_size; | ||||||
|  |         std::array<Storage, chunk_size> storage; | ||||||
|  |         std::unique_ptr<Chunk> next; | ||||||
|  |     }; | ||||||
|  |  | ||||||
|  |     [[nodiscard]] T* Memory() { | ||||||
|  |         Chunk* const chunk{FreeChunk()}; | ||||||
|  |         return &chunk->storage[--chunk->free_objects].object; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     [[nodiscard]] Chunk* FreeChunk() { | ||||||
|  |         if (node->free_objects > 0) { | ||||||
|  |             return node; | ||||||
|  |         } | ||||||
|  |         if (node->next) { | ||||||
|  |             node = node->next.get(); | ||||||
|  |             return node; | ||||||
|  |         } | ||||||
|  |         node->next = std::make_unique<Chunk>(); | ||||||
|  |         node = node->next.get(); | ||||||
|  |         return node; | ||||||
|  |     } | ||||||
|  |  | ||||||
|  |     Chunk* node{&root}; | ||||||
|  |     Chunk root; | ||||||
|  | }; | ||||||
|  |  | ||||||
|  | } // namespace Shader | ||||||
		Reference in New Issue
	
	Block a user