pvr: render timeout when using ggpo or !threaded

will cause ggpo desyncs with previous versions
This commit is contained in:
Flyinghead 2021-10-01 16:48:01 +02:00
parent 621e4d196e
commit c1bcf91dd6
6 changed files with 39 additions and 23 deletions

View File

@ -679,8 +679,11 @@ void EventManager::broadcastEvent(Event event) {
callback(event);
}
void Emulator::run() {
void Emulator::run()
{
verify(state == Running);
startTime = sh4_sched_now64();
renderTimeout = false;
try {
runInternal();
if (ggpo::active())
@ -724,6 +727,8 @@ void Emulator::start()
try {
while (state == Running)
{
startTime = sh4_sched_now64();
renderTimeout = false;
runInternal();
if (!ggpo::nextFrame())
break;
@ -744,7 +749,8 @@ void Emulator::start()
}
}
bool Emulator::checkStatus() {
bool Emulator::checkStatus()
{
try {
if (threadResult.wait_for(std::chrono::seconds(0)) == std::future_status::timeout)
return true;
@ -756,19 +762,30 @@ bool Emulator::checkStatus() {
}
}
bool Emulator::render() {
bool Emulator::render()
{
if (!config::ThreadedRendering)
{
if (state != Running)
return false;
// FIXME used to timeout in retro_rend_vblank()
//startTime = sh4_sched_now64();
run();
return true; // FIXME need something like is_dupe
// TODO if stopping due to a user request, no frame has been rendered
return !renderTimeout;
}
if (!checkStatus())
return false;
return rend_single_frame(true); // FIXME stop flag?
}
void Emulator::vblank()
{
// Time out if a frame hasn't been rendered for 50 ms
if (sh4_sched_now64() - startTime <= 10000000)
return;
renderTimeout = true;
if (ggpo::active())
ggpo::endOfFrame();
else if (!config::ThreadedRendering)
sh4_cpu.Stop();
}
Emulator emu;

View File

@ -19,10 +19,12 @@
along with flycast. If not, see <https://www.gnu.org/licenses/>.
*/
#pragma once
#include "types.h"
#include <atomic>
#include <map>
#include <vector>
#include <future>
#include <string>
void loadGameSpecificSettings();
void SaveSettings();
@ -37,7 +39,7 @@ void dc_savestate(int index = 0);
void dc_loadstate(int index = 0);
bool dc_loadstate(const void **data, unsigned size);
void dc_load_game(const char *path);
void dc_load_game(const std::string& path);
bool dc_is_load_done();
void dc_cancel_load();
void dc_get_load_status();
@ -137,6 +139,10 @@ public:
* Called internally to reset the emulator.
*/
void requestReset();
/**
* Called internally on vblank.
*/
void vblank();
private:
bool checkStatus();
@ -154,5 +160,7 @@ private:
std::shared_future<void> threadResult;
bool resetRequested = false;
bool singleStep = false;
u64 startTime = 0;
bool renderTimeout = false;
};
extern Emulator emu;

View File

@ -6,19 +6,18 @@
#include "rend/TexCache.h"
#include "cfg/option.h"
#include "network/ggpo.h"
#include "emulator.h"
#include <mutex>
#include <zlib.h>
void retro_rend_present();
void retro_rend_vblank();
#ifndef LIBRETRO
void retro_rend_present()
{
if (!config::ThreadedRendering)
sh4_cpu.Stop();
}
void retro_rend_vblank() {}
#endif
u32 VertexCount=0;
@ -407,7 +406,7 @@ void rend_vblank()
render_called = false;
check_framebuffer_write();
cheatManager.apply();
retro_rend_vblank();
emu.vblank();
}
void check_framebuffer_write()

View File

@ -215,12 +215,12 @@ void dc_loadstate(int index)
INFO_LOG(SAVESTATE, "Loaded state from %s size %d", filename.c_str(), total_size) ;
}
void dc_load_game(const char *path)
void dc_load_game(const std::string& path)
{
loading_canceled = false;
loadingDone = std::async(std::launch::async, [path] {
emu.loadGame(path);
emu.loadGame(path.c_str());
});
}

View File

@ -427,10 +427,7 @@ void gui_start_game(const std::string& path)
scanner.stop();
gui_state = GuiState::Loading;
static std::string path_copy;
path_copy = path; // path may be a local var
dc_load_game(path.empty() ? NULL : path_copy.c_str());
dc_load_game(path);
}
void gui_stop_game(const std::string& message)
@ -447,6 +444,8 @@ void gui_stop_game(const std::string& message)
}
else
{
if (!message.empty())
ERROR_LOG(COMMON, "Flycast has stopped: %s", message.c_str());
// Exit emulator
dc_exit();
}

View File

@ -1922,13 +1922,6 @@ void retro_rend_present()
}
}
void retro_rend_vblank()
{
// Time out if a frame hasn't been rendered for 50 ms
if (!config::ThreadedRendering && is_dupe && sh4_sched_now64() - startTime > 10000000)
sh4_cpu.Stop();
}
static uint32_t get_time_ms()
{
return (uint32_t)(os_GetSeconds() * 1000.0);