diff options
Diffstat (limited to 'src')
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 | ||
| 90 | static 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 | |||
| 103 | struct KernelCore::Impl { | 88 | struct 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 | ||
| 201 | SharedPtr<Timer> KernelCore::RetrieveTimerFromCallbackHandleTable(Handle handle) const { | ||
| 202 | return impl->timer_callback_handle_table.Get<Timer>(handle); | ||
| 203 | } | ||
| 204 | |||
| 205 | void KernelCore::AppendNewProcess(SharedPtr<Process> process) { | 171 | void 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 | ||
| 250 | ResultVal<Handle> KernelCore::CreateTimerCallbackHandle(const SharedPtr<Timer>& timer) { | ||
| 251 | return impl->timer_callback_handle_table.Create(timer); | ||
| 252 | } | ||
| 253 | |||
| 254 | CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const { | 216 | CoreTiming::EventType* KernelCore::ThreadWakeupCallbackEventType() const { |
| 255 | return impl->thread_wakeup_event_type; | 217 | return impl->thread_wakeup_event_type; |
| 256 | } | 218 | } |
| 257 | 219 | ||
| 258 | CoreTiming::EventType* KernelCore::TimerCallbackEventType() const { | ||
| 259 | return impl->timer_callback_event_type; | ||
| 260 | } | ||
| 261 | |||
| 262 | Kernel::HandleTable& KernelCore::ThreadWakeupCallbackHandleTable() { | 220 | Kernel::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; | |||
| 22 | class Process; | 22 | class Process; |
| 23 | class ResourceLimit; | 23 | class ResourceLimit; |
| 24 | class Thread; | 24 | class Thread; |
| 25 | class Timer; | ||
| 26 | 25 | ||
| 27 | /// Represents a single instance of the kernel. | 26 | /// Represents a single instance of the kernel. |
| 28 | class KernelCore { | 27 | class 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 | ||
| 47 | void 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 | |||
| 16 | namespace Kernel { | ||
| 17 | |||
| 18 | Timer::Timer(KernelCore& kernel) : WaitObject{kernel} {} | ||
| 19 | Timer::~Timer() = default; | ||
| 20 | |||
| 21 | SharedPtr<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 | |||
| 34 | bool Timer::ShouldWait(Thread* thread) const { | ||
| 35 | return !signaled; | ||
| 36 | } | ||
| 37 | |||
| 38 | void Timer::Acquire(Thread* thread) { | ||
| 39 | ASSERT_MSG(!ShouldWait(thread), "object unavailable!"); | ||
| 40 | |||
| 41 | if (reset_type == ResetType::OneShot) | ||
| 42 | signaled = false; | ||
| 43 | } | ||
| 44 | |||
| 45 | void 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 | |||
| 61 | void Timer::Cancel() { | ||
| 62 | CoreTiming::UnscheduleEvent(kernel.TimerCallbackEventType(), callback_handle); | ||
| 63 | } | ||
| 64 | |||
| 65 | void Timer::Clear() { | ||
| 66 | signaled = false; | ||
| 67 | } | ||
| 68 | |||
| 69 | void Timer::WakeupAllWaitingThreads() { | ||
| 70 | WaitObject::WakeupAllWaitingThreads(); | ||
| 71 | } | ||
| 72 | |||
| 73 | void 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 | |||
| 11 | namespace Kernel { | ||
| 12 | |||
| 13 | class KernelCore; | ||
| 14 | |||
| 15 | class Timer final : public WaitObject { | ||
| 16 | public: | ||
| 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 | |||
| 74 | private: | ||
| 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 { | |||
| 12 | class IAudioIn final : public ServiceFramework<IAudioIn> { | 12 | class IAudioIn final : public ServiceFramework<IAudioIn> { |
| 13 | public: | 13 | public: |
| 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 | ||
| 36 | AudInU::AudInU() : ServiceFramework("audin:u") { | 39 | AudInU::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 { | |||
| 12 | class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { | 12 | class IFinalOutputRecorder final : public ServiceFramework<IFinalOutputRecorder> { |
| 13 | public: | 13 | public: |
| 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 | ||
| 231 | AudRenU::AudRenU() : ServiceFramework("audren:u") { | 231 | AudRenU::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 | ||
| 316 | void AudRenU::GetAudioDevice(Kernel::HLERequestContext& ctx) { | 318 | void 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: | |||
| 20 | private: | 20 | private: |
| 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 | ||
| 41 | private: | 41 | private: |
| 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 | ||
| 70 | private: | 70 | private: |
| 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 | ||
| 120 | private: | 120 | private: |
| 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 | ||
| 219 | private: | 261 | private: |
| 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: | |||
| 627 | FSP_SRV::FSP_SRV() : ServiceFramework("fsp-srv") { | 627 | FSP_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 | ||
| 725 | FSP_SRV::~FSP_SRV() = default; | 733 | FSP_SRV::~FSP_SRV() = default; |
| 726 | 734 | ||
| 727 | void FSP_SRV::Initialize(Kernel::HLERequestContext& ctx) { | 735 | void 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 | ||
| 746 | void FSP_SRV::MountSdCard(Kernel::HLERequestContext& ctx) { | 754 | void 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 | ||
| 756 | void FSP_SRV::CreateSaveData(Kernel::HLERequestContext& ctx) { | 764 | void 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 | ||
| 770 | void FSP_SRV::MountSaveData(Kernel::HLERequestContext& ctx) { | 778 | void 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 | ||
| 794 | void FSP_SRV::OpenReadOnlySaveDataFileSystem(Kernel::HLERequestContext& ctx) { | 802 | void 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 | ||
| 799 | void FSP_SRV::OpenSaveDataInfoReaderBySaveDataSpaceId(Kernel::HLERequestContext& ctx) { | 807 | void 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 | ||
| 884 | void FSP_SRV::OpenRomStorage(Kernel::HLERequestContext& ctx) { | 892 | void 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 | ||
| 21 | private: | 21 | private: |
| 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 | ||
| 27 | namespace Service::NVFlinger { | 25 | namespace Service::NVFlinger { |
| 28 | 26 | ||
| @@ -30,12 +28,6 @@ constexpr std::size_t SCREEN_REFRESH_RATE = 60; | |||
| 30 | constexpr u64 frame_ticks = static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); | 28 | constexpr u64 frame_ticks = static_cast<u64>(CoreTiming::BASE_CLOCK_RATE / SCREEN_REFRESH_RATE); |
| 31 | 29 | ||
| 32 | NVFlinger::NVFlinger() { | 30 | NVFlinger::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 | ||
| 57 | u64 NVFlinger::OpenDisplay(std::string_view name) { | 49 | u64 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 | ||
| 71 | u64 NVFlinger::CreateLayer(u64 display_id) { | 63 | u64 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 | ||
| 84 | u32 NVFlinger::GetBufferQueueId(u64 display_id, u64 layer_id) { | 76 | u32 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 | ||
| 89 | Kernel::SharedPtr<Kernel::ReadableEvent> NVFlinger::GetVsyncEvent(u64 display_id) { | 81 | Kernel::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 | ||
| 93 | std::shared_ptr<BufferQueue> NVFlinger::GetBufferQueue(u32 id) const { | 85 | std::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 | ||
| 101 | Display& NVFlinger::GetDisplay(u64 display_id) { | 93 | Display& 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 | |||
| 101 | const 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 | ||
| 109 | Layer& NVFlinger::GetLayer(u64 display_id, u64 layer_id) { | 109 | Layer& 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 | |||
| 119 | const 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 | ||
| 78 | private: | 79 | private: |
| 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 command’s 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 | ||
| 213 | enum class StoreType : u64 { | 215 | enum 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. | ||
| 127 | enum class BufferMethods { | 132 | enum 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 | |||
| 154 | enum class GpuSemaphoreOperation { | ||
| 155 | AcquireEqual = 0x1, | ||
| 156 | WriteLong = 0x2, | ||
| 157 | AcquireGequal = 0x4, | ||
| 158 | AcquireMask = 0x8, | ||
| 130 | }; | 159 | }; |
| 131 | 160 | ||
| 132 | void GPU::CallMethod(const MethodCall& method_call) { | 161 | void 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 | |||
| 174 | bool 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)) { | 179 | void 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 | ||
| 238 | void 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 | ||
| 262 | void 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 | |||
| 269 | void 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 | |||
| 316 | void GPU::ProcessSemaphoreRelease() { | ||
| 317 | const auto address = memory_manager->GpuToCpuAddress(regs.smaphore_address.SmaphoreAddress()); | ||
| 318 | Memory::Write32(*address, regs.semaphore_release); | ||
| 319 | } | ||
| 320 | |||
| 321 | void 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 | |||
| 159 | private: | 199 | private: |
| 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 | |||
| 234 | ASSERT_REG_POSITION(smaphore_address, 0x4); | ||
| 235 | ASSERT_REG_POSITION(semaphore_sequence, 0x6); | ||
| 236 | ASSERT_REG_POSITION(semaphore_trigger, 0x7); | ||
| 237 | ASSERT_REG_POSITION(reference_count, 0x14); | ||
| 238 | ASSERT_REG_POSITION(semaphore_acquire, 0x1A); | ||
| 239 | ASSERT_REG_POSITION(semaphore_release, 0x1B); | ||
| 240 | |||
| 241 | ASSERT_REG_POSITION(acquire_mode, 0x100); | ||
| 242 | ASSERT_REG_POSITION(acquire_source, 0x101); | ||
| 243 | ASSERT_REG_POSITION(acquire_active, 0x102); | ||
| 244 | ASSERT_REG_POSITION(acquire_timeout, 0x103); | ||
| 245 | ASSERT_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 | ||
| 11 | namespace OpenGL { | 16 | namespace 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 | ||
| 26 | void 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 | |||
| 41 | GlobalRegion 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 | |||
| 49 | GlobalRegion 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 | |||
| 60 | void GlobalRegionCacheOpenGL::ReserveGlobalRegion(const GlobalRegion& region) { | ||
| 61 | reserve[region->GetAddr()] = region; | ||
| 62 | } | ||
| 63 | |||
| 21 | GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer) | 64 | GlobalRegionCacheOpenGL::GlobalRegionCacheOpenGL(RasterizerOpenGL& rasterizer) |
| 22 | : RasterizerCache{rasterizer} {} | 65 | : RasterizerCache{rasterizer} {} |
| 23 | 66 | ||
| 67 | GlobalRegion 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: | |||
| 55 | class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> { | 62 | class GlobalRegionCacheOpenGL final : public RasterizerCache<GlobalRegion> { |
| 56 | public: | 63 | public: |
| 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 | |||
| 70 | private: | ||
| 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 | ||
| 795 | bool RasterizerOpenGL::AccelerateFill(const void* config) { | ||
| 796 | UNREACHABLE(); | ||
| 797 | return true; | ||
| 798 | } | ||
| 799 | |||
| 800 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 786 | bool 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 | ||
| 929 | u32 RasterizerOpenGL::SetupConstBuffers(Maxwell::ShaderStage stage, Shader& shader, | 915 | void 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()); | 980 | void 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 | ||
| 998 | u32 RasterizerOpenGL::SetupTextures(Maxwell::ShaderStage stage, Shader& shader, | 995 | void 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 | ||
| 1049 | void RasterizerOpenGL::SyncViewport(OpenGLState& current_state) { | 1034 | void 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 | ||
| 898 | MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); | 904 | MICROPROFILE_DEFINE(OpenGL_TextureUL, "OpenGL", "Texture Upload", MP_RGB(128, 192, 64)); |
| 899 | void CachedSurface::UploadGLTexture(GLuint read_fb_handle, GLuint draw_fb_handle) { | 905 | void 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; | |||
| 35 | using ComponentType = VideoCore::Surface::ComponentType; | 35 | using ComponentType = VideoCore::Surface::ComponentType; |
| 36 | 36 | ||
| 37 | struct SurfaceParams { | 37 | struct 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 |
| 38 | static void SetShaderUniformBlockBinding(GLuint shader, const char* name, | 38 | constexpr 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 | ||
| 53 | static 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 | ||
| 62 | CachedShader::CachedShader(VAddr addr, Maxwell::ShaderProgram program_type) | 52 | CachedShader::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) { | 86 | std::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 | ||
| 110 | GLuint CachedShader::GetProgramResourceIndex(const GLShader::ConstBufferEntry& buffer) { | 116 | std::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 | ||
| 122 | GLint 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 | |||
| 137 | GLuint 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 | ||
| 133 | GLuint CachedShader::LazyGeometryProgram(OGLProgram& target_program, | 166 | GLuint 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; | |||
| 23 | using Shader = std::shared_ptr<CachedShader>; | 26 | using Shader = std::shared_ptr<CachedShader>; |
| 24 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; | 27 | using Maxwell = Tegra::Engines::Maxwell3D::Regs; |
| 25 | 28 | ||
| 29 | struct 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 | |||
| 26 | class CachedShader final : public RasterizerCacheObject { | 39 | class CachedShader final : public RasterizerCacheObject { |
| 27 | public: | 40 | public: |
| 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 | 63 | private: |
| 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 | ||
| 82 | private: | ||
| 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&; | |||
| 34 | enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 }; | 34 | enum : u32 { POSITION_VARYING_LOCATION = 0, GENERIC_VARYING_START_LOCATION = 1 }; |
| 35 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = | 35 | constexpr u32 MAX_CONSTBUFFER_ELEMENTS = |
| 36 | static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float)); | 36 | static_cast<u32>(RasterizerOpenGL::MaxConstbufferSize) / (4 * sizeof(float)); |
| 37 | constexpr u32 MAX_GLOBALMEMORY_ELEMENTS = | ||
| 38 | static_cast<u32>(RasterizerOpenGL::MaxGlobalMemorySize) / sizeof(float); | ||
| 37 | 39 | ||
| 38 | enum class Type { Bool, Bool2, Float, Int, Uint, HalfFloat }; | 40 | enum 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 | ||
| 1507 | std::string GetCommonDeclarations() { | 1542 | std::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 | |||
| 45 | private: | 41 | private: |
| 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 { | 61 | private: |
| 66 | return (static_cast<u32>(stage) << 16) | static_cast<u32>(GetIndex()); | 62 | std::string name; |
| 63 | Maxwell::ShaderStage stage{}; | ||
| 64 | }; | ||
| 65 | |||
| 66 | class GlobalMemoryEntry { | ||
| 67 | public: | ||
| 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 | ||
| 69 | private: | 88 | private: |
| 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 | ||
| 74 | struct ShaderEntries { | 95 | struct 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}; | |||
| 20 | ProgramResult GenerateVertexShader(const ShaderSetup& setup) { | 20 | ProgramResult 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"( |
| 29 | layout (location = 0) out vec4 position; | 28 | layout (location = 0) out vec4 position; |
| 30 | 29 | ||
| 31 | layout(std140) uniform vs_config { | 30 | layout (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 | ||
| 80 | ProgramResult GenerateGeometryShader(const ShaderSetup& setup) { | 79 | ProgramResult 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) { | |||
| 89 | layout (location = 0) in vec4 gs_position[]; | 87 | layout (location = 0) in vec4 gs_position[]; |
| 90 | layout (location = 0) out vec4 position; | 88 | layout (location = 0) out vec4 position; |
| 91 | 89 | ||
| 92 | layout (std140) uniform gs_config { | 90 | layout (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() { | |||
| 112 | ProgramResult GenerateFragmentShader(const ShaderSetup& setup) { | 110 | ProgramResult 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 | ||
| 130 | layout (location = 0) in vec4 position; | 127 | layout (location = 0) in vec4 position; |
| 131 | 128 | ||
| 132 | layout (std140) uniform fs_config { | 129 | layout (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 | ||
| 260 | struct 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 | |||
| 260 | struct MetaArithmetic { | 269 | struct MetaArithmetic { |
| 261 | bool precise{}; | 270 | bool precise{}; |
| 262 | }; | 271 | }; |
| @@ -478,14 +487,26 @@ private: | |||
| 478 | /// Global memory node | 487 | /// Global memory node |
| 479 | class GmemNode final { | 488 | class GmemNode final { |
| 480 | public: | 489 | public: |
| 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 | ||
| 487 | private: | 506 | private: |
| 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 | |||
| 11 | namespace VideoCommon::Shader { | ||
| 12 | |||
| 13 | namespace { | ||
| 14 | std::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 | |||
| 27 | Node 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 | |||
| 56 | std::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 | ||
| 53 | bool 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 | |||
| 53 | PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format) { | 71 | PixelFormat 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 | ||
| 116 | enum class SurfaceTarget { | 115 | enum class SurfaceTarget { |
| @@ -441,6 +440,8 @@ SurfaceTarget SurfaceTargetFromTextureType(Tegra::Texture::TextureType texture_t | |||
| 441 | 440 | ||
| 442 | bool SurfaceTargetIsLayered(SurfaceTarget target); | 441 | bool SurfaceTargetIsLayered(SurfaceTarget target); |
| 443 | 442 | ||
| 443 | bool SurfaceTargetIsArray(SurfaceTarget target); | ||
| 444 | |||
| 444 | PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format); | 445 | PixelFormat PixelFormatFromDepthFormat(Tegra::DepthFormat format); |
| 445 | 446 | ||
| 446 | PixelFormat PixelFormatFromRenderTargetFormat(Tegra::RenderTargetFormat format); | 447 | PixelFormat 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 | ||
| 351 | WaitTreeTimer::WaitTreeTimer(const Kernel::Timer& object) : WaitTreeWaitObject(object) {} | ||
| 352 | WaitTreeTimer::~WaitTreeTimer() = default; | ||
| 353 | |||
| 354 | std::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 | |||
| 368 | WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) | 348 | WaitTreeThreadList::WaitTreeThreadList(const std::vector<Kernel::SharedPtr<Kernel::Thread>>& list) |
| 369 | : thread_list(list) {} | 349 | : thread_list(list) {} |
| 370 | WaitTreeThreadList::~WaitTreeThreadList() = default; | 350 | WaitTreeThreadList::~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 { | |||
| 20 | class ReadableEvent; | 20 | class ReadableEvent; |
| 21 | class WaitObject; | 21 | class WaitObject; |
| 22 | class Thread; | 22 | class Thread; |
| 23 | class Timer; | ||
| 24 | } // namespace Kernel | 23 | } // namespace Kernel |
| 25 | 24 | ||
| 26 | class WaitTreeThread; | 25 | class 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 | ||
| 153 | class WaitTreeTimer : public WaitTreeWaitObject { | ||
| 154 | Q_OBJECT | ||
| 155 | public: | ||
| 156 | explicit WaitTreeTimer(const Kernel::Timer& object); | ||
| 157 | ~WaitTreeTimer() override; | ||
| 158 | |||
| 159 | std::vector<std::unique_ptr<WaitTreeItem>> GetChildren() const override; | ||
| 160 | }; | ||
| 161 | |||
| 162 | class WaitTreeThreadList : public WaitTreeExpandableItem { | 152 | class WaitTreeThreadList : public WaitTreeExpandableItem { |
| 163 | Q_OBJECT | 153 | Q_OBJECT |
| 164 | public: | 154 | public: |