void RunGpu() { SCPFifoStruct &fifo = CommandProcessor::fifo; const SConfig& param = SConfig::GetInstance(); // execute GPU if (!param.bCPUThread || g_use_deterministic_gpu_thread) { bool reset_simd_state = false; while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() ) { if (g_use_deterministic_gpu_thread) { ReadDataFromFifoOnCPU(fifo.CPReadPointer); s_gpu_mainloop.Wakeup(); } else { if (!reset_simd_state) { FPURoundMode::SaveSIMDState(); FPURoundMode::LoadDefaultSIMDState(); reset_simd_state = true; } ReadDataFromFifo(fifo.CPReadPointer); s_video_buffer_read_ptr = OpcodeDecoder_Run(DataReader(s_video_buffer_read_ptr, s_video_buffer_write_ptr), nullptr, false); } //DEBUG_LOG(COMMANDPROCESSOR, "Fifo wraps to base"); if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase; else fifo.CPReadPointer += 32; fifo.CPReadWriteDistance -= 32; } CommandProcessor::SetCPStatusFromGPU(); if (reset_simd_state) { FPURoundMode::LoadSIMDState(); } } // wake up GPU thread if (param.bCPUThread) { s_gpu_mainloop.Wakeup(); } }
TEST(BusyLoopTest, MultiThreaded) { Common::BlockingLoop loop; Common::Event e; for (int i = 0; i < 100; i++) { loop.Prepare(); std::thread loop_thread([&]() { loop.Run([&]() { e.Set(); }); }); // Ping - Pong for (int j = 0; j < 10; j++) { loop.Wakeup(); e.Wait(); // Just waste some time. So the main loop did fall back to the sleep state much more likely. Common::SleepCurrentThread(1); } for (int j = 0; j < 100; j++) { // We normally have to call Wakeup to assure the Event is triggered. // But this check is for an internal feature of the BlockingLoop. // It's implemented to fall back to a busy loop regulary. // If we're in the busy loop, the payload (and so the Event) is called all the time. // loop.Wakeup(); e.Wait(); } loop.Stop(); loop_thread.join(); } }
void EmulatorState(bool running) { s_emu_running_state.Set(running); if (running) s_gpu_mainloop.Wakeup(); else s_gpu_mainloop.AllowSleep(); }
static int RunGpuOnCpu(int ticks) { SCPFifoStruct& fifo = CommandProcessor::fifo; bool reset_simd_state = false; int available_ticks = int(ticks * SConfig::GetInstance().fSyncGpuOverclock) + s_sync_ticks.load(); while (fifo.bFF_GPReadEnable && fifo.CPReadWriteDistance && !AtBreakpoint() && available_ticks >= 0) { if (s_use_deterministic_gpu_thread) { ReadDataFromFifoOnCPU(fifo.CPReadPointer); s_gpu_mainloop.Wakeup(); } else { if (!reset_simd_state) { FPURoundMode::SaveSIMDState(); FPURoundMode::LoadDefaultSIMDState(); reset_simd_state = true; } ReadDataFromFifo(fifo.CPReadPointer); u32 cycles = 0; s_video_buffer_read_ptr = OpcodeDecoder::Run( DataReader(s_video_buffer_read_ptr, s_video_buffer_write_ptr), &cycles, false); available_ticks -= cycles; } if (fifo.CPReadPointer == fifo.CPEnd) fifo.CPReadPointer = fifo.CPBase; else fifo.CPReadPointer += 32; fifo.CPReadWriteDistance -= 32; } CommandProcessor::SetCPStatusFromGPU(); if (reset_simd_state) { FPURoundMode::LoadSIMDState(); } // Discard all available ticks as there is nothing to do any more. s_sync_ticks.store(std::min(available_ticks, 0)); // If the GPU is idle, drop the handler. if (available_ticks >= 0) return -1; // Always wait at least for GPU_TIME_SLOT_SIZE cycles. return -available_ticks + GPU_TIME_SLOT_SIZE; }
void RunGpu() { const SConfig& param = SConfig::GetInstance(); // wake up GPU thread if (param.bCPUThread && !s_use_deterministic_gpu_thread) { s_gpu_mainloop.Wakeup(); } // if the sync GPU callback is suspended, wake it up. if (!SConfig::GetInstance().bCPUThread || s_use_deterministic_gpu_thread || SConfig::GetInstance().bSyncGPU) { if (s_syncing_suspended) { s_syncing_suspended = false; CoreTiming::ScheduleEvent(GPU_TIME_SLOT_SIZE, s_event_sync_gpu, GPU_TIME_SLOT_SIZE); } } }
void EmulatorState(bool running) { s_emu_running_state.store(running); s_gpu_mainloop.Wakeup(); }