Просмотр исходного кода

core: Add a configuration setting for use_multi_core.

bunnei 8 лет назад
Родитель
Сommit
9bf2a428f9

+ 26 - 6
src/core/core.cpp

@@ -126,6 +126,21 @@ PerfStats::Results System::GetAndResetPerfStats() {
     return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
     return perf_stats.GetAndResetStats(CoreTiming::GetGlobalTimeUs());
 }
 }
 
 
+const std::shared_ptr<Kernel::Scheduler>& System::Scheduler(size_t core_index) {
+    if (!Settings::values.use_multi_core) {
+        // Always use Core 0 scheduler when multicore is disabled
+        return cpu_cores[0]->Scheduler();
+    }
+
+    ASSERT(core_index < NUM_CPU_CORES);
+    return cpu_cores[core_index]->Scheduler();
+}
+
+ARM_Interface& System::ArmInterface(size_t core_index) {
+    ASSERT(core_index < NUM_CPU_CORES);
+    return cpu_cores[core_index]->ArmInterface();
+}
+
 System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
 System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
     NGLOG_DEBUG(HW_Memory, "initialized OK");
     NGLOG_DEBUG(HW_Memory, "initialized OK");
 
 
@@ -154,9 +169,12 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
     // Create threads for CPU cores 1-3, and build thread_to_cpu map
     // Create threads for CPU cores 1-3, and build thread_to_cpu map
     // CPU core 0 is run on the main thread
     // CPU core 0 is run on the main thread
     thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
     thread_to_cpu[std::this_thread::get_id()] = cpu_cores[0];
-    for (size_t index = 0; index < cpu_core_threads.size(); ++index) {
-        cpu_core_threads[index] = std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]);
-        thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1];
+    if (Settings::values.use_multi_core) {
+        for (size_t index = 0; index < cpu_core_threads.size(); ++index) {
+            cpu_core_threads[index] =
+                std::make_unique<std::thread>(RunCpuCore, cpu_cores[index + 1]);
+            thread_to_cpu[cpu_core_threads[index]->get_id()] = cpu_cores[index + 1];
+        }
     }
     }
 
 
     NGLOG_DEBUG(Core, "Initialized OK");
     NGLOG_DEBUG(Core, "Initialized OK");
@@ -190,9 +208,11 @@ void System::Shutdown() {
 
 
     // Close all CPU/threading state
     // Close all CPU/threading state
     cpu_barrier->NotifyEnd();
     cpu_barrier->NotifyEnd();
-    for (auto& thread : cpu_core_threads) {
-        thread->join();
-        thread.reset();
+    if (Settings::values.use_multi_core) {
+        for (auto& thread : cpu_core_threads) {
+            thread->join();
+            thread.reset();
+        }
     }
     }
     thread_to_cpu.clear();
     thread_to_cpu.clear();
     for (auto& cpu_core : cpu_cores) {
     for (auto& cpu_core : cpu_cores) {

+ 2 - 8
src/core/core.h

@@ -112,10 +112,7 @@ public:
         return CurrentCpuCore().ArmInterface();
         return CurrentCpuCore().ArmInterface();
     }
     }
 
 
-    ARM_Interface& ArmInterface(size_t core_index) {
-        ASSERT(core_index < NUM_CPU_CORES);
-        return cpu_cores[core_index]->ArmInterface();
-    }
+    ARM_Interface& ArmInterface(size_t core_index);
 
 
     Tegra::GPU& GPU() {
     Tegra::GPU& GPU() {
         return *gpu_core;
         return *gpu_core;
@@ -125,10 +122,7 @@ public:
         return *CurrentCpuCore().Scheduler();
         return *CurrentCpuCore().Scheduler();
     }
     }
 
 
-    const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index) {
-        ASSERT(core_index < NUM_CPU_CORES);
-        return cpu_cores[core_index]->Scheduler();
-    }
+    const std::shared_ptr<Kernel::Scheduler>& Scheduler(size_t core_index);
 
 
     Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
     Kernel::SharedPtr<Kernel::Process>& CurrentProcess() {
         return current_process;
         return current_process;

+ 8 - 3
src/core/core_cpu.cpp

@@ -26,9 +26,12 @@ void CpuBarrier::NotifyEnd() {
 }
 }
 
 
 bool CpuBarrier::Rendezvous() {
 bool CpuBarrier::Rendezvous() {
-    if (end) {
-        return false;
-    } else {
+    if (!Settings::values.use_multi_core) {
+        // Meaningless when running in single-core mode
+        return true;
+    }
+
+    if (!end) {
         std::unique_lock<std::mutex> lock(mutex);
         std::unique_lock<std::mutex> lock(mutex);
 
 
         --cores_waiting;
         --cores_waiting;
@@ -41,6 +44,8 @@ bool CpuBarrier::Rendezvous() {
         condition.wait(lock);
         condition.wait(lock);
         return true;
         return true;
     }
     }
+
+    return false;
 }
 }
 
 
 Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)
 Cpu::Cpu(std::shared_ptr<CpuBarrier> cpu_barrier, size_t core_index)

+ 1 - 0
src/core/settings.h

@@ -121,6 +121,7 @@ struct Values {
 
 
     // Core
     // Core
     bool use_cpu_jit;
     bool use_cpu_jit;
+    bool use_multi_core;
 
 
     // Data Storage
     // Data Storage
     bool use_virtual_sd;
     bool use_virtual_sd;

+ 2 - 0
src/core/telemetry_session.cpp

@@ -155,6 +155,8 @@ TelemetrySession::TelemetrySession() {
 
 
     // Log user configuration information
     // Log user configuration information
     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit);
     AddField(Telemetry::FieldType::UserConfig, "Core_UseCpuJit", Settings::values.use_cpu_jit);
+    AddField(Telemetry::FieldType::UserConfig, "Core_UseMultiCore",
+             Settings::values.use_multi_core);
     AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor",
     AddField(Telemetry::FieldType::UserConfig, "Renderer_ResolutionFactor",
              Settings::values.resolution_factor);
              Settings::values.resolution_factor);
     AddField(Telemetry::FieldType::UserConfig, "Renderer_ToggleFramelimit",
     AddField(Telemetry::FieldType::UserConfig, "Renderer_ToggleFramelimit",

+ 2 - 0
src/yuzu/configuration/config.cpp

@@ -78,6 +78,7 @@ void Config::ReadValues() {
 
 
     qt_config->beginGroup("Core");
     qt_config->beginGroup("Core");
     Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
     Settings::values.use_cpu_jit = qt_config->value("use_cpu_jit", true).toBool();
+    Settings::values.use_multi_core = qt_config->value("use_multi_core", false).toBool();
     qt_config->endGroup();
     qt_config->endGroup();
 
 
     qt_config->beginGroup("Renderer");
     qt_config->beginGroup("Renderer");
@@ -177,6 +178,7 @@ void Config::SaveValues() {
 
 
     qt_config->beginGroup("Core");
     qt_config->beginGroup("Core");
     qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit);
     qt_config->setValue("use_cpu_jit", Settings::values.use_cpu_jit);
+    qt_config->setValue("use_multi_core", Settings::values.use_multi_core);
     qt_config->endGroup();
     qt_config->endGroup();
 
 
     qt_config->beginGroup("Renderer");
     qt_config->beginGroup("Renderer");

+ 3 - 0
src/yuzu/configuration/configure_general.cpp

@@ -20,6 +20,7 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent)
     this->setConfiguration();
     this->setConfiguration();
 
 
     ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
     ui->use_cpu_jit->setEnabled(!Core::System::GetInstance().IsPoweredOn());
+    ui->use_multi_core->setEnabled(!Core::System::GetInstance().IsPoweredOn());
     ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
     ui->use_docked_mode->setEnabled(!Core::System::GetInstance().IsPoweredOn());
 }
 }
 
 
@@ -30,6 +31,7 @@ void ConfigureGeneral::setConfiguration() {
     ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
     ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing);
     ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
     ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme));
     ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
     ui->use_cpu_jit->setChecked(Settings::values.use_cpu_jit);
+    ui->use_multi_core->setChecked(Settings::values.use_multi_core);
     ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
     ui->use_docked_mode->setChecked(Settings::values.use_docked_mode);
 }
 }
 
 
@@ -40,6 +42,7 @@ void ConfigureGeneral::applyConfiguration() {
         ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
         ui->theme_combobox->itemData(ui->theme_combobox->currentIndex()).toString();
 
 
     Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
     Settings::values.use_cpu_jit = ui->use_cpu_jit->isChecked();
+    Settings::values.use_multi_core = ui->use_multi_core->isChecked();
     Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
     Settings::values.use_docked_mode = ui->use_docked_mode->isChecked();
     Settings::Apply();
     Settings::Apply();
 }
 }

+ 7 - 0
src/yuzu/configuration/configure_general.ui

@@ -58,6 +58,13 @@
             </property>
             </property>
            </widget>
            </widget>
           </item>
           </item>
+          <item>
+           <widget class="QCheckBox" name="use_multi_core">
+            <property name="text">
+             <string>Enable multi-core</string>
+            </property>
+           </widget>
+          </item>
          </layout>
          </layout>
         </item>
         </item>
        </layout>
        </layout>

+ 1 - 0
src/yuzu_cmd/config.cpp

@@ -91,6 +91,7 @@ void Config::ReadValues() {
 
 
     // Core
     // Core
     Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
     Settings::values.use_cpu_jit = sdl2_config->GetBoolean("Core", "use_cpu_jit", true);
+    Settings::values.use_multi_core = sdl2_config->GetBoolean("Core", "use_multi_core", false);
 
 
     // Renderer
     // Renderer
     Settings::values.resolution_factor =
     Settings::values.resolution_factor =

+ 4 - 0
src/yuzu_cmd/default_ini.h

@@ -80,6 +80,10 @@ touch_device=
 # 0: Interpreter (slow), 1 (default): JIT (fast)
 # 0: Interpreter (slow), 1 (default): JIT (fast)
 use_cpu_jit =
 use_cpu_jit =
 
 
+# Whether to use multi-core for CPU emulation
+# 0 (default): Disabled, 1: Enabled
+use_multi_core=
+
 [Renderer]
 [Renderer]
 # Whether to use software or hardware rendering.
 # Whether to use software or hardware rendering.
 # 0: Software, 1 (default): Hardware
 # 0: Software, 1 (default): Hardware