citra-emu
/
citra-canary
Archived
1
0
Fork 0

shader_jit_x64: Allocate each program independently and persist for emu session.

This commit is contained in:
bunnei 2016-03-20 00:37:05 -04:00
parent 4632791a40
commit c9d10de644
3 changed files with 28 additions and 38 deletions

View File

@ -28,15 +28,8 @@ namespace Pica {
namespace Shader { namespace Shader {
#ifdef ARCHITECTURE_x86_64 #ifdef ARCHITECTURE_x86_64
static std::unordered_map<u64, CompiledShader*> shader_map; static std::unordered_map<u64, std::unique_ptr<JitCompiler>> shader_map;
static JitCompiler jit; static const JitCompiler* jit_shader;
static CompiledShader* jit_shader;
static void ClearCache() {
shader_map.clear();
jit.Clear();
LOG_INFO(HW_GPU, "Shader JIT cache cleared");
}
#endif // ARCHITECTURE_x86_64 #endif // ARCHITECTURE_x86_64
void Setup(UnitState<false>& state) { void Setup(UnitState<false>& state) {
@ -48,16 +41,12 @@ void Setup(UnitState<false>& state) {
auto iter = shader_map.find(cache_key); auto iter = shader_map.find(cache_key);
if (iter != shader_map.end()) { if (iter != shader_map.end()) {
jit_shader = iter->second; jit_shader = iter->second.get();
} else { } else {
// Check if remaining JIT code space is enough for at least one more (massive) shader auto shader = std::make_unique<JitCompiler>();
if (jit.GetSpaceLeft() < jit_shader_size) { shader->Compile();
// If not, clear the cache of all previously compiled shaders jit_shader = shader.get();
ClearCache(); shader_map[cache_key] = std::move(shader);
}
jit_shader = jit.Compile();
shader_map.emplace(cache_key, jit_shader);
} }
} }
#endif // ARCHITECTURE_x86_64 #endif // ARCHITECTURE_x86_64
@ -65,7 +54,7 @@ void Setup(UnitState<false>& state) {
void Shutdown() { void Shutdown() {
#ifdef ARCHITECTURE_x86_64 #ifdef ARCHITECTURE_x86_64
ClearCache(); shader_map.clear();
#endif // ARCHITECTURE_x86_64 #endif // ARCHITECTURE_x86_64
} }
@ -109,7 +98,7 @@ OutputVertex Run(UnitState<false>& state, const InputVertex& input, int num_attr
#ifdef ARCHITECTURE_x86_64 #ifdef ARCHITECTURE_x86_64
if (VideoCore::g_shader_jit_enabled) if (VideoCore::g_shader_jit_enabled)
jit_shader(&state.registers); jit_shader->Run(&state.registers);
else else
RunInterpreter(state); RunInterpreter(state);
#else #else

View File

@ -589,7 +589,7 @@ void JitCompiler::Compile_CALL(Instruction instr) {
fixup_branches.push_back({ b, instr.flow_control.dest_offset }); fixup_branches.push_back({ b, instr.flow_control.dest_offset });
// Make sure that if the above code changes, SKIP gets updated // Make sure that if the above code changes, SKIP gets updated
ASSERT(reinterpret_cast<uintptr_t>(GetCodePtr()) - start == SKIP); ASSERT(reinterpret_cast<ptrdiff_t>(GetCodePtr()) - start == SKIP);
} }
void JitCompiler::Compile_CALLC(Instruction instr) { void JitCompiler::Compile_CALLC(Instruction instr) {
@ -803,8 +803,8 @@ void JitCompiler::FindReturnOffsets() {
} }
} }
CompiledShader* JitCompiler::Compile() { void JitCompiler::Compile() {
const u8* start = GetCodePtr(); program = (CompiledShader*)GetCodePtr();
// The stack pointer is 8 modulo 16 at the entry of a procedure // The stack pointer is 8 modulo 16 at the entry of a procedure
ABI_PushRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8); ABI_PushRegistersAndAdjustStack(ABI_ALL_CALLEE_SAVED, 8);
@ -850,15 +850,14 @@ CompiledShader* JitCompiler::Compile() {
SetJumpTarget(branch.first, code_ptr[branch.second]); SetJumpTarget(branch.first, code_ptr[branch.second]);
} }
return (CompiledShader*)start; uintptr_t size = reinterpret_cast<uintptr_t>(GetCodePtr()) - reinterpret_cast<uintptr_t>(program);
ASSERT_MSG(size <= MAX_SHADER_SIZE, "Compiled a shader that exceeds the allocated size!");
LOG_DEBUG(HW_GPU, "Compiled shader size=%d", size);
} }
JitCompiler::JitCompiler() { JitCompiler::JitCompiler() {
AllocCodeSpace(jit_cache_size); AllocCodeSpace(MAX_SHADER_SIZE);
}
void JitCompiler::Clear() {
ClearCodeSpace();
} }
} // namespace Shader } // namespace Shader

View File

@ -22,10 +22,8 @@ namespace Pica {
namespace Shader { namespace Shader {
/// Memory needed to be available to compile the next shader (otherwise, clear the cache) /// Memory allocated for each compiled shader (64Kb)
constexpr size_t jit_shader_size = 1024 * 512; constexpr size_t MAX_SHADER_SIZE = 1024 * 64;
/// Memory allocated for the JIT code space cache
constexpr size_t jit_cache_size = 1024 * 1024 * 8;
using CompiledShader = void(void* registers); using CompiledShader = void(void* registers);
@ -37,9 +35,11 @@ class JitCompiler : public Gen::XCodeBlock {
public: public:
JitCompiler(); JitCompiler();
CompiledShader* Compile(); void Run(void* registers) const {
program(registers);
}
void Clear(); void Compile();
void Compile_ADD(Instruction instr); void Compile_ADD(Instruction instr);
void Compile_DP3(Instruction instr); void Compile_DP3(Instruction instr);
@ -104,12 +104,14 @@ private:
/// Offsets in code where a return needs to be inserted /// Offsets in code where a return needs to be inserted
std::set<unsigned> return_offsets; std::set<unsigned> return_offsets;
unsigned last_program_counter; ///< Offset of the most recent instruction decoded unsigned last_program_counter = 0; ///< Offset of the most recent instruction decoded
unsigned program_counter; ///< Offset of the next instruction to decode unsigned program_counter = 0; ///< Offset of the next instruction to decode
bool looping = false; ///< True if compiling a loop, used to check for nested loops bool looping = false; ///< True if compiling a loop, used to check for nested loops
/// Branches that need to be fixed up once the entire shader program is compiled /// Branches that need to be fixed up once the entire shader program is compiled
std::vector<std::pair<Gen::FixupBranch, unsigned>> fixup_branches; std::vector<std::pair<Gen::FixupBranch, unsigned>> fixup_branches;
CompiledShader* program = nullptr;
}; };
} // Shader } // Shader