From 1d90719abea9e223fd553bd29f42599a94af4346 Mon Sep 17 00:00:00 2001 From: mimimi085181 Date: Sun, 8 May 2016 15:29:01 +0200 Subject: [PATCH] Fix latency regression On master, when polling the 1st in-game controller, Dolphin would poll all the 1st local controllers. With the 1st commit, each client waits its turn, which would dramatically increase the lag. Now with this commit, it even polls all local controllers at once, so it should have even less latency than master in a few setups. Like one player with 3 controllers and the 2nd one with just one controller. --- Source/Core/Core/HW/SI_DeviceGCAdapter.cpp | 12 ++-- Source/Core/Core/HW/SI_DeviceGCController.cpp | 12 ++-- Source/Core/Core/NetPlayClient.cpp | 63 +++++++++++++------ Source/Core/Core/NetPlayClient.h | 5 +- 4 files changed, 57 insertions(+), 35 deletions(-) diff --git a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp index bb42ff812a..2f955164bf 100644 --- a/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCAdapter.cpp @@ -8,7 +8,7 @@ #include "Common/MsgHandler.h" #include "Common/Logging/Log.h" #include "Core/ConfigManager.h" -#include "Core/NetPlayClient.h" +#include "Core/NetPlayProto.h" #include "Core/HW/GCPad.h" #include "Core/HW/SI_DeviceGCAdapter.h" #include "InputCommon/GCAdapter.h" @@ -27,13 +27,9 @@ GCPadStatus CSIDevice_GCAdapter::GetPadStatus() GCPadStatus PadStatus; memset(&PadStatus, 0, sizeof(PadStatus)); - if (NetPlay::IsNetPlayRunning()) - { - const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); - if (numPAD < 4) - GCAdapter::Input(numPAD, &PadStatus); - } - else + // For netplay, the local controllers are polled in GetNetPads(), and + // the remote controllers receive their status there as well + if (!NetPlay::IsNetPlayRunning()) { GCAdapter::Input(ISIDevice::m_iDeviceNumber, &PadStatus); } diff --git a/Source/Core/Core/HW/SI_DeviceGCController.cpp b/Source/Core/Core/HW/SI_DeviceGCController.cpp index cd06dc65ee..572e49c8b8 100644 --- a/Source/Core/Core/HW/SI_DeviceGCController.cpp +++ b/Source/Core/Core/HW/SI_DeviceGCController.cpp @@ -8,7 +8,7 @@ #include "Common/Logging/Log.h" #include "Core/CoreTiming.h" #include "Core/Movie.h" -#include "Core/NetPlayClient.h" +#include "Core/NetPlayProto.h" #include "Core/HW/GCPad.h" #include "Core/HW/ProcessorInterface.h" #include "Core/HW/SI_Device.h" @@ -145,13 +145,9 @@ GCPadStatus CSIDevice_GCController::GetPadStatus() GCPadStatus PadStatus; memset(&PadStatus, 0, sizeof(PadStatus)); - if (NetPlay::IsNetPlayRunning()) - { - const u8 numPAD = NetPlay_InGamePadToLocalPad(ISIDevice::m_iDeviceNumber); - if (numPAD < 4) - Pad::GetStatus(numPAD, &PadStatus); - } - else + // For netplay, the local controllers are polled in GetNetPads(), and + // the remote controllers receive their status there as well + if (!NetPlay::IsNetPlayRunning()) { Pad::GetStatus(ISIDevice::m_iDeviceNumber, &PadStatus); } diff --git a/Source/Core/Core/NetPlayClient.cpp b/Source/Core/Core/NetPlayClient.cpp index 229658cd5a..a8992e1a21 100644 --- a/Source/Core/Core/NetPlayClient.cpp +++ b/Source/Core/Core/NetPlayClient.cpp @@ -19,6 +19,7 @@ #include "Core/HW/WiimoteEmu/WiimoteEmu.h" #include "Core/HW/WiimoteReal/WiimoteReal.h" #include "Core/IPC_HLE/WII_IPC_HLE_Device_usb.h" +#include "InputCommon/GCAdapter.h" static std::mutex crit_netplay_client; static NetPlayClient * netplay_client = nullptr; @@ -864,31 +865,43 @@ bool NetPlayClient::GetNetPads(const u8 pad_nb, GCPadStatus* pad_status) // // The slot number is the "local" pad number, and what player // it actually means is the "in-game" pad number. - // - // GetNetPads() gets called for all "in-game" pads with the their - // status. For the pads, which are mapped locally, the status is - // polled in GetPadStatus() earlier, and here it is send to the - // other clients. For all "in-game" pads, which are mapped to - // the others, the passed over status is ignored. Instead we - // wait for the other clients to send the status to this client. - // If this in-game pad is mapped to this client, then update - // with the status polled earlier in GetPadStatus() - if (m_pad_map[pad_nb] == m_local_player->pid) + // When the 1st in-game pad is polled, we assume the others will + // will be polled as well. To reduce latency, we poll all local + // controllers at once and then send the status to the other + // clients. + if (IsFirstInGamePad(pad_nb)) { - // adjust the buffer either up or down - // inserting multiple padstates or dropping states - while (m_pad_buffer[pad_nb].Size() <= m_target_buffer_size) + const u8 num_local_pads = NumLocalPads(); + for (u8 local_pad = 0; local_pad < num_local_pads; local_pad++) { - // add to buffer - m_pad_buffer[pad_nb].Push(*pad_status); + switch (SConfig::GetInstance().m_SIDevice[local_pad]) + { + case SIDEVICE_WIIU_ADAPTER: + GCAdapter::Input(local_pad, pad_status); + break; + case SIDEVICE_GC_CONTROLLER: + default: + Pad::GetStatus(local_pad, pad_status); + break; + } - // send - SendPadState(pad_nb, *pad_status); + u8 ingame_pad = LocalPadToInGamePad(local_pad); + + // adjust the buffer either up or down + // inserting multiple padstates or dropping states + while (m_pad_buffer[ingame_pad].Size() <= m_target_buffer_size) + { + // add to buffer + m_pad_buffer[ingame_pad].Push(*pad_status); + + // send + SendPadState(ingame_pad, *pad_status); + } } } - // Now, we either use the data we just pushed, or wait for the + // Now, we either use the data pushed earlier, or wait for the // other clients to send it to us while (!m_pad_buffer[pad_nb].Pop(*pad_status)) { @@ -1061,6 +1074,20 @@ bool NetPlayClient::LocalPlayerHasControllerMapped() const std::any_of(m_wiimote_map.begin(), m_wiimote_map.end(), mapping_matches_player_id); } +bool NetPlayClient::IsFirstInGamePad(u8 ingame_pad) const +{ + return std::none_of(m_pad_map.begin(), m_pad_map.begin() + ingame_pad, [](auto mapping) { + return mapping > 0; + }); +} + +u8 NetPlayClient::NumLocalPads() const +{ + return static_cast(std::count_if(m_pad_map.begin(), m_pad_map.end(), [this](auto mapping) { + return mapping == m_local_player->pid; + })); +} + u8 NetPlayClient::InGamePadToLocalPad(u8 ingame_pad) { // not our pad diff --git a/Source/Core/Core/NetPlayClient.h b/Source/Core/Core/NetPlayClient.h index 3c9222e087..285db13b5b 100644 --- a/Source/Core/Core/NetPlayClient.h +++ b/Source/Core/Core/NetPlayClient.h @@ -75,8 +75,11 @@ public: void OnConnectReady(ENetAddress addr) override; void OnConnectFailed(u8 reason) override; + bool IsFirstInGamePad(u8 ingame_pad) const; + u8 NumLocalPads() const; + + u8 InGamePadToLocalPad(u8 ingame_pad); u8 LocalPadToInGamePad(u8 localPad); - u8 InGamePadToLocalPad(u8 localPad); u8 LocalWiimoteToInGameWiimote(u8 local_pad);