ggpo: rollback glitches. win32 init. switch build. stats

Block net rollbacks until the current frame has been processed to avoid
glitched textures.
Call WSAStartup at init on windows
Display net stats when in game
Switch build fix
This commit is contained in:
Flyinghead 2021-09-03 11:11:46 +02:00
parent 69d0801121
commit b362a55c04
11 changed files with 102 additions and 2 deletions

View File

@ -303,6 +303,9 @@ typedef struct GGPONetworkStats {
int local_frames_behind;
int remote_frames_behind;
} timesync;
struct {
int predicted_frames;
} sync;
} GGPONetworkStats;
/*

View File

@ -529,6 +529,7 @@ Peer2PeerBackend::GetNetworkStats(GGPONetworkStats *stats, GGPOPlayerHandle play
memset(stats, 0, sizeof *stats);
_endpoints[queue].GetNetworkStats(stats);
stats->sync.predicted_frames = _sync.GetPredictedFrames();
return GGPO_OK;
}

View File

@ -15,6 +15,10 @@ struct Init
{
Init() {
srand(Platform::GetCurrentTimeMS() + Platform::GetProcessID());
#ifdef _WIN32
WSADATA wsaData;
WSAStartup(MAKEWORD(2, 0), &wsaData);
#endif
}
};
static Init init;

View File

@ -21,7 +21,11 @@
#include <sys/stat.h>
#include <sys/socket.h>
#include <netinet/in.h>
#ifdef __SWITCH__
#include "nswitch.h"
#else
#include <netinet/ip.h>
#endif
#include <netinet/tcp.h>
#include <arpa/inet.h>

View File

@ -57,6 +57,7 @@ public:
int GetFrameCount() { return _framecount; }
bool InRollback() { return _rollingback; }
int GetPredictedFrames() { return _framecount - _last_confirmed_frame; }
bool GetEvent(Event &e);

View File

@ -27,6 +27,7 @@ cResetEvent rs, re;
static bool do_swap;
std::mutex swap_mutex;
u32 fb_w_cur = 1;
static cResetEvent vramRollback;
// direct framebuffer write detection
static bool render_called = false;
@ -197,6 +198,7 @@ static bool rend_frame(TA_context* ctx)
if (!proc || (!ctx->rend.isRTT && !ctx->rend.isRenderFramebuffer))
// If rendering to texture, continue locking until the frame is rendered
re.Set();
rend_allow_rollback();
return proc && renderer->Render();
}
@ -437,6 +439,7 @@ void rend_cancel_emu_wait()
{
FinishRender(NULL);
re.Set();
rend_allow_rollback();
}
}
@ -470,3 +473,18 @@ void rend_swap_frame(u32 fb_r_sof1)
}
swap_mutex.unlock();
}
void rend_disable_rollback()
{
vramRollback.Reset();
}
void rend_allow_rollback()
{
vramRollback.Set();
}
void rend_start_rollback()
{
vramRollback.Wait();
}

View File

@ -15,6 +15,9 @@ bool rend_single_frame(const bool& enabled);
void rend_swap_frame(u32 fb_r_sof1);
void rend_set_fb_write_addr(u32 fb_w_sof1);
void rend_reset();
void rend_disable_rollback();
void rend_start_rollback();
void rend_allow_rollback();
///////
extern TA_context* _pvrrc;

View File

@ -4,6 +4,7 @@
#if defined(__SWITCH__)
#include <malloc.h>
#endif
#include "Renderer_if.h"
extern u32 fskip;
extern u32 FrameCount;
@ -101,7 +102,8 @@ bool QueueRender(TA_context* ctx)
fskip++;
return false;
}
// disable net rollbacks until the render thread has processed the frame
rend_disable_rollback();
frame_finished.Reset();
mtx_rqueue.lock();
TA_context* old = rqueue;

View File

@ -30,6 +30,7 @@
#include <mutex>
#include <unordered_map>
#include <xxhash.h>
#include "imgui/imgui.h"
//#define SYNC_TEST 1
@ -59,6 +60,8 @@ struct MemPages
static std::unordered_map<int, MemPages> deltaStates;
static int lastSavedFrame = -1;
static int timesyncOccurred;
/*
* begin_game callback - This callback has been deprecated. You must
* implement it, but should ignore the 'game' parameter.
@ -99,6 +102,7 @@ static bool on_event(GGPOEvent *info)
break;
case GGPO_EVENTCODE_TIMESYNC:
INFO_LOG(NETWORK, "Timesync: %d frames ahead", info->u.timesync.frames_ahead);
timesyncOccurred += 5;
std::this_thread::sleep_for(std::chrono::milliseconds(1000 * info->u.timesync.frames_ahead / 60)); // FIXME assumes 60 FPS
break;
case GGPO_EVENTCODE_CONNECTION_INTERRUPTED:
@ -149,6 +153,7 @@ static bool load_game_state(unsigned char *buffer, int len)
{
INFO_LOG(NETWORK, "load_game_state");
rend_start_rollback();
// FIXME will invalidate too much stuff: palette/fog textures, maple stuff
// FIXME dynarecs
int frame = *(u32 *)buffer;
@ -172,6 +177,7 @@ static bool load_game_state(unsigned char *buffer, int len)
DEBUG_LOG(NETWORK, "Restored frame %d pages: %d ram, %d vram, %d aica ram", f, (u32)pages.ram.size(),
(u32)pages.vram.size(), (u32)pages.aram.size());
}
rend_allow_rollback(); // ggpo might load another state right after this one
memwatch::reset();
memwatch::protect();
return true;
@ -468,6 +474,59 @@ std::future<bool> startNetwork()
});
}
void displayStats()
{
if (!active())
return;
GGPONetworkStats stats;
ggpo_get_network_stats(ggpoSession, remotePlayer, &stats);
ImGui::PushStyleVar(ImGuiStyleVar_WindowRounding, 0);
ImGui::PushStyleVar(ImGuiStyleVar_WindowBorderSize, 0);
ImGui::SetNextWindowPos(ImVec2(10, 10));
ImGui::SetNextWindowSize(ImVec2(95 * scaling, 0));
ImGui::SetNextWindowBgAlpha(0.7f);
ImGui::Begin("", NULL, ImGuiWindowFlags_AlwaysAutoResize | ImGuiWindowFlags_NoDecoration);
ImGui::Columns(2, "cols", false);
ImGui::SetColumnWidth(0, 55 * scaling);
ImGui::SetColumnWidth(1, 40 * scaling);
ImGui::Text("Send Q");
ImGui::NextColumn();
ImGui::Text("%d", stats.network.send_queue_len);
ImGui::NextColumn();
ImGui::Text("Ping");
ImGui::NextColumn();
ImGui::Text("%d", stats.network.ping);
ImGui::NextColumn();
if (stats.sync.predicted_frames == 7)
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 0, 0, 1));
ImGui::Text("Predicted");
ImGui::NextColumn();
ImGui::Text("%d", stats.sync.predicted_frames);
ImGui::NextColumn();
if (stats.sync.predicted_frames == 7)
ImGui::PopStyleColor();
int timesync = timesyncOccurred;
if (timesync > 0)
ImGui::PushStyleColor(ImGuiCol_Text, ImVec4(1, 0, 0, 1));
ImGui::Text("Behind");
ImGui::NextColumn();
ImGui::Text("%d", stats.timesync.local_frames_behind);
if (timesync > 0)
{
ImGui::PopStyleColor();
timesyncOccurred--;
}
ImGui::Columns(1);
ImGui::End();
ImGui::PopStyleVar(2);
}
}
#else // LIBRETRO
@ -496,5 +555,8 @@ std::future<bool> startNetwork() {
return std::async(std::launch::deferred, []{ return false; });;
}
void displayStats() {
}
}
#endif

View File

@ -28,5 +28,6 @@ void stopSession();
void getInput(u32 out_kcode[4]);
void nextFrame();
bool active();
void displayStats();
}

View File

@ -2242,7 +2242,7 @@ void gui_display_osd()
if (message.empty())
message = getFPSNotification();
if (!message.empty() || config::FloatVMUs || crosshairsNeeded())
if (!message.empty() || config::FloatVMUs || crosshairsNeeded() || ggpo::active())
{
ImGui_Impl_NewFrame();
ImGui::NewFrame();
@ -2263,6 +2263,7 @@ void gui_display_osd()
if (config::FloatVMUs)
display_vmus();
// gui_plot_render_time(screen_width, screen_height);
ggpo::displayStats();
ImGui::Render();
ImGui_impl_RenderDrawData(ImGui::GetDrawData());