diff --git a/Externals/mGBA/mgba b/Externals/mGBA/mgba
index 89f8873df3..8739b22fbc 160000
--- a/Externals/mGBA/mgba
+++ b/Externals/mGBA/mgba
@@ -1 +1 @@
-Subproject commit 89f8873df366a99dfdf40347f72e68763fb50bd9
+Subproject commit 8739b22fbc90fdf0b4f6612ef9c0520f0ba44a51
diff --git a/Externals/mGBA/mgba.vcxproj b/Externals/mGBA/mgba.vcxproj
index ce46cbd41e..8219fddf76 100644
--- a/Externals/mGBA/mgba.vcxproj
+++ b/Externals/mGBA/mgba.vcxproj
@@ -151,23 +151,25 @@
+
+
-
-
+
+
@@ -215,6 +217,7 @@
+
diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp
index cb62141522..5c8ac7b275 100644
--- a/Source/Core/Core/HW/GBACore.cpp
+++ b/Source/Core/Core/HW/GBACore.cpp
@@ -305,7 +305,7 @@ CoreInfo Core::GetCoreInfo() const
info.has_rom = !m_rom_path.empty();
info.has_ereader =
info.is_gba && static_cast<::GBA*>(m_core->board)->memory.hw.devices & HW_EREADER;
- m_core->desiredVideoDimensions(m_core, &info.width, &info.height);
+ m_core->currentVideoSize(m_core, &info.width, &info.height);
info.game_title = m_game_title;
return info;
}
@@ -392,7 +392,7 @@ void Core::SetSIODriver()
void Core::SetVideoBuffer()
{
u32 width, height;
- m_core->desiredVideoDimensions(m_core, &width, &height);
+ m_core->currentVideoSize(m_core, &width, &height);
m_video_buffer.resize(width * height);
m_core->setVideoBuffer(m_core, m_video_buffer.data(), width);
if (auto host = m_host.lock())
diff --git a/Source/Core/Core/IOS/IOS.cpp b/Source/Core/Core/IOS/IOS.cpp
index 82f51dac33..bc09da7837 100644
--- a/Source/Core/Core/IOS/IOS.cpp
+++ b/Source/Core/Core/IOS/IOS.cpp
@@ -308,6 +308,7 @@ Kernel::~Kernel()
{
std::lock_guard lock(m_device_map_mutex);
m_device_map.clear();
+ m_socket_manager.reset();
}
if (m_is_responsible_for_nand_root)
@@ -363,6 +364,11 @@ std::shared_ptr Kernel::GetES()
return std::static_pointer_cast(m_device_map.at("/dev/es"));
}
+std::shared_ptr Kernel::GetSocketManager()
+{
+ return m_socket_manager;
+}
+
// Since we don't have actual processes, we keep track of only the PPC's UID/GID.
// These functions roughly correspond to syscalls 0x2b, 0x2c, 0x2d, 0x2e (though only for the PPC).
void Kernel::SetUidForPPC(u32 uid)
@@ -562,6 +568,11 @@ void Kernel::AddStaticDevices()
AddDevice(std::make_unique(*this, "/dev/sdio/slot1"));
// Network modules
+ if (HasFeature(features, Feature::KD) || HasFeature(features, Feature::SO) ||
+ HasFeature(features, Feature::SSL))
+ {
+ m_socket_manager = std::make_shared();
+ }
if (HasFeature(features, Feature::KD))
{
AddDevice(std::make_unique(*this, "/dev/net/kd/request"));
@@ -825,7 +836,8 @@ void Kernel::UpdateDevices()
void Kernel::UpdateWantDeterminism(const bool new_want_determinism)
{
- WiiSockMan::GetInstance().UpdateWantDeterminism(new_want_determinism);
+ if (m_socket_manager)
+ m_socket_manager->UpdateWantDeterminism(new_want_determinism);
for (const auto& device : m_device_map)
device.second->UpdateWantDeterminism(new_want_determinism);
}
@@ -846,6 +858,9 @@ void Kernel::DoState(PointerWrap& p)
if (m_title_id == Titles::MIOS)
return;
+ if (m_socket_manager)
+ m_socket_manager->DoState(p);
+
for (const auto& entry : m_device_map)
entry.second->DoState(p);
diff --git a/Source/Core/Core/IOS/IOS.h b/Source/Core/Core/IOS/IOS.h
index a9ca0ec0f5..878bb56ccc 100644
--- a/Source/Core/Core/IOS/IOS.h
+++ b/Source/Core/Core/IOS/IOS.h
@@ -35,6 +35,7 @@ class FileSystem;
class Device;
class ESDevice;
class FSDevice;
+class WiiSockMan;
struct Request;
struct OpenRequest;
@@ -130,6 +131,9 @@ public:
std::shared_ptr GetFSDevice();
std::shared_ptr GetES();
+ // This is only available on an EmulationKernel if the IOS features require it.
+ std::shared_ptr GetSocketManager();
+
void EnqueueIPCRequest(u32 address);
void EnqueueIPCReply(const Request& request, s32 return_value, s64 cycles_in_future = 0,
CoreTiming::FromThread from = CoreTiming::FromThread::CPU);
@@ -179,6 +183,7 @@ protected:
IOSC m_iosc;
std::shared_ptr m_fs;
+ std::shared_ptr m_socket_manager;
};
// HLE for an IOS tied to emulation: base kernel which may have additional modules loaded.
diff --git a/Source/Core/Core/IOS/Network/IP/Top.cpp b/Source/Core/Core/IOS/Network/IP/Top.cpp
index 27487918d0..261b6db9b7 100644
--- a/Source/Core/Core/IOS/Network/IP/Top.cpp
+++ b/Source/Core/Core/IOS/Network/IP/Top.cpp
@@ -77,7 +77,6 @@ NetIPTopDevice::NetIPTopDevice(Kernel& ios, const std::string& device_name)
void NetIPTopDevice::DoState(PointerWrap& p)
{
Device::DoState(p);
- WiiSockMan::GetInstance().DoState(p);
}
static int inet_pton(const char* src, unsigned char* dst)
@@ -371,7 +370,7 @@ void NetIPTopDevice::Update()
m_async_replies.pop();
}
}
- WiiSockMan::GetInstance().Update();
+ m_ios.GetSocketManager()->Update();
}
IPCReply NetIPTopDevice::HandleInitInterfaceRequest(const IOCtlRequest& request)
@@ -389,8 +388,7 @@ IPCReply NetIPTopDevice::HandleSocketRequest(const IOCtlRequest& request)
const u32 type = memory.Read_U32(request.buffer_in + 4);
const u32 prot = memory.Read_U32(request.buffer_in + 8);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- const s32 return_value = sm.NewSocket(af, type, prot);
+ const s32 return_value = m_ios.GetSocketManager()->NewSocket(af, type, prot);
INFO_LOG_FMT(IOS_NET,
"IOCTL_SO_SOCKET "
"Socket: {:08x} ({},{},{}), BufferIn: ({:08x}, {}), BufferOut: ({:08x}, {})",
@@ -407,8 +405,7 @@ IPCReply NetIPTopDevice::HandleICMPSocketRequest(const IOCtlRequest& request)
const u32 pf = memory.Read_U32(request.buffer_in);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- const s32 return_value = sm.NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
+ const s32 return_value = m_ios.GetSocketManager()->NewSocket(pf, SOCK_RAW, IPPROTO_ICMP);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_ICMPSOCKET({:x}) {}", pf, return_value);
return IPCReply(return_value);
}
@@ -419,8 +416,7 @@ IPCReply NetIPTopDevice::HandleCloseRequest(const IOCtlRequest& request)
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- const s32 return_value = sm.DeleteSocket(fd);
+ const s32 return_value = m_ios.GetSocketManager()->DeleteSocket(fd);
const char* const close_fn =
request.request == IOCTL_SO_ICMPCLOSE ? "IOCTL_SO_ICMPCLOSE" : "IOCTL_SO_CLOSE";
@@ -435,8 +431,7 @@ std::optional NetIPTopDevice::HandleDoSockRequest(const IOCtlRequest&
auto& memory = system.GetMemory();
const u32 fd = memory.Read_U32(request.buffer_in);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(fd, request, static_cast(request.request));
+ m_ios.GetSocketManager()->DoSock(fd, request, static_cast(request.request));
return std::nullopt;
}
@@ -454,8 +449,7 @@ IPCReply NetIPTopDevice::HandleShutdownRequest(const IOCtlRequest& request)
const u32 fd = memory.Read_U32(request.buffer_in);
const u32 how = memory.Read_U32(request.buffer_in + 4);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- const s32 return_value = sm.ShutdownSocket(fd, how);
+ const s32 return_value = m_ios.GetSocketManager()->ShutdownSocket(fd, how);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_SHUTDOWN(fd={}, how={}) = {}", fd, how, return_value);
return IPCReply(return_value);
@@ -468,10 +462,11 @@ IPCReply NetIPTopDevice::HandleListenRequest(const IOCtlRequest& request)
u32 fd = memory.Read_U32(request.buffer_in);
u32 BACKLOG = memory.Read_U32(request.buffer_in + 0x04);
- u32 ret = listen(WiiSockMan::GetInstance().GetHostSocket(fd), BACKLOG);
+ auto socket_manager = m_ios.GetSocketManager();
+ u32 ret = listen(socket_manager->GetHostSocket(fd), BACKLOG);
request.Log(GetDeviceName(), Common::Log::LogType::IOS_WC24);
- return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_LISTEN", false));
+ return IPCReply(socket_manager->GetNetErrorCode(ret, "SO_LISTEN", false));
}
IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
@@ -492,16 +487,17 @@ IPCReply NetIPTopDevice::HandleGetSockOptRequest(const IOCtlRequest& request)
u8 optval[20];
u32 optlen = 4;
- int ret = getsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname,
- (char*)&optval, (socklen_t*)&optlen);
- const s32 return_value = WiiSockMan::GetNetErrorCode(ret, "SO_GETSOCKOPT", false);
+ auto socket_manager = m_ios.GetSocketManager();
+ int ret = getsockopt(socket_manager->GetHostSocket(fd), nat_level, nat_optname, (char*)&optval,
+ (socklen_t*)&optlen);
+ const s32 return_value = socket_manager->GetNetErrorCode(ret, "SO_GETSOCKOPT", false);
memory.Write_U32(optlen, request.buffer_out + 0xC);
memory.CopyToEmu(request.buffer_out + 0x10, optval, optlen);
if (optname == SO_ERROR)
{
- s32 last_error = WiiSockMan::GetInstance().GetLastNetError();
+ s32 last_error = socket_manager->GetLastNetError();
memory.Write_U32(sizeof(s32), request.buffer_out + 0xC);
memory.Write_U32(last_error, request.buffer_out + 0x10);
@@ -543,9 +539,10 @@ IPCReply NetIPTopDevice::HandleSetSockOptRequest(const IOCtlRequest& request)
const int nat_level = MapWiiSockOptLevelToNative(level);
const int nat_optname = MapWiiSockOptNameToNative(optname);
- const int ret = setsockopt(WiiSockMan::GetInstance().GetHostSocket(fd), nat_level, nat_optname,
+ auto socket_manager = m_ios.GetSocketManager();
+ const int ret = setsockopt(socket_manager->GetHostSocket(fd), nat_level, nat_optname,
reinterpret_cast(optval), optlen);
- return IPCReply(WiiSockMan::GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
+ return IPCReply(socket_manager->GetNetErrorCode(ret, "SO_SETSOCKOPT", false));
}
IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
@@ -559,7 +556,7 @@ IPCReply NetIPTopDevice::HandleGetSockNameRequest(const IOCtlRequest& request)
sockaddr sa;
socklen_t sa_len = sizeof(sa);
- const int ret = getsockname(WiiSockMan::GetInstance().GetHostSocket(fd), &sa, &sa_len);
+ const int ret = getsockname(m_ios.GetSocketManager()->GetHostSocket(fd), &sa, &sa_len);
if (request.buffer_out_size < 2 + sizeof(sa.sa_data))
WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETSOCKNAME output buffer is too small. Truncating");
@@ -586,7 +583,7 @@ IPCReply NetIPTopDevice::HandleGetPeerNameRequest(const IOCtlRequest& request)
sockaddr sa;
socklen_t sa_len = sizeof(sa);
- const int ret = getpeername(WiiSockMan::GetInstance().GetHostSocket(fd), &sa, &sa_len);
+ const int ret = getpeername(m_ios.GetSocketManager()->GetHostSocket(fd), &sa, &sa_len);
if (request.buffer_out_size < 2 + sizeof(sa.sa_data))
WARN_LOG_FMT(IOS_NET, "IOCTL_SO_GETPEERNAME output buffer is too small. Truncating");
@@ -677,7 +674,7 @@ IPCReply NetIPTopDevice::HandleInetNToPRequest(const IOCtlRequest& request)
std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& request)
{
- WiiSockMan& sm = WiiSockMan::GetInstance();
+ auto sm = m_ios.GetSocketManager();
if (!request.buffer_in || !request.buffer_out)
return IPCReply(-SO_EINVAL);
@@ -700,7 +697,7 @@ std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re
for (u32 i = 0; i < nfds; ++i)
{
const s32 wii_fd = memory.Read_U32(request.buffer_out + 0xc * i);
- ufds[i].fd = sm.GetHostSocket(wii_fd); // fd
+ ufds[i].fd = sm->GetHostSocket(wii_fd); // fd
const int events = memory.Read_U32(request.buffer_out + 0xc * i + 4); // events
ufds[i].revents = 0;
@@ -717,7 +714,7 @@ std::optional NetIPTopDevice::HandlePollRequest(const IOCtlRequest& re
}
// Prevents blocking emulation on a blocking poll
- sm.AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout});
+ sm->AddPollCommand({request.address, request.buffer_out, std::move(ufds), timeout});
return std::nullopt;
}
@@ -1014,8 +1011,7 @@ std::optional NetIPTopDevice::HandleSendToRequest(const IOCtlVRequest&
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.in_vectors[1].address);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(fd, request, IOCTLV_SO_SENDTO);
+ m_ios.GetSocketManager()->DoSock(fd, request, IOCTLV_SO_SENDTO);
return std::nullopt;
}
@@ -1025,8 +1021,7 @@ std::optional NetIPTopDevice::HandleRecvFromRequest(const IOCtlVReques
auto& memory = system.GetMemory();
u32 fd = memory.Read_U32(request.in_vectors[0].address);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(fd, request, IOCTLV_SO_RECVFROM);
+ m_ios.GetSocketManager()->DoSock(fd, request, IOCTLV_SO_RECVFROM);
return std::nullopt;
}
@@ -1181,11 +1176,12 @@ IPCReply NetIPTopDevice::HandleICMPPingRequest(const IOCtlVRequest& request)
icmp_length = 22;
}
- int ret = icmp_echo_req(WiiSockMan::GetInstance().GetHostSocket(fd), &addr, data, icmp_length);
+ auto socket_manager = m_ios.GetSocketManager();
+ int ret = icmp_echo_req(socket_manager->GetHostSocket(fd), &addr, data, icmp_length);
if (ret == icmp_length)
{
- ret = icmp_echo_rep(WiiSockMan::GetInstance().GetHostSocket(fd), &addr,
- static_cast(timeout), icmp_length);
+ ret = icmp_echo_rep(socket_manager->GetHostSocket(fd), &addr, static_cast(timeout),
+ icmp_length);
}
// TODO proper error codes
diff --git a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp
index cc1469bdfa..fd7988cf44 100644
--- a/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp
+++ b/Source/Core/Core/IOS/Network/KD/NetKDRequest.cpp
@@ -161,7 +161,9 @@ NetKDRequestDevice::NetKDRequestDevice(Kernel& ios, const std::string& device_na
NetKDRequestDevice::~NetKDRequestDevice()
{
- WiiSockMan::GetInstance().Clean();
+ auto socket_manager = m_ios.GetSocketManager();
+ if (socket_manager)
+ socket_manager->Clean();
}
void NetKDRequestDevice::Update()
@@ -348,7 +350,7 @@ std::optional NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
case IOCTL_NWC24_CLEANUP_SOCKET:
INFO_LOG_FMT(IOS_WC24, "NET_KD_REQ: IOCTL_NWC24_CLEANUP_SOCKET");
- WiiSockMan::GetInstance().Clean();
+ m_ios.GetSocketManager()->Clean();
break;
case IOCTL_NWC24_LOCK_SOCKET: // WiiMenu
@@ -452,7 +454,7 @@ std::optional NetKDRequestDevice::IOCtl(const IOCtlRequest& request)
// SOGetInterfaceOpt(0xfffe,0xc001); // DHCP lease time remaining?
// SOGetInterfaceOpt(0xfffe,0x1003); // Error
// Call /dev/net/ip/top 0x1b (SOCleanup), it closes all sockets
- WiiSockMan::GetInstance().Clean();
+ m_ios.GetSocketManager()->Clean();
return_value = IPC_SUCCESS;
break;
}
diff --git a/Source/Core/Core/IOS/Network/SSL.cpp b/Source/Core/Core/IOS/Network/SSL.cpp
index a26d2451db..bbd182347a 100644
--- a/Source/Core/Core/IOS/Network/SSL.cpp
+++ b/Source/Core/Core/IOS/Network/SSL.cpp
@@ -496,8 +496,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
WII_SSL* ssl = &_SSL[sslID];
mbedtls_ssl_setup(&ssl->ctx, &ssl->config);
ssl->sockfd = memory.Read_U32(BufferOut2);
- WiiSockMan& sm = WiiSockMan::GetInstance();
- ssl->hostfd = sm.GetHostSocket(ssl->sockfd);
+ ssl->hostfd = m_ios.GetSocketManager()->GetHostSocket(ssl->sockfd);
INFO_LOG_FMT(IOS_SSL, "IOCTLV_NET_SSL_CONNECT socket = {}", ssl->sockfd);
mbedtls_ssl_set_bio(&ssl->ctx, ssl, SSLSendWithoutSNI, SSLRecv, nullptr);
WriteReturnValue(SSL_OK, BufferIn);
@@ -520,8 +519,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE);
+ m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_DOHANDSHAKE);
return std::nullopt;
}
else
@@ -535,8 +533,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
const int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE);
+ m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_WRITE);
return std::nullopt;
}
else
@@ -559,8 +556,7 @@ std::optional NetSSLDevice::IOCtlV(const IOCtlVRequest& request)
int sslID = memory.Read_U32(BufferOut) - 1;
if (IsSSLIDValid(sslID))
{
- WiiSockMan& sm = WiiSockMan::GetInstance();
- sm.DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ);
+ m_ios.GetSocketManager()->DoSock(_SSL[sslID].sockfd, request, IOCTLV_NET_SSL_READ);
return std::nullopt;
}
else
diff --git a/Source/Core/Core/IOS/Network/Socket.cpp b/Source/Core/Core/IOS/Network/Socket.cpp
index ff60c09b20..9e1b45097e 100644
--- a/Source/Core/Core/IOS/Network/Socket.cpp
+++ b/Source/Core/Core/IOS/Network/Socket.cpp
@@ -85,6 +85,10 @@ static s32 TranslateErrorCode(s32 native_error, bool is_rw)
}
}
+WiiSockMan::WiiSockMan() = default;
+
+WiiSockMan::~WiiSockMan() = default;
+
// Don't use string! (see https://github.com/dolphin-emu/dolphin/pull/3143)
s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw)
{
@@ -96,7 +100,7 @@ s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw)
if (ret >= 0)
{
- WiiSockMan::GetInstance().SetLastNetError(ret);
+ SetLastNetError(ret);
return ret;
}
@@ -104,7 +108,7 @@ s32 WiiSockMan::GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw)
Common::DecodeNetworkError(error_code), ret);
const s32 return_value = TranslateErrorCode(error_code, is_rw);
- WiiSockMan::GetInstance().SetLastNetError(return_value);
+ SetLastNetError(return_value);
return return_value;
}
@@ -158,7 +162,7 @@ s32 WiiSocket::Shutdown(u32 how)
// Adjust pending operations
// Values based on https://dolp.in/pr8758 hwtest
- const s32 ret = WiiSockMan::GetNetErrorCode(shutdown(fd, how), "SO_SHUTDOWN", false);
+ const s32 ret = m_socket_manager.GetNetErrorCode(shutdown(fd, how), "SO_SHUTDOWN", false);
const bool shut_read = how == 0 || how == 2;
const bool shut_write = how == 1 || how == 2;
for (auto& op : pending_sockops)
@@ -198,11 +202,11 @@ s32 WiiSocket::CloseFd()
if (fd >= 0)
{
s32 ret = closesocket(fd);
- ReturnValue = WiiSockMan::GetNetErrorCode(ret, "CloseFd", false);
+ ReturnValue = m_socket_manager.GetNetErrorCode(ret, "CloseFd", false);
}
else
{
- ReturnValue = WiiSockMan::GetNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "CloseFd", false);
+ ReturnValue = m_socket_manager.GetNetErrorCode(EITHER(WSAENOTSOCK, EBADF), "CloseFd", false);
}
fd = -1;
@@ -273,7 +277,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
WiiSockMan::ToNativeAddrIn(addr, &local_name);
int ret = bind(fd, (sockaddr*)&local_name, sizeof(local_name));
- ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_BIND", false);
+ ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_BIND", false);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_BIND ({:08X}, {}:{}) = {}", wii_fd,
inet_ntoa(local_name.sin_addr), Common::swap16(local_name.sin_port), ret);
@@ -286,7 +290,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
WiiSockMan::ToNativeAddrIn(addr, &local_name);
int ret = connect(fd, (sockaddr*)&local_name, sizeof(local_name));
- ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_CONNECT", false);
+ ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_CONNECT", false);
UpdateConnectingState(ReturnValue);
INFO_LOG_FMT(IOS_NET, "IOCTL_SO_CONNECT ({:08x}, {}:{}) = {}", wii_fd,
@@ -312,7 +316,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
ret = static_cast(accept(fd, nullptr, nullptr));
}
- ReturnValue = WiiSockMan::GetInstance().AddSocket(ret, true);
+ ReturnValue = m_socket_manager.AddSocket(ret, true);
ioctl.Log("IOCTL_SO_ACCEPT", Common::Log::LogType::IOS_NET);
break;
@@ -593,7 +597,7 @@ void WiiSocket::Update(bool read, bool write, bool except)
auto* to = has_destaddr ? reinterpret_cast(&local_name) : nullptr;
socklen_t tolen = has_destaddr ? sizeof(sockaddr) : 0;
const int ret = sendto(fd, data, BufferInSize, flags, to, tolen);
- ReturnValue = WiiSockMan::GetNetErrorCode(ret, "SO_SENDTO", true);
+ ReturnValue = m_socket_manager.GetNetErrorCode(ret, "SO_SENDTO", true);
if (ret > 0)
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogWrite(data, ret, fd, to);
@@ -651,8 +655,8 @@ void WiiSocket::Update(bool read, bool write, bool except)
auto* from = BufferOutSize2 ? reinterpret_cast(&local_name) : nullptr;
socklen_t* fromlen = BufferOutSize2 ? &addrlen : nullptr;
const int ret = recvfrom(fd, data, data_len, flags, from, fromlen);
- ReturnValue =
- WiiSockMan::GetNetErrorCode(ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true);
+ ReturnValue = m_socket_manager.GetNetErrorCode(
+ ret, BufferOutSize2 ? "SO_RECVFROM" : "SO_RECV", true);
if (ret > 0)
system.GetPowerPC().GetDebugInterface().NetworkLogger()->LogRead(data, ret, fd, from);
@@ -862,7 +866,7 @@ s32 WiiSockMan::AddSocket(s32 fd, bool is_rw)
}
else
{
- WiiSocket& sock = WiiSockets[wii_fd];
+ WiiSocket& sock = WiiSockets.emplace(wii_fd, *this).first->second;
sock.SetFd(fd);
sock.SetWiiFd(wii_fd);
Core::System::GetInstance().GetPowerPC().GetDebugInterface().NetworkLogger()->OnNewSocket(fd);
diff --git a/Source/Core/Core/IOS/Network/Socket.h b/Source/Core/Core/IOS/Network/Socket.h
index 2a2350d752..6c236e38b3 100644
--- a/Source/Core/Core/IOS/Network/Socket.h
+++ b/Source/Core/Core/IOS/Network/Socket.h
@@ -174,10 +174,12 @@ struct WiiSockAddrIn
};
#pragma pack(pop)
+class WiiSockMan;
+
class WiiSocket
{
public:
- WiiSocket() = default;
+ explicit WiiSocket(WiiSockMan& socket_manager) : m_socket_manager(socket_manager) {}
WiiSocket(const WiiSocket&) = delete;
WiiSocket(WiiSocket&&) = default;
~WiiSocket();
@@ -225,6 +227,8 @@ private:
bool IsValid() const { return fd >= 0; }
bool IsTCP() const;
+ WiiSockMan& m_socket_manager;
+
s32 fd = -1;
s32 wii_fd = -1;
bool nonBlock = false;
@@ -251,14 +255,15 @@ public:
s64 timeout = 0;
};
- static s32 GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw);
- static char* DecodeError(s32 ErrorCode);
+ WiiSockMan();
+ WiiSockMan(const WiiSockMan&) = delete;
+ WiiSockMan& operator=(const WiiSockMan&) = delete;
+ WiiSockMan(WiiSockMan&&) = delete;
+ WiiSockMan& operator=(WiiSockMan&&) = delete;
+ ~WiiSockMan();
+
+ s32 GetNetErrorCode(s32 ret, std::string_view caller, bool is_rw);
- static WiiSockMan& GetInstance()
- {
- static WiiSockMan instance; // Guaranteed to be destroyed.
- return instance; // Instantiated on first use.
- }
void Update();
static void ToNativeAddrIn(const u8* from, sockaddr_in* to);
static void ToWiiAddrIn(const sockaddr_in& from, u8* to,
@@ -296,12 +301,6 @@ public:
void UpdateWantDeterminism(bool want);
private:
- WiiSockMan() = default;
- WiiSockMan(const WiiSockMan&) = delete;
- WiiSockMan& operator=(const WiiSockMan&) = delete;
- WiiSockMan(WiiSockMan&&) = delete;
- WiiSockMan& operator=(WiiSockMan&&) = delete;
-
void UpdatePollCommands();
std::unordered_map WiiSockets;
diff --git a/Source/Core/Core/NetPlayServer.cpp b/Source/Core/Core/NetPlayServer.cpp
index 8108b124ee..97f2b040ef 100644
--- a/Source/Core/Core/NetPlayServer.cpp
+++ b/Source/Core/Core/NetPlayServer.cpp
@@ -1721,7 +1721,15 @@ std::optional NetPlayServer::CollectSaveSyncInfo()
for (const u64 title : ios.GetES()->GetInstalledTitles())
{
auto save = WiiSave::MakeNandStorage(sync_info.configured_fs.get(), title);
- sync_info.wii_saves.emplace_back(title, std::move(save));
+ if (save && save->ReadHeader().has_value() && save->ReadBkHeader().has_value() &&
+ save->ReadFiles().has_value())
+ {
+ sync_info.wii_saves.emplace_back(title, std::move(save));
+ }
+ else
+ {
+ INFO_LOG_FMT(NETPLAY, "Skipping Wii save of title {:016x}.", title);
+ }
}
}
else if (sync_info.game->GetPlatform() == DiscIO::Platform::WiiDisc ||
diff --git a/Source/Core/Core/PowerPC/PPCCache.cpp b/Source/Core/Core/PowerPC/PPCCache.cpp
index d159eba1f2..03e5ef3a1a 100644
--- a/Source/Core/Core/PowerPC/PPCCache.cpp
+++ b/Source/Core/Core/PowerPC/PPCCache.cpp
@@ -3,6 +3,7 @@
#include "Core/PowerPC/PPCCache.h"
+#include
#include
#include "Common/ChunkFile.h"
@@ -99,9 +100,9 @@ void Cache::Reset()
valid.fill(0);
plru.fill(0);
modified.fill(0);
- lookup_table.fill(0xFF);
- lookup_table_ex.fill(0xFF);
- lookup_table_vmem.fill(0xFF);
+ std::fill(lookup_table.begin(), lookup_table.end(), 0xFF);
+ std::fill(lookup_table_ex.begin(), lookup_table_ex.end(), 0xFF);
+ std::fill(lookup_table_vmem.begin(), lookup_table_vmem.end(), 0xFF);
}
void InstructionCache::Reset()
@@ -112,8 +113,14 @@ void InstructionCache::Reset()
void Cache::Init()
{
+ auto& system = Core::System::GetInstance();
+ auto& memory = system.GetMemory();
+
data.fill({});
addrs.fill({});
+ lookup_table.resize(memory.GetRamSize() >> 5);
+ lookup_table_ex.resize(memory.GetExRamSize() >> 5);
+ lookup_table_vmem.resize(memory.GetFakeVMemSize() >> 5);
Reset();
}
@@ -160,6 +167,9 @@ void Cache::FlushAll()
void Cache::Invalidate(u32 addr)
{
+ auto& system = Core::System::GetInstance();
+ auto& memory = system.GetMemory();
+
auto [set, way] = GetCache(addr, true);
if (way == 0xff)
@@ -168,11 +178,11 @@ void Cache::Invalidate(u32 addr)
if (valid[set] & (1U << way))
{
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
valid[set] &= ~(1U << way);
modified[set] &= ~(1U << way);
@@ -195,11 +205,11 @@ void Cache::Flush(u32 addr)
memory.CopyToEmu((addr & ~0x1f), reinterpret_cast(data[set][way].data()), 32);
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
valid[set] &= ~(1U << way);
modified[set] &= ~(1U << way);
@@ -222,15 +232,15 @@ std::pair Cache::GetCache(u32 addr, bool locked)
if (addr & CACHE_VMEM_BIT)
{
- way = lookup_table_vmem[(addr >> 5) & 0xfffff];
+ way = lookup_table_vmem[(addr & memory.GetFakeVMemMask()) >> 5];
}
else if (addr & CACHE_EXRAM_BIT)
{
- way = lookup_table_ex[(addr >> 5) & 0x1fffff];
+ way = lookup_table_ex[(addr & memory.GetExRamMask()) >> 5];
}
else
{
- way = lookup_table[(addr >> 5) & 0xfffff];
+ way = lookup_table[(addr & memory.GetRamMask()) >> 5];
}
// load to the cache
@@ -249,22 +259,22 @@ std::pair Cache::GetCache(u32 addr, bool locked)
memory.CopyToEmu(addrs[set][way], reinterpret_cast(data[set][way].data()), 32);
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
}
// load
memory.CopyFromEmu(reinterpret_cast(data[set][way].data()), (addr & ~0x1f), 32);
if (addr & CACHE_VMEM_BIT)
- lookup_table_vmem[(addr >> 5) & 0xfffff] = way;
+ lookup_table_vmem[(addr & memory.GetFakeVMemMask()) >> 5] = way;
else if (addr & CACHE_EXRAM_BIT)
- lookup_table_ex[(addr >> 5) & 0x1fffff] = way;
+ lookup_table_ex[(addr & memory.GetExRamMask()) >> 5] = way;
else
- lookup_table[(addr >> 5) & 0xfffff] = way;
+ lookup_table[(addr & memory.GetRamMask()) >> 5] = way;
addrs[set][way] = addr;
valid[set] |= (1 << way);
@@ -341,6 +351,9 @@ void Cache::Write(u32 addr, const void* buffer, u32 len, bool locked)
void Cache::DoState(PointerWrap& p)
{
+ auto& system = Core::System::GetInstance();
+ auto& memory = system.GetMemory();
+
if (p.IsReadMode())
{
// Clear valid parts of the lookup tables (this is done instead of using fill(0xff) to avoid
@@ -352,11 +365,11 @@ void Cache::DoState(PointerWrap& p)
if ((valid[set] & (1 << way)) != 0)
{
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
}
}
}
@@ -378,11 +391,11 @@ void Cache::DoState(PointerWrap& p)
if ((valid[set] & (1 << way)) != 0)
{
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
}
}
}
@@ -405,6 +418,7 @@ u32 InstructionCache::ReadInstruction(u32 addr)
void InstructionCache::Invalidate(u32 addr)
{
auto& system = Core::System::GetInstance();
+ auto& memory = system.GetMemory();
auto& ppc_state = system.GetPPCState();
if (!HID0(ppc_state).ICE || m_disable_icache)
return;
@@ -416,11 +430,11 @@ void InstructionCache::Invalidate(u32 addr)
if (valid[set] & (1U << way))
{
if (addrs[set][way] & CACHE_VMEM_BIT)
- lookup_table_vmem[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table_vmem[(addrs[set][way] & memory.GetFakeVMemMask()) >> 5] = 0xff;
else if (addrs[set][way] & CACHE_EXRAM_BIT)
- lookup_table_ex[(addrs[set][way] >> 5) & 0x1fffff] = 0xff;
+ lookup_table_ex[(addrs[set][way] & memory.GetExRamMask()) >> 5] = 0xff;
else
- lookup_table[(addrs[set][way] >> 5) & 0xfffff] = 0xff;
+ lookup_table[(addrs[set][way] & memory.GetRamMask()) >> 5] = 0xff;
}
}
valid[set] = 0;
diff --git a/Source/Core/Core/PowerPC/PPCCache.h b/Source/Core/Core/PowerPC/PPCCache.h
index 49843c9b74..8214b116af 100644
--- a/Source/Core/Core/PowerPC/PPCCache.h
+++ b/Source/Core/Core/PowerPC/PPCCache.h
@@ -5,6 +5,7 @@
#include
#include
+#include
#include "Common/CommonTypes.h"
@@ -36,9 +37,9 @@ struct Cache
// Note: This is only for performance purposes; this same data could be computed at runtime
// from the tags and valid fields (and that's how it's done on the actual cache)
- std::array lookup_table{};
- std::array lookup_table_ex{};
- std::array lookup_table_vmem{};
+ std::vector lookup_table{};
+ std::vector lookup_table_ex{};
+ std::vector lookup_table_vmem{};
void Store(u32 addr);
void Invalidate(u32 addr);
diff --git a/Source/Core/Core/State.cpp b/Source/Core/Core/State.cpp
index a82da71663..c298dd121e 100644
--- a/Source/Core/Core/State.cpp
+++ b/Source/Core/Core/State.cpp
@@ -96,7 +96,7 @@ static size_t s_state_writes_in_queue;
static std::condition_variable s_state_write_queue_is_empty;
// Don't forget to increase this after doing changes on the savestate system
-constexpr u32 STATE_VERSION = 161; // Last changed in PR 11655
+constexpr u32 STATE_VERSION = 162; // Last changed in PR 11767
// Maps savestate versions to Dolphin versions.
// Versions after 42 don't need to be added to this list,
diff --git a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
index 6439a061ba..b9504e64ff 100644
--- a/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
+++ b/Source/Core/DolphinQt/Debugger/NetworkWidget.cpp
@@ -24,8 +24,10 @@
#include "Common/FileUtil.h"
#include "Core/Config/MainSettings.h"
+#include "Core/Core.h"
#include "Core/IOS/Network/SSL.h"
#include "Core/IOS/Network/Socket.h"
+#include "Core/System.h"
#include "DolphinQt/Host.h"
#include "DolphinQt/Settings.h"
@@ -95,9 +97,8 @@ QTableWidgetItem* GetSocketState(s32 host_fd)
return new QTableWidgetItem(QTableWidget::tr("Unbound"));
}
-QTableWidgetItem* GetSocketBlocking(s32 wii_fd)
+static QTableWidgetItem* GetSocketBlocking(const IOS::HLE::WiiSockMan& socket_manager, s32 wii_fd)
{
- const auto& socket_manager = IOS::HLE::WiiSockMan::GetInstance();
if (socket_manager.GetHostSocket(wii_fd) < 0)
return new QTableWidgetItem();
const bool is_blocking = socket_manager.IsSocketBlocking(wii_fd);
@@ -238,16 +239,27 @@ void NetworkWidget::Update()
if (!isVisible())
return;
+ // needed because there's a race condition on the IOS instance otherwise
+ Core::CPUThreadGuard guard(Core::System::GetInstance());
+
+ auto* ios = IOS::HLE::GetIOS();
+ if (!ios)
+ return;
+
+ auto socket_manager = ios->GetSocketManager();
+ if (!socket_manager)
+ return;
+
m_socket_table->setRowCount(0);
for (u32 wii_fd = 0; wii_fd < IOS::HLE::WII_SOCKET_FD_MAX; wii_fd++)
{
m_socket_table->insertRow(wii_fd);
- const s32 host_fd = IOS::HLE::WiiSockMan::GetInstance().GetHostSocket(wii_fd);
+ const s32 host_fd = socket_manager->GetHostSocket(wii_fd);
m_socket_table->setItem(wii_fd, 0, new QTableWidgetItem(QString::number(wii_fd)));
m_socket_table->setItem(wii_fd, 1, GetSocketDomain(host_fd));
m_socket_table->setItem(wii_fd, 2, GetSocketType(host_fd));
m_socket_table->setItem(wii_fd, 3, GetSocketState(host_fd));
- m_socket_table->setItem(wii_fd, 4, GetSocketBlocking(wii_fd));
+ m_socket_table->setItem(wii_fd, 4, GetSocketBlocking(*socket_manager, wii_fd));
m_socket_table->setItem(wii_fd, 5, GetSocketName(host_fd));
}
m_socket_table->resizeColumnsToContents();
diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.cpp b/Source/Core/VideoBackends/OGL/OGLConfig.cpp
index ab31592bd2..e5e1bff83f 100644
--- a/Source/Core/VideoBackends/OGL/OGLConfig.cpp
+++ b/Source/Core/VideoBackends/OGL/OGLConfig.cpp
@@ -333,11 +333,7 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_ogl_config.bSupportsDebug =
GLExtensions::Supports("GL_KHR_debug") || GLExtensions::Supports("GL_ARB_debug_output");
g_ogl_config.bSupportsTextureStorage = GLExtensions::Supports("GL_ARB_texture_storage");
- g_ogl_config.bSupports3DTextureStorageMultisample =
- GLExtensions::Supports("GL_ARB_texture_storage_multisample") ||
- GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array");
- g_ogl_config.bSupports2DTextureStorageMultisample =
- GLExtensions::Supports("GL_ARB_texture_storage_multisample");
+ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageNone;
g_ogl_config.bSupportsImageLoadStore = GLExtensions::Supports("GL_ARB_shader_image_load_store");
g_ogl_config.bSupportsConservativeDepth = GLExtensions::Supports("GL_ARB_conservative_depth");
g_ogl_config.bSupportsAniso = GLExtensions::Supports("GL_EXT_texture_filter_anisotropic");
@@ -368,9 +364,10 @@ bool PopulateConfig(GLContext* m_main_gl_context)
if (m_main_gl_context->IsGLES())
{
- g_ogl_config.SupportedESPointSize = GLExtensions::Supports("GL_OES_geometry_point_size") ? 1 :
- GLExtensions::Supports("GL_EXT_geometry_point_size") ? 2 :
- 0;
+ g_ogl_config.SupportedESPointSize =
+ GLExtensions::Supports("GL_OES_geometry_point_size") ? EsPointSizeType::PointSizeOes :
+ GLExtensions::Supports("GL_EXT_geometry_point_size") ? EsPointSizeType::PointSizeExt :
+ EsPointSizeType::PointSizeNone;
g_ogl_config.SupportedESTextureBuffer =
GLExtensions::Supports("VERSION_GLES_3_2") ? EsTexbufType::TexbufCore :
GLExtensions::Supports("GL_OES_texture_buffer") ? EsTexbufType::TexbufOes :
@@ -410,21 +407,16 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_Config.backend_info.bSupportsGeometryShaders = g_ogl_config.bSupportsAEP;
g_Config.backend_info.bSupportsComputeShaders = true;
g_Config.backend_info.bSupportsGSInstancing =
- g_Config.backend_info.bSupportsGeometryShaders && g_ogl_config.SupportedESPointSize > 0;
+ g_Config.backend_info.bSupportsGeometryShaders &&
+ g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone;
g_Config.backend_info.bSupportsSSAA = g_ogl_config.bSupportsAEP;
g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true;
g_ogl_config.bSupportsMSAA = true;
g_ogl_config.bSupportsTextureStorage = true;
- g_ogl_config.bSupports2DTextureStorageMultisample = true;
+ if (GLExtensions::Supports("GL_OES_texture_storage_multisample_2d_array"))
+ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageOes;
g_Config.backend_info.bSupportsBitfield = true;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = g_ogl_config.bSupportsAEP;
- if (g_ActiveConfig.stereo_mode != StereoMode::Off && g_ActiveConfig.iMultisamples > 1 &&
- !g_ogl_config.bSupports3DTextureStorageMultisample)
- {
- // GLES 3.1 can't support stereo rendering and MSAA
- OSD::AddMessage("MSAA Stereo rendering isn't supported by your GPU.", 10000);
- Config::SetCurrent(Config::GFX_MSAA, UINT32_C(1));
- }
}
else
{
@@ -434,7 +426,8 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsGeometryShaders = true;
g_Config.backend_info.bSupportsComputeShaders = true;
- g_Config.backend_info.bSupportsGSInstancing = g_ogl_config.SupportedESPointSize > 0;
+ g_Config.backend_info.bSupportsGSInstancing =
+ g_ogl_config.SupportedESPointSize != EsPointSizeType::PointSizeNone;
g_Config.backend_info.bSupportsPaletteConversion = true;
g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsFragmentStoresAndAtomics = true;
@@ -443,8 +436,7 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_ogl_config.bSupportsDebug = true;
g_ogl_config.bSupportsMSAA = true;
g_ogl_config.bSupportsTextureStorage = true;
- g_ogl_config.bSupports2DTextureStorageMultisample = true;
- g_ogl_config.bSupports3DTextureStorageMultisample = true;
+ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore;
g_Config.backend_info.bSupportsBitfield = true;
g_Config.backend_info.bSupportsDynamicSamplerIndexing = true;
g_Config.backend_info.bSupportsSettingObjectNames = true;
@@ -452,6 +444,9 @@ bool PopulateConfig(GLContext* m_main_gl_context)
}
else
{
+ if (GLExtensions::Supports("GL_ARB_texture_storage_multisample"))
+ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore;
+
if (GLExtensions::Version() < 300)
{
PanicAlertFmtT("GPU: OGL ERROR: Need at least GLSL 1.30\n"
@@ -498,6 +493,7 @@ bool PopulateConfig(GLContext* m_main_gl_context)
g_ogl_config.eSupportedGLSLVersion = Glsl430;
}
g_ogl_config.bSupportsTextureStorage = true;
+ g_ogl_config.SupportedMultisampleTexStorage = MultisampleTexStorageType::TexStorageCore;
g_ogl_config.bSupportsImageLoadStore = true;
g_Config.backend_info.bSupportsSSAA = true;
g_Config.backend_info.bSupportsSettingObjectNames = true;
diff --git a/Source/Core/VideoBackends/OGL/OGLConfig.h b/Source/Core/VideoBackends/OGL/OGLConfig.h
index 570e1954eb..4929901b09 100644
--- a/Source/Core/VideoBackends/OGL/OGLConfig.h
+++ b/Source/Core/VideoBackends/OGL/OGLConfig.h
@@ -22,6 +22,14 @@ enum GlslVersion
GlslEs310, // GLES 3.1
GlslEs320, // GLES 3.2
};
+
+enum class EsPointSizeType
+{
+ PointSizeNone,
+ PointSizeOes,
+ PointSizeExt,
+};
+
enum class EsTexbufType
{
TexbufNone,
@@ -37,6 +45,13 @@ enum class EsFbFetchType
FbFetchArm,
};
+enum class MultisampleTexStorageType
+{
+ TexStorageNone,
+ TexStorageCore,
+ TexStorageOes,
+};
+
// ogl-only config, so not in VideoConfig.h
struct VideoConfig
{
@@ -51,11 +66,10 @@ struct VideoConfig
bool bSupportsAEP;
bool bSupportsDebug;
bool bSupportsCopySubImage;
- u8 SupportedESPointSize;
+ EsPointSizeType SupportedESPointSize;
EsTexbufType SupportedESTextureBuffer;
bool bSupportsTextureStorage;
- bool bSupports2DTextureStorageMultisample;
- bool bSupports3DTextureStorageMultisample;
+ MultisampleTexStorageType SupportedMultisampleTexStorage;
bool bSupportsConservativeDepth;
bool bSupportsImageLoadStore;
bool bSupportsAniso;
diff --git a/Source/Core/VideoBackends/OGL/OGLTexture.cpp b/Source/Core/VideoBackends/OGL/OGLTexture.cpp
index 4e90211c59..d3274a3528 100644
--- a/Source/Core/VideoBackends/OGL/OGLTexture.cpp
+++ b/Source/Core/VideoBackends/OGL/OGLTexture.cpp
@@ -130,12 +130,18 @@ OGLTexture::OGLTexture(const TextureConfig& tex_config, std::string_view name)
GLenum gl_internal_format = GetGLInternalFormatForTextureFormat(m_config.format, true);
if (tex_config.IsMultisampled())
{
- if (g_ogl_config.bSupportsTextureStorage)
+ ASSERT(g_ogl_config.bSupportsMSAA);
+ if (g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone)
+ {
glTexStorage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
m_config.height, m_config.layers, GL_FALSE);
+ }
else
+ {
+ ASSERT(!g_ogl_config.bIsES);
glTexImage3DMultisample(target, tex_config.samples, gl_internal_format, m_config.width,
m_config.height, m_config.layers, GL_FALSE);
+ }
}
else if (g_ogl_config.bSupportsTextureStorage)
{
diff --git a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
index eff1497e7f..a149c9fad0 100644
--- a/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
+++ b/Source/Core/VideoBackends/OGL/ProgramShaderCache.cpp
@@ -664,12 +664,13 @@ void ProgramShaderCache::CreateHeader()
std::string SupportedESTextureBuffer;
switch (g_ogl_config.SupportedESPointSize)
{
- case 1:
+ case EsPointSizeType::PointSizeOes:
SupportedESPointSize = "#extension GL_OES_geometry_point_size : enable";
break;
- case 2:
+ case EsPointSizeType::PointSizeExt:
SupportedESPointSize = "#extension GL_EXT_geometry_point_size : enable";
break;
+ case EsPointSizeType::PointSizeNone:
default:
SupportedESPointSize = "";
break;
@@ -721,6 +722,13 @@ void ProgramShaderCache::CreateHeader()
break;
}
+ // The sampler2DMSArray keyword is reserved in GLSL ES 3.0 and 3.1, but is available in 3.2 and
+ // with GL_OES_texture_storage_multisample_2d_array for 3.1.
+ // See https://bugs.dolphin-emu.org/issues/13198.
+ const bool use_multisample_2d_array_precision =
+ v >= GlslEs320 ||
+ g_ogl_config.SupportedMultisampleTexStorage != MultisampleTexStorageType::TexStorageNone;
+
std::string shader_shuffle_string;
if (g_ogl_config.bSupportsKHRShaderSubgroup)
{
@@ -758,6 +766,7 @@ void ProgramShaderCache::CreateHeader()
"{}\n" // shader thread shuffle
"{}\n" // derivative control
"{}\n" // query levels
+ "{}\n" // OES multisample texture storage
// Precision defines for GLSL ES
"{}\n"
@@ -843,12 +852,18 @@ void ProgramShaderCache::CreateHeader()
g_ActiveConfig.backend_info.bSupportsTextureQueryLevels ?
"#extension GL_ARB_texture_query_levels : enable" :
"",
+ // Note: GL_ARB_texture_storage_multisample doesn't have an #extension, as it doesn't
+ // need to change GLSL, but on GLES 3.1 sampler2DMSArray is a reserved keyword unless
+ // the extension is enabled. Thus, we don't need to check TexStorageCore/have an ARB version.
+ g_ogl_config.SupportedMultisampleTexStorage == MultisampleTexStorageType::TexStorageOes ?
+ "#extension GL_OES_texture_storage_multisample_2d_array : enable" :
+ "",
is_glsles ? "precision highp float;" : "", is_glsles ? "precision highp int;" : "",
is_glsles ? "precision highp sampler2DArray;" : "",
(is_glsles && g_ActiveConfig.backend_info.bSupportsPaletteConversion) ?
"precision highp usamplerBuffer;" :
"",
- v > GlslEs300 ? "precision highp sampler2DMSArray;" : "",
+ use_multisample_2d_array_precision ? "precision highp sampler2DMSArray;" : "",
v >= GlslEs310 ? "precision highp image2DArray;" : "");
}