CPU: Add settings for execution mode
This commit is contained in:
parent
b8de55b9b8
commit
889bd73ac8
|
@ -9,8 +9,6 @@ Log_SetChannel(CPU::CodeCache);
|
|||
|
||||
namespace CPU {
|
||||
|
||||
bool USE_CODE_CACHE = false;
|
||||
bool USE_RECOMPILER = false;
|
||||
constexpr bool USE_BLOCK_LINKING = true;
|
||||
|
||||
static constexpr size_t RECOMPILER_CODE_CACHE_SIZE = 32 * 1024 * 1024;
|
||||
|
@ -20,11 +18,12 @@ CodeCache::CodeCache() = default;
|
|||
|
||||
CodeCache::~CodeCache() = default;
|
||||
|
||||
void CodeCache::Initialize(System* system, Core* core, Bus* bus)
|
||||
void CodeCache::Initialize(System* system, Core* core, Bus* bus, bool use_recompiler)
|
||||
{
|
||||
m_system = system;
|
||||
m_core = core;
|
||||
m_bus = bus;
|
||||
m_use_recompiler = use_recompiler;
|
||||
|
||||
m_code_buffer = std::make_unique<JitCodeBuffer>(RECOMPILER_CODE_CACHE_SIZE, RECOMPILER_FAR_CODE_CACHE_SIZE);
|
||||
m_asm_functions = std::make_unique<Recompiler::ASMFunctions>();
|
||||
|
@ -63,7 +62,7 @@ void CodeCache::Execute()
|
|||
#endif
|
||||
|
||||
reexecute_block:
|
||||
if (USE_RECOMPILER)
|
||||
if (m_use_recompiler)
|
||||
block->host_code(m_core);
|
||||
else
|
||||
InterpretCachedBlock(*block);
|
||||
|
@ -118,7 +117,16 @@ void CodeCache::Execute()
|
|||
}
|
||||
}
|
||||
|
||||
void CodeCache::Reset()
|
||||
void CodeCache::SetUseRecompiler(bool enable)
|
||||
{
|
||||
if (m_use_recompiler == enable)
|
||||
return;
|
||||
|
||||
m_use_recompiler = enable;
|
||||
Flush();
|
||||
}
|
||||
|
||||
void CodeCache::Flush()
|
||||
{
|
||||
m_bus->ClearRAMCodePageFlags();
|
||||
for (auto& it : m_ram_block_map)
|
||||
|
@ -285,7 +293,7 @@ bool CodeCache::CompileBlock(CodeBlock* block)
|
|||
return false;
|
||||
}
|
||||
|
||||
if (USE_RECOMPILER)
|
||||
if (m_use_recompiler)
|
||||
{
|
||||
// Ensure we're not going to run out of space while compiling this block.
|
||||
if (m_code_buffer->GetFreeCodeSpace() <
|
||||
|
@ -294,7 +302,7 @@ bool CodeCache::CompileBlock(CodeBlock* block)
|
|||
(block->instructions.size() * Recompiler::MAX_FAR_HOST_BYTES_PER_INSTRUCTION))
|
||||
{
|
||||
Log_WarningPrintf("Out of code space, flushing all blocks.");
|
||||
Reset();
|
||||
Flush();
|
||||
}
|
||||
|
||||
Recompiler::CodeGenerator codegen(m_core, m_code_buffer.get(), *m_asm_functions.get());
|
||||
|
|
|
@ -24,10 +24,15 @@ public:
|
|||
CodeCache();
|
||||
~CodeCache();
|
||||
|
||||
void Initialize(System* system, Core* core, Bus* bus);
|
||||
void Reset();
|
||||
void Initialize(System* system, Core* core, Bus* bus, bool use_recompiler);
|
||||
void Execute();
|
||||
|
||||
/// Flushes the code cache, forcing all blocks to be recompiled.
|
||||
void Flush();
|
||||
|
||||
/// Changes whether the recompiler is enabled.
|
||||
void SetUseRecompiler(bool enable);
|
||||
|
||||
/// Invalidates all blocks which are in the range of the specified code page.
|
||||
void InvalidateBlocksWithPageIndex(u32 page_index);
|
||||
|
||||
|
@ -69,10 +74,9 @@ private:
|
|||
|
||||
BlockMap m_blocks;
|
||||
|
||||
bool m_use_recompiler = false;
|
||||
|
||||
std::array<std::vector<CodeBlock*>, CPU_CODE_CACHE_PAGE_COUNT> m_ram_block_map;
|
||||
};
|
||||
|
||||
extern bool USE_CODE_CACHE;
|
||||
extern bool USE_RECOMPILER;
|
||||
|
||||
} // namespace CPU
|
|
@ -14,6 +14,7 @@ Settings::Settings() = default;
|
|||
void Settings::SetDefaults()
|
||||
{
|
||||
region = ConsoleRegion::Auto;
|
||||
cpu_execution_mode = CPUExecutionMode::Interpreter;
|
||||
|
||||
audio_sync_enabled = true;
|
||||
video_sync_enabled = true;
|
||||
|
@ -50,6 +51,9 @@ void Settings::Load(const char* filename)
|
|||
speed_limiter_enabled = ini.GetBoolValue("General", "SpeedLimiterEnabled", true);
|
||||
start_paused = ini.GetBoolValue("General", "StartPaused", false);
|
||||
|
||||
cpu_execution_mode =
|
||||
ParseCPUExecutionMode(ini.GetValue("CPU", "ExecutionMode", "Interpreter")).value_or(CPUExecutionMode::Interpreter);
|
||||
|
||||
gpu_renderer = ParseRendererName(ini.GetValue("GPU", "Renderer", "OpenGL")).value_or(GPURenderer::HardwareOpenGL);
|
||||
gpu_resolution_scale = static_cast<u32>(ini.GetLongValue("GPU", "ResolutionScale", 1));
|
||||
gpu_true_color = ini.GetBoolValue("GPU", "TrueColor", false);
|
||||
|
@ -79,6 +83,8 @@ bool Settings::Save(const char* filename) const
|
|||
ini.SetBoolValue("General", "SpeedLimiterEnabled", speed_limiter_enabled);
|
||||
ini.SetBoolValue("General", "StartPaused", start_paused);
|
||||
|
||||
ini.SetValue("CPU", "ExecutionMode", GetCPUExecutionModeName(cpu_execution_mode));
|
||||
|
||||
ini.SetValue("GPU", "Renderer", GetRendererName(gpu_renderer));
|
||||
ini.SetLongValue("GPU", "ResolutionScale", static_cast<long>(gpu_resolution_scale));
|
||||
ini.SetBoolValue("GPU", "VSync", video_sync_enabled);
|
||||
|
@ -138,6 +144,34 @@ const char* Settings::GetConsoleRegionDisplayName(ConsoleRegion region)
|
|||
return s_console_region_display_names[static_cast<int>(region)];
|
||||
}
|
||||
|
||||
static std::array<const char*, 3> s_cpu_execution_mode_names = {{"Interpreter", "CachedInterpreter", "Recompiler"}};
|
||||
static std::array<const char*, 3> s_cpu_execution_mode_display_names = {
|
||||
{"Intepreter (Slowest)", "Cached Interpreter (Faster)", "Recompiler (Fastest)"}};
|
||||
|
||||
std::optional<CPUExecutionMode> Settings::ParseCPUExecutionMode(const char* str)
|
||||
{
|
||||
u8 index = 0;
|
||||
for (const char* name : s_cpu_execution_mode_names)
|
||||
{
|
||||
if (strcasecmp(name, str) == 0)
|
||||
return static_cast<CPUExecutionMode>(index);
|
||||
|
||||
index++;
|
||||
}
|
||||
|
||||
return std::nullopt;
|
||||
}
|
||||
|
||||
const char* Settings::GetCPUExecutionModeName(CPUExecutionMode mode)
|
||||
{
|
||||
return s_cpu_execution_mode_names[static_cast<u8>(mode)];
|
||||
}
|
||||
|
||||
const char* Settings::GetCPUExecutionModeDisplayName(CPUExecutionMode mode)
|
||||
{
|
||||
return s_cpu_execution_mode_display_names[static_cast<u8>(mode)];
|
||||
}
|
||||
|
||||
static std::array<const char*, 3> s_gpu_renderer_names = {{"D3D11", "OpenGL", "Software"}};
|
||||
static std::array<const char*, 3> s_gpu_renderer_display_names = {
|
||||
{"Hardware (D3D11)", "Hardware (OpenGL)", "Software"}};
|
||||
|
|
|
@ -8,6 +8,8 @@ struct Settings
|
|||
|
||||
ConsoleRegion region = ConsoleRegion::Auto;
|
||||
|
||||
CPUExecutionMode cpu_execution_mode = CPUExecutionMode::Interpreter;
|
||||
|
||||
bool start_paused = false;
|
||||
bool speed_limiter_enabled = true;
|
||||
bool audio_sync_enabled = true;
|
||||
|
@ -51,6 +53,10 @@ struct Settings
|
|||
static const char* GetConsoleRegionName(ConsoleRegion region);
|
||||
static const char* GetConsoleRegionDisplayName(ConsoleRegion region);
|
||||
|
||||
static std::optional<CPUExecutionMode> ParseCPUExecutionMode(const char* str);
|
||||
static const char* GetCPUExecutionModeName(CPUExecutionMode mode);
|
||||
static const char* GetCPUExecutionModeDisplayName(CPUExecutionMode mode);
|
||||
|
||||
static std::optional<GPURenderer> ParseRendererName(const char* str);
|
||||
static const char* GetRendererName(GPURenderer renderer);
|
||||
static const char* GetRendererDisplayName(GPURenderer renderer);
|
||||
|
|
|
@ -34,6 +34,7 @@ System::System(HostInterface* host_interface) : m_host_interface(host_interface)
|
|||
m_spu = std::make_unique<SPU>();
|
||||
m_mdec = std::make_unique<MDEC>();
|
||||
m_region = host_interface->GetSettings().region;
|
||||
m_cpu_execution_mode = host_interface->GetSettings().cpu_execution_mode;
|
||||
}
|
||||
|
||||
System::~System() = default;
|
||||
|
@ -171,7 +172,7 @@ bool System::Boot(const char* filename)
|
|||
void System::InitializeComponents()
|
||||
{
|
||||
m_cpu->Initialize(m_bus.get());
|
||||
m_cpu_code_cache->Initialize(this, m_cpu.get(), m_bus.get());
|
||||
m_cpu_code_cache->Initialize(this, m_cpu.get(), m_bus.get(), m_cpu_execution_mode == CPUExecutionMode::Recompiler);
|
||||
m_bus->Initialize(m_cpu.get(), m_cpu_code_cache.get(), m_dma.get(), m_interrupt_controller.get(), m_gpu.get(),
|
||||
m_cdrom.get(), m_pad.get(), m_timers.get(), m_spu.get(), m_mdec.get());
|
||||
|
||||
|
@ -239,7 +240,7 @@ bool System::DoState(StateWrapper& sw)
|
|||
return false;
|
||||
|
||||
if (sw.IsReading())
|
||||
m_cpu_code_cache->Reset();
|
||||
m_cpu_code_cache->Flush();
|
||||
|
||||
if (!sw.DoMarker("Bus") || !m_bus->DoState(sw))
|
||||
return false;
|
||||
|
@ -274,7 +275,7 @@ bool System::DoState(StateWrapper& sw)
|
|||
void System::Reset()
|
||||
{
|
||||
m_cpu->Reset();
|
||||
m_cpu_code_cache->Reset();
|
||||
m_cpu_code_cache->Flush();
|
||||
m_bus->Reset();
|
||||
m_dma->Reset();
|
||||
m_interrupt_controller->Reset();
|
||||
|
@ -303,14 +304,23 @@ bool System::SaveState(ByteStream* state)
|
|||
|
||||
void System::RunFrame()
|
||||
{
|
||||
// Duplicated to avoid branch in the while loop, as the downcount can be quite low at times.
|
||||
u32 current_frame_number = m_frame_number;
|
||||
while (current_frame_number == m_frame_number)
|
||||
if (m_cpu_execution_mode == CPUExecutionMode::Interpreter)
|
||||
{
|
||||
if (CPU::USE_CODE_CACHE)
|
||||
m_cpu_code_cache->Execute();
|
||||
else
|
||||
while (current_frame_number == m_frame_number)
|
||||
{
|
||||
m_cpu->Execute();
|
||||
Synchronize();
|
||||
Synchronize();
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
while (current_frame_number == m_frame_number)
|
||||
{
|
||||
m_cpu_code_cache->Execute();
|
||||
Synchronize();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -471,6 +481,13 @@ void System::UpdateMemoryCards()
|
|||
}
|
||||
}
|
||||
|
||||
void System::UpdateCPUExecutionMode()
|
||||
{
|
||||
m_cpu_execution_mode = GetSettings().cpu_execution_mode;
|
||||
m_cpu_code_cache->Flush();
|
||||
m_cpu_code_cache->SetUseRecompiler(m_cpu_execution_mode == CPUExecutionMode::Recompiler);
|
||||
}
|
||||
|
||||
bool System::HasMedia() const
|
||||
{
|
||||
return m_cdrom->HasMedia();
|
||||
|
|
|
@ -83,6 +83,7 @@ public:
|
|||
|
||||
void SetController(u32 slot, std::shared_ptr<PadDevice> dev);
|
||||
void UpdateMemoryCards();
|
||||
void UpdateCPUExecutionMode();
|
||||
|
||||
bool HasMedia() const;
|
||||
bool InsertMedia(const char* path);
|
||||
|
@ -109,6 +110,7 @@ private:
|
|||
std::unique_ptr<SPU> m_spu;
|
||||
std::unique_ptr<MDEC> m_mdec;
|
||||
ConsoleRegion m_region = ConsoleRegion::NTSC_U;
|
||||
CPUExecutionMode m_cpu_execution_mode = CPUExecutionMode::Interpreter;
|
||||
u32 m_frame_number = 1;
|
||||
u32 m_internal_frame_number = 1;
|
||||
u32 m_global_tick_counter = 0;
|
||||
|
|
|
@ -31,6 +31,14 @@ enum class ConsoleRegion
|
|||
Count
|
||||
};
|
||||
|
||||
enum class CPUExecutionMode : u8
|
||||
{
|
||||
Interpreter,
|
||||
CachedInterpreter,
|
||||
Recompiler,
|
||||
Count
|
||||
};
|
||||
|
||||
enum class GPURenderer : u8
|
||||
{
|
||||
HardwareD3D11,
|
||||
|
|
|
@ -803,6 +803,26 @@ void SDLHostInterface::DrawQuickSettingsMenu()
|
|||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("CPU Execution Mode"))
|
||||
{
|
||||
const CPUExecutionMode current = m_settings.cpu_execution_mode;
|
||||
for (u32 i = 0; i < static_cast<u32>(CPUExecutionMode::Count); i++)
|
||||
{
|
||||
if (ImGui::MenuItem(Settings::GetCPUExecutionModeDisplayName(static_cast<CPUExecutionMode>(i)), nullptr,
|
||||
i == static_cast<u32>(current)))
|
||||
{
|
||||
m_settings.cpu_execution_mode = static_cast<CPUExecutionMode>(i);
|
||||
settings_changed = true;
|
||||
if (m_system)
|
||||
m_system->UpdateCPUExecutionMode();
|
||||
}
|
||||
}
|
||||
|
||||
ImGui::EndMenu();
|
||||
}
|
||||
|
||||
ImGui::Separator();
|
||||
|
||||
if (ImGui::BeginMenu("Renderer"))
|
||||
{
|
||||
const GPURenderer current = m_settings.gpu_renderer;
|
||||
|
@ -1012,6 +1032,13 @@ void SDLHostInterface::DrawSettingsWindow()
|
|||
m_settings.region = static_cast<ConsoleRegion>(region);
|
||||
settings_changed = true;
|
||||
}
|
||||
|
||||
ImGui::Text("BIOS Path:");
|
||||
ImGui::SameLine(indent);
|
||||
settings_changed |= DrawFileChooser("##bios_path", &m_settings.bios_path);
|
||||
|
||||
settings_changed |= ImGui::Checkbox("Enable TTY Output", &m_settings.bios_patch_tty_enable);
|
||||
settings_changed |= ImGui::Checkbox("Fast Boot", &m_settings.bios_patch_fast_boot);
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
|
@ -1041,17 +1068,6 @@ void SDLHostInterface::DrawSettingsWindow()
|
|||
}
|
||||
}
|
||||
|
||||
ImGui::NewLine();
|
||||
if (DrawSettingsSectionHeader("BIOS"))
|
||||
{
|
||||
ImGui::Text("ROM Path:");
|
||||
ImGui::SameLine(indent);
|
||||
settings_changed |= DrawFileChooser("##bios_path", &m_settings.bios_path);
|
||||
|
||||
settings_changed |= ImGui::Checkbox("Enable TTY Output", &m_settings.bios_patch_tty_enable);
|
||||
settings_changed |= ImGui::Checkbox("Fast Boot", &m_settings.bios_patch_fast_boot);
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
|
@ -1089,6 +1105,29 @@ void SDLHostInterface::DrawSettingsWindow()
|
|||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("CPU"))
|
||||
{
|
||||
ImGui::Text("Execution Mode:");
|
||||
ImGui::SameLine(indent);
|
||||
|
||||
int execution_mode = static_cast<int>(m_settings.cpu_execution_mode);
|
||||
if (ImGui::Combo(
|
||||
"##execution_mode", &execution_mode,
|
||||
[](void*, int index, const char** out_text) {
|
||||
*out_text = Settings::GetCPUExecutionModeDisplayName(static_cast<CPUExecutionMode>(index));
|
||||
return true;
|
||||
},
|
||||
nullptr, static_cast<int>(CPUExecutionMode::Count)))
|
||||
{
|
||||
m_settings.cpu_execution_mode = static_cast<CPUExecutionMode>(execution_mode);
|
||||
settings_changed = true;
|
||||
if (m_system)
|
||||
m_system->UpdateCPUExecutionMode();
|
||||
}
|
||||
|
||||
ImGui::EndTabItem();
|
||||
}
|
||||
|
||||
if (ImGui::BeginTabItem("GPU"))
|
||||
{
|
||||
if (DrawSettingsSectionHeader("Basic"))
|
||||
|
|
Loading…
Reference in New Issue