mirror of
https://github.com/citra-emu/citra.git
synced 2024-11-15 11:50:05 +00:00
shader_jit_x64: Allocate each program independently and persist for emu session.
This commit is contained in:
parent
4632791a40
commit
c9d10de644
@ -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
|
||||||
|
@ -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
|
||||||
|
@ -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
|
||||||
|
Loading…
Reference in New Issue
Block a user