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;" : ""); }