summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hle/kernel/kernel.cpp42
-rw-r--r--src/core/hle/kernel/kernel.h11
-rw-r--r--src/core/hle/kernel/object.cpp1
-rw-r--r--src/core/hle/kernel/object.h1
-rw-r--r--src/core/hle/kernel/readable_event.cpp4
-rw-r--r--src/core/hle/kernel/readable_event.h2
-rw-r--r--src/core/hle/kernel/timer.cpp88
-rw-r--r--src/core/hle/kernel/timer.h90
-rw-r--r--src/core/hle/kernel/wait_object.h6
-rw-r--r--src/core/hle/service/am/applet_ae.cpp3
-rw-r--r--src/core/hle/service/audio/audin_u.cpp13
-rw-r--r--src/core/hle/service/audio/audrec_u.cpp6
-rw-r--r--src/core/hle/service/audio/audren_u.cpp10
-rw-r--r--src/core/hle/service/audio/audren_u.h2
-rw-r--r--src/core/hle/service/btdrv/btdrv.cpp147
-rw-r--r--src/core/hle/service/btm/btm.cpp152
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.cpp32
-rw-r--r--src/core/hle/service/filesystem/fsp_srv.h10
-rw-r--r--src/core/hle/service/ncm/ncm.cpp8
-rw-r--r--src/core/hle/service/ns/ns.cpp34
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.cpp66
-rw-r--r--src/core/hle/service/nvflinger/nvflinger.h35
-rw-r--r--src/core/hle/service/psc/psc.cpp17
-rw-r--r--src/core/hle/service/vi/vi.cpp10
-rw-r--r--src/video_core/CMakeLists.txt1
-rw-r--r--src/video_core/dma_pusher.h2
-rw-r--r--src/video_core/engines/shader_bytecode.h8
-rw-r--r--src/video_core/gpu.cpp183
-rw-r--r--src/video_core/gpu.h71
-rw-r--r--src/video_core/rasterizer_interface.h5
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.cpp70
-rw-r--r--src/video_core/renderer_opengl/gl_global_cache.h18
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.cpp121
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer.h30
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.cpp19
-rw-r--r--src/video_core/renderer_opengl/gl_rasterizer_cache.h55
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.cpp140
-rw-r--r--src/video_core/renderer_opengl/gl_shader_cache.h92
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.cpp53
-rw-r--r--src/video_core/renderer_opengl/gl_shader_decompiler.h36
-rw-r--r--src/video_core/renderer_opengl/gl_shader_gen.cpp13
-rw-r--r--src/video_core/shader/decode/memory.cpp49
-rw-r--r--src/video_core/shader/shader_ir.h38
-rw-r--r--src/video_core/shader/track.cpp76
-rw-r--r--src/video_core/surface.cpp18
-rw-r--r--src/video_core/surface.h5
-rw-r--r--src/yuzu/debugger/wait_tree.cpp20
-rw-r--r--src/yuzu/debugger/wait_tree.h10
49 files changed, 1205 insertions, 720 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 965c28787..f61bcd40d 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -140,8 +140,6 @@ add_library(core STATIC
140 hle/kernel/svc_wrap.h 140 hle/kernel/svc_wrap.h
141 hle/kernel/thread.cpp 141 hle/kernel/thread.cpp
142 hle/kernel/thread.h 142 hle/kernel/thread.h
143 hle/kernel/timer.cpp
144 hle/kernel/timer.h
145 hle/kernel/vm_manager.cpp 143 hle/kernel/vm_manager.cpp
146 hle/kernel/vm_manager.h 144 hle/kernel/vm_manager.h
147 hle/kernel/wait_object.cpp 145 hle/kernel/wait_object.cpp
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 67674cd47..7a524ce5a 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -18,7 +18,6 @@
18#include "core/hle/kernel/process.h" 18#include "core/hle/kernel/process.h"
19#include "core/hle/kernel/resource_limit.h" 19#include "core/hle/kernel/resource_limit.h"
20#include "core/hle/kernel/thread.h" 20#include "core/hle/kernel/thread.h"
21#include "core/hle/kernel/timer.h"
22#include "core/hle/lock.h" 21#include "core/hle/lock.h"
23#include "core/hle/result.h" 22#include "core/hle/result.h"
24 23
@@ -86,27 +85,12 @@ static void ThreadWakeupCallback(u64 thread_handle, [[maybe_unused]] int cycles_
86 } 85 }
87} 86}
88 87
89/// The timer callback event, called when a timer is fired
90static void TimerCallback(u64 timer_handle, int cycles_late) {
91 const auto proper_handle = static_cast<Handle>(timer_handle);
92 const auto& system = Core::System::GetInstance();
93 SharedPtr<Timer> timer = system.Kernel().RetrieveTimerFromCallbackHandleTable(proper_handle);
94
95 if (timer == nullptr) {
96 LOG_CRITICAL(Kernel, "Callback fired for invalid timer {:016X}", timer_handle);
97 return;
98 }
99
100 timer->Signal(cycles_late);
101}
102
103struct KernelCore::Impl { 88struct KernelCore::Impl {
104 void Initialize(KernelCore& kernel) { 89 void Initialize(KernelCore& kernel) {
105 Shutdown(); 90 Shutdown();
106 91
107 InitializeSystemResourceLimit(kernel); 92 InitializeSystemResourceLimit(kernel);
108 InitializeThreads(); 93 InitializeThreads();
109 InitializeTimers();
110 } 94 }
111 95
112 void Shutdown() { 96 void Shutdown() {
@@ -122,9 +106,6 @@ struct KernelCore::Impl {
122 thread_wakeup_callback_handle_table.Clear(); 106 thread_wakeup_callback_handle_table.Clear();
123 thread_wakeup_event_type = nullptr; 107 thread_wakeup_event_type = nullptr;
124 108
125 timer_callback_handle_table.Clear();
126 timer_callback_event_type = nullptr;
127
128 named_ports.clear(); 109 named_ports.clear();
129 } 110 }
130 111
@@ -146,11 +127,6 @@ struct KernelCore::Impl {
146 CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback); 127 CoreTiming::RegisterEvent("ThreadWakeupCallback", ThreadWakeupCallback);
147 } 128 }
148 129
149 void InitializeTimers() {
150 timer_callback_handle_table.Clear();
151 timer_callback_event_type = CoreTiming::RegisterEvent("TimerCallback", TimerCallback);
152 }
153
154 std::atomic<u32> next_object_id{0}; 130 std::atomic<u32> next_object_id{0};
155 std::atomic<u64> next_process_id{Process::ProcessIDMin}; 131 std::atomic<u64> next_process_id{Process::ProcessIDMin};
156 std::atomic<u64> next_thread_id{1}; 132 std::atomic<u64> next_thread_id{1};
@@ -161,12 +137,6 @@ struct KernelCore::Impl {
161 137
162 SharedPtr<ResourceLimit> system_resource_limit; 138 SharedPtr<ResourceLimit> system_resource_limit;
163 139
164 /// The event type of the generic timer callback event
165 CoreTiming::EventType* timer_callback_event_type = nullptr;
166 // TODO(yuriks): This can be removed if Timer objects are explicitly pooled in the future,
167 // allowing us to simply use a pool index or similar.
168 Kernel::HandleTable timer_callback_handle_table;
169
170 CoreTiming::EventType* thread_wakeup_event_type = nullptr; 140 CoreTiming::EventType* thread_wakeup_event_type = nullptr;
171 // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future, 141 // TODO(yuriks): This can be removed if Thread objects are explicitly pooled in the future,
172 // allowing us to simply use a pool index or similar. 142 // allowing us to simply use a pool index or similar.
@@ -198,10 +168,6 @@ SharedPtr<Thread> KernelCore::RetrieveThreadFromWakeupCallbackHandleTable(Handle
198 return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle); 168 return impl->thread_wakeup_callback_handle_table.Get<Thread>(handle);
199} 169}
200 170
201SharedPtr<Timer> KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const {
202 return impl->timer_callback_handle_table.Get<Timer>(handle);
203}
204
205void KernelCore::AppendNewProcess(SharedPtr<Process> process) { 171void KernelCore::AppendNewProcess(SharedPtr<Process> process) {
206 impl->process_list.push_back(std::move(process)); 172 impl->process_list.push_back(std::move(process));
207} 173}
@@ -247,18 +213,10 @@ u64 KernelCore::CreateNewProcessID() {
247 return impl->next_process_id++; 213 return impl->next_process_id++;
248} 214}
249 215
250ResultVal<Handle> KernelCore::CreateTimerCallbackHandle(const SharedPtr<Timer>& timer) {
251 return impl->timer_callback_handle_table.Create(timer);
252}
253
254CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const { 216CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const {
255 return impl->thread_wakeup_event_type; 217 return impl->thread_wakeup_event_type;
256} 218}
257 219
258CoreTiming::EventType* KernelCore::TimerCallbackEventType() const {
259 return impl->timer_callback_event_type;
260}
261
262Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { 220Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() {
263 return impl->thread_wakeup_callback_handle_table; 221 return impl->thread_wakeup_callback_handle_table;
264} 222}
diff --git a/src/core/hle/kernel/kernel.h b/src/core/hle/kernel/kernel.h
index 58c9d108b..c643a6401 100644
--- a/src/core/hle/kernel/kernel.h
+++ b/src/core/hle/kernel/kernel.h
@@ -22,7 +22,6 @@ class HandleTable;
22class Process; 22class Process;
23class ResourceLimit; 23class ResourceLimit;
24class Thread; 24class Thread;
25class Timer;
26 25
27/// Represents a single instance of the kernel. 26/// Represents a single instance of the kernel.
28class KernelCore { 27class KernelCore {
@@ -51,9 +50,6 @@ public:
51 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table. 50 /// Retrieves a shared pointer to a Thread instance within the thread wakeup handle table.
52 SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const; 51 SharedPtr<Thread> RetrieveThreadFromWakeupCallbackHandleTable(Handle handle) const;
53 52
54 /// Retrieves a shared pointer to a Timer instance within the timer callback handle table.
55 SharedPtr<Timer> RetrieveTimerFromCallbackHandleTable(Handle handle) const;
56
57 /// Adds the given shared pointer to an internal list of active processes. 53 /// Adds the given shared pointer to an internal list of active processes.
58 void AppendNewProcess(SharedPtr<Process> process); 54 void AppendNewProcess(SharedPtr<Process> process);
59 55
@@ -82,7 +78,6 @@ private:
82 friend class Object; 78 friend class Object;
83 friend class Process; 79 friend class Process;
84 friend class Thread; 80 friend class Thread;
85 friend class Timer;
86 81
87 /// Creates a new object ID, incrementing the internal object ID counter. 82 /// Creates a new object ID, incrementing the internal object ID counter.
88 u32 CreateNewObjectID(); 83 u32 CreateNewObjectID();
@@ -93,15 +88,9 @@ private:
93 /// Creates a new thread ID, incrementing the internal thread ID counter. 88 /// Creates a new thread ID, incrementing the internal thread ID counter.
94 u64 CreateNewThreadID(); 89 u64 CreateNewThreadID();
95 90
96 /// Creates a timer callback handle for the given timer.
97 ResultVal<Handle> CreateTimerCallbackHandle(const SharedPtr<Timer>& timer);
98
99 /// Retrieves the event type used for thread wakeup callbacks. 91 /// Retrieves the event type used for thread wakeup callbacks.
100 CoreTiming::EventType* ThreadWakeupCallbackEventType() const; 92 CoreTiming::EventType* ThreadWakeupCallbackEventType() const;
101 93
102 /// Retrieves the event type used for timer callbacks.
103 CoreTiming::EventType* TimerCallbackEventType() const;
104
105 /// Provides a reference to the thread wakeup callback handle table. 94 /// Provides a reference to the thread wakeup callback handle table.
106 Kernel::HandleTable& ThreadWakeupCallbackHandleTable(); 95 Kernel::HandleTable& ThreadWakeupCallbackHandleTable();
107 96
diff --git a/src/core/hle/kernel/object.cpp b/src/core/hle/kernel/object.cpp
index 806078638..8870463d0 100644
--- a/src/core/hle/kernel/object.cpp
+++ b/src/core/hle/kernel/object.cpp
@@ -16,7 +16,6 @@ bool Object::IsWaitable() const {
16 case HandleType::ReadableEvent: 16 case HandleType::ReadableEvent:
17 case HandleType::Thread: 17 case HandleType::Thread:
18 case HandleType::Process: 18 case HandleType::Process:
19 case HandleType::Timer:
20 case HandleType::ServerPort: 19 case HandleType::ServerPort:
21 case HandleType::ServerSession: 20 case HandleType::ServerSession:
22 return true; 21 return true;
diff --git a/src/core/hle/kernel/object.h b/src/core/hle/kernel/object.h
index 1541b6e3c..4c2505908 100644
--- a/src/core/hle/kernel/object.h
+++ b/src/core/hle/kernel/object.h
@@ -25,7 +25,6 @@ enum class HandleType : u32 {
25 Thread, 25 Thread,
26 Process, 26 Process,
27 AddressArbiter, 27 AddressArbiter,
28 Timer,
29 ResourceLimit, 28 ResourceLimit,
30 ClientPort, 29 ClientPort,
31 ServerPort, 30 ServerPort,
diff --git a/src/core/hle/kernel/readable_event.cpp b/src/core/hle/kernel/readable_event.cpp
index 6973e580c..0e5083f70 100644
--- a/src/core/hle/kernel/readable_event.cpp
+++ b/src/core/hle/kernel/readable_event.cpp
@@ -44,8 +44,4 @@ ResultCode ReadableEvent::Reset() {
44 return RESULT_SUCCESS; 44 return RESULT_SUCCESS;
45} 45}
46 46
47void ReadableEvent::WakeupAllWaitingThreads() {
48 WaitObject::WakeupAllWaitingThreads();
49}
50
51} // namespace Kernel 47} // namespace Kernel
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
index 80b3b0aba..77a9c362c 100644
--- a/src/core/hle/kernel/readable_event.h
+++ b/src/core/hle/kernel/readable_event.h
@@ -39,8 +39,6 @@ public:
39 bool ShouldWait(Thread* thread) const override; 39 bool ShouldWait(Thread* thread) const override;
40 void Acquire(Thread* thread) override; 40 void Acquire(Thread* thread) override;
41 41
42 void WakeupAllWaitingThreads() override;
43
44 /// Unconditionally clears the readable event's state. 42 /// Unconditionally clears the readable event's state.
45 void Clear(); 43 void Clear();
46 44
diff --git a/src/core/hle/kernel/timer.cpp b/src/core/hle/kernel/timer.cpp
deleted file mode 100644
index 2c4f50e2b..000000000
--- a/src/core/hle/kernel/timer.cpp
+++ /dev/null
@@ -1,88 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/assert.h"
6#include "common/logging/log.h"
7#include "core/core.h"
8#include "core/core_timing.h"
9#include "core/core_timing_util.h"
10#include "core/hle/kernel/handle_table.h"
11#include "core/hle/kernel/kernel.h"
12#include "core/hle/kernel/object.h"
13#include "core/hle/kernel/thread.h"
14#include "core/hle/kernel/timer.h"
15
16namespace Kernel {
17
18Timer::Timer(KernelCore& kernel) : WaitObject{kernel} {}
19Timer::~Timer() = default;
20
21SharedPtr<Timer> Timer::Create(KernelCore& kernel, ResetType reset_type, std::string name) {
22 SharedPtr<Timer> timer(new Timer(kernel));
23
24 timer->reset_type = reset_type;
25 timer->signaled = false;
26 timer->name = std::move(name);
27 timer->initial_delay = 0;
28 timer->interval_delay = 0;
29 timer->callback_handle = kernel.CreateTimerCallbackHandle(timer).Unwrap();
30
31 return timer;
32}
33
34bool Timer::ShouldWait(Thread* thread) const {
35 return !signaled;
36}
37
38void Timer::Acquire(Thread* thread) {
39 ASSERT_MSG(!ShouldWait(thread), "object unavailable!");
40
41 if (reset_type == ResetType::OneShot)
42 signaled = false;
43}
44
45void Timer::Set(s64 initial, s64 interval) {
46 // Ensure we get rid of any previous scheduled event
47 Cancel();
48
49 initial_delay = initial;
50 interval_delay = interval;
51
52 if (initial == 0) {
53 // Immediately invoke the callback
54 Signal(0);
55 } else {
56 CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(initial), kernel.TimerCallbackEventType(),
57 callback_handle);
58 }
59}
60
61void Timer::Cancel() {
62 CoreTiming::UnscheduleEvent(kernel.TimerCallbackEventType(), callback_handle);
63}
64
65void Timer::Clear() {
66 signaled = false;
67}
68
69void Timer::WakeupAllWaitingThreads() {
70 WaitObject::WakeupAllWaitingThreads();
71}
72
73void Timer::Signal(int cycles_late) {
74 LOG_TRACE(Kernel, "Timer {} fired", GetObjectId());
75
76 signaled = true;
77
78 // Resume all waiting threads
79 WakeupAllWaitingThreads();
80
81 if (interval_delay != 0) {
82 // Reschedule the timer with the interval delay
83 CoreTiming::ScheduleEvent(CoreTiming::nsToCycles(interval_delay) - cycles_late,
84 kernel.TimerCallbackEventType(), callback_handle);
85 }
86}
87
88} // namespace Kernel
diff --git a/src/core/hle/kernel/timer.h b/src/core/hle/kernel/timer.h
deleted file mode 100644
index 12915c1b1..000000000
--- a/src/core/hle/kernel/timer.h
+++ /dev/null
@@ -1,90 +0,0 @@
1// Copyright 2015 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include "common/common_types.h"
8#include "core/hle/kernel/object.h"
9#include "core/hle/kernel/wait_object.h"
10
11namespace Kernel {
12
13class KernelCore;
14
15class Timer final : public WaitObject {
16public:
17 /**
18 * Creates a timer
19 * @param kernel The kernel instance to create the timer callback handle for.
20 * @param reset_type ResetType describing how to create the timer
21 * @param name Optional name of timer
22 * @return The created Timer
23 */
24 static SharedPtr<Timer> Create(KernelCore& kernel, ResetType reset_type,
25 std::string name = "Unknown");
26
27 std::string GetTypeName() const override {
28 return "Timer";
29 }
30 std::string GetName() const override {
31 return name;
32 }
33
34 static const HandleType HANDLE_TYPE = HandleType::Timer;
35 HandleType GetHandleType() const override {
36 return HANDLE_TYPE;
37 }
38
39 ResetType GetResetType() const {
40 return reset_type;
41 }
42
43 u64 GetInitialDelay() const {
44 return initial_delay;
45 }
46
47 u64 GetIntervalDelay() const {
48 return interval_delay;
49 }
50
51 bool ShouldWait(Thread* thread) const override;
52 void Acquire(Thread* thread) override;
53
54 void WakeupAllWaitingThreads() override;
55
56 /**
57 * Starts the timer, with the specified initial delay and interval.
58 * @param initial Delay until the timer is first fired
59 * @param interval Delay until the timer is fired after the first time
60 */
61 void Set(s64 initial, s64 interval);
62
63 void Cancel();
64 void Clear();
65
66 /**
67 * Signals the timer, waking up any waiting threads and rescheduling it
68 * for the next interval.
69 * This method should not be called from outside the timer callback handler,
70 * lest multiple callback events get scheduled.
71 */
72 void Signal(int cycles_late);
73
74private:
75 explicit Timer(KernelCore& kernel);
76 ~Timer() override;
77
78 ResetType reset_type; ///< The ResetType of this timer
79
80 u64 initial_delay; ///< The delay until the timer fires for the first time
81 u64 interval_delay; ///< The delay until the timer fires after the first time
82
83 bool signaled; ///< Whether the timer has been signaled or not
84 std::string name; ///< Name of timer (optional)
85
86 /// Handle used as userdata to reference this object when inserting into the CoreTiming queue.
87 Handle callback_handle;
88};
89
90} // namespace Kernel
diff --git a/src/core/hle/kernel/wait_object.h b/src/core/hle/kernel/wait_object.h
index d70b67893..5987fb971 100644
--- a/src/core/hle/kernel/wait_object.h
+++ b/src/core/hle/kernel/wait_object.h
@@ -33,19 +33,19 @@ public:
33 * Add a thread to wait on this object 33 * Add a thread to wait on this object
34 * @param thread Pointer to thread to add 34 * @param thread Pointer to thread to add
35 */ 35 */
36 virtual void AddWaitingThread(SharedPtr<Thread> thread); 36 void AddWaitingThread(SharedPtr<Thread> thread);
37 37
38 /** 38 /**
39 * Removes a thread from waiting on this object (e.g. if it was resumed already) 39 * Removes a thread from waiting on this object (e.g. if it was resumed already)
40 * @param thread Pointer to thread to remove 40 * @param thread Pointer to thread to remove
41 */ 41 */
42 virtual void RemoveWaitingThread(Thread* thread); 42 void RemoveWaitingThread(Thread* thread);
43 43
44 /** 44 /**
45 * Wake up all threads waiting on this object that can be awoken, in priority order, 45 * Wake up all threads waiting on this object that can be awoken, in priority order,
46 * and set the synchronization result and output of the thread. 46 * and set the synchronization result and output of the thread.
47 */ 47 */
48 virtual void WakeupAllWaitingThreads(); 48 void WakeupAllWaitingThreads();
49 49
50 /** 50 /**
51 * Wakes up a single thread waiting on this object. 51 * Wakes up a single thread waiting on this object.
diff --git a/src/core/hle/service/am/applet_ae.cpp b/src/core/hle/service/am/applet_ae.cpp
index 41a573a91..b888f861d 100644
--- a/src/core/hle/service/am/applet_ae.cpp
+++ b/src/core/hle/service/am/applet_ae.cpp
@@ -249,7 +249,8 @@ AppletAE::AppletAE(std::shared_ptr<NVFlinger::NVFlinger> nvflinger,
249 {300, nullptr, "OpenOverlayAppletProxy"}, 249 {300, nullptr, "OpenOverlayAppletProxy"},
250 {350, nullptr, "OpenSystemApplicationProxy"}, 250 {350, nullptr, "OpenSystemApplicationProxy"},
251 {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"}, 251 {400, nullptr, "CreateSelfLibraryAppletCreatorForDevelop"},
252 {401, nullptr, "GetSystemAppletControllerForDebug"}, 252 {410, nullptr, "GetSystemAppletControllerForDebug"},
253 {1000, nullptr, "GetDebugFunctions"},
253 }; 254 };
254 // clang-format on 255 // clang-format on
255 256
diff --git a/src/core/hle/service/audio/audin_u.cpp b/src/core/hle/service/audio/audin_u.cpp
index 657010312..088410564 100644
--- a/src/core/hle/service/audio/audin_u.cpp
+++ b/src/core/hle/service/audio/audin_u.cpp
@@ -12,6 +12,7 @@ namespace Service::Audio {
12class IAudioIn final : public ServiceFramework<IAudioIn> { 12class IAudioIn final : public ServiceFramework<IAudioIn> {
13public: 13public:
14 IAudioIn() : ServiceFramework("IAudioIn") { 14 IAudioIn() : ServiceFramework("IAudioIn") {
15 // clang-format off
15 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
16 {0, nullptr, "GetAudioInState"}, 17 {0, nullptr, "GetAudioInState"},
17 {1, nullptr, "StartAudioIn"}, 18 {1, nullptr, "StartAudioIn"},
@@ -28,16 +29,24 @@ public:
28 {12, nullptr, "SetAudioInDeviceGain"}, 29 {12, nullptr, "SetAudioInDeviceGain"},
29 {13, nullptr, "GetAudioInDeviceGain"}, 30 {13, nullptr, "GetAudioInDeviceGain"},
30 }; 31 };
32 // clang-format on
33
31 RegisterHandlers(functions); 34 RegisterHandlers(functions);
32 } 35 }
33 ~IAudioIn() = default; 36 ~IAudioIn() = default;
34}; 37};
35 38
36AudInU::AudInU() : ServiceFramework("audin:u") { 39AudInU::AudInU() : ServiceFramework("audin:u") {
40 // clang-format off
37 static const FunctionInfo functions[] = { 41 static const FunctionInfo functions[] = {
38 {0, nullptr, "ListAudioIns"}, {1, nullptr, "OpenAudioIn"}, {2, nullptr, "Unknown"}, 42 {0, nullptr, "ListAudioIns"},
39 {3, nullptr, "OpenAudioInAuto"}, {4, nullptr, "ListAudioInsAuto"}, 43 {1, nullptr, "OpenAudioIn"},
44 {2, nullptr, "Unknown"},
45 {3, nullptr, "OpenAudioInAuto"},
46 {4, nullptr, "ListAudioInsAuto"},
40 }; 47 };
48 // clang-format on
49
41 RegisterHandlers(functions); 50 RegisterHandlers(functions);
42} 51}
43 52
diff --git a/src/core/hle/service/audio/audrec_u.cpp b/src/core/hle/service/audio/audrec_u.cpp
index 34974afa9..6956a2e64 100644
--- a/src/core/hle/service/audio/audrec_u.cpp
+++ b/src/core/hle/service/audio/audrec_u.cpp
@@ -12,6 +12,7 @@ namespace Service::Audio {
12class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { 12class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> {
13public: 13public:
14 IFinalOutputRecorder() : ServiceFramework("IFinalOutputRecorder") { 14 IFinalOutputRecorder() : ServiceFramework("IFinalOutputRecorder") {
15 // clang-format off
15 static const FunctionInfo functions[] = { 16 static const FunctionInfo functions[] = {
16 {0, nullptr, "GetFinalOutputRecorderState"}, 17 {0, nullptr, "GetFinalOutputRecorderState"},
17 {1, nullptr, "StartFinalOutputRecorder"}, 18 {1, nullptr, "StartFinalOutputRecorder"},
@@ -20,10 +21,13 @@ public:
20 {4, nullptr, "RegisterBufferEvent"}, 21 {4, nullptr, "RegisterBufferEvent"},
21 {5, nullptr, "GetReleasedFinalOutputRecorderBuffer"}, 22 {5, nullptr, "GetReleasedFinalOutputRecorderBuffer"},
22 {6, nullptr, "ContainsFinalOutputRecorderBuffer"}, 23 {6, nullptr, "ContainsFinalOutputRecorderBuffer"},
23 {7, nullptr, "Unknown"}, 24 {7, nullptr, "GetFinalOutputRecorderBufferEndTime"},
24 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"}, 25 {8, nullptr, "AppendFinalOutputRecorderBufferAuto"},
25 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"}, 26 {9, nullptr, "GetReleasedFinalOutputRecorderBufferAuto"},
27 {10, nullptr, "FlushFinalOutputRecorderBuffers"},
26 }; 28 };
29 // clang-format on
30
27 RegisterHandlers(functions); 31 RegisterHandlers(functions);
28 } 32 }
29 ~IFinalOutputRecorder() = default; 33 ~IFinalOutputRecorder() = default;
diff --git a/src/core/hle/service/audio/audren_u.cpp b/src/core/hle/service/audio/audren_u.cpp
index 945259c7d..76cc48254 100644
--- a/src/core/hle/service/audio/audren_u.cpp
+++ b/src/core/hle/service/audio/audren_u.cpp
@@ -229,14 +229,16 @@ private:
229}; // namespace Audio 229}; // namespace Audio
230 230
231AudRenU::AudRenU() : ServiceFramework("audren:u") { 231AudRenU::AudRenU() : ServiceFramework("audren:u") {
232 // clang-format off
232 static const FunctionInfo functions[] = { 233 static const FunctionInfo functions[] = {
233 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"}, 234 {0, &AudRenU::OpenAudioRenderer, "OpenAudioRenderer"},
234 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"}, 235 {1, &AudRenU::GetAudioRendererWorkBufferSize, "GetAudioRendererWorkBufferSize"},
235 {2, &AudRenU::GetAudioDevice, "GetAudioDevice"}, 236 {2, &AudRenU::GetAudioDeviceService, "GetAudioDeviceService"},
236 {3, nullptr, "OpenAudioRendererAuto"}, 237 {3, nullptr, "OpenAudioRendererAuto"},
237 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, 238 {4, &AudRenU::GetAudioDeviceServiceWithRevisionInfo, "GetAudioDeviceServiceWithRevisionInfo"},
238 "GetAudioDeviceServiceWithRevisionInfo"},
239 }; 239 };
240 // clang-format on
241
240 RegisterHandlers(functions); 242 RegisterHandlers(functions);
241} 243}
242 244
@@ -313,7 +315,7 @@ void AudRenU::GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx) {
313 LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", output_sz); 315 LOG_DEBUG(Service_Audio, "buffer_size=0x{:X}", output_sz);
314} 316}
315 317
316void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { 318void AudRenU::GetAudioDeviceService(Kernel::HLERequestContext& ctx) {
317 LOG_DEBUG(Service_Audio, "called"); 319 LOG_DEBUG(Service_Audio, "called");
318 320
319 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 321 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/hle/service/audio/audren_u.h b/src/core/hle/service/audio/audren_u.h
index c6bc3a90a..3d63388fb 100644
--- a/src/core/hle/service/audio/audren_u.h
+++ b/src/core/hle/service/audio/audren_u.h
@@ -20,7 +20,7 @@ public:
20private: 20private:
21 void OpenAudioRenderer(Kernel::HLERequestContext& ctx); 21 void OpenAudioRenderer(Kernel::HLERequestContext& ctx);
22 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx); 22 void GetAudioRendererWorkBufferSize(Kernel::HLERequestContext& ctx);
23 void GetAudioDevice(Kernel::HLERequestContext& ctx); 23 void GetAudioDeviceService(Kernel::HLERequestContext& ctx);
24 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx); 24 void GetAudioDeviceServiceWithRevisionInfo(Kernel::HLERequestContext& ctx);
25 25
26 enum class AudioFeatures : u32 { 26 enum class AudioFeatures : u32 {
diff --git a/src/core/hle/service/btdrv/btdrv.cpp b/src/core/hle/service/btdrv/btdrv.cpp
index 5704ca0ab..59ef603e1 100644
--- a/src/core/hle/service/btdrv/btdrv.cpp
+++ b/src/core/hle/service/btdrv/btdrv.cpp
@@ -19,16 +19,16 @@ public:
19 explicit Bt() : ServiceFramework{"bt"} { 19 explicit Bt() : ServiceFramework{"bt"} {
20 // clang-format off 20 // clang-format off
21 static const FunctionInfo functions[] = { 21 static const FunctionInfo functions[] = {
22 {0, nullptr, "Unknown0"}, 22 {0, nullptr, "LeClientReadCharacteristic"},
23 {1, nullptr, "Unknown1"}, 23 {1, nullptr, "LeClientReadDescriptor"},
24 {2, nullptr, "Unknown2"}, 24 {2, nullptr, "LeClientWriteCharacteristic"},
25 {3, nullptr, "Unknown3"}, 25 {3, nullptr, "LeClientWriteDescriptor"},
26 {4, nullptr, "Unknown4"}, 26 {4, nullptr, "LeClientRegisterNotification"},
27 {5, nullptr, "Unknown5"}, 27 {5, nullptr, "LeClientDeregisterNotification"},
28 {6, nullptr, "Unknown6"}, 28 {6, nullptr, "SetLeResponse"},
29 {7, nullptr, "Unknown7"}, 29 {7, nullptr, "LeSendIndication"},
30 {8, nullptr, "Unknown8"}, 30 {8, nullptr, "GetLeEventInfo"},
31 {9, &Bt::RegisterEvent, "RegisterEvent"}, 31 {9, &Bt::RegisterBleEvent, "RegisterBleEvent"},
32 }; 32 };
33 // clang-format on 33 // clang-format on
34 RegisterHandlers(functions); 34 RegisterHandlers(functions);
@@ -39,7 +39,7 @@ public:
39 } 39 }
40 40
41private: 41private:
42 void RegisterEvent(Kernel::HLERequestContext& ctx) { 42 void RegisterBleEvent(Kernel::HLERequestContext& ctx) {
43 LOG_WARNING(Service_BTM, "(STUBBED) called"); 43 LOG_WARNING(Service_BTM, "(STUBBED) called");
44 44
45 IPC::ResponseBuilder rb{ctx, 2, 1}; 45 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -55,11 +55,11 @@ public:
55 explicit BtDrv() : ServiceFramework{"btdrv"} { 55 explicit BtDrv() : ServiceFramework{"btdrv"} {
56 // clang-format off 56 // clang-format off
57 static const FunctionInfo functions[] = { 57 static const FunctionInfo functions[] = {
58 {0, nullptr, "Unknown"}, 58 {0, nullptr, "InitializeBluetoothDriver"},
59 {1, nullptr, "Init"}, 59 {1, nullptr, "InitializeBluetooth"},
60 {2, nullptr, "Enable"}, 60 {2, nullptr, "EnableBluetooth"},
61 {3, nullptr, "Disable"}, 61 {3, nullptr, "DisableBluetooth"},
62 {4, nullptr, "CleanupAndShutdown"}, 62 {4, nullptr, "CleanupBluetooth"},
63 {5, nullptr, "GetAdapterProperties"}, 63 {5, nullptr, "GetAdapterProperties"},
64 {6, nullptr, "GetAdapterProperty"}, 64 {6, nullptr, "GetAdapterProperty"},
65 {7, nullptr, "SetAdapterProperty"}, 65 {7, nullptr, "SetAdapterProperty"},
@@ -70,36 +70,91 @@ public:
70 {12, nullptr, "CancelBond"}, 70 {12, nullptr, "CancelBond"},
71 {13, nullptr, "PinReply"}, 71 {13, nullptr, "PinReply"},
72 {14, nullptr, "SspReply"}, 72 {14, nullptr, "SspReply"},
73 {15, nullptr, "Unknown2"}, 73 {15, nullptr, "GetEventInfo"},
74 {16, nullptr, "InitInterfaces"}, 74 {16, nullptr, "InitializeHid"},
75 {17, nullptr, "HidHostInterface_Connect"}, 75 {17, nullptr, "HidConnect"},
76 {18, nullptr, "HidHostInterface_Disconnect"}, 76 {18, nullptr, "HidDisconnect"},
77 {19, nullptr, "HidHostInterface_SendData"}, 77 {19, nullptr, "HidSendData"},
78 {20, nullptr, "HidHostInterface_SendData2"}, 78 {20, nullptr, "HidSendData2"},
79 {21, nullptr, "HidHostInterface_SetReport"}, 79 {21, nullptr, "HidSetReport"},
80 {22, nullptr, "HidHostInterface_GetReport"}, 80 {22, nullptr, "HidGetReport"},
81 {23, nullptr, "HidHostInterface_WakeController"}, 81 {23, nullptr, "HidWakeController"},
82 {24, nullptr, "HidHostInterface_AddPairedDevice"}, 82 {24, nullptr, "HidAddPairedDevice"},
83 {25, nullptr, "HidHostInterface_GetPairedDevice"}, 83 {25, nullptr, "HidGetPairedDevice"},
84 {26, nullptr, "HidHostInterface_CleanupAndShutdown"}, 84 {26, nullptr, "CleanupHid"},
85 {27, nullptr, "Unknown3"}, 85 {27, nullptr, "HidGetEventInfo"},
86 {28, nullptr, "ExtInterface_SetTSI"}, 86 {28, nullptr, "ExtSetTsi"},
87 {29, nullptr, "ExtInterface_SetBurstMode"}, 87 {29, nullptr, "ExtSetBurstMode"},
88 {30, nullptr, "ExtInterface_SetZeroRetran"}, 88 {30, nullptr, "ExtSetZeroRetran"},
89 {31, nullptr, "ExtInterface_SetMcMode"}, 89 {31, nullptr, "ExtSetMcMode"},
90 {32, nullptr, "ExtInterface_StartLlrMode"}, 90 {32, nullptr, "ExtStartLlrMode"},
91 {33, nullptr, "ExtInterface_ExitLlrMode"}, 91 {33, nullptr, "ExtExitLlrMode"},
92 {34, nullptr, "ExtInterface_SetRadio"}, 92 {34, nullptr, "ExtSetRadio"},
93 {35, nullptr, "ExtInterface_SetVisibility"}, 93 {35, nullptr, "ExtSetVisibility"},
94 {36, nullptr, "Unknown4"}, 94 {36, nullptr, "ExtSetTbfcScan"},
95 {37, nullptr, "Unknown5"}, 95 {37, nullptr, "RegisterHidReportEvent"},
96 {38, nullptr, "HidHostInterface_GetLatestPlr"}, 96 {38, nullptr, "HidGetReportEventInfo"},
97 {39, nullptr, "ExtInterface_GetPendingConnections"}, 97 {39, nullptr, "GetLatestPlr"},
98 {40, nullptr, "HidHostInterface_GetChannelMap"}, 98 {40, nullptr, "ExtGetPendingConnections"},
99 {41, nullptr, "SetIsBluetoothBoostEnabled"}, 99 {41, nullptr, "GetChannelMap"},
100 {42, nullptr, "GetIsBluetoothBoostEnabled"}, 100 {42, nullptr, "EnableBluetoothBoostSetting"},
101 {43, nullptr, "SetIsBluetoothAfhEnabled"}, 101 {43, nullptr, "IsBluetoothBoostSettingEnabled"},
102 {44, nullptr, "GetIsBluetoothAfhEnabled"}, 102 {44, nullptr, "EnableBluetoothAfhSetting"},
103 {45, nullptr, "IsBluetoothAfhSettingEnabled"},
104 {46, nullptr, "InitializeBluetoothLe"},
105 {47, nullptr, "EnableBluetoothLe"},
106 {48, nullptr, "DisableBluetoothLe"},
107 {49, nullptr, "CleanupBluetoothLe"},
108 {50, nullptr, "SetLeVisibility"},
109 {51, nullptr, "SetLeConnectionParameter"},
110 {52, nullptr, "SetLeDefaultConnectionParameter"},
111 {53, nullptr, "SetLeAdvertiseData"},
112 {54, nullptr, "SetLeAdvertiseParameter"},
113 {55, nullptr, "StartLeScan"},
114 {56, nullptr, "StopLeScan"},
115 {57, nullptr, "AddLeScanFilterCondition"},
116 {58, nullptr, "DeleteLeScanFilterCondition"},
117 {59, nullptr, "DeleteLeScanFilter"},
118 {60, nullptr, "ClearLeScanFilters"},
119 {61, nullptr, "EnableLeScanFilter"},
120 {62, nullptr, "RegisterLeClient"},
121 {63, nullptr, "UnregisterLeClient"},
122 {64, nullptr, "UnregisterLeClientAll"},
123 {65, nullptr, "LeClientConnect"},
124 {66, nullptr, "LeClientCancelConnection"},
125 {67, nullptr, "LeClientDisconnect"},
126 {68, nullptr, "LeClientGetAttributes"},
127 {69, nullptr, "LeClientDiscoverService"},
128 {70, nullptr, "LeClientConfigureMtu"},
129 {71, nullptr, "RegisterLeServer"},
130 {72, nullptr, "UnregisterLeServer"},
131 {73, nullptr, "LeServerConnect"},
132 {74, nullptr, "LeServerDisconnect"},
133 {75, nullptr, "CreateLeService"},
134 {76, nullptr, "StartLeService"},
135 {77, nullptr, "AddLeCharacteristic"},
136 {78, nullptr, "AddLeDescriptor"},
137 {79, nullptr, "GetLeCoreEventInfo"},
138 {80, nullptr, "LeGetFirstCharacteristic"},
139 {81, nullptr, "LeGetNextCharacteristic"},
140 {82, nullptr, "LeGetFirstDescriptor"},
141 {83, nullptr, "LeGetNextDescriptor"},
142 {84, nullptr, "RegisterLeCoreDataPath"},
143 {85, nullptr, "UnregisterLeCoreDataPath"},
144 {86, nullptr, "RegisterLeHidDataPath"},
145 {87, nullptr, "UnregisterLeHidDataPath"},
146 {88, nullptr, "RegisterLeDataPath"},
147 {89, nullptr, "UnregisterLeDataPath"},
148 {90, nullptr, "LeClientReadCharacteristic"},
149 {91, nullptr, "LeClientReadDescriptor"},
150 {92, nullptr, "LeClientWriteCharacteristic"},
151 {93, nullptr, "LeClientWriteDescriptor"},
152 {94, nullptr, "LeClientRegisterNotification"},
153 {95, nullptr, "LeClientDeregisterNotification"},
154 {96, nullptr, "GetLeHidEventInfo"},
155 {97, nullptr, "RegisterBleHidEvent"},
156 {98, nullptr, "SetLeScanParameter"},
157 {256, nullptr, "GetIsManufacturingMode"}
103 }; 158 };
104 // clang-format on 159 // clang-format on
105 160
diff --git a/src/core/hle/service/btm/btm.cpp b/src/core/hle/service/btm/btm.cpp
index ef7398a23..4f15c3f19 100644
--- a/src/core/hle/service/btm/btm.cpp
+++ b/src/core/hle/service/btm/btm.cpp
@@ -20,38 +20,38 @@ public:
20 explicit IBtmUserCore() : ServiceFramework{"IBtmUserCore"} { 20 explicit IBtmUserCore() : ServiceFramework{"IBtmUserCore"} {
21 // clang-format off 21 // clang-format off
22 static const FunctionInfo functions[] = { 22 static const FunctionInfo functions[] = {
23 {0, &IBtmUserCore::GetScanEvent, "GetScanEvent"}, 23 {0, &IBtmUserCore::AcquireBleScanEvent, "AcquireBleScanEvent"},
24 {1, nullptr, "Unknown1"}, 24 {1, nullptr, "GetBleScanFilterParameter"},
25 {2, nullptr, "Unknown2"}, 25 {2, nullptr, "GetBleScanFilterParameter2"},
26 {3, nullptr, "Unknown3"}, 26 {3, nullptr, "StartBleScanForGeneral"},
27 {4, nullptr, "Unknown4"}, 27 {4, nullptr, "StopBleScanForGeneral"},
28 {5, nullptr, "Unknown5"}, 28 {5, nullptr, "GetBleScanResultsForGeneral"},
29 {6, nullptr, "Unknown6"}, 29 {6, nullptr, "StartBleScanForPaired"},
30 {7, nullptr, "Unknown7"}, 30 {7, nullptr, "StopBleScanForPaired"},
31 {8, nullptr, "Unknown8"}, 31 {8, nullptr, "StartBleScanForSmartDevice"},
32 {9, nullptr, "Unknown9"}, 32 {9, nullptr, "StopBleScanForSmartDevice"},
33 {10, nullptr, "Unknown10"}, 33 {10, nullptr, "GetBleScanResultsForSmartDevice"},
34 {17, &IBtmUserCore::GetConnectionEvent, "GetConnectionEvent"}, 34 {17, &IBtmUserCore::AcquireBleConnectionEvent, "AcquireBleConnectionEvent"},
35 {18, nullptr, "Unknown18"}, 35 {18, nullptr, "BleConnect"},
36 {19, nullptr, "Unknown19"}, 36 {19, nullptr, "BleDisconnect"},
37 {20, nullptr, "Unknown20"}, 37 {20, nullptr, "BleGetConnectionState"},
38 {21, nullptr, "Unknown21"}, 38 {21, nullptr, "AcquireBlePairingEvent"},
39 {22, nullptr, "Unknown22"}, 39 {22, nullptr, "BlePairDevice"},
40 {23, nullptr, "Unknown23"}, 40 {23, nullptr, "BleUnPairDevice"},
41 {24, nullptr, "Unknown24"}, 41 {24, nullptr, "BleUnPairDevice2"},
42 {25, nullptr, "Unknown25"}, 42 {25, nullptr, "BleGetPairedDevices"},
43 {26, &IBtmUserCore::GetDiscoveryEvent, "AcquireBleServiceDiscoveryEventImpl"}, 43 {26, &IBtmUserCore::AcquireBleServiceDiscoveryEvent, "AcquireBleServiceDiscoveryEvent"},
44 {27, nullptr, "Unknown27"}, 44 {27, nullptr, "GetGattServices"},
45 {28, nullptr, "Unknown28"}, 45 {28, nullptr, "GetGattService"},
46 {29, nullptr, "Unknown29"}, 46 {29, nullptr, "GetGattIncludedServices"},
47 {30, nullptr, "Unknown30"}, 47 {30, nullptr, "GetBelongingGattService"},
48 {31, nullptr, "Unknown31"}, 48 {31, nullptr, "GetGattCharacteristics"},
49 {32, nullptr, "Unknown32"}, 49 {32, nullptr, "GetGattDescriptors"},
50 {33, &IBtmUserCore::GetConfigEvent, "GetConfigEvent"}, 50 {33, &IBtmUserCore::AcquireBleMtuConfigEvent, "AcquireBleMtuConfigEvent"},
51 {34, nullptr, "Unknown34"}, 51 {34, nullptr, "ConfigureBleMtu"},
52 {35, nullptr, "Unknown35"}, 52 {35, nullptr, "GetBleMtu"},
53 {36, nullptr, "Unknown36"}, 53 {36, nullptr, "RegisterBleGattDataPath"},
54 {37, nullptr, "Unknown37"}, 54 {37, nullptr, "UnregisterBleGattDataPath"},
55 }; 55 };
56 // clang-format on 56 // clang-format on
57 RegisterHandlers(functions); 57 RegisterHandlers(functions);
@@ -68,7 +68,7 @@ public:
68 } 68 }
69 69
70private: 70private:
71 void GetScanEvent(Kernel::HLERequestContext& ctx) { 71 void AcquireBleScanEvent(Kernel::HLERequestContext& ctx) {
72 LOG_WARNING(Service_BTM, "(STUBBED) called"); 72 LOG_WARNING(Service_BTM, "(STUBBED) called");
73 73
74 IPC::ResponseBuilder rb{ctx, 2, 1}; 74 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -76,7 +76,7 @@ private:
76 rb.PushCopyObjects(scan_event.readable); 76 rb.PushCopyObjects(scan_event.readable);
77 } 77 }
78 78
79 void GetConnectionEvent(Kernel::HLERequestContext& ctx) { 79 void AcquireBleConnectionEvent(Kernel::HLERequestContext& ctx) {
80 LOG_WARNING(Service_BTM, "(STUBBED) called"); 80 LOG_WARNING(Service_BTM, "(STUBBED) called");
81 81
82 IPC::ResponseBuilder rb{ctx, 2, 1}; 82 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -84,7 +84,7 @@ private:
84 rb.PushCopyObjects(connection_event.readable); 84 rb.PushCopyObjects(connection_event.readable);
85 } 85 }
86 86
87 void GetDiscoveryEvent(Kernel::HLERequestContext& ctx) { 87 void AcquireBleServiceDiscoveryEvent(Kernel::HLERequestContext& ctx) {
88 LOG_WARNING(Service_BTM, "(STUBBED) called"); 88 LOG_WARNING(Service_BTM, "(STUBBED) called");
89 89
90 IPC::ResponseBuilder rb{ctx, 2, 1}; 90 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -92,7 +92,7 @@ private:
92 rb.PushCopyObjects(service_discovery.readable); 92 rb.PushCopyObjects(service_discovery.readable);
93 } 93 }
94 94
95 void GetConfigEvent(Kernel::HLERequestContext& ctx) { 95 void AcquireBleMtuConfigEvent(Kernel::HLERequestContext& ctx) {
96 LOG_WARNING(Service_BTM, "(STUBBED) called"); 96 LOG_WARNING(Service_BTM, "(STUBBED) called");
97 97
98 IPC::ResponseBuilder rb{ctx, 2, 1}; 98 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -111,14 +111,14 @@ public:
111 explicit BTM_USR() : ServiceFramework{"btm:u"} { 111 explicit BTM_USR() : ServiceFramework{"btm:u"} {
112 // clang-format off 112 // clang-format off
113 static const FunctionInfo functions[] = { 113 static const FunctionInfo functions[] = {
114 {0, &BTM_USR::GetCoreImpl, "GetCoreImpl"}, 114 {0, &BTM_USR::GetCore, "GetCore"},
115 }; 115 };
116 // clang-format on 116 // clang-format on
117 RegisterHandlers(functions); 117 RegisterHandlers(functions);
118 } 118 }
119 119
120private: 120private:
121 void GetCoreImpl(Kernel::HLERequestContext& ctx) { 121 void GetCore(Kernel::HLERequestContext& ctx) {
122 LOG_DEBUG(Service_BTM, "called"); 122 LOG_DEBUG(Service_BTM, "called");
123 123
124 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 124 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
@@ -134,26 +134,64 @@ public:
134 static const FunctionInfo functions[] = { 134 static const FunctionInfo functions[] = {
135 {0, nullptr, "Unknown1"}, 135 {0, nullptr, "Unknown1"},
136 {1, nullptr, "Unknown2"}, 136 {1, nullptr, "Unknown2"},
137 {2, nullptr, "RegisterSystemEventForConnectedDeviceConditionImpl"}, 137 {2, nullptr, "RegisterSystemEventForConnectedDeviceCondition"},
138 {3, nullptr, "Unknown3"}, 138 {3, nullptr, "Unknown3"},
139 {4, nullptr, "Unknown4"}, 139 {4, nullptr, "Unknown4"},
140 {5, nullptr, "Unknown5"}, 140 {5, nullptr, "Unknown5"},
141 {6, nullptr, "Unknown6"}, 141 {6, nullptr, "Unknown6"},
142 {7, nullptr, "Unknown7"}, 142 {7, nullptr, "Unknown7"},
143 {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfoImpl"}, 143 {8, nullptr, "RegisterSystemEventForRegisteredDeviceInfo"},
144 {9, nullptr, "Unknown8"}, 144 {9, nullptr, "Unknown8"},
145 {10, nullptr, "Unknown9"}, 145 {10, nullptr, "Unknown9"},
146 {11, nullptr, "Unknown10"}, 146 {11, nullptr, "Unknown10"},
147 {12, nullptr, "Unknown11"}, 147 {12, nullptr, "Unknown11"},
148 {13, nullptr, "Unknown12"}, 148 {13, nullptr, "Unknown12"},
149 {14, nullptr, "EnableRadioImpl"}, 149 {14, nullptr, "EnableRadio"},
150 {15, nullptr, "DisableRadioImpl"}, 150 {15, nullptr, "DisableRadio"},
151 {16, nullptr, "Unknown13"}, 151 {16, nullptr, "Unknown13"},
152 {17, nullptr, "Unknown14"}, 152 {17, nullptr, "Unknown14"},
153 {18, nullptr, "Unknown15"}, 153 {18, nullptr, "Unknown15"},
154 {19, nullptr, "Unknown16"}, 154 {19, nullptr, "Unknown16"},
155 {20, nullptr, "Unknown17"}, 155 {20, nullptr, "Unknown17"},
156 {21, nullptr, "Unknown18"}, 156 {21, nullptr, "Unknown18"},
157 {22, nullptr, "Unknown19"},
158 {23, nullptr, "Unknown20"},
159 {24, nullptr, "Unknown21"},
160 {25, nullptr, "Unknown22"},
161 {26, nullptr, "Unknown23"},
162 {27, nullptr, "Unknown24"},
163 {28, nullptr, "Unknown25"},
164 {29, nullptr, "Unknown26"},
165 {30, nullptr, "Unknown27"},
166 {31, nullptr, "Unknown28"},
167 {32, nullptr, "Unknown29"},
168 {33, nullptr, "Unknown30"},
169 {34, nullptr, "Unknown31"},
170 {35, nullptr, "Unknown32"},
171 {36, nullptr, "Unknown33"},
172 {37, nullptr, "Unknown34"},
173 {38, nullptr, "Unknown35"},
174 {39, nullptr, "Unknown36"},
175 {40, nullptr, "Unknown37"},
176 {41, nullptr, "Unknown38"},
177 {42, nullptr, "Unknown39"},
178 {43, nullptr, "Unknown40"},
179 {44, nullptr, "Unknown41"},
180 {45, nullptr, "Unknown42"},
181 {46, nullptr, "Unknown43"},
182 {47, nullptr, "Unknown44"},
183 {48, nullptr, "Unknown45"},
184 {49, nullptr, "Unknown46"},
185 {50, nullptr, "Unknown47"},
186 {51, nullptr, "Unknown48"},
187 {52, nullptr, "Unknown49"},
188 {53, nullptr, "Unknown50"},
189 {54, nullptr, "Unknown51"},
190 {55, nullptr, "Unknown52"},
191 {56, nullptr, "Unknown53"},
192 {57, nullptr, "Unknown54"},
193 {58, nullptr, "Unknown55"},
194 {59, nullptr, "Unknown56"},
157 }; 195 };
158 // clang-format on 196 // clang-format on
159 197
@@ -166,7 +204,7 @@ public:
166 explicit BTM_DBG() : ServiceFramework{"btm:dbg"} { 204 explicit BTM_DBG() : ServiceFramework{"btm:dbg"} {
167 // clang-format off 205 // clang-format off
168 static const FunctionInfo functions[] = { 206 static const FunctionInfo functions[] = {
169 {0, nullptr, "RegisterSystemEventForDiscoveryImpl"}, 207 {0, nullptr, "RegisterSystemEventForDiscovery"},
170 {1, nullptr, "Unknown1"}, 208 {1, nullptr, "Unknown1"},
171 {2, nullptr, "Unknown2"}, 209 {2, nullptr, "Unknown2"},
172 {3, nullptr, "Unknown3"}, 210 {3, nullptr, "Unknown3"},
@@ -175,6 +213,10 @@ public:
175 {6, nullptr, "Unknown6"}, 213 {6, nullptr, "Unknown6"},
176 {7, nullptr, "Unknown7"}, 214 {7, nullptr, "Unknown7"},
177 {8, nullptr, "Unknown8"}, 215 {8, nullptr, "Unknown8"},
216 {9, nullptr, "Unknown9"},
217 {10, nullptr, "Unknown10"},
218 {11, nullptr, "Unknown11"},
219 {12, nullptr, "Unknown11"},
178 }; 220 };
179 // clang-format on 221 // clang-format on
180 222
@@ -187,16 +229,16 @@ public:
187 explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} { 229 explicit IBtmSystemCore() : ServiceFramework{"IBtmSystemCore"} {
188 // clang-format off 230 // clang-format off
189 static const FunctionInfo functions[] = { 231 static const FunctionInfo functions[] = {
190 {0, nullptr, "StartGamepadPairingImpl"}, 232 {0, nullptr, "StartGamepadPairing"},
191 {1, nullptr, "CancelGamepadPairingImpl"}, 233 {1, nullptr, "CancelGamepadPairing"},
192 {2, nullptr, "ClearGamepadPairingDatabaseImpl"}, 234 {2, nullptr, "ClearGamepadPairingDatabase"},
193 {3, nullptr, "GetPairedGamepadCountImpl"}, 235 {3, nullptr, "GetPairedGamepadCount"},
194 {4, nullptr, "EnableRadioImpl"}, 236 {4, nullptr, "EnableRadio"},
195 {5, nullptr, "DisableRadioImpl"}, 237 {5, nullptr, "DisableRadio"},
196 {6, nullptr, "GetRadioOnOffImpl"}, 238 {6, nullptr, "GetRadioOnOff"},
197 {7, nullptr, "AcquireRadioEventImpl"}, 239 {7, nullptr, "AcquireRadioEvent"},
198 {8, nullptr, "AcquireGamepadPairingEventImpl"}, 240 {8, nullptr, "AcquireGamepadPairingEvent"},
199 {9, nullptr, "IsGamepadPairingStartedImpl"}, 241 {9, nullptr, "IsGamepadPairingStarted"},
200 }; 242 };
201 // clang-format on 243 // clang-format on
202 244
@@ -209,7 +251,7 @@ public:
209 explicit BTM_SYS() : ServiceFramework{"btm:sys"} { 251 explicit BTM_SYS() : ServiceFramework{"btm:sys"} {
210 // clang-format off 252 // clang-format off
211 static const FunctionInfo functions[] = { 253 static const FunctionInfo functions[] = {
212 {0, &BTM_SYS::GetCoreImpl, "GetCoreImpl"}, 254 {0, &BTM_SYS::GetCore, "GetCore"},
213 }; 255 };
214 // clang-format on 256 // clang-format on
215 257
@@ -217,7 +259,7 @@ public:
217 } 259 }
218 260
219private: 261private:
220 void GetCoreImpl(Kernel::HLERequestContext& ctx) { 262 void GetCore(Kernel::HLERequestContext& ctx) {
221 LOG_DEBUG(Service_BTM, "called"); 263 LOG_DEBUG(Service_BTM, "called");
222 264
223 IPC::ResponseBuilder rb{ctx, 2, 0, 1}; 265 IPC::ResponseBuilder rb{ctx, 2, 0, 1};
diff --git a/src/core/hle/service/filesystem/fsp_srv.cpp b/src/core/hle/service/filesystem/fsp_srv.cpp
index 74c4e583b..54959edd8 100644
--- a/src/core/hle/service/filesystem/fsp_srv.cpp
+++ b/src/core/hle/service/filesystem/fsp_srv.cpp
@@ -627,8 +627,8 @@ private:
627FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { 627FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
628 // clang-format off 628 // clang-format off
629 static const FunctionInfo functions[] = { 629 static const FunctionInfo functions[] = {
630 {0, nullptr, "MountContent"}, 630 {0, nullptr, "OpenFileSystem"},
631 {1, &FSP_SRV::Initialize, "Initialize"}, 631 {1, &FSP_SRV::SetCurrentProcess, "SetCurrentProcess"},
632 {2, nullptr, "OpenDataFileSystemByCurrentProcess"}, 632 {2, nullptr, "OpenDataFileSystemByCurrentProcess"},
633 {7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"}, 633 {7, &FSP_SRV::OpenFileSystemWithPatch, "OpenFileSystemWithPatch"},
634 {8, nullptr, "OpenFileSystemWithId"}, 634 {8, nullptr, "OpenFileSystemWithId"},
@@ -637,10 +637,10 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
637 {12, nullptr, "OpenBisStorage"}, 637 {12, nullptr, "OpenBisStorage"},
638 {13, nullptr, "InvalidateBisCache"}, 638 {13, nullptr, "InvalidateBisCache"},
639 {17, nullptr, "OpenHostFileSystem"}, 639 {17, nullptr, "OpenHostFileSystem"},
640 {18, &FSP_SRV::MountSdCard, "MountSdCard"}, 640 {18, &FSP_SRV::OpenSdCardFileSystem, "OpenSdCardFileSystem"},
641 {19, nullptr, "FormatSdCardFileSystem"}, 641 {19, nullptr, "FormatSdCardFileSystem"},
642 {21, nullptr, "DeleteSaveDataFileSystem"}, 642 {21, nullptr, "DeleteSaveDataFileSystem"},
643 {22, &FSP_SRV::CreateSaveData, "CreateSaveData"}, 643 {22, &FSP_SRV::CreateSaveDataFileSystem, "CreateSaveDataFileSystem"},
644 {23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"}, 644 {23, nullptr, "CreateSaveDataFileSystemBySystemSaveDataId"},
645 {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"}, 645 {24, nullptr, "RegisterSaveDataFileSystemAtomicDeletion"},
646 {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"}, 646 {25, nullptr, "DeleteSaveDataFileSystemBySaveDataSpaceId"},
@@ -652,7 +652,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
652 {32, nullptr, "ExtendSaveDataFileSystem"}, 652 {32, nullptr, "ExtendSaveDataFileSystem"},
653 {33, nullptr, "DeleteCacheStorage"}, 653 {33, nullptr, "DeleteCacheStorage"},
654 {34, nullptr, "GetCacheStorageSize"}, 654 {34, nullptr, "GetCacheStorageSize"},
655 {51, &FSP_SRV::MountSaveData, "MountSaveData"}, 655 {35, nullptr, "CreateSaveDataFileSystemByHashSalt"},
656 {51, &FSP_SRV::OpenSaveDataFileSystem, "OpenSaveDataFileSystem"},
656 {52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"}, 657 {52, nullptr, "OpenSaveDataFileSystemBySystemSaveDataId"},
657 {53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"}, 658 {53, &FSP_SRV::OpenReadOnlySaveDataFileSystem, "OpenReadOnlySaveDataFileSystem"},
658 {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"}, 659 {57, nullptr, "ReadSaveDataFileSystemExtraDataBySaveDataSpaceId"},
@@ -664,21 +665,26 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
664 {64, nullptr, "OpenSaveDataInternalStorageFileSystem"}, 665 {64, nullptr, "OpenSaveDataInternalStorageFileSystem"},
665 {65, nullptr, "UpdateSaveDataMacForDebug"}, 666 {65, nullptr, "UpdateSaveDataMacForDebug"},
666 {66, nullptr, "WriteSaveDataFileSystemExtraData2"}, 667 {66, nullptr, "WriteSaveDataFileSystemExtraData2"},
668 {67, nullptr, "FindSaveDataWithFilter"},
669 {68, nullptr, "OpenSaveDataInfoReaderBySaveDataFilter"},
667 {80, nullptr, "OpenSaveDataMetaFile"}, 670 {80, nullptr, "OpenSaveDataMetaFile"},
668 {81, nullptr, "OpenSaveDataTransferManager"}, 671 {81, nullptr, "OpenSaveDataTransferManager"},
669 {82, nullptr, "OpenSaveDataTransferManagerVersion2"}, 672 {82, nullptr, "OpenSaveDataTransferManagerVersion2"},
670 {83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"}, 673 {83, nullptr, "OpenSaveDataTransferProhibiterForCloudBackUp"},
674 {84, nullptr, "ListApplicationAccessibleSaveDataOwnerId"},
671 {100, nullptr, "OpenImageDirectoryFileSystem"}, 675 {100, nullptr, "OpenImageDirectoryFileSystem"},
672 {110, nullptr, "OpenContentStorageFileSystem"}, 676 {110, nullptr, "OpenContentStorageFileSystem"},
677 {120, nullptr, "OpenCloudBackupWorkStorageFileSystem"},
673 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"}, 678 {200, &FSP_SRV::OpenDataStorageByCurrentProcess, "OpenDataStorageByCurrentProcess"},
674 {201, nullptr, "OpenDataStorageByProgramId"}, 679 {201, nullptr, "OpenDataStorageByProgramId"},
675 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"}, 680 {202, &FSP_SRV::OpenDataStorageByDataId, "OpenDataStorageByDataId"},
676 {203, &FSP_SRV::OpenRomStorage, "OpenRomStorage"}, 681 {203, &FSP_SRV::OpenPatchDataStorageByCurrentProcess, "OpenPatchDataStorageByCurrentProcess"},
677 {400, nullptr, "OpenDeviceOperator"}, 682 {400, nullptr, "OpenDeviceOperator"},
678 {500, nullptr, "OpenSdCardDetectionEventNotifier"}, 683 {500, nullptr, "OpenSdCardDetectionEventNotifier"},
679 {501, nullptr, "OpenGameCardDetectionEventNotifier"}, 684 {501, nullptr, "OpenGameCardDetectionEventNotifier"},
680 {510, nullptr, "OpenSystemDataUpdateEventNotifier"}, 685 {510, nullptr, "OpenSystemDataUpdateEventNotifier"},
681 {511, nullptr, "NotifySystemDataUpdateEvent"}, 686 {511, nullptr, "NotifySystemDataUpdateEvent"},
687 {520, nullptr, "SimulateGameCardDetectionEvent"},
682 {600, nullptr, "SetCurrentPosixTime"}, 688 {600, nullptr, "SetCurrentPosixTime"},
683 {601, nullptr, "QuerySaveDataTotalSize"}, 689 {601, nullptr, "QuerySaveDataTotalSize"},
684 {602, nullptr, "VerifySaveDataFileSystem"}, 690 {602, nullptr, "VerifySaveDataFileSystem"},
@@ -717,6 +723,8 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
717 {1008, nullptr, "OpenRegisteredUpdatePartition"}, 723 {1008, nullptr, "OpenRegisteredUpdatePartition"},
718 {1009, nullptr, "GetAndClearMemoryReportInfo"}, 724 {1009, nullptr, "GetAndClearMemoryReportInfo"},
719 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"}, 725 {1100, nullptr, "OverrideSaveDataTransferTokenSignVerificationKey"},
726 {1110, nullptr, "CorruptSaveDataFileSystemBySaveDataSpaceId2"},
727 {1200, nullptr, "OpenMultiCommitManager"},
720 }; 728 };
721 // clang-format on 729 // clang-format on
722 RegisterHandlers(functions); 730 RegisterHandlers(functions);
@@ -724,7 +732,7 @@ FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") {
724 732
725FSP_SRV::~FSP_SRV() = default; 733FSP_SRV::~FSP_SRV() = default;
726 734
727void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { 735void FSP_SRV::SetCurrentProcess(Kernel::HLERequestContext& ctx) {
728 LOG_WARNING(Service_FS, "(STUBBED) called"); 736 LOG_WARNING(Service_FS, "(STUBBED) called");
729 737
730 IPC::ResponseBuilder rb{ctx, 2}; 738 IPC::ResponseBuilder rb{ctx, 2};
@@ -743,7 +751,7 @@ void FSP_SRV::OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx) {
743 rb.Push(ResultCode(-1)); 751 rb.Push(ResultCode(-1));
744} 752}
745 753
746void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { 754void FSP_SRV::OpenSdCardFileSystem(Kernel::HLERequestContext& ctx) {
747 LOG_DEBUG(Service_FS, "called"); 755 LOG_DEBUG(Service_FS, "called");
748 756
749 IFileSystem filesystem(OpenSDMC().Unwrap()); 757 IFileSystem filesystem(OpenSDMC().Unwrap());
@@ -753,7 +761,7 @@ void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) {
753 rb.PushIpcInterface<IFileSystem>(std::move(filesystem)); 761 rb.PushIpcInterface<IFileSystem>(std::move(filesystem));
754} 762}
755 763
756void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { 764void FSP_SRV::CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
757 IPC::RequestParser rp{ctx}; 765 IPC::RequestParser rp{ctx};
758 766
759 auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>(); 767 auto save_struct = rp.PopRaw<FileSys::SaveDataDescriptor>();
@@ -767,7 +775,7 @@ void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) {
767 rb.Push(RESULT_SUCCESS); 775 rb.Push(RESULT_SUCCESS);
768} 776}
769 777
770void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { 778void FSP_SRV::OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx) {
771 IPC::RequestParser rp{ctx}; 779 IPC::RequestParser rp{ctx};
772 780
773 auto space_id = rp.PopRaw<FileSys::SaveDataSpaceId>(); 781 auto space_id = rp.PopRaw<FileSys::SaveDataSpaceId>();
@@ -793,7 +801,7 @@ void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) {
793 801
794void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { 802void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) {
795 LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem"); 803 LOG_WARNING(Service_FS, "(STUBBED) called, delegating to 51 OpenSaveDataFilesystem");
796 MountSaveData(ctx); 804 OpenSaveDataFileSystem(ctx);
797} 805}
798 806
799void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { 807void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) {
@@ -881,7 +889,7 @@ void FSP_SRV::OpenDataStorageByDataId(Kernel::HLERequestContext& ctx) {
881 rb.PushIpcInterface<IStorage>(std::move(storage)); 889 rb.PushIpcInterface<IStorage>(std::move(storage));
882} 890}
883 891
884void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { 892void FSP_SRV::OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx) {
885 IPC::RequestParser rp{ctx}; 893 IPC::RequestParser rp{ctx};
886 894
887 auto storage_id = rp.PopRaw<FileSys::StorageId>(); 895 auto storage_id = rp.PopRaw<FileSys::StorageId>();
diff --git a/src/core/hle/service/filesystem/fsp_srv.h b/src/core/hle/service/filesystem/fsp_srv.h
index e7abec0a3..3a5f4e200 100644
--- a/src/core/hle/service/filesystem/fsp_srv.h
+++ b/src/core/hle/service/filesystem/fsp_srv.h
@@ -19,17 +19,17 @@ public:
19 ~FSP_SRV() override; 19 ~FSP_SRV() override;
20 20
21private: 21private:
22 void Initialize(Kernel::HLERequestContext& ctx); 22 void SetCurrentProcess(Kernel::HLERequestContext& ctx);
23 void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx); 23 void OpenFileSystemWithPatch(Kernel::HLERequestContext& ctx);
24 void MountSdCard(Kernel::HLERequestContext& ctx); 24 void OpenSdCardFileSystem(Kernel::HLERequestContext& ctx);
25 void CreateSaveData(Kernel::HLERequestContext& ctx); 25 void CreateSaveDataFileSystem(Kernel::HLERequestContext& ctx);
26 void MountSaveData(Kernel::HLERequestContext& ctx); 26 void OpenSaveDataFileSystem(Kernel::HLERequestContext& ctx);
27 void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx); 27 void OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx);
28 void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx); 28 void OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx);
29 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx); 29 void GetGlobalAccessLogMode(Kernel::HLERequestContext& ctx);
30 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx); 30 void OpenDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
31 void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx); 31 void OpenDataStorageByDataId(Kernel::HLERequestContext& ctx);
32 void OpenRomStorage(Kernel::HLERequestContext& ctx); 32 void OpenPatchDataStorageByCurrentProcess(Kernel::HLERequestContext& ctx);
33 33
34 FileSys::VirtualFile romfs; 34 FileSys::VirtualFile romfs;
35}; 35};
diff --git a/src/core/hle/service/ncm/ncm.cpp b/src/core/hle/service/ncm/ncm.cpp
index 0297edca0..5d31f638f 100644
--- a/src/core/hle/service/ncm/ncm.cpp
+++ b/src/core/hle/service/ncm/ncm.cpp
@@ -40,10 +40,10 @@ public:
40 {6, nullptr, "CloseContentStorageForcibly"}, 40 {6, nullptr, "CloseContentStorageForcibly"},
41 {7, nullptr, "CloseContentMetaDatabaseForcibly"}, 41 {7, nullptr, "CloseContentMetaDatabaseForcibly"},
42 {8, nullptr, "CleanupContentMetaDatabase"}, 42 {8, nullptr, "CleanupContentMetaDatabase"},
43 {9, nullptr, "OpenContentStorage2"}, 43 {9, nullptr, "ActivateContentStorage"},
44 {10, nullptr, "CloseContentStorage"}, 44 {10, nullptr, "InactivateContentStorage"},
45 {11, nullptr, "OpenContentMetaDatabase2"}, 45 {11, nullptr, "ActivateContentMetaDatabase"},
46 {12, nullptr, "CloseContentMetaDatabase"}, 46 {12, nullptr, "InactivateContentMetaDatabase"},
47 }; 47 };
48 // clang-format on 48 // clang-format on
49 49
diff --git a/src/core/hle/service/ns/ns.cpp b/src/core/hle/service/ns/ns.cpp
index 2663f56b1..0eb04037a 100644
--- a/src/core/hle/service/ns/ns.cpp
+++ b/src/core/hle/service/ns/ns.cpp
@@ -43,7 +43,7 @@ public:
43 {11, nullptr, "CalculateApplicationOccupiedSize"}, 43 {11, nullptr, "CalculateApplicationOccupiedSize"},
44 {16, nullptr, "PushApplicationRecord"}, 44 {16, nullptr, "PushApplicationRecord"},
45 {17, nullptr, "ListApplicationRecordContentMeta"}, 45 {17, nullptr, "ListApplicationRecordContentMeta"},
46 {19, nullptr, "LaunchApplication"}, 46 {19, nullptr, "LaunchApplicationOld"},
47 {21, nullptr, "GetApplicationContentPath"}, 47 {21, nullptr, "GetApplicationContentPath"},
48 {22, nullptr, "TerminateApplication"}, 48 {22, nullptr, "TerminateApplication"},
49 {23, nullptr, "ResolveApplicationContentPath"}, 49 {23, nullptr, "ResolveApplicationContentPath"},
@@ -96,10 +96,10 @@ public:
96 {86, nullptr, "EnableApplicationCrashReport"}, 96 {86, nullptr, "EnableApplicationCrashReport"},
97 {87, nullptr, "IsApplicationCrashReportEnabled"}, 97 {87, nullptr, "IsApplicationCrashReportEnabled"},
98 {90, nullptr, "BoostSystemMemoryResourceLimit"}, 98 {90, nullptr, "BoostSystemMemoryResourceLimit"},
99 {91, nullptr, "Unknown1"}, 99 {91, nullptr, "DeprecatedLaunchApplication"},
100 {92, nullptr, "Unknown2"}, 100 {92, nullptr, "GetRunningApplicationProgramId"},
101 {93, nullptr, "GetMainApplicationProgramIndex"}, 101 {93, nullptr, "GetMainApplicationProgramIndex"},
102 {94, nullptr, "LaunchApplication2"}, 102 {94, nullptr, "LaunchApplication"},
103 {95, nullptr, "GetApplicationLaunchInfo"}, 103 {95, nullptr, "GetApplicationLaunchInfo"},
104 {96, nullptr, "AcquireApplicationLaunchInfo"}, 104 {96, nullptr, "AcquireApplicationLaunchInfo"},
105 {97, nullptr, "GetMainApplicationProgramIndex2"}, 105 {97, nullptr, "GetMainApplicationProgramIndex2"},
@@ -163,7 +163,7 @@ public:
163 {907, nullptr, "WithdrawApplicationUpdateRequest"}, 163 {907, nullptr, "WithdrawApplicationUpdateRequest"},
164 {908, nullptr, "ListApplicationRecordInstalledContentMeta"}, 164 {908, nullptr, "ListApplicationRecordInstalledContentMeta"},
165 {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"}, 165 {909, nullptr, "WithdrawCleanupAddOnContentsWithNoRightsRecommendation"},
166 {910, nullptr, "Unknown3"}, 166 {910, nullptr, "HasApplicationRecord"},
167 {911, nullptr, "SetPreInstalledApplication"}, 167 {911, nullptr, "SetPreInstalledApplication"},
168 {912, nullptr, "ClearPreInstalledApplicationFlag"}, 168 {912, nullptr, "ClearPreInstalledApplicationFlag"},
169 {1000, nullptr, "RequestVerifyApplicationDeprecated"}, 169 {1000, nullptr, "RequestVerifyApplicationDeprecated"},
@@ -219,10 +219,10 @@ public:
219 {2015, nullptr, "CompareSystemDeliveryInfo"}, 219 {2015, nullptr, "CompareSystemDeliveryInfo"},
220 {2016, nullptr, "ListNotCommittedContentMeta"}, 220 {2016, nullptr, "ListNotCommittedContentMeta"},
221 {2017, nullptr, "CreateDownloadTask"}, 221 {2017, nullptr, "CreateDownloadTask"},
222 {2018, nullptr, "Unknown4"}, 222 {2018, nullptr, "GetApplicationDeliveryInfoHash"},
223 {2050, nullptr, "Unknown5"}, 223 {2050, nullptr, "GetApplicationRightsOnClient"},
224 {2100, nullptr, "Unknown6"}, 224 {2100, nullptr, "GetApplicationTerminateResult"},
225 {2101, nullptr, "Unknown7"}, 225 {2101, nullptr, "GetRawApplicationTerminateResult"},
226 {2150, nullptr, "CreateRightsEnvironment"}, 226 {2150, nullptr, "CreateRightsEnvironment"},
227 {2151, nullptr, "DestroyRightsEnvironment"}, 227 {2151, nullptr, "DestroyRightsEnvironment"},
228 {2152, nullptr, "ActivateRightsEnvironment"}, 228 {2152, nullptr, "ActivateRightsEnvironment"},
@@ -237,10 +237,10 @@ public:
237 {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"}, 237 {2182, nullptr, "SetActiveRightsContextUsingStateToRightsEnvironment"},
238 {2190, nullptr, "GetRightsEnvironmentHandleForApplication"}, 238 {2190, nullptr, "GetRightsEnvironmentHandleForApplication"},
239 {2199, nullptr, "GetRightsEnvironmentCountForDebug"}, 239 {2199, nullptr, "GetRightsEnvironmentCountForDebug"},
240 {2200, nullptr, "Unknown8"}, 240 {2200, nullptr, "GetGameCardApplicationCopyIdentifier"},
241 {2201, nullptr, "Unknown9"}, 241 {2201, nullptr, "GetInstalledApplicationCopyIdentifier"},
242 {2250, nullptr, "Unknown10"}, 242 {2250, nullptr, "RequestReportActiveELicence"},
243 {2300, nullptr, "Unknown11"}, 243 {2300, nullptr, "ListEventLog"},
244 }; 244 };
245 // clang-format on 245 // clang-format on
246 246
@@ -355,6 +355,7 @@ public:
355 static const FunctionInfo functions[] = { 355 static const FunctionInfo functions[] = {
356 {21, nullptr, "GetApplicationContentPath"}, 356 {21, nullptr, "GetApplicationContentPath"},
357 {23, nullptr, "ResolveApplicationContentPath"}, 357 {23, nullptr, "ResolveApplicationContentPath"},
358 {93, nullptr, "GetRunningApplicationProgramId"},
358 }; 359 };
359 // clang-format on 360 // clang-format on
360 361
@@ -389,6 +390,11 @@ public:
389 // clang-format off 390 // clang-format off
390 static const FunctionInfo functions[] = { 391 static const FunctionInfo functions[] = {
391 {0, nullptr, "RequestLinkDevice"}, 392 {0, nullptr, "RequestLinkDevice"},
393 {1, nullptr, "RequestCleanupAllPreInstalledApplications"},
394 {2, nullptr, "RequestCleanupPreInstalledApplication"},
395 {3, nullptr, "RequestSyncRights"},
396 {4, nullptr, "RequestUnlinkDevice"},
397 {5, nullptr, "RequestRevokeAllELicense"},
392 }; 398 };
393 // clang-format on 399 // clang-format on
394 400
@@ -403,7 +409,7 @@ public:
403 static const FunctionInfo functions[] = { 409 static const FunctionInfo functions[] = {
404 {100, nullptr, "ResetToFactorySettings"}, 410 {100, nullptr, "ResetToFactorySettings"},
405 {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"}, 411 {101, nullptr, "ResetToFactorySettingsWithoutUserSaveData"},
406 {102, nullptr, "ResetToFactorySettingsForRefurbishment "}, 412 {102, nullptr, "ResetToFactorySettingsForRefurbishment"},
407 }; 413 };
408 // clang-format on 414 // clang-format on
409 415
diff --git a/src/core/hle/service/nvflinger/nvflinger.cpp b/src/core/hle/service/nvflinger/nvflinger.cpp
index 6a613aeab..8dfc0df03 100644
--- a/src/core/hle/service/nvflinger/nvflinger.cpp
+++ b/src/core/hle/service/nvflinger/nvflinger.cpp
@@ -5,7 +5,6 @@
5#include <algorithm> 5#include <algorithm>
6#include <optional> 6#include <optional>
7 7
8#include "common/alignment.h"
9#include "common/assert.h" 8#include "common/assert.h"
10#include "common/logging/log.h" 9#include "common/logging/log.h"
11#include "common/microprofile.h" 10#include "common/microprofile.h"
@@ -22,7 +21,6 @@
22#include "core/hle/service/nvflinger/nvflinger.h" 21#include "core/hle/service/nvflinger/nvflinger.h"
23#include "core/perf_stats.h" 22#include "core/perf_stats.h"
24#include "video_core/renderer_base.h" 23#include "video_core/renderer_base.h"
25#include "video_core/video_core.h"
26 24
27namespace Service::NVFlinger { 25namespace Service::NVFlinger {
28 26
@@ -30,12 +28,6 @@ constexpr std::size_t SCREEN_REFRESH_RATE = 60;
30constexpr u64 frame_ticks = static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); 28constexpr u64 frame_ticks = static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE);
31 29
32NVFlinger::NVFlinger() { 30NVFlinger::NVFlinger() {
33 // Add the different displays to the list of displays.
34 displays.emplace_back(0, "Default");
35 displays.emplace_back(1, "External");
36 displays.emplace_back(2, "Edid");
37 displays.emplace_back(3, "Internal");
38
39 // Schedule the screen composition events 31 // Schedule the screen composition events
40 composition_event = 32 composition_event =
41 CoreTiming::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) { 33 CoreTiming::RegisterEvent("ScreenComposition", [this](u64 userdata, int cycles_late) {
@@ -55,13 +47,13 @@ void NVFlinger::SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance) {
55} 47}
56 48
57u64 NVFlinger::OpenDisplay(std::string_view name) { 49u64 NVFlinger::OpenDisplay(std::string_view name) {
58 LOG_WARNING(Service, "Opening display {}", name); 50 LOG_DEBUG(Service, "Opening \"{}\" display", name);
59 51
60 // TODO(Subv): Currently we only support the Default display. 52 // TODO(Subv): Currently we only support the Default display.
61 ASSERT(name == "Default"); 53 ASSERT(name == "Default");
62 54
63 auto itr = std::find_if(displays.begin(), displays.end(), 55 const auto itr = std::find_if(displays.begin(), displays.end(),
64 [&](const Display& display) { return display.name == name; }); 56 [&](const Display& display) { return display.name == name; });
65 57
66 ASSERT(itr != displays.end()); 58 ASSERT(itr != displays.end());
67 59
@@ -69,48 +61,66 @@ u64 NVFlinger::OpenDisplay(std::string_view name) {
69} 61}
70 62
71u64 NVFlinger::CreateLayer(u64 display_id) { 63u64 NVFlinger::CreateLayer(u64 display_id) {
72 auto& display = GetDisplay(display_id); 64 auto& display = FindDisplay(display_id);
73 65
74 ASSERT_MSG(display.layers.empty(), "Only one layer is supported per display at the moment"); 66 ASSERT_MSG(display.layers.empty(), "Only one layer is supported per display at the moment");
75 67
76 u64 layer_id = next_layer_id++; 68 const u64 layer_id = next_layer_id++;
77 u32 buffer_queue_id = next_buffer_queue_id++; 69 const u32 buffer_queue_id = next_buffer_queue_id++;
78 auto buffer_queue = std::make_shared<BufferQueue>(buffer_queue_id, layer_id); 70 auto buffer_queue = std::make_shared<BufferQueue>(buffer_queue_id, layer_id);
79 display.layers.emplace_back(layer_id, buffer_queue); 71 display.layers.emplace_back(layer_id, buffer_queue);
80 buffer_queues.emplace_back(std::move(buffer_queue)); 72 buffer_queues.emplace_back(std::move(buffer_queue));
81 return layer_id; 73 return layer_id;
82} 74}
83 75
84u32 NVFlinger::GetBufferQueueId(u64 display_id, u64 layer_id) { 76u32 NVFlinger::FindBufferQueueId(u64 display_id, u64 layer_id) const {
85 const auto& layer = GetLayer(display_id, layer_id); 77 const auto& layer = FindLayer(display_id, layer_id);
86 return layer.buffer_queue->GetId(); 78 return layer.buffer_queue->GetId();
87} 79}
88 80
89Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) { 81Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) {
90 return GetDisplay(display_id).vsync_event.readable; 82 return FindDisplay(display_id).vsync_event.readable;
91} 83}
92 84
93std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const { 85std::shared_ptr<BufferQueue> NVFlinger::FindBufferQueue(u32 id) const {
94 auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(), 86 const auto itr = std::find_if(buffer_queues.begin(), buffer_queues.end(),
95 [&](const auto& queue) { return queue->GetId() == id; }); 87 [&](const auto& queue) { return queue->GetId() == id; });
96 88
97 ASSERT(itr != buffer_queues.end()); 89 ASSERT(itr != buffer_queues.end());
98 return *itr; 90 return *itr;
99} 91}
100 92
101Display& NVFlinger::GetDisplay(u64 display_id) { 93Display& NVFlinger::FindDisplay(u64 display_id) {
102 auto itr = std::find_if(displays.begin(), displays.end(), 94 const auto itr = std::find_if(displays.begin(), displays.end(),
103 [&](const Display& display) { return display.id == display_id; }); 95 [&](const Display& display) { return display.id == display_id; });
96
97 ASSERT(itr != displays.end());
98 return *itr;
99}
100
101const Display& NVFlinger::FindDisplay(u64 display_id) const {
102 const auto itr = std::find_if(displays.begin(), displays.end(),
103 [&](const Display& display) { return display.id == display_id; });
104 104
105 ASSERT(itr != displays.end()); 105 ASSERT(itr != displays.end());
106 return *itr; 106 return *itr;
107} 107}
108 108
109Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) { 109Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) {
110 auto& display = GetDisplay(display_id); 110 auto& display = FindDisplay(display_id);
111
112 const auto itr = std::find_if(display.layers.begin(), display.layers.end(),
113 [&](const Layer& layer) { return layer.id == layer_id; });
114
115 ASSERT(itr != display.layers.end());
116 return *itr;
117}
118
119const Layer& NVFlinger::FindLayer(u64 display_id, u64 layer_id) const {
120 const auto& display = FindDisplay(display_id);
111 121
112 auto itr = std::find_if(display.layers.begin(), display.layers.end(), 122 const auto itr = std::find_if(display.layers.begin(), display.layers.end(),
113 [&](const Layer& layer) { return layer.id == layer_id; }); 123 [&](const Layer& layer) { return layer.id == layer_id; });
114 124
115 ASSERT(itr != display.layers.end()); 125 ASSERT(itr != display.layers.end());
116 return *itr; 126 return *itr;
@@ -145,7 +155,7 @@ void NVFlinger::Compose() {
145 continue; 155 continue;
146 } 156 }
147 157
148 auto& igbp_buffer = buffer->get().igbp_buffer; 158 const auto& igbp_buffer = buffer->get().igbp_buffer;
149 159
150 // Now send the buffer to the GPU for drawing. 160 // Now send the buffer to the GPU for drawing.
151 // TODO(Subv): Support more than just disp0. The display device selection is probably based 161 // TODO(Subv): Support more than just disp0. The display device selection is probably based
diff --git a/src/core/hle/service/nvflinger/nvflinger.h b/src/core/hle/service/nvflinger/nvflinger.h
index 9abba555b..83e974ed3 100644
--- a/src/core/hle/service/nvflinger/nvflinger.h
+++ b/src/core/hle/service/nvflinger/nvflinger.h
@@ -4,6 +4,7 @@
4 4
5#pragma once 5#pragma once
6 6
7#include <array>
7#include <memory> 8#include <memory>
8#include <string> 9#include <string>
9#include <string_view> 10#include <string_view>
@@ -56,35 +57,47 @@ public:
56 /// Sets the NVDrv module instance to use to send buffers to the GPU. 57 /// Sets the NVDrv module instance to use to send buffers to the GPU.
57 void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance); 58 void SetNVDrvInstance(std::shared_ptr<Nvidia::Module> instance);
58 59
59 /// Opens the specified display and returns the id. 60 /// Opens the specified display and returns the ID.
60 u64 OpenDisplay(std::string_view name); 61 u64 OpenDisplay(std::string_view name);
61 62
62 /// Creates a layer on the specified display and returns the layer id. 63 /// Creates a layer on the specified display and returns the layer ID.
63 u64 CreateLayer(u64 display_id); 64 u64 CreateLayer(u64 display_id);
64 65
65 /// Gets the buffer queue id of the specified layer in the specified display. 66 /// Finds the buffer queue ID of the specified layer in the specified display.
66 u32 GetBufferQueueId(u64 display_id, u64 layer_id); 67 u32 FindBufferQueueId(u64 display_id, u64 layer_id) const;
67 68
68 /// Gets the vsync event for the specified display. 69 /// Gets the vsync event for the specified display.
69 Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id); 70 Kernel::SharedPtr<Kernel::ReadableEvent> GetVsyncEvent(u64 display_id);
70 71
71 /// Obtains a buffer queue identified by the id. 72 /// Obtains a buffer queue identified by the ID.
72 std::shared_ptr<BufferQueue> GetBufferQueue(u32 id) const; 73 std::shared_ptr<BufferQueue> FindBufferQueue(u32 id) const;
73 74
74 /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when 75 /// Performs a composition request to the emulated nvidia GPU and triggers the vsync events when
75 /// finished. 76 /// finished.
76 void Compose(); 77 void Compose();
77 78
78private: 79private:
79 /// Returns the display identified by the specified id. 80 /// Finds the display identified by the specified ID.
80 Display& GetDisplay(u64 display_id); 81 Display& FindDisplay(u64 display_id);
81 82
82 /// Returns the layer identified by the specified id in the desired display. 83 /// Finds the display identified by the specified ID.
83 Layer& GetLayer(u64 display_id, u64 layer_id); 84 const Display& FindDisplay(u64 display_id) const;
85
86 /// Finds the layer identified by the specified ID in the desired display.
87 Layer& FindLayer(u64 display_id, u64 layer_id);
88
89 /// Finds the layer identified by the specified ID in the desired display.
90 const Layer& FindLayer(u64 display_id, u64 layer_id) const;
84 91
85 std::shared_ptr<Nvidia::Module> nvdrv; 92 std::shared_ptr<Nvidia::Module> nvdrv;
86 93
87 std::vector<Display> displays; 94 std::array<Display, 5> displays{{
95 {0, "Default"},
96 {1, "External"},
97 {2, "Edid"},
98 {3, "Internal"},
99 {4, "Null"},
100 }};
88 std::vector<std::shared_ptr<BufferQueue>> buffer_queues; 101 std::vector<std::shared_ptr<BufferQueue>> buffer_queues;
89 102
90 /// Id to use for the next layer that is created, this counter is shared among all displays. 103 /// Id to use for the next layer that is created, this counter is shared among all displays.
diff --git a/src/core/hle/service/psc/psc.cpp b/src/core/hle/service/psc/psc.cpp
index 0ba0a4076..53ec6b031 100644
--- a/src/core/hle/service/psc/psc.cpp
+++ b/src/core/hle/service/psc/psc.cpp
@@ -17,13 +17,13 @@ public:
17 explicit PSC_C() : ServiceFramework{"psc:c"} { 17 explicit PSC_C() : ServiceFramework{"psc:c"} {
18 // clang-format off 18 // clang-format off
19 static const FunctionInfo functions[] = { 19 static const FunctionInfo functions[] = {
20 {0, nullptr, "Unknown1"}, 20 {0, nullptr, "Initialize"},
21 {1, nullptr, "Unknown2"}, 21 {1, nullptr, "DispatchRequest"},
22 {2, nullptr, "Unknown3"}, 22 {2, nullptr, "GetResult"},
23 {3, nullptr, "Unknown4"}, 23 {3, nullptr, "GetState"},
24 {4, nullptr, "Unknown5"}, 24 {4, nullptr, "Cancel"},
25 {5, nullptr, "Unknown6"}, 25 {5, nullptr, "PrintModuleInformation"},
26 {6, nullptr, "Unknown7"}, 26 {6, nullptr, "GetModuleInformation"},
27 }; 27 };
28 // clang-format on 28 // clang-format on
29 29
@@ -39,7 +39,8 @@ public:
39 {0, nullptr, "Initialize"}, 39 {0, nullptr, "Initialize"},
40 {1, nullptr, "GetRequest"}, 40 {1, nullptr, "GetRequest"},
41 {2, nullptr, "Acknowledge"}, 41 {2, nullptr, "Acknowledge"},
42 {3, nullptr, "Unknown1"}, 42 {3, nullptr, "Finalize"},
43 {4, nullptr, "AcknowledgeEx"},
43 }; 44 };
44 // clang-format on 45 // clang-format on
45 46
diff --git a/src/core/hle/service/vi/vi.cpp b/src/core/hle/service/vi/vi.cpp
index 0f2c25182..fe08c38f2 100644
--- a/src/core/hle/service/vi/vi.cpp
+++ b/src/core/hle/service/vi/vi.cpp
@@ -524,7 +524,7 @@ private:
524 LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id, 524 LOG_DEBUG(Service_VI, "called. id=0x{:08X} transaction={:X}, flags=0x{:08X}", id,
525 static_cast<u32>(transaction), flags); 525 static_cast<u32>(transaction), flags);
526 526
527 auto buffer_queue = nv_flinger->GetBufferQueue(id); 527 auto buffer_queue = nv_flinger->FindBufferQueue(id);
528 528
529 if (transaction == TransactionId::Connect) { 529 if (transaction == TransactionId::Connect) {
530 IGBPConnectRequestParcel request{ctx.ReadBuffer()}; 530 IGBPConnectRequestParcel request{ctx.ReadBuffer()};
@@ -558,7 +558,7 @@ private:
558 [=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx, 558 [=](Kernel::SharedPtr<Kernel::Thread> thread, Kernel::HLERequestContext& ctx,
559 Kernel::ThreadWakeupReason reason) { 559 Kernel::ThreadWakeupReason reason) {
560 // Repeat TransactParcel DequeueBuffer when a buffer is available 560 // Repeat TransactParcel DequeueBuffer when a buffer is available
561 auto buffer_queue = nv_flinger->GetBufferQueue(id); 561 auto buffer_queue = nv_flinger->FindBufferQueue(id);
562 std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height); 562 std::optional<u32> slot = buffer_queue->DequeueBuffer(width, height);
563 ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer."); 563 ASSERT_MSG(slot != std::nullopt, "Could not dequeue buffer.");
564 564
@@ -628,7 +628,7 @@ private:
628 628
629 LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown); 629 LOG_WARNING(Service_VI, "(STUBBED) called id={}, unknown={:08X}", id, unknown);
630 630
631 const auto buffer_queue = nv_flinger->GetBufferQueue(id); 631 const auto buffer_queue = nv_flinger->FindBufferQueue(id);
632 632
633 // TODO(Subv): Find out what this actually is. 633 // TODO(Subv): Find out what this actually is.
634 IPC::ResponseBuilder rb{ctx, 2, 1}; 634 IPC::ResponseBuilder rb{ctx, 2, 1};
@@ -1044,7 +1044,7 @@ private:
1044 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid); 1044 LOG_DEBUG(Service_VI, "called. layer_id=0x{:016X}, aruid=0x{:016X}", layer_id, aruid);
1045 1045
1046 const u64 display_id = nv_flinger->OpenDisplay(display_name); 1046 const u64 display_id = nv_flinger->OpenDisplay(display_name);
1047 const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); 1047 const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id);
1048 1048
1049 NativeWindow native_window{buffer_queue_id}; 1049 NativeWindow native_window{buffer_queue_id};
1050 IPC::ResponseBuilder rb{ctx, 4}; 1050 IPC::ResponseBuilder rb{ctx, 4};
@@ -1063,7 +1063,7 @@ private:
1063 // TODO(Subv): What's the difference between a Stray and a Managed layer? 1063 // TODO(Subv): What's the difference between a Stray and a Managed layer?
1064 1064
1065 const u64 layer_id = nv_flinger->CreateLayer(display_id); 1065 const u64 layer_id = nv_flinger->CreateLayer(display_id);
1066 const u32 buffer_queue_id = nv_flinger->GetBufferQueueId(display_id, layer_id); 1066 const u32 buffer_queue_id = nv_flinger->FindBufferQueueId(display_id, layer_id);
1067 1067
1068 NativeWindow native_window{buffer_queue_id}; 1068 NativeWindow native_window{buffer_queue_id};
1069 IPC::ResponseBuilder rb{ctx, 6}; 1069 IPC::ResponseBuilder rb{ctx, 6};
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index 509ca117a..6113e17ff 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -87,6 +87,7 @@ add_library(video_core STATIC
87 shader/decode.cpp 87 shader/decode.cpp
88 shader/shader_ir.cpp 88 shader/shader_ir.cpp
89 shader/shader_ir.h 89 shader/shader_ir.h
90 shader/track.cpp
90 surface.cpp 91 surface.cpp
91 surface.h 92 surface.h
92 textures/astc.cpp 93 textures/astc.cpp
diff --git a/src/video_core/dma_pusher.h b/src/video_core/dma_pusher.h
index 16e0697c4..1097e5c49 100644
--- a/src/video_core/dma_pusher.h
+++ b/src/video_core/dma_pusher.h
@@ -83,7 +83,7 @@ private:
83 u32 subchannel; ///< Current subchannel 83 u32 subchannel; ///< Current subchannel
84 u32 method_count; ///< Current method count 84 u32 method_count; ///< Current method count
85 u32 length_pending; ///< Large NI command length pending 85 u32 length_pending; ///< Large NI command length pending
86 bool non_incrementing; ///< Current commands NI flag 86 bool non_incrementing; ///< Current command's NI flag
87 }; 87 };
88 88
89 DmaState dma_state{}; 89 DmaState dma_state{};
diff --git a/src/video_core/engines/shader_bytecode.h b/src/video_core/engines/shader_bytecode.h
index cdef97bc6..9989825f8 100644
--- a/src/video_core/engines/shader_bytecode.h
+++ b/src/video_core/engines/shader_bytecode.h
@@ -208,6 +208,8 @@ enum class UniformType : u64 {
208 SignedShort = 3, 208 SignedShort = 3,
209 Single = 4, 209 Single = 4,
210 Double = 5, 210 Double = 5,
211 Quad = 6,
212 UnsignedQuad = 7,
211}; 213};
212 214
213enum class StoreType : u64 { 215enum class StoreType : u64 {
@@ -785,6 +787,12 @@ union Instruction {
785 } st_l; 787 } st_l;
786 788
787 union { 789 union {
790 BitField<48, 3, UniformType> type;
791 BitField<46, 2, u64> cache_mode;
792 BitField<20, 24, s64> immediate_offset;
793 } ldg;
794
795 union {
788 BitField<0, 3, u64> pred0; 796 BitField<0, 3, u64> pred0;
789 BitField<3, 3, u64> pred3; 797 BitField<3, 3, u64> pred3;
790 BitField<7, 1, u64> abs_a; 798 BitField<7, 1, u64> abs_a;
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 08cf6268f..d3d32a359 100644
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -3,6 +3,8 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include "common/assert.h" 5#include "common/assert.h"
6#include "core/core_timing.h"
7#include "core/memory.h"
6#include "video_core/engines/fermi_2d.h" 8#include "video_core/engines/fermi_2d.h"
7#include "video_core/engines/kepler_memory.h" 9#include "video_core/engines/kepler_memory.h"
8#include "video_core/engines/maxwell_3d.h" 10#include "video_core/engines/maxwell_3d.h"
@@ -124,9 +126,36 @@ u32 DepthFormatBytesPerPixel(DepthFormat format) {
124 } 126 }
125} 127}
126 128
129// Note that, traditionally, methods are treated as 4-byte addressable locations, and hence
130// their numbers are written down multiplied by 4 in Docs. Here we are not multiply by 4.
131// So the values you see in docs might be multiplied by 4.
127enum class BufferMethods { 132enum class BufferMethods {
128 BindObject = 0, 133 BindObject = 0x0,
129 CountBufferMethods = 0x40, 134 Nop = 0x2,
135 SemaphoreAddressHigh = 0x4,
136 SemaphoreAddressLow = 0x5,
137 SemaphoreSequence = 0x6,
138 SemaphoreTrigger = 0x7,
139 NotifyIntr = 0x8,
140 WrcacheFlush = 0x9,
141 Unk28 = 0xA,
142 Unk2c = 0xB,
143 RefCnt = 0x14,
144 SemaphoreAcquire = 0x1A,
145 SemaphoreRelease = 0x1B,
146 Unk70 = 0x1C,
147 Unk74 = 0x1D,
148 Unk78 = 0x1E,
149 Unk7c = 0x1F,
150 Yield = 0x20,
151 NonPullerMethods = 0x40,
152};
153
154enum class GpuSemaphoreOperation {
155 AcquireEqual = 0x1,
156 WriteLong = 0x2,
157 AcquireGequal = 0x4,
158 AcquireMask = 0x8,
130}; 159};
131 160
132void GPU::CallMethod(const MethodCall& method_call) { 161void GPU::CallMethod(const MethodCall& method_call) {
@@ -135,20 +164,78 @@ void GPU::CallMethod(const MethodCall& method_call) {
135 164
136 ASSERT(method_call.subchannel < bound_engines.size()); 165 ASSERT(method_call.subchannel < bound_engines.size());
137 166
138 if (method_call.method == static_cast<u32>(BufferMethods::BindObject)) { 167 if (ExecuteMethodOnEngine(method_call)) {
139 // Bind the current subchannel to the desired engine id. 168 CallEngineMethod(method_call);
140 LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel, 169 } else {
141 method_call.argument); 170 CallPullerMethod(method_call);
142 bound_engines[method_call.subchannel] = static_cast<EngineID>(method_call.argument);
143 return;
144 } 171 }
172}
173
174bool GPU::ExecuteMethodOnEngine(const MethodCall& method_call) {
175 const auto method = static_cast<BufferMethods>(method_call.method);
176 return method >= BufferMethods::NonPullerMethods;
177}
145 178
146 if (method_call.method < static_cast<u32>(BufferMethods::CountBufferMethods)) { 179void GPU::CallPullerMethod(const MethodCall& method_call) {
147 // TODO(Subv): Research and implement these methods. 180 regs.reg_array[method_call.method] = method_call.argument;
148 LOG_ERROR(HW_GPU, "Special buffer methods other than Bind are not implemented"); 181 const auto method = static_cast<BufferMethods>(method_call.method);
149 return; 182
183 switch (method) {
184 case BufferMethods::BindObject: {
185 ProcessBindMethod(method_call);
186 break;
187 }
188 case BufferMethods::Nop:
189 case BufferMethods::SemaphoreAddressHigh:
190 case BufferMethods::SemaphoreAddressLow:
191 case BufferMethods::SemaphoreSequence:
192 case BufferMethods::RefCnt:
193 break;
194 case BufferMethods::SemaphoreTrigger: {
195 ProcessSemaphoreTriggerMethod();
196 break;
197 }
198 case BufferMethods::NotifyIntr: {
199 // TODO(Kmather73): Research and implement this method.
200 LOG_ERROR(HW_GPU, "Special puller engine method NotifyIntr not implemented");
201 break;
202 }
203 case BufferMethods::WrcacheFlush: {
204 // TODO(Kmather73): Research and implement this method.
205 LOG_ERROR(HW_GPU, "Special puller engine method WrcacheFlush not implemented");
206 break;
207 }
208 case BufferMethods::Unk28: {
209 // TODO(Kmather73): Research and implement this method.
210 LOG_ERROR(HW_GPU, "Special puller engine method Unk28 not implemented");
211 break;
212 }
213 case BufferMethods::Unk2c: {
214 // TODO(Kmather73): Research and implement this method.
215 LOG_ERROR(HW_GPU, "Special puller engine method Unk2c not implemented");
216 break;
217 }
218 case BufferMethods::SemaphoreAcquire: {
219 ProcessSemaphoreAcquire();
220 break;
150 } 221 }
222 case BufferMethods::SemaphoreRelease: {
223 ProcessSemaphoreRelease();
224 break;
225 }
226 case BufferMethods::Yield: {
227 // TODO(Kmather73): Research and implement this method.
228 LOG_ERROR(HW_GPU, "Special puller engine method Yield not implemented");
229 break;
230 }
231 default:
232 LOG_ERROR(HW_GPU, "Special puller engine method {:X} not implemented",
233 static_cast<u32>(method));
234 break;
235 }
236}
151 237
238void GPU::CallEngineMethod(const MethodCall& method_call) {
152 const EngineID engine = bound_engines[method_call.subchannel]; 239 const EngineID engine = bound_engines[method_call.subchannel];
153 240
154 switch (engine) { 241 switch (engine) {
@@ -172,4 +259,76 @@ void GPU::CallMethod(const MethodCall& method_call) {
172 } 259 }
173} 260}
174 261
262void GPU::ProcessBindMethod(const MethodCall& method_call) {
263 // Bind the current subchannel to the desired engine id.
264 LOG_DEBUG(HW_GPU, "Binding subchannel {} to engine {}", method_call.subchannel,
265 method_call.argument);
266 bound_engines[method_call.subchannel] = static_cast<EngineID>(method_call.argument);
267}
268
269void GPU::ProcessSemaphoreTriggerMethod() {
270 const auto semaphoreOperationMask = 0xF;
271 const auto op =
272 static_cast<GpuSemaphoreOperation>(regs.semaphore_trigger & semaphoreOperationMask);
273 if (op == GpuSemaphoreOperation::WriteLong) {
274 auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
275 struct Block {
276 u32 sequence;
277 u32 zeros = 0;
278 u64 timestamp;
279 };
280
281 Block block{};
282 block.sequence = regs.semaphore_sequence;
283 // TODO(Kmather73): Generate a real GPU timestamp and write it here instead of
284 // CoreTiming
285 block.timestamp = CoreTiming::GetTicks();
286 Memory::WriteBlock(*address, &block, sizeof(block));
287 } else {
288 const auto address =
289 memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
290 const u32 word = Memory::Read32(*address);
291 if ((op == GpuSemaphoreOperation::AcquireEqual && word == regs.semaphore_sequence) ||
292 (op == GpuSemaphoreOperation::AcquireGequal &&
293 static_cast<s32>(word - regs.semaphore_sequence) > 0) ||
294 (op == GpuSemaphoreOperation::AcquireMask && (word & regs.semaphore_sequence))) {
295 // Nothing to do in this case
296 } else {
297 regs.acquire_source = true;
298 regs.acquire_value = regs.semaphore_sequence;
299 if (op == GpuSemaphoreOperation::AcquireEqual) {
300 regs.acquire_active = true;
301 regs.acquire_mode = false;
302 } else if (op == GpuSemaphoreOperation::AcquireGequal) {
303 regs.acquire_active = true;
304 regs.acquire_mode = true;
305 } else if (op == GpuSemaphoreOperation::AcquireMask) {
306 // TODO(kemathe) The acquire mask operation waits for a value that, ANDed with
307 // semaphore_sequence, gives a non-0 result
308 LOG_ERROR(HW_GPU, "Invalid semaphore operation AcquireMask not implemented");
309 } else {
310 LOG_ERROR(HW_GPU, "Invalid semaphore operation");
311 }
312 }
313 }
314}
315
316void GPU::ProcessSemaphoreRelease() {
317 const auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
318 Memory::Write32(*address, regs.semaphore_release);
319}
320
321void GPU::ProcessSemaphoreAcquire() {
322 const auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress());
323 const u32 word = Memory::Read32(*address);
324 const auto value = regs.semaphore_acquire;
325 if (word != value) {
326 regs.acquire_active = true;
327 regs.acquire_value = value;
328 // TODO(kemathe73) figure out how to do the acquire_timeout
329 regs.acquire_mode = false;
330 regs.acquire_source = false;
331 }
332}
333
175} // namespace Tegra 334} // namespace Tegra
diff --git a/src/video_core/gpu.h b/src/video_core/gpu.h
index af5ccd1e9..fb8975811 100644
--- a/src/video_core/gpu.h
+++ b/src/video_core/gpu.h
@@ -156,6 +156,46 @@ public:
156 /// Returns a const reference to the GPU DMA pusher. 156 /// Returns a const reference to the GPU DMA pusher.
157 const Tegra::DmaPusher& DmaPusher() const; 157 const Tegra::DmaPusher& DmaPusher() const;
158 158
159 struct Regs {
160 static constexpr size_t NUM_REGS = 0x100;
161
162 union {
163 struct {
164 INSERT_PADDING_WORDS(0x4);
165 struct {
166 u32 address_high;
167 u32 address_low;
168
169 GPUVAddr SmaphoreAddress() const {
170 return static_cast<GPUVAddr>((static_cast<GPUVAddr>(address_high) << 32) |
171 address_low);
172 }
173 } smaphore_address;
174
175 u32 semaphore_sequence;
176 u32 semaphore_trigger;
177 INSERT_PADDING_WORDS(0xC);
178
179 // The puser and the puller share the reference counter, the pusher only has read
180 // access
181 u32 reference_count;
182 INSERT_PADDING_WORDS(0x5);
183
184 u32 semaphore_acquire;
185 u32 semaphore_release;
186 INSERT_PADDING_WORDS(0xE4);
187
188 // Puller state
189 u32 acquire_mode;
190 u32 acquire_source;
191 u32 acquire_active;
192 u32 acquire_timeout;
193 u32 acquire_value;
194 };
195 std::array<u32, NUM_REGS> reg_array;
196 };
197 } regs{};
198
159private: 199private:
160 std::unique_ptr<Tegra::DmaPusher> dma_pusher; 200 std::unique_ptr<Tegra::DmaPusher> dma_pusher;
161 std::unique_ptr<Tegra::MemoryManager> memory_manager; 201 std::unique_ptr<Tegra::MemoryManager> memory_manager;
@@ -173,6 +213,37 @@ private:
173 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma; 213 std::unique_ptr<Engines::MaxwellDMA> maxwell_dma;
174 /// Inline memory engine 214 /// Inline memory engine
175 std::unique_ptr<Engines::KeplerMemory> kepler_memory; 215 std::unique_ptr<Engines::KeplerMemory> kepler_memory;
216
217 void ProcessBindMethod(const MethodCall& method_call);
218 void ProcessSemaphoreTriggerMethod();
219 void ProcessSemaphoreRelease();
220 void ProcessSemaphoreAcquire();
221
222 // Calls a GPU puller method.
223 void CallPullerMethod(const MethodCall& method_call);
224 // Calls a GPU engine method.
225 void CallEngineMethod(const MethodCall& method_call);
226 // Determines where the method should be executed.
227 bool ExecuteMethodOnEngine(const MethodCall& method_call);
176}; 228};
177 229
230#define ASSERT_REG_POSITION(field_name, position) \
231 static_assert(offsetof(GPU::Regs, field_name) == position * 4, \
232 "Field " #field_name " has invalid position")
233
234ASSERT_REG_POSITION(smaphore_address, 0x4);
235ASSERT_REG_POSITION(semaphore_sequence, 0x6);
236ASSERT_REG_POSITION(semaphore_trigger, 0x7);
237ASSERT_REG_POSITION(reference_count, 0x14);
238ASSERT_REG_POSITION(semaphore_acquire, 0x1A);
239ASSERT_REG_POSITION(semaphore_release, 0x1B);
240
241ASSERT_REG_POSITION(acquire_mode, 0x100);
242ASSERT_REG_POSITION(acquire_source, 0x101);
243ASSERT_REG_POSITION(acquire_active, 0x102);
244ASSERT_REG_POSITION(acquire_timeout, 0x103);
245ASSERT_REG_POSITION(acquire_value, 0x104);
246
247#undef ASSERT_REG_POSITION
248
178} // namespace Tegra 249} // namespace Tegra
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h
index ff5310848..4c08bb148 100644
--- a/src/video_core/rasterizer_interface.h
+++ b/src/video_core/rasterizer_interface.h
@@ -49,11 +49,6 @@ public:
49 return false; 49 return false;
50 } 50 }
51 51
52 /// Attempt to use a faster method to fill a region
53 virtual bool AccelerateFill(const void* config) {
54 return false;
55 }
56
57 /// Attempt to use a faster method to display the framebuffer to screen 52 /// Attempt to use a faster method to display the framebuffer to screen
58 virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 53 virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
59 u32 pixel_stride) { 54 u32 pixel_stride) {
diff --git a/src/video_core/renderer_opengl/gl_global_cache.cpp b/src/video_core/renderer_opengl/gl_global_cache.cpp
index 7992b82c4..c7f32feaa 100644
--- a/src/video_core/renderer_opengl/gl_global_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_global_cache.cpp
@@ -4,8 +4,13 @@
4 4
5#include <glad/glad.h> 5#include <glad/glad.h>
6 6
7#include "common/assert.h"
8#include "common/logging/log.h"
9#include "core/core.h"
10#include "core/memory.h"
7#include "video_core/renderer_opengl/gl_global_cache.h" 11#include "video_core/renderer_opengl/gl_global_cache.h"
8#include "video_core/renderer_opengl/gl_rasterizer.h" 12#include "video_core/renderer_opengl/gl_rasterizer.h"
13#include "video_core/renderer_opengl/gl_shader_decompiler.h"
9#include "video_core/renderer_opengl/utils.h" 14#include "video_core/renderer_opengl/utils.h"
10 15
11namespace OpenGL { 16namespace OpenGL {
@@ -18,7 +23,72 @@ CachedGlobalRegion::CachedGlobalRegion(VAddr addr, u32 size) : addr{addr}, size{
18 LabelGLObject(GL_BUFFER, buffer.handle, addr, "GlobalMemory"); 23 LabelGLObject(GL_BUFFER, buffer.handle, addr, "GlobalMemory");
19} 24}
20 25
26void CachedGlobalRegion::Reload(u32 size_) {
27 constexpr auto max_size = static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize);
28
29 size = size_;
30 if (size > max_size) {
31 size = max_size;
32 LOG_CRITICAL(HW_GPU, "Global region size {} exceeded the expected size {}!", size_,
33 max_size);
34 }
35
36 // TODO(Rodrigo): Get rid of Memory::GetPointer with a staging buffer
37 glBindBuffer(GL_SHADER_STORAGE_BUFFER, buffer.handle);
38 glBufferData(GL_SHADER_STORAGE_BUFFER, size, Memory::GetPointer(addr), GL_DYNAMIC_DRAW);
39}
40
41GlobalRegion GlobalRegionCacheOpenGL::TryGetReservedGlobalRegion(VAddr addr, u32 size) const {
42 const auto search{reserve.find(addr)};
43 if (search == reserve.end()) {
44 return {};
45 }
46 return search->second;
47}
48
49GlobalRegion GlobalRegionCacheOpenGL::GetUncachedGlobalRegion(VAddr addr, u32 size) {
50 GlobalRegion region{TryGetReservedGlobalRegion(addr, size)};
51 if (!region) {
52 // No reserved surface available, create a new one and reserve it
53 region = std::make_shared<CachedGlobalRegion>(addr, size);
54 ReserveGlobalRegion(region);
55 }
56 region->Reload(size);
57 return region;
58}
59
60void GlobalRegionCacheOpenGL::ReserveGlobalRegion(const GlobalRegion& region) {
61 reserve[region->GetAddr()] = region;
62}
63
21GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer) 64GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer)
22 : RasterizerCache{rasterizer} {} 65 : RasterizerCache{rasterizer} {}
23 66
67GlobalRegion GlobalRegionCacheOpenGL::GetGlobalRegion(
68 const GLShader::GlobalMemoryEntry& global_region,
69 Tegra::Engines::Maxwell3D::Regs::ShaderStage stage) {
70
71 auto& gpu{Core::System::GetInstance().GPU()};
72 const auto cbufs = gpu.Maxwell3D().state.shader_stages[static_cast<u64>(stage)];
73 const auto cbuf_addr = gpu.MemoryManager().GpuToCpuAddress(
74 cbufs.const_buffers[global_region.GetCbufIndex()].address + global_region.GetCbufOffset());
75 ASSERT(cbuf_addr);
76
77 const auto actual_addr_gpu = Memory::Read64(*cbuf_addr);
78 const auto size = Memory::Read32(*cbuf_addr + 8);
79 const auto actual_addr = gpu.MemoryManager().GpuToCpuAddress(actual_addr_gpu);
80 ASSERT(actual_addr);
81
82 // Look up global region in the cache based on address
83 GlobalRegion region = TryGet(*actual_addr);
84
85 if (!region) {
86 // No global region found - create a new one
87 region = GetUncachedGlobalRegion(*actual_addr, size);
88 Register(region);
89 }
90
91 return region;
92}
93
24} // namespace OpenGL 94} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_global_cache.h b/src/video_core/renderer_opengl/gl_global_cache.h
index 406a735bc..37830bb7c 100644
--- a/src/video_core/renderer_opengl/gl_global_cache.h
+++ b/src/video_core/renderer_opengl/gl_global_cache.h
@@ -5,9 +5,13 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <unordered_map>
9
8#include <glad/glad.h> 10#include <glad/glad.h>
9 11
12#include "common/assert.h"
10#include "common/common_types.h" 13#include "common/common_types.h"
14#include "video_core/engines/maxwell_3d.h"
11#include "video_core/rasterizer_cache.h" 15#include "video_core/rasterizer_cache.h"
12#include "video_core/renderer_opengl/gl_resource_manager.h" 16#include "video_core/renderer_opengl/gl_resource_manager.h"
13 17
@@ -40,6 +44,9 @@ public:
40 return buffer.handle; 44 return buffer.handle;
41 } 45 }
42 46
47 /// Reloads the global region from guest memory
48 void Reload(u32 size_);
49
43 // TODO(Rodrigo): When global memory is written (STG), implement flushing 50 // TODO(Rodrigo): When global memory is written (STG), implement flushing
44 void Flush() override { 51 void Flush() override {
45 UNIMPLEMENTED(); 52 UNIMPLEMENTED();
@@ -55,6 +62,17 @@ private:
55class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> { 62class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> {
56public: 63public:
57 explicit GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer); 64 explicit GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer);
65
66 /// Gets the current specified shader stage program
67 GlobalRegion GetGlobalRegion(const GLShader::GlobalMemoryEntry& descriptor,
68 Tegra::Engines::Maxwell3D::Regs::ShaderStage stage);
69
70private:
71 GlobalRegion TryGetReservedGlobalRegion(VAddr addr, u32 size) const;
72 GlobalRegion GetUncachedGlobalRegion(VAddr addr, u32 size);
73 void ReserveGlobalRegion(const GlobalRegion& region);
74
75 std::unordered_map<VAddr, GlobalRegion> reserve;
58}; 76};
59 77
60} // namespace OpenGL 78} // namespace OpenGL
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp
index 5ea1c7746..e3163389f 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp
@@ -297,10 +297,7 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
297 MICROPROFILE_SCOPE(OpenGL_Shader); 297 MICROPROFILE_SCOPE(OpenGL_Shader);
298 auto& gpu = Core::System::GetInstance().GPU().Maxwell3D(); 298 auto& gpu = Core::System::GetInstance().GPU().Maxwell3D();
299 299
300 // Next available bindpoints to use when uploading the const buffers and textures to the GLSL 300 BaseBindings base_bindings;
301 // shaders. The constbuffer bindpoint starts after the shader stage configuration bind points.
302 u32 current_constbuffer_bindpoint = Tegra::Engines::Maxwell3D::Regs::MaxShaderStage;
303 u32 current_texture_bindpoint = 0;
304 std::array<bool, Maxwell::NumClipDistances> clip_distances{}; 301 std::array<bool, Maxwell::NumClipDistances> clip_distances{};
305 302
306 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) { 303 for (std::size_t index = 0; index < Maxwell::MaxShaderProgram; ++index) {
@@ -324,43 +321,35 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
324 const GLintptr offset = buffer_cache.UploadHostMemory( 321 const GLintptr offset = buffer_cache.UploadHostMemory(
325 &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment)); 322 &ubo, sizeof(ubo), static_cast<std::size_t>(uniform_buffer_alignment));
326 323
327 // Bind the buffer 324 // Bind the emulation info buffer
328 glBindBufferRange(GL_UNIFORM_BUFFER, static_cast<GLuint>(stage), buffer_cache.GetHandle(), 325 glBindBufferRange(GL_UNIFORM_BUFFER, base_bindings.cbuf, buffer_cache.GetHandle(), offset,
329 offset, static_cast<GLsizeiptr>(sizeof(ubo))); 326 static_cast<GLsizeiptr>(sizeof(ubo)));
330 327
331 Shader shader{shader_cache.GetStageProgram(program)}; 328 Shader shader{shader_cache.GetStageProgram(program)};
329 const auto [program_handle, next_bindings] =
330 shader->GetProgramHandle(primitive_mode, base_bindings);
332 331
333 switch (program) { 332 switch (program) {
334 case Maxwell::ShaderProgram::VertexA: 333 case Maxwell::ShaderProgram::VertexA:
335 case Maxwell::ShaderProgram::VertexB: { 334 case Maxwell::ShaderProgram::VertexB:
336 shader_program_manager->UseProgrammableVertexShader( 335 shader_program_manager->UseProgrammableVertexShader(program_handle);
337 shader->GetProgramHandle(primitive_mode));
338 break; 336 break;
339 } 337 case Maxwell::ShaderProgram::Geometry:
340 case Maxwell::ShaderProgram::Geometry: { 338 shader_program_manager->UseProgrammableGeometryShader(program_handle);
341 shader_program_manager->UseProgrammableGeometryShader(
342 shader->GetProgramHandle(primitive_mode));
343 break; 339 break;
344 } 340 case Maxwell::ShaderProgram::Fragment:
345 case Maxwell::ShaderProgram::Fragment: { 341 shader_program_manager->UseProgrammableFragmentShader(program_handle);
346 shader_program_manager->UseProgrammableFragmentShader(
347 shader->GetProgramHandle(primitive_mode));
348 break; 342 break;
349 }
350 default: 343 default:
351 LOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset=0x{:08X}", index, 344 LOG_CRITICAL(HW_GPU, "Unimplemented shader index={}, enable={}, offset=0x{:08X}", index,
352 shader_config.enable.Value(), shader_config.offset); 345 shader_config.enable.Value(), shader_config.offset);
353 UNREACHABLE(); 346 UNREACHABLE();
354 } 347 }
355 348
356 // Configure the const buffers for this shader stage. 349 const auto stage_enum = static_cast<Maxwell::ShaderStage>(stage);
357 current_constbuffer_bindpoint = 350 SetupConstBuffers(stage_enum, shader, program_handle, base_bindings);
358 SetupConstBuffers(static_cast<Maxwell::ShaderStage>(stage), shader, primitive_mode, 351 SetupGlobalRegions(stage_enum, shader, program_handle, base_bindings);
359 current_constbuffer_bindpoint); 352 SetupTextures(stage_enum, shader, program_handle, base_bindings);
360
361 // Configure the textures for this shader stage.
362 current_texture_bindpoint = SetupTextures(static_cast<Maxwell::ShaderStage>(stage), shader,
363 primitive_mode, current_texture_bindpoint);
364 353
365 // Workaround for Intel drivers. 354 // Workaround for Intel drivers.
366 // When a clip distance is enabled but not set in the shader it crops parts of the screen 355 // When a clip distance is enabled but not set in the shader it crops parts of the screen
@@ -375,6 +364,8 @@ void RasterizerOpenGL::SetupShaders(GLenum primitive_mode) {
375 // VertexB was combined with VertexA, so we skip the VertexB iteration 364 // VertexB was combined with VertexA, so we skip the VertexB iteration
376 index++; 365 index++;
377 } 366 }
367
368 base_bindings = next_bindings;
378 } 369 }
379 370
380 SyncClipEnabled(clip_distances); 371 SyncClipEnabled(clip_distances);
@@ -792,11 +783,6 @@ bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs
792 return true; 783 return true;
793} 784}
794 785
795bool RasterizerOpenGL::AccelerateFill(const void* config) {
796 UNREACHABLE();
797 return true;
798}
799
800bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, 786bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config,
801 VAddr framebuffer_addr, u32 pixel_stride) { 787 VAddr framebuffer_addr, u32 pixel_stride) {
802 if (!framebuffer_addr) { 788 if (!framebuffer_addr) {
@@ -926,8 +912,9 @@ void RasterizerOpenGL::SamplerInfo::SyncWithConfig(const Tegra::Texture::TSCEntr
926 } 912 }
927} 913}
928 914
929u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader, 915void RasterizerOpenGL::SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
930 GLenum primitive_mode, u32 current_bindpoint) { 916 const Shader& shader, GLuint program_handle,
917 BaseBindings base_bindings) {
931 MICROPROFILE_SCOPE(OpenGL_UBO); 918 MICROPROFILE_SCOPE(OpenGL_UBO);
932 const auto& gpu = Core::System::GetInstance().GPU(); 919 const auto& gpu = Core::System::GetInstance().GPU();
933 const auto& maxwell3d = gpu.Maxwell3D(); 920 const auto& maxwell3d = gpu.Maxwell3D();
@@ -975,75 +962,73 @@ u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shad
975 size = Common::AlignUp(size, sizeof(GLvec4)); 962 size = Common::AlignUp(size, sizeof(GLvec4));
976 ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big"); 963 ASSERT_MSG(size <= MaxConstbufferSize, "Constbuffer too big");
977 964
978 GLintptr const_buffer_offset = buffer_cache.UploadMemory( 965 const GLintptr const_buffer_offset = buffer_cache.UploadMemory(
979 buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment)); 966 buffer.address, size, static_cast<std::size_t>(uniform_buffer_alignment));
980 967
981 // Now configure the bindpoint of the buffer inside the shader
982 glUniformBlockBinding(shader->GetProgramHandle(primitive_mode),
983 shader->GetProgramResourceIndex(used_buffer),
984 current_bindpoint + bindpoint);
985
986 // Prepare values for multibind 968 // Prepare values for multibind
987 bind_buffers[bindpoint] = buffer_cache.GetHandle(); 969 bind_buffers[bindpoint] = buffer_cache.GetHandle();
988 bind_offsets[bindpoint] = const_buffer_offset; 970 bind_offsets[bindpoint] = const_buffer_offset;
989 bind_sizes[bindpoint] = size; 971 bind_sizes[bindpoint] = size;
990 } 972 }
991 973
992 glBindBuffersRange(GL_UNIFORM_BUFFER, current_bindpoint, static_cast<GLsizei>(entries.size()), 974 // The first binding is reserved for emulation values
975 const GLuint ubo_base_binding = base_bindings.cbuf + 1;
976 glBindBuffersRange(GL_UNIFORM_BUFFER, ubo_base_binding, static_cast<GLsizei>(entries.size()),
993 bind_buffers.data(), bind_offsets.data(), bind_sizes.data()); 977 bind_buffers.data(), bind_offsets.data(), bind_sizes.data());
978}
994 979
995 return current_bindpoint + static_cast<u32>(entries.size()); 980void RasterizerOpenGL::SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
981 const Shader& shader, GLenum primitive_mode,
982 BaseBindings base_bindings) {
983 // TODO(Rodrigo): Use ARB_multi_bind here
984 const auto& entries = shader->GetShaderEntries().global_memory_entries;
985
986 for (u32 bindpoint = 0; bindpoint < static_cast<u32>(entries.size()); ++bindpoint) {
987 const auto& entry = entries[bindpoint];
988 const u32 current_bindpoint = base_bindings.gmem + bindpoint;
989 const auto& region = global_cache.GetGlobalRegion(entry, stage);
990
991 glBindBufferBase(GL_SHADER_STORAGE_BUFFER, current_bindpoint, region->GetBufferHandle());
992 }
996} 993}
997 994
998u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, 995void RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, const Shader& shader,
999 GLenum primitive_mode, u32 current_unit) { 996 GLuint program_handle, BaseBindings base_bindings) {
1000 MICROPROFILE_SCOPE(OpenGL_Texture); 997 MICROPROFILE_SCOPE(OpenGL_Texture);
1001 const auto& gpu = Core::System::GetInstance().GPU(); 998 const auto& gpu = Core::System::GetInstance().GPU();
1002 const auto& maxwell3d = gpu.Maxwell3D(); 999 const auto& maxwell3d = gpu.Maxwell3D();
1003 const auto& entries = shader->GetShaderEntries().samplers; 1000 const auto& entries = shader->GetShaderEntries().samplers;
1004 1001
1005 ASSERT_MSG(current_unit + entries.size() <= std::size(state.texture_units), 1002 ASSERT_MSG(base_bindings.sampler + entries.size() <= std::size(state.texture_units),
1006 "Exceeded the number of active textures."); 1003 "Exceeded the number of active textures.");
1007 1004
1008 for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) { 1005 for (u32 bindpoint = 0; bindpoint < entries.size(); ++bindpoint) {
1009 const auto& entry = entries[bindpoint]; 1006 const auto& entry = entries[bindpoint];
1010 const u32 current_bindpoint = current_unit + bindpoint; 1007 const u32 current_bindpoint = base_bindings.sampler + bindpoint;
1011 1008 auto& unit = state.texture_units[current_bindpoint];
1012 // Bind the uniform to the sampler.
1013
1014 glProgramUniform1i(shader->GetProgramHandle(primitive_mode),
1015 shader->GetUniformLocation(entry), current_bindpoint);
1016 1009
1017 const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset()); 1010 const auto texture = maxwell3d.GetStageTexture(entry.GetStage(), entry.GetOffset());
1018
1019 if (!texture.enabled) { 1011 if (!texture.enabled) {
1020 state.texture_units[current_bindpoint].texture = 0; 1012 unit.texture = 0;
1021 continue; 1013 continue;
1022 } 1014 }
1023 1015
1024 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc); 1016 texture_samplers[current_bindpoint].SyncWithConfig(texture.tsc);
1017
1025 Surface surface = res_cache.GetTextureSurface(texture, entry); 1018 Surface surface = res_cache.GetTextureSurface(texture, entry);
1026 if (surface != nullptr) { 1019 if (surface != nullptr) {
1027 const GLuint handle = 1020 unit.texture =
1028 entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle; 1021 entry.IsArray() ? surface->TextureLayer().handle : surface->Texture().handle;
1029 const GLenum target = entry.IsArray() ? surface->TargetLayer() : surface->Target(); 1022 unit.target = entry.IsArray() ? surface->TargetLayer() : surface->Target();
1030 state.texture_units[current_bindpoint].texture = handle; 1023 unit.swizzle.r = MaxwellToGL::SwizzleSource(texture.tic.x_source);
1031 state.texture_units[current_bindpoint].target = target; 1024 unit.swizzle.g = MaxwellToGL::SwizzleSource(texture.tic.y_source);
1032 state.texture_units[current_bindpoint].swizzle.r = 1025 unit.swizzle.b = MaxwellToGL::SwizzleSource(texture.tic.z_source);
1033 MaxwellToGL::SwizzleSource(texture.tic.x_source); 1026 unit.swizzle.a = MaxwellToGL::SwizzleSource(texture.tic.w_source);
1034 state.texture_units[current_bindpoint].swizzle.g =
1035 MaxwellToGL::SwizzleSource(texture.tic.y_source);
1036 state.texture_units[current_bindpoint].swizzle.b =
1037 MaxwellToGL::SwizzleSource(texture.tic.z_source);
1038 state.texture_units[current_bindpoint].swizzle.a =
1039 MaxwellToGL::SwizzleSource(texture.tic.w_source);
1040 } else { 1027 } else {
1041 // Can occur when texture addr is null or its memory is unmapped/invalid 1028 // Can occur when texture addr is null or its memory is unmapped/invalid
1042 state.texture_units[current_bindpoint].texture = 0; 1029 unit.texture = 0;
1043 } 1030 }
1044 } 1031 }
1045
1046 return current_unit + static_cast<u32>(entries.size());
1047} 1032}
1048 1033
1049void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { 1034void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) {
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h
index f6824c402..7f2bf0f8b 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer.h
@@ -56,7 +56,6 @@ public:
56 void FlushAndInvalidateRegion(VAddr addr, u64 size) override; 56 void FlushAndInvalidateRegion(VAddr addr, u64 size) override;
57 bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src, 57 bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Regs::Surface& src,
58 const Tegra::Engines::Fermi2D::Regs::Surface& dst) override; 58 const Tegra::Engines::Fermi2D::Regs::Surface& dst) override;
59 bool AccelerateFill(const void* config) override;
60 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, 59 bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr,
61 u32 pixel_stride) override; 60 u32 pixel_stride) override;
62 bool AccelerateDrawBatch(bool is_indexed) override; 61 bool AccelerateDrawBatch(bool is_indexed) override;
@@ -129,25 +128,18 @@ private:
129 OpenGLState& current_state, bool use_color_fb = true, bool using_depth_fb = true, 128 OpenGLState& current_state, bool use_color_fb = true, bool using_depth_fb = true,
130 bool preserve_contents = true, std::optional<std::size_t> single_color_target = {}); 129 bool preserve_contents = true, std::optional<std::size_t> single_color_target = {});
131 130
132 /** 131 /// Configures the current constbuffers to use for the draw command.
133 * Configures the current constbuffers to use for the draw command. 132 void SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
134 * @param stage The shader stage to configure buffers for. 133 GLuint program_handle, BaseBindings base_bindings);
135 * @param shader The shader object that contains the specified stage.
136 * @param current_bindpoint The offset at which to start counting new buffer bindpoints.
137 * @returns The next available bindpoint for use in the next shader stage.
138 */
139 u32 SetupConstBuffers(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader,
140 GLenum primitive_mode, u32 current_bindpoint);
141 134
142 /** 135 /// Configures the current global memory entries to use for the draw command.
143 * Configures the current textures to use for the draw command. 136 void SetupGlobalRegions(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage,
144 * @param stage The shader stage to configure textures for. 137 const Shader& shader, GLenum primitive_mode,
145 * @param shader The shader object that contains the specified stage. 138 BaseBindings base_bindings);
146 * @param current_unit The offset at which to start counting unused texture units. 139
147 * @returns The next available bindpoint for use in the next shader stage. 140 /// Configures the current textures to use for the draw command.
148 */ 141 void SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, const Shader& shader,
149 u32 SetupTextures(Tegra::Engines::Maxwell3D::Regs::ShaderStage stage, Shader& shader, 142 GLuint program_handle, BaseBindings base_bindings);
150 GLenum primitive_mode, u32 current_unit);
151 143
152 /// Syncs the viewport and depth range to match the guest state 144 /// Syncs the viewport and depth range to match the guest state
153 void SyncViewport(OpenGLState& current_state); 145 void SyncViewport(OpenGLState& current_state);
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
index a05b8b936..50286432d 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.cpp
@@ -128,6 +128,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
128 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format)); 128 params.height = Common::AlignUp(config.tic.Height(), GetCompressionFactor(params.pixel_format));
129 params.unaligned_height = config.tic.Height(); 129 params.unaligned_height = config.tic.Height();
130 params.target = SurfaceTargetFromTextureType(config.tic.texture_type); 130 params.target = SurfaceTargetFromTextureType(config.tic.texture_type);
131 params.identity = SurfaceClass::Uploaded;
131 132
132 switch (params.target) { 133 switch (params.target) {
133 case SurfaceTarget::Texture1D: 134 case SurfaceTarget::Texture1D:
@@ -167,6 +168,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
167 } 168 }
168 169
169 params.is_layered = SurfaceTargetIsLayered(params.target); 170 params.is_layered = SurfaceTargetIsLayered(params.target);
171 params.is_array = SurfaceTargetIsArray(params.target);
170 params.max_mip_level = config.tic.max_mip_level + 1; 172 params.max_mip_level = config.tic.max_mip_level + 1;
171 params.rt = {}; 173 params.rt = {};
172 174
@@ -194,6 +196,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
194 params.height = config.height; 196 params.height = config.height;
195 params.unaligned_height = config.height; 197 params.unaligned_height = config.height;
196 params.target = SurfaceTarget::Texture2D; 198 params.target = SurfaceTarget::Texture2D;
199 params.identity = SurfaceClass::RenderTarget;
197 params.depth = 1; 200 params.depth = 1;
198 params.max_mip_level = 1; 201 params.max_mip_level = 1;
199 params.is_layered = false; 202 params.is_layered = false;
@@ -229,6 +232,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
229 params.height = zeta_height; 232 params.height = zeta_height;
230 params.unaligned_height = zeta_height; 233 params.unaligned_height = zeta_height;
231 params.target = SurfaceTarget::Texture2D; 234 params.target = SurfaceTarget::Texture2D;
235 params.identity = SurfaceClass::DepthBuffer;
232 params.depth = 1; 236 params.depth = 1;
233 params.max_mip_level = 1; 237 params.max_mip_level = 1;
234 params.is_layered = false; 238 params.is_layered = false;
@@ -257,6 +261,7 @@ std::size_t SurfaceParams::InnerMemorySize(bool force_gl, bool layer_only,
257 params.height = config.height; 261 params.height = config.height;
258 params.unaligned_height = config.height; 262 params.unaligned_height = config.height;
259 params.target = SurfaceTarget::Texture2D; 263 params.target = SurfaceTarget::Texture2D;
264 params.identity = SurfaceClass::Copy;
260 params.depth = 1; 265 params.depth = 1;
261 params.max_mip_level = 1; 266 params.max_mip_level = 1;
262 params.rt = {}; 267 params.rt = {};
@@ -574,8 +579,7 @@ CachedSurface::CachedSurface(const SurfaceParams& params)
574 579
575 ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level); 580 ApplyTextureDefaults(SurfaceTargetToGL(params.target), params.max_mip_level);
576 581
577 LabelGLObject(GL_TEXTURE, texture.handle, params.addr, 582 OpenGL::LabelGLObject(GL_TEXTURE, texture.handle, params.addr, params.IdentityString());
578 SurfaceParams::SurfaceTargetName(params.target));
579 583
580 // Clamp size to mapped GPU memory region 584 // Clamp size to mapped GPU memory region
581 // TODO(bunnei): Super Mario Odyssey maps a 0x40000 byte region and then uses it for a 0x80000 585 // TODO(bunnei): Super Mario Odyssey maps a 0x40000 byte region and then uses it for a 0x80000
@@ -730,7 +734,6 @@ void CachedSurface::FlushGLBuffer() {
730 glPixelStorei(GL_PACK_ROW_LENGTH, 0); 734 glPixelStorei(GL_PACK_ROW_LENGTH, 0);
731 ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer[0], params.pixel_format, params.width, 735 ConvertFormatAsNeeded_FlushGLBuffer(gl_buffer[0], params.pixel_format, params.width,
732 params.height); 736 params.height);
733 ASSERT(params.type != SurfaceType::Fill);
734 const u8* const texture_src_data = Memory::GetPointer(params.addr); 737 const u8* const texture_src_data = Memory::GetPointer(params.addr);
735 ASSERT(texture_src_data); 738 ASSERT(texture_src_data);
736 if (params.is_tiled) { 739 if (params.is_tiled) {
@@ -877,10 +880,13 @@ void CachedSurface::EnsureTextureView() {
877 UNIMPLEMENTED_IF(gl_is_compressed); 880 UNIMPLEMENTED_IF(gl_is_compressed);
878 881
879 const GLenum target{TargetLayer()}; 882 const GLenum target{TargetLayer()};
883 const GLuint num_layers{target == GL_TEXTURE_CUBE_MAP_ARRAY ? 6u : 1u};
884 constexpr GLuint min_layer = 0;
885 constexpr GLuint min_level = 0;
880 886
881 texture_view.Create(); 887 texture_view.Create();
882 glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, 0, 888 glTextureView(texture_view.handle, target, texture.handle, gl_internal_format, min_level,
883 params.max_mip_level, 0, 1); 889 params.max_mip_level, min_layer, num_layers);
884 890
885 OpenGLState cur_state = OpenGLState::GetCurState(); 891 OpenGLState cur_state = OpenGLState::GetCurState();
886 const auto& old_tex = cur_state.texture_units[0]; 892 const auto& old_tex = cur_state.texture_units[0];
@@ -897,9 +903,6 @@ void CachedSurface::EnsureTextureView() {
897 903
898MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); 904MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64));
899void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { 905void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) {
900 if (params.type == SurfaceType::Fill)
901 return;
902
903 MICROPROFILE_SCOPE(OpenGL_TextureUL); 906 MICROPROFILE_SCOPE(OpenGL_TextureUL);
904 907
905 for (u32 i = 0; i < params.max_mip_level; i++) 908 for (u32 i = 0; i < params.max_mip_level; i++)
diff --git a/src/video_core/renderer_opengl/gl_rasterizer_cache.h b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
index 37611c4fc..8d7d6722c 100644
--- a/src/video_core/renderer_opengl/gl_rasterizer_cache.h
+++ b/src/video_core/renderer_opengl/gl_rasterizer_cache.h
@@ -35,6 +35,14 @@ using PixelFormat = VideoCore::Surface::PixelFormat;
35using ComponentType = VideoCore::Surface::ComponentType; 35using ComponentType = VideoCore::Surface::ComponentType;
36 36
37struct SurfaceParams { 37struct SurfaceParams {
38
39 enum class SurfaceClass {
40 Uploaded,
41 RenderTarget,
42 DepthBuffer,
43 Copy,
44 };
45
38 static std::string SurfaceTargetName(SurfaceTarget target) { 46 static std::string SurfaceTargetName(SurfaceTarget target) {
39 switch (target) { 47 switch (target) {
40 case SurfaceTarget::Texture1D: 48 case SurfaceTarget::Texture1D:
@@ -210,6 +218,48 @@ struct SurfaceParams {
210 /// Initializes parameters for caching, should be called after everything has been initialized 218 /// Initializes parameters for caching, should be called after everything has been initialized
211 void InitCacheParameters(Tegra::GPUVAddr gpu_addr); 219 void InitCacheParameters(Tegra::GPUVAddr gpu_addr);
212 220
221 std::string TargetName() const {
222 switch (target) {
223 case SurfaceTarget::Texture1D:
224 return "1D";
225 case SurfaceTarget::Texture2D:
226 return "2D";
227 case SurfaceTarget::Texture3D:
228 return "3D";
229 case SurfaceTarget::Texture1DArray:
230 return "1DArray";
231 case SurfaceTarget::Texture2DArray:
232 return "2DArray";
233 case SurfaceTarget::TextureCubemap:
234 return "Cube";
235 default:
236 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
237 UNREACHABLE();
238 return fmt::format("TUK({})", static_cast<u32>(target));
239 }
240 }
241
242 std::string ClassName() const {
243 switch (identity) {
244 case SurfaceClass::Uploaded:
245 return "UP";
246 case SurfaceClass::RenderTarget:
247 return "RT";
248 case SurfaceClass::DepthBuffer:
249 return "DB";
250 case SurfaceClass::Copy:
251 return "CP";
252 default:
253 LOG_CRITICAL(HW_GPU, "Unimplemented surface_class={}", static_cast<u32>(identity));
254 UNREACHABLE();
255 return fmt::format("CUK({})", static_cast<u32>(identity));
256 }
257 }
258
259 std::string IdentityString() const {
260 return ClassName() + '_' + TargetName() + '_' + (is_tiled ? 'T' : 'L');
261 }
262
213 bool is_tiled; 263 bool is_tiled;
214 u32 block_width; 264 u32 block_width;
215 u32 block_height; 265 u32 block_height;
@@ -223,8 +273,10 @@ struct SurfaceParams {
223 u32 depth; 273 u32 depth;
224 u32 unaligned_height; 274 u32 unaligned_height;
225 SurfaceTarget target; 275 SurfaceTarget target;
276 SurfaceClass identity;
226 u32 max_mip_level; 277 u32 max_mip_level;
227 bool is_layered; 278 bool is_layered;
279 bool is_array;
228 bool srgb_conversion; 280 bool srgb_conversion;
229 // Parameters used for caching 281 // Parameters used for caching
230 VAddr addr; 282 VAddr addr;
@@ -255,6 +307,7 @@ struct SurfaceReserveKey : Common::HashableStruct<OpenGL::SurfaceParams> {
255 static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) { 307 static SurfaceReserveKey Create(const OpenGL::SurfaceParams& params) {
256 SurfaceReserveKey res; 308 SurfaceReserveKey res;
257 res.state = params; 309 res.state = params;
310 res.state.identity = {}; // Ignore the origin of the texture
258 res.state.gpu_addr = {}; // Ignore GPU vaddr in caching 311 res.state.gpu_addr = {}; // Ignore GPU vaddr in caching
259 res.state.rt = {}; // Ignore rt config in caching 312 res.state.rt = {}; // Ignore rt config in caching
260 return res; 313 return res;
@@ -294,7 +347,7 @@ public:
294 } 347 }
295 348
296 const OGLTexture& TextureLayer() { 349 const OGLTexture& TextureLayer() {
297 if (params.is_layered) { 350 if (params.is_array) {
298 return Texture(); 351 return Texture();
299 } 352 }
300 EnsureTextureView(); 353 EnsureTextureView();
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp
index b3aca39af..90eda7814 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp
@@ -34,36 +34,25 @@ static ProgramCode GetShaderCode(VAddr addr) {
34 return program_code; 34 return program_code;
35} 35}
36 36
37/// Helper function to set shader uniform block bindings for a single shader stage 37/// Gets the shader type from a Maxwell program type
38static void SetShaderUniformBlockBinding(GLuint shader, const char* name, 38constexpr GLenum GetShaderType(Maxwell::ShaderProgram program_type) {
39 Maxwell::ShaderStage binding, std::size_t expected_size) { 39 switch (program_type) {
40 const GLuint ub_index = glGetUniformBlockIndex(shader, name); 40 case Maxwell::ShaderProgram::VertexA:
41 if (ub_index == GL_INVALID_INDEX) { 41 case Maxwell::ShaderProgram::VertexB:
42 return; 42 return GL_VERTEX_SHADER;
43 case Maxwell::ShaderProgram::Geometry:
44 return GL_GEOMETRY_SHADER;
45 case Maxwell::ShaderProgram::Fragment:
46 return GL_FRAGMENT_SHADER;
47 default:
48 return GL_NONE;
43 } 49 }
44
45 GLint ub_size = 0;
46 glGetActiveUniformBlockiv(shader, ub_index, GL_UNIFORM_BLOCK_DATA_SIZE, &ub_size);
47 ASSERT_MSG(static_cast<std::size_t>(ub_size) == expected_size,
48 "Uniform block size did not match! Got {}, expected {}", ub_size, expected_size);
49 glUniformBlockBinding(shader, ub_index, static_cast<GLuint>(binding));
50}
51
52/// Sets shader uniform block bindings for an entire shader program
53static void SetShaderUniformBlockBindings(GLuint shader) {
54 SetShaderUniformBlockBinding(shader, "vs_config", Maxwell::ShaderStage::Vertex,
55 sizeof(GLShader::MaxwellUniformData));
56 SetShaderUniformBlockBinding(shader, "gs_config", Maxwell::ShaderStage::Geometry,
57 sizeof(GLShader::MaxwellUniformData));
58 SetShaderUniformBlockBinding(shader, "fs_config", Maxwell::ShaderStage::Fragment,
59 sizeof(GLShader::MaxwellUniformData));
60} 50}
61 51
62CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) 52CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
63 : addr{addr}, program_type{program_type}, setup{GetShaderCode(addr)} { 53 : addr{addr}, program_type{program_type}, setup{GetShaderCode(addr)} {
64 54
65 GLShader::ProgramResult program_result; 55 GLShader::ProgramResult program_result;
66 GLenum gl_type{};
67 56
68 switch (program_type) { 57 switch (program_type) {
69 case Maxwell::ShaderProgram::VertexA: 58 case Maxwell::ShaderProgram::VertexA:
@@ -74,17 +63,14 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
74 case Maxwell::ShaderProgram::VertexB: 63 case Maxwell::ShaderProgram::VertexB:
75 CalculateProperties(); 64 CalculateProperties();
76 program_result = GLShader::GenerateVertexShader(setup); 65 program_result = GLShader::GenerateVertexShader(setup);
77 gl_type = GL_VERTEX_SHADER;
78 break; 66 break;
79 case Maxwell::ShaderProgram::Geometry: 67 case Maxwell::ShaderProgram::Geometry:
80 CalculateProperties(); 68 CalculateProperties();
81 program_result = GLShader::GenerateGeometryShader(setup); 69 program_result = GLShader::GenerateGeometryShader(setup);
82 gl_type = GL_GEOMETRY_SHADER;
83 break; 70 break;
84 case Maxwell::ShaderProgram::Fragment: 71 case Maxwell::ShaderProgram::Fragment:
85 CalculateProperties(); 72 CalculateProperties();
86 program_result = GLShader::GenerateFragmentShader(setup); 73 program_result = GLShader::GenerateFragmentShader(setup);
87 gl_type = GL_FRAGMENT_SHADER;
88 break; 74 break;
89 default: 75 default:
90 LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type)); 76 LOG_CRITICAL(HW_GPU, "Unimplemented program_type={}", static_cast<u32>(program_type));
@@ -92,59 +78,105 @@ CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type)
92 return; 78 return;
93 } 79 }
94 80
81 code = program_result.first;
95 entries = program_result.second; 82 entries = program_result.second;
96 shader_length = entries.shader_length; 83 shader_length = entries.shader_length;
84}
97 85
98 if (program_type != Maxwell::ShaderProgram::Geometry) { 86std::tuple<GLuint, BaseBindings> CachedShader::GetProgramHandle(GLenum primitive_mode,
99 OGLShader shader; 87 BaseBindings base_bindings) {
100 shader.Create(program_result.first.c_str(), gl_type); 88 GLuint handle{};
101 program.Create(true, shader.handle); 89 if (program_type == Maxwell::ShaderProgram::Geometry) {
102 SetShaderUniformBlockBindings(program.handle); 90 handle = GetGeometryShader(primitive_mode, base_bindings);
103 LabelGLObject(GL_PROGRAM, program.handle, addr);
104 } else { 91 } else {
105 // Store shader's code to lazily build it on draw 92 const auto [entry, is_cache_miss] = programs.try_emplace(base_bindings);
106 geometry_programs.code = program_result.first; 93 auto& program = entry->second;
94 if (is_cache_miss) {
95 std::string source = AllocateBindings(base_bindings);
96 source += code;
97
98 OGLShader shader;
99 shader.Create(source.c_str(), GetShaderType(program_type));
100 program.Create(true, shader.handle);
101 LabelGLObject(GL_PROGRAM, program.handle, addr);
102 }
103
104 handle = program.handle;
107 } 105 }
106
107 // Add const buffer and samplers offset reserved by this shader. One UBO binding is reserved for
108 // emulation values
109 base_bindings.cbuf += static_cast<u32>(entries.const_buffers.size()) + 1;
110 base_bindings.gmem += static_cast<u32>(entries.global_memory_entries.size());
111 base_bindings.sampler += static_cast<u32>(entries.samplers.size());
112
113 return {handle, base_bindings};
108} 114}
109 115
110GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { 116std::string CachedShader::AllocateBindings(BaseBindings base_bindings) {
111 const auto search{resource_cache.find(buffer.GetHash())}; 117 std::string code = "#version 430 core\n";
112 if (search == resource_cache.end()) { 118 code += fmt::format("#define EMULATION_UBO_BINDING {}\n", base_bindings.cbuf++);
113 const GLuint index{ 119
114 glGetProgramResourceIndex(program.handle, GL_UNIFORM_BLOCK, buffer.GetName().c_str())}; 120 for (const auto& cbuf : entries.const_buffers) {
115 resource_cache[buffer.GetHash()] = index; 121 code += fmt::format("#define CBUF_BINDING_{} {}\n", cbuf.GetIndex(), base_bindings.cbuf++);
116 return index;
117 } 122 }
118 123
119 return search->second; 124 for (const auto& gmem : entries.global_memory_entries) {
120} 125 code += fmt::format("#define GMEM_BINDING_{}_{} {}\n", gmem.GetCbufIndex(),
126 gmem.GetCbufOffset(), base_bindings.gmem++);
127 }
121 128
122GLint CachedShader::GetUniformLocation(const GLShader::SamplerEntry& sampler) { 129 for (const auto& sampler : entries.samplers) {
123 const auto search{uniform_cache.find(sampler.GetHash())}; 130 code += fmt::format("#define SAMPLER_BINDING_{} {}\n", sampler.GetIndex(),
124 if (search == uniform_cache.end()) { 131 base_bindings.sampler++);
125 const GLint index{glGetUniformLocation(program.handle, sampler.GetName().c_str())};
126 uniform_cache[sampler.GetHash()] = index;
127 return index;
128 } 132 }
129 133
130 return search->second; 134 return code;
135}
136
137GLuint CachedShader::GetGeometryShader(GLenum primitive_mode, BaseBindings base_bindings) {
138 const auto [entry, is_cache_miss] = geometry_programs.try_emplace(base_bindings);
139 auto& programs = entry->second;
140
141 switch (primitive_mode) {
142 case GL_POINTS:
143 return LazyGeometryProgram(programs.points, base_bindings, "points", 1, "ShaderPoints");
144 case GL_LINES:
145 case GL_LINE_STRIP:
146 return LazyGeometryProgram(programs.lines, base_bindings, "lines", 2, "ShaderLines");
147 case GL_LINES_ADJACENCY:
148 case GL_LINE_STRIP_ADJACENCY:
149 return LazyGeometryProgram(programs.lines_adjacency, base_bindings, "lines_adjacency", 4,
150 "ShaderLinesAdjacency");
151 case GL_TRIANGLES:
152 case GL_TRIANGLE_STRIP:
153 case GL_TRIANGLE_FAN:
154 return LazyGeometryProgram(programs.triangles, base_bindings, "triangles", 3,
155 "ShaderTriangles");
156 case GL_TRIANGLES_ADJACENCY:
157 case GL_TRIANGLE_STRIP_ADJACENCY:
158 return LazyGeometryProgram(programs.triangles_adjacency, base_bindings,
159 "triangles_adjacency", 6, "ShaderTrianglesAdjacency");
160 default:
161 UNREACHABLE_MSG("Unknown primitive mode.");
162 return LazyGeometryProgram(programs.points, base_bindings, "points", 1, "ShaderPoints");
163 }
131} 164}
132 165
133GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, 166GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, BaseBindings base_bindings,
134 const std::string& glsl_topology, u32 max_vertices, 167 const std::string& glsl_topology, u32 max_vertices,
135 const std::string& debug_name) { 168 const std::string& debug_name) {
136 if (target_program.handle != 0) { 169 if (target_program.handle != 0) {
137 return target_program.handle; 170 return target_program.handle;
138 } 171 }
139 std::string source = "#version 430 core\n"; 172 std::string source = AllocateBindings(base_bindings);
140 source += "layout (" + glsl_topology + ") in;\n"; 173 source += "layout (" + glsl_topology + ") in;\n";
141 source += "#define MAX_VERTEX_INPUT " + std::to_string(max_vertices) + '\n'; 174 source += "#define MAX_VERTEX_INPUT " + std::to_string(max_vertices) + '\n';
142 source += geometry_programs.code; 175 source += code;
143 176
144 OGLShader shader; 177 OGLShader shader;
145 shader.Create(source.c_str(), GL_GEOMETRY_SHADER); 178 shader.Create(source.c_str(), GL_GEOMETRY_SHADER);
146 target_program.Create(true, shader.handle); 179 target_program.Create(true, shader.handle);
147 SetShaderUniformBlockBindings(target_program.handle);
148 LabelGLObject(GL_PROGRAM, target_program.handle, addr, debug_name); 180 LabelGLObject(GL_PROGRAM, target_program.handle, addr, debug_name);
149 return target_program.handle; 181 return target_program.handle;
150}; 182};
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.h b/src/video_core/renderer_opengl/gl_shader_cache.h
index e0887dd7b..904d15dd0 100644
--- a/src/video_core/renderer_opengl/gl_shader_cache.h
+++ b/src/video_core/renderer_opengl/gl_shader_cache.h
@@ -7,6 +7,9 @@
7#include <array> 7#include <array>
8#include <map> 8#include <map>
9#include <memory> 9#include <memory>
10#include <tuple>
11
12#include <glad/glad.h>
10 13
11#include "common/assert.h" 14#include "common/assert.h"
12#include "common/common_types.h" 15#include "common/common_types.h"
@@ -23,6 +26,16 @@ class RasterizerOpenGL;
23using Shader = std::shared_ptr<CachedShader>; 26using Shader = std::shared_ptr<CachedShader>;
24using Maxwell = Tegra::Engines::Maxwell3D::Regs; 27using Maxwell = Tegra::Engines::Maxwell3D::Regs;
25 28
29struct BaseBindings {
30 u32 cbuf{};
31 u32 gmem{};
32 u32 sampler{};
33
34 bool operator<(const BaseBindings& rhs) const {
35 return std::tie(cbuf, gmem, sampler) < std::tie(rhs.cbuf, rhs.gmem, rhs.sampler);
36 }
37};
38
26class CachedShader final : public RasterizerCacheObject { 39class CachedShader final : public RasterizerCacheObject {
27public: 40public:
28 CachedShader(VAddr addr, Maxwell::ShaderProgram program_type); 41 CachedShader(VAddr addr, Maxwell::ShaderProgram program_type);
@@ -44,70 +57,45 @@ public:
44 } 57 }
45 58
46 /// Gets the GL program handle for the shader 59 /// Gets the GL program handle for the shader
47 GLuint GetProgramHandle(GLenum primitive_mode) { 60 std::tuple<GLuint, BaseBindings> GetProgramHandle(GLenum primitive_mode,
48 if (program_type != Maxwell::ShaderProgram::Geometry) { 61 BaseBindings base_bindings);
49 return program.handle;
50 }
51 switch (primitive_mode) {
52 case GL_POINTS:
53 return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints");
54 case GL_LINES:
55 case GL_LINE_STRIP:
56 return LazyGeometryProgram(geometry_programs.lines, "lines", 2, "ShaderLines");
57 case GL_LINES_ADJACENCY:
58 case GL_LINE_STRIP_ADJACENCY:
59 return LazyGeometryProgram(geometry_programs.lines_adjacency, "lines_adjacency", 4,
60 "ShaderLinesAdjacency");
61 case GL_TRIANGLES:
62 case GL_TRIANGLE_STRIP:
63 case GL_TRIANGLE_FAN:
64 return LazyGeometryProgram(geometry_programs.triangles, "triangles", 3,
65 "ShaderTriangles");
66 case GL_TRIANGLES_ADJACENCY:
67 case GL_TRIANGLE_STRIP_ADJACENCY:
68 return LazyGeometryProgram(geometry_programs.triangles_adjacency, "triangles_adjacency",
69 6, "ShaderTrianglesAdjacency");
70 default:
71 UNREACHABLE_MSG("Unknown primitive mode.");
72 return LazyGeometryProgram(geometry_programs.points, "points", 1, "ShaderPoints");
73 }
74 }
75 62
76 /// Gets the GL program resource location for the specified resource, caching as needed 63private:
77 GLuint GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer); 64 // Geometry programs. These are needed because GLSL needs an input topology but it's not
65 // declared by the hardware. Workaround this issue by generating a different shader per input
66 // topology class.
67 struct GeometryPrograms {
68 OGLProgram points;
69 OGLProgram lines;
70 OGLProgram lines_adjacency;
71 OGLProgram triangles;
72 OGLProgram triangles_adjacency;
73 };
78 74
79 /// Gets the GL uniform location for the specified resource, caching as needed 75 std::string AllocateBindings(BaseBindings base_bindings);
80 GLint GetUniformLocation(const GLShader::SamplerEntry& sampler); 76
77 GLuint GetGeometryShader(GLenum primitive_mode, BaseBindings base_bindings);
81 78
82private:
83 /// Generates a geometry shader or returns one that already exists. 79 /// Generates a geometry shader or returns one that already exists.
84 GLuint LazyGeometryProgram(OGLProgram& target_program, const std::string& glsl_topology, 80 GLuint LazyGeometryProgram(OGLProgram& target_program, BaseBindings base_bindings,
85 u32 max_vertices, const std::string& debug_name); 81 const std::string& glsl_topology, u32 max_vertices,
82 const std::string& debug_name);
86 83
87 void CalculateProperties(); 84 void CalculateProperties();
88 85
89 VAddr addr; 86 VAddr addr{};
90 std::size_t shader_length; 87 std::size_t shader_length{};
91 Maxwell::ShaderProgram program_type; 88 Maxwell::ShaderProgram program_type{};
92 GLShader::ShaderSetup setup; 89 GLShader::ShaderSetup setup;
93 GLShader::ShaderEntries entries; 90 GLShader::ShaderEntries entries;
94 91
95 // Non-geometry program. 92 std::string code;
96 OGLProgram program;
97 93
98 // Geometry programs. These are needed because GLSL needs an input topology but it's not 94 std::map<BaseBindings, OGLProgram> programs;
99 // declared by the hardware. Workaround this issue by generating a different shader per input 95 std::map<BaseBindings, GeometryPrograms> geometry_programs;
100 // topology class.
101 struct {
102 std::string code;
103 OGLProgram points;
104 OGLProgram lines;
105 OGLProgram lines_adjacency;
106 OGLProgram triangles;
107 OGLProgram triangles_adjacency;
108 } geometry_programs;
109 96
110 std::map<u32, GLuint> resource_cache; 97 std::map<u32, GLuint> cbuf_resource_cache;
98 std::map<u32, GLuint> gmem_resource_cache;
111 std::map<u32, GLint> uniform_cache; 99 std::map<u32, GLint> uniform_cache;
112}; 100};
113 101
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
index 3411cf9e6..004245431 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.cpp
@@ -34,6 +34,8 @@ using Operation = const OperationNode&;
34enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 }; 34enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 };
35constexpr u32 MAX_CONSTBUFFER_ELEMENTS = 35constexpr u32 MAX_CONSTBUFFER_ELEMENTS =
36 static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float)); 36 static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float));
37constexpr u32 MAX_GLOBALMEMORY_ELEMENTS =
38 static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float);
37 39
38enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat }; 40enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat };
39 41
@@ -143,6 +145,7 @@ public:
143 DeclareInputAttributes(); 145 DeclareInputAttributes();
144 DeclareOutputAttributes(); 146 DeclareOutputAttributes();
145 DeclareConstantBuffers(); 147 DeclareConstantBuffers();
148 DeclareGlobalMemory();
146 DeclareSamplers(); 149 DeclareSamplers();
147 150
148 code.AddLine("void execute_" + suffix + "() {"); 151 code.AddLine("void execute_" + suffix + "() {");
@@ -190,12 +193,15 @@ public:
190 ShaderEntries GetShaderEntries() const { 193 ShaderEntries GetShaderEntries() const {
191 ShaderEntries entries; 194 ShaderEntries entries;
192 for (const auto& cbuf : ir.GetConstantBuffers()) { 195 for (const auto& cbuf : ir.GetConstantBuffers()) {
193 ConstBufferEntry desc(cbuf.second, stage, GetConstBufferBlock(cbuf.first), cbuf.first); 196 entries.const_buffers.emplace_back(cbuf.second, stage, GetConstBufferBlock(cbuf.first),
194 entries.const_buffers.push_back(desc); 197 cbuf.first);
195 } 198 }
196 for (const auto& sampler : ir.GetSamplers()) { 199 for (const auto& sampler : ir.GetSamplers()) {
197 SamplerEntry desc(sampler, stage, GetSampler(sampler)); 200 entries.samplers.emplace_back(sampler, stage, GetSampler(sampler));
198 entries.samplers.push_back(desc); 201 }
202 for (const auto& gmem : ir.GetGlobalMemoryBases()) {
203 entries.global_memory_entries.emplace_back(gmem.cbuf_index, gmem.cbuf_offset, stage,
204 GetGlobalMemoryBlock(gmem));
199 } 205 }
200 entries.clip_distances = ir.GetClipDistances(); 206 entries.clip_distances = ir.GetClipDistances();
201 entries.shader_length = ir.GetLength(); 207 entries.shader_length = ir.GetLength();
@@ -368,13 +374,26 @@ private:
368 void DeclareConstantBuffers() { 374 void DeclareConstantBuffers() {
369 for (const auto& entry : ir.GetConstantBuffers()) { 375 for (const auto& entry : ir.GetConstantBuffers()) {
370 const auto [index, size] = entry; 376 const auto [index, size] = entry;
371 code.AddLine("layout (std140) uniform " + GetConstBufferBlock(index) + " {"); 377 code.AddLine("layout (std140, binding = CBUF_BINDING_" + std::to_string(index) +
378 ") uniform " + GetConstBufferBlock(index) + " {");
372 code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];"); 379 code.AddLine(" vec4 " + GetConstBuffer(index) + "[MAX_CONSTBUFFER_ELEMENTS];");
373 code.AddLine("};"); 380 code.AddLine("};");
374 code.AddNewLine(); 381 code.AddNewLine();
375 } 382 }
376 } 383 }
377 384
385 void DeclareGlobalMemory() {
386 for (const auto& entry : ir.GetGlobalMemoryBases()) {
387 const std::string binding =
388 fmt::format("GMEM_BINDING_{}_{}", entry.cbuf_index, entry.cbuf_offset);
389 code.AddLine("layout (std430, binding = " + binding + ") buffer " +
390 GetGlobalMemoryBlock(entry) + " {");
391 code.AddLine(" float " + GetGlobalMemory(entry) + "[MAX_GLOBALMEMORY_ELEMENTS];");
392 code.AddLine("};");
393 code.AddNewLine();
394 }
395 }
396
378 void DeclareSamplers() { 397 void DeclareSamplers() {
379 const auto& samplers = ir.GetSamplers(); 398 const auto& samplers = ir.GetSamplers();
380 for (const auto& sampler : samplers) { 399 for (const auto& sampler : samplers) {
@@ -398,7 +417,8 @@ private:
398 if (sampler.IsShadow()) 417 if (sampler.IsShadow())
399 sampler_type += "Shadow"; 418 sampler_type += "Shadow";
400 419
401 code.AddLine("uniform " + sampler_type + ' ' + GetSampler(sampler) + ';'); 420 code.AddLine("layout (binding = SAMPLER_BINDING_" + std::to_string(sampler.GetIndex()) +
421 ") uniform " + sampler_type + ' ' + GetSampler(sampler) + ';');
402 } 422 }
403 if (!samplers.empty()) 423 if (!samplers.empty())
404 code.AddNewLine(); 424 code.AddNewLine();
@@ -538,6 +558,12 @@ private:
538 UNREACHABLE_MSG("Unmanaged offset node type"); 558 UNREACHABLE_MSG("Unmanaged offset node type");
539 } 559 }
540 560
561 } else if (const auto gmem = std::get_if<GmemNode>(node)) {
562 const std::string real = Visit(gmem->GetRealAddress());
563 const std::string base = Visit(gmem->GetBaseAddress());
564 const std::string final_offset = "(ftou(" + real + ") - ftou(" + base + ")) / 4";
565 return fmt::format("{}[{}]", GetGlobalMemory(gmem->GetDescriptor()), final_offset);
566
541 } else if (const auto lmem = std::get_if<LmemNode>(node)) { 567 } else if (const auto lmem = std::get_if<LmemNode>(node)) {
542 return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress())); 568 return fmt::format("{}[ftou({}) / 4]", GetLocalMemory(), Visit(lmem->GetAddress()));
543 569
@@ -1471,6 +1497,15 @@ private:
1471 return GetDeclarationWithSuffix(index, "cbuf"); 1497 return GetDeclarationWithSuffix(index, "cbuf");
1472 } 1498 }
1473 1499
1500 std::string GetGlobalMemory(const GlobalMemoryBase& descriptor) const {
1501 return fmt::format("gmem_{}_{}_{}", descriptor.cbuf_index, descriptor.cbuf_offset, suffix);
1502 }
1503
1504 std::string GetGlobalMemoryBlock(const GlobalMemoryBase& descriptor) const {
1505 return fmt::format("gmem_block_{}_{}_{}", descriptor.cbuf_index, descriptor.cbuf_offset,
1506 suffix);
1507 }
1508
1474 std::string GetConstBufferBlock(u32 index) const { 1509 std::string GetConstBufferBlock(u32 index) const {
1475 return GetDeclarationWithSuffix(index, "cbuf_block"); 1510 return GetDeclarationWithSuffix(index, "cbuf_block");
1476 } 1511 }
@@ -1505,8 +1540,10 @@ private:
1505}; 1540};
1506 1541
1507std::string GetCommonDeclarations() { 1542std::string GetCommonDeclarations() {
1508 return "#define MAX_CONSTBUFFER_ELEMENTS " + std::to_string(MAX_CONSTBUFFER_ELEMENTS) + 1543 const auto cbuf = std::to_string(MAX_CONSTBUFFER_ELEMENTS);
1509 "\n" 1544 const auto gmem = std::to_string(MAX_GLOBALMEMORY_ELEMENTS);
1545 return "#define MAX_CONSTBUFFER_ELEMENTS " + cbuf + "\n" +
1546 "#define MAX_GLOBALMEMORY_ELEMENTS " + gmem + "\n" +
1510 "#define ftoi floatBitsToInt\n" 1547 "#define ftoi floatBitsToInt\n"
1511 "#define ftou floatBitsToUint\n" 1548 "#define ftou floatBitsToUint\n"
1512 "#define itof intBitsToFloat\n" 1549 "#define itof intBitsToFloat\n"
diff --git a/src/video_core/renderer_opengl/gl_shader_decompiler.h b/src/video_core/renderer_opengl/gl_shader_decompiler.h
index 396a560d8..0856a1361 100644
--- a/src/video_core/renderer_opengl/gl_shader_decompiler.h
+++ b/src/video_core/renderer_opengl/gl_shader_decompiler.h
@@ -38,10 +38,6 @@ public:
38 return index; 38 return index;
39 } 39 }
40 40
41 u32 GetHash() const {
42 return (static_cast<u32>(stage) << 16) | index;
43 }
44
45private: 41private:
46 std::string name; 42 std::string name;
47 Maxwell::ShaderStage stage{}; 43 Maxwell::ShaderStage stage{};
@@ -62,18 +58,44 @@ public:
62 return stage; 58 return stage;
63 } 59 }
64 60
65 u32 GetHash() const { 61private:
66 return (static_cast<u32>(stage) << 16) | static_cast<u32>(GetIndex()); 62 std::string name;
63 Maxwell::ShaderStage stage{};
64};
65
66class GlobalMemoryEntry {
67public:
68 explicit GlobalMemoryEntry(u32 cbuf_index, u32 cbuf_offset, Maxwell::ShaderStage stage,
69 std::string name)
70 : cbuf_index{cbuf_index}, cbuf_offset{cbuf_offset}, stage{stage}, name{std::move(name)} {}
71
72 u32 GetCbufIndex() const {
73 return cbuf_index;
74 }
75
76 u32 GetCbufOffset() const {
77 return cbuf_offset;
78 }
79
80 const std::string& GetName() const {
81 return name;
82 }
83
84 Maxwell::ShaderStage GetStage() const {
85 return stage;
67 } 86 }
68 87
69private: 88private:
70 std::string name; 89 u32 cbuf_index{};
90 u32 cbuf_offset{};
71 Maxwell::ShaderStage stage{}; 91 Maxwell::ShaderStage stage{};
92 std::string name;
72}; 93};
73 94
74struct ShaderEntries { 95struct ShaderEntries {
75 std::vector<ConstBufferEntry> const_buffers; 96 std::vector<ConstBufferEntry> const_buffers;
76 std::vector<SamplerEntry> samplers; 97 std::vector<SamplerEntry> samplers;
98 std::vector<GlobalMemoryEntry> global_memory_entries;
77 std::array<bool, Maxwell::NumClipDistances> clip_distances{}; 99 std::array<bool, Maxwell::NumClipDistances> clip_distances{};
78 std::size_t shader_length{}; 100 std::size_t shader_length{};
79}; 101};
diff --git a/src/video_core/renderer_opengl/gl_shader_gen.cpp b/src/video_core/renderer_opengl/gl_shader_gen.cpp
index 446d1a93f..04e1db911 100644
--- a/src/video_core/renderer_opengl/gl_shader_gen.cpp
+++ b/src/video_core/renderer_opengl/gl_shader_gen.cpp
@@ -20,15 +20,14 @@ static constexpr u32 PROGRAM_OFFSET{10};
20ProgramResult GenerateVertexShader(const ShaderSetup& setup) { 20ProgramResult GenerateVertexShader(const ShaderSetup& setup) {
21 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); 21 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
22 22
23 std::string out = "#version 430 core\n"; 23 std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
24 out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
25 out += "// Shader Unique Id: VS" + id + "\n\n"; 24 out += "// Shader Unique Id: VS" + id + "\n\n";
26 out += GetCommonDeclarations(); 25 out += GetCommonDeclarations();
27 26
28 out += R"( 27 out += R"(
29layout (location = 0) out vec4 position; 28layout (location = 0) out vec4 position;
30 29
31layout(std140) uniform vs_config { 30layout (std140, binding = EMULATION_UBO_BINDING) uniform vs_config {
32 vec4 viewport_flip; 31 vec4 viewport_flip;
33 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding 32 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
34 uvec4 alpha_test; 33 uvec4 alpha_test;
@@ -78,7 +77,6 @@ void main() {
78} 77}
79 78
80ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { 79ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
81 // Version is intentionally skipped in shader generation, it's added by the lazy compilation.
82 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); 80 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
83 81
84 std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n"; 82 std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
@@ -89,7 +87,7 @@ ProgramResult GenerateGeometryShader(const ShaderSetup& setup) {
89layout (location = 0) in vec4 gs_position[]; 87layout (location = 0) in vec4 gs_position[];
90layout (location = 0) out vec4 position; 88layout (location = 0) out vec4 position;
91 89
92layout (std140) uniform gs_config { 90layout (std140, binding = EMULATION_UBO_BINDING) uniform gs_config {
93 vec4 viewport_flip; 91 vec4 viewport_flip;
94 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding 92 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
95 uvec4 alpha_test; 93 uvec4 alpha_test;
@@ -112,8 +110,7 @@ void main() {
112ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { 110ProgramResult GenerateFragmentShader(const ShaderSetup& setup) {
113 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier); 111 const std::string id = fmt::format("{:016x}", setup.program.unique_identifier);
114 112
115 std::string out = "#version 430 core\n"; 113 std::string out = "#extension GL_ARB_separate_shader_objects : enable\n\n";
116 out += "#extension GL_ARB_separate_shader_objects : enable\n\n";
117 out += "// Shader Unique Id: FS" + id + "\n\n"; 114 out += "// Shader Unique Id: FS" + id + "\n\n";
118 out += GetCommonDeclarations(); 115 out += GetCommonDeclarations();
119 116
@@ -129,7 +126,7 @@ layout (location = 7) out vec4 FragColor7;
129 126
130layout (location = 0) in vec4 position; 127layout (location = 0) in vec4 position;
131 128
132layout (std140) uniform fs_config { 129layout (std140, binding = EMULATION_UBO_BINDING) uniform fs_config {
133 vec4 viewport_flip; 130 vec4 viewport_flip;
134 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding 131 uvec4 config_pack; // instance_id, flip_stage, y_direction, padding
135 uvec4 alpha_test; 132 uvec4 alpha_test;
diff --git a/src/video_core/shader/decode/memory.cpp b/src/video_core/shader/decode/memory.cpp
index ae71672d6..04cb386b7 100644
--- a/src/video_core/shader/decode/memory.cpp
+++ b/src/video_core/shader/decode/memory.cpp
@@ -4,6 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6#include <vector> 6#include <vector>
7#include <fmt/format.h>
7 8
8#include "common/assert.h" 9#include "common/assert.h"
9#include "common/common_types.h" 10#include "common/common_types.h"
@@ -119,6 +120,54 @@ u32 ShaderIR::DecodeMemory(BasicBlock& bb, const BasicBlock& code, u32 pc) {
119 } 120 }
120 break; 121 break;
121 } 122 }
123 case OpCode::Id::LDG: {
124 const u32 count = [&]() {
125 switch (instr.ldg.type) {
126 case Tegra::Shader::UniformType::Single:
127 return 1;
128 case Tegra::Shader::UniformType::Double:
129 return 2;
130 case Tegra::Shader::UniformType::Quad:
131 case Tegra::Shader::UniformType::UnsignedQuad:
132 return 4;
133 default:
134 UNIMPLEMENTED_MSG("Unimplemented LDG size!");
135 return 1;
136 }
137 }();
138
139 const Node addr_register = GetRegister(instr.gpr8);
140 const Node base_address = TrackCbuf(addr_register, code, static_cast<s64>(code.size()));
141 const auto cbuf = std::get_if<CbufNode>(base_address);
142 ASSERT(cbuf != nullptr);
143 const auto cbuf_offset_imm = std::get_if<ImmediateNode>(cbuf->GetOffset());
144 ASSERT(cbuf_offset_imm != nullptr);
145 const auto cbuf_offset = cbuf_offset_imm->GetValue() * 4;
146
147 bb.push_back(Comment(
148 fmt::format("Base address is c[0x{:x}][0x{:x}]", cbuf->GetIndex(), cbuf_offset)));
149
150 const GlobalMemoryBase descriptor{cbuf->GetIndex(), cbuf_offset};
151 used_global_memory_bases.insert(descriptor);
152
153 const Node immediate_offset =
154 Immediate(static_cast<u32>(instr.ldg.immediate_offset.Value()));
155 const Node base_real_address =
156 Operation(OperationCode::UAdd, NO_PRECISE, immediate_offset, addr_register);
157
158 for (u32 i = 0; i < count; ++i) {
159 const Node it_offset = Immediate(i * 4);
160 const Node real_address =
161 Operation(OperationCode::UAdd, NO_PRECISE, base_real_address, it_offset);
162 const Node gmem = StoreNode(GmemNode(real_address, base_address, descriptor));
163
164 SetTemporal(bb, i, gmem);
165 }
166 for (u32 i = 0; i < count; ++i) {
167 SetRegister(bb, instr.gpr0.Value() + i, GetTemporal(i));
168 }
169 break;
170 }
122 case OpCode::Id::ST_A: { 171 case OpCode::Id::ST_A: {
123 UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex, 172 UNIMPLEMENTED_IF_MSG(instr.gpr8.Value() != Register::ZeroIndex,
124 "Indirect attribute loads are not supported"); 173 "Indirect attribute loads are not supported");
diff --git a/src/video_core/shader/shader_ir.h b/src/video_core/shader/shader_ir.h
index ef8f94480..c4ecb2e3c 100644
--- a/src/video_core/shader/shader_ir.h
+++ b/src/video_core/shader/shader_ir.h
@@ -257,6 +257,15 @@ private:
257 bool is_indirect{}; 257 bool is_indirect{};
258}; 258};
259 259
260struct GlobalMemoryBase {
261 u32 cbuf_index{};
262 u32 cbuf_offset{};
263
264 bool operator<(const GlobalMemoryBase& rhs) const {
265 return std::tie(cbuf_index, cbuf_offset) < std::tie(rhs.cbuf_index, rhs.cbuf_offset);
266 }
267};
268
260struct MetaArithmetic { 269struct MetaArithmetic {
261 bool precise{}; 270 bool precise{};
262}; 271};
@@ -478,14 +487,26 @@ private:
478/// Global memory node 487/// Global memory node
479class GmemNode final { 488class GmemNode final {
480public: 489public:
481 explicit constexpr GmemNode(Node address) : address{address} {} 490 explicit constexpr GmemNode(Node real_address, Node base_address,
491 const GlobalMemoryBase& descriptor)
492 : real_address{real_address}, base_address{base_address}, descriptor{descriptor} {}
482 493
483 Node GetAddress() const { 494 Node GetRealAddress() const {
484 return address; 495 return real_address;
496 }
497
498 Node GetBaseAddress() const {
499 return base_address;
500 }
501
502 const GlobalMemoryBase& GetDescriptor() const {
503 return descriptor;
485 } 504 }
486 505
487private: 506private:
488 const Node address; 507 const Node real_address;
508 const Node base_address;
509 const GlobalMemoryBase descriptor;
489}; 510};
490 511
491/// Commentary, can be dropped 512/// Commentary, can be dropped
@@ -543,6 +564,10 @@ public:
543 return used_clip_distances; 564 return used_clip_distances;
544 } 565 }
545 566
567 const std::set<GlobalMemoryBase>& GetGlobalMemoryBases() const {
568 return used_global_memory_bases;
569 }
570
546 std::size_t GetLength() const { 571 std::size_t GetLength() const {
547 return static_cast<std::size_t>(coverage_end * sizeof(u64)); 572 return static_cast<std::size_t>(coverage_end * sizeof(u64));
548 } 573 }
@@ -734,6 +759,10 @@ private:
734 void WriteLop3Instruction(BasicBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b, 759 void WriteLop3Instruction(BasicBlock& bb, Tegra::Shader::Register dest, Node op_a, Node op_b,
735 Node op_c, Node imm_lut, bool sets_cc); 760 Node op_c, Node imm_lut, bool sets_cc);
736 761
762 Node TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor);
763
764 std::pair<Node, s64> TrackRegister(const GprNode* tracked, const BasicBlock& code, s64 cursor);
765
737 template <typename... T> 766 template <typename... T>
738 Node Operation(OperationCode code, const T*... operands) { 767 Node Operation(OperationCode code, const T*... operands) {
739 return StoreNode(OperationNode(code, operands...)); 768 return StoreNode(OperationNode(code, operands...));
@@ -786,6 +815,7 @@ private:
786 std::map<u32, ConstBuffer> used_cbufs; 815 std::map<u32, ConstBuffer> used_cbufs;
787 std::set<Sampler> used_samplers; 816 std::set<Sampler> used_samplers;
788 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{}; 817 std::array<bool, Tegra::Engines::Maxwell3D::Regs::NumClipDistances> used_clip_distances{};
818 std::set<GlobalMemoryBase> used_global_memory_bases;
789 819
790 Tegra::Shader::Header header; 820 Tegra::Shader::Header header;
791}; 821};
diff --git a/src/video_core/shader/track.cpp b/src/video_core/shader/track.cpp
new file mode 100644
index 000000000..d6d29ee9f
--- /dev/null
+++ b/src/video_core/shader/track.cpp
@@ -0,0 +1,76 @@
1// Copyright 2018 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <algorithm>
6#include <utility>
7#include <variant>
8
9#include "video_core/shader/shader_ir.h"
10
11namespace VideoCommon::Shader {
12
13namespace {
14std::pair<Node, s64> FindOperation(const BasicBlock& code, s64 cursor,
15 OperationCode operation_code) {
16 for (; cursor >= 0; --cursor) {
17 const Node node = code[cursor];
18 if (const auto operation = std::get_if<OperationNode>(node)) {
19 if (operation->GetCode() == operation_code)
20 return {node, cursor};
21 }
22 }
23 return {};
24}
25} // namespace
26
27Node ShaderIR::TrackCbuf(Node tracked, const BasicBlock& code, s64 cursor) {
28 if (const auto cbuf = std::get_if<CbufNode>(tracked)) {
29 // Cbuf found, but it has to be immediate
30 return std::holds_alternative<ImmediateNode>(*cbuf->GetOffset()) ? tracked : nullptr;
31 }
32 if (const auto gpr = std::get_if<GprNode>(tracked)) {
33 if (gpr->GetIndex() == Tegra::Shader::Register::ZeroIndex) {
34 return nullptr;
35 }
36 // Reduce the cursor in one to avoid infinite loops when the instruction sets the same
37 // register that it uses as operand
38 const auto [source, new_cursor] = TrackRegister(gpr, code, cursor - 1);
39 if (!source) {
40 return nullptr;
41 }
42 return TrackCbuf(source, code, new_cursor);
43 }
44 if (const auto operation = std::get_if<OperationNode>(tracked)) {
45 for (std::size_t i = 0; i < operation->GetOperandsCount(); ++i) {
46 if (const auto found = TrackCbuf((*operation)[i], code, cursor)) {
47 // Cbuf found in operand
48 return found;
49 }
50 }
51 return nullptr;
52 }
53 return nullptr;
54}
55
56std::pair<Node, s64> ShaderIR::TrackRegister(const GprNode* tracked, const BasicBlock& code,
57 s64 cursor) {
58 for (; cursor >= 0; --cursor) {
59 const auto [found_node, new_cursor] = FindOperation(code, cursor, OperationCode::Assign);
60 if (!found_node) {
61 return {};
62 }
63 const auto operation = std::get_if<OperationNode>(found_node);
64 ASSERT(operation);
65
66 const auto& target = (*operation)[0];
67 if (const auto gpr_target = std::get_if<GprNode>(target)) {
68 if (gpr_target->GetIndex() == tracked->GetIndex()) {
69 return {(*operation)[1], new_cursor};
70 }
71 }
72 }
73 return {};
74}
75
76} // namespace VideoCommon::Shader
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp
index 1a344229f..2f6612a35 100644
--- a/src/video_core/surface.cpp
+++ b/src/video_core/surface.cpp
@@ -50,6 +50,24 @@ bool SurfaceTargetIsLayered(SurfaceTarget target) {
50 } 50 }
51} 51}
52 52
53bool SurfaceTargetIsArray(SurfaceTarget target) {
54 switch (target) {
55 case SurfaceTarget::Texture1D:
56 case SurfaceTarget::Texture2D:
57 case SurfaceTarget::Texture3D:
58 case SurfaceTarget::TextureCubemap:
59 return false;
60 case SurfaceTarget::Texture1DArray:
61 case SurfaceTarget::Texture2DArray:
62 case SurfaceTarget::TextureCubeArray:
63 return true;
64 default:
65 LOG_CRITICAL(HW_GPU, "Unimplemented surface_target={}", static_cast<u32>(target));
66 UNREACHABLE();
67 return false;
68 }
69}
70
53PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { 71PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) {
54 switch (format) { 72 switch (format) {
55 case Tegra::DepthFormat::S8_Z24_UNORM: 73 case Tegra::DepthFormat::S8_Z24_UNORM:
diff --git a/src/video_core/surface.h b/src/video_core/surface.h
index c2259c3c2..b783e4b27 100644
--- a/src/video_core/surface.h
+++ b/src/video_core/surface.h
@@ -109,8 +109,7 @@ enum class SurfaceType {
109 ColorTexture = 0, 109 ColorTexture = 0,
110 Depth = 1, 110 Depth = 1,
111 DepthStencil = 2, 111 DepthStencil = 2,
112 Fill = 3, 112 Invalid = 3,
113 Invalid = 4,
114}; 113};
115 114
116enum class SurfaceTarget { 115enum class SurfaceTarget {
@@ -441,6 +440,8 @@ SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_t
441 440
442bool SurfaceTargetIsLayered(SurfaceTarget target); 441bool SurfaceTargetIsLayered(SurfaceTarget target);
443 442
443bool SurfaceTargetIsArray(SurfaceTarget target);
444
444PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format); 445PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format);
445 446
446PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format); 447PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format);
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 0c0864742..f50225d5f 100644
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -13,7 +13,6 @@
13#include "core/hle/kernel/readable_event.h" 13#include "core/hle/kernel/readable_event.h"
14#include "core/hle/kernel/scheduler.h" 14#include "core/hle/kernel/scheduler.h"
15#include "core/hle/kernel/thread.h" 15#include "core/hle/kernel/thread.h"
16#include "core/hle/kernel/timer.h"
17#include "core/hle/kernel/wait_object.h" 16#include "core/hle/kernel/wait_object.h"
18#include "core/memory.h" 17#include "core/memory.h"
19 18
@@ -155,8 +154,6 @@ std::unique_ptr<WaitTreeWaitObject> WaitTreeWaitObject::make(const Kernel::WaitO
155 switch (object.GetHandleType()) { 154 switch (object.GetHandleType()) {
156 case Kernel::HandleType::ReadableEvent: 155 case Kernel::HandleType::ReadableEvent:
157 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object)); 156 return std::make_unique<WaitTreeEvent>(static_cast<const Kernel::ReadableEvent&>(object));
158 case Kernel::HandleType::Timer:
159 return std::make_unique<WaitTreeTimer>(static_cast<const Kernel::Timer&>(object));
160 case Kernel::HandleType::Thread: 157 case Kernel::HandleType::Thread:
161 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::Thread&>(object)); 158 return std::make_unique<WaitTreeThread>(static_cast<const Kernel::Thread&>(object));
162 default: 159 default:
@@ -348,23 +345,6 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeEvent::GetChildren() const {
348 return list; 345 return list;
349} 346}
350 347
351WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {}
352WaitTreeTimer::~WaitTreeTimer() = default;
353
354std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeTimer::GetChildren() const {
355 std::vector<std::unique_ptr<WaitTreeItem>> list(WaitTreeWaitObject::GetChildren());
356
357 const auto& timer = static_cast<const Kernel::Timer&>(object);
358
359 list.push_back(std::make_unique<WaitTreeText>(
360 tr("reset type = %1").arg(GetResetTypeQString(timer.GetResetType()))));
361 list.push_back(
362 std::make_unique<WaitTreeText>(tr("initial delay = %1").arg(timer.GetInitialDelay())));
363 list.push_back(
364 std::make_unique<WaitTreeText>(tr("interval delay = %1").arg(timer.GetIntervalDelay())));
365 return list;
366}
367
368WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) 348WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list)
369 : thread_list(list) {} 349 : thread_list(list) {}
370WaitTreeThreadList::~WaitTreeThreadList() = default; 350WaitTreeThreadList::~WaitTreeThreadList() = default;
diff --git a/src/yuzu/debugger/wait_tree.h b/src/yuzu/debugger/wait_tree.h
index e639ef412..365c3dbfe 100644
--- a/src/yuzu/debugger/wait_tree.h
+++ b/src/yuzu/debugger/wait_tree.h
@@ -20,7 +20,6 @@ namespace Kernel {
20class ReadableEvent; 20class ReadableEvent;
21class WaitObject; 21class WaitObject;
22class Thread; 22class Thread;
23class Timer;
24} // namespace Kernel 23} // namespace Kernel
25 24
26class WaitTreeThread; 25class WaitTreeThread;
@@ -150,15 +149,6 @@ public:
150 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; 149 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
151}; 150};
152 151
153class WaitTreeTimer : public WaitTreeWaitObject {
154 Q_OBJECT
155public:
156 explicit WaitTreeTimer(const Kernel::Timer& object);
157 ~WaitTreeTimer() override;
158
159 std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override;
160};
161
162class WaitTreeThreadList : public WaitTreeExpandableItem { 152class WaitTreeThreadList : public WaitTreeExpandableItem {
163 Q_OBJECT 153 Q_OBJECT
164public: 154public: