dolphin/Source/Core/Core/NetPlayProto.h
JosJuice ac28b89fa5 NetPlay/Jit64: Avoid using software FMA
When I added the software FMA path in 2c38d64 and made us use
it when determinism is enabled, I was assuming that either the
performance impact of software FMA wouldn't be too large or CPUs
that were too old to have FMA instructions were too slow to run
Dolphin well anyway. This was wrong. To give an example, the
netplay performance went from 60 FPS to 30 FPS in one case.

This change makes netplay clients negotiate whether FMA should
be used. If all clients use an x64 CPU that supports FMA, or
AArch64, then FMA is enabled, and otherwise FMA is disabled.
In other words, we sacrifice accuracy if needed to avoid massive
slowdown, but not otherwise. When not using netplay, whether to
enable FMA is simply based on whether the host CPU supports it.

The only remaining case where the software FMA path gets used
under normal circumstances is when an input recording is created
on a CPU with FMA support and then played back on a CPU without.
This is not an especially common scenario (though it can happen),
and TASers are generally less picky about performance and more
picky about accuracy than other users anyway.

With this change, FMA desyncs are avoided between AArch64 and
modern x64 CPUs (unlike before 2c38d64), but we do get FMA
desyncs between AArch64 and old x64 CPUs (like before 2c38d64).
This desync can be avoided by adding a non-FMA path to JitArm64 as
an option, which I will wait with for another pull request so that
we can get the performance regression fixed as quickly as possible.

https://bugs.dolphin-emu.org/issues/12542
2021-06-09 22:56:26 +02:00

246 lines
5.6 KiB
C++

// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
#pragma once
#include <array>
#include <vector>
#include "Common/CommonTypes.h"
#include "Core/Config/SYSCONFSettings.h"
#include "Core/HW/EXI/EXI_Device.h"
namespace DiscIO
{
enum class Region;
}
namespace IOS::HLE::FS
{
class FileSystem;
}
namespace PowerPC
{
enum class CPUCore;
}
namespace NetPlay
{
struct NetSettings
{
bool m_CPUthread;
PowerPC::CPUCore m_CPUcore;
bool m_EnableCheats;
int m_SelectedLanguage;
bool m_OverrideRegionSettings;
bool m_DSPHLE;
bool m_DSPEnableJIT;
bool m_WriteToMemcard;
bool m_RAMOverrideEnable;
u32 m_Mem1Size;
u32 m_Mem2Size;
DiscIO::Region m_FallbackRegion;
bool m_AllowSDWrites;
bool m_CopyWiiSave;
bool m_OCEnable;
float m_OCFactor;
std::array<ExpansionInterface::TEXIDevices, 3> m_EXIDevice;
std::array<u32, Config::SYSCONF_SETTINGS.size()> m_SYSCONFSettings;
bool m_EFBAccessEnable;
bool m_BBoxEnable;
bool m_ForceProgressive;
bool m_EFBToTextureEnable;
bool m_XFBToTextureEnable;
bool m_DisableCopyToVRAM;
bool m_ImmediateXFBEnable;
bool m_EFBEmulateFormatChanges;
int m_SafeTextureCacheColorSamples;
bool m_PerfQueriesEnable;
bool m_FPRF;
bool m_AccurateNaNs;
bool m_DisableICache;
bool m_SyncOnSkipIdle;
bool m_SyncGPU;
int m_SyncGpuMaxDistance;
int m_SyncGpuMinDistance;
float m_SyncGpuOverclock;
bool m_JITFollowBranch;
bool m_FastDiscSpeed;
bool m_MMU;
bool m_Fastmem;
bool m_SkipIPL;
bool m_LoadIPLDump;
bool m_VertexRounding;
int m_InternalResolution;
bool m_EFBScaledCopy;
bool m_FastDepthCalc;
bool m_EnablePixelLighting;
bool m_WidescreenHack;
bool m_ForceFiltering;
int m_MaxAnisotropy;
bool m_ForceTrueColor;
bool m_DisableCopyFilter;
bool m_DisableFog;
bool m_ArbitraryMipmapDetection;
float m_ArbitraryMipmapDetectionThreshold;
bool m_EnableGPUTextureDecoding;
bool m_DeferEFBCopies;
int m_EFBAccessTileSize;
bool m_EFBAccessDeferInvalidation;
bool m_StrictSettingsSync;
bool m_SyncSaveData;
bool m_SyncCodes;
std::string m_SaveDataRegion;
bool m_SyncAllWiiSaves;
std::array<int, 4> m_WiimoteExtension;
bool m_GolfMode;
bool m_UseFMA;
// These aren't sent over the network directly
bool m_IsHosting;
bool m_HostInputAuthority;
};
struct NetTraversalConfig
{
NetTraversalConfig() = default;
NetTraversalConfig(bool use_traversal_, std::string traversal_host_, u16 traversal_port_)
: use_traversal{use_traversal_}, traversal_host{std::move(traversal_host_)},
traversal_port{traversal_port_}
{
}
bool use_traversal = false;
std::string traversal_host;
u16 traversal_port = 0;
};
struct Rpt : public std::vector<u8>
{
u16 channel;
};
// messages
enum
{
NP_MSG_PLAYER_JOIN = 0x10,
NP_MSG_PLAYER_LEAVE = 0x11,
NP_MSG_CHAT_MESSAGE = 0x30,
NP_MSG_CHUNKED_DATA_START = 0x40,
NP_MSG_CHUNKED_DATA_END = 0x41,
NP_MSG_CHUNKED_DATA_PAYLOAD = 0x42,
NP_MSG_CHUNKED_DATA_PROGRESS = 0x43,
NP_MSG_CHUNKED_DATA_COMPLETE = 0x44,
NP_MSG_CHUNKED_DATA_ABORT = 0x45,
NP_MSG_PAD_DATA = 0x60,
NP_MSG_PAD_MAPPING = 0x61,
NP_MSG_PAD_BUFFER = 0x62,
NP_MSG_PAD_HOST_DATA = 0x63,
NP_MSG_WIIMOTE_DATA = 0x70,
NP_MSG_WIIMOTE_MAPPING = 0x71,
NP_MSG_GOLF_REQUEST = 0x90,
NP_MSG_GOLF_SWITCH = 0x91,
NP_MSG_GOLF_ACQUIRE = 0x92,
NP_MSG_GOLF_RELEASE = 0x93,
NP_MSG_GOLF_PREPARE = 0x94,
NP_MSG_START_GAME = 0xA0,
NP_MSG_CHANGE_GAME = 0xA1,
NP_MSG_STOP_GAME = 0xA2,
NP_MSG_DISABLE_GAME = 0xA3,
NP_MSG_GAME_STATUS = 0xA4,
NP_MSG_CLIENT_CAPABILITIES = 0xA5,
NP_MSG_HOST_INPUT_AUTHORITY = 0xA6,
NP_MSG_POWER_BUTTON = 0xA7,
NP_MSG_TIMEBASE = 0xB0,
NP_MSG_DESYNC_DETECTED = 0xB1,
NP_MSG_COMPUTE_MD5 = 0xC0,
NP_MSG_MD5_PROGRESS = 0xC1,
NP_MSG_MD5_RESULT = 0xC2,
NP_MSG_MD5_ABORT = 0xC3,
NP_MSG_MD5_ERROR = 0xC4,
NP_MSG_READY = 0xD0,
NP_MSG_NOT_READY = 0xD1,
NP_MSG_PING = 0xE0,
NP_MSG_PONG = 0xE1,
NP_MSG_PLAYER_PING_DATA = 0xE2,
NP_MSG_SYNC_GC_SRAM = 0xF0,
NP_MSG_SYNC_SAVE_DATA = 0xF1,
NP_MSG_SYNC_CODES = 0xF2,
};
enum
{
CON_ERR_SERVER_FULL = 1,
CON_ERR_GAME_RUNNING = 2,
CON_ERR_VERSION_MISMATCH = 3,
CON_ERR_NAME_TOO_LONG = 4
};
enum
{
SYNC_SAVE_DATA_NOTIFY = 0,
SYNC_SAVE_DATA_SUCCESS = 1,
SYNC_SAVE_DATA_FAILURE = 2,
SYNC_SAVE_DATA_RAW = 3,
SYNC_SAVE_DATA_GCI = 4,
SYNC_SAVE_DATA_WII = 5
};
enum
{
SYNC_CODES_NOTIFY = 0,
SYNC_CODES_NOTIFY_GECKO = 1,
SYNC_CODES_NOTIFY_AR = 2,
SYNC_CODES_DATA_GECKO = 3,
SYNC_CODES_DATA_AR = 4,
SYNC_CODES_SUCCESS = 5,
SYNC_CODES_FAILURE = 6,
};
constexpr u32 NETPLAY_LZO_IN_LEN = 1024 * 64;
constexpr u32 NETPLAY_LZO_OUT_LEN = NETPLAY_LZO_IN_LEN + (NETPLAY_LZO_IN_LEN / 16) + 64 + 3;
constexpr u32 MAX_NAME_LENGTH = 30;
constexpr size_t CHUNKED_DATA_UNIT_SIZE = 16384;
constexpr u8 CHANNEL_COUNT = 2;
constexpr u8 DEFAULT_CHANNEL = 0;
constexpr u8 CHUNKED_DATA_CHANNEL = 1;
struct WiimoteInput
{
u8 report_id;
std::vector<u8> data;
};
using MessageId = u8;
using PlayerId = u8;
using FrameNum = u32;
using PadIndex = s8;
using PadMappingArray = std::array<PlayerId, 4>;
bool IsNetPlayRunning();
// Precondition: A netplay client instance must be present. In other words,
// IsNetPlayRunning() must be true before calling this.
const NetSettings& GetNetSettings();
IOS::HLE::FS::FileSystem* GetWiiSyncFS();
const std::vector<u64>& GetWiiSyncTitles();
void SetWiiSyncData(std::unique_ptr<IOS::HLE::FS::FileSystem> fs, const std::vector<u64>& titles);
void ClearWiiSyncData();
void SetSIPollBatching(bool state);
void SendPowerButtonEvent();
bool IsSyncingAllWiiSaves();
void SetupWiimotes();
} // namespace NetPlay