diff options
Diffstat (limited to 'src')
27 files changed, 384 insertions, 119 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index 57922b51c..b18a2a2f5 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -53,6 +53,8 @@ add_library(common STATIC div_ceil.h dynamic_library.cpp dynamic_library.h + error.cpp + error.h fiber.cpp fiber.h fs/file.cpp @@ -88,7 +90,6 @@ add_library(common STATIC microprofile.cpp microprofile.h microprofileui.h - misc.cpp nvidia_flags.cpp nvidia_flags.h page_table.cpp diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index 53bd7da60..1e74d6930 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -4,9 +4,8 @@ #pragma once -#include <algorithm> #include <array> -#include <string> +#include <iterator> #if !defined(ARCHITECTURE_x86_64) #include <cstdlib> // for exit @@ -49,16 +48,6 @@ __declspec(dllimport) void __stdcall DebugBreak(void); #endif // _MSC_VER ndef -// Generic function to get last error message. -// Call directly after the command or use the error num. -// This function might change the error code. -// Defined in misc.cpp. -[[nodiscard]] std::string GetLastErrorMsg(); - -// Like GetLastErrorMsg(), but passing an explicit error code. -// Defined in misc.cpp. -[[nodiscard]] std::string NativeErrorToString(int e); - #define DECLARE_ENUM_FLAG_OPERATORS(type) \ [[nodiscard]] constexpr type operator|(type a, type b) noexcept { \ using T = std::underlying_type_t<type>; \ diff --git a/src/common/misc.cpp b/src/common/error.cpp index 495385b9e..d4455e310 100644 --- a/src/common/misc.cpp +++ b/src/common/error.cpp @@ -10,7 +10,9 @@ #include <cstring> #endif -#include "common/common_funcs.h" +#include "common/error.h" + +namespace Common { std::string NativeErrorToString(int e) { #ifdef _WIN32 @@ -50,3 +52,5 @@ std::string GetLastErrorMsg() { return NativeErrorToString(errno); #endif } + +} // namespace Common diff --git a/src/common/error.h b/src/common/error.h new file mode 100644 index 000000000..e084d4b0f --- /dev/null +++ b/src/common/error.h @@ -0,0 +1,21 @@ +// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <string> + +namespace Common { + +// Generic function to get last error message. +// Call directly after the command or use the error num. +// This function might change the error code. +// Defined in error.cpp. +[[nodiscard]] std::string GetLastErrorMsg(); + +// Like GetLastErrorMsg(), but passing an explicit error code. +// Defined in error.cpp. +[[nodiscard]] std::string NativeErrorToString(int e); + +} // namespace Common diff --git a/src/common/thread.cpp b/src/common/thread.cpp index d2c1ac60d..946a1114d 100644 --- a/src/common/thread.cpp +++ b/src/common/thread.cpp @@ -2,7 +2,9 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/common_funcs.h" +#include <string> + +#include "common/error.h" #include "common/logging/log.h" #include "common/thread.h" #ifdef __APPLE__ @@ -21,8 +23,6 @@ #include <unistd.h> #endif -#include <string> - #ifdef __FreeBSD__ #define cpu_set_t cpuset_t #endif diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index 87d47e2e5..7140d0db8 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt @@ -263,6 +263,8 @@ add_library(core STATIC hle/service/acc/acc_u0.h hle/service/acc/acc_u1.cpp hle/service/acc/acc_u1.h + hle/service/acc/async_context.cpp + hle/service/acc/async_context.h hle/service/acc/errors.h hle/service/acc/profile_manager.cpp hle/service/acc/profile_manager.h diff --git a/src/core/file_sys/kernel_executable.h b/src/core/file_sys/kernel_executable.h index 044c554d3..79ca82f8b 100644 --- a/src/core/file_sys/kernel_executable.h +++ b/src/core/file_sys/kernel_executable.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <string> #include <vector> #include "common/common_funcs.h" diff --git a/src/core/hle/api_version.h b/src/core/hle/api_version.h index 43d5670a9..626e30753 100644 --- a/src/core/hle/api_version.h +++ b/src/core/hle/api_version.h @@ -28,13 +28,20 @@ constexpr char DISPLAY_TITLE[] = "NintendoSDK Firmware for NX 12.1.0-1.0"; // Atmosphere version constants. -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 0; -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 19; -constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 5; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MAJOR = 1; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MINOR = 0; +constexpr u8 ATMOSPHERE_RELEASE_VERSION_MICRO = 0; + +constexpr u32 AtmosphereTargetFirmwareWithRevision(u8 major, u8 minor, u8 micro, u8 rev) { + return u32{major} << 24 | u32{minor} << 16 | u32{micro} << 8 | u32{rev}; +} + +constexpr u32 AtmosphereTargetFirmware(u8 major, u8 minor, u8 micro) { + return AtmosphereTargetFirmwareWithRevision(major, minor, micro, 0); +} constexpr u32 GetTargetFirmware() { - return u32{HOS_VERSION_MAJOR} << 24 | u32{HOS_VERSION_MINOR} << 16 | - u32{HOS_VERSION_MICRO} << 8 | 0U; + return AtmosphereTargetFirmware(HOS_VERSION_MAJOR, HOS_VERSION_MINOR, HOS_VERSION_MICRO); } } // namespace HLE::ApiVersion diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h index 3a6db0b1c..901d43da9 100644 --- a/src/core/hle/kernel/kernel.h +++ b/src/core/hle/kernel/kernel.h @@ -5,6 +5,7 @@ #pragma once #include <array> +#include <functional> #include <memory> #include <string> #include <unordered_map> diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 882fc1492..6d9ec0a8a 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp @@ -23,6 +23,7 @@ #include "core/hle/service/acc/acc_su.h" #include "core/hle/service/acc/acc_u0.h" #include "core/hle/service/acc/acc_u1.h" +#include "core/hle/service/acc/async_context.h" #include "core/hle/service/acc/errors.h" #include "core/hle/service/acc/profile_manager.h" #include "core/hle/service/glue/arp.h" @@ -454,22 +455,6 @@ public: : IProfileCommon{system_, "IProfileEditor", true, user_id_, profile_manager_} {} }; -class IAsyncContext final : public ServiceFramework<IAsyncContext> { -public: - explicit IAsyncContext(Core::System& system_) : ServiceFramework{system_, "IAsyncContext"} { - // clang-format off - static const FunctionInfo functions[] = { - {0, nullptr, "GetSystemEvent"}, - {1, nullptr, "Cancel"}, - {2, nullptr, "HasDone"}, - {3, nullptr, "GetResult"}, - }; - // clang-format on - - RegisterHandlers(functions); - } -}; - class ISessionObject final : public ServiceFramework<ISessionObject> { public: explicit ISessionObject(Core::System& system_, Common::UUID) @@ -504,16 +489,44 @@ public: } }; +class EnsureTokenIdCacheAsyncInterface final : public IAsyncContext { +public: + explicit EnsureTokenIdCacheAsyncInterface(Core::System& system_) : IAsyncContext{system_} { + MarkComplete(); + } + ~EnsureTokenIdCacheAsyncInterface() = default; + + void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); + } + +protected: + bool IsComplete() const override { + return true; + } + + void Cancel() override {} + + ResultCode GetResult() const override { + return ResultSuccess; + } +}; + class IManagerForApplication final : public ServiceFramework<IManagerForApplication> { public: explicit IManagerForApplication(Core::System& system_, Common::UUID user_id_) - : ServiceFramework{system_, "IManagerForApplication"}, user_id{user_id_} { + : ServiceFramework{system_, "IManagerForApplication"}, + ensure_token_id{std::make_shared<EnsureTokenIdCacheAsyncInterface>(system)}, + user_id{user_id_} { // clang-format off static const FunctionInfo functions[] = { {0, &IManagerForApplication::CheckAvailability, "CheckAvailability"}, {1, &IManagerForApplication::GetAccountId, "GetAccountId"}, - {2, nullptr, "EnsureIdTokenCacheAsync"}, - {3, nullptr, "LoadIdTokenCache"}, + {2, &IManagerForApplication::EnsureIdTokenCacheAsync, "EnsureIdTokenCacheAsync"}, + {3, &IManagerForApplication::LoadIdTokenCache, "LoadIdTokenCache"}, {130, &IManagerForApplication::GetNintendoAccountUserResourceCacheForApplication, "GetNintendoAccountUserResourceCacheForApplication"}, {150, nullptr, "CreateAuthorizationRequest"}, {160, &IManagerForApplication::StoreOpenContext, "StoreOpenContext"}, @@ -540,6 +553,20 @@ private: rb.PushRaw<u64>(user_id.GetNintendoID()); } + void EnsureIdTokenCacheAsync(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + IPC::ResponseBuilder rb{ctx, 2, 0, 1}; + rb.Push(ResultSuccess); + rb.PushIpcInterface(ensure_token_id); + } + + void LoadIdTokenCache(Kernel::HLERequestContext& ctx) { + LOG_WARNING(Service_ACC, "(STUBBED) called"); + + ensure_token_id->LoadIdTokenCache(ctx); + } + void GetNintendoAccountUserResourceCacheForApplication(Kernel::HLERequestContext& ctx) { LOG_WARNING(Service_ACC, "(STUBBED) called"); @@ -562,6 +589,7 @@ private: rb.Push(ResultSuccess); } + std::shared_ptr<EnsureTokenIdCacheAsyncInterface> ensure_token_id{}; Common::UUID user_id{Common::INVALID_UUID}; }; diff --git a/src/core/hle/service/acc/async_context.cpp b/src/core/hle/service/acc/async_context.cpp new file mode 100644 index 000000000..459323132 --- /dev/null +++ b/src/core/hle/service/acc/async_context.cpp @@ -0,0 +1,68 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#include "core/core.h" +#include "core/hle/ipc_helpers.h" +#include "core/hle/service/acc/async_context.h" + +namespace Service::Account { +IAsyncContext::IAsyncContext(Core::System& system_) + : ServiceFramework{system_, "IAsyncContext"}, compeletion_event{system_.Kernel()} { + + Kernel::KAutoObject::Create(std::addressof(compeletion_event)); + compeletion_event.Initialize("IAsyncContext:CompletionEvent"); + + // clang-format off + static const FunctionInfo functions[] = { + {0, &IAsyncContext::GetSystemEvent, "GetSystemEvent"}, + {1, &IAsyncContext::Cancel, "Cancel"}, + {2, &IAsyncContext::HasDone, "HasDone"}, + {3, &IAsyncContext::GetResult, "GetResult"}, + }; + // clang-format on + + RegisterHandlers(functions); +} + +void IAsyncContext::GetSystemEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(compeletion_event.GetReadableEvent()); +} + +void IAsyncContext::Cancel(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + Cancel(); + MarkComplete(); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + +void IAsyncContext::HasDone(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + is_complete.store(IsComplete()); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(ResultSuccess); + rb.Push(is_complete.load()); +} + +void IAsyncContext::GetResult(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_ACC, "called"); + + IPC::ResponseBuilder rb{ctx, 3}; + rb.Push(GetResult()); +} + +void IAsyncContext::MarkComplete() { + is_complete.store(true); + compeletion_event.GetWritableEvent().Signal(); +} + +} // namespace Service::Account diff --git a/src/core/hle/service/acc/async_context.h b/src/core/hle/service/acc/async_context.h new file mode 100644 index 000000000..c694b4946 --- /dev/null +++ b/src/core/hle/service/acc/async_context.h @@ -0,0 +1,37 @@ +// Copyright 2021 yuzu emulator team +// Licensed under GPLv2 or any later version +// Refer to the license.txt file included. + +#pragma once + +#include <atomic> +#include "core/hle/kernel/k_event.h" +#include "core/hle/service/service.h" + +namespace Core { +class System; +} + +namespace Service::Account { + +class IAsyncContext : public ServiceFramework<IAsyncContext> { +public: + explicit IAsyncContext(Core::System& system_); + + void GetSystemEvent(Kernel::HLERequestContext& ctx); + void Cancel(Kernel::HLERequestContext& ctx); + void HasDone(Kernel::HLERequestContext& ctx); + void GetResult(Kernel::HLERequestContext& ctx); + +protected: + virtual bool IsComplete() const = 0; + virtual void Cancel() = 0; + virtual ResultCode GetResult() const = 0; + + void MarkComplete(); + + std::atomic<bool> is_complete{false}; + Kernel::KEvent compeletion_event; +}; + +} // namespace Service::Account diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index a538f82e3..c3ac73131 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp @@ -1270,7 +1270,8 @@ void ILibraryAppletCreator::CreateHandleStorage(Kernel::HLERequestContext& ctx) IApplicationFunctions::IApplicationFunctions(Core::System& system_) : ServiceFramework{system_, "IApplicationFunctions"}, gpu_error_detected_event{system.Kernel()}, friend_invitation_storage_channel_event{system.Kernel()}, - health_warning_disappeared_system_event{system.Kernel()} { + notification_storage_channel_event{system.Kernel()}, health_warning_disappeared_system_event{ + system.Kernel()} { // clang-format off static const FunctionInfo functions[] = { {1, &IApplicationFunctions::PopLaunchParameter, "PopLaunchParameter"}, @@ -1322,7 +1323,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) {131, nullptr, "SetDelayTimeToAbortOnGpuError"}, {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, {141, &IApplicationFunctions::TryPopFromFriendInvitationStorageChannel, "TryPopFromFriendInvitationStorageChannel"}, - {150, nullptr, "GetNotificationStorageChannelEvent"}, + {150, &IApplicationFunctions::GetNotificationStorageChannelEvent, "GetNotificationStorageChannelEvent"}, {151, nullptr, "TryPopFromNotificationStorageChannel"}, {160, &IApplicationFunctions::GetHealthWarningDisappearedSystemEvent, "GetHealthWarningDisappearedSystemEvent"}, {170, nullptr, "SetHdcpAuthenticationActivated"}, @@ -1340,11 +1341,14 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) Kernel::KAutoObject::Create(std::addressof(gpu_error_detected_event)); Kernel::KAutoObject::Create(std::addressof(friend_invitation_storage_channel_event)); + Kernel::KAutoObject::Create(std::addressof(notification_storage_channel_event)); Kernel::KAutoObject::Create(std::addressof(health_warning_disappeared_system_event)); gpu_error_detected_event.Initialize("IApplicationFunctions:GpuErrorDetectedSystemEvent"); friend_invitation_storage_channel_event.Initialize( "IApplicationFunctions:FriendInvitationStorageChannelEvent"); + notification_storage_channel_event.Initialize( + "IApplicationFunctions:NotificationStorageChannelEvent"); health_warning_disappeared_system_event.Initialize( "IApplicationFunctions:HealthWarningDisappearedSystemEvent"); } @@ -1762,6 +1766,14 @@ void IApplicationFunctions::TryPopFromFriendInvitationStorageChannel( rb.Push(ERR_NO_DATA_IN_CHANNEL); } +void IApplicationFunctions::GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx) { + LOG_DEBUG(Service_AM, "called"); + + IPC::ResponseBuilder rb{ctx, 2, 1}; + rb.Push(ResultSuccess); + rb.PushCopyObjects(notification_storage_channel_event.GetReadableEvent()); +} + void IApplicationFunctions::GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx) { LOG_DEBUG(Service_AM, "called"); diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 184030a8e..c13aa5787 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h @@ -295,6 +295,7 @@ private: void GetGpuErrorDetectedSystemEvent(Kernel::HLERequestContext& ctx); void GetFriendInvitationStorageChannelEvent(Kernel::HLERequestContext& ctx); void TryPopFromFriendInvitationStorageChannel(Kernel::HLERequestContext& ctx); + void GetNotificationStorageChannelEvent(Kernel::HLERequestContext& ctx); void GetHealthWarningDisappearedSystemEvent(Kernel::HLERequestContext& ctx); bool launch_popped_application_specific = false; @@ -302,6 +303,7 @@ private: s32 previous_program_index{-1}; Kernel::KEvent gpu_error_detected_event; Kernel::KEvent friend_invitation_storage_channel_event; + Kernel::KEvent notification_storage_channel_event; Kernel::KEvent health_warning_disappeared_system_event; }; diff --git a/src/core/hle/service/filesystem/filesystem.cpp b/src/core/hle/service/filesystem/filesystem.cpp index 4a9b13e45..db17d61e4 100644 --- a/src/core/hle/service/filesystem/filesystem.cpp +++ b/src/core/hle/service/filesystem/filesystem.cpp @@ -97,14 +97,19 @@ ResultCode VfsDirectoryServiceWrapper::DeleteFile(const std::string& path_) cons ResultCode VfsDirectoryServiceWrapper::CreateDirectory(const std::string& path_) const { std::string path(Common::FS::SanitizePath(path_)); - auto dir = GetDirectoryRelativeWrapped(backing, Common::FS::GetParentPath(path)); - if (dir == nullptr || Common::FS::GetFilename(Common::FS::GetParentPath(path)).empty()) { - dir = backing; - } - auto new_dir = dir->CreateSubdirectory(Common::FS::GetFilename(path)); - if (new_dir == nullptr) { - // TODO(DarkLordZach): Find a better error code for this - return ResultUnknown; + const auto components = Common::FS::SplitPathComponents(path); + std::string relative_path; + for (const auto& component : components) { + // Skip empty path components + if (component.empty()) { + continue; + } + relative_path = Common::FS::SanitizePath(relative_path + '/' + component); + auto new_dir = backing->CreateSubdirectory(relative_path); + if (new_dir == nullptr) { + // TODO(DarkLordZach): Find a better error code for this + return ResultUnknown; + } } return ResultSuccess; } diff --git a/src/core/hle/service/hid/controllers/touchscreen.h b/src/core/hle/service/hid/controllers/touchscreen.h index ef2becefd..8e9b40c0a 100644 --- a/src/core/hle/service/hid/controllers/touchscreen.h +++ b/src/core/hle/service/hid/controllers/touchscreen.h @@ -15,6 +15,20 @@ namespace Service::HID { class Controller_Touchscreen final : public ControllerBase { public: + enum class TouchScreenModeForNx : u8 { + UseSystemSetting, + Finger, + Heat2, + }; + + struct TouchScreenConfigurationForNx { + TouchScreenModeForNx mode; + INSERT_PADDING_BYTES_NOINIT(0x7); + INSERT_PADDING_BYTES_NOINIT(0xF); // Reserved + }; + static_assert(sizeof(TouchScreenConfigurationForNx) == 0x17, + "TouchScreenConfigurationForNx is an invalid size"); + explicit Controller_Touchscreen(Core::System& system_); ~Controller_Touchscreen() override; diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index b8b80570d..a1707a72a 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp @@ -331,7 +331,7 @@ Hid::Hid(Core::System& system_) {529, nullptr, "SetDisallowedPalmaConnection"}, {1000, &Hid::SetNpadCommunicationMode, "SetNpadCommunicationMode"}, {1001, &Hid::GetNpadCommunicationMode, "GetNpadCommunicationMode"}, - {1002, nullptr, "SetTouchScreenConfiguration"}, + {1002, &Hid::SetTouchScreenConfiguration, "SetTouchScreenConfiguration"}, {1003, nullptr, "IsFirmwareUpdateNeededForNotification"}, {2000, nullptr, "ActivateDigitizer"}, }; @@ -1631,6 +1631,18 @@ void Hid::GetNpadCommunicationMode(Kernel::HLERequestContext& ctx) { .GetNpadCommunicationMode()); } +void Hid::SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx) { + IPC::RequestParser rp{ctx}; + const auto touchscreen_mode{rp.PopRaw<Controller_Touchscreen::TouchScreenConfigurationForNx>()}; + const auto applet_resource_user_id{rp.Pop<u64>()}; + + LOG_WARNING(Service_HID, "(STUBBED) called, touchscreen_mode={}, applet_resource_user_id={}", + touchscreen_mode.mode, applet_resource_user_id); + + IPC::ResponseBuilder rb{ctx, 2}; + rb.Push(ResultSuccess); +} + class HidDbg final : public ServiceFramework<HidDbg> { public: explicit HidDbg(Core::System& system_) : ServiceFramework{system_, "hid:dbg"} { diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 9c5c7f252..b1fe75e94 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h @@ -159,6 +159,7 @@ private: void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); void SetNpadCommunicationMode(Kernel::HLERequestContext& ctx); void GetNpadCommunicationMode(Kernel::HLERequestContext& ctx); + void SetTouchScreenConfiguration(Kernel::HLERequestContext& ctx); enum class VibrationDeviceType : u32 { Unknown = 0, diff --git a/src/core/network/network.cpp b/src/core/network/network.cpp index 4732d4485..72eea52f0 100644 --- a/src/core/network/network.cpp +++ b/src/core/network/network.cpp @@ -7,7 +7,8 @@ #include <limits> #include <utility> #include <vector> -#include "common/common_funcs.h" + +#include "common/error.h" #ifdef _WIN32 #include <winsock2.h> @@ -223,7 +224,7 @@ Errno GetAndLogLastError() { if (err == Errno::AGAIN) { return err; } - LOG_ERROR(Network, "Socket operation error: {}", NativeErrorToString(e)); + LOG_ERROR(Network, "Socket operation error: {}", Common::NativeErrorToString(e)); return err; } diff --git a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp index a982dd8a2..cd285e2c8 100644 --- a/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp +++ b/src/shader_recompiler/backend/glsl/emit_glsl_warp.cpp @@ -11,6 +11,8 @@ namespace Shader::Backend::GLSL { namespace { +constexpr char THREAD_ID[]{"gl_SubGroupInvocationARB"}; + void SetInBoundsFlag(EmitContext& ctx, IR::Inst& inst) { IR::Inst* const in_bounds{inst.GetAssociatedPseudoOperation(IR::Opcode::GetInBoundsFromOp)}; if (!in_bounds) { @@ -43,84 +45,100 @@ void UseShuffleNv(EmitContext& ctx, IR::Inst& inst, std::string_view shfl_op, ctx.AddU32("{}={}({},{},{},shfl_in_bounds);", inst, shfl_op, value, index, width); SetInBoundsFlag(ctx, inst); } + +std::string_view BallotIndex(EmitContext& ctx) { + if (!ctx.profile.warp_size_potentially_larger_than_guest) { + return ".x"; + } + return "[gl_SubGroupInvocationARB>>5]"; +} + +std::string GetMask(EmitContext& ctx, std::string_view mask) { + const auto ballot_index{BallotIndex(ctx)}; + return fmt::format("uint(uvec2({}){})", mask, ballot_index); +} } // Anonymous namespace void EmitLaneId(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=gl_SubGroupInvocationARB&31u;", inst); + ctx.AddU32("{}={}&31u;", inst, THREAD_ID); } void EmitVoteAll(EmitContext& ctx, IR::Inst& inst, std::string_view pred) { if (!ctx.profile.warp_size_potentially_larger_than_guest) { ctx.AddU1("{}=allInvocationsEqualARB({});", inst, pred); - } else { - const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")}; - const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)}; - ctx.AddU1("{}=({}&{})=={};", inst, ballot, active_mask, active_mask); + return; } + const auto ballot_index{BallotIndex(ctx)}; + const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)}; + const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)}; + ctx.AddU1("{}=({}&{})=={};", inst, ballot, active_mask, active_mask); } void EmitVoteAny(EmitContext& ctx, IR::Inst& inst, std::string_view pred) { if (!ctx.profile.warp_size_potentially_larger_than_guest) { ctx.AddU1("{}=anyInvocationARB({});", inst, pred); - } else { - const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")}; - const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)}; - ctx.AddU1("{}=({}&{})!=0u;", inst, ballot, active_mask, active_mask); + return; } + const auto ballot_index{BallotIndex(ctx)}; + const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)}; + const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)}; + ctx.AddU1("{}=({}&{})!=0u;", inst, ballot, active_mask, active_mask); } void EmitVoteEqual(EmitContext& ctx, IR::Inst& inst, std::string_view pred) { if (!ctx.profile.warp_size_potentially_larger_than_guest) { ctx.AddU1("{}=allInvocationsEqualARB({});", inst, pred); - } else { - const auto active_mask{fmt::format("uvec2(ballotARB(true))[gl_SubGroupInvocationARB]")}; - const auto ballot{fmt::format("uvec2(ballotARB({}))[gl_SubGroupInvocationARB]", pred)}; - const auto value{fmt::format("({}^{})", ballot, active_mask)}; - ctx.AddU1("{}=({}==0)||({}=={});", inst, value, value, active_mask); + return; } + const auto ballot_index{BallotIndex(ctx)}; + const auto active_mask{fmt::format("uvec2(ballotARB(true)){}", ballot_index)}; + const auto ballot{fmt::format("uvec2(ballotARB({})){}", pred, ballot_index)}; + const auto value{fmt::format("({}^{})", ballot, active_mask)}; + ctx.AddU1("{}=({}==0)||({}=={});", inst, value, value, active_mask); } void EmitSubgroupBallot(EmitContext& ctx, IR::Inst& inst, std::string_view pred) { - if (!ctx.profile.warp_size_potentially_larger_than_guest) { - ctx.AddU32("{}=uvec2(ballotARB({})).x;", inst, pred); - } else { - ctx.AddU32("{}=uvec2(ballotARB({}))[gl_SubGroupInvocationARB];", inst, pred); - } + const auto ballot_index{BallotIndex(ctx)}; + ctx.AddU32("{}=uvec2(ballotARB({})){};", inst, pred, ballot_index); } void EmitSubgroupEqMask(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=uint(gl_SubGroupEqMaskARB.x);", inst); + ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupEqMaskARB")); } void EmitSubgroupLtMask(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=uint(gl_SubGroupLtMaskARB.x);", inst); + ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupLtMaskARB")); } void EmitSubgroupLeMask(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=uint(gl_SubGroupLeMaskARB.x);", inst); + ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupLeMaskARB")); } void EmitSubgroupGtMask(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=uint(gl_SubGroupGtMaskARB.x);", inst); + ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupGtMaskARB")); } void EmitSubgroupGeMask(EmitContext& ctx, IR::Inst& inst) { - ctx.AddU32("{}=uint(gl_SubGroupGeMaskARB.x);", inst); + ctx.AddU32("{}={};", inst, GetMask(ctx, "gl_SubGroupGeMaskARB")); } void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { + std::string_view index, std::string_view clamp, std::string_view seg_mask) { if (ctx.profile.support_gl_warp_intrinsics) { - UseShuffleNv(ctx, inst, "shuffleNV", value, index, clamp, segmentation_mask); + UseShuffleNv(ctx, inst, "shuffleNV", value, index, clamp, seg_mask); return; } - const auto not_seg_mask{fmt::format("(~{})", segmentation_mask)}; - const auto thread_id{"gl_SubGroupInvocationARB"}; - const auto min_thread_id{ComputeMinThreadId(thread_id, segmentation_mask)}; - const auto max_thread_id{ComputeMaxThreadId(min_thread_id, clamp, not_seg_mask)}; + const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest}; + const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"}; + const auto upper_index{fmt::format("{}?{}+32:{}", is_upper_partition, index, index)}; + const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)}; + + const auto not_seg_mask{fmt::format("(~{})", seg_mask)}; + const auto min_thread_id{ComputeMinThreadId(THREAD_ID, seg_mask)}; + const auto max_thread_id{ + ComputeMaxThreadId(min_thread_id, big_warp ? upper_clamp : clamp, not_seg_mask)}; - const auto lhs{fmt::format("({}&{})", index, not_seg_mask)}; + const auto lhs{fmt::format("({}&{})", big_warp ? upper_index : index, not_seg_mask)}; const auto src_thread_id{fmt::format("({})|({})", lhs, min_thread_id)}; ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id); SetInBoundsFlag(ctx, inst); @@ -128,29 +146,34 @@ void EmitShuffleIndex(EmitContext& ctx, IR::Inst& inst, std::string_view value, } void EmitShuffleUp(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, - std::string_view clamp, std::string_view segmentation_mask) { + std::string_view clamp, std::string_view seg_mask) { if (ctx.profile.support_gl_warp_intrinsics) { - UseShuffleNv(ctx, inst, "shuffleUpNV", value, index, clamp, segmentation_mask); + UseShuffleNv(ctx, inst, "shuffleUpNV", value, index, clamp, seg_mask); return; } - const auto thread_id{"gl_SubGroupInvocationARB"}; - const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)}; - const auto src_thread_id{fmt::format("({}-{})", thread_id, index)}; + const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest}; + const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"}; + const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)}; + + const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)}; + const auto src_thread_id{fmt::format("({}-{})", THREAD_ID, index)}; ctx.Add("shfl_in_bounds=int({})>=int({});", src_thread_id, max_thread_id); SetInBoundsFlag(ctx, inst); ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value); } void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, - std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { + std::string_view index, std::string_view clamp, std::string_view seg_mask) { if (ctx.profile.support_gl_warp_intrinsics) { - UseShuffleNv(ctx, inst, "shuffleDownNV", value, index, clamp, segmentation_mask); + UseShuffleNv(ctx, inst, "shuffleDownNV", value, index, clamp, seg_mask); return; } - const auto thread_id{"gl_SubGroupInvocationARB"}; - const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)}; - const auto src_thread_id{fmt::format("({}+{})", thread_id, index)}; + const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest}; + const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"}; + const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)}; + + const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)}; + const auto src_thread_id{fmt::format("({}+{})", THREAD_ID, index)}; ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id); SetInBoundsFlag(ctx, inst); ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value); @@ -158,14 +181,17 @@ void EmitShuffleDown(EmitContext& ctx, IR::Inst& inst, std::string_view value, void EmitShuffleButterfly(EmitContext& ctx, IR::Inst& inst, std::string_view value, std::string_view index, std::string_view clamp, - std::string_view segmentation_mask) { + std::string_view seg_mask) { if (ctx.profile.support_gl_warp_intrinsics) { - UseShuffleNv(ctx, inst, "shuffleXorNV", value, index, clamp, segmentation_mask); + UseShuffleNv(ctx, inst, "shuffleXorNV", value, index, clamp, seg_mask); return; } - const auto thread_id{"gl_SubGroupInvocationARB"}; - const auto max_thread_id{GetMaxThreadId(thread_id, clamp, segmentation_mask)}; - const auto src_thread_id{fmt::format("({}^{})", thread_id, index)}; + const bool big_warp{ctx.profile.warp_size_potentially_larger_than_guest}; + const auto is_upper_partition{"int(gl_SubGroupInvocationARB)>=32"}; + const auto upper_clamp{fmt::format("{}?{}+32:{}", is_upper_partition, clamp, clamp)}; + + const auto max_thread_id{GetMaxThreadId(THREAD_ID, big_warp ? upper_clamp : clamp, seg_mask)}; + const auto src_thread_id{fmt::format("({}^{})", THREAD_ID, index)}; ctx.Add("shfl_in_bounds=int({})<=int({});", src_thread_id, max_thread_id); SetInBoundsFlag(ctx, inst); ctx.AddU32("{}=shfl_in_bounds?readInvocationARB({},{}):{};", inst, value, src_thread_id, value); diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp index 78b1e1ba7..cef52c56e 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp +++ b/src/shader_recompiler/backend/spirv/emit_spirv_warp.cpp @@ -7,8 +7,13 @@ namespace Shader::Backend::SPIRV { namespace { +Id GetThreadId(EmitContext& ctx) { + return ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id); +} + Id WarpExtract(EmitContext& ctx, Id value) { - const Id local_index{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id thread_id{GetThreadId(ctx)}; + const Id local_index{ctx.OpShiftRightArithmetic(ctx.U32[1], thread_id, ctx.Const(5U))}; return ctx.OpVectorExtractDynamic(ctx.U32[1], value, local_index); } @@ -48,10 +53,17 @@ Id SelectValue(EmitContext& ctx, Id in_range, Id value, Id src_thread_id) { return ctx.OpSelect(ctx.U32[1], in_range, ctx.OpSubgroupReadInvocationKHR(ctx.U32[1], value, src_thread_id), value); } + +Id GetUpperClamp(EmitContext& ctx, Id invocation_id, Id clamp) { + const Id thirty_two{ctx.Const(32u)}; + const Id is_upper_partition{ctx.OpSGreaterThanEqual(ctx.U1, invocation_id, thirty_two)}; + const Id upper_clamp{ctx.OpIAdd(ctx.U32[1], thirty_two, clamp)}; + return ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_clamp, clamp); +} } // Anonymous namespace Id EmitLaneId(EmitContext& ctx) { - const Id id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id id{GetThreadId(ctx)}; if (!ctx.profile.warp_size_potentially_larger_than_guest) { return id; } @@ -123,7 +135,15 @@ Id EmitSubgroupGeMask(EmitContext& ctx) { Id EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, Id segmentation_mask) { const Id not_seg_mask{ctx.OpNot(ctx.U32[1], segmentation_mask)}; - const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id thread_id{GetThreadId(ctx)}; + if (ctx.profile.warp_size_potentially_larger_than_guest) { + const Id thirty_two{ctx.Const(32u)}; + const Id is_upper_partition{ctx.OpSGreaterThanEqual(ctx.U1, thread_id, thirty_two)}; + const Id upper_index{ctx.OpIAdd(ctx.U32[1], thirty_two, index)}; + const Id upper_clamp{ctx.OpIAdd(ctx.U32[1], thirty_two, clamp)}; + index = ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_index, index); + clamp = ctx.OpSelect(ctx.U32[1], is_upper_partition, upper_clamp, clamp); + } const Id min_thread_id{ComputeMinThreadId(ctx, thread_id, segmentation_mask)}; const Id max_thread_id{ComputeMaxThreadId(ctx, min_thread_id, clamp, not_seg_mask)}; @@ -137,7 +157,10 @@ Id EmitShuffleIndex(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id cla Id EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, Id segmentation_mask) { - const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id thread_id{GetThreadId(ctx)}; + if (ctx.profile.warp_size_potentially_larger_than_guest) { + clamp = GetUpperClamp(ctx, thread_id, clamp); + } const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)}; const Id src_thread_id{ctx.OpISub(ctx.U32[1], thread_id, index)}; const Id in_range{ctx.OpSGreaterThanEqual(ctx.U1, src_thread_id, max_thread_id)}; @@ -148,7 +171,10 @@ Id EmitShuffleUp(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, Id EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, Id segmentation_mask) { - const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id thread_id{GetThreadId(ctx)}; + if (ctx.profile.warp_size_potentially_larger_than_guest) { + clamp = GetUpperClamp(ctx, thread_id, clamp); + } const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)}; const Id src_thread_id{ctx.OpIAdd(ctx.U32[1], thread_id, index)}; const Id in_range{ctx.OpSLessThanEqual(ctx.U1, src_thread_id, max_thread_id)}; @@ -159,7 +185,10 @@ Id EmitShuffleDown(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clam Id EmitShuffleButterfly(EmitContext& ctx, IR::Inst* inst, Id value, Id index, Id clamp, Id segmentation_mask) { - const Id thread_id{ctx.OpLoad(ctx.U32[1], ctx.subgroup_local_invocation_id)}; + const Id thread_id{GetThreadId(ctx)}; + if (ctx.profile.warp_size_potentially_larger_than_guest) { + clamp = GetUpperClamp(ctx, thread_id, clamp); + } const Id max_thread_id{GetMaxThreadId(ctx, thread_id, clamp, segmentation_mask)}; const Id src_thread_id{ctx.OpBitwiseXor(ctx.U32[1], thread_id, index)}; const Id in_range{ctx.OpSLessThanEqual(ctx.U1, src_thread_id, max_thread_id)}; diff --git a/src/video_core/command_classes/codecs/codec.h b/src/video_core/command_classes/codecs/codec.h index 1508d36c2..f9a80886f 100644 --- a/src/video_core/command_classes/codecs/codec.h +++ b/src/video_core/command_classes/codecs/codec.h @@ -5,6 +5,7 @@ #pragma once #include <memory> +#include <string_view> #include <queue> #include "common/common_types.h" #include "video_core/command_classes/nvdec_common.h" diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index c60ed6453..dce00e829 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp @@ -2,6 +2,8 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> + #include "common/alignment.h" #include "common/assert.h" #include "common/logging/log.h" diff --git a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp index 8e77e4796..adb557f60 100644 --- a/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_descriptor_pool.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> #include <mutex> #include <span> #include <vector> diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 8a4581c19..81a878bb2 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include <algorithm> #include <filesystem> #include <fstream> #include <memory> diff --git a/src/video_core/texture_cache/slot_vector.h b/src/video_core/texture_cache/slot_vector.h index 6180b8c0e..74cd3c9d8 100644 --- a/src/video_core/texture_cache/slot_vector.h +++ b/src/video_core/texture_cache/slot_vector.h @@ -4,6 +4,7 @@ #pragma once +#include <algorithm> #include <array> #include <bit> #include <concepts> diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index e36774cc6..77d53e7bc 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp @@ -3174,12 +3174,11 @@ std::optional<u64> GMainWindow::SelectRomFSDumpTarget(const FileSys::ContentProv } bool GMainWindow::ConfirmClose() { - if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) + if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { return true; - - QMessageBox::StandardButton answer = - QMessageBox::question(this, tr("yuzu"), tr("Are you sure you want to close yuzu?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + } + const auto text = tr("Are you sure you want to close yuzu?"); + const auto answer = QMessageBox::question(this, tr("yuzu"), text); return answer != QMessageBox::No; } @@ -3261,14 +3260,13 @@ bool GMainWindow::ConfirmChangeGame() { } bool GMainWindow::ConfirmForceLockedExit() { - if (emu_thread == nullptr) + if (emu_thread == nullptr || !UISettings::values.confirm_before_closing) { return true; + } + const auto text = tr("The currently running application has requested yuzu to not exit.\n\n" + "Would you like to bypass this and exit anyway?"); - const auto answer = - QMessageBox::question(this, tr("yuzu"), - tr("The currently running application has requested yuzu to not " - "exit.\n\nWould you like to bypass this and exit anyway?"), - QMessageBox::Yes | QMessageBox::No, QMessageBox::No); + const auto answer = QMessageBox::question(this, tr("yuzu"), text); return answer != QMessageBox::No; } |