summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt12
-rw-r--r--src/core/hle/service/caps/caps.cpp158
-rw-r--r--src/core/hle/service/caps/caps.h71
-rw-r--r--src/core/hle/service/caps/caps_a.cpp78
-rw-r--r--src/core/hle/service/caps/caps_a.h21
-rw-r--r--src/core/hle/service/caps/caps_c.cpp75
-rw-r--r--src/core/hle/service/caps/caps_c.h21
-rw-r--r--src/core/hle/service/caps/caps_sc.cpp40
-rw-r--r--src/core/hle/service/caps/caps_sc.h21
-rw-r--r--src/core/hle/service/caps/caps_ss.cpp26
-rw-r--r--src/core/hle/service/caps/caps_ss.h21
-rw-r--r--src/core/hle/service/caps/caps_su.cpp22
-rw-r--r--src/core/hle/service/caps/caps_su.h21
-rw-r--r--src/core/hle/service/caps/caps_u.cpp76
-rw-r--r--src/core/hle/service/caps/caps_u.h24
-rw-r--r--src/video_core/engines/shader_bytecode.h14
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp20
-rw-r--r--src/video_core/renderer_vulkan/vk_shader_decompiler.cpp31
-rw-r--r--src/video_core/shader/decode/arithmetic_integer.cpp15
-rw-r--r--src/video_core/shader/decode/conversion.cpp15
-rw-r--r--src/video_core/shader/decode/memory.cpp60
-rw-r--r--src/video_core/shader/node.h16
-rw-r--r--src/video_core/shader/node_helper.cpp14
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
11namespace Service::Capture { 14namespace Service::Capture {
12 15
13class CAPS_A final : public ServiceFramework<CAPS_A> {
14public:
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
60class CAPS_C final : public ServiceFramework<CAPS_C> {
61public:
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
83class CAPS_SC final : public ServiceFramework<CAPS_SC> {
84public:
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
105class CAPS_SS final : public ServiceFramework<CAPS_SS> {
106public:
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
121class CAPS_SU final : public ServiceFramework<CAPS_SU> {
122public:
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
135class CAPS_U final : public ServiceFramework<CAPS_U> {
136public:
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
160void InstallInterfaces(SM::ServiceManager& sm) { 16void 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
7namespace Service::SM { 9namespace Service::SM {
8class ServiceManager; 10class ServiceManager;
9} 11}
10 12
11namespace Service::Capture { 13namespace Service::Capture {
12 14
15enum AlbumImageOrientation {
16 Orientation0 = 0,
17 Orientation1 = 1,
18 Orientation2 = 2,
19 Orientation3 = 3,
20};
21
22enum AlbumReportOption {
23 Disable = 0,
24 Enable = 1,
25};
26
27enum ContentType : u8 {
28 Screenshot = 0,
29 Movie = 1,
30 ExtraMovie = 3,
31};
32
33enum AlbumStorage : u8 {
34 NAND = 0,
35 SD = 1,
36};
37
38struct AlbumFileDateTime {
39 u16 year;
40 u8 month;
41 u8 day;
42 u8 hour;
43 u8 minute;
44 u8 second;
45 u8 uid;
46};
47
48struct AlbumEntry {
49 u64 size;
50 u64 application_id;
51 AlbumFileDateTime datetime;
52 AlbumStorage storage;
53 ContentType content;
54 u8 padding[6];
55};
56
57struct 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
67struct 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
77struct ApplicationAlbumFileEntry {
78 ApplicationAlbumEntry entry;
79 AlbumFileDateTime datetime;
80 u64 unknown;
81};
82
83/// Registers all Capture services with the specified service manager.
13void InstallInterfaces(SM::ServiceManager& sm); 84void 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
7namespace Service::Capture {
8
9class IAlbumAccessorSession final : public ServiceFramework<IAlbumAccessorSession> {
10public:
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
29CAPS_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
76CAPS_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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_A final : public ServiceFramework<CAPS_A> {
16public:
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
7namespace Service::Capture {
8
9class IAlbumControlSession final : public ServiceFramework<IAlbumControlSession> {
10public:
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
45CAPS_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
73CAPS_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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_C final : public ServiceFramework<CAPS_C> {
16public:
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
7namespace Service::Capture {
8
9CAPS_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
38CAPS_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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_SC final : public ServiceFramework<CAPS_SC> {
16public:
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
7namespace Service::Capture {
8
9CAPS_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
24CAPS_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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_SS final : public ServiceFramework<CAPS_SS> {
16public:
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
7namespace Service::Capture {
8
9CAPS_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
20CAPS_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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_SU final : public ServiceFramework<CAPS_SU> {
16public:
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
10namespace Service::Capture {
11
12class IAlbumAccessorApplicationSession final
13 : public ServiceFramework<IAlbumAccessorApplicationSession> {
14public:
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
31CAPS_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
54CAPS_U::~CAPS_U() = default;
55
56void 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
9namespace Kernel {
10class HLERequestContext;
11}
12
13namespace Service::Capture {
14
15class CAPS_U final : public ServiceFramework<CAPS_U> {
16public:
17 explicit CAPS_U();
18 ~CAPS_U() override;
19
20private:
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
236enum 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 {
19using Tegra::Shader::AtomicOp; 19using Tegra::Shader::AtomicOp;
20using Tegra::Shader::AtomicType; 20using Tegra::Shader::AtomicType;
21using Tegra::Shader::Attribute; 21using Tegra::Shader::Attribute;
22using Tegra::Shader::GlobalAtomicOp;
23using Tegra::Shader::GlobalAtomicType; 22using Tegra::Shader::GlobalAtomicType;
24using Tegra::Shader::Instruction; 23using Tegra::Shader::Instruction;
25using Tegra::Shader::OpCode; 24using Tegra::Shader::OpCode;
@@ -28,6 +27,28 @@ using Tegra::Shader::StoreType;
28 27
29namespace { 28namespace {
30 29
30Node 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
31bool IsUnaligned(Tegra::Shader::UniformType uniform_type) { 52bool 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 {};