diff options
Diffstat (limited to 'src')
38 files changed, 784 insertions, 461 deletions
diff --git a/src/core/hle/kernel/memory/memory_manager.cpp b/src/core/hle/kernel/memory/memory_manager.cpp index 616148190..acf13585c 100644 --- a/src/core/hle/kernel/memory/memory_manager.cpp +++ b/src/core/hle/kernel/memory/memory_manager.cpp | |||
| @@ -139,7 +139,6 @@ ResultCode MemoryManager::Allocate(PageLinkedList& page_list, std::size_t num_pa | |||
| 139 | } | 139 | } |
| 140 | 140 | ||
| 141 | // Only succeed if we allocated as many pages as we wanted | 141 | // Only succeed if we allocated as many pages as we wanted |
| 142 | ASSERT(num_pages >= 0); | ||
| 143 | if (num_pages) { | 142 | if (num_pages) { |
| 144 | return ERR_OUT_OF_MEMORY; | 143 | return ERR_OUT_OF_MEMORY; |
| 145 | } | 144 | } |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index 4df74c4f9..20f366635 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -68,6 +68,7 @@ IWindowController::IWindowController(Core::System& system_) | |||
| 68 | static const FunctionInfo functions[] = { | 68 | static const FunctionInfo functions[] = { |
| 69 | {0, nullptr, "CreateWindow"}, | 69 | {0, nullptr, "CreateWindow"}, |
| 70 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, | 70 | {1, &IWindowController::GetAppletResourceUserId, "GetAppletResourceUserId"}, |
| 71 | {2, nullptr, "GetAppletResourceUserIdOfCallerApplet"}, | ||
| 71 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, | 72 | {10, &IWindowController::AcquireForegroundRights, "AcquireForegroundRights"}, |
| 72 | {11, nullptr, "ReleaseForegroundRights"}, | 73 | {11, nullptr, "ReleaseForegroundRights"}, |
| 73 | {12, nullptr, "RejectToChangeIntoBackground"}, | 74 | {12, nullptr, "RejectToChangeIntoBackground"}, |
| @@ -189,8 +190,8 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController" | |||
| 189 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, | 190 | {5, nullptr, "GetLastForegroundCaptureImageEx"}, |
| 190 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, | 191 | {6, nullptr, "GetLastApplicationCaptureImageEx"}, |
| 191 | {7, nullptr, "GetCallerAppletCaptureImageEx"}, | 192 | {7, nullptr, "GetCallerAppletCaptureImageEx"}, |
| 192 | {8, nullptr, "TakeScreenShotOfOwnLayer"}, // 2.0.0+ | 193 | {8, nullptr, "TakeScreenShotOfOwnLayer"}, |
| 193 | {9, nullptr, "CopyBetweenCaptureBuffers"}, // 5.0.0+ | 194 | {9, nullptr, "CopyBetweenCaptureBuffers"}, |
| 194 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, | 195 | {10, nullptr, "AcquireLastApplicationCaptureBuffer"}, |
| 195 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, | 196 | {11, nullptr, "ReleaseLastApplicationCaptureBuffer"}, |
| 196 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, | 197 | {12, nullptr, "AcquireLastForegroundCaptureBuffer"}, |
| @@ -200,17 +201,14 @@ IDisplayController::IDisplayController() : ServiceFramework("IDisplayController" | |||
| 200 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, | 201 | {16, nullptr, "AcquireLastApplicationCaptureBufferEx"}, |
| 201 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, | 202 | {17, nullptr, "AcquireLastForegroundCaptureBufferEx"}, |
| 202 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, | 203 | {18, nullptr, "AcquireCallerAppletCaptureBufferEx"}, |
| 203 | // 2.0.0+ | ||
| 204 | {20, nullptr, "ClearCaptureBuffer"}, | 204 | {20, nullptr, "ClearCaptureBuffer"}, |
| 205 | {21, nullptr, "ClearAppletTransitionBuffer"}, | 205 | {21, nullptr, "ClearAppletTransitionBuffer"}, |
| 206 | // 4.0.0+ | ||
| 207 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, | 206 | {22, nullptr, "AcquireLastApplicationCaptureSharedBuffer"}, |
| 208 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, | 207 | {23, nullptr, "ReleaseLastApplicationCaptureSharedBuffer"}, |
| 209 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, | 208 | {24, nullptr, "AcquireLastForegroundCaptureSharedBuffer"}, |
| 210 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, | 209 | {25, nullptr, "ReleaseLastForegroundCaptureSharedBuffer"}, |
| 211 | {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, | 210 | {26, nullptr, "AcquireCallerAppletCaptureSharedBuffer"}, |
| 212 | {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, | 211 | {27, nullptr, "ReleaseCallerAppletCaptureSharedBuffer"}, |
| 213 | // 6.0.0+ | ||
| 214 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, | 212 | {28, nullptr, "TakeScreenShotOfOwnLayerEx"}, |
| 215 | }; | 213 | }; |
| 216 | // clang-format on | 214 | // clang-format on |
| @@ -225,7 +223,7 @@ IDebugFunctions::IDebugFunctions() : ServiceFramework{"IDebugFunctions"} { | |||
| 225 | static const FunctionInfo functions[] = { | 223 | static const FunctionInfo functions[] = { |
| 226 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, | 224 | {0, nullptr, "NotifyMessageToHomeMenuForDebug"}, |
| 227 | {1, nullptr, "OpenMainApplication"}, | 225 | {1, nullptr, "OpenMainApplication"}, |
| 228 | {10, nullptr, "EmulateButtonEvent"}, | 226 | {10, nullptr, "PerformSystemButtonPressing"}, |
| 229 | {20, nullptr, "InvalidateTransitionLayer"}, | 227 | {20, nullptr, "InvalidateTransitionLayer"}, |
| 230 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, | 228 | {30, nullptr, "RequestLaunchApplicationWithUserAndArgumentForDebug"}, |
| 231 | {40, nullptr, "GetAppletResourceUsageInfo"}, | 229 | {40, nullptr, "GetAppletResourceUsageInfo"}, |
| @@ -267,7 +265,7 @@ ISelfController::ISelfController(Core::System& system, | |||
| 267 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, | 265 | {16, &ISelfController::SetOutOfFocusSuspendingEnabled, "SetOutOfFocusSuspendingEnabled"}, |
| 268 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, | 266 | {17, nullptr, "SetControllerFirmwareUpdateSection"}, |
| 269 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, | 267 | {18, nullptr, "SetRequiresCaptureButtonShortPressedMessage"}, |
| 270 | {19, &ISelfController::SetScreenShotImageOrientation, "SetScreenShotImageOrientation"}, | 268 | {19, &ISelfController::SetAlbumImageOrientation, "SetAlbumImageOrientation"}, |
| 271 | {20, nullptr, "SetDesirableKeyboardLayout"}, | 269 | {20, nullptr, "SetDesirableKeyboardLayout"}, |
| 272 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, | 270 | {40, &ISelfController::CreateManagedDisplayLayer, "CreateManagedDisplayLayer"}, |
| 273 | {41, nullptr, "IsSystemBufferSharingEnabled"}, | 271 | {41, nullptr, "IsSystemBufferSharingEnabled"}, |
| @@ -443,7 +441,7 @@ void ISelfController::SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& | |||
| 443 | rb.Push(RESULT_SUCCESS); | 441 | rb.Push(RESULT_SUCCESS); |
| 444 | } | 442 | } |
| 445 | 443 | ||
| 446 | void ISelfController::SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx) { | 444 | void ISelfController::SetAlbumImageOrientation(Kernel::HLERequestContext& ctx) { |
| 447 | LOG_WARNING(Service_AM, "(STUBBED) called"); | 445 | LOG_WARNING(Service_AM, "(STUBBED) called"); |
| 448 | 446 | ||
| 449 | IPC::ResponseBuilder rb{ctx, 2}; | 447 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -607,6 +605,7 @@ ICommonStateGetter::ICommonStateGetter(Core::System& system, | |||
| 607 | {20, nullptr, "PushToGeneralChannel"}, | 605 | {20, nullptr, "PushToGeneralChannel"}, |
| 608 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, | 606 | {30, nullptr, "GetHomeButtonReaderLockAccessor"}, |
| 609 | {31, nullptr, "GetReaderLockAccessorEx"}, | 607 | {31, nullptr, "GetReaderLockAccessorEx"}, |
| 608 | {32, nullptr, "GetWriterLockAccessorEx"}, | ||
| 610 | {40, nullptr, "GetCradleFwVersion"}, | 609 | {40, nullptr, "GetCradleFwVersion"}, |
| 611 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, | 610 | {50, &ICommonStateGetter::IsVrModeEnabled, "IsVrModeEnabled"}, |
| 612 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, | 611 | {51, &ICommonStateGetter::SetVrModeEnabled, "SetVrModeEnabled"}, |
| @@ -1132,6 +1131,7 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1132 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, | 1131 | {24, nullptr, "GetLaunchStorageInfoForDebug"}, |
| 1133 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, | 1132 | {25, &IApplicationFunctions::ExtendSaveData, "ExtendSaveData"}, |
| 1134 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, | 1133 | {26, &IApplicationFunctions::GetSaveDataSize, "GetSaveDataSize"}, |
| 1134 | {27, nullptr, "CreateCacheStorage"}, | ||
| 1135 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, | 1135 | {30, &IApplicationFunctions::BeginBlockingHomeButtonShortAndLongPressed, "BeginBlockingHomeButtonShortAndLongPressed"}, |
| 1136 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, | 1136 | {31, &IApplicationFunctions::EndBlockingHomeButtonShortAndLongPressed, "EndBlockingHomeButtonShortAndLongPressed"}, |
| 1137 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, | 1137 | {32, &IApplicationFunctions::BeginBlockingHomeButton, "BeginBlockingHomeButton"}, |
| @@ -1157,6 +1157,8 @@ IApplicationFunctions::IApplicationFunctions(Core::System& system_) | |||
| 1157 | {120, nullptr, "ExecuteProgram"}, | 1157 | {120, nullptr, "ExecuteProgram"}, |
| 1158 | {121, nullptr, "ClearUserChannel"}, | 1158 | {121, nullptr, "ClearUserChannel"}, |
| 1159 | {122, nullptr, "UnpopToUserChannel"}, | 1159 | {122, nullptr, "UnpopToUserChannel"}, |
| 1160 | {123, nullptr, "GetPreviousProgramIndex"}, | ||
| 1161 | {124, nullptr, "EnableApplicationAllThreadDumpOnCrash"}, | ||
| 1160 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, | 1162 | {130, &IApplicationFunctions::GetGpuErrorDetectedSystemEvent, "GetGpuErrorDetectedSystemEvent"}, |
| 1161 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, | 1163 | {140, &IApplicationFunctions::GetFriendInvitationStorageChannelEvent, "GetFriendInvitationStorageChannelEvent"}, |
| 1162 | {141, nullptr, "TryPopFromFriendInvitationStorageChannel"}, | 1164 | {141, nullptr, "TryPopFromFriendInvitationStorageChannel"}, |
diff --git a/src/core/hle/service/am/am.h b/src/core/hle/service/am/am.h index 469f7f814..2f69466ec 100644 --- a/src/core/hle/service/am/am.h +++ b/src/core/hle/service/am/am.h | |||
| @@ -138,7 +138,7 @@ private: | |||
| 138 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); | 138 | void SetFocusHandlingMode(Kernel::HLERequestContext& ctx); |
| 139 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); | 139 | void SetRestartMessageEnabled(Kernel::HLERequestContext& ctx); |
| 140 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); | 140 | void SetOutOfFocusSuspendingEnabled(Kernel::HLERequestContext& ctx); |
| 141 | void SetScreenShotImageOrientation(Kernel::HLERequestContext& ctx); | 141 | void SetAlbumImageOrientation(Kernel::HLERequestContext& ctx); |
| 142 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); | 142 | void CreateManagedDisplayLayer(Kernel::HLERequestContext& ctx); |
| 143 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); | 143 | void SetHandlesRequestToDisplay(Kernel::HLERequestContext& ctx); |
| 144 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); | 144 | void SetIdleTimeDetectionExtension(Kernel::HLERequestContext& ctx); |
diff --git a/src/core/hle/service/am/spsm.cpp b/src/core/hle/service/am/spsm.cpp index 003ee8667..f27729ce7 100644 --- a/src/core/hle/service/am/spsm.cpp +++ b/src/core/hle/service/am/spsm.cpp | |||
| @@ -10,17 +10,17 @@ SPSM::SPSM() : ServiceFramework{"spsm"} { | |||
| 10 | // clang-format off | 10 | // clang-format off |
| 11 | static const FunctionInfo functions[] = { | 11 | static const FunctionInfo functions[] = { |
| 12 | {0, nullptr, "GetState"}, | 12 | {0, nullptr, "GetState"}, |
| 13 | {1, nullptr, "SleepSystemAndWaitAwake"}, | 13 | {1, nullptr, "EnterSleep"}, |
| 14 | {2, nullptr, "Unknown1"}, | 14 | {2, nullptr, "GetLastWakeReason"}, |
| 15 | {3, nullptr, "Unknown2"}, | 15 | {3, nullptr, "Shutdown"}, |
| 16 | {4, nullptr, "GetNotificationMessageEventHandle"}, | 16 | {4, nullptr, "GetNotificationMessageEventHandle"}, |
| 17 | {5, nullptr, "Unknown3"}, | 17 | {5, nullptr, "ReceiveNotificationMessage"}, |
| 18 | {6, nullptr, "Unknown4"}, | 18 | {6, nullptr, "AnalyzeLogForLastSleepWakeSequence"}, |
| 19 | {7, nullptr, "Unknown5"}, | 19 | {7, nullptr, "ResetEventLog"}, |
| 20 | {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, | 20 | {8, nullptr, "AnalyzePerformanceLogForLastSleepWakeSequence"}, |
| 21 | {9, nullptr, "ChangeHomeButtonLongPressingTime"}, | 21 | {9, nullptr, "ChangeHomeButtonLongPressingTime"}, |
| 22 | {10, nullptr, "Unknown6"}, | 22 | {10, nullptr, "PutErrorState"}, |
| 23 | {11, nullptr, "Unknown7"}, | 23 | {11, nullptr, "InvalidateCurrentHomeButtonPressing"}, |
| 24 | }; | 24 | }; |
| 25 | // clang-format on | 25 | // clang-format on |
| 26 | 26 | ||
diff --git a/src/core/hle/service/aoc/aoc_u.cpp b/src/core/hle/service/aoc/aoc_u.cpp index 4227a4adf..8e79f707b 100644 --- a/src/core/hle/service/aoc/aoc_u.cpp +++ b/src/core/hle/service/aoc/aoc_u.cpp | |||
| @@ -60,6 +60,7 @@ AOC_U::AOC_U(Core::System& system) | |||
| 60 | {6, nullptr, "PrepareAddOnContentByApplicationId"}, | 60 | {6, nullptr, "PrepareAddOnContentByApplicationId"}, |
| 61 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, | 61 | {7, &AOC_U::PrepareAddOnContent, "PrepareAddOnContent"}, |
| 62 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, | 62 | {8, &AOC_U::GetAddOnContentListChangedEvent, "GetAddOnContentListChangedEvent"}, |
| 63 | {9, nullptr, "GetAddOnContentLostErrorCode"}, | ||
| 63 | {100, nullptr, "CreateEcPurchasedEventManager"}, | 64 | {100, nullptr, "CreateEcPurchasedEventManager"}, |
| 64 | {101, nullptr, "CreatePermanentEcPurchasedEventManager"}, | 65 | {101, nullptr, "CreatePermanentEcPurchasedEventManager"}, |
| 65 | }; | 66 | }; |
diff --git a/src/core/hle/service/bcat/bcat.cpp b/src/core/hle/service/bcat/bcat.cpp index 8bb2528c9..b31766212 100644 --- a/src/core/hle/service/bcat/bcat.cpp +++ b/src/core/hle/service/bcat/bcat.cpp | |||
| @@ -14,6 +14,8 @@ BCAT::BCAT(Core::System& system, std::shared_ptr<Module> module, | |||
| 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, | 14 | {0, &BCAT::CreateBcatService, "CreateBcatService"}, |
| 15 | {1, &BCAT::CreateDeliveryCacheStorageService, "CreateDeliveryCacheStorageService"}, | 15 | {1, &BCAT::CreateDeliveryCacheStorageService, "CreateDeliveryCacheStorageService"}, |
| 16 | {2, &BCAT::CreateDeliveryCacheStorageServiceWithApplicationId, "CreateDeliveryCacheStorageServiceWithApplicationId"}, | 16 | {2, &BCAT::CreateDeliveryCacheStorageServiceWithApplicationId, "CreateDeliveryCacheStorageServiceWithApplicationId"}, |
| 17 | {3, nullptr, "CreateDeliveryCacheProgressService"}, | ||
| 18 | {4, nullptr, "CreateDeliveryCacheProgressServiceWithApplicationId"}, | ||
| 17 | }; | 19 | }; |
| 18 | // clang-format on | 20 | // clang-format on |
| 19 | RegisterHandlers(functions); | 21 | RegisterHandlers(functions); |
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 34aba7a27..603b64d4f 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -143,10 +143,13 @@ public: | |||
| 143 | {20401, nullptr, "UnregisterSystemApplicationDeliveryTask"}, | 143 | {20401, nullptr, "UnregisterSystemApplicationDeliveryTask"}, |
| 144 | {20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"}, | 144 | {20410, nullptr, "SetSystemApplicationDeliveryTaskTimer"}, |
| 145 | {30100, &IBcatService::SetPassphrase, "SetPassphrase"}, | 145 | {30100, &IBcatService::SetPassphrase, "SetPassphrase"}, |
| 146 | {30101, nullptr, "Unknown"}, | ||
| 147 | {30102, nullptr, "Unknown2"}, | ||
| 146 | {30200, nullptr, "RegisterBackgroundDeliveryTask"}, | 148 | {30200, nullptr, "RegisterBackgroundDeliveryTask"}, |
| 147 | {30201, nullptr, "UnregisterBackgroundDeliveryTask"}, | 149 | {30201, nullptr, "UnregisterBackgroundDeliveryTask"}, |
| 148 | {30202, nullptr, "BlockDeliveryTask"}, | 150 | {30202, nullptr, "BlockDeliveryTask"}, |
| 149 | {30203, nullptr, "UnblockDeliveryTask"}, | 151 | {30203, nullptr, "UnblockDeliveryTask"}, |
| 152 | {30210, nullptr, "SetDeliveryTaskTimer"}, | ||
| 150 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, | 153 | {30300, nullptr, "RegisterSystemApplicationDeliveryTasks"}, |
| 151 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, | 154 | {90100, nullptr, "EnumerateBackgroundDeliveryTask"}, |
| 152 | {90200, nullptr, "GetDeliveryList"}, | 155 | {90200, nullptr, "GetDeliveryList"}, |
diff --git a/src/core/hle/service/bpc/bpc.cpp b/src/core/hle/service/bpc/bpc.cpp index 1c1ecdb60..fac6b2f9c 100644 --- a/src/core/hle/service/bpc/bpc.cpp +++ b/src/core/hle/service/bpc/bpc.cpp | |||
| @@ -23,9 +23,14 @@ public: | |||
| 23 | {5, nullptr, "GetBoardPowerControlEvent"}, | 23 | {5, nullptr, "GetBoardPowerControlEvent"}, |
| 24 | {6, nullptr, "GetSleepButtonState"}, | 24 | {6, nullptr, "GetSleepButtonState"}, |
| 25 | {7, nullptr, "GetPowerEvent"}, | 25 | {7, nullptr, "GetPowerEvent"}, |
| 26 | {8, nullptr, "Unknown1"}, | 26 | {8, nullptr, "CreateWakeupTimer"}, |
| 27 | {9, nullptr, "Unknown2"}, | 27 | {9, nullptr, "CancelWakeupTimer"}, |
| 28 | {10, nullptr, "Unknown3"}, | 28 | {10, nullptr, "EnableWakeupTimerOnDevice"}, |
| 29 | {11, nullptr, "CreateWakeupTimerEx"}, | ||
| 30 | {12, nullptr, "GetLastEnabledWakeupTimerType"}, | ||
| 31 | {13, nullptr, "CleanAllWakeupTimers"}, | ||
| 32 | {14, nullptr, "Unknown"}, | ||
| 33 | {15, nullptr, "Unknown2"}, | ||
| 29 | }; | 34 | }; |
| 30 | // clang-format on | 35 | // clang-format on |
| 31 | 36 | ||
| @@ -38,10 +43,11 @@ public: | |||
| 38 | explicit BPC_R() : ServiceFramework{"bpc:r"} { | 43 | explicit BPC_R() : ServiceFramework{"bpc:r"} { |
| 39 | // clang-format off | 44 | // clang-format off |
| 40 | static const FunctionInfo functions[] = { | 45 | static const FunctionInfo functions[] = { |
| 41 | {0, nullptr, "GetExternalRtcValue"}, | 46 | {0, nullptr, "GetRtcTime"}, |
| 42 | {1, nullptr, "SetExternalRtcValue"}, | 47 | {1, nullptr, "SetRtcTime"}, |
| 43 | {2, nullptr, "ReadExternalRtcResetFlag"}, | 48 | {2, nullptr, "GetRtcResetDetected"}, |
| 44 | {3, nullptr, "ClearExternalRtcResetFlag"}, | 49 | {3, nullptr, "ClearRtcResetDetected"}, |
| 50 | {4, nullptr, "SetUpRtcResetOnShutdown"}, | ||
| 45 | }; | 51 | }; |
| 46 | // clang-format on | 52 | // clang-format on |
| 47 | 53 | ||
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp index 40a06c9fd..f311afa2f 100644 --- a/src/core/hle/service/btdrv/btdrv.cpp +++ b/src/core/hle/service/btdrv/btdrv.cpp | |||
| @@ -58,102 +58,103 @@ public: | |||
| 58 | {1, nullptr, "InitializeBluetooth"}, | 58 | {1, nullptr, "InitializeBluetooth"}, |
| 59 | {2, nullptr, "EnableBluetooth"}, | 59 | {2, nullptr, "EnableBluetooth"}, |
| 60 | {3, nullptr, "DisableBluetooth"}, | 60 | {3, nullptr, "DisableBluetooth"}, |
| 61 | {4, nullptr, "CleanupBluetooth"}, | 61 | {4, nullptr, "FinalizeBluetooth"}, |
| 62 | {5, nullptr, "GetAdapterProperties"}, | 62 | {5, nullptr, "GetAdapterProperties"}, |
| 63 | {6, nullptr, "GetAdapterProperty"}, | 63 | {6, nullptr, "GetAdapterProperty"}, |
| 64 | {7, nullptr, "SetAdapterProperty"}, | 64 | {7, nullptr, "SetAdapterProperty"}, |
| 65 | {8, nullptr, "StartDiscovery"}, | 65 | {8, nullptr, "StartInquiry"}, |
| 66 | {9, nullptr, "CancelDiscovery"}, | 66 | {9, nullptr, "StopInquiry"}, |
| 67 | {10, nullptr, "CreateBond"}, | 67 | {10, nullptr, "CreateBond"}, |
| 68 | {11, nullptr, "RemoveBond"}, | 68 | {11, nullptr, "RemoveBond"}, |
| 69 | {12, nullptr, "CancelBond"}, | 69 | {12, nullptr, "CancelBond"}, |
| 70 | {13, nullptr, "PinReply"}, | 70 | {13, nullptr, "RespondToPinRequest"}, |
| 71 | {14, nullptr, "SspReply"}, | 71 | {14, nullptr, "RespondToSspRequest"}, |
| 72 | {15, nullptr, "GetEventInfo"}, | 72 | {15, nullptr, "GetEventInfo"}, |
| 73 | {16, nullptr, "InitializeHid"}, | 73 | {16, nullptr, "InitializeHid"}, |
| 74 | {17, nullptr, "HidConnect"}, | 74 | {17, nullptr, "OpenHidConnection"}, |
| 75 | {18, nullptr, "HidDisconnect"}, | 75 | {18, nullptr, "CloseHidConnection"}, |
| 76 | {19, nullptr, "HidSendData"}, | 76 | {19, nullptr, "WriteHidData"}, |
| 77 | {20, nullptr, "HidSendData2"}, | 77 | {20, nullptr, "WriteHidData2"}, |
| 78 | {21, nullptr, "HidSetReport"}, | 78 | {21, nullptr, "SetHidReport"}, |
| 79 | {22, nullptr, "HidGetReport"}, | 79 | {22, nullptr, "GetHidReport"}, |
| 80 | {23, nullptr, "HidWakeController"}, | 80 | {23, nullptr, "TriggerConnection"}, |
| 81 | {24, nullptr, "HidAddPairedDevice"}, | 81 | {24, nullptr, "AddPairedDeviceInfo"}, |
| 82 | {25, nullptr, "HidGetPairedDevice"}, | 82 | {25, nullptr, "GetPairedDeviceInfo"}, |
| 83 | {26, nullptr, "CleanupHid"}, | 83 | {26, nullptr, "FinalizeHid"}, |
| 84 | {27, nullptr, "HidGetEventInfo"}, | 84 | {27, nullptr, "GetHidEventInfo"}, |
| 85 | {28, nullptr, "ExtSetTsi"}, | 85 | {28, nullptr, "SetTsi"}, |
| 86 | {29, nullptr, "ExtSetBurstMode"}, | 86 | {29, nullptr, "EnableBurstMode"}, |
| 87 | {30, nullptr, "ExtSetZeroRetran"}, | 87 | {30, nullptr, "SetZeroRetransmission"}, |
| 88 | {31, nullptr, "ExtSetMcMode"}, | 88 | {31, nullptr, "EnableMcMode"}, |
| 89 | {32, nullptr, "ExtStartLlrMode"}, | 89 | {32, nullptr, "EnableLlrScan"}, |
| 90 | {33, nullptr, "ExtExitLlrMode"}, | 90 | {33, nullptr, "DisableLlrScan"}, |
| 91 | {34, nullptr, "ExtSetRadio"}, | 91 | {34, nullptr, "EnableRadio"}, |
| 92 | {35, nullptr, "ExtSetVisibility"}, | 92 | {35, nullptr, "SetVisibility"}, |
| 93 | {36, nullptr, "ExtSetTbfcScan"}, | 93 | {36, nullptr, "EnableTbfcScan"}, |
| 94 | {37, nullptr, "RegisterHidReportEvent"}, | 94 | {37, nullptr, "RegisterHidReportEvent"}, |
| 95 | {38, nullptr, "HidGetReportEventInfo"}, | 95 | {38, nullptr, "GetHidReportEventInfo"}, |
| 96 | {39, nullptr, "GetLatestPlr"}, | 96 | {39, nullptr, "GetLatestPlr"}, |
| 97 | {40, nullptr, "ExtGetPendingConnections"}, | 97 | {40, nullptr, "GetPendingConnections"}, |
| 98 | {41, nullptr, "GetChannelMap"}, | 98 | {41, nullptr, "GetChannelMap"}, |
| 99 | {42, nullptr, "EnableBluetoothBoostSetting"}, | 99 | {42, nullptr, "EnableTxPowerBoostSetting"}, |
| 100 | {43, nullptr, "IsBluetoothBoostSettingEnabled"}, | 100 | {43, nullptr, "IsTxPowerBoostSettingEnabled"}, |
| 101 | {44, nullptr, "EnableBluetoothAfhSetting"}, | 101 | {44, nullptr, "EnableAfhSetting"}, |
| 102 | {45, nullptr, "IsBluetoothAfhSettingEnabled"}, | 102 | {45, nullptr, "IsAfhSettingEnabled"}, |
| 103 | {46, nullptr, "InitializeBluetoothLe"}, | 103 | {46, nullptr, "InitializeBle"}, |
| 104 | {47, nullptr, "EnableBluetoothLe"}, | 104 | {47, nullptr, "EnableBle"}, |
| 105 | {48, nullptr, "DisableBluetoothLe"}, | 105 | {48, nullptr, "DisableBle"}, |
| 106 | {49, nullptr, "CleanupBluetoothLe"}, | 106 | {49, nullptr, "FinalizeBle"}, |
| 107 | {50, nullptr, "SetLeVisibility"}, | 107 | {50, nullptr, "SetBleVisibility"}, |
| 108 | {51, nullptr, "SetLeConnectionParameter"}, | 108 | {51, nullptr, "SetBleConnectionParameter"}, |
| 109 | {52, nullptr, "SetLeDefaultConnectionParameter"}, | 109 | {52, nullptr, "SetBleDefaultConnectionParameter"}, |
| 110 | {53, nullptr, "SetLeAdvertiseData"}, | 110 | {53, nullptr, "SetBleAdvertiseData"}, |
| 111 | {54, nullptr, "SetLeAdvertiseParameter"}, | 111 | {54, nullptr, "SetBleAdvertiseParameter"}, |
| 112 | {55, nullptr, "StartLeScan"}, | 112 | {55, nullptr, "StartBleScan"}, |
| 113 | {56, nullptr, "StopLeScan"}, | 113 | {56, nullptr, "StopBleScan"}, |
| 114 | {57, nullptr, "AddLeScanFilterCondition"}, | 114 | {57, nullptr, "AddBleScanFilterCondition"}, |
| 115 | {58, nullptr, "DeleteLeScanFilterCondition"}, | 115 | {58, nullptr, "DeleteBleScanFilterCondition"}, |
| 116 | {59, nullptr, "DeleteLeScanFilter"}, | 116 | {59, nullptr, "DeleteBleScanFilter"}, |
| 117 | {60, nullptr, "ClearLeScanFilters"}, | 117 | {60, nullptr, "ClearBleScanFilters"}, |
| 118 | {61, nullptr, "EnableLeScanFilter"}, | 118 | {61, nullptr, "EnableBleScanFilter"}, |
| 119 | {62, nullptr, "RegisterLeClient"}, | 119 | {62, nullptr, "RegisterGattClient"}, |
| 120 | {63, nullptr, "UnregisterLeClient"}, | 120 | {63, nullptr, "UnregisterGattClient"}, |
| 121 | {64, nullptr, "UnregisterLeClientAll"}, | 121 | {64, nullptr, "UnregisterAllGattClients"}, |
| 122 | {65, nullptr, "LeClientConnect"}, | 122 | {65, nullptr, "ConnectGattServer"}, |
| 123 | {66, nullptr, "LeClientCancelConnection"}, | 123 | {66, nullptr, "CancelConnectGattServer"}, |
| 124 | {67, nullptr, "LeClientDisconnect"}, | 124 | {67, nullptr, "DisconnectGattServer"}, |
| 125 | {68, nullptr, "LeClientGetAttributes"}, | 125 | {68, nullptr, "GetGattAttribute"}, |
| 126 | {69, nullptr, "LeClientDiscoverService"}, | 126 | {69, nullptr, "GetGattService"}, |
| 127 | {70, nullptr, "LeClientConfigureMtu"}, | 127 | {70, nullptr, "ConfigureAttMtu"}, |
| 128 | {71, nullptr, "RegisterLeServer"}, | 128 | {71, nullptr, "RegisterGattServer"}, |
| 129 | {72, nullptr, "UnregisterLeServer"}, | 129 | {72, nullptr, "UnregisterGattServer"}, |
| 130 | {73, nullptr, "LeServerConnect"}, | 130 | {73, nullptr, "ConnectGattClient"}, |
| 131 | {74, nullptr, "LeServerDisconnect"}, | 131 | {74, nullptr, "DisconnectGattClient"}, |
| 132 | {75, nullptr, "CreateLeService"}, | 132 | {75, nullptr, "AddGattService"}, |
| 133 | {76, nullptr, "StartLeService"}, | 133 | {76, nullptr, "EnableGattService"}, |
| 134 | {77, nullptr, "AddLeCharacteristic"}, | 134 | {77, nullptr, "AddGattCharacteristic"}, |
| 135 | {78, nullptr, "AddLeDescriptor"}, | 135 | {78, nullptr, "AddGattDescriptor"}, |
| 136 | {79, nullptr, "GetLeCoreEventInfo"}, | 136 | {79, nullptr, "GetBleManagedEventInfo"}, |
| 137 | {80, nullptr, "LeGetFirstCharacteristic"}, | 137 | {80, nullptr, "GetGattFirstCharacteristic"}, |
| 138 | {81, nullptr, "LeGetNextCharacteristic"}, | 138 | {81, nullptr, "GetGattNextCharacteristic"}, |
| 139 | {82, nullptr, "LeGetFirstDescriptor"}, | 139 | {82, nullptr, "GetGattFirstDescriptor"}, |
| 140 | {83, nullptr, "LeGetNextDescriptor"}, | 140 | {83, nullptr, "GetGattNextDescriptor"}, |
| 141 | {84, nullptr, "RegisterLeCoreDataPath"}, | 141 | {84, nullptr, "RegisterGattManagedDataPath"}, |
| 142 | {85, nullptr, "UnregisterLeCoreDataPath"}, | 142 | {85, nullptr, "UnregisterGattManagedDataPath"}, |
| 143 | {86, nullptr, "RegisterLeHidDataPath"}, | 143 | {86, nullptr, "RegisterGattHidDataPath"}, |
| 144 | {87, nullptr, "UnregisterLeHidDataPath"}, | 144 | {87, nullptr, "UnregisterGattHidDataPath"}, |
| 145 | {88, nullptr, "RegisterLeDataPath"}, | 145 | {88, nullptr, "RegisterGattDataPath"}, |
| 146 | {89, nullptr, "UnregisterLeDataPath"}, | 146 | {89, nullptr, "UnregisterGattDataPath"}, |
| 147 | {90, nullptr, "LeClientReadCharacteristic"}, | 147 | {90, nullptr, "ReadGattCharacteristic"}, |
| 148 | {91, nullptr, "LeClientReadDescriptor"}, | 148 | {91, nullptr, "ReadGattDescriptor"}, |
| 149 | {92, nullptr, "LeClientWriteCharacteristic"}, | 149 | {92, nullptr, "WriteGattCharacteristic"}, |
| 150 | {93, nullptr, "LeClientWriteDescriptor"}, | 150 | {93, nullptr, "WriteGattDescriptor"}, |
| 151 | {94, nullptr, "LeClientRegisterNotification"}, | 151 | {94, nullptr, "RegisterGattNotification"}, |
| 152 | {95, nullptr, "LeClientDeregisterNotification"}, | 152 | {95, nullptr, "UnregisterGattNotification"}, |
| 153 | {96, nullptr, "GetLeHidEventInfo"}, | 153 | {96, nullptr, "GetLeHidEventInfo"}, |
| 154 | {97, nullptr, "RegisterBleHidEvent"}, | 154 | {97, nullptr, "RegisterBleHidEvent"}, |
| 155 | {98, nullptr, "SetLeScanParameter"}, | 155 | {98, nullptr, "SetBleScanParameter"}, |
| 156 | {256, nullptr, "GetIsManufacturingMode"}, | 156 | {99, nullptr, "MoveToSecondaryPiconet"}, |
| 157 | {256, nullptr, "IsManufacturingMode"}, | ||
| 157 | {257, nullptr, "EmulateBluetoothCrash"}, | 158 | {257, nullptr, "EmulateBluetoothCrash"}, |
| 158 | {258, nullptr, "GetBleChannelMap"}, | 159 | {258, nullptr, "GetBleChannelMap"}, |
| 159 | }; | 160 | }; |
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp index 251b3c9df..0d251c6d0 100644 --- a/src/core/hle/service/btm/btm.cpp +++ b/src/core/hle/service/btm/btm.cpp | |||
| @@ -132,66 +132,71 @@ public: | |||
| 132 | explicit BTM() : ServiceFramework{"btm"} { | 132 | explicit BTM() : ServiceFramework{"btm"} { |
| 133 | // clang-format off | 133 | // clang-format off |
| 134 | static const FunctionInfo functions[] = { | 134 | static const FunctionInfo functions[] = { |
| 135 | {0, nullptr, "Unknown1"}, | 135 | {0, nullptr, "GetState"}, |
| 136 | {1, nullptr, "Unknown2"}, | 136 | {1, nullptr, "GetHostDeviceProperty"}, |
| 137 | {2, nullptr, "RegisterSystemEventForConnectedDeviceCondition"}, | 137 | {2, nullptr, "AcquireDeviceConditionEvent"}, |
| 138 | {3, nullptr, "Unknown3"}, | 138 | {3, nullptr, "GetDeviceCondition"}, |
| 139 | {4, nullptr, "Unknown4"}, | 139 | {4, nullptr, "SetBurstMode"}, |
| 140 | {5, nullptr, "Unknown5"}, | 140 | {5, nullptr, "SetSlotMode"}, |
| 141 | {6, nullptr, "Unknown6"}, | 141 | {6, nullptr, "SetBluetoothMode"}, |
| 142 | {7, nullptr, "Unknown7"}, | 142 | {7, nullptr, "SetWlanMode"}, |
| 143 | {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfo"}, | 143 | {8, nullptr, "AcquireDeviceInfoEvent"}, |
| 144 | {9, nullptr, "Unknown8"}, | 144 | {9, nullptr, "GetDeviceInfo"}, |
| 145 | {10, nullptr, "Unknown9"}, | 145 | {10, nullptr, "AddDeviceInfo"}, |
| 146 | {11, nullptr, "Unknown10"}, | 146 | {11, nullptr, "RemoveDeviceInfo"}, |
| 147 | {12, nullptr, "Unknown11"}, | 147 | {12, nullptr, "IncreaseDeviceInfoOrder"}, |
| 148 | {13, nullptr, "Unknown12"}, | 148 | {13, nullptr, "LlrNotify"}, |
| 149 | {14, nullptr, "EnableRadio"}, | 149 | {14, nullptr, "EnableRadio"}, |
| 150 | {15, nullptr, "DisableRadio"}, | 150 | {15, nullptr, "DisableRadio"}, |
| 151 | {16, nullptr, "Unknown13"}, | 151 | {16, nullptr, "HidDisconnect"}, |
| 152 | {17, nullptr, "Unknown14"}, | 152 | {17, nullptr, "HidSetRetransmissionMode"}, |
| 153 | {18, nullptr, "Unknown15"}, | 153 | {18, nullptr, "AcquireAwakeReqEvent"}, |
| 154 | {19, nullptr, "Unknown16"}, | 154 | {19, nullptr, "AcquireLlrStateEvent"}, |
| 155 | {20, nullptr, "Unknown17"}, | 155 | {20, nullptr, "IsLlrStarted"}, |
| 156 | {21, nullptr, "Unknown18"}, | 156 | {21, nullptr, "EnableSlotSaving"}, |
| 157 | {22, nullptr, "Unknown19"}, | 157 | {22, nullptr, "ProtectDeviceInfo"}, |
| 158 | {23, nullptr, "Unknown20"}, | 158 | {23, nullptr, "AcquireBleScanEvent"}, |
| 159 | {24, nullptr, "Unknown21"}, | 159 | {24, nullptr, "GetBleScanParameterGeneral"}, |
| 160 | {25, nullptr, "Unknown22"}, | 160 | {25, nullptr, "GetBleScanParameterSmartDevice"}, |
| 161 | {26, nullptr, "Unknown23"}, | 161 | {26, nullptr, "StartBleScanForGeneral"}, |
| 162 | {27, nullptr, "Unknown24"}, | 162 | {27, nullptr, "StopBleScanForGeneral"}, |
| 163 | {28, nullptr, "Unknown25"}, | 163 | {28, nullptr, "GetBleScanResultsForGeneral"}, |
| 164 | {29, nullptr, "Unknown26"}, | 164 | {29, nullptr, "StartBleScanForPairedDevice"}, |
| 165 | {30, nullptr, "Unknown27"}, | 165 | {30, nullptr, "StopBleScanForPairedDevice"}, |
| 166 | {31, nullptr, "Unknown28"}, | 166 | {31, nullptr, "StartBleScanForSmartDevice"}, |
| 167 | {32, nullptr, "Unknown29"}, | 167 | {32, nullptr, "StopBleScanForSmartDevice"}, |
| 168 | {33, nullptr, "Unknown30"}, | 168 | {33, nullptr, "GetBleScanResultsForSmartDevice"}, |
| 169 | {34, nullptr, "Unknown31"}, | 169 | {34, nullptr, "AcquireBleConnectionEvent"}, |
| 170 | {35, nullptr, "Unknown32"}, | 170 | {35, nullptr, "BleConnect"}, |
| 171 | {36, nullptr, "Unknown33"}, | 171 | {36, nullptr, "BleOverrideConnection"}, |
| 172 | {37, nullptr, "Unknown34"}, | 172 | {37, nullptr, "BleDisconnect"}, |
| 173 | {38, nullptr, "Unknown35"}, | 173 | {38, nullptr, "BleGetConnectionState"}, |
| 174 | {39, nullptr, "Unknown36"}, | 174 | {39, nullptr, "BleGetGattClientConditionList"}, |
| 175 | {40, nullptr, "Unknown37"}, | 175 | {40, nullptr, "AcquireBlePairingEvent"}, |
| 176 | {41, nullptr, "Unknown38"}, | 176 | {41, nullptr, "BlePairDevice"}, |
| 177 | {42, nullptr, "Unknown39"}, | 177 | {42, nullptr, "BleUnpairDeviceOnBoth"}, |
| 178 | {43, nullptr, "Unknown40"}, | 178 | {43, nullptr, "BleUnpairDevice"}, |
| 179 | {44, nullptr, "Unknown41"}, | 179 | {44, nullptr, "BleGetPairedAddresses"}, |
| 180 | {45, nullptr, "Unknown42"}, | 180 | {45, nullptr, "AcquireBleServiceDiscoveryEvent"}, |
| 181 | {46, nullptr, "Unknown43"}, | 181 | {46, nullptr, "GetGattServices"}, |
| 182 | {47, nullptr, "Unknown44"}, | 182 | {47, nullptr, "GetGattService"}, |
| 183 | {48, nullptr, "Unknown45"}, | 183 | {48, nullptr, "GetGattIncludedServices"}, |
| 184 | {49, nullptr, "Unknown46"}, | 184 | {49, nullptr, "GetBelongingService"}, |
| 185 | {50, nullptr, "Unknown47"}, | 185 | {50, nullptr, "GetGattCharacteristics"}, |
| 186 | {51, nullptr, "Unknown48"}, | 186 | {51, nullptr, "GetGattDescriptors"}, |
| 187 | {52, nullptr, "Unknown49"}, | 187 | {52, nullptr, "AcquireBleMtuConfigEvent"}, |
| 188 | {53, nullptr, "Unknown50"}, | 188 | {53, nullptr, "ConfigureBleMtu"}, |
| 189 | {54, nullptr, "Unknown51"}, | 189 | {54, nullptr, "GetBleMtu"}, |
| 190 | {55, nullptr, "Unknown52"}, | 190 | {55, nullptr, "RegisterBleGattDataPath"}, |
| 191 | {56, nullptr, "Unknown53"}, | 191 | {56, nullptr, "UnregisterBleGattDataPath"}, |
| 192 | {57, nullptr, "Unknown54"}, | 192 | {57, nullptr, "RegisterAppletResourceUserId"}, |
| 193 | {58, nullptr, "Unknown55"}, | 193 | {58, nullptr, "UnregisterAppletResourceUserId"}, |
| 194 | {59, nullptr, "Unknown56"}, | 194 | {59, nullptr, "SetAppletResourceUserId"}, |
| 195 | {60, nullptr, "Unknown60"}, | ||
| 196 | {61, nullptr, "Unknown61"}, | ||
| 197 | {62, nullptr, "Unknown62"}, | ||
| 198 | {63, nullptr, "Unknown63"}, | ||
| 199 | {64, nullptr, "Unknown64"}, | ||
| 195 | }; | 200 | }; |
| 196 | // clang-format on | 201 | // clang-format on |
| 197 | 202 | ||
| @@ -204,19 +209,19 @@ public: | |||
| 204 | explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { | 209 | explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { |
| 205 | // clang-format off | 210 | // clang-format off |
| 206 | static const FunctionInfo functions[] = { | 211 | static const FunctionInfo functions[] = { |
| 207 | {0, nullptr, "RegisterSystemEventForDiscovery"}, | 212 | {0, nullptr, "AcquireDiscoveryEvent"}, |
| 208 | {1, nullptr, "Unknown1"}, | 213 | {1, nullptr, "StartDiscovery"}, |
| 209 | {2, nullptr, "Unknown2"}, | 214 | {2, nullptr, "CancelDiscovery"}, |
| 210 | {3, nullptr, "Unknown3"}, | 215 | {3, nullptr, "GetDeviceProperty"}, |
| 211 | {4, nullptr, "Unknown4"}, | 216 | {4, nullptr, "CreateBond"}, |
| 212 | {5, nullptr, "Unknown5"}, | 217 | {5, nullptr, "CancelBond"}, |
| 213 | {6, nullptr, "Unknown6"}, | 218 | {6, nullptr, "SetTsiMode"}, |
| 214 | {7, nullptr, "Unknown7"}, | 219 | {7, nullptr, "GeneralTest"}, |
| 215 | {8, nullptr, "Unknown8"}, | 220 | {8, nullptr, "HidConnect"}, |
| 216 | {9, nullptr, "Unknown9"}, | 221 | {9, nullptr, "GeneralGet"}, |
| 217 | {10, nullptr, "Unknown10"}, | 222 | {10, nullptr, "GetGattClientDisconnectionReason"}, |
| 218 | {11, nullptr, "Unknown11"}, | 223 | {11, nullptr, "GetBleConnectionParameter"}, |
| 219 | {12, nullptr, "Unknown11"}, | 224 | {12, nullptr, "GetBleConnectionParameterRequest"}, |
| 220 | }; | 225 | }; |
| 221 | // clang-format on | 226 | // clang-format on |
| 222 | 227 | ||
diff --git a/src/core/hle/service/es/es.cpp b/src/core/hle/service/es/es.cpp index f8e9df4b1..9365f27e1 100644 --- a/src/core/hle/service/es/es.cpp +++ b/src/core/hle/service/es/es.cpp | |||
| @@ -27,8 +27,8 @@ public: | |||
| 27 | {8, &ETicket::GetTitleKey, "GetTitleKey"}, | 27 | {8, &ETicket::GetTitleKey, "GetTitleKey"}, |
| 28 | {9, &ETicket::CountCommonTicket, "CountCommonTicket"}, | 28 | {9, &ETicket::CountCommonTicket, "CountCommonTicket"}, |
| 29 | {10, &ETicket::CountPersonalizedTicket, "CountPersonalizedTicket"}, | 29 | {10, &ETicket::CountPersonalizedTicket, "CountPersonalizedTicket"}, |
| 30 | {11, &ETicket::ListCommonTicket, "ListCommonTicket"}, | 30 | {11, &ETicket::ListCommonTicketRightsIds, "ListCommonTicketRightsIds"}, |
| 31 | {12, &ETicket::ListPersonalizedTicket, "ListPersonalizedTicket"}, | 31 | {12, &ETicket::ListPersonalizedTicketRightsIds, "ListPersonalizedTicketRightsIds"}, |
| 32 | {13, nullptr, "ListMissingPersonalizedTicket"}, | 32 | {13, nullptr, "ListMissingPersonalizedTicket"}, |
| 33 | {14, &ETicket::GetCommonTicketSize, "GetCommonTicketSize"}, | 33 | {14, &ETicket::GetCommonTicketSize, "GetCommonTicketSize"}, |
| 34 | {15, &ETicket::GetPersonalizedTicketSize, "GetPersonalizedTicketSize"}, | 34 | {15, &ETicket::GetPersonalizedTicketSize, "GetPersonalizedTicketSize"}, |
| @@ -55,7 +55,46 @@ public: | |||
| 55 | {36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"}, | 55 | {36, nullptr, "DeleteAllInactiveELicenseRequiredPersonalizedTicket"}, |
| 56 | {37, nullptr, "OwnTicket2"}, | 56 | {37, nullptr, "OwnTicket2"}, |
| 57 | {38, nullptr, "OwnTicket3"}, | 57 | {38, nullptr, "OwnTicket3"}, |
| 58 | {501, nullptr, "Unknown501"}, | ||
| 59 | {502, nullptr, "Unknown502"}, | ||
| 58 | {503, nullptr, "GetTitleKey"}, | 60 | {503, nullptr, "GetTitleKey"}, |
| 61 | {504, nullptr, "Unknown504"}, | ||
| 62 | {508, nullptr, "Unknown508"}, | ||
| 63 | {509, nullptr, "Unknown509"}, | ||
| 64 | {510, nullptr, "Unknown510"}, | ||
| 65 | {511, nullptr, "Unknown511"}, | ||
| 66 | {1001, nullptr, "Unknown1001"}, | ||
| 67 | {1002, nullptr, "Unknown1001"}, | ||
| 68 | {1003, nullptr, "Unknown1003"}, | ||
| 69 | {1004, nullptr, "Unknown1004"}, | ||
| 70 | {1005, nullptr, "Unknown1005"}, | ||
| 71 | {1006, nullptr, "Unknown1006"}, | ||
| 72 | {1007, nullptr, "Unknown1007"}, | ||
| 73 | {1009, nullptr, "Unknown1009"}, | ||
| 74 | {1010, nullptr, "Unknown1010"}, | ||
| 75 | {1011, nullptr, "Unknown1011"}, | ||
| 76 | {1012, nullptr, "Unknown1012"}, | ||
| 77 | {1013, nullptr, "Unknown1013"}, | ||
| 78 | {1014, nullptr, "Unknown1014"}, | ||
| 79 | {1015, nullptr, "Unknown1015"}, | ||
| 80 | {1016, nullptr, "Unknown1016"}, | ||
| 81 | {1017, nullptr, "Unknown1017"}, | ||
| 82 | {1018, nullptr, "Unknown1018"}, | ||
| 83 | {1019, nullptr, "Unknown1019"}, | ||
| 84 | {1020, nullptr, "Unknown1020"}, | ||
| 85 | {1021, nullptr, "Unknown1021"}, | ||
| 86 | {1501, nullptr, "Unknown1501"}, | ||
| 87 | {1502, nullptr, "Unknown1502"}, | ||
| 88 | {1503, nullptr, "Unknown1503"}, | ||
| 89 | {1504, nullptr, "Unknown1504"}, | ||
| 90 | {1505, nullptr, "Unknown1505"}, | ||
| 91 | {2000, nullptr, "Unknown2000"}, | ||
| 92 | {2001, nullptr, "Unknown2001"}, | ||
| 93 | {2100, nullptr, "Unknown2100"}, | ||
| 94 | {2501, nullptr, "Unknown2501"}, | ||
| 95 | {2502, nullptr, "Unknown2502"}, | ||
| 96 | {3001, nullptr, "Unknown3001"}, | ||
| 97 | {3002, nullptr, "Unknown3002"}, | ||
| 59 | }; | 98 | }; |
| 60 | // clang-format on | 99 | // clang-format on |
| 61 | RegisterHandlers(functions); | 100 | RegisterHandlers(functions); |
| @@ -147,7 +186,7 @@ private: | |||
| 147 | rb.Push<u32>(count); | 186 | rb.Push<u32>(count); |
| 148 | } | 187 | } |
| 149 | 188 | ||
| 150 | void ListCommonTicket(Kernel::HLERequestContext& ctx) { | 189 | void ListCommonTicketRightsIds(Kernel::HLERequestContext& ctx) { |
| 151 | u32 out_entries; | 190 | u32 out_entries; |
| 152 | if (keys.GetCommonTickets().empty()) | 191 | if (keys.GetCommonTickets().empty()) |
| 153 | out_entries = 0; | 192 | out_entries = 0; |
| @@ -170,7 +209,7 @@ private: | |||
| 170 | rb.Push<u32>(out_entries); | 209 | rb.Push<u32>(out_entries); |
| 171 | } | 210 | } |
| 172 | 211 | ||
| 173 | void ListPersonalizedTicket(Kernel::HLERequestContext& ctx) { | 212 | void ListPersonalizedTicketRightsIds(Kernel::HLERequestContext& ctx) { |
| 174 | u32 out_entries; | 213 | u32 out_entries; |
| 175 | if (keys.GetPersonalizedTickets().empty()) | 214 | if (keys.GetPersonalizedTickets().empty()) |
| 176 | out_entries = 0; | 215 | out_entries = 0; |
diff --git a/src/core/hle/service/eupld/eupld.cpp b/src/core/hle/service/eupld/eupld.cpp index 2df30acee..0d6d244f4 100644 --- a/src/core/hle/service/eupld/eupld.cpp +++ b/src/core/hle/service/eupld/eupld.cpp | |||
| @@ -19,6 +19,7 @@ public: | |||
| 19 | {1, nullptr, "ImportCrt"}, | 19 | {1, nullptr, "ImportCrt"}, |
| 20 | {2, nullptr, "ImportPki"}, | 20 | {2, nullptr, "ImportPki"}, |
| 21 | {3, nullptr, "SetAutoUpload"}, | 21 | {3, nullptr, "SetAutoUpload"}, |
| 22 | {4, nullptr, "GetAutoUpload"}, | ||
| 22 | }; | 23 | }; |
| 23 | // clang-format on | 24 | // clang-format on |
| 24 | 25 | ||
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp index 415c2829e..57d5edea7 100644 --- a/src/core/hle/service/hid/hid.cpp +++ b/src/core/hle/service/hid/hid.cpp | |||
| @@ -230,15 +230,15 @@ Hid::Hid(Core::System& system) : ServiceFramework("hid"), system(system) { | |||
| 230 | {211, nullptr, "IsVibrationDeviceMounted"}, | 230 | {211, nullptr, "IsVibrationDeviceMounted"}, |
| 231 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, | 231 | {300, &Hid::ActivateConsoleSixAxisSensor, "ActivateConsoleSixAxisSensor"}, |
| 232 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, | 232 | {301, &Hid::StartConsoleSixAxisSensor, "StartConsoleSixAxisSensor"}, |
| 233 | {302, nullptr, "StopConsoleSixAxisSensor"}, | 233 | {302, &Hid::StopConsoleSixAxisSensor, "StopConsoleSixAxisSensor"}, |
| 234 | {303, nullptr, "ActivateSevenSixAxisSensor"}, | 234 | {303, &Hid::ActivateSevenSixAxisSensor, "ActivateSevenSixAxisSensor"}, |
| 235 | {304, nullptr, "StartSevenSixAxisSensor"}, | 235 | {304, &Hid::StartSevenSixAxisSensor, "StartSevenSixAxisSensor"}, |
| 236 | {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"}, | 236 | {305, &Hid::StopSevenSixAxisSensor, "StopSevenSixAxisSensor"}, |
| 237 | {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"}, | 237 | {306, &Hid::InitializeSevenSixAxisSensor, "InitializeSevenSixAxisSensor"}, |
| 238 | {307, nullptr, "FinalizeSevenSixAxisSensor"}, | 238 | {307, &Hid::FinalizeSevenSixAxisSensor, "FinalizeSevenSixAxisSensor"}, |
| 239 | {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, | 239 | {308, nullptr, "SetSevenSixAxisSensorFusionStrength"}, |
| 240 | {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, | 240 | {309, nullptr, "GetSevenSixAxisSensorFusionStrength"}, |
| 241 | {310, nullptr, "ResetSevenSixAxisSensorTimestamp"}, | 241 | {310, &Hid::ResetSevenSixAxisSensorTimestamp, "ResetSevenSixAxisSensorTimestamp"}, |
| 242 | {400, nullptr, "IsUsbFullKeyControllerEnabled"}, | 242 | {400, nullptr, "IsUsbFullKeyControllerEnabled"}, |
| 243 | {401, nullptr, "EnableUsbFullKeyController"}, | 243 | {401, nullptr, "EnableUsbFullKeyController"}, |
| 244 | {402, nullptr, "IsUsbFullKeyControllerConnected"}, | 244 | {402, nullptr, "IsUsbFullKeyControllerConnected"}, |
| @@ -374,6 +374,15 @@ void Hid::ActivateKeyboard(Kernel::HLERequestContext& ctx) { | |||
| 374 | rb.Push(RESULT_SUCCESS); | 374 | rb.Push(RESULT_SUCCESS); |
| 375 | } | 375 | } |
| 376 | 376 | ||
| 377 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | ||
| 378 | IPC::RequestParser rp{ctx}; | ||
| 379 | const auto flags{rp.Pop<u32>()}; | ||
| 380 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | ||
| 381 | |||
| 382 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 383 | rb.Push(RESULT_SUCCESS); | ||
| 384 | } | ||
| 385 | |||
| 377 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { | 386 | void Hid::ActivateGesture(Kernel::HLERequestContext& ctx) { |
| 378 | IPC::RequestParser rp{ctx}; | 387 | IPC::RequestParser rp{ctx}; |
| 379 | const auto unknown{rp.Pop<u32>()}; | 388 | const auto unknown{rp.Pop<u32>()}; |
| @@ -413,6 +422,18 @@ void Hid::StartSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 413 | rb.Push(RESULT_SUCCESS); | 422 | rb.Push(RESULT_SUCCESS); |
| 414 | } | 423 | } |
| 415 | 424 | ||
| 425 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | ||
| 426 | IPC::RequestParser rp{ctx}; | ||
| 427 | const auto handle{rp.Pop<u32>()}; | ||
| 428 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 429 | |||
| 430 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, | ||
| 431 | applet_resource_user_id); | ||
| 432 | |||
| 433 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 434 | rb.Push(RESULT_SUCCESS); | ||
| 435 | } | ||
| 436 | |||
| 416 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { | 437 | void Hid::SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx) { |
| 417 | IPC::RequestParser rp{ctx}; | 438 | IPC::RequestParser rp{ctx}; |
| 418 | const auto handle{rp.Pop<u32>()}; | 439 | const auto handle{rp.Pop<u32>()}; |
| @@ -864,33 +885,35 @@ void Hid::StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 864 | rb.Push(RESULT_SUCCESS); | 885 | rb.Push(RESULT_SUCCESS); |
| 865 | } | 886 | } |
| 866 | 887 | ||
| 867 | void Hid::StopSixAxisSensor(Kernel::HLERequestContext& ctx) { | 888 | void Hid::StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 868 | IPC::RequestParser rp{ctx}; | 889 | IPC::RequestParser rp{ctx}; |
| 869 | const auto handle{rp.Pop<u32>()}; | 890 | const auto handle{rp.Pop<u32>()}; |
| 891 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 870 | 892 | ||
| 871 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}", handle); | 893 | LOG_WARNING(Service_HID, "(STUBBED) called, handle={}, applet_resource_user_id={}", handle, |
| 894 | applet_resource_user_id); | ||
| 872 | 895 | ||
| 873 | IPC::ResponseBuilder rb{ctx, 2}; | 896 | IPC::ResponseBuilder rb{ctx, 2}; |
| 874 | rb.Push(RESULT_SUCCESS); | 897 | rb.Push(RESULT_SUCCESS); |
| 875 | } | 898 | } |
| 876 | 899 | ||
| 877 | void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { | 900 | void Hid::ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 878 | IPC::RequestParser rp{ctx}; | 901 | IPC::RequestParser rp{ctx}; |
| 879 | const auto applet_resource_user_id{rp.Pop<u64>()}; | 902 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 880 | const auto unknown{rp.Pop<u32>()}; | ||
| 881 | 903 | ||
| 882 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}, unknown={}", | 904 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", |
| 883 | applet_resource_user_id, unknown); | 905 | applet_resource_user_id); |
| 884 | 906 | ||
| 885 | IPC::ResponseBuilder rb{ctx, 2}; | 907 | IPC::ResponseBuilder rb{ctx, 2}; |
| 886 | rb.Push(RESULT_SUCCESS); | 908 | rb.Push(RESULT_SUCCESS); |
| 887 | } | 909 | } |
| 888 | 910 | ||
| 889 | void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { | 911 | void Hid::StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 890 | IPC::RequestParser rp{ctx}; | 912 | IPC::RequestParser rp{ctx}; |
| 891 | const auto unknown{rp.Pop<u32>()}; | 913 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 892 | 914 | ||
| 893 | LOG_WARNING(Service_HID, "(STUBBED) called, unknown={}", unknown); | 915 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", |
| 916 | applet_resource_user_id); | ||
| 894 | 917 | ||
| 895 | IPC::ResponseBuilder rb{ctx, 2}; | 918 | IPC::ResponseBuilder rb{ctx, 2}; |
| 896 | rb.Push(RESULT_SUCCESS); | 919 | rb.Push(RESULT_SUCCESS); |
| @@ -914,10 +937,46 @@ void Hid::InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { | |||
| 914 | rb.Push(RESULT_SUCCESS); | 937 | rb.Push(RESULT_SUCCESS); |
| 915 | } | 938 | } |
| 916 | 939 | ||
| 917 | void Hid::SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx) { | 940 | void Hid::FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx) { |
| 918 | IPC::RequestParser rp{ctx}; | 941 | IPC::RequestParser rp{ctx}; |
| 919 | const auto flags{rp.Pop<u32>()}; | 942 | const auto applet_resource_user_id{rp.Pop<u64>()}; |
| 920 | LOG_WARNING(Service_HID, "(STUBBED) called. flags={}", flags); | 943 | |
| 944 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | ||
| 945 | applet_resource_user_id); | ||
| 946 | |||
| 947 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 948 | rb.Push(RESULT_SUCCESS); | ||
| 949 | } | ||
| 950 | |||
| 951 | void Hid::ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx) { | ||
| 952 | IPC::RequestParser rp{ctx}; | ||
| 953 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 954 | |||
| 955 | LOG_WARNING(Service_HID, "(STUBBED) called, applet_resource_user_id={}", | ||
| 956 | applet_resource_user_id); | ||
| 957 | |||
| 958 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 959 | rb.Push(RESULT_SUCCESS); | ||
| 960 | } | ||
| 961 | |||
| 962 | void Hid::SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx) { | ||
| 963 | IPC::RequestParser rp{ctx}; | ||
| 964 | const auto applet_resource_user_id{rp.Pop<u64>()}; | ||
| 965 | const auto is_palma_all_connectable{rp.Pop<bool>()}; | ||
| 966 | |||
| 967 | LOG_WARNING(Service_HID, | ||
| 968 | "(STUBBED) called, applet_resource_user_id={}, is_palma_all_connectable={}", | ||
| 969 | applet_resource_user_id, is_palma_all_connectable); | ||
| 970 | |||
| 971 | IPC::ResponseBuilder rb{ctx, 2}; | ||
| 972 | rb.Push(RESULT_SUCCESS); | ||
| 973 | } | ||
| 974 | |||
| 975 | void Hid::SetPalmaBoostMode(Kernel::HLERequestContext& ctx) { | ||
| 976 | IPC::RequestParser rp{ctx}; | ||
| 977 | const auto palma_boost_mode{rp.Pop<bool>()}; | ||
| 978 | |||
| 979 | LOG_WARNING(Service_HID, "(STUBBED) called, palma_boost_mode={}", palma_boost_mode); | ||
| 921 | 980 | ||
| 922 | IPC::ResponseBuilder rb{ctx, 2}; | 981 | IPC::ResponseBuilder rb{ctx, 2}; |
| 923 | rb.Push(RESULT_SUCCESS); | 982 | rb.Push(RESULT_SUCCESS); |
diff --git a/src/core/hle/service/hid/hid.h b/src/core/hle/service/hid/hid.h index 41b330fa9..6fb048360 100644 --- a/src/core/hle/service/hid/hid.h +++ b/src/core/hle/service/hid/hid.h | |||
| @@ -91,9 +91,11 @@ private: | |||
| 91 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); | 91 | void ActivateTouchScreen(Kernel::HLERequestContext& ctx); |
| 92 | void ActivateMouse(Kernel::HLERequestContext& ctx); | 92 | void ActivateMouse(Kernel::HLERequestContext& ctx); |
| 93 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); | 93 | void ActivateKeyboard(Kernel::HLERequestContext& ctx); |
| 94 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | ||
| 94 | void ActivateGesture(Kernel::HLERequestContext& ctx); | 95 | void ActivateGesture(Kernel::HLERequestContext& ctx); |
| 95 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); | 96 | void ActivateNpadWithRevision(Kernel::HLERequestContext& ctx); |
| 96 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); | 97 | void StartSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 98 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | ||
| 97 | void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 99 | void SetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 98 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 100 | void GetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| 99 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); | 101 | void ResetGyroscopeZeroDriftMode(Kernel::HLERequestContext& ctx); |
| @@ -128,12 +130,15 @@ private: | |||
| 128 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); | 130 | void IsVibrationPermitted(Kernel::HLERequestContext& ctx); |
| 129 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 131 | void ActivateConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 130 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); | 132 | void StartConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 131 | void StopSixAxisSensor(Kernel::HLERequestContext& ctx); | 133 | void StopConsoleSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 132 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | 134 | void ActivateSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 133 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | 135 | void StartSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 134 | void StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx); | 136 | void StopSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 135 | void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); | 137 | void InitializeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 136 | void SendKeyboardLockKeyEvent(Kernel::HLERequestContext& ctx); | 138 | void FinalizeSevenSixAxisSensor(Kernel::HLERequestContext& ctx); |
| 139 | void ResetSevenSixAxisSensorTimestamp(Kernel::HLERequestContext& ctx); | ||
| 140 | void SetIsPalmaAllConnectable(Kernel::HLERequestContext& ctx); | ||
| 141 | void SetPalmaBoostMode(Kernel::HLERequestContext& ctx); | ||
| 137 | 142 | ||
| 138 | std::shared_ptr<IAppletResource> applet_resource; | 143 | std::shared_ptr<IAppletResource> applet_resource; |
| 139 | Core::System& system; | 144 | Core::System& system; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index bae1d527c..cf8bdd021 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -41,7 +41,11 @@ class BufferCache { | |||
| 41 | static constexpr u64 BLOCK_PAGE_SIZE = 1ULL << BLOCK_PAGE_BITS; | 41 | static constexpr u64 BLOCK_PAGE_SIZE = 1ULL << BLOCK_PAGE_BITS; |
| 42 | 42 | ||
| 43 | public: | 43 | public: |
| 44 | using BufferInfo = std::pair<BufferType, u64>; | 44 | struct BufferInfo { |
| 45 | BufferType handle; | ||
| 46 | u64 offset; | ||
| 47 | u64 address; | ||
| 48 | }; | ||
| 45 | 49 | ||
| 46 | BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, | 50 | BufferInfo UploadMemory(GPUVAddr gpu_addr, std::size_t size, std::size_t alignment = 4, |
| 47 | bool is_written = false, bool use_fast_cbuf = false) { | 51 | bool is_written = false, bool use_fast_cbuf = false) { |
| @@ -50,7 +54,7 @@ public: | |||
| 50 | auto& memory_manager = system.GPU().MemoryManager(); | 54 | auto& memory_manager = system.GPU().MemoryManager(); |
| 51 | const std::optional<VAddr> cpu_addr_opt = memory_manager.GpuToCpuAddress(gpu_addr); | 55 | const std::optional<VAddr> cpu_addr_opt = memory_manager.GpuToCpuAddress(gpu_addr); |
| 52 | if (!cpu_addr_opt) { | 56 | if (!cpu_addr_opt) { |
| 53 | return {GetEmptyBuffer(size), 0}; | 57 | return GetEmptyBuffer(size); |
| 54 | } | 58 | } |
| 55 | const VAddr cpu_addr = *cpu_addr_opt; | 59 | const VAddr cpu_addr = *cpu_addr_opt; |
| 56 | 60 | ||
| @@ -88,7 +92,7 @@ public: | |||
| 88 | Buffer* const block = GetBlock(cpu_addr, size); | 92 | Buffer* const block = GetBlock(cpu_addr, size); |
| 89 | MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size); | 93 | MapInterval* const map = MapAddress(block, gpu_addr, cpu_addr, size); |
| 90 | if (!map) { | 94 | if (!map) { |
| 91 | return {GetEmptyBuffer(size), 0}; | 95 | return GetEmptyBuffer(size); |
| 92 | } | 96 | } |
| 93 | if (is_written) { | 97 | if (is_written) { |
| 94 | map->MarkAsModified(true, GetModifiedTicks()); | 98 | map->MarkAsModified(true, GetModifiedTicks()); |
| @@ -101,7 +105,7 @@ public: | |||
| 101 | } | 105 | } |
| 102 | } | 106 | } |
| 103 | 107 | ||
| 104 | return {block->Handle(), static_cast<u64>(block->Offset(cpu_addr))}; | 108 | return BufferInfo{block->Handle(), block->Offset(cpu_addr), block->Address()}; |
| 105 | } | 109 | } |
| 106 | 110 | ||
| 107 | /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. | 111 | /// Uploads from a host memory. Returns the OpenGL buffer where it's located and its offset. |
| @@ -254,27 +258,17 @@ public: | |||
| 254 | committed_flushes.pop_front(); | 258 | committed_flushes.pop_front(); |
| 255 | } | 259 | } |
| 256 | 260 | ||
| 257 | virtual BufferType GetEmptyBuffer(std::size_t size) = 0; | 261 | virtual BufferInfo GetEmptyBuffer(std::size_t size) = 0; |
| 258 | 262 | ||
| 259 | protected: | 263 | protected: |
| 260 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 264 | explicit BufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, |
| 261 | std::unique_ptr<StreamBuffer> stream_buffer_) | 265 | std::unique_ptr<StreamBuffer> stream_buffer) |
| 262 | : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer_)}, | 266 | : rasterizer{rasterizer}, system{system}, stream_buffer{std::move(stream_buffer)} {} |
| 263 | stream_buffer_handle{stream_buffer->Handle()} {} | ||
| 264 | 267 | ||
| 265 | ~BufferCache() = default; | 268 | ~BufferCache() = default; |
| 266 | 269 | ||
| 267 | virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; | 270 | virtual std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) = 0; |
| 268 | 271 | ||
| 269 | virtual void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 270 | const u8* data) = 0; | ||
| 271 | |||
| 272 | virtual void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 273 | u8* data) = 0; | ||
| 274 | |||
| 275 | virtual void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 276 | std::size_t dst_offset, std::size_t size) = 0; | ||
| 277 | |||
| 278 | virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { | 272 | virtual BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) { |
| 279 | return {}; | 273 | return {}; |
| 280 | } | 274 | } |
| @@ -336,11 +330,11 @@ private: | |||
| 336 | const VAddr cpu_addr_end = cpu_addr + size; | 330 | const VAddr cpu_addr_end = cpu_addr + size; |
| 337 | if (memory_manager.IsGranularRange(gpu_addr, size)) { | 331 | if (memory_manager.IsGranularRange(gpu_addr, size)) { |
| 338 | u8* host_ptr = memory_manager.GetPointer(gpu_addr); | 332 | u8* host_ptr = memory_manager.GetPointer(gpu_addr); |
| 339 | UploadBlockData(*block, block->Offset(cpu_addr), size, host_ptr); | 333 | block->Upload(block->Offset(cpu_addr), size, host_ptr); |
| 340 | } else { | 334 | } else { |
| 341 | staging_buffer.resize(size); | 335 | staging_buffer.resize(size); |
| 342 | memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); | 336 | memory_manager.ReadBlockUnsafe(gpu_addr, staging_buffer.data(), size); |
| 343 | UploadBlockData(*block, block->Offset(cpu_addr), size, staging_buffer.data()); | 337 | block->Upload(block->Offset(cpu_addr), size, staging_buffer.data()); |
| 344 | } | 338 | } |
| 345 | return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); | 339 | return Register(MapInterval(cpu_addr, cpu_addr_end, gpu_addr)); |
| 346 | } | 340 | } |
| @@ -399,7 +393,7 @@ private: | |||
| 399 | } | 393 | } |
| 400 | staging_buffer.resize(size); | 394 | staging_buffer.resize(size); |
| 401 | system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size); | 395 | system.Memory().ReadBlockUnsafe(interval.lower(), staging_buffer.data(), size); |
| 402 | UploadBlockData(*block, block->Offset(interval.lower()), size, staging_buffer.data()); | 396 | block->Upload(block->Offset(interval.lower()), size, staging_buffer.data()); |
| 403 | } | 397 | } |
| 404 | } | 398 | } |
| 405 | 399 | ||
| @@ -436,7 +430,7 @@ private: | |||
| 436 | 430 | ||
| 437 | const std::size_t size = map->end - map->start; | 431 | const std::size_t size = map->end - map->start; |
| 438 | staging_buffer.resize(size); | 432 | staging_buffer.resize(size); |
| 439 | DownloadBlockData(*block, block->Offset(map->start), size, staging_buffer.data()); | 433 | block->Download(block->Offset(map->start), size, staging_buffer.data()); |
| 440 | system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); | 434 | system.Memory().WriteBlockUnsafe(map->start, staging_buffer.data(), size); |
| 441 | map->MarkAsModified(false, 0); | 435 | map->MarkAsModified(false, 0); |
| 442 | } | 436 | } |
| @@ -449,7 +443,7 @@ private: | |||
| 449 | 443 | ||
| 450 | buffer_ptr += size; | 444 | buffer_ptr += size; |
| 451 | buffer_offset += size; | 445 | buffer_offset += size; |
| 452 | return {stream_buffer_handle, uploaded_offset}; | 446 | return BufferInfo{stream_buffer->Handle(), uploaded_offset, stream_buffer->Address()}; |
| 453 | } | 447 | } |
| 454 | 448 | ||
| 455 | void AlignBuffer(std::size_t alignment) { | 449 | void AlignBuffer(std::size_t alignment) { |
| @@ -464,7 +458,7 @@ private: | |||
| 464 | const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; | 458 | const std::size_t new_size = old_size + BLOCK_PAGE_SIZE; |
| 465 | const VAddr cpu_addr = buffer->CpuAddr(); | 459 | const VAddr cpu_addr = buffer->CpuAddr(); |
| 466 | std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); | 460 | std::shared_ptr<Buffer> new_buffer = CreateBlock(cpu_addr, new_size); |
| 467 | CopyBlock(*buffer, *new_buffer, 0, 0, old_size); | 461 | new_buffer->CopyFrom(*buffer, 0, 0, old_size); |
| 468 | QueueDestruction(std::move(buffer)); | 462 | QueueDestruction(std::move(buffer)); |
| 469 | 463 | ||
| 470 | const VAddr cpu_addr_end = cpu_addr + new_size - 1; | 464 | const VAddr cpu_addr_end = cpu_addr + new_size - 1; |
| @@ -486,8 +480,8 @@ private: | |||
| 486 | const std::size_t new_size = size_1 + size_2; | 480 | const std::size_t new_size = size_1 + size_2; |
| 487 | 481 | ||
| 488 | std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); | 482 | std::shared_ptr<Buffer> new_buffer = CreateBlock(new_addr, new_size); |
| 489 | CopyBlock(*first, *new_buffer, 0, new_buffer->Offset(first_addr), size_1); | 483 | new_buffer->CopyFrom(*first, 0, new_buffer->Offset(first_addr), size_1); |
| 490 | CopyBlock(*second, *new_buffer, 0, new_buffer->Offset(second_addr), size_2); | 484 | new_buffer->CopyFrom(*second, 0, new_buffer->Offset(second_addr), size_2); |
| 491 | QueueDestruction(std::move(first)); | 485 | QueueDestruction(std::move(first)); |
| 492 | QueueDestruction(std::move(second)); | 486 | QueueDestruction(std::move(second)); |
| 493 | 487 | ||
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index e7cb87589..d374b73cf 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -661,6 +661,10 @@ union Instruction { | |||
| 661 | constexpr Instruction(u64 value) : value{value} {} | 661 | constexpr Instruction(u64 value) : value{value} {} |
| 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} | 662 | constexpr Instruction(const Instruction& instr) : value(instr.value) {} |
| 663 | 663 | ||
| 664 | constexpr bool Bit(u64 offset) const { | ||
| 665 | return ((value >> offset) & 1) != 0; | ||
| 666 | } | ||
| 667 | |||
| 664 | BitField<0, 8, Register> gpr0; | 668 | BitField<0, 8, Register> gpr0; |
| 665 | BitField<8, 8, Register> gpr8; | 669 | BitField<8, 8, Register> gpr8; |
| 666 | union { | 670 | union { |
| @@ -1874,7 +1878,9 @@ public: | |||
| 1874 | HSETP2_C, | 1878 | HSETP2_C, |
| 1875 | HSETP2_R, | 1879 | HSETP2_R, |
| 1876 | HSETP2_IMM, | 1880 | HSETP2_IMM, |
| 1881 | HSET2_C, | ||
| 1877 | HSET2_R, | 1882 | HSET2_R, |
| 1883 | HSET2_IMM, | ||
| 1878 | POPC_C, | 1884 | POPC_C, |
| 1879 | POPC_R, | 1885 | POPC_R, |
| 1880 | POPC_IMM, | 1886 | POPC_IMM, |
| @@ -2194,7 +2200,9 @@ private: | |||
| 2194 | INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), | 2200 | INST("0111111-1-------", Id::HSETP2_C, Type::HalfSetPredicate, "HSETP2_C"), |
| 2195 | INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), | 2201 | INST("0101110100100---", Id::HSETP2_R, Type::HalfSetPredicate, "HSETP2_R"), |
| 2196 | INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), | 2202 | INST("0111111-0-------", Id::HSETP2_IMM, Type::HalfSetPredicate, "HSETP2_IMM"), |
| 2203 | INST("0111110-1-------", Id::HSET2_C, Type::HalfSet, "HSET2_C"), | ||
| 2197 | INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), | 2204 | INST("0101110100011---", Id::HSET2_R, Type::HalfSet, "HSET2_R"), |
| 2205 | INST("0111110-0-------", Id::HSET2_IMM, Type::HalfSet, "HSET2_IMM"), | ||
| 2198 | INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), | 2206 | INST("010110111010----", Id::FCMP_RR, Type::Arithmetic, "FCMP_RR"), |
| 2199 | INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), | 2207 | INST("010010111010----", Id::FCMP_RC, Type::Arithmetic, "FCMP_RC"), |
| 2200 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), | 2208 | INST("0101000010000---", Id::MUFU, Type::Arithmetic, "MUFU"), |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.cpp b/src/video_core/renderer_opengl/gl_buffer_cache.cpp index ad0577a4f..d9f7b4cc6 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.cpp +++ b/src/video_core/renderer_opengl/gl_buffer_cache.cpp | |||
| @@ -22,21 +22,46 @@ using Maxwell = Tegra::Engines::Maxwell3D::Regs; | |||
| 22 | 22 | ||
| 23 | MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); | 23 | MICROPROFILE_DEFINE(OpenGL_Buffer_Download, "OpenGL", "Buffer Download", MP_RGB(192, 192, 128)); |
| 24 | 24 | ||
| 25 | Buffer::Buffer(VAddr cpu_addr, const std::size_t size) : VideoCommon::BufferBlock{cpu_addr, size} { | 25 | Buffer::Buffer(const Device& device, VAddr cpu_addr, std::size_t size) |
| 26 | : VideoCommon::BufferBlock{cpu_addr, size} { | ||
| 26 | gl_buffer.Create(); | 27 | gl_buffer.Create(); |
| 27 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); | 28 | glNamedBufferData(gl_buffer.handle, static_cast<GLsizeiptr>(size), nullptr, GL_DYNAMIC_DRAW); |
| 29 | if (device.HasVertexBufferUnifiedMemory()) { | ||
| 30 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_WRITE); | ||
| 31 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); | ||
| 32 | } | ||
| 28 | } | 33 | } |
| 29 | 34 | ||
| 30 | Buffer::~Buffer() = default; | 35 | Buffer::~Buffer() = default; |
| 31 | 36 | ||
| 37 | void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { | ||
| 38 | glNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||
| 39 | data); | ||
| 40 | } | ||
| 41 | |||
| 42 | void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { | ||
| 43 | MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||
| 44 | glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||
| 45 | glGetNamedBufferSubData(Handle(), static_cast<GLintptr>(offset), static_cast<GLsizeiptr>(size), | ||
| 46 | data); | ||
| 47 | } | ||
| 48 | |||
| 49 | void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 50 | std::size_t size) const { | ||
| 51 | glCopyNamedBufferSubData(src.Handle(), Handle(), static_cast<GLintptr>(src_offset), | ||
| 52 | static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||
| 53 | } | ||
| 54 | |||
| 32 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, | 55 | OGLBufferCache::OGLBufferCache(RasterizerOpenGL& rasterizer, Core::System& system, |
| 33 | const Device& device, std::size_t stream_size) | 56 | const Device& device_, std::size_t stream_size) |
| 34 | : GenericBufferCache{rasterizer, system, std::make_unique<OGLStreamBuffer>(stream_size, true)} { | 57 | : GenericBufferCache{rasterizer, system, |
| 58 | std::make_unique<OGLStreamBuffer>(device_, stream_size, true)}, | ||
| 59 | device{device_} { | ||
| 35 | if (!device.HasFastBufferSubData()) { | 60 | if (!device.HasFastBufferSubData()) { |
| 36 | return; | 61 | return; |
| 37 | } | 62 | } |
| 38 | 63 | ||
| 39 | static constexpr auto size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize); | 64 | static constexpr GLsizeiptr size = static_cast<GLsizeiptr>(Maxwell::MaxConstBufferSize); |
| 40 | glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); | 65 | glCreateBuffers(static_cast<GLsizei>(std::size(cbufs)), std::data(cbufs)); |
| 41 | for (const GLuint cbuf : cbufs) { | 66 | for (const GLuint cbuf : cbufs) { |
| 42 | glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW); | 67 | glNamedBufferData(cbuf, size, nullptr, GL_STREAM_DRAW); |
| @@ -48,39 +73,20 @@ OGLBufferCache::~OGLBufferCache() { | |||
| 48 | } | 73 | } |
| 49 | 74 | ||
| 50 | std::shared_ptr<Buffer> OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | 75 | std::shared_ptr<Buffer> OGLBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { |
| 51 | return std::make_shared<Buffer>(cpu_addr, size); | 76 | return std::make_shared<Buffer>(device, cpu_addr, size); |
| 52 | } | 77 | } |
| 53 | 78 | ||
| 54 | GLuint OGLBufferCache::GetEmptyBuffer(std::size_t) { | 79 | OGLBufferCache::BufferInfo OGLBufferCache::GetEmptyBuffer(std::size_t) { |
| 55 | return 0; | 80 | return {0, 0, 0}; |
| 56 | } | ||
| 57 | |||
| 58 | void OGLBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 59 | const u8* data) { | ||
| 60 | glNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||
| 61 | static_cast<GLsizeiptr>(size), data); | ||
| 62 | } | ||
| 63 | |||
| 64 | void OGLBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 65 | u8* data) { | ||
| 66 | MICROPROFILE_SCOPE(OpenGL_Buffer_Download); | ||
| 67 | glMemoryBarrier(GL_BUFFER_UPDATE_BARRIER_BIT); | ||
| 68 | glGetNamedBufferSubData(buffer.Handle(), static_cast<GLintptr>(offset), | ||
| 69 | static_cast<GLsizeiptr>(size), data); | ||
| 70 | } | ||
| 71 | |||
| 72 | void OGLBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 73 | std::size_t dst_offset, std::size_t size) { | ||
| 74 | glCopyNamedBufferSubData(src.Handle(), dst.Handle(), static_cast<GLintptr>(src_offset), | ||
| 75 | static_cast<GLintptr>(dst_offset), static_cast<GLsizeiptr>(size)); | ||
| 76 | } | 81 | } |
| 77 | 82 | ||
| 78 | OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, | 83 | OGLBufferCache::BufferInfo OGLBufferCache::ConstBufferUpload(const void* raw_pointer, |
| 79 | std::size_t size) { | 84 | std::size_t size) { |
| 80 | DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); | 85 | DEBUG_ASSERT(cbuf_cursor < std::size(cbufs)); |
| 81 | const GLuint cbuf = cbufs[cbuf_cursor++]; | 86 | const GLuint cbuf = cbufs[cbuf_cursor++]; |
| 87 | |||
| 82 | glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); | 88 | glNamedBufferSubData(cbuf, 0, static_cast<GLsizeiptr>(size), raw_pointer); |
| 83 | return {cbuf, 0}; | 89 | return {cbuf, 0, 0}; |
| 84 | } | 90 | } |
| 85 | 91 | ||
| 86 | } // namespace OpenGL | 92 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_buffer_cache.h b/src/video_core/renderer_opengl/gl_buffer_cache.h index a49aaf9c4..59d95adbc 100644 --- a/src/video_core/renderer_opengl/gl_buffer_cache.h +++ b/src/video_core/renderer_opengl/gl_buffer_cache.h | |||
| @@ -25,15 +25,27 @@ class RasterizerOpenGL; | |||
| 25 | 25 | ||
| 26 | class Buffer : public VideoCommon::BufferBlock { | 26 | class Buffer : public VideoCommon::BufferBlock { |
| 27 | public: | 27 | public: |
| 28 | explicit Buffer(VAddr cpu_addr, const std::size_t size); | 28 | explicit Buffer(const Device& device, VAddr cpu_addr, std::size_t size); |
| 29 | ~Buffer(); | 29 | ~Buffer(); |
| 30 | 30 | ||
| 31 | GLuint Handle() const { | 31 | void Upload(std::size_t offset, std::size_t size, const u8* data) const; |
| 32 | |||
| 33 | void Download(std::size_t offset, std::size_t size, u8* data) const; | ||
| 34 | |||
| 35 | void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 36 | std::size_t size) const; | ||
| 37 | |||
| 38 | GLuint Handle() const noexcept { | ||
| 32 | return gl_buffer.handle; | 39 | return gl_buffer.handle; |
| 33 | } | 40 | } |
| 34 | 41 | ||
| 42 | u64 Address() const noexcept { | ||
| 43 | return gpu_address; | ||
| 44 | } | ||
| 45 | |||
| 35 | private: | 46 | private: |
| 36 | OGLBuffer gl_buffer; | 47 | OGLBuffer gl_buffer; |
| 48 | u64 gpu_address = 0; | ||
| 37 | }; | 49 | }; |
| 38 | 50 | ||
| 39 | using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>; | 51 | using GenericBufferCache = VideoCommon::BufferCache<Buffer, GLuint, OGLStreamBuffer>; |
| @@ -43,7 +55,7 @@ public: | |||
| 43 | const Device& device, std::size_t stream_size); | 55 | const Device& device, std::size_t stream_size); |
| 44 | ~OGLBufferCache(); | 56 | ~OGLBufferCache(); |
| 45 | 57 | ||
| 46 | GLuint GetEmptyBuffer(std::size_t) override; | 58 | BufferInfo GetEmptyBuffer(std::size_t) override; |
| 47 | 59 | ||
| 48 | void Acquire() noexcept { | 60 | void Acquire() noexcept { |
| 49 | cbuf_cursor = 0; | 61 | cbuf_cursor = 0; |
| @@ -52,22 +64,16 @@ public: | |||
| 52 | protected: | 64 | protected: |
| 53 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | 65 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; |
| 54 | 66 | ||
| 55 | void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 56 | const u8* data) override; | ||
| 57 | |||
| 58 | void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 59 | u8* data) override; | ||
| 60 | |||
| 61 | void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 62 | std::size_t dst_offset, std::size_t size) override; | ||
| 63 | |||
| 64 | BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override; | 67 | BufferInfo ConstBufferUpload(const void* raw_pointer, std::size_t size) override; |
| 65 | 68 | ||
| 66 | private: | 69 | private: |
| 70 | static constexpr std::size_t NUM_CBUFS = Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers * | ||
| 71 | Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram; | ||
| 72 | |||
| 73 | const Device& device; | ||
| 74 | |||
| 67 | std::size_t cbuf_cursor = 0; | 75 | std::size_t cbuf_cursor = 0; |
| 68 | std::array<GLuint, Tegra::Engines::Maxwell3D::Regs::MaxConstBuffers * | 76 | std::array<GLuint, NUM_CBUFS> cbufs{}; |
| 69 | Tegra::Engines::Maxwell3D::Regs::MaxShaderProgram> | ||
| 70 | cbufs; | ||
| 71 | }; | 77 | }; |
| 72 | 78 | ||
| 73 | } // namespace OpenGL | 79 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_device.cpp b/src/video_core/renderer_opengl/gl_device.cpp index 1011c7738..b6b6659c1 100644 --- a/src/video_core/renderer_opengl/gl_device.cpp +++ b/src/video_core/renderer_opengl/gl_device.cpp | |||
| @@ -178,7 +178,7 @@ bool IsASTCSupported() { | |||
| 178 | for (const GLenum format : formats) { | 178 | for (const GLenum format : formats) { |
| 179 | for (const GLenum support : required_support) { | 179 | for (const GLenum support : required_support) { |
| 180 | GLint value; | 180 | GLint value; |
| 181 | glGetInternalformativ(GL_TEXTURE_2D, format, support, 1, &value); | 181 | glGetInternalformativ(target, format, support, 1, &value); |
| 182 | if (value != GL_FULL_SUPPORT) { | 182 | if (value != GL_FULL_SUPPORT) { |
| 183 | return false; | 183 | return false; |
| 184 | } | 184 | } |
| @@ -188,16 +188,32 @@ bool IsASTCSupported() { | |||
| 188 | return true; | 188 | return true; |
| 189 | } | 189 | } |
| 190 | 190 | ||
| 191 | /// @brief Returns true when a GL_RENDERER is a Turing GPU | ||
| 192 | /// @param renderer GL_RENDERER string | ||
| 193 | bool IsTuring(std::string_view renderer) { | ||
| 194 | static constexpr std::array<std::string_view, 12> TURING_GPUS = { | ||
| 195 | "GTX 1650", "GTX 1660", "RTX 2060", "RTX 2070", | ||
| 196 | "RTX 2080", "TITAN RTX", "Quadro RTX 3000", "Quadro RTX 4000", | ||
| 197 | "Quadro RTX 5000", "Quadro RTX 6000", "Quadro RTX 8000", "Tesla T4", | ||
| 198 | }; | ||
| 199 | return std::any_of(TURING_GPUS.begin(), TURING_GPUS.end(), | ||
| 200 | [renderer](std::string_view candidate) { | ||
| 201 | return renderer.find(candidate) != std::string_view::npos; | ||
| 202 | }); | ||
| 203 | } | ||
| 204 | |||
| 191 | } // Anonymous namespace | 205 | } // Anonymous namespace |
| 192 | 206 | ||
| 193 | Device::Device() | 207 | Device::Device() |
| 194 | : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} { | 208 | : max_uniform_buffers{BuildMaxUniformBuffers()}, base_bindings{BuildBaseBindings()} { |
| 195 | const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); | 209 | const std::string_view vendor = reinterpret_cast<const char*>(glGetString(GL_VENDOR)); |
| 210 | const std::string_view renderer = reinterpret_cast<const char*>(glGetString(GL_RENDERER)); | ||
| 196 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); | 211 | const std::string_view version = reinterpret_cast<const char*>(glGetString(GL_VERSION)); |
| 197 | const std::vector extensions = GetExtensions(); | 212 | const std::vector extensions = GetExtensions(); |
| 198 | 213 | ||
| 199 | const bool is_nvidia = vendor == "NVIDIA Corporation"; | 214 | const bool is_nvidia = vendor == "NVIDIA Corporation"; |
| 200 | const bool is_amd = vendor == "ATI Technologies Inc."; | 215 | const bool is_amd = vendor == "ATI Technologies Inc."; |
| 216 | const bool is_turing = is_nvidia && IsTuring(renderer); | ||
| 201 | 217 | ||
| 202 | bool disable_fast_buffer_sub_data = false; | 218 | bool disable_fast_buffer_sub_data = false; |
| 203 | if (is_nvidia && version == "4.6.0 NVIDIA 443.24") { | 219 | if (is_nvidia && version == "4.6.0 NVIDIA 443.24") { |
| @@ -221,8 +237,16 @@ Device::Device() | |||
| 221 | has_variable_aoffi = TestVariableAoffi(); | 237 | has_variable_aoffi = TestVariableAoffi(); |
| 222 | has_component_indexing_bug = is_amd; | 238 | has_component_indexing_bug = is_amd; |
| 223 | has_precise_bug = TestPreciseBug(); | 239 | has_precise_bug = TestPreciseBug(); |
| 224 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | ||
| 225 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; | 240 | has_nv_viewport_array2 = GLAD_GL_NV_viewport_array2; |
| 241 | |||
| 242 | // At the moment of writing this, only Nvidia's driver optimizes BufferSubData on exclusive | ||
| 243 | // uniform buffers as "push constants" | ||
| 244 | has_fast_buffer_sub_data = is_nvidia && !disable_fast_buffer_sub_data; | ||
| 245 | |||
| 246 | // Nvidia's driver on Turing GPUs randomly crashes when the buffer is made resident, or on | ||
| 247 | // DeleteBuffers. Disable unified memory on these devices. | ||
| 248 | has_vertex_buffer_unified_memory = GLAD_GL_NV_vertex_buffer_unified_memory && !is_turing; | ||
| 249 | |||
| 226 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && | 250 | use_assembly_shaders = Settings::values.use_assembly_shaders && GLAD_GL_NV_gpu_program5 && |
| 227 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && | 251 | GLAD_GL_NV_compute_program5 && GLAD_GL_NV_transform_feedback && |
| 228 | GLAD_GL_NV_transform_feedback2; | 252 | GLAD_GL_NV_transform_feedback2; |
diff --git a/src/video_core/renderer_opengl/gl_device.h b/src/video_core/renderer_opengl/gl_device.h index c86e709b1..e1d811966 100644 --- a/src/video_core/renderer_opengl/gl_device.h +++ b/src/video_core/renderer_opengl/gl_device.h | |||
| @@ -72,6 +72,10 @@ public: | |||
| 72 | return has_texture_shadow_lod; | 72 | return has_texture_shadow_lod; |
| 73 | } | 73 | } |
| 74 | 74 | ||
| 75 | bool HasVertexBufferUnifiedMemory() const { | ||
| 76 | return has_vertex_buffer_unified_memory; | ||
| 77 | } | ||
| 78 | |||
| 75 | bool HasASTC() const { | 79 | bool HasASTC() const { |
| 76 | return has_astc; | 80 | return has_astc; |
| 77 | } | 81 | } |
| @@ -115,6 +119,7 @@ private: | |||
| 115 | bool has_vertex_viewport_layer{}; | 119 | bool has_vertex_viewport_layer{}; |
| 116 | bool has_image_load_formatted{}; | 120 | bool has_image_load_formatted{}; |
| 117 | bool has_texture_shadow_lod{}; | 121 | bool has_texture_shadow_lod{}; |
| 122 | bool has_vertex_buffer_unified_memory{}; | ||
| 118 | bool has_astc{}; | 123 | bool has_astc{}; |
| 119 | bool has_variable_aoffi{}; | 124 | bool has_variable_aoffi{}; |
| 120 | bool has_component_indexing_bug{}; | 125 | bool has_component_indexing_bug{}; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 2d6c11320..362457ffe 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -61,7 +61,8 @@ constexpr std::size_t NUM_CONST_BUFFERS_BYTES_PER_STAGE = | |||
| 61 | constexpr std::size_t TOTAL_CONST_BUFFER_BYTES = | 61 | constexpr std::size_t TOTAL_CONST_BUFFER_BYTES = |
| 62 | NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage; | 62 | NUM_CONST_BUFFERS_BYTES_PER_STAGE * Maxwell::MaxShaderStage; |
| 63 | 63 | ||
| 64 | constexpr std::size_t NumSupportedVertexAttributes = 16; | 64 | constexpr std::size_t NUM_SUPPORTED_VERTEX_ATTRIBUTES = 16; |
| 65 | constexpr std::size_t NUM_SUPPORTED_VERTEX_BINDINGS = 16; | ||
| 65 | 66 | ||
| 66 | template <typename Engine, typename Entry> | 67 | template <typename Engine, typename Entry> |
| 67 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, | 68 | Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry& entry, |
| @@ -193,7 +194,7 @@ void RasterizerOpenGL::SetupVertexFormat() { | |||
| 193 | // avoid OpenGL errors. | 194 | // avoid OpenGL errors. |
| 194 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't | 195 | // TODO(Subv): Analyze the shader to identify which attributes are actually used and don't |
| 195 | // assume every shader uses them all. | 196 | // assume every shader uses them all. |
| 196 | for (std::size_t index = 0; index < NumSupportedVertexAttributes; ++index) { | 197 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) { |
| 197 | if (!flags[Dirty::VertexFormat0 + index]) { | 198 | if (!flags[Dirty::VertexFormat0 + index]) { |
| 198 | continue; | 199 | continue; |
| 199 | } | 200 | } |
| @@ -231,9 +232,11 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 231 | 232 | ||
| 232 | MICROPROFILE_SCOPE(OpenGL_VB); | 233 | MICROPROFILE_SCOPE(OpenGL_VB); |
| 233 | 234 | ||
| 235 | const bool use_unified_memory = device.HasVertexBufferUnifiedMemory(); | ||
| 236 | |||
| 234 | // Upload all guest vertex arrays sequentially to our buffer | 237 | // Upload all guest vertex arrays sequentially to our buffer |
| 235 | const auto& regs = gpu.regs; | 238 | const auto& regs = gpu.regs; |
| 236 | for (std::size_t index = 0; index < Maxwell::NumVertexArrays; ++index) { | 239 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_BINDINGS; ++index) { |
| 237 | if (!flags[Dirty::VertexBuffer0 + index]) { | 240 | if (!flags[Dirty::VertexBuffer0 + index]) { |
| 238 | continue; | 241 | continue; |
| 239 | } | 242 | } |
| @@ -246,16 +249,25 @@ void RasterizerOpenGL::SetupVertexBuffer() { | |||
| 246 | 249 | ||
| 247 | const GPUVAddr start = vertex_array.StartAddress(); | 250 | const GPUVAddr start = vertex_array.StartAddress(); |
| 248 | const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); | 251 | const GPUVAddr end = regs.vertex_array_limit[index].LimitAddress(); |
| 249 | |||
| 250 | ASSERT(end >= start); | 252 | ASSERT(end >= start); |
| 253 | |||
| 254 | const GLuint gl_index = static_cast<GLuint>(index); | ||
| 251 | const u64 size = end - start; | 255 | const u64 size = end - start; |
| 252 | if (size == 0) { | 256 | if (size == 0) { |
| 253 | glBindVertexBuffer(static_cast<GLuint>(index), 0, 0, vertex_array.stride); | 257 | glBindVertexBuffer(gl_index, 0, 0, vertex_array.stride); |
| 258 | if (use_unified_memory) { | ||
| 259 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, gl_index, 0, 0); | ||
| 260 | } | ||
| 254 | continue; | 261 | continue; |
| 255 | } | 262 | } |
| 256 | const auto [vertex_buffer, vertex_buffer_offset] = buffer_cache.UploadMemory(start, size); | 263 | const auto info = buffer_cache.UploadMemory(start, size); |
| 257 | glBindVertexBuffer(static_cast<GLuint>(index), vertex_buffer, vertex_buffer_offset, | 264 | if (use_unified_memory) { |
| 258 | vertex_array.stride); | 265 | glBindVertexBuffer(gl_index, 0, 0, vertex_array.stride); |
| 266 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, gl_index, | ||
| 267 | info.address + info.offset, size); | ||
| 268 | } else { | ||
| 269 | glBindVertexBuffer(gl_index, info.handle, info.offset, vertex_array.stride); | ||
| 270 | } | ||
| 259 | } | 271 | } |
| 260 | } | 272 | } |
| 261 | 273 | ||
| @@ -268,7 +280,7 @@ void RasterizerOpenGL::SetupVertexInstances() { | |||
| 268 | flags[Dirty::VertexInstances] = false; | 280 | flags[Dirty::VertexInstances] = false; |
| 269 | 281 | ||
| 270 | const auto& regs = gpu.regs; | 282 | const auto& regs = gpu.regs; |
| 271 | for (std::size_t index = 0; index < NumSupportedVertexAttributes; ++index) { | 283 | for (std::size_t index = 0; index < NUM_SUPPORTED_VERTEX_ATTRIBUTES; ++index) { |
| 272 | if (!flags[Dirty::VertexInstance0 + index]) { | 284 | if (!flags[Dirty::VertexInstance0 + index]) { |
| 273 | continue; | 285 | continue; |
| 274 | } | 286 | } |
| @@ -285,9 +297,9 @@ GLintptr RasterizerOpenGL::SetupIndexBuffer() { | |||
| 285 | MICROPROFILE_SCOPE(OpenGL_Index); | 297 | MICROPROFILE_SCOPE(OpenGL_Index); |
| 286 | const auto& regs = system.GPU().Maxwell3D().regs; | 298 | const auto& regs = system.GPU().Maxwell3D().regs; |
| 287 | const std::size_t size = CalculateIndexBufferSize(); | 299 | const std::size_t size = CalculateIndexBufferSize(); |
| 288 | const auto [buffer, offset] = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); | 300 | const auto info = buffer_cache.UploadMemory(regs.index_array.IndexStart(), size); |
| 289 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, buffer); | 301 | glBindBuffer(GL_ELEMENT_ARRAY_BUFFER, info.handle); |
| 290 | return offset; | 302 | return info.offset; |
| 291 | } | 303 | } |
| 292 | 304 | ||
| 293 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { | 305 | void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) { |
| @@ -643,9 +655,9 @@ void RasterizerOpenGL::Draw(bool is_indexed, bool is_instanced) { | |||
| 643 | if (!device.UseAssemblyShaders()) { | 655 | if (!device.UseAssemblyShaders()) { |
| 644 | MaxwellUniformData ubo; | 656 | MaxwellUniformData ubo; |
| 645 | ubo.SetFromRegs(gpu); | 657 | ubo.SetFromRegs(gpu); |
| 646 | const auto [buffer, offset] = | 658 | const auto info = |
| 647 | buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); | 659 | buffer_cache.UploadHostMemory(&ubo, sizeof(ubo), device.GetUniformBufferAlignment()); |
| 648 | glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, buffer, offset, | 660 | glBindBufferRange(GL_UNIFORM_BUFFER, EmulationUniformBlockBinding, info.handle, info.offset, |
| 649 | static_cast<GLsizeiptr>(sizeof(ubo))); | 661 | static_cast<GLsizeiptr>(sizeof(ubo))); |
| 650 | } | 662 | } |
| 651 | 663 | ||
| @@ -956,8 +968,7 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding, | |||
| 956 | if (device.UseAssemblyShaders()) { | 968 | if (device.UseAssemblyShaders()) { |
| 957 | glBindBufferRangeNV(stage, entry.GetIndex(), 0, 0, 0); | 969 | glBindBufferRangeNV(stage, entry.GetIndex(), 0, 0, 0); |
| 958 | } else { | 970 | } else { |
| 959 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, | 971 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, 0, 0, sizeof(float)); |
| 960 | buffer_cache.GetEmptyBuffer(sizeof(float)), 0, sizeof(float)); | ||
| 961 | } | 972 | } |
| 962 | return; | 973 | return; |
| 963 | } | 974 | } |
| @@ -970,24 +981,25 @@ void RasterizerOpenGL::SetupConstBuffer(GLenum stage, u32 binding, | |||
| 970 | 981 | ||
| 971 | const std::size_t alignment = use_unified ? 4 : device.GetUniformBufferAlignment(); | 982 | const std::size_t alignment = use_unified ? 4 : device.GetUniformBufferAlignment(); |
| 972 | const GPUVAddr gpu_addr = buffer.address; | 983 | const GPUVAddr gpu_addr = buffer.address; |
| 973 | auto [cbuf, offset] = buffer_cache.UploadMemory(gpu_addr, size, alignment, false, fast_upload); | 984 | auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, false, fast_upload); |
| 974 | 985 | ||
| 975 | if (device.UseAssemblyShaders()) { | 986 | if (device.UseAssemblyShaders()) { |
| 976 | UNIMPLEMENTED_IF(use_unified); | 987 | UNIMPLEMENTED_IF(use_unified); |
| 977 | if (offset != 0) { | 988 | if (info.offset != 0) { |
| 978 | const GLuint staging_cbuf = staging_cbufs[current_cbuf++]; | 989 | const GLuint staging_cbuf = staging_cbufs[current_cbuf++]; |
| 979 | glCopyNamedBufferSubData(cbuf, staging_cbuf, offset, 0, size); | 990 | glCopyNamedBufferSubData(info.handle, staging_cbuf, info.offset, 0, size); |
| 980 | cbuf = staging_cbuf; | 991 | info.handle = staging_cbuf; |
| 981 | offset = 0; | 992 | info.offset = 0; |
| 982 | } | 993 | } |
| 983 | glBindBufferRangeNV(stage, binding, cbuf, offset, size); | 994 | glBindBufferRangeNV(stage, binding, info.handle, info.offset, size); |
| 984 | return; | 995 | return; |
| 985 | } | 996 | } |
| 986 | 997 | ||
| 987 | if (use_unified) { | 998 | if (use_unified) { |
| 988 | glCopyNamedBufferSubData(cbuf, unified_uniform_buffer.handle, offset, unified_offset, size); | 999 | glCopyNamedBufferSubData(info.handle, unified_uniform_buffer.handle, info.offset, |
| 1000 | unified_offset, size); | ||
| 989 | } else { | 1001 | } else { |
| 990 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, cbuf, offset, size); | 1002 | glBindBufferRange(GL_UNIFORM_BUFFER, binding, info.handle, info.offset, size); |
| 991 | } | 1003 | } |
| 992 | } | 1004 | } |
| 993 | 1005 | ||
| @@ -1023,9 +1035,8 @@ void RasterizerOpenGL::SetupComputeGlobalMemory(Shader* kernel) { | |||
| 1023 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, | 1035 | void RasterizerOpenGL::SetupGlobalMemory(u32 binding, const GlobalMemoryEntry& entry, |
| 1024 | GPUVAddr gpu_addr, std::size_t size) { | 1036 | GPUVAddr gpu_addr, std::size_t size) { |
| 1025 | const auto alignment{device.GetShaderStorageBufferAlignment()}; | 1037 | const auto alignment{device.GetShaderStorageBufferAlignment()}; |
| 1026 | const auto [ssbo, buffer_offset] = | 1038 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); |
| 1027 | buffer_cache.UploadMemory(gpu_addr, size, alignment, entry.is_written); | 1039 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, info.handle, info.offset, |
| 1028 | glBindBufferRange(GL_SHADER_STORAGE_BUFFER, binding, ssbo, buffer_offset, | ||
| 1029 | static_cast<GLsizeiptr>(size)); | 1040 | static_cast<GLsizeiptr>(size)); |
| 1030 | } | 1041 | } |
| 1031 | 1042 | ||
| @@ -1712,8 +1723,9 @@ void RasterizerOpenGL::EndTransformFeedback() { | |||
| 1712 | const GLuint handle = transform_feedback_buffers[index].handle; | 1723 | const GLuint handle = transform_feedback_buffers[index].handle; |
| 1713 | const GPUVAddr gpu_addr = binding.Address(); | 1724 | const GPUVAddr gpu_addr = binding.Address(); |
| 1714 | const std::size_t size = binding.buffer_size; | 1725 | const std::size_t size = binding.buffer_size; |
| 1715 | const auto [dest_buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | 1726 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, 4, true); |
| 1716 | glCopyNamedBufferSubData(handle, dest_buffer, 0, offset, static_cast<GLsizeiptr>(size)); | 1727 | glCopyNamedBufferSubData(handle, info.handle, 0, info.offset, |
| 1728 | static_cast<GLsizeiptr>(size)); | ||
| 1717 | } | 1729 | } |
| 1718 | } | 1730 | } |
| 1719 | 1731 | ||
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 46e780a06..c6a3bf3a1 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -460,8 +460,9 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 460 | const u8* host_ptr_b = memory_manager.GetPointer(address_b); | 460 | const u8* host_ptr_b = memory_manager.GetPointer(address_b); |
| 461 | code_b = GetShaderCode(memory_manager, address_b, host_ptr_b, false); | 461 | code_b = GetShaderCode(memory_manager, address_b, host_ptr_b, false); |
| 462 | } | 462 | } |
| 463 | const std::size_t code_size = code.size() * sizeof(u64); | ||
| 463 | 464 | ||
| 464 | const auto unique_identifier = GetUniqueIdentifier( | 465 | const u64 unique_identifier = GetUniqueIdentifier( |
| 465 | GetShaderType(program), program == Maxwell::ShaderProgram::VertexA, code, code_b); | 466 | GetShaderType(program), program == Maxwell::ShaderProgram::VertexA, code, code_b); |
| 466 | 467 | ||
| 467 | const ShaderParameters params{system, disk_cache, device, | 468 | const ShaderParameters params{system, disk_cache, device, |
| @@ -477,7 +478,7 @@ Shader* ShaderCacheOpenGL::GetStageProgram(Maxwell::ShaderProgram program) { | |||
| 477 | 478 | ||
| 478 | Shader* const result = shader.get(); | 479 | Shader* const result = shader.get(); |
| 479 | if (cpu_addr) { | 480 | if (cpu_addr) { |
| 480 | Register(std::move(shader), *cpu_addr, code.size() * sizeof(u64)); | 481 | Register(std::move(shader), *cpu_addr, code_size); |
| 481 | } else { | 482 | } else { |
| 482 | null_shader = std::move(shader); | 483 | null_shader = std::move(shader); |
| 483 | } | 484 | } |
| @@ -495,8 +496,9 @@ Shader* ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) { | |||
| 495 | 496 | ||
| 496 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; | 497 | const auto host_ptr{memory_manager.GetPointer(code_addr)}; |
| 497 | // No kernel found, create a new one | 498 | // No kernel found, create a new one |
| 498 | auto code{GetShaderCode(memory_manager, code_addr, host_ptr, true)}; | 499 | ProgramCode code{GetShaderCode(memory_manager, code_addr, host_ptr, true)}; |
| 499 | const auto unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; | 500 | const std::size_t code_size{code.size() * sizeof(u64)}; |
| 501 | const u64 unique_identifier{GetUniqueIdentifier(ShaderType::Compute, false, code)}; | ||
| 500 | 502 | ||
| 501 | const ShaderParameters params{system, disk_cache, device, | 503 | const ShaderParameters params{system, disk_cache, device, |
| 502 | *cpu_addr, host_ptr, unique_identifier}; | 504 | *cpu_addr, host_ptr, unique_identifier}; |
| @@ -511,7 +513,7 @@ Shader* ShaderCacheOpenGL::GetComputeKernel(GPUVAddr code_addr) { | |||
| 511 | 513 | ||
| 512 | Shader* const result = kernel.get(); | 514 | Shader* const result = kernel.get(); |
| 513 | if (cpu_addr) { | 515 | if (cpu_addr) { |
| 514 | Register(std::move(kernel), *cpu_addr, code.size() * sizeof(u64)); | 516 | Register(std::move(kernel), *cpu_addr, code_size); |
| 515 | } else { | 517 | } else { |
| 516 | null_kernel = std::move(kernel); | 518 | null_kernel = std::move(kernel); |
| 517 | } | 519 | } |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h index 6848f1388..994aaeaf2 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.h +++ b/src/video_core/renderer_opengl/gl_shader_cache.h | |||
| @@ -37,7 +37,6 @@ namespace OpenGL { | |||
| 37 | 37 | ||
| 38 | class Device; | 38 | class Device; |
| 39 | class RasterizerOpenGL; | 39 | class RasterizerOpenGL; |
| 40 | struct UnspecializedShader; | ||
| 41 | 40 | ||
| 42 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 41 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 43 | 42 | ||
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.cpp b/src/video_core/renderer_opengl/gl_stream_buffer.cpp index 932a2f69e..3655ff629 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.cpp +++ b/src/video_core/renderer_opengl/gl_stream_buffer.cpp | |||
| @@ -2,11 +2,13 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #include <deque> | 5 | #include <tuple> |
| 6 | #include <vector> | 6 | #include <vector> |
| 7 | |||
| 7 | #include "common/alignment.h" | 8 | #include "common/alignment.h" |
| 8 | #include "common/assert.h" | 9 | #include "common/assert.h" |
| 9 | #include "common/microprofile.h" | 10 | #include "common/microprofile.h" |
| 11 | #include "video_core/renderer_opengl/gl_device.h" | ||
| 10 | #include "video_core/renderer_opengl/gl_stream_buffer.h" | 12 | #include "video_core/renderer_opengl/gl_stream_buffer.h" |
| 11 | 13 | ||
| 12 | MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", | 14 | MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", |
| @@ -14,8 +16,7 @@ MICROPROFILE_DEFINE(OpenGL_StreamBuffer, "OpenGL", "Stream Buffer Orphaning", | |||
| 14 | 16 | ||
| 15 | namespace OpenGL { | 17 | namespace OpenGL { |
| 16 | 18 | ||
| 17 | OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent, | 19 | OGLStreamBuffer::OGLStreamBuffer(const Device& device, GLsizeiptr size, bool vertex_data_usage) |
| 18 | bool use_persistent) | ||
| 19 | : buffer_size(size) { | 20 | : buffer_size(size) { |
| 20 | gl_buffer.Create(); | 21 | gl_buffer.Create(); |
| 21 | 22 | ||
| @@ -29,23 +30,19 @@ OGLStreamBuffer::OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool p | |||
| 29 | allocate_size *= 2; | 30 | allocate_size *= 2; |
| 30 | } | 31 | } |
| 31 | 32 | ||
| 32 | if (use_persistent) { | 33 | static constexpr GLbitfield flags = GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT; |
| 33 | persistent = true; | 34 | glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); |
| 34 | coherent = prefer_coherent; | 35 | mapped_ptr = static_cast<u8*>( |
| 35 | const GLbitfield flags = | 36 | glMapNamedBufferRange(gl_buffer.handle, 0, buffer_size, flags | GL_MAP_FLUSH_EXPLICIT_BIT)); |
| 36 | GL_MAP_WRITE_BIT | GL_MAP_PERSISTENT_BIT | (coherent ? GL_MAP_COHERENT_BIT : 0); | 37 | |
| 37 | glNamedBufferStorage(gl_buffer.handle, allocate_size, nullptr, flags); | 38 | if (device.HasVertexBufferUnifiedMemory()) { |
| 38 | mapped_ptr = static_cast<u8*>(glMapNamedBufferRange( | 39 | glMakeNamedBufferResidentNV(gl_buffer.handle, GL_READ_ONLY); |
| 39 | gl_buffer.handle, 0, buffer_size, flags | (coherent ? 0 : GL_MAP_FLUSH_EXPLICIT_BIT))); | 40 | glGetNamedBufferParameterui64vNV(gl_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, &gpu_address); |
| 40 | } else { | ||
| 41 | glNamedBufferData(gl_buffer.handle, allocate_size, nullptr, GL_STREAM_DRAW); | ||
| 42 | } | 41 | } |
| 43 | } | 42 | } |
| 44 | 43 | ||
| 45 | OGLStreamBuffer::~OGLStreamBuffer() { | 44 | OGLStreamBuffer::~OGLStreamBuffer() { |
| 46 | if (persistent) { | 45 | glUnmapNamedBuffer(gl_buffer.handle); |
| 47 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 48 | } | ||
| 49 | gl_buffer.Release(); | 46 | gl_buffer.Release(); |
| 50 | } | 47 | } |
| 51 | 48 | ||
| @@ -60,36 +57,21 @@ std::tuple<u8*, GLintptr, bool> OGLStreamBuffer::Map(GLsizeiptr size, GLintptr a | |||
| 60 | 57 | ||
| 61 | bool invalidate = false; | 58 | bool invalidate = false; |
| 62 | if (buffer_pos + size > buffer_size) { | 59 | if (buffer_pos + size > buffer_size) { |
| 60 | MICROPROFILE_SCOPE(OpenGL_StreamBuffer); | ||
| 61 | glInvalidateBufferData(gl_buffer.handle); | ||
| 62 | |||
| 63 | buffer_pos = 0; | 63 | buffer_pos = 0; |
| 64 | invalidate = true; | 64 | invalidate = true; |
| 65 | |||
| 66 | if (persistent) { | ||
| 67 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 68 | } | ||
| 69 | } | 65 | } |
| 70 | 66 | ||
| 71 | if (invalidate || !persistent) { | 67 | return std::make_tuple(mapped_ptr + buffer_pos, buffer_pos, invalidate); |
| 72 | MICROPROFILE_SCOPE(OpenGL_StreamBuffer); | ||
| 73 | GLbitfield flags = GL_MAP_WRITE_BIT | (persistent ? GL_MAP_PERSISTENT_BIT : 0) | | ||
| 74 | (coherent ? GL_MAP_COHERENT_BIT : GL_MAP_FLUSH_EXPLICIT_BIT) | | ||
| 75 | (invalidate ? GL_MAP_INVALIDATE_BUFFER_BIT : GL_MAP_UNSYNCHRONIZED_BIT); | ||
| 76 | mapped_ptr = static_cast<u8*>( | ||
| 77 | glMapNamedBufferRange(gl_buffer.handle, buffer_pos, buffer_size - buffer_pos, flags)); | ||
| 78 | mapped_offset = buffer_pos; | ||
| 79 | } | ||
| 80 | |||
| 81 | return std::make_tuple(mapped_ptr + buffer_pos - mapped_offset, buffer_pos, invalidate); | ||
| 82 | } | 68 | } |
| 83 | 69 | ||
| 84 | void OGLStreamBuffer::Unmap(GLsizeiptr size) { | 70 | void OGLStreamBuffer::Unmap(GLsizeiptr size) { |
| 85 | ASSERT(size <= mapped_size); | 71 | ASSERT(size <= mapped_size); |
| 86 | 72 | ||
| 87 | if (!coherent && size > 0) { | 73 | if (size > 0) { |
| 88 | glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos - mapped_offset, size); | 74 | glFlushMappedNamedBufferRange(gl_buffer.handle, buffer_pos, size); |
| 89 | } | ||
| 90 | |||
| 91 | if (!persistent) { | ||
| 92 | glUnmapNamedBuffer(gl_buffer.handle); | ||
| 93 | } | 75 | } |
| 94 | 76 | ||
| 95 | buffer_pos += size; | 77 | buffer_pos += size; |
diff --git a/src/video_core/renderer_opengl/gl_stream_buffer.h b/src/video_core/renderer_opengl/gl_stream_buffer.h index 866da3594..307a67113 100644 --- a/src/video_core/renderer_opengl/gl_stream_buffer.h +++ b/src/video_core/renderer_opengl/gl_stream_buffer.h | |||
| @@ -11,10 +11,11 @@ | |||
| 11 | 11 | ||
| 12 | namespace OpenGL { | 12 | namespace OpenGL { |
| 13 | 13 | ||
| 14 | class Device; | ||
| 15 | |||
| 14 | class OGLStreamBuffer : private NonCopyable { | 16 | class OGLStreamBuffer : private NonCopyable { |
| 15 | public: | 17 | public: |
| 16 | explicit OGLStreamBuffer(GLsizeiptr size, bool vertex_data_usage, bool prefer_coherent = false, | 18 | explicit OGLStreamBuffer(const Device& device, GLsizeiptr size, bool vertex_data_usage); |
| 17 | bool use_persistent = true); | ||
| 18 | ~OGLStreamBuffer(); | 19 | ~OGLStreamBuffer(); |
| 19 | 20 | ||
| 20 | /* | 21 | /* |
| @@ -33,19 +34,20 @@ public: | |||
| 33 | return gl_buffer.handle; | 34 | return gl_buffer.handle; |
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | GLsizeiptr Size() const { | 37 | u64 Address() const { |
| 38 | return gpu_address; | ||
| 39 | } | ||
| 40 | |||
| 41 | GLsizeiptr Size() const noexcept { | ||
| 37 | return buffer_size; | 42 | return buffer_size; |
| 38 | } | 43 | } |
| 39 | 44 | ||
| 40 | private: | 45 | private: |
| 41 | OGLBuffer gl_buffer; | 46 | OGLBuffer gl_buffer; |
| 42 | 47 | ||
| 43 | bool coherent = false; | 48 | GLuint64EXT gpu_address = 0; |
| 44 | bool persistent = false; | ||
| 45 | |||
| 46 | GLintptr buffer_pos = 0; | 49 | GLintptr buffer_pos = 0; |
| 47 | GLsizeiptr buffer_size = 0; | 50 | GLsizeiptr buffer_size = 0; |
| 48 | GLintptr mapped_offset = 0; | ||
| 49 | GLsizeiptr mapped_size = 0; | 51 | GLsizeiptr mapped_size = 0; |
| 50 | u8* mapped_ptr = nullptr; | 52 | u8* mapped_ptr = nullptr; |
| 51 | }; | 53 | }; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 6214fcbc3..c40adb6e7 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -488,6 +488,15 @@ void RendererOpenGL::InitOpenGLObjects() { | |||
| 488 | 488 | ||
| 489 | // Clear screen to black | 489 | // Clear screen to black |
| 490 | LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); | 490 | LoadColorToActiveGLTexture(0, 0, 0, 0, screen_info.texture); |
| 491 | |||
| 492 | // Enable unified vertex attributes and query vertex buffer address when the driver supports it | ||
| 493 | if (device.HasVertexBufferUnifiedMemory()) { | ||
| 494 | glEnableClientState(GL_VERTEX_ATTRIB_ARRAY_UNIFIED_NV); | ||
| 495 | |||
| 496 | glMakeNamedBufferResidentNV(vertex_buffer.handle, GL_READ_ONLY); | ||
| 497 | glGetNamedBufferParameterui64vNV(vertex_buffer.handle, GL_BUFFER_GPU_ADDRESS_NV, | ||
| 498 | &vertex_buffer_address); | ||
| 499 | } | ||
| 491 | } | 500 | } |
| 492 | 501 | ||
| 493 | void RendererOpenGL::AddTelemetryFields() { | 502 | void RendererOpenGL::AddTelemetryFields() { |
| @@ -656,7 +665,13 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | |||
| 656 | offsetof(ScreenRectVertex, tex_coord)); | 665 | offsetof(ScreenRectVertex, tex_coord)); |
| 657 | glVertexAttribBinding(PositionLocation, 0); | 666 | glVertexAttribBinding(PositionLocation, 0); |
| 658 | glVertexAttribBinding(TexCoordLocation, 0); | 667 | glVertexAttribBinding(TexCoordLocation, 0); |
| 659 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); | 668 | if (device.HasVertexBufferUnifiedMemory()) { |
| 669 | glBindVertexBuffer(0, 0, 0, sizeof(ScreenRectVertex)); | ||
| 670 | glBufferAddressRangeNV(GL_VERTEX_ATTRIB_ARRAY_ADDRESS_NV, 0, vertex_buffer_address, | ||
| 671 | sizeof(vertices)); | ||
| 672 | } else { | ||
| 673 | glBindVertexBuffer(0, vertex_buffer.handle, 0, sizeof(ScreenRectVertex)); | ||
| 674 | } | ||
| 660 | 675 | ||
| 661 | glBindTextureUnit(0, screen_info.display_texture); | 676 | glBindTextureUnit(0, screen_info.display_texture); |
| 662 | glBindSampler(0, 0); | 677 | glBindSampler(0, 0); |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.h b/src/video_core/renderer_opengl/renderer_opengl.h index 61bf507f4..8b18d32e6 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.h +++ b/src/video_core/renderer_opengl/renderer_opengl.h | |||
| @@ -107,6 +107,9 @@ private: | |||
| 107 | OGLPipeline pipeline; | 107 | OGLPipeline pipeline; |
| 108 | OGLFramebuffer screenshot_framebuffer; | 108 | OGLFramebuffer screenshot_framebuffer; |
| 109 | 109 | ||
| 110 | // GPU address of the vertex buffer | ||
| 111 | GLuint64EXT vertex_buffer_address = 0; | ||
| 112 | |||
| 110 | /// Display information for Switch screen | 113 | /// Display information for Switch screen |
| 111 | ScreenInfo screen_info; | 114 | ScreenInfo screen_info; |
| 112 | 115 | ||
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index 1fde38328..f10f96cd8 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -37,9 +37,9 @@ std::unique_ptr<VKStreamBuffer> CreateStreamBuffer(const VKDevice& device, VKSch | |||
| 37 | 37 | ||
| 38 | } // Anonymous namespace | 38 | } // Anonymous namespace |
| 39 | 39 | ||
| 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | 40 | Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler_, |
| 41 | std::size_t size) | 41 | VKStagingBufferPool& staging_pool_, VAddr cpu_addr, std::size_t size) |
| 42 | : VideoCommon::BufferBlock{cpu_addr, size} { | 42 | : VideoCommon::BufferBlock{cpu_addr, size}, scheduler{scheduler_}, staging_pool{staging_pool_} { |
| 43 | VkBufferCreateInfo ci; | 43 | VkBufferCreateInfo ci; |
| 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; | 44 | ci.sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO; |
| 45 | ci.pNext = nullptr; | 45 | ci.pNext = nullptr; |
| @@ -56,40 +56,15 @@ Buffer::Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cp | |||
| 56 | 56 | ||
| 57 | Buffer::~Buffer() = default; | 57 | Buffer::~Buffer() = default; |
| 58 | 58 | ||
| 59 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | 59 | void Buffer::Upload(std::size_t offset, std::size_t size, const u8* data) const { |
| 60 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 61 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 62 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 63 | CreateStreamBuffer(device, | ||
| 64 | scheduler)}, | ||
| 65 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 66 | staging_pool} {} | ||
| 67 | |||
| 68 | VKBufferCache::~VKBufferCache() = default; | ||
| 69 | |||
| 70 | std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 71 | return std::make_shared<Buffer>(device, memory_manager, cpu_addr, size); | ||
| 72 | } | ||
| 73 | |||
| 74 | VkBuffer VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 75 | size = std::max(size, std::size_t(4)); | ||
| 76 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 77 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 78 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 79 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 80 | }); | ||
| 81 | return *empty.handle; | ||
| 82 | } | ||
| 83 | |||
| 84 | void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 85 | const u8* data) { | ||
| 86 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 60 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 87 | std::memcpy(staging.commit->Map(size), data, size); | 61 | std::memcpy(staging.commit->Map(size), data, size); |
| 88 | 62 | ||
| 89 | scheduler.RequestOutsideRenderPassOperationContext(); | 63 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 90 | scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | 64 | |
| 91 | size](vk::CommandBuffer cmdbuf) { | 65 | const VkBuffer handle = Handle(); |
| 92 | cmdbuf.CopyBuffer(staging, buffer, VkBufferCopy{0, offset, size}); | 66 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { |
| 67 | cmdbuf.CopyBuffer(staging, handle, VkBufferCopy{0, offset, size}); | ||
| 93 | 68 | ||
| 94 | VkBufferMemoryBarrier barrier; | 69 | VkBufferMemoryBarrier barrier; |
| 95 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 70 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| @@ -98,7 +73,7 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 98 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; | 73 | barrier.dstAccessMask = UPLOAD_ACCESS_BARRIERS; |
| 99 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 74 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 100 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 75 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 101 | barrier.buffer = buffer; | 76 | barrier.buffer = handle; |
| 102 | barrier.offset = offset; | 77 | barrier.offset = offset; |
| 103 | barrier.size = size; | 78 | barrier.size = size; |
| 104 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, | 79 | cmdbuf.PipelineBarrier(VK_PIPELINE_STAGE_TRANSFER_BIT, UPLOAD_PIPELINE_STAGE, 0, {}, |
| @@ -106,12 +81,12 @@ void VKBufferCache::UploadBlockData(const Buffer& buffer, std::size_t offset, st | |||
| 106 | }); | 81 | }); |
| 107 | } | 82 | } |
| 108 | 83 | ||
| 109 | void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | 84 | void Buffer::Download(std::size_t offset, std::size_t size, u8* data) const { |
| 110 | u8* data) { | ||
| 111 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); | 85 | const auto& staging = staging_pool.GetUnusedBuffer(size, true); |
| 112 | scheduler.RequestOutsideRenderPassOperationContext(); | 86 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 113 | scheduler.Record([staging = *staging.handle, buffer = buffer.Handle(), offset, | 87 | |
| 114 | size](vk::CommandBuffer cmdbuf) { | 88 | const VkBuffer handle = Handle(); |
| 89 | scheduler.Record([staging = *staging.handle, handle, offset, size](vk::CommandBuffer cmdbuf) { | ||
| 115 | VkBufferMemoryBarrier barrier; | 90 | VkBufferMemoryBarrier barrier; |
| 116 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; | 91 | barrier.sType = VK_STRUCTURE_TYPE_BUFFER_MEMORY_BARRIER; |
| 117 | barrier.pNext = nullptr; | 92 | barrier.pNext = nullptr; |
| @@ -119,7 +94,7 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 119 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; | 94 | barrier.dstAccessMask = VK_ACCESS_TRANSFER_READ_BIT; |
| 120 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 95 | barrier.srcQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 121 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; | 96 | barrier.dstQueueFamilyIndex = VK_QUEUE_FAMILY_IGNORED; |
| 122 | barrier.buffer = buffer; | 97 | barrier.buffer = handle; |
| 123 | barrier.offset = offset; | 98 | barrier.offset = offset; |
| 124 | barrier.size = size; | 99 | barrier.size = size; |
| 125 | 100 | ||
| @@ -127,17 +102,19 @@ void VKBufferCache::DownloadBlockData(const Buffer& buffer, std::size_t offset, | |||
| 127 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | | 102 | VK_PIPELINE_STAGE_FRAGMENT_SHADER_BIT | |
| 128 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, | 103 | VK_PIPELINE_STAGE_COMPUTE_SHADER_BIT, |
| 129 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); | 104 | VK_PIPELINE_STAGE_TRANSFER_BIT, 0, {}, barrier, {}); |
| 130 | cmdbuf.CopyBuffer(buffer, staging, VkBufferCopy{offset, 0, size}); | 105 | cmdbuf.CopyBuffer(handle, staging, VkBufferCopy{offset, 0, size}); |
| 131 | }); | 106 | }); |
| 132 | scheduler.Finish(); | 107 | scheduler.Finish(); |
| 133 | 108 | ||
| 134 | std::memcpy(data, staging.commit->Map(size), size); | 109 | std::memcpy(data, staging.commit->Map(size), size); |
| 135 | } | 110 | } |
| 136 | 111 | ||
| 137 | void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | 112 | void Buffer::CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, |
| 138 | std::size_t dst_offset, std::size_t size) { | 113 | std::size_t size) const { |
| 139 | scheduler.RequestOutsideRenderPassOperationContext(); | 114 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 140 | scheduler.Record([src_buffer = src.Handle(), dst_buffer = dst.Handle(), src_offset, dst_offset, | 115 | |
| 116 | const VkBuffer dst_buffer = Handle(); | ||
| 117 | scheduler.Record([src_buffer = src.Handle(), dst_buffer, src_offset, dst_offset, | ||
| 141 | size](vk::CommandBuffer cmdbuf) { | 118 | size](vk::CommandBuffer cmdbuf) { |
| 142 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); | 119 | cmdbuf.CopyBuffer(src_buffer, dst_buffer, VkBufferCopy{src_offset, dst_offset, size}); |
| 143 | 120 | ||
| @@ -165,4 +142,30 @@ void VKBufferCache::CopyBlock(const Buffer& src, const Buffer& dst, std::size_t | |||
| 165 | }); | 142 | }); |
| 166 | } | 143 | } |
| 167 | 144 | ||
| 145 | VKBufferCache::VKBufferCache(VideoCore::RasterizerInterface& rasterizer, Core::System& system, | ||
| 146 | const VKDevice& device, VKMemoryManager& memory_manager, | ||
| 147 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool) | ||
| 148 | : VideoCommon::BufferCache<Buffer, VkBuffer, VKStreamBuffer>{rasterizer, system, | ||
| 149 | CreateStreamBuffer(device, | ||
| 150 | scheduler)}, | ||
| 151 | device{device}, memory_manager{memory_manager}, scheduler{scheduler}, staging_pool{ | ||
| 152 | staging_pool} {} | ||
| 153 | |||
| 154 | VKBufferCache::~VKBufferCache() = default; | ||
| 155 | |||
| 156 | std::shared_ptr<Buffer> VKBufferCache::CreateBlock(VAddr cpu_addr, std::size_t size) { | ||
| 157 | return std::make_shared<Buffer>(device, memory_manager, scheduler, staging_pool, cpu_addr, | ||
| 158 | size); | ||
| 159 | } | ||
| 160 | |||
| 161 | VKBufferCache::BufferInfo VKBufferCache::GetEmptyBuffer(std::size_t size) { | ||
| 162 | size = std::max(size, std::size_t(4)); | ||
| 163 | const auto& empty = staging_pool.GetUnusedBuffer(size, false); | ||
| 164 | scheduler.RequestOutsideRenderPassOperationContext(); | ||
| 165 | scheduler.Record([size, buffer = *empty.handle](vk::CommandBuffer cmdbuf) { | ||
| 166 | cmdbuf.FillBuffer(buffer, 0, size, 0); | ||
| 167 | }); | ||
| 168 | return {*empty.handle, 0, 0}; | ||
| 169 | } | ||
| 170 | |||
| 168 | } // namespace Vulkan | 171 | } // namespace Vulkan |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.h b/src/video_core/renderer_vulkan/vk_buffer_cache.h index 9ebbef835..3630aca77 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.h +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.h | |||
| @@ -25,15 +25,29 @@ class VKScheduler; | |||
| 25 | 25 | ||
| 26 | class Buffer final : public VideoCommon::BufferBlock { | 26 | class Buffer final : public VideoCommon::BufferBlock { |
| 27 | public: | 27 | public: |
| 28 | explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VAddr cpu_addr, | 28 | explicit Buffer(const VKDevice& device, VKMemoryManager& memory_manager, VKScheduler& scheduler, |
| 29 | std::size_t size); | 29 | VKStagingBufferPool& staging_pool, VAddr cpu_addr, std::size_t size); |
| 30 | ~Buffer(); | 30 | ~Buffer(); |
| 31 | 31 | ||
| 32 | void Upload(std::size_t offset, std::size_t size, const u8* data) const; | ||
| 33 | |||
| 34 | void Download(std::size_t offset, std::size_t size, u8* data) const; | ||
| 35 | |||
| 36 | void CopyFrom(const Buffer& src, std::size_t src_offset, std::size_t dst_offset, | ||
| 37 | std::size_t size) const; | ||
| 38 | |||
| 32 | VkBuffer Handle() const { | 39 | VkBuffer Handle() const { |
| 33 | return *buffer.handle; | 40 | return *buffer.handle; |
| 34 | } | 41 | } |
| 35 | 42 | ||
| 43 | u64 Address() const { | ||
| 44 | return 0; | ||
| 45 | } | ||
| 46 | |||
| 36 | private: | 47 | private: |
| 48 | VKScheduler& scheduler; | ||
| 49 | VKStagingBufferPool& staging_pool; | ||
| 50 | |||
| 37 | VKBuffer buffer; | 51 | VKBuffer buffer; |
| 38 | }; | 52 | }; |
| 39 | 53 | ||
| @@ -44,20 +58,11 @@ public: | |||
| 44 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); | 58 | VKScheduler& scheduler, VKStagingBufferPool& staging_pool); |
| 45 | ~VKBufferCache(); | 59 | ~VKBufferCache(); |
| 46 | 60 | ||
| 47 | VkBuffer GetEmptyBuffer(std::size_t size) override; | 61 | BufferInfo GetEmptyBuffer(std::size_t size) override; |
| 48 | 62 | ||
| 49 | protected: | 63 | protected: |
| 50 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; | 64 | std::shared_ptr<Buffer> CreateBlock(VAddr cpu_addr, std::size_t size) override; |
| 51 | 65 | ||
| 52 | void UploadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 53 | const u8* data) override; | ||
| 54 | |||
| 55 | void DownloadBlockData(const Buffer& buffer, std::size_t offset, std::size_t size, | ||
| 56 | u8* data) override; | ||
| 57 | |||
| 58 | void CopyBlock(const Buffer& src, const Buffer& dst, std::size_t src_offset, | ||
| 59 | std::size_t dst_offset, std::size_t size) override; | ||
| 60 | |||
| 61 | private: | 66 | private: |
| 62 | const VKDevice& device; | 67 | const VKDevice& device; |
| 63 | VKMemoryManager& memory_manager; | 68 | VKMemoryManager& memory_manager; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 29001953c..a8d94eac3 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -143,6 +143,49 @@ Tegra::Texture::FullTextureInfo GetTextureInfo(const Engine& engine, const Entry | |||
| 143 | } | 143 | } |
| 144 | } | 144 | } |
| 145 | 145 | ||
| 146 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 147 | /// @param is_clear True when a clear is being executed | ||
| 148 | /// @param regs 3D registers | ||
| 149 | /// @return True when the contents have to be preserved | ||
| 150 | bool HasToPreserveColorContents(bool is_clear, const Maxwell& regs) { | ||
| 151 | if (!is_clear) { | ||
| 152 | return true; | ||
| 153 | } | ||
| 154 | // First we have to make sure all clear masks are enabled. | ||
| 155 | if (!regs.clear_buffers.R || !regs.clear_buffers.G || !regs.clear_buffers.B || | ||
| 156 | !regs.clear_buffers.A) { | ||
| 157 | return true; | ||
| 158 | } | ||
| 159 | // If scissors are disabled, the whole screen is cleared | ||
| 160 | if (!regs.clear_flags.scissor) { | ||
| 161 | return false; | ||
| 162 | } | ||
| 163 | // Then we have to confirm scissor testing clears the whole image | ||
| 164 | const std::size_t index = regs.clear_buffers.RT; | ||
| 165 | const auto& scissor = regs.scissor_test[0]; | ||
| 166 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.rt[index].width || | ||
| 167 | scissor.max_y < regs.rt[index].height; | ||
| 168 | } | ||
| 169 | |||
| 170 | /// @brief Determine if an attachment to be updated has to preserve contents | ||
| 171 | /// @param is_clear True when a clear is being executed | ||
| 172 | /// @param regs 3D registers | ||
| 173 | /// @return True when the contents have to be preserved | ||
| 174 | bool HasToPreserveDepthContents(bool is_clear, const Maxwell& regs) { | ||
| 175 | // If we are not clearing, the contents have to be preserved | ||
| 176 | if (!is_clear) { | ||
| 177 | return true; | ||
| 178 | } | ||
| 179 | // For depth stencil clears we only have to confirm scissor test covers the whole image | ||
| 180 | if (!regs.clear_flags.scissor) { | ||
| 181 | return false; | ||
| 182 | } | ||
| 183 | // Make sure the clear cover the whole image | ||
| 184 | const auto& scissor = regs.scissor_test[0]; | ||
| 185 | return scissor.min_x > 0 || scissor.min_y > 0 || scissor.max_x < regs.zeta_width || | ||
| 186 | scissor.max_y < regs.zeta_height; | ||
| 187 | } | ||
| 188 | |||
| 146 | } // Anonymous namespace | 189 | } // Anonymous namespace |
| 147 | 190 | ||
| 148 | class BufferBindings final { | 191 | class BufferBindings final { |
| @@ -344,7 +387,7 @@ void RasterizerVulkan::Draw(bool is_indexed, bool is_instanced) { | |||
| 344 | 387 | ||
| 345 | buffer_cache.Unmap(); | 388 | buffer_cache.Unmap(); |
| 346 | 389 | ||
| 347 | const Texceptions texceptions = UpdateAttachments(); | 390 | const Texceptions texceptions = UpdateAttachments(false); |
| 348 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); | 391 | SetupImageTransitions(texceptions, color_attachments, zeta_attachment); |
| 349 | 392 | ||
| 350 | key.renderpass_params = GetRenderPassParams(texceptions); | 393 | key.renderpass_params = GetRenderPassParams(texceptions); |
| @@ -400,7 +443,7 @@ void RasterizerVulkan::Clear() { | |||
| 400 | return; | 443 | return; |
| 401 | } | 444 | } |
| 402 | 445 | ||
| 403 | [[maybe_unused]] const auto texceptions = UpdateAttachments(); | 446 | [[maybe_unused]] const auto texceptions = UpdateAttachments(true); |
| 404 | DEBUG_ASSERT(texceptions.none()); | 447 | DEBUG_ASSERT(texceptions.none()); |
| 405 | SetupImageTransitions(0, color_attachments, zeta_attachment); | 448 | SetupImageTransitions(0, color_attachments, zeta_attachment); |
| 406 | 449 | ||
| @@ -677,9 +720,12 @@ void RasterizerVulkan::FlushWork() { | |||
| 677 | draw_counter = 0; | 720 | draw_counter = 0; |
| 678 | } | 721 | } |
| 679 | 722 | ||
| 680 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | 723 | RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments(bool is_clear) { |
| 681 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); | 724 | MICROPROFILE_SCOPE(Vulkan_RenderTargets); |
| 682 | auto& dirty = system.GPU().Maxwell3D().dirty.flags; | 725 | auto& maxwell3d = system.GPU().Maxwell3D(); |
| 726 | auto& dirty = maxwell3d.dirty.flags; | ||
| 727 | auto& regs = maxwell3d.regs; | ||
| 728 | |||
| 683 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; | 729 | const bool update_rendertargets = dirty[VideoCommon::Dirty::RenderTargets]; |
| 684 | dirty[VideoCommon::Dirty::RenderTargets] = false; | 730 | dirty[VideoCommon::Dirty::RenderTargets] = false; |
| 685 | 731 | ||
| @@ -688,7 +734,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 688 | Texceptions texceptions; | 734 | Texceptions texceptions; |
| 689 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { | 735 | for (std::size_t rt = 0; rt < Maxwell::NumRenderTargets; ++rt) { |
| 690 | if (update_rendertargets) { | 736 | if (update_rendertargets) { |
| 691 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, true); | 737 | const bool preserve_contents = HasToPreserveColorContents(is_clear, regs); |
| 738 | color_attachments[rt] = texture_cache.GetColorBufferSurface(rt, preserve_contents); | ||
| 692 | } | 739 | } |
| 693 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { | 740 | if (color_attachments[rt] && WalkAttachmentOverlaps(*color_attachments[rt])) { |
| 694 | texceptions[rt] = true; | 741 | texceptions[rt] = true; |
| @@ -696,7 +743,8 @@ RasterizerVulkan::Texceptions RasterizerVulkan::UpdateAttachments() { | |||
| 696 | } | 743 | } |
| 697 | 744 | ||
| 698 | if (update_rendertargets) { | 745 | if (update_rendertargets) { |
| 699 | zeta_attachment = texture_cache.GetDepthBufferSurface(true); | 746 | const bool preserve_contents = HasToPreserveDepthContents(is_clear, regs); |
| 747 | zeta_attachment = texture_cache.GetDepthBufferSurface(preserve_contents); | ||
| 700 | } | 748 | } |
| 701 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { | 749 | if (zeta_attachment && WalkAttachmentOverlaps(*zeta_attachment)) { |
| 702 | texceptions[ZETA_TEXCEPTION_INDEX] = true; | 750 | texceptions[ZETA_TEXCEPTION_INDEX] = true; |
| @@ -870,10 +918,10 @@ void RasterizerVulkan::BeginTransformFeedback() { | |||
| 870 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); | 918 | UNIMPLEMENTED_IF(binding.buffer_offset != 0); |
| 871 | 919 | ||
| 872 | const GPUVAddr gpu_addr = binding.Address(); | 920 | const GPUVAddr gpu_addr = binding.Address(); |
| 873 | const auto size = static_cast<VkDeviceSize>(binding.buffer_size); | 921 | const VkDeviceSize size = static_cast<VkDeviceSize>(binding.buffer_size); |
| 874 | const auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, size, 4, true); | 922 | const auto info = buffer_cache.UploadMemory(gpu_addr, size, 4, true); |
| 875 | 923 | ||
| 876 | scheduler.Record([buffer = buffer, offset = offset, size](vk::CommandBuffer cmdbuf) { | 924 | scheduler.Record([buffer = info.handle, offset = info.offset, size](vk::CommandBuffer cmdbuf) { |
| 877 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); | 925 | cmdbuf.BindTransformFeedbackBuffersEXT(0, 1, &buffer, &offset, &size); |
| 878 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); | 926 | cmdbuf.BeginTransformFeedbackEXT(0, 0, nullptr, nullptr); |
| 879 | }); | 927 | }); |
| @@ -925,8 +973,8 @@ void RasterizerVulkan::SetupVertexArrays(FixedPipelineState::VertexInput& vertex | |||
| 925 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); | 973 | buffer_bindings.AddVertexBinding(DefaultBuffer(), 0); |
| 926 | continue; | 974 | continue; |
| 927 | } | 975 | } |
| 928 | const auto [buffer, offset] = buffer_cache.UploadMemory(start, size); | 976 | const auto info = buffer_cache.UploadMemory(start, size); |
| 929 | buffer_bindings.AddVertexBinding(buffer, offset); | 977 | buffer_bindings.AddVertexBinding(info.handle, info.offset); |
| 930 | } | 978 | } |
| 931 | } | 979 | } |
| 932 | 980 | ||
| @@ -948,7 +996,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 948 | break; | 996 | break; |
| 949 | } | 997 | } |
| 950 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 998 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 951 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 999 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 1000 | VkBuffer buffer = info.handle; | ||
| 1001 | u64 offset = info.offset; | ||
| 952 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( | 1002 | std::tie(buffer, offset) = quad_indexed_pass.Assemble( |
| 953 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); | 1003 | regs.index_array.format, params.num_vertices, params.base_vertex, buffer, offset); |
| 954 | 1004 | ||
| @@ -962,7 +1012,9 @@ void RasterizerVulkan::SetupIndexBuffer(BufferBindings& buffer_bindings, DrawPar | |||
| 962 | break; | 1012 | break; |
| 963 | } | 1013 | } |
| 964 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); | 1014 | const GPUVAddr gpu_addr = regs.index_array.IndexStart(); |
| 965 | auto [buffer, offset] = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); | 1015 | const auto info = buffer_cache.UploadMemory(gpu_addr, CalculateIndexBufferSize()); |
| 1016 | VkBuffer buffer = info.handle; | ||
| 1017 | u64 offset = info.offset; | ||
| 966 | 1018 | ||
| 967 | auto format = regs.index_array.format; | 1019 | auto format = regs.index_array.format; |
| 968 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; | 1020 | const bool is_uint8 = format == Maxwell::IndexFormat::UnsignedByte; |
| @@ -1109,10 +1161,9 @@ void RasterizerVulkan::SetupConstBuffer(const ConstBufferEntry& entry, | |||
| 1109 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); | 1161 | Common::AlignUp(CalculateConstBufferSize(entry, buffer), 4 * sizeof(float)); |
| 1110 | ASSERT(size <= MaxConstbufferSize); | 1162 | ASSERT(size <= MaxConstbufferSize); |
| 1111 | 1163 | ||
| 1112 | const auto [buffer_handle, offset] = | 1164 | const auto info = |
| 1113 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); | 1165 | buffer_cache.UploadMemory(buffer.address, size, device.GetUniformBufferAlignment()); |
| 1114 | 1166 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); | |
| 1115 | update_descriptor_queue.AddBuffer(buffer_handle, offset, size); | ||
| 1116 | } | 1167 | } |
| 1117 | 1168 | ||
| 1118 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { | 1169 | void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAddr address) { |
| @@ -1126,14 +1177,14 @@ void RasterizerVulkan::SetupGlobalBuffer(const GlobalBufferEntry& entry, GPUVAdd | |||
| 1126 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the | 1177 | // Note: Do *not* use DefaultBuffer() here, storage buffers can be written breaking the |
| 1127 | // default buffer. | 1178 | // default buffer. |
| 1128 | static constexpr std::size_t dummy_size = 4; | 1179 | static constexpr std::size_t dummy_size = 4; |
| 1129 | const auto buffer = buffer_cache.GetEmptyBuffer(dummy_size); | 1180 | const auto info = buffer_cache.GetEmptyBuffer(dummy_size); |
| 1130 | update_descriptor_queue.AddBuffer(buffer, 0, dummy_size); | 1181 | update_descriptor_queue.AddBuffer(info.handle, info.offset, dummy_size); |
| 1131 | return; | 1182 | return; |
| 1132 | } | 1183 | } |
| 1133 | 1184 | ||
| 1134 | const auto [buffer, offset] = buffer_cache.UploadMemory( | 1185 | const auto info = buffer_cache.UploadMemory( |
| 1135 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); | 1186 | actual_addr, size, device.GetStorageBufferAlignment(), entry.IsWritten()); |
| 1136 | update_descriptor_queue.AddBuffer(buffer, offset, size); | 1187 | update_descriptor_queue.AddBuffer(info.handle, info.offset, size); |
| 1137 | } | 1188 | } |
| 1138 | 1189 | ||
| 1139 | void RasterizerVulkan::SetupUniformTexels(const Tegra::Texture::TICEntry& tic, | 1190 | void RasterizerVulkan::SetupUniformTexels(const Tegra::Texture::TICEntry& tic, |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index c8c187606..83e00e7e9 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -159,7 +159,10 @@ private: | |||
| 159 | 159 | ||
| 160 | void FlushWork(); | 160 | void FlushWork(); |
| 161 | 161 | ||
| 162 | Texceptions UpdateAttachments(); | 162 | /// @brief Updates the currently bound attachments |
| 163 | /// @param is_clear True when the framebuffer is updated as a clear | ||
| 164 | /// @return Bitfield of attachments being used as sampled textures | ||
| 165 | Texceptions UpdateAttachments(bool is_clear); | ||
| 163 | 166 | ||
| 164 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); | 167 | std::tuple<VkFramebuffer, VkExtent2D> ConfigureFramebuffers(VkRenderPass renderpass); |
| 165 | 168 | ||
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h index c765c60a0..689f0d276 100644 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ b/src/video_core/renderer_vulkan/vk_stream_buffer.h | |||
| @@ -35,10 +35,14 @@ public: | |||
| 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. | 35 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. |
| 36 | void Unmap(u64 size); | 36 | void Unmap(u64 size); |
| 37 | 37 | ||
| 38 | VkBuffer Handle() const { | 38 | VkBuffer Handle() const noexcept { |
| 39 | return *buffer; | 39 | return *buffer; |
| 40 | } | 40 | } |
| 41 | 41 | ||
| 42 | u64 Address() const noexcept { | ||
| 43 | return 0; | ||
| 44 | } | ||
| 45 | |||
| 42 | private: | 46 | private: |
| 43 | struct Watch final { | 47 | struct Watch final { |
| 44 | VKFenceWatch fence; | 48 | VKFenceWatch fence; |
diff --git a/src/video_core/shader/decode/half_set.cpp b/src/video_core/shader/decode/half_set.cpp index 848e46874..b2e88fa20 100644 --- a/src/video_core/shader/decode/half_set.cpp +++ b/src/video_core/shader/decode/half_set.cpp | |||
| @@ -13,55 +13,101 @@ | |||
| 13 | 13 | ||
| 14 | namespace VideoCommon::Shader { | 14 | namespace VideoCommon::Shader { |
| 15 | 15 | ||
| 16 | using std::move; | ||
| 16 | using Tegra::Shader::Instruction; | 17 | using Tegra::Shader::Instruction; |
| 17 | using Tegra::Shader::OpCode; | 18 | using Tegra::Shader::OpCode; |
| 19 | using Tegra::Shader::PredCondition; | ||
| 18 | 20 | ||
| 19 | u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { | 21 | u32 ShaderIR::DecodeHalfSet(NodeBlock& bb, u32 pc) { |
| 20 | const Instruction instr = {program_code[pc]}; | 22 | const Instruction instr = {program_code[pc]}; |
| 21 | const auto opcode = OpCode::Decode(instr); | 23 | const auto opcode = OpCode::Decode(instr); |
| 22 | 24 | ||
| 23 | if (instr.hset2.ftz == 0) { | 25 | PredCondition cond; |
| 24 | LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | 26 | bool bf; |
| 27 | bool ftz; | ||
| 28 | bool neg_a; | ||
| 29 | bool abs_a; | ||
| 30 | bool neg_b; | ||
| 31 | bool abs_b; | ||
| 32 | switch (opcode->get().GetId()) { | ||
| 33 | case OpCode::Id::HSET2_C: | ||
| 34 | case OpCode::Id::HSET2_IMM: | ||
| 35 | cond = instr.hsetp2.cbuf_and_imm.cond; | ||
| 36 | bf = instr.Bit(53); | ||
| 37 | ftz = instr.Bit(54); | ||
| 38 | neg_a = instr.Bit(43); | ||
| 39 | abs_a = instr.Bit(44); | ||
| 40 | neg_b = instr.Bit(56); | ||
| 41 | abs_b = instr.Bit(54); | ||
| 42 | break; | ||
| 43 | case OpCode::Id::HSET2_R: | ||
| 44 | cond = instr.hsetp2.reg.cond; | ||
| 45 | bf = instr.Bit(49); | ||
| 46 | ftz = instr.Bit(50); | ||
| 47 | neg_a = instr.Bit(43); | ||
| 48 | abs_a = instr.Bit(44); | ||
| 49 | neg_b = instr.Bit(31); | ||
| 50 | abs_b = instr.Bit(30); | ||
| 51 | break; | ||
| 52 | default: | ||
| 53 | UNREACHABLE(); | ||
| 25 | } | 54 | } |
| 26 | 55 | ||
| 27 | Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); | 56 | Node op_b = [this, instr, opcode] { |
| 28 | op_a = GetOperandAbsNegHalf(op_a, instr.hset2.abs_a, instr.hset2.negate_a); | ||
| 29 | |||
| 30 | Node op_b = [&]() { | ||
| 31 | switch (opcode->get().GetId()) { | 57 | switch (opcode->get().GetId()) { |
| 58 | case OpCode::Id::HSET2_C: | ||
| 59 | // Inform as unimplemented as this is not tested. | ||
| 60 | UNIMPLEMENTED_MSG("HSET2_C is not implemented"); | ||
| 61 | return GetConstBuffer(instr.cbuf34.index, instr.cbuf34.GetOffset()); | ||
| 32 | case OpCode::Id::HSET2_R: | 62 | case OpCode::Id::HSET2_R: |
| 33 | return GetRegister(instr.gpr20); | 63 | return GetRegister(instr.gpr20); |
| 64 | case OpCode::Id::HSET2_IMM: | ||
| 65 | return UnpackHalfImmediate(instr, true); | ||
| 34 | default: | 66 | default: |
| 35 | UNREACHABLE(); | 67 | UNREACHABLE(); |
| 36 | return Immediate(0); | 68 | return Node{}; |
| 37 | } | 69 | } |
| 38 | }(); | 70 | }(); |
| 39 | op_b = UnpackHalfFloat(op_b, instr.hset2.type_b); | ||
| 40 | op_b = GetOperandAbsNegHalf(op_b, instr.hset2.abs_b, instr.hset2.negate_b); | ||
| 41 | 71 | ||
| 42 | const Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); | 72 | if (!ftz) { |
| 73 | LOG_DEBUG(HW_GPU, "{} without FTZ is not implemented", opcode->get().GetName()); | ||
| 74 | } | ||
| 75 | |||
| 76 | Node op_a = UnpackHalfFloat(GetRegister(instr.gpr8), instr.hset2.type_a); | ||
| 77 | op_a = GetOperandAbsNegHalf(op_a, abs_a, neg_a); | ||
| 78 | |||
| 79 | switch (opcode->get().GetId()) { | ||
| 80 | case OpCode::Id::HSET2_R: | ||
| 81 | op_b = GetOperandAbsNegHalf(move(op_b), abs_b, neg_b); | ||
| 82 | [[fallthrough]]; | ||
| 83 | case OpCode::Id::HSET2_C: | ||
| 84 | op_b = UnpackHalfFloat(move(op_b), instr.hset2.type_b); | ||
| 85 | break; | ||
| 86 | default: | ||
| 87 | break; | ||
| 88 | } | ||
| 43 | 89 | ||
| 44 | const Node comparison_pair = GetPredicateComparisonHalf(instr.hset2.cond, op_a, op_b); | 90 | Node second_pred = GetPredicate(instr.hset2.pred39, instr.hset2.neg_pred); |
| 91 | |||
| 92 | Node comparison_pair = GetPredicateComparisonHalf(cond, op_a, op_b); | ||
| 45 | 93 | ||
| 46 | const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); | 94 | const OperationCode combiner = GetPredicateCombiner(instr.hset2.op); |
| 47 | 95 | ||
| 48 | // HSET2 operates on each half float in the pack. | 96 | // HSET2 operates on each half float in the pack. |
| 49 | std::array<Node, 2> values; | 97 | std::array<Node, 2> values; |
| 50 | for (u32 i = 0; i < 2; ++i) { | 98 | for (u32 i = 0; i < 2; ++i) { |
| 51 | const u32 raw_value = instr.hset2.bf ? 0x3c00 : 0xffff; | 99 | const u32 raw_value = bf ? 0x3c00 : 0xffff; |
| 52 | const Node true_value = Immediate(raw_value << (i * 16)); | 100 | Node true_value = Immediate(raw_value << (i * 16)); |
| 53 | const Node false_value = Immediate(0); | 101 | Node false_value = Immediate(0); |
| 54 | |||
| 55 | const Node comparison = | ||
| 56 | Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||
| 57 | const Node predicate = Operation(combiner, comparison, second_pred); | ||
| 58 | 102 | ||
| 103 | Node comparison = Operation(OperationCode::LogicalPick2, comparison_pair, Immediate(i)); | ||
| 104 | Node predicate = Operation(combiner, comparison, second_pred); | ||
| 59 | values[i] = | 105 | values[i] = |
| 60 | Operation(OperationCode::Select, NO_PRECISE, predicate, true_value, false_value); | 106 | Operation(OperationCode::Select, predicate, move(true_value), move(false_value)); |
| 61 | } | 107 | } |
| 62 | 108 | ||
| 63 | const Node value = Operation(OperationCode::UBitwiseOr, NO_PRECISE, values[0], values[1]); | 109 | Node value = Operation(OperationCode::UBitwiseOr, values[0], values[1]); |
| 64 | SetRegister(bb, instr.gpr0, value); | 110 | SetRegister(bb, instr.gpr0, move(value)); |
| 65 | 111 | ||
| 66 | return pc; | 112 | return pc; |
| 67 | } | 113 | } |
diff --git a/src/video_core/shader/decode/image.cpp b/src/video_core/shader/decode/image.cpp index 60b6ad72a..07778dc3e 100644 --- a/src/video_core/shader/decode/image.cpp +++ b/src/video_core/shader/decode/image.cpp | |||
| @@ -97,6 +97,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 97 | break; | 97 | break; |
| 98 | case TextureFormat::B5G6R5: | 98 | case TextureFormat::B5G6R5: |
| 99 | case TextureFormat::B6G5R5: | 99 | case TextureFormat::B6G5R5: |
| 100 | case TextureFormat::BF10GF11RF11: | ||
| 100 | if (component == 0) { | 101 | if (component == 0) { |
| 101 | return descriptor.b_type; | 102 | return descriptor.b_type; |
| 102 | } | 103 | } |
| @@ -119,7 +120,7 @@ ComponentType GetComponentType(Tegra::Engines::SamplerDescriptor descriptor, | |||
| 119 | } | 120 | } |
| 120 | break; | 121 | break; |
| 121 | } | 122 | } |
| 122 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | 123 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); |
| 123 | return ComponentType::FLOAT; | 124 | return ComponentType::FLOAT; |
| 124 | } | 125 | } |
| 125 | 126 | ||
| @@ -191,6 +192,14 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 191 | return 6; | 192 | return 6; |
| 192 | } | 193 | } |
| 193 | return 0; | 194 | return 0; |
| 195 | case TextureFormat::BF10GF11RF11: | ||
| 196 | if (component == 1 || component == 2) { | ||
| 197 | return 11; | ||
| 198 | } | ||
| 199 | if (component == 0) { | ||
| 200 | return 10; | ||
| 201 | } | ||
| 202 | return 0; | ||
| 194 | case TextureFormat::G8R24: | 203 | case TextureFormat::G8R24: |
| 195 | if (component == 0) { | 204 | if (component == 0) { |
| 196 | return 8; | 205 | return 8; |
| @@ -211,10 +220,9 @@ u32 GetComponentSize(TextureFormat format, std::size_t component) { | |||
| 211 | return (component == 0 || component == 1) ? 8 : 0; | 220 | return (component == 0 || component == 1) ? 8 : 0; |
| 212 | case TextureFormat::G4R4: | 221 | case TextureFormat::G4R4: |
| 213 | return (component == 0 || component == 1) ? 4 : 0; | 222 | return (component == 0 || component == 1) ? 4 : 0; |
| 214 | default: | ||
| 215 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | ||
| 216 | return 0; | ||
| 217 | } | 223 | } |
| 224 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); | ||
| 225 | return 0; | ||
| 218 | } | 226 | } |
| 219 | 227 | ||
| 220 | std::size_t GetImageComponentMask(TextureFormat format) { | 228 | std::size_t GetImageComponentMask(TextureFormat format) { |
| @@ -235,6 +243,7 @@ std::size_t GetImageComponentMask(TextureFormat format) { | |||
| 235 | case TextureFormat::R32_B24G8: | 243 | case TextureFormat::R32_B24G8: |
| 236 | case TextureFormat::B5G6R5: | 244 | case TextureFormat::B5G6R5: |
| 237 | case TextureFormat::B6G5R5: | 245 | case TextureFormat::B6G5R5: |
| 246 | case TextureFormat::BF10GF11RF11: | ||
| 238 | return std::size_t{R | G | B}; | 247 | return std::size_t{R | G | B}; |
| 239 | case TextureFormat::R32_G32: | 248 | case TextureFormat::R32_G32: |
| 240 | case TextureFormat::R16_G16: | 249 | case TextureFormat::R16_G16: |
| @@ -248,10 +257,9 @@ std::size_t GetImageComponentMask(TextureFormat format) { | |||
| 248 | case TextureFormat::R8: | 257 | case TextureFormat::R8: |
| 249 | case TextureFormat::R1: | 258 | case TextureFormat::R1: |
| 250 | return std::size_t{R}; | 259 | return std::size_t{R}; |
| 251 | default: | ||
| 252 | UNIMPLEMENTED_MSG("texture format not implement={}", format); | ||
| 253 | return std::size_t{R | G | B | A}; | ||
| 254 | } | 260 | } |
| 261 | UNIMPLEMENTED_MSG("Texture format not implemented={}", format); | ||
| 262 | return std::size_t{R | G | B | A}; | ||
| 255 | } | 263 | } |
| 256 | 264 | ||
| 257 | std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) { | 265 | std::size_t GetImageTypeNumCoordinates(Tegra::Shader::ImageType image_type) { |
| @@ -299,7 +307,7 @@ std::pair<Node, bool> ShaderIR::GetComponentValue(ComponentType component_type, | |||
| 299 | return {std::move(original_value), true}; | 307 | return {std::move(original_value), true}; |
| 300 | } | 308 | } |
| 301 | default: | 309 | default: |
| 302 | UNIMPLEMENTED_MSG("Unimplement component type={}", component_type); | 310 | UNIMPLEMENTED_MSG("Unimplemented component type={}", component_type); |
| 303 | return {std::move(original_value), true}; | 311 | return {std::move(original_value), true}; |
| 304 | } | 312 | } |
| 305 | } | 313 | } |
| @@ -459,7 +467,7 @@ u32 ShaderIR::DecodeImage(NodeBlock& bb, u32 pc) { | |||
| 459 | default: | 467 | default: |
| 460 | break; | 468 | break; |
| 461 | } | 469 | } |
| 462 | UNIMPLEMENTED_MSG("Unimplemented operation={} type={}", | 470 | UNIMPLEMENTED_MSG("Unimplemented operation={}, type={}", |
| 463 | static_cast<u64>(instr.suatom_d.operation.Value()), | 471 | static_cast<u64>(instr.suatom_d.operation.Value()), |
| 464 | static_cast<u64>(instr.suatom_d.operation_type.Value())); | 472 | static_cast<u64>(instr.suatom_d.operation_type.Value())); |
| 465 | return OperationCode::AtomicImageAdd; | 473 | return OperationCode::AtomicImageAdd; |
diff --git a/src/video_core/texture_cache/surface_base.cpp b/src/video_core/texture_cache/surface_base.cpp index 94d3a6ae5..0caf3b4f0 100644 --- a/src/video_core/texture_cache/surface_base.cpp +++ b/src/video_core/texture_cache/surface_base.cpp | |||
| @@ -120,6 +120,9 @@ std::optional<std::pair<u32, u32>> SurfaceBaseImpl::GetLayerMipmap( | |||
| 120 | } | 120 | } |
| 121 | const auto relative_address{static_cast<GPUVAddr>(candidate_gpu_addr - gpu_addr)}; | 121 | const auto relative_address{static_cast<GPUVAddr>(candidate_gpu_addr - gpu_addr)}; |
| 122 | const auto layer{static_cast<u32>(relative_address / layer_size)}; | 122 | const auto layer{static_cast<u32>(relative_address / layer_size)}; |
| 123 | if (layer >= params.depth) { | ||
| 124 | return {}; | ||
| 125 | } | ||
| 123 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; | 126 | const GPUVAddr mipmap_address = relative_address - layer_size * layer; |
| 124 | const auto mipmap_it = | 127 | const auto mipmap_it = |
| 125 | Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); | 128 | Common::BinaryFind(mipmap_offsets.begin(), mipmap_offsets.end(), mipmap_address); |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 059b96e70..4dedb2549 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -56,6 +56,7 @@ static FileSys::VirtualFile VfsDirectoryCreateFileWrapper(const FileSys::Virtual | |||
| 56 | #include <QShortcut> | 56 | #include <QShortcut> |
| 57 | #include <QStatusBar> | 57 | #include <QStatusBar> |
| 58 | #include <QSysInfo> | 58 | #include <QSysInfo> |
| 59 | #include <QUrl> | ||
| 59 | #include <QtConcurrent/QtConcurrent> | 60 | #include <QtConcurrent/QtConcurrent> |
| 60 | 61 | ||
| 61 | #include <fmt/format.h> | 62 | #include <fmt/format.h> |
| @@ -836,6 +837,7 @@ void GMainWindow::ConnectMenuEvents() { | |||
| 836 | connect(ui.action_Stop, &QAction::triggered, this, &GMainWindow::OnStopGame); | 837 | connect(ui.action_Stop, &QAction::triggered, this, &GMainWindow::OnStopGame); |
| 837 | connect(ui.action_Report_Compatibility, &QAction::triggered, this, | 838 | connect(ui.action_Report_Compatibility, &QAction::triggered, this, |
| 838 | &GMainWindow::OnMenuReportCompatibility); | 839 | &GMainWindow::OnMenuReportCompatibility); |
| 840 | connect(ui.action_Open_Mods_Page, &QAction::triggered, this, &GMainWindow::OnOpenModsPage); | ||
| 839 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); | 841 | connect(ui.action_Restart, &QAction::triggered, this, [this] { BootGame(QString(game_path)); }); |
| 840 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); | 842 | connect(ui.action_Configure, &QAction::triggered, this, &GMainWindow::OnConfigure); |
| 841 | 843 | ||
| @@ -1807,6 +1809,16 @@ void GMainWindow::OnMenuReportCompatibility() { | |||
| 1807 | } | 1809 | } |
| 1808 | } | 1810 | } |
| 1809 | 1811 | ||
| 1812 | void GMainWindow::OnOpenModsPage() { | ||
| 1813 | const auto mods_page_url = QStringLiteral("https://github.com/yuzu-emu/yuzu/wiki/Switch-Mods"); | ||
| 1814 | const QUrl mods_page(mods_page_url); | ||
| 1815 | const bool open = QDesktopServices::openUrl(mods_page); | ||
| 1816 | if (!open) { | ||
| 1817 | QMessageBox::warning(this, tr("Error opening URL"), | ||
| 1818 | tr("Unable to open the URL \"%1\".").arg(mods_page_url)); | ||
| 1819 | } | ||
| 1820 | } | ||
| 1821 | |||
| 1810 | void GMainWindow::ToggleFullscreen() { | 1822 | void GMainWindow::ToggleFullscreen() { |
| 1811 | if (!emulation_running) { | 1823 | if (!emulation_running) { |
| 1812 | return; | 1824 | return; |
diff --git a/src/yuzu/main.h b/src/yuzu/main.h index 4f4c8ddbe..d55e55cc6 100644 --- a/src/yuzu/main.h +++ b/src/yuzu/main.h | |||
| @@ -181,6 +181,7 @@ private slots: | |||
| 181 | void OnPauseGame(); | 181 | void OnPauseGame(); |
| 182 | void OnStopGame(); | 182 | void OnStopGame(); |
| 183 | void OnMenuReportCompatibility(); | 183 | void OnMenuReportCompatibility(); |
| 184 | void OnOpenModsPage(); | ||
| 184 | /// Called whenever a user selects a game in the game list widget. | 185 | /// Called whenever a user selects a game in the game list widget. |
| 185 | void OnGameListLoadFile(QString game_path); | 186 | void OnGameListLoadFile(QString game_path); |
| 186 | void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); | 187 | void OnGameListOpenFolder(GameListOpenTarget target, const std::string& game_path); |
diff --git a/src/yuzu/main.ui b/src/yuzu/main.ui index 97c90f50b..b5745dfd5 100644 --- a/src/yuzu/main.ui +++ b/src/yuzu/main.ui | |||
| @@ -113,6 +113,7 @@ | |||
| 113 | <string>&Help</string> | 113 | <string>&Help</string> |
| 114 | </property> | 114 | </property> |
| 115 | <addaction name="action_Report_Compatibility"/> | 115 | <addaction name="action_Report_Compatibility"/> |
| 116 | <addaction name="action_Open_Mods_Page"/> | ||
| 116 | <addaction name="separator"/> | 117 | <addaction name="separator"/> |
| 117 | <addaction name="action_About"/> | 118 | <addaction name="action_About"/> |
| 118 | </widget> | 119 | </widget> |
| @@ -256,6 +257,11 @@ | |||
| 256 | <bool>false</bool> | 257 | <bool>false</bool> |
| 257 | </property> | 258 | </property> |
| 258 | </action> | 259 | </action> |
| 260 | <action name="action_Open_Mods_Page"> | ||
| 261 | <property name="text"> | ||
| 262 | <string>Open Mods Page</string> | ||
| 263 | </property> | ||
| 264 | </action> | ||
| 259 | <action name="action_Open_yuzu_Folder"> | 265 | <action name="action_Open_yuzu_Folder"> |
| 260 | <property name="text"> | 266 | <property name="text"> |
| 261 | <string>Open yuzu Folder</string> | 267 | <string>Open yuzu Folder</string> |