This commit is contained in:
Huw Pascoe 2017-09-23 21:04:55 +01:00
parent a81536f53f
commit dcea128d80
5 changed files with 64 additions and 6 deletions

View File

@ -3,6 +3,7 @@
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <memory> #include <memory>
#include <thread>
#include <utility> #include <utility>
#include "audio_core/audio_core.h" #include "audio_core/audio_core.h"
#include "common/logging/log.h" #include "common/logging/log.h"
@ -26,6 +27,11 @@ namespace Core {
/*static*/ System System::s_instance; /*static*/ System System::s_instance;
std::thread CpuThread;
std::atomic<bool> CpuThreadRunning;
std::atomic<bool> RunCPU;
std::atomic<int> TightLoop;
System::ResultStatus System::RunLoop(int tight_loop) { System::ResultStatus System::RunLoop(int tight_loop) {
status = ResultStatus::Success; status = ResultStatus::Success;
if (!cpu_core) { if (!cpu_core) {
@ -47,6 +53,15 @@ System::ResultStatus System::RunLoop(int tight_loop) {
} }
} }
TightLoop += tight_loop;
RunCPU = true;
HW::Update();
return status;
}
void System::RunLoopInner() {
// If we don't have a currently active thread then don't execute instructions, // If we don't have a currently active thread then don't execute instructions,
// instead advance to the next event and try to yield to the next thread // instead advance to the next event and try to yield to the next thread
if (Kernel::GetCurrentThread() == nullptr) { if (Kernel::GetCurrentThread() == nullptr) {
@ -55,13 +70,20 @@ System::ResultStatus System::RunLoop(int tight_loop) {
CoreTiming::Advance(); CoreTiming::Advance();
PrepareReschedule(); PrepareReschedule();
} else { } else {
cpu_core->Run(tight_loop); cpu_core->Run(TightLoop);
} }
HW::Update(); TightLoop = 0;
Reschedule(); Reschedule();
}
return status; void System::RunLoopInThread() {
while (CpuThreadRunning) {
if (RunCPU) {
RunLoopInner();
RunCPU = false;
}
}
} }
System::ResultStatus System::SingleStep() { System::ResultStatus System::SingleStep() {
@ -164,10 +186,16 @@ System::ResultStatus System::Init(EmuWindow* emu_window, u32 system_mode) {
GetAndResetPerfStats(); GetAndResetPerfStats();
perf_stats.BeginSystemFrame(); perf_stats.BeginSystemFrame();
CpuThreadRunning = true;
CpuThread = std::thread(&System::RunLoopInThread, this);
return ResultStatus::Success; return ResultStatus::Success;
} }
void System::Shutdown() { void System::Shutdown() {
CpuThreadRunning = false;
CpuThread.join();
// Log last frame performance stats // Log last frame performance stats
auto perf_results = GetAndResetPerfStats(); auto perf_results = GetAndResetPerfStats();
Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed", Telemetry().AddField(Telemetry::FieldType::Performance, "Shutdown_EmulationSpeed",

View File

@ -54,6 +54,8 @@ public:
* @return Result status, indicating whethor or not the operation succeeded. * @return Result status, indicating whethor or not the operation succeeded.
*/ */
ResultStatus RunLoop(int tight_loop = 1000); ResultStatus RunLoop(int tight_loop = 1000);
void RunLoopInThread();
void RunLoopInner();
/** /**
* Step the CPU one instruction * Step the CPU one instruction

View File

@ -2,6 +2,7 @@
// Licensed under GPLv2 or any later version // Licensed under GPLv2 or any later version
// Refer to the license.txt file included. // Refer to the license.txt file included.
#include <boost/lockfree/queue.hpp>
#include <cstring> #include <cstring>
#include <numeric> #include <numeric>
#include <type_traits> #include <type_traits>
@ -28,6 +29,14 @@ namespace GPU {
Regs g_regs; Regs g_regs;
struct WriteThing {
u32 addr;
u32 data;
};
std::atomic<bool> VBlankGo = false;
boost::lockfree::queue<WriteThing> WriteQueue(128);
/// 268MHz CPU clocks / 60Hz frames per second /// 268MHz CPU clocks / 60Hz frames per second
const u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE_ARM11 / SCREEN_REFRESH_RATE); const u64 frame_ticks = static_cast<u64>(BASE_CLOCK_RATE_ARM11 / SCREEN_REFRESH_RATE);
/// Event id for CoreTiming /// Event id for CoreTiming
@ -392,6 +401,11 @@ static void TextureCopy(const Regs::DisplayTransferConfig& config) {
template <typename T> template <typename T>
inline void Write(u32 addr, const T data) { inline void Write(u32 addr, const T data) {
WriteQueue.push(WriteThing{addr, static_cast<u32>(data)});
}
template <typename T>
inline void WriteE(u32 addr, const T data) {
addr -= HW::VADDR_GPU; addr -= HW::VADDR_GPU;
u32 index = addr / 4; u32 index = addr / 4;
@ -515,8 +529,6 @@ template void Write<u8>(u32 addr, const u8 data);
/// Update hardware /// Update hardware
static void VBlankCallback(u64 userdata, int cycles_late) { static void VBlankCallback(u64 userdata, int cycles_late) {
VideoCore::g_renderer->SwapBuffers();
// Signal to GSP that GPU interrupt has occurred // Signal to GSP that GPU interrupt has occurred
// TODO(yuriks): hwtest to determine if PDC0 is for the Top screen and PDC1 for the Sub // TODO(yuriks): hwtest to determine if PDC0 is for the Top screen and PDC1 for the Sub
// screen, or if both use the same interrupts and these two instead determine the // screen, or if both use the same interrupts and these two instead determine the
@ -524,6 +536,7 @@ static void VBlankCallback(u64 userdata, int cycles_late) {
// two different intervals. // two different intervals.
Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC0); Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC0);
Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC1); Service::GSP::SignalInterrupt(Service::GSP::InterruptId::PDC1);
VBlankGo = true;
// Reschedule recurrent event // Reschedule recurrent event
CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event); CoreTiming::ScheduleEvent(frame_ticks - cycles_late, vblank_event);
@ -565,6 +578,17 @@ void Init() {
LOG_DEBUG(HW_GPU, "initialized OK"); LOG_DEBUG(HW_GPU, "initialized OK");
} }
void Update() {
WriteThing thing;
while (WriteQueue.pop(thing)) {
WriteE<u32>(thing.addr, thing.data);
}
if (VBlankGo) {
VideoCore::g_renderer->SwapBuffers();
VBlankGo = false;
}
}
/// Shutdown hardware /// Shutdown hardware
void Shutdown() { void Shutdown() {
LOG_DEBUG(HW_GPU, "shutdown OK"); LOG_DEBUG(HW_GPU, "shutdown OK");

View File

@ -328,6 +328,8 @@ void Write(u32 addr, const T data);
/// Initialize hardware /// Initialize hardware
void Init(); void Init();
void Update();
/// Shutdown hardware /// Shutdown hardware
void Shutdown(); void Shutdown();

View File

@ -82,7 +82,9 @@ template void Write<u16>(u32 addr, const u16 data);
template void Write<u8>(u32 addr, const u8 data); template void Write<u8>(u32 addr, const u8 data);
/// Update hardware /// Update hardware
void Update() {} void Update() {
GPU::Update();
}
/// Initialize hardware /// Initialize hardware
void Init() { void Init() {