diff options
23 files changed, 669 insertions, 203 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt index b31a0328c..e836bf396 100644 --- a/src/core/CMakeLists.txt +++ b/src/core/CMakeLists.txt | |||
| @@ -287,6 +287,18 @@ add_library(core STATIC | |||
| 287 | hle/service/btm/btm.h | 287 | hle/service/btm/btm.h |
| 288 | hle/service/caps/caps.cpp | 288 | hle/service/caps/caps.cpp |
| 289 | hle/service/caps/caps.h | 289 | hle/service/caps/caps.h |
| 290 | hle/service/caps/caps_a.cpp | ||
| 291 | hle/service/caps/caps_a.h | ||
| 292 | hle/service/caps/caps_c.cpp | ||
| 293 | hle/service/caps/caps_c.h | ||
| 294 | hle/service/caps/caps_u.cpp | ||
| 295 | hle/service/caps/caps_u.h | ||
| 296 | hle/service/caps/caps_sc.cpp | ||
| 297 | hle/service/caps/caps_sc.h | ||
| 298 | hle/service/caps/caps_ss.cpp | ||
| 299 | hle/service/caps/caps_ss.h | ||
| 300 | hle/service/caps/caps_su.cpp | ||
| 301 | hle/service/caps/caps_su.h | ||
| 290 | hle/service/erpt/erpt.cpp | 302 | hle/service/erpt/erpt.cpp |
| 291 | hle/service/erpt/erpt.h | 303 | hle/service/erpt/erpt.h |
| 292 | hle/service/es/es.cpp | 304 | hle/service/es/es.cpp |
diff --git a/src/core/hle/service/caps/caps.cpp b/src/core/hle/service/caps/caps.cpp index 907f464ab..26c8a7081 100644 --- a/src/core/hle/service/caps/caps.cpp +++ b/src/core/hle/service/caps/caps.cpp | |||
| @@ -2,168 +2,24 @@ | |||
| 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 <memory> | ||
| 6 | |||
| 7 | #include "core/hle/service/caps/caps.h" | 5 | #include "core/hle/service/caps/caps.h" |
| 6 | #include "core/hle/service/caps/caps_a.h" | ||
| 7 | #include "core/hle/service/caps/caps_c.h" | ||
| 8 | #include "core/hle/service/caps/caps_sc.h" | ||
| 9 | #include "core/hle/service/caps/caps_ss.h" | ||
| 10 | #include "core/hle/service/caps/caps_su.h" | ||
| 11 | #include "core/hle/service/caps/caps_u.h" | ||
| 8 | #include "core/hle/service/service.h" | 12 | #include "core/hle/service/service.h" |
| 9 | #include "core/hle/service/sm/sm.h" | ||
| 10 | 13 | ||
| 11 | namespace Service::Capture { | 14 | namespace Service::Capture { |
| 12 | 15 | ||
| 13 | class CAPS_A final : public ServiceFramework<CAPS_A> { | ||
| 14 | public: | ||
| 15 | explicit CAPS_A() : ServiceFramework{"caps:a"} { | ||
| 16 | // clang-format off | ||
| 17 | static const FunctionInfo functions[] = { | ||
| 18 | {0, nullptr, "GetAlbumFileCount"}, | ||
| 19 | {1, nullptr, "GetAlbumFileList"}, | ||
| 20 | {2, nullptr, "LoadAlbumFile"}, | ||
| 21 | {3, nullptr, "DeleteAlbumFile"}, | ||
| 22 | {4, nullptr, "StorageCopyAlbumFile"}, | ||
| 23 | {5, nullptr, "IsAlbumMounted"}, | ||
| 24 | {6, nullptr, "GetAlbumUsage"}, | ||
| 25 | {7, nullptr, "GetAlbumFileSize"}, | ||
| 26 | {8, nullptr, "LoadAlbumFileThumbnail"}, | ||
| 27 | {9, nullptr, "LoadAlbumScreenShotImage"}, | ||
| 28 | {10, nullptr, "LoadAlbumScreenShotThumbnailImage"}, | ||
| 29 | {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"}, | ||
| 30 | {12, nullptr, "Unknown12"}, | ||
| 31 | {13, nullptr, "Unknown13"}, | ||
| 32 | {14, nullptr, "Unknown14"}, | ||
| 33 | {15, nullptr, "Unknown15"}, | ||
| 34 | {16, nullptr, "Unknown16"}, | ||
| 35 | {17, nullptr, "Unknown17"}, | ||
| 36 | {18, nullptr, "Unknown18"}, | ||
| 37 | {202, nullptr, "SaveEditedScreenShot"}, | ||
| 38 | {301, nullptr, "GetLastThumbnail"}, | ||
| 39 | {401, nullptr, "GetAutoSavingStorage"}, | ||
| 40 | {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"}, | ||
| 41 | {1001, nullptr, "Unknown1001"}, | ||
| 42 | {1002, nullptr, "Unknown1002"}, | ||
| 43 | {1003, nullptr, "Unknown1003"}, | ||
| 44 | {8001, nullptr, "ForceAlbumUnmounted"}, | ||
| 45 | {8002, nullptr, "ResetAlbumMountStatus"}, | ||
| 46 | {8011, nullptr, "RefreshAlbumCache"}, | ||
| 47 | {8012, nullptr, "GetAlbumCache"}, | ||
| 48 | {8013, nullptr, "Unknown8013"}, | ||
| 49 | {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"}, | ||
| 50 | {10011, nullptr, "SetInternalErrorConversionEnabled"}, | ||
| 51 | {50000, nullptr, "Unknown50000"}, | ||
| 52 | {60002, nullptr, "Unknown60002"}, | ||
| 53 | }; | ||
| 54 | // clang-format on | ||
| 55 | |||
| 56 | RegisterHandlers(functions); | ||
| 57 | } | ||
| 58 | }; | ||
| 59 | |||
| 60 | class CAPS_C final : public ServiceFramework<CAPS_C> { | ||
| 61 | public: | ||
| 62 | explicit CAPS_C() : ServiceFramework{"caps:c"} { | ||
| 63 | // clang-format off | ||
| 64 | static const FunctionInfo functions[] = { | ||
| 65 | {33, nullptr, "Unknown33"}, | ||
| 66 | {2001, nullptr, "Unknown2001"}, | ||
| 67 | {2002, nullptr, "Unknown2002"}, | ||
| 68 | {2011, nullptr, "Unknown2011"}, | ||
| 69 | {2012, nullptr, "Unknown2012"}, | ||
| 70 | {2013, nullptr, "Unknown2013"}, | ||
| 71 | {2014, nullptr, "Unknown2014"}, | ||
| 72 | {2101, nullptr, "Unknown2101"}, | ||
| 73 | {2102, nullptr, "Unknown2102"}, | ||
| 74 | {2201, nullptr, "Unknown2201"}, | ||
| 75 | {2301, nullptr, "Unknown2301"}, | ||
| 76 | }; | ||
| 77 | // clang-format on | ||
| 78 | |||
| 79 | RegisterHandlers(functions); | ||
| 80 | } | ||
| 81 | }; | ||
| 82 | |||
| 83 | class CAPS_SC final : public ServiceFramework<CAPS_SC> { | ||
| 84 | public: | ||
| 85 | explicit CAPS_SC() : ServiceFramework{"caps:sc"} { | ||
| 86 | // clang-format off | ||
| 87 | static const FunctionInfo functions[] = { | ||
| 88 | {1, nullptr, "Unknown1"}, | ||
| 89 | {2, nullptr, "Unknown2"}, | ||
| 90 | {1001, nullptr, "Unknown3"}, | ||
| 91 | {1002, nullptr, "Unknown4"}, | ||
| 92 | {1003, nullptr, "Unknown5"}, | ||
| 93 | {1011, nullptr, "Unknown6"}, | ||
| 94 | {1012, nullptr, "Unknown7"}, | ||
| 95 | {1201, nullptr, "Unknown8"}, | ||
| 96 | {1202, nullptr, "Unknown9"}, | ||
| 97 | {1203, nullptr, "Unknown10"}, | ||
| 98 | }; | ||
| 99 | // clang-format on | ||
| 100 | |||
| 101 | RegisterHandlers(functions); | ||
| 102 | } | ||
| 103 | }; | ||
| 104 | |||
| 105 | class CAPS_SS final : public ServiceFramework<CAPS_SS> { | ||
| 106 | public: | ||
| 107 | explicit CAPS_SS() : ServiceFramework{"caps:ss"} { | ||
| 108 | // clang-format off | ||
| 109 | static const FunctionInfo functions[] = { | ||
| 110 | {201, nullptr, "Unknown1"}, | ||
| 111 | {202, nullptr, "Unknown2"}, | ||
| 112 | {203, nullptr, "Unknown3"}, | ||
| 113 | {204, nullptr, "Unknown4"}, | ||
| 114 | }; | ||
| 115 | // clang-format on | ||
| 116 | |||
| 117 | RegisterHandlers(functions); | ||
| 118 | } | ||
| 119 | }; | ||
| 120 | |||
| 121 | class CAPS_SU final : public ServiceFramework<CAPS_SU> { | ||
| 122 | public: | ||
| 123 | explicit CAPS_SU() : ServiceFramework{"caps:su"} { | ||
| 124 | // clang-format off | ||
| 125 | static const FunctionInfo functions[] = { | ||
| 126 | {201, nullptr, "SaveScreenShot"}, | ||
| 127 | {203, nullptr, "SaveScreenShotEx0"}, | ||
| 128 | }; | ||
| 129 | // clang-format on | ||
| 130 | |||
| 131 | RegisterHandlers(functions); | ||
| 132 | } | ||
| 133 | }; | ||
| 134 | |||
| 135 | class CAPS_U final : public ServiceFramework<CAPS_U> { | ||
| 136 | public: | ||
| 137 | explicit CAPS_U() : ServiceFramework{"caps:u"} { | ||
| 138 | // clang-format off | ||
| 139 | static const FunctionInfo functions[] = { | ||
| 140 | {32, nullptr, "SetShimLibraryVersion"}, | ||
| 141 | {102, nullptr, "GetAlbumFileListByAruid"}, | ||
| 142 | {103, nullptr, "DeleteAlbumFileByAruid"}, | ||
| 143 | {104, nullptr, "GetAlbumFileSizeByAruid"}, | ||
| 144 | {105, nullptr, "DeleteAlbumFileByAruidForDebug"}, | ||
| 145 | {110, nullptr, "LoadAlbumScreenShotImageByAruid"}, | ||
| 146 | {120, nullptr, "LoadAlbumScreenShotThumbnailImageByAruid"}, | ||
| 147 | {130, nullptr, "PrecheckToCreateContentsByAruid"}, | ||
| 148 | {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"}, | ||
| 149 | {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, | ||
| 150 | {142, nullptr, "GetAlbumFileList3AaeAruid"}, | ||
| 151 | {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, | ||
| 152 | {60002, nullptr, "OpenAccessorSessionForApplication"}, | ||
| 153 | }; | ||
| 154 | // clang-format on | ||
| 155 | |||
| 156 | RegisterHandlers(functions); | ||
| 157 | } | ||
| 158 | }; | ||
| 159 | |||
| 160 | void InstallInterfaces(SM::ServiceManager& sm) { | 16 | void InstallInterfaces(SM::ServiceManager& sm) { |
| 161 | std::make_shared<CAPS_A>()->InstallAsService(sm); | 17 | std::make_shared<CAPS_A>()->InstallAsService(sm); |
| 162 | std::make_shared<CAPS_C>()->InstallAsService(sm); | 18 | std::make_shared<CAPS_C>()->InstallAsService(sm); |
| 19 | std::make_shared<CAPS_U>()->InstallAsService(sm); | ||
| 163 | std::make_shared<CAPS_SC>()->InstallAsService(sm); | 20 | std::make_shared<CAPS_SC>()->InstallAsService(sm); |
| 164 | std::make_shared<CAPS_SS>()->InstallAsService(sm); | 21 | std::make_shared<CAPS_SS>()->InstallAsService(sm); |
| 165 | std::make_shared<CAPS_SU>()->InstallAsService(sm); | 22 | std::make_shared<CAPS_SU>()->InstallAsService(sm); |
| 166 | std::make_shared<CAPS_U>()->InstallAsService(sm); | ||
| 167 | } | 23 | } |
| 168 | 24 | ||
| 169 | } // namespace Service::Capture | 25 | } // namespace Service::Capture |
diff --git a/src/core/hle/service/caps/caps.h b/src/core/hle/service/caps/caps.h index 471185dfa..fc70a4c27 100644 --- a/src/core/hle/service/caps/caps.h +++ b/src/core/hle/service/caps/caps.h | |||
| @@ -4,12 +4,83 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 7 | namespace Service::SM { | 9 | namespace Service::SM { |
| 8 | class ServiceManager; | 10 | class ServiceManager; |
| 9 | } | 11 | } |
| 10 | 12 | ||
| 11 | namespace Service::Capture { | 13 | namespace Service::Capture { |
| 12 | 14 | ||
| 15 | enum AlbumImageOrientation { | ||
| 16 | Orientation0 = 0, | ||
| 17 | Orientation1 = 1, | ||
| 18 | Orientation2 = 2, | ||
| 19 | Orientation3 = 3, | ||
| 20 | }; | ||
| 21 | |||
| 22 | enum AlbumReportOption { | ||
| 23 | Disable = 0, | ||
| 24 | Enable = 1, | ||
| 25 | }; | ||
| 26 | |||
| 27 | enum ContentType : u8 { | ||
| 28 | Screenshot = 0, | ||
| 29 | Movie = 1, | ||
| 30 | ExtraMovie = 3, | ||
| 31 | }; | ||
| 32 | |||
| 33 | enum AlbumStorage : u8 { | ||
| 34 | NAND = 0, | ||
| 35 | SD = 1, | ||
| 36 | }; | ||
| 37 | |||
| 38 | struct AlbumFileDateTime { | ||
| 39 | u16 year; | ||
| 40 | u8 month; | ||
| 41 | u8 day; | ||
| 42 | u8 hour; | ||
| 43 | u8 minute; | ||
| 44 | u8 second; | ||
| 45 | u8 uid; | ||
| 46 | }; | ||
| 47 | |||
| 48 | struct AlbumEntry { | ||
| 49 | u64 size; | ||
| 50 | u64 application_id; | ||
| 51 | AlbumFileDateTime datetime; | ||
| 52 | AlbumStorage storage; | ||
| 53 | ContentType content; | ||
| 54 | u8 padding[6]; | ||
| 55 | }; | ||
| 56 | |||
| 57 | struct AlbumFileEntry { | ||
| 58 | u64 size; | ||
| 59 | u64 hash; | ||
| 60 | AlbumFileDateTime datetime; | ||
| 61 | AlbumStorage storage; | ||
| 62 | ContentType content; | ||
| 63 | u8 padding[5]; | ||
| 64 | u8 unknown; | ||
| 65 | }; | ||
| 66 | |||
| 67 | struct ApplicationAlbumEntry { | ||
| 68 | u64 size; | ||
| 69 | u64 hash; | ||
| 70 | AlbumFileDateTime datetime; | ||
| 71 | AlbumStorage storage; | ||
| 72 | ContentType content; | ||
| 73 | u8 padding[5]; | ||
| 74 | u8 unknown; | ||
| 75 | }; | ||
| 76 | |||
| 77 | struct ApplicationAlbumFileEntry { | ||
| 78 | ApplicationAlbumEntry entry; | ||
| 79 | AlbumFileDateTime datetime; | ||
| 80 | u64 unknown; | ||
| 81 | }; | ||
| 82 | |||
| 83 | /// Registers all Capture services with the specified service manager. | ||
| 13 | void InstallInterfaces(SM::ServiceManager& sm); | 84 | void InstallInterfaces(SM::ServiceManager& sm); |
| 14 | 85 | ||
| 15 | } // namespace Service::Capture | 86 | } // namespace Service::Capture |
diff --git a/src/core/hle/service/caps/caps_a.cpp b/src/core/hle/service/caps/caps_a.cpp new file mode 100644 index 000000000..88a3fdc05 --- /dev/null +++ b/src/core/hle/service/caps/caps_a.cpp | |||
| @@ -0,0 +1,78 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/caps/caps_a.h" | ||
| 6 | |||
| 7 | namespace Service::Capture { | ||
| 8 | |||
| 9 | class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> { | ||
| 10 | public: | ||
| 11 | explicit IAlbumAccessorSession() : ServiceFramework{"IAlbumAccessorSession"} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {2001, nullptr, "OpenAlbumMovieReadStream"}, | ||
| 15 | {2002, nullptr, "CloseAlbumMovieReadStream"}, | ||
| 16 | {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"}, | ||
| 17 | {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"}, | ||
| 18 | {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"}, | ||
| 19 | {2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"}, | ||
| 20 | {2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"}, | ||
| 21 | {2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"}, | ||
| 22 | }; | ||
| 23 | // clang-format on | ||
| 24 | |||
| 25 | RegisterHandlers(functions); | ||
| 26 | } | ||
| 27 | }; | ||
| 28 | |||
| 29 | CAPS_A::CAPS_A() : ServiceFramework("caps:a") { | ||
| 30 | // clang-format off | ||
| 31 | static const FunctionInfo functions[] = { | ||
| 32 | {0, nullptr, "GetAlbumFileCount"}, | ||
| 33 | {1, nullptr, "GetAlbumFileList"}, | ||
| 34 | {2, nullptr, "LoadAlbumFile"}, | ||
| 35 | {3, nullptr, "DeleteAlbumFile"}, | ||
| 36 | {4, nullptr, "StorageCopyAlbumFile"}, | ||
| 37 | {5, nullptr, "IsAlbumMounted"}, | ||
| 38 | {6, nullptr, "GetAlbumUsage"}, | ||
| 39 | {7, nullptr, "GetAlbumFileSize"}, | ||
| 40 | {8, nullptr, "LoadAlbumFileThumbnail"}, | ||
| 41 | {9, nullptr, "LoadAlbumScreenShotImage"}, | ||
| 42 | {10, nullptr, "LoadAlbumScreenShotThumbnailImage"}, | ||
| 43 | {11, nullptr, "GetAlbumEntryFromApplicationAlbumEntry"}, | ||
| 44 | {12, nullptr, "LoadAlbumScreenShotImageEx"}, | ||
| 45 | {13, nullptr, "LoadAlbumScreenShotThumbnailImageEx"}, | ||
| 46 | {14, nullptr, "LoadAlbumScreenShotImageEx0"}, | ||
| 47 | {15, nullptr, "GetAlbumUsage3"}, | ||
| 48 | {16, nullptr, "GetAlbumMountResult"}, | ||
| 49 | {17, nullptr, "GetAlbumUsage16"}, | ||
| 50 | {18, nullptr, "Unknown18"}, | ||
| 51 | {100, nullptr, "GetAlbumFileCountEx0"}, | ||
| 52 | {101, nullptr, "GetAlbumFileListEx0"}, | ||
| 53 | {202, nullptr, "SaveEditedScreenShot"}, | ||
| 54 | {301, nullptr, "GetLastThumbnail"}, | ||
| 55 | {302, nullptr, "GetLastOverlayMovieThumbnail"}, | ||
| 56 | {401, nullptr, "GetAutoSavingStorage"}, | ||
| 57 | {501, nullptr, "GetRequiredStorageSpaceSizeToCopyAll"}, | ||
| 58 | {1001, nullptr, "LoadAlbumScreenShotThumbnailImageEx0"}, | ||
| 59 | {1002, nullptr, "LoadAlbumScreenShotImageEx1"}, | ||
| 60 | {1003, nullptr, "LoadAlbumScreenShotThumbnailImageEx1"}, | ||
| 61 | {8001, nullptr, "ForceAlbumUnmounted"}, | ||
| 62 | {8002, nullptr, "ResetAlbumMountStatus"}, | ||
| 63 | {8011, nullptr, "RefreshAlbumCache"}, | ||
| 64 | {8012, nullptr, "GetAlbumCache"}, | ||
| 65 | {8013, nullptr, "GetAlbumCacheEx"}, | ||
| 66 | {8021, nullptr, "GetAlbumEntryFromApplicationAlbumEntryAruid"}, | ||
| 67 | {10011, nullptr, "SetInternalErrorConversionEnabled"}, | ||
| 68 | {50000, nullptr, "LoadMakerNoteInfoForDebug"}, | ||
| 69 | {60002, nullptr, "OpenAccessorSession"}, | ||
| 70 | }; | ||
| 71 | // clang-format on | ||
| 72 | |||
| 73 | RegisterHandlers(functions); | ||
| 74 | } | ||
| 75 | |||
| 76 | CAPS_A::~CAPS_A() = default; | ||
| 77 | |||
| 78 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_a.h b/src/core/hle/service/caps/caps_a.h new file mode 100644 index 000000000..8de832491 --- /dev/null +++ b/src/core/hle/service/caps/caps_a.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_A final : public ServiceFramework<CAPS_A> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_A(); | ||
| 18 | ~CAPS_A() override; | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_c.cpp b/src/core/hle/service/caps/caps_c.cpp new file mode 100644 index 000000000..ea6452ffa --- /dev/null +++ b/src/core/hle/service/caps/caps_c.cpp | |||
| @@ -0,0 +1,75 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/caps/caps_c.h" | ||
| 6 | |||
| 7 | namespace Service::Capture { | ||
| 8 | |||
| 9 | class IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> { | ||
| 10 | public: | ||
| 11 | explicit IAlbumControlSession() : ServiceFramework{"IAlbumControlSession"} { | ||
| 12 | // clang-format off | ||
| 13 | static const FunctionInfo functions[] = { | ||
| 14 | {2001, nullptr, "OpenAlbumMovieReadStream"}, | ||
| 15 | {2002, nullptr, "CloseAlbumMovieReadStream"}, | ||
| 16 | {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"}, | ||
| 17 | {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"}, | ||
| 18 | {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"}, | ||
| 19 | {2006, nullptr, "GetAlbumMovieReadStreamImageDataSize"}, | ||
| 20 | {2007, nullptr, "ReadImageDataFromAlbumMovieReadStream"}, | ||
| 21 | {2008, nullptr, "ReadFileAttributeFromAlbumMovieReadStream"}, | ||
| 22 | {2401, nullptr, "OpenAlbumMovieWriteStream"}, | ||
| 23 | {2402, nullptr, "FinishAlbumMovieWriteStream"}, | ||
| 24 | {2403, nullptr, "CommitAlbumMovieWriteStream"}, | ||
| 25 | {2404, nullptr, "DiscardAlbumMovieWriteStream"}, | ||
| 26 | {2405, nullptr, "DiscardAlbumMovieWriteStreamNoDelete"}, | ||
| 27 | {2406, nullptr, "CommitAlbumMovieWriteStreamEx"}, | ||
| 28 | {2411, nullptr, "StartAlbumMovieWriteStreamDataSection"}, | ||
| 29 | {2412, nullptr, "EndAlbumMovieWriteStreamDataSection"}, | ||
| 30 | {2413, nullptr, "StartAlbumMovieWriteStreamMetaSection"}, | ||
| 31 | {2414, nullptr, "EndAlbumMovieWriteStreamMetaSection"}, | ||
| 32 | {2421, nullptr, "ReadDataFromAlbumMovieWriteStream"}, | ||
| 33 | {2422, nullptr, "WriteDataToAlbumMovieWriteStream"}, | ||
| 34 | {2424, nullptr, "WriteMetaToAlbumMovieWriteStream"}, | ||
| 35 | {2431, nullptr, "GetAlbumMovieWriteStreamBrokenReason"}, | ||
| 36 | {2433, nullptr, "GetAlbumMovieWriteStreamDataSize"}, | ||
| 37 | {2434, nullptr, "SetAlbumMovieWriteStreamDataSize"}, | ||
| 38 | }; | ||
| 39 | // clang-format on | ||
| 40 | |||
| 41 | RegisterHandlers(functions); | ||
| 42 | } | ||
| 43 | }; | ||
| 44 | |||
| 45 | CAPS_C::CAPS_C() : ServiceFramework("caps:c") { | ||
| 46 | // clang-format off | ||
| 47 | static const FunctionInfo functions[] = { | ||
| 48 | {1, nullptr, "CaptureRawImage"}, | ||
| 49 | {2, nullptr, "CaptureRawImageWithTimeout"}, | ||
| 50 | {33, nullptr, "Unknown33"}, | ||
| 51 | {1001, nullptr, "RequestTakingScreenShot"}, | ||
| 52 | {1002, nullptr, "RequestTakingScreenShotWithTimeout"}, | ||
| 53 | {1011, nullptr, "NotifyTakingScreenShotRefused"}, | ||
| 54 | {2001, nullptr, "NotifyAlbumStorageIsAvailable"}, | ||
| 55 | {2002, nullptr, "NotifyAlbumStorageIsUnavailable"}, | ||
| 56 | {2011, nullptr, "RegisterAppletResourceUserId"}, | ||
| 57 | {2012, nullptr, "UnregisterAppletResourceUserId"}, | ||
| 58 | {2013, nullptr, "GetApplicationIdFromAruid"}, | ||
| 59 | {2014, nullptr, "CheckApplicationIdRegistered"}, | ||
| 60 | {2101, nullptr, "GenerateCurrentAlbumFileId"}, | ||
| 61 | {2102, nullptr, "GenerateApplicationAlbumEntry"}, | ||
| 62 | {2201, nullptr, "SaveAlbumScreenShotFile"}, | ||
| 63 | {2202, nullptr, "SaveAlbumScreenShotFileEx"}, | ||
| 64 | {2301, nullptr, "SetOverlayScreenShotThumbnailData"}, | ||
| 65 | {2302, nullptr, "SetOverlayMovieThumbnailData"}, | ||
| 66 | {60001, nullptr, "OpenControlSession"}, | ||
| 67 | }; | ||
| 68 | // clang-format on | ||
| 69 | |||
| 70 | RegisterHandlers(functions); | ||
| 71 | } | ||
| 72 | |||
| 73 | CAPS_C::~CAPS_C() = default; | ||
| 74 | |||
| 75 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_c.h b/src/core/hle/service/caps/caps_c.h new file mode 100644 index 000000000..d07cdb441 --- /dev/null +++ b/src/core/hle/service/caps/caps_c.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_C final : public ServiceFramework<CAPS_C> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_C(); | ||
| 18 | ~CAPS_C() override; | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_sc.cpp b/src/core/hle/service/caps/caps_sc.cpp new file mode 100644 index 000000000..d01a8a58e --- /dev/null +++ b/src/core/hle/service/caps/caps_sc.cpp | |||
| @@ -0,0 +1,40 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/caps/caps_sc.h" | ||
| 6 | |||
| 7 | namespace Service::Capture { | ||
| 8 | |||
| 9 | CAPS_SC::CAPS_SC() : ServiceFramework("caps:sc") { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {1, nullptr, "CaptureRawImage"}, | ||
| 13 | {2, nullptr, "CaptureRawImageWithTimeout"}, | ||
| 14 | {3, nullptr, "AttachSharedBuffer"}, | ||
| 15 | {5, nullptr, "CaptureRawImageToAttachedSharedBuffer"}, | ||
| 16 | {210, nullptr, "Unknown210"}, | ||
| 17 | {1001, nullptr, "RequestTakingScreenShot"}, | ||
| 18 | {1002, nullptr, "RequestTakingScreenShotWithTimeout"}, | ||
| 19 | {1003, nullptr, "RequestTakingScreenShotEx"}, | ||
| 20 | {1004, nullptr, "RequestTakingScreenShotEx1"}, | ||
| 21 | {1009, nullptr, "CancelTakingScreenShot"}, | ||
| 22 | {1010, nullptr, "SetTakingScreenShotCancelState"}, | ||
| 23 | {1011, nullptr, "NotifyTakingScreenShotRefused"}, | ||
| 24 | {1012, nullptr, "NotifyTakingScreenShotFailed"}, | ||
| 25 | {1101, nullptr, "SetupOverlayMovieThumbnail"}, | ||
| 26 | {1106, nullptr, "Unknown1106"}, | ||
| 27 | {1107, nullptr, "Unknown1107"}, | ||
| 28 | {1201, nullptr, "OpenRawScreenShotReadStream"}, | ||
| 29 | {1202, nullptr, "CloseRawScreenShotReadStream"}, | ||
| 30 | {1203, nullptr, "ReadRawScreenShotReadStream"}, | ||
| 31 | {1204, nullptr, "Unknown1204"}, | ||
| 32 | }; | ||
| 33 | // clang-format on | ||
| 34 | |||
| 35 | RegisterHandlers(functions); | ||
| 36 | } | ||
| 37 | |||
| 38 | CAPS_SC::~CAPS_SC() = default; | ||
| 39 | |||
| 40 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_sc.h b/src/core/hle/service/caps/caps_sc.h new file mode 100644 index 000000000..9ba372f7a --- /dev/null +++ b/src/core/hle/service/caps/caps_sc.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_SC final : public ServiceFramework<CAPS_SC> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_SC(); | ||
| 18 | ~CAPS_SC() override; | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_ss.cpp b/src/core/hle/service/caps/caps_ss.cpp new file mode 100644 index 000000000..eaa3a7494 --- /dev/null +++ b/src/core/hle/service/caps/caps_ss.cpp | |||
| @@ -0,0 +1,26 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/caps/caps_ss.h" | ||
| 6 | |||
| 7 | namespace Service::Capture { | ||
| 8 | |||
| 9 | CAPS_SS::CAPS_SS() : ServiceFramework("caps:ss") { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {201, nullptr, "SaveScreenShot"}, | ||
| 13 | {202, nullptr, "SaveEditedScreenShot"}, | ||
| 14 | {203, nullptr, "SaveScreenShotEx0"}, | ||
| 15 | {204, nullptr, "SaveEditedScreenShotEx0"}, | ||
| 16 | {206, nullptr, "Unknown206"}, | ||
| 17 | {208, nullptr, "SaveScreenShotOfMovieEx1"}, | ||
| 18 | }; | ||
| 19 | // clang-format on | ||
| 20 | |||
| 21 | RegisterHandlers(functions); | ||
| 22 | } | ||
| 23 | |||
| 24 | CAPS_SS::~CAPS_SS() = default; | ||
| 25 | |||
| 26 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_ss.h b/src/core/hle/service/caps/caps_ss.h new file mode 100644 index 000000000..e258a6925 --- /dev/null +++ b/src/core/hle/service/caps/caps_ss.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_SS final : public ServiceFramework<CAPS_SS> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_SS(); | ||
| 18 | ~CAPS_SS() override; | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_su.cpp b/src/core/hle/service/caps/caps_su.cpp new file mode 100644 index 000000000..2b4c2d808 --- /dev/null +++ b/src/core/hle/service/caps/caps_su.cpp | |||
| @@ -0,0 +1,22 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "core/hle/service/caps/caps_su.h" | ||
| 6 | |||
| 7 | namespace Service::Capture { | ||
| 8 | |||
| 9 | CAPS_SU::CAPS_SU() : ServiceFramework("caps:su") { | ||
| 10 | // clang-format off | ||
| 11 | static const FunctionInfo functions[] = { | ||
| 12 | {201, nullptr, "SaveScreenShot"}, | ||
| 13 | {203, nullptr, "SaveScreenShotEx0"}, | ||
| 14 | }; | ||
| 15 | // clang-format on | ||
| 16 | |||
| 17 | RegisterHandlers(functions); | ||
| 18 | } | ||
| 19 | |||
| 20 | CAPS_SU::~CAPS_SU() = default; | ||
| 21 | |||
| 22 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_su.h b/src/core/hle/service/caps/caps_su.h new file mode 100644 index 000000000..cb11f7c9a --- /dev/null +++ b/src/core/hle/service/caps/caps_su.h | |||
| @@ -0,0 +1,21 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_SU final : public ServiceFramework<CAPS_SU> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_SU(); | ||
| 18 | ~CAPS_SU() override; | ||
| 19 | }; | ||
| 20 | |||
| 21 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_u.cpp b/src/core/hle/service/caps/caps_u.cpp new file mode 100644 index 000000000..78bab6ed8 --- /dev/null +++ b/src/core/hle/service/caps/caps_u.cpp | |||
| @@ -0,0 +1,76 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/logging/log.h" | ||
| 6 | #include "core/hle/ipc_helpers.h" | ||
| 7 | #include "core/hle/service/caps/caps.h" | ||
| 8 | #include "core/hle/service/caps/caps_u.h" | ||
| 9 | |||
| 10 | namespace Service::Capture { | ||
| 11 | |||
| 12 | class IAlbumAccessorApplicationSession final | ||
| 13 | : public ServiceFramework<IAlbumAccessorApplicationSession> { | ||
| 14 | public: | ||
| 15 | explicit IAlbumAccessorApplicationSession() | ||
| 16 | : ServiceFramework{"IAlbumAccessorApplicationSession"} { | ||
| 17 | // clang-format off | ||
| 18 | static const FunctionInfo functions[] = { | ||
| 19 | {2001, nullptr, "OpenAlbumMovieReadStream"}, | ||
| 20 | {2002, nullptr, "CloseAlbumMovieReadStream"}, | ||
| 21 | {2003, nullptr, "GetAlbumMovieReadStreamMovieDataSize"}, | ||
| 22 | {2004, nullptr, "ReadMovieDataFromAlbumMovieReadStream"}, | ||
| 23 | {2005, nullptr, "GetAlbumMovieReadStreamBrokenReason"}, | ||
| 24 | }; | ||
| 25 | // clang-format on | ||
| 26 | |||
| 27 | RegisterHandlers(functions); | ||
| 28 | } | ||
| 29 | }; | ||
| 30 | |||
| 31 | CAPS_U::CAPS_U() : ServiceFramework("caps:u") { | ||
| 32 | // clang-format off | ||
| 33 | static const FunctionInfo functions[] = { | ||
| 34 | {31, nullptr, "GetShimLibraryVersion"}, | ||
| 35 | {32, nullptr, "SetShimLibraryVersion"}, | ||
| 36 | {102, &CAPS_U::GetAlbumContentsFileListForApplication, "GetAlbumContentsFileListForApplication"}, | ||
| 37 | {103, nullptr, "DeleteAlbumContentsFileForApplication"}, | ||
| 38 | {104, nullptr, "GetAlbumContentsFileSizeForApplication"}, | ||
| 39 | {105, nullptr, "DeleteAlbumFileByAruidForDebug"}, | ||
| 40 | {110, nullptr, "LoadAlbumContentsFileScreenShotImageForApplication"}, | ||
| 41 | {120, nullptr, "LoadAlbumContentsFileThumbnailImageForApplication"}, | ||
| 42 | {130, nullptr, "PrecheckToCreateContentsForApplication"}, | ||
| 43 | {140, nullptr, "GetAlbumFileList1AafeAruidDeprecated"}, | ||
| 44 | {141, nullptr, "GetAlbumFileList2AafeUidAruidDeprecated"}, | ||
| 45 | {142, nullptr, "GetAlbumFileList3AaeAruid"}, | ||
| 46 | {143, nullptr, "GetAlbumFileList4AaeUidAruid"}, | ||
| 47 | {60002, nullptr, "OpenAccessorSessionForApplication"}, | ||
| 48 | }; | ||
| 49 | // clang-format on | ||
| 50 | |||
| 51 | RegisterHandlers(functions); | ||
| 52 | } | ||
| 53 | |||
| 54 | CAPS_U::~CAPS_U() = default; | ||
| 55 | |||
| 56 | void CAPS_U::GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx) { | ||
| 57 | // Takes a type-0x6 output buffer containing an array of ApplicationAlbumFileEntry, a PID, an | ||
| 58 | // u8 ContentType, two s64s, and an u64 AppletResourceUserId. Returns an output u64 for total | ||
| 59 | // output entries (which is copied to a s32 by official SW). | ||
| 60 | IPC::RequestParser rp{ctx}; | ||
| 61 | [[maybe_unused]] const auto application_album_file_entries = rp.PopRaw<std::array<u8, 0x30>>(); | ||
| 62 | const auto pid = rp.Pop<s32>(); | ||
| 63 | const auto content_type = rp.PopRaw<ContentType>(); | ||
| 64 | [[maybe_unused]] const auto start_datetime = rp.PopRaw<AlbumFileDateTime>(); | ||
| 65 | [[maybe_unused]] const auto end_datetime = rp.PopRaw<AlbumFileDateTime>(); | ||
| 66 | const auto applet_resource_user_id = rp.Pop<u64>(); | ||
| 67 | LOG_WARNING(Service_Capture, | ||
| 68 | "(STUBBED) called. pid={}, content_type={}, applet_resource_user_id={}", pid, | ||
| 69 | content_type, applet_resource_user_id); | ||
| 70 | |||
| 71 | IPC::ResponseBuilder rb{ctx, 3}; | ||
| 72 | rb.Push(RESULT_SUCCESS); | ||
| 73 | rb.Push<s32>(0); | ||
| 74 | } | ||
| 75 | |||
| 76 | } // namespace Service::Capture | ||
diff --git a/src/core/hle/service/caps/caps_u.h b/src/core/hle/service/caps/caps_u.h new file mode 100644 index 000000000..e6e0716ff --- /dev/null +++ b/src/core/hle/service/caps/caps_u.h | |||
| @@ -0,0 +1,24 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include "core/hle/service/service.h" | ||
| 8 | |||
| 9 | namespace Kernel { | ||
| 10 | class HLERequestContext; | ||
| 11 | } | ||
| 12 | |||
| 13 | namespace Service::Capture { | ||
| 14 | |||
| 15 | class CAPS_U final : public ServiceFramework<CAPS_U> { | ||
| 16 | public: | ||
| 17 | explicit CAPS_U(); | ||
| 18 | ~CAPS_U() override; | ||
| 19 | |||
| 20 | private: | ||
| 21 | void GetAlbumContentsFileListForApplication(Kernel::HLERequestContext& ctx); | ||
| 22 | }; | ||
| 23 | |||
| 24 | } // namespace Service::Capture | ||
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h index 49dc5abe0..930b605af 100644 --- a/src/video_core/engines/shader_bytecode.h +++ b/src/video_core/engines/shader_bytecode.h | |||
| @@ -231,18 +231,6 @@ enum class AtomicOp : u64 { | |||
| 231 | Or = 6, | 231 | Or = 6, |
| 232 | Xor = 7, | 232 | Xor = 7, |
| 233 | Exch = 8, | 233 | Exch = 8, |
| 234 | }; | ||
| 235 | |||
| 236 | enum class GlobalAtomicOp : u64 { | ||
| 237 | Add = 0, | ||
| 238 | Min = 1, | ||
| 239 | Max = 2, | ||
| 240 | Inc = 3, | ||
| 241 | Dec = 4, | ||
| 242 | And = 5, | ||
| 243 | Or = 6, | ||
| 244 | Xor = 7, | ||
| 245 | Exch = 8, | ||
| 246 | SafeAdd = 10, | 234 | SafeAdd = 10, |
| 247 | }; | 235 | }; |
| 248 | 236 | ||
| @@ -1001,7 +989,7 @@ union Instruction { | |||
| 1001 | } stg; | 989 | } stg; |
| 1002 | 990 | ||
| 1003 | union { | 991 | union { |
| 1004 | BitField<52, 4, GlobalAtomicOp> operation; | 992 | BitField<52, 4, AtomicOp> operation; |
| 1005 | BitField<49, 3, GlobalAtomicType> type; | 993 | BitField<49, 3, GlobalAtomicType> type; |
| 1006 | BitField<28, 20, s64> offset; | 994 | BitField<28, 20, s64> offset; |
| 1007 | } atom; | 995 | } atom; |
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp index 8aa4a7ac9..c7d24cf14 100644 --- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp +++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp | |||
| @@ -2114,6 +2114,10 @@ private: | |||
| 2114 | 2114 | ||
| 2115 | template <const std::string_view& opname, Type type> | 2115 | template <const std::string_view& opname, Type type> |
| 2116 | Expression Atomic(Operation operation) { | 2116 | Expression Atomic(Operation operation) { |
| 2117 | if ((opname == Func::Min || opname == Func::Max) && type == Type::Int) { | ||
| 2118 | UNIMPLEMENTED_MSG("Unimplemented Min & Max for atomic operations"); | ||
| 2119 | return {}; | ||
| 2120 | } | ||
| 2117 | return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), | 2121 | return {fmt::format("atomic{}({}, {})", opname, Visit(operation[0]).GetCode(), |
| 2118 | Visit(operation[1]).As(type)), | 2122 | Visit(operation[1]).As(type)), |
| 2119 | type}; | 2123 | type}; |
| @@ -2307,6 +2311,8 @@ private: | |||
| 2307 | ~Func() = delete; | 2311 | ~Func() = delete; |
| 2308 | 2312 | ||
| 2309 | static constexpr std::string_view Add = "Add"; | 2313 | static constexpr std::string_view Add = "Add"; |
| 2314 | static constexpr std::string_view Min = "Min"; | ||
| 2315 | static constexpr std::string_view Max = "Max"; | ||
| 2310 | static constexpr std::string_view And = "And"; | 2316 | static constexpr std::string_view And = "And"; |
| 2311 | static constexpr std::string_view Or = "Or"; | 2317 | static constexpr std::string_view Or = "Or"; |
| 2312 | static constexpr std::string_view Xor = "Xor"; | 2318 | static constexpr std::string_view Xor = "Xor"; |
| @@ -2457,7 +2463,21 @@ private: | |||
| 2457 | &GLSLDecompiler::AtomicImage<Func::Xor>, | 2463 | &GLSLDecompiler::AtomicImage<Func::Xor>, |
| 2458 | &GLSLDecompiler::AtomicImage<Func::Exchange>, | 2464 | &GLSLDecompiler::AtomicImage<Func::Exchange>, |
| 2459 | 2465 | ||
| 2466 | &GLSLDecompiler::Atomic<Func::Exchange, Type::Uint>, | ||
| 2460 | &GLSLDecompiler::Atomic<Func::Add, Type::Uint>, | 2467 | &GLSLDecompiler::Atomic<Func::Add, Type::Uint>, |
| 2468 | &GLSLDecompiler::Atomic<Func::Min, Type::Uint>, | ||
| 2469 | &GLSLDecompiler::Atomic<Func::Max, Type::Uint>, | ||
| 2470 | &GLSLDecompiler::Atomic<Func::And, Type::Uint>, | ||
| 2471 | &GLSLDecompiler::Atomic<Func::Or, Type::Uint>, | ||
| 2472 | &GLSLDecompiler::Atomic<Func::Xor, Type::Uint>, | ||
| 2473 | |||
| 2474 | &GLSLDecompiler::Atomic<Func::Exchange, Type::Int>, | ||
| 2475 | &GLSLDecompiler::Atomic<Func::Add, Type::Int>, | ||
| 2476 | &GLSLDecompiler::Atomic<Func::Min, Type::Int>, | ||
| 2477 | &GLSLDecompiler::Atomic<Func::Max, Type::Int>, | ||
| 2478 | &GLSLDecompiler::Atomic<Func::And, Type::Int>, | ||
| 2479 | &GLSLDecompiler::Atomic<Func::Or, Type::Int>, | ||
| 2480 | &GLSLDecompiler::Atomic<Func::Xor, Type::Int>, | ||
| 2461 | 2481 | ||
| 2462 | &GLSLDecompiler::Branch, | 2482 | &GLSLDecompiler::Branch, |
| 2463 | &GLSLDecompiler::BranchIndirect, | 2483 | &GLSLDecompiler::BranchIndirect, |
diff --git a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp index 51ecb5567..d67f08cf9 100644 --- a/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp +++ b/src/video_core/renderer_vulkan/vk_shader_decompiler.cpp | |||
| @@ -1941,7 +1941,11 @@ private: | |||
| 1941 | return {}; | 1941 | return {}; |
| 1942 | } | 1942 | } |
| 1943 | 1943 | ||
| 1944 | Expression AtomicAdd(Operation operation) { | 1944 | template <Id (Module::*func)(Id, Id, Id, Id, Id), Type result_type, |
| 1945 | Type value_type = result_type> | ||
| 1946 | Expression Atomic(Operation operation) { | ||
| 1947 | const Id type_def = GetTypeDefinition(result_type); | ||
| 1948 | |||
| 1945 | Id pointer; | 1949 | Id pointer; |
| 1946 | if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { | 1950 | if (const auto smem = std::get_if<SmemNode>(&*operation[0])) { |
| 1947 | pointer = GetSharedMemoryPointer(*smem); | 1951 | pointer = GetSharedMemoryPointer(*smem); |
| @@ -1949,14 +1953,15 @@ private: | |||
| 1949 | pointer = GetGlobalMemoryPointer(*gmem); | 1953 | pointer = GetGlobalMemoryPointer(*gmem); |
| 1950 | } else { | 1954 | } else { |
| 1951 | UNREACHABLE(); | 1955 | UNREACHABLE(); |
| 1952 | return {Constant(t_uint, 0), Type::Uint}; | 1956 | return {Constant(type_def, 0), result_type}; |
| 1953 | } | 1957 | } |
| 1954 | 1958 | ||
| 1959 | const Id value = As(Visit(operation[1]), value_type); | ||
| 1960 | |||
| 1955 | const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); | 1961 | const Id scope = Constant(t_uint, static_cast<u32>(spv::Scope::Device)); |
| 1956 | const Id semantics = Constant(t_uint, 0U); | 1962 | const Id semantics = Constant(type_def, 0); |
| 1957 | 1963 | ||
| 1958 | const Id value = AsUint(Visit(operation[1])); | 1964 | return {(this->*func)(type_def, pointer, scope, semantics, value), result_type}; |
| 1959 | return {OpAtomicIAdd(t_uint, pointer, scope, semantics, value), Type::Uint}; | ||
| 1960 | } | 1965 | } |
| 1961 | 1966 | ||
| 1962 | Expression Branch(Operation operation) { | 1967 | Expression Branch(Operation operation) { |
| @@ -2545,7 +2550,21 @@ private: | |||
| 2545 | &SPIRVDecompiler::AtomicImageXor, | 2550 | &SPIRVDecompiler::AtomicImageXor, |
| 2546 | &SPIRVDecompiler::AtomicImageExchange, | 2551 | &SPIRVDecompiler::AtomicImageExchange, |
| 2547 | 2552 | ||
| 2548 | &SPIRVDecompiler::AtomicAdd, | 2553 | &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Uint>, |
| 2554 | &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Uint>, | ||
| 2555 | &SPIRVDecompiler::Atomic<&Module::OpAtomicUMin, Type::Uint>, | ||
| 2556 | &SPIRVDecompiler::Atomic<&Module::OpAtomicUMax, Type::Uint>, | ||
| 2557 | &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Uint>, | ||
| 2558 | &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Uint>, | ||
| 2559 | &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Uint>, | ||
| 2560 | |||
| 2561 | &SPIRVDecompiler::Atomic<&Module::OpAtomicExchange, Type::Int>, | ||
| 2562 | &SPIRVDecompiler::Atomic<&Module::OpAtomicIAdd, Type::Int>, | ||
| 2563 | &SPIRVDecompiler::Atomic<&Module::OpAtomicSMin, Type::Int>, | ||
| 2564 | &SPIRVDecompiler::Atomic<&Module::OpAtomicSMax, Type::Int>, | ||
| 2565 | &SPIRVDecompiler::Atomic<&Module::OpAtomicAnd, Type::Int>, | ||
| 2566 | &SPIRVDecompiler::Atomic<&Module::OpAtomicOr, Type::Int>, | ||
| 2567 | &SPIRVDecompiler::Atomic<&Module::OpAtomicXor, Type::Int>, | ||
| 2549 | 2568 | ||
| 2550 | &SPIRVDecompiler::Branch, | 2569 | &SPIRVDecompiler::Branch, |
| 2551 | &SPIRVDecompiler::BranchIndirect, | 2570 | &SPIRVDecompiler::BranchIndirect, |
diff --git a/src/video_core/shader/decode/arithmetic_integer.cpp b/src/video_core/shader/decode/arithmetic_integer.cpp index 2fe787d6f..0f4c3103a 100644 --- a/src/video_core/shader/decode/arithmetic_integer.cpp +++ b/src/video_core/shader/decode/arithmetic_integer.cpp | |||
| @@ -235,34 +235,30 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) { | |||
| 235 | case OpCode::Id::LEA_IMM: | 235 | case OpCode::Id::LEA_IMM: |
| 236 | case OpCode::Id::LEA_RZ: | 236 | case OpCode::Id::LEA_RZ: |
| 237 | case OpCode::Id::LEA_HI: { | 237 | case OpCode::Id::LEA_HI: { |
| 238 | const auto [op_a, op_b, op_c] = [&]() -> std::tuple<Node, Node, Node> { | 238 | auto [op_a, op_b, op_c] = [&]() -> std::tuple<Node, Node, Node> { |
| 239 | switch (opcode->get().GetId()) { | 239 | switch (opcode->get().GetId()) { |
| 240 | case OpCode::Id::LEA_R2: { | 240 | case OpCode::Id::LEA_R2: { |
| 241 | return {GetRegister(instr.gpr20), GetRegister(instr.gpr39), | 241 | return {GetRegister(instr.gpr20), GetRegister(instr.gpr39), |
| 242 | Immediate(static_cast<u32>(instr.lea.r2.entry_a))}; | 242 | Immediate(static_cast<u32>(instr.lea.r2.entry_a))}; |
| 243 | } | 243 | } |
| 244 | |||
| 245 | case OpCode::Id::LEA_R1: { | 244 | case OpCode::Id::LEA_R1: { |
| 246 | const bool neg = instr.lea.r1.neg != 0; | 245 | const bool neg = instr.lea.r1.neg != 0; |
| 247 | return {GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), | 246 | return {GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), |
| 248 | GetRegister(instr.gpr20), | 247 | GetRegister(instr.gpr20), |
| 249 | Immediate(static_cast<u32>(instr.lea.r1.entry_a))}; | 248 | Immediate(static_cast<u32>(instr.lea.r1.entry_a))}; |
| 250 | } | 249 | } |
| 251 | |||
| 252 | case OpCode::Id::LEA_IMM: { | 250 | case OpCode::Id::LEA_IMM: { |
| 253 | const bool neg = instr.lea.imm.neg != 0; | 251 | const bool neg = instr.lea.imm.neg != 0; |
| 254 | return {Immediate(static_cast<u32>(instr.lea.imm.entry_a)), | 252 | return {Immediate(static_cast<u32>(instr.lea.imm.entry_a)), |
| 255 | GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), | 253 | GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), |
| 256 | Immediate(static_cast<u32>(instr.lea.imm.entry_b))}; | 254 | Immediate(static_cast<u32>(instr.lea.imm.entry_b))}; |
| 257 | } | 255 | } |
| 258 | |||
| 259 | case OpCode::Id::LEA_RZ: { | 256 | case OpCode::Id::LEA_RZ: { |
| 260 | const bool neg = instr.lea.rz.neg != 0; | 257 | const bool neg = instr.lea.rz.neg != 0; |
| 261 | return {GetConstBuffer(instr.lea.rz.cb_index, instr.lea.rz.cb_offset), | 258 | return {GetConstBuffer(instr.lea.rz.cb_index, instr.lea.rz.cb_offset), |
| 262 | GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), | 259 | GetOperandAbsNegInteger(GetRegister(instr.gpr8), false, neg, true), |
| 263 | Immediate(static_cast<u32>(instr.lea.rz.entry_a))}; | 260 | Immediate(static_cast<u32>(instr.lea.rz.entry_a))}; |
| 264 | } | 261 | } |
| 265 | |||
| 266 | case OpCode::Id::LEA_HI: | 262 | case OpCode::Id::LEA_HI: |
| 267 | default: | 263 | default: |
| 268 | UNIMPLEMENTED_MSG("Unhandled LEA subinstruction: {}", opcode->get().GetName()); | 264 | UNIMPLEMENTED_MSG("Unhandled LEA subinstruction: {}", opcode->get().GetName()); |
| @@ -275,12 +271,9 @@ u32 ShaderIR::DecodeArithmeticInteger(NodeBlock& bb, u32 pc) { | |||
| 275 | UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex), | 271 | UNIMPLEMENTED_IF_MSG(instr.lea.pred48 != static_cast<u64>(Pred::UnusedIndex), |
| 276 | "Unhandled LEA Predicate"); | 272 | "Unhandled LEA Predicate"); |
| 277 | 273 | ||
| 278 | const Node shifted_c = | 274 | Node value = Operation(OperationCode::ILogicalShiftLeft, std::move(op_a), std::move(op_c)); |
| 279 | Operation(OperationCode::ILogicalShiftLeft, NO_PRECISE, Immediate(1), op_c); | 275 | value = Operation(OperationCode::IAdd, std::move(op_b), std::move(value)); |
| 280 | const Node mul_bc = Operation(OperationCode::IMul, NO_PRECISE, op_b, shifted_c); | 276 | SetRegister(bb, instr.gpr0, std::move(value)); |
| 281 | const Node value = Operation(OperationCode::IAdd, NO_PRECISE, op_a, mul_bc); | ||
| 282 | |||
| 283 | SetRegister(bb, instr.gpr0, value); | ||
| 284 | 277 | ||
| 285 | break; | 278 | break; |
| 286 | } | 279 | } |
diff --git a/src/video_core/shader/decode/conversion.cpp b/src/video_core/shader/decode/conversion.cpp index 6ead42070..c72690b2b 100644 --- a/src/video_core/shader/decode/conversion.cpp +++ b/src/video_core/shader/decode/conversion.cpp | |||
| @@ -138,18 +138,23 @@ u32 ShaderIR::DecodeConversion(NodeBlock& bb, u32 pc) { | |||
| 138 | 138 | ||
| 139 | value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); | 139 | value = GetOperandAbsNegFloat(value, instr.conversion.abs_a, instr.conversion.negate_a); |
| 140 | 140 | ||
| 141 | value = [&]() { | 141 | value = [&] { |
| 142 | if (instr.conversion.src_size != instr.conversion.dst_size) { | ||
| 143 | // Rounding operations only matter when the source and destination conversion size | ||
| 144 | // is the same. | ||
| 145 | return value; | ||
| 146 | } | ||
| 142 | switch (instr.conversion.f2f.GetRoundingMode()) { | 147 | switch (instr.conversion.f2f.GetRoundingMode()) { |
| 143 | case Tegra::Shader::F2fRoundingOp::None: | 148 | case Tegra::Shader::F2fRoundingOp::None: |
| 144 | return value; | 149 | return value; |
| 145 | case Tegra::Shader::F2fRoundingOp::Round: | 150 | case Tegra::Shader::F2fRoundingOp::Round: |
| 146 | return Operation(OperationCode::FRoundEven, PRECISE, value); | 151 | return Operation(OperationCode::FRoundEven, value); |
| 147 | case Tegra::Shader::F2fRoundingOp::Floor: | 152 | case Tegra::Shader::F2fRoundingOp::Floor: |
| 148 | return Operation(OperationCode::FFloor, PRECISE, value); | 153 | return Operation(OperationCode::FFloor, value); |
| 149 | case Tegra::Shader::F2fRoundingOp::Ceil: | 154 | case Tegra::Shader::F2fRoundingOp::Ceil: |
| 150 | return Operation(OperationCode::FCeil, PRECISE, value); | 155 | return Operation(OperationCode::FCeil, value); |
| 151 | case Tegra::Shader::F2fRoundingOp::Trunc: | 156 | case Tegra::Shader::F2fRoundingOp::Trunc: |
| 152 | return Operation(OperationCode::FTrunc, PRECISE, value); | 157 | return Operation(OperationCode::FTrunc, value); |
| 153 | default: | 158 | default: |
| 154 | UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}", | 159 | UNIMPLEMENTED_MSG("Unimplemented F2F rounding mode {}", |
| 155 | static_cast<u32>(instr.conversion.f2f.rounding.Value())); | 160 | static_cast<u32>(instr.conversion.f2f.rounding.Value())); |
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp index b5fbc4d58..28a49addd 100644 --- a/src/video_core/shader/decode/memory.cpp +++ b/src/video_core/shader/decode/memory.cpp | |||
| @@ -19,7 +19,6 @@ namespace VideoCommon::Shader { | |||
| 19 | using Tegra::Shader::AtomicOp; | 19 | using Tegra::Shader::AtomicOp; |
| 20 | using Tegra::Shader::AtomicType; | 20 | using Tegra::Shader::AtomicType; |
| 21 | using Tegra::Shader::Attribute; | 21 | using Tegra::Shader::Attribute; |
| 22 | using Tegra::Shader::GlobalAtomicOp; | ||
| 23 | using Tegra::Shader::GlobalAtomicType; | 22 | using Tegra::Shader::GlobalAtomicType; |
| 24 | using Tegra::Shader::Instruction; | 23 | using Tegra::Shader::Instruction; |
| 25 | using Tegra::Shader::OpCode; | 24 | using Tegra::Shader::OpCode; |
| @@ -28,6 +27,28 @@ using Tegra::Shader::StoreType; | |||
| 28 | 27 | ||
| 29 | namespace { | 28 | namespace { |
| 30 | 29 | ||
| 30 | Node GetAtomOperation(AtomicOp op, bool is_signed, Node memory, Node data) { | ||
| 31 | const OperationCode operation_code = [op] { | ||
| 32 | switch (op) { | ||
| 33 | case AtomicOp::Add: | ||
| 34 | return OperationCode::AtomicIAdd; | ||
| 35 | case AtomicOp::Min: | ||
| 36 | return OperationCode::AtomicIMin; | ||
| 37 | case AtomicOp::Max: | ||
| 38 | return OperationCode::AtomicIMax; | ||
| 39 | case AtomicOp::And: | ||
| 40 | return OperationCode::AtomicIAnd; | ||
| 41 | case AtomicOp::Or: | ||
| 42 | return OperationCode::AtomicIOr; | ||
| 43 | case AtomicOp::Xor: | ||
| 44 | return OperationCode::AtomicIXor; | ||
| 45 | case AtomicOp::Exch: | ||
| 46 | return OperationCode::AtomicIExchange; | ||
| 47 | } | ||
| 48 | }(); | ||
| 49 | return SignedOperation(operation_code, is_signed, std::move(memory), std::move(data)); | ||
| 50 | } | ||
| 51 | |||
| 31 | bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { | 52 | bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { |
| 32 | return uniform_type == Tegra::Shader::UniformType::UnsignedByte || | 53 | return uniform_type == Tegra::Shader::UniformType::UnsignedByte || |
| 33 | uniform_type == Tegra::Shader::UniformType::UnsignedShort; | 54 | uniform_type == Tegra::Shader::UniformType::UnsignedShort; |
| @@ -363,10 +384,13 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 363 | break; | 384 | break; |
| 364 | } | 385 | } |
| 365 | case OpCode::Id::ATOM: { | 386 | case OpCode::Id::ATOM: { |
| 366 | UNIMPLEMENTED_IF_MSG(instr.atom.operation != GlobalAtomicOp::Add, "operation={}", | 387 | UNIMPLEMENTED_IF_MSG(instr.atom.operation == AtomicOp::Inc || |
| 367 | static_cast<int>(instr.atom.operation.Value())); | 388 | instr.atom.operation == AtomicOp::Dec || |
| 368 | UNIMPLEMENTED_IF_MSG(instr.atom.type != GlobalAtomicType::S32, "type={}", | 389 | instr.atom.operation == AtomicOp::SafeAdd, |
| 369 | static_cast<int>(instr.atom.type.Value())); | 390 | "operation={}", static_cast<int>(instr.atom.operation.Value())); |
| 391 | UNIMPLEMENTED_IF_MSG(instr.atom.type == GlobalAtomicType::S64 || | ||
| 392 | instr.atom.type == GlobalAtomicType::U64, | ||
| 393 | "type={}", static_cast<int>(instr.atom.type.Value())); | ||
| 370 | 394 | ||
| 371 | const auto [real_address, base_address, descriptor] = | 395 | const auto [real_address, base_address, descriptor] = |
| 372 | TrackGlobalMemory(bb, instr, true, true); | 396 | TrackGlobalMemory(bb, instr, true, true); |
| @@ -375,25 +399,29 @@ u32 ShaderIR::DecodeMemory(NodeBlock& bb, u32 pc) { | |||
| 375 | break; | 399 | break; |
| 376 | } | 400 | } |
| 377 | 401 | ||
| 402 | const bool is_signed = | ||
| 403 | instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; | ||
| 378 | Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); | 404 | Node gmem = MakeNode<GmemNode>(real_address, base_address, descriptor); |
| 379 | Node value = Operation(OperationCode::AtomicAdd, std::move(gmem), GetRegister(instr.gpr20)); | 405 | Node value = GetAtomOperation(static_cast<AtomicOp>(instr.atom.operation), is_signed, gmem, |
| 406 | GetRegister(instr.gpr20)); | ||
| 380 | SetRegister(bb, instr.gpr0, std::move(value)); | 407 | SetRegister(bb, instr.gpr0, std::move(value)); |
| 381 | break; | 408 | break; |
| 382 | } | 409 | } |
| 383 | case OpCode::Id::ATOMS: { | 410 | case OpCode::Id::ATOMS: { |
| 384 | UNIMPLEMENTED_IF_MSG(instr.atoms.operation != AtomicOp::Add, "operation={}", | 411 | UNIMPLEMENTED_IF_MSG(instr.atoms.operation == AtomicOp::Inc || |
| 385 | static_cast<int>(instr.atoms.operation.Value())); | 412 | instr.atoms.operation == AtomicOp::Dec, |
| 386 | UNIMPLEMENTED_IF_MSG(instr.atoms.type != AtomicType::U32, "type={}", | 413 | "operation={}", static_cast<int>(instr.atoms.operation.Value())); |
| 387 | static_cast<int>(instr.atoms.type.Value())); | 414 | UNIMPLEMENTED_IF_MSG(instr.atoms.type == AtomicType::S64 || |
| 388 | 415 | instr.atoms.type == AtomicType::U64, | |
| 416 | "type={}", static_cast<int>(instr.atoms.type.Value())); | ||
| 417 | const bool is_signed = | ||
| 418 | instr.atoms.type == AtomicType::S32 || instr.atoms.type == AtomicType::S64; | ||
| 389 | const s32 offset = instr.atoms.GetImmediateOffset(); | 419 | const s32 offset = instr.atoms.GetImmediateOffset(); |
| 390 | Node address = GetRegister(instr.gpr8); | 420 | Node address = GetRegister(instr.gpr8); |
| 391 | address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); | 421 | address = Operation(OperationCode::IAdd, std::move(address), Immediate(offset)); |
| 392 | 422 | Node value = | |
| 393 | Node memory = GetSharedMemory(std::move(address)); | 423 | GetAtomOperation(static_cast<AtomicOp>(instr.atoms.operation), is_signed, |
| 394 | Node data = GetRegister(instr.gpr20); | 424 | GetSharedMemory(std::move(address)), GetRegister(instr.gpr20)); |
| 395 | |||
| 396 | Node value = Operation(OperationCode::AtomicAdd, std::move(memory), std::move(data)); | ||
| 397 | SetRegister(bb, instr.gpr0, std::move(value)); | 425 | SetRegister(bb, instr.gpr0, std::move(value)); |
| 398 | break; | 426 | break; |
| 399 | } | 427 | } |
diff --git a/src/video_core/shader/node.h b/src/video_core/shader/node.h index a1828546e..5fcc9da60 100644 --- a/src/video_core/shader/node.h +++ b/src/video_core/shader/node.h | |||
| @@ -162,7 +162,21 @@ enum class OperationCode { | |||
| 162 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void | 162 | AtomicImageXor, /// (MetaImage, int[N] coords) -> void |
| 163 | AtomicImageExchange, /// (MetaImage, int[N] coords) -> void | 163 | AtomicImageExchange, /// (MetaImage, int[N] coords) -> void |
| 164 | 164 | ||
| 165 | AtomicAdd, /// (memory, {u}int) -> {u}int | 165 | AtomicUExchange, /// (memory, uint) -> uint |
| 166 | AtomicUAdd, /// (memory, uint) -> uint | ||
| 167 | AtomicUMin, /// (memory, uint) -> uint | ||
| 168 | AtomicUMax, /// (memory, uint) -> uint | ||
| 169 | AtomicUAnd, /// (memory, uint) -> uint | ||
| 170 | AtomicUOr, /// (memory, uint) -> uint | ||
| 171 | AtomicUXor, /// (memory, uint) -> uint | ||
| 172 | |||
| 173 | AtomicIExchange, /// (memory, int) -> int | ||
| 174 | AtomicIAdd, /// (memory, int) -> int | ||
| 175 | AtomicIMin, /// (memory, int) -> int | ||
| 176 | AtomicIMax, /// (memory, int) -> int | ||
| 177 | AtomicIAnd, /// (memory, int) -> int | ||
| 178 | AtomicIOr, /// (memory, int) -> int | ||
| 179 | AtomicIXor, /// (memory, int) -> int | ||
| 166 | 180 | ||
| 167 | Branch, /// (uint branch_target) -> void | 181 | Branch, /// (uint branch_target) -> void |
| 168 | BranchIndirect, /// (uint branch_target) -> void | 182 | BranchIndirect, /// (uint branch_target) -> void |
diff --git a/src/video_core/shader/node_helper.cpp b/src/video_core/shader/node_helper.cpp index 76c56abb5..7bf4ff387 100644 --- a/src/video_core/shader/node_helper.cpp +++ b/src/video_core/shader/node_helper.cpp | |||
| @@ -86,6 +86,20 @@ OperationCode SignedToUnsignedCode(OperationCode operation_code, bool is_signed) | |||
| 86 | return OperationCode::LogicalUNotEqual; | 86 | return OperationCode::LogicalUNotEqual; |
| 87 | case OperationCode::LogicalIGreaterEqual: | 87 | case OperationCode::LogicalIGreaterEqual: |
| 88 | return OperationCode::LogicalUGreaterEqual; | 88 | return OperationCode::LogicalUGreaterEqual; |
| 89 | case OperationCode::AtomicIExchange: | ||
| 90 | return OperationCode::AtomicUExchange; | ||
| 91 | case OperationCode::AtomicIAdd: | ||
| 92 | return OperationCode::AtomicUAdd; | ||
| 93 | case OperationCode::AtomicIMin: | ||
| 94 | return OperationCode::AtomicUMin; | ||
| 95 | case OperationCode::AtomicIMax: | ||
| 96 | return OperationCode::AtomicUMax; | ||
| 97 | case OperationCode::AtomicIAnd: | ||
| 98 | return OperationCode::AtomicUAnd; | ||
| 99 | case OperationCode::AtomicIOr: | ||
| 100 | return OperationCode::AtomicUOr; | ||
| 101 | case OperationCode::AtomicIXor: | ||
| 102 | return OperationCode::AtomicUXor; | ||
| 89 | case OperationCode::INegate: | 103 | case OperationCode::INegate: |
| 90 | UNREACHABLE_MSG("Can't negate an unsigned integer"); | 104 | UNREACHABLE_MSG("Can't negate an unsigned integer"); |
| 91 | return {}; | 105 | return {}; |