summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/common/ring_buffer.h21
-rw-r--r--src/core/hle/kernel/k_address_arbiter.cpp84
-rw-r--r--src/core/hle/kernel/svc.cpp247
-rw-r--r--src/core/hle/service/lm/lm.cpp16
-rw-r--r--src/core/hle/service/ns/pl_u.cpp9
-rw-r--r--src/tests/common/ring_buffer.cpp10
-rw-r--r--src/video_core/CMakeLists.txt2
-rw-r--r--src/video_core/morton.cpp0
-rw-r--r--src/video_core/morton.h0
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp2
-rw-r--r--src/yuzu/bootmanager.cpp31
-rw-r--r--src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp26
12 files changed, 266 insertions, 182 deletions
diff --git a/src/common/ring_buffer.h b/src/common/ring_buffer.h
index 138fa0131..4a8d09806 100644
--- a/src/common/ring_buffer.h
+++ b/src/common/ring_buffer.h
@@ -19,15 +19,14 @@ namespace Common {
19/// SPSC ring buffer 19/// SPSC ring buffer
20/// @tparam T Element type 20/// @tparam T Element type
21/// @tparam capacity Number of slots in ring buffer 21/// @tparam capacity Number of slots in ring buffer
22/// @tparam granularity Slot size in terms of number of elements 22template <typename T, std::size_t capacity>
23template <typename T, std::size_t capacity, std::size_t granularity = 1>
24class RingBuffer { 23class RingBuffer {
25 /// A "slot" is made of `granularity` elements of `T`. 24 /// A "slot" is made of a single `T`.
26 static constexpr std::size_t slot_size = granularity * sizeof(T); 25 static constexpr std::size_t slot_size = sizeof(T);
27 // T must be safely memcpy-able and have a trivial default constructor. 26 // T must be safely memcpy-able and have a trivial default constructor.
28 static_assert(std::is_trivial_v<T>); 27 static_assert(std::is_trivial_v<T>);
29 // Ensure capacity is sensible. 28 // Ensure capacity is sensible.
30 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2 / granularity); 29 static_assert(capacity < std::numeric_limits<std::size_t>::max() / 2);
31 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two"); 30 static_assert((capacity & (capacity - 1)) == 0, "capacity must be a power of two");
32 // Ensure lock-free. 31 // Ensure lock-free.
33 static_assert(std::atomic_size_t::is_always_lock_free); 32 static_assert(std::atomic_size_t::is_always_lock_free);
@@ -47,7 +46,7 @@ public:
47 const std::size_t second_copy = push_count - first_copy; 46 const std::size_t second_copy = push_count - first_copy;
48 47
49 const char* in = static_cast<const char*>(new_slots); 48 const char* in = static_cast<const char*>(new_slots);
50 std::memcpy(m_data.data() + pos * granularity, in, first_copy * slot_size); 49 std::memcpy(m_data.data() + pos, in, first_copy * slot_size);
51 in += first_copy * slot_size; 50 in += first_copy * slot_size;
52 std::memcpy(m_data.data(), in, second_copy * slot_size); 51 std::memcpy(m_data.data(), in, second_copy * slot_size);
53 52
@@ -74,7 +73,7 @@ public:
74 const std::size_t second_copy = pop_count - first_copy; 73 const std::size_t second_copy = pop_count - first_copy;
75 74
76 char* out = static_cast<char*>(output); 75 char* out = static_cast<char*>(output);
77 std::memcpy(out, m_data.data() + pos * granularity, first_copy * slot_size); 76 std::memcpy(out, m_data.data() + pos, first_copy * slot_size);
78 out += first_copy * slot_size; 77 out += first_copy * slot_size;
79 std::memcpy(out, m_data.data(), second_copy * slot_size); 78 std::memcpy(out, m_data.data(), second_copy * slot_size);
80 79
@@ -84,9 +83,9 @@ public:
84 } 83 }
85 84
86 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) { 85 std::vector<T> Pop(std::size_t max_slots = ~std::size_t(0)) {
87 std::vector<T> out(std::min(max_slots, capacity) * granularity); 86 std::vector<T> out(std::min(max_slots, capacity));
88 const std::size_t count = Pop(out.data(), out.size() / granularity); 87 const std::size_t count = Pop(out.data(), out.size());
89 out.resize(count * granularity); 88 out.resize(count);
90 return out; 89 return out;
91 } 90 }
92 91
@@ -113,7 +112,7 @@ private:
113 alignas(128) std::atomic_size_t m_write_index{0}; 112 alignas(128) std::atomic_size_t m_write_index{0};
114#endif 113#endif
115 114
116 std::array<T, granularity * capacity> m_data; 115 std::array<T, capacity> m_data;
117}; 116};
118 117
119} // namespace Common 118} // namespace Common
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index f2f497dc4..d0e90fd60 100644
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -118,9 +118,10 @@ ResultCode KAddressArbiter::SignalAndIncrementIfEqual(VAddr addr, s32 value, s32
118 118
119 // Check the userspace value. 119 // Check the userspace value.
120 s32 user_value{}; 120 s32 user_value{};
121 R_UNLESS(UpdateIfEqual(system, std::addressof(user_value), addr, value, value + 1), 121 if (!UpdateIfEqual(system, &user_value, addr, value, value + 1)) {
122 Svc::ResultInvalidCurrentMemory); 122 LOG_ERROR(Kernel, "Invalid current memory!");
123 123 return Svc::ResultInvalidCurrentMemory;
124 }
124 if (user_value != value) { 125 if (user_value != value) {
125 return Svc::ResultInvalidState; 126 return Svc::ResultInvalidState;
126 } 127 }
@@ -146,61 +147,34 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
146 // Perform signaling. 147 // Perform signaling.
147 s32 num_waiters{}; 148 s32 num_waiters{};
148 { 149 {
149 KScopedSchedulerLock sl(kernel); 150 [[maybe_unused]] const KScopedSchedulerLock sl(kernel);
150 151
151 auto it = thread_tree.nfind_light({addr, -1}); 152 auto it = thread_tree.nfind_light({addr, -1});
152 // Determine the updated value. 153 // Determine the updated value.
153 s32 new_value{}; 154 s32 new_value{};
154 if (/*GetTargetFirmware() >= TargetFirmware_7_0_0*/ true) { 155 if (count <= 0) {
155 if (count <= 0) { 156 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
156 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 157 new_value = value - 2;
157 new_value = value - 2;
158 } else {
159 new_value = value + 1;
160 }
161 } else { 158 } else {
162 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) { 159 new_value = value + 1;
163 auto tmp_it = it;
164 s32 tmp_num_waiters{};
165 while ((++tmp_it != thread_tree.end()) &&
166 (tmp_it->GetAddressArbiterKey() == addr)) {
167 if ((tmp_num_waiters++) >= count) {
168 break;
169 }
170 }
171
172 if (tmp_num_waiters < count) {
173 new_value = value - 1;
174 } else {
175 new_value = value;
176 }
177 } else {
178 new_value = value + 1;
179 }
180 } 160 }
181 } else { 161 } else {
182 if (count <= 0) { 162 if (it != thread_tree.end() && it->GetAddressArbiterKey() == addr) {
183 if ((it != thread_tree.end()) && (it->GetAddressArbiterKey() == addr)) {
184 new_value = value - 1;
185 } else {
186 new_value = value + 1;
187 }
188 } else {
189 auto tmp_it = it; 163 auto tmp_it = it;
190 s32 tmp_num_waiters{}; 164 s32 tmp_num_waiters{};
191 while ((tmp_it != thread_tree.end()) && (tmp_it->GetAddressArbiterKey() == addr) && 165 while (++tmp_it != thread_tree.end() && tmp_it->GetAddressArbiterKey() == addr) {
192 (tmp_num_waiters < count + 1)) { 166 if (tmp_num_waiters++ >= count) {
193 ++tmp_num_waiters; 167 break;
194 ++tmp_it; 168 }
195 } 169 }
196 170
197 if (tmp_num_waiters == 0) { 171 if (tmp_num_waiters < count) {
198 new_value = value + 1;
199 } else if (tmp_num_waiters <= count) {
200 new_value = value - 1; 172 new_value = value - 1;
201 } else { 173 } else {
202 new_value = value; 174 new_value = value;
203 } 175 }
176 } else {
177 new_value = value + 1;
204 } 178 }
205 } 179 }
206 180
@@ -208,13 +182,15 @@ ResultCode KAddressArbiter::SignalAndModifyByWaitingCountIfEqual(VAddr addr, s32
208 s32 user_value{}; 182 s32 user_value{};
209 bool succeeded{}; 183 bool succeeded{};
210 if (value != new_value) { 184 if (value != new_value) {
211 succeeded = UpdateIfEqual(system, std::addressof(user_value), addr, value, new_value); 185 succeeded = UpdateIfEqual(system, &user_value, addr, value, new_value);
212 } else { 186 } else {
213 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 187 succeeded = ReadFromUser(system, &user_value, addr);
214 } 188 }
215 189
216 R_UNLESS(succeeded, Svc::ResultInvalidCurrentMemory); 190 if (!succeeded) {
217 191 LOG_ERROR(Kernel, "Invalid current memory!");
192 return Svc::ResultInvalidCurrentMemory;
193 }
218 if (user_value != value) { 194 if (user_value != value) {
219 return Svc::ResultInvalidState; 195 return Svc::ResultInvalidState;
220 } 196 }
@@ -255,9 +231,9 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
255 s32 user_value{}; 231 s32 user_value{};
256 bool succeeded{}; 232 bool succeeded{};
257 if (decrement) { 233 if (decrement) {
258 succeeded = DecrementIfLessThan(system, std::addressof(user_value), addr, value); 234 succeeded = DecrementIfLessThan(system, &user_value, addr, value);
259 } else { 235 } else {
260 succeeded = ReadFromUser(system, std::addressof(user_value), addr); 236 succeeded = ReadFromUser(system, &user_value, addr);
261 } 237 }
262 238
263 if (!succeeded) { 239 if (!succeeded) {
@@ -278,7 +254,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
278 } 254 }
279 255
280 // Set the arbiter. 256 // Set the arbiter.
281 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 257 cur_thread->SetAddressArbiter(&thread_tree, addr);
282 thread_tree.insert(*cur_thread); 258 thread_tree.insert(*cur_thread);
283 cur_thread->SetState(ThreadState::Waiting); 259 cur_thread->SetState(ThreadState::Waiting);
284 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 260 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -299,7 +275,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
299 275
300 // Get the result. 276 // Get the result.
301 KSynchronizationObject* dummy{}; 277 KSynchronizationObject* dummy{};
302 return cur_thread->GetWaitResult(std::addressof(dummy)); 278 return cur_thread->GetWaitResult(&dummy);
303} 279}
304 280
305ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) { 281ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
@@ -320,7 +296,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
320 296
321 // Read the value from userspace. 297 // Read the value from userspace.
322 s32 user_value{}; 298 s32 user_value{};
323 if (!ReadFromUser(system, std::addressof(user_value), addr)) { 299 if (!ReadFromUser(system, &user_value, addr)) {
324 slp.CancelSleep(); 300 slp.CancelSleep();
325 return Svc::ResultInvalidCurrentMemory; 301 return Svc::ResultInvalidCurrentMemory;
326 } 302 }
@@ -338,7 +314,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
338 } 314 }
339 315
340 // Set the arbiter. 316 // Set the arbiter.
341 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 317 cur_thread->SetAddressArbiter(&thread_tree, addr);
342 thread_tree.insert(*cur_thread); 318 thread_tree.insert(*cur_thread);
343 cur_thread->SetState(ThreadState::Waiting); 319 cur_thread->SetState(ThreadState::Waiting);
344 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration); 320 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
@@ -359,7 +335,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
359 335
360 // Get the result. 336 // Get the result.
361 KSynchronizationObject* dummy{}; 337 KSynchronizationObject* dummy{};
362 return cur_thread->GetWaitResult(std::addressof(dummy)); 338 return cur_thread->GetWaitResult(&dummy);
363} 339}
364 340
365} // namespace Kernel 341} // namespace Kernel
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index edf208eff..26650a513 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -368,7 +368,10 @@ static ResultCode GetThreadId(Core::System& system, u64* out_thread_id, Handle t
368 // Get the thread from its handle. 368 // Get the thread from its handle.
369 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 369 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
370 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 370 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
371 R_UNLESS(thread, Svc::ResultInvalidHandle); 371 if (!thread) {
372 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
373 return ResultInvalidHandle;
374 }
372 375
373 // Get the thread's id. 376 // Get the thread's id.
374 *out_thread_id = thread->GetThreadID(); 377 *out_thread_id = thread->GetThreadID();
@@ -478,7 +481,10 @@ static ResultCode CancelSynchronization(Core::System& system, Handle thread_hand
478 // Get the thread from its handle. 481 // Get the thread from its handle.
479 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 482 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
480 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 483 std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
481 R_UNLESS(thread, Svc::ResultInvalidHandle); 484 if (!thread) {
485 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
486 return ResultInvalidHandle;
487 }
482 488
483 // Cancel the thread's wait. 489 // Cancel the thread's wait.
484 thread->WaitCancel(); 490 thread->WaitCancel();
@@ -496,8 +502,15 @@ static ResultCode ArbitrateLock(Core::System& system, Handle thread_handle, VAdd
496 thread_handle, address, tag); 502 thread_handle, address, tag);
497 503
498 // Validate the input address. 504 // Validate the input address.
499 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 505 if (Memory::IsKernelAddress(address)) {
500 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); 506 LOG_ERROR(Kernel_SVC, "Attempting to arbitrate a lock on a kernel address (address={:08X})",
507 address);
508 return ResultInvalidCurrentMemory;
509 }
510 if (!Common::IsAligned(address, sizeof(u32))) {
511 LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
512 return ResultInvalidAddress;
513 }
501 514
502 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag); 515 return system.Kernel().CurrentProcess()->WaitForAddress(thread_handle, address, tag);
503} 516}
@@ -512,8 +525,16 @@ static ResultCode ArbitrateUnlock(Core::System& system, VAddr address) {
512 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address); 525 LOG_TRACE(Kernel_SVC, "called address=0x{:X}", address);
513 526
514 // Validate the input address. 527 // Validate the input address.
515 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 528 if (Memory::IsKernelAddress(address)) {
516 R_UNLESS(Common::IsAligned(address, sizeof(u32)), Svc::ResultInvalidAddress); 529 LOG_ERROR(Kernel_SVC,
530 "Attempting to arbitrate an unlock on a kernel address (address={:08X})",
531 address);
532 return ResultInvalidCurrentMemory;
533 }
534 if (!Common::IsAligned(address, sizeof(u32))) {
535 LOG_ERROR(Kernel_SVC, "Input address must be 4 byte aligned (address: {:08X})", address);
536 return ResultInvalidAddress;
537 }
517 538
518 return system.Kernel().CurrentProcess()->SignalToAddress(address); 539 return system.Kernel().CurrentProcess()->SignalToAddress(address);
519} 540}
@@ -1025,37 +1046,47 @@ static ResultCode UnmapPhysicalMemory32(Core::System& system, u32 addr, u32 size
1025 return UnmapPhysicalMemory(system, addr, size); 1046 return UnmapPhysicalMemory(system, addr, size);
1026} 1047}
1027 1048
1028constexpr bool IsValidThreadActivity(Svc::ThreadActivity thread_activity) {
1029 switch (thread_activity) {
1030 case Svc::ThreadActivity::Runnable:
1031 case Svc::ThreadActivity::Paused:
1032 return true;
1033 default:
1034 return false;
1035 }
1036}
1037
1038/// Sets the thread activity 1049/// Sets the thread activity
1039static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle, 1050static ResultCode SetThreadActivity(Core::System& system, Handle thread_handle,
1040 Svc::ThreadActivity thread_activity) { 1051 ThreadActivity thread_activity) {
1041 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle, 1052 LOG_DEBUG(Kernel_SVC, "called, handle=0x{:08X}, activity=0x{:08X}", thread_handle,
1042 thread_activity); 1053 thread_activity);
1043 1054
1044 // Validate the activity. 1055 // Validate the activity.
1045 R_UNLESS(IsValidThreadActivity(thread_activity), Svc::ResultInvalidEnumValue); 1056 constexpr auto IsValidThreadActivity = [](ThreadActivity activity) {
1057 return activity == ThreadActivity::Runnable || activity == ThreadActivity::Paused;
1058 };
1059 if (!IsValidThreadActivity(thread_activity)) {
1060 LOG_ERROR(Kernel_SVC, "Invalid thread activity value provided (activity={})",
1061 thread_activity);
1062 return ResultInvalidEnumValue;
1063 }
1046 1064
1047 // Get the thread from its handle. 1065 // Get the thread from its handle.
1048 auto& kernel = system.Kernel(); 1066 auto& kernel = system.Kernel();
1049 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable(); 1067 const auto& handle_table = kernel.CurrentProcess()->GetHandleTable();
1050 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1068 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1051 R_UNLESS(thread, Svc::ResultInvalidHandle); 1069 if (!thread) {
1070 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
1071 return ResultInvalidHandle;
1072 }
1052 1073
1053 // Check that the activity is being set on a non-current thread for the current process. 1074 // Check that the activity is being set on a non-current thread for the current process.
1054 R_UNLESS(thread->GetOwnerProcess() == kernel.CurrentProcess(), Svc::ResultInvalidHandle); 1075 if (thread->GetOwnerProcess() != kernel.CurrentProcess()) {
1055 R_UNLESS(thread.get() != GetCurrentThreadPointer(kernel), Svc::ResultBusy); 1076 LOG_ERROR(Kernel_SVC, "Invalid owning process for the created thread.");
1077 return ResultInvalidHandle;
1078 }
1079 if (thread.get() == GetCurrentThreadPointer(kernel)) {
1080 LOG_ERROR(Kernel_SVC, "Thread is busy");
1081 return ResultBusy;
1082 }
1056 1083
1057 // Set the activity. 1084 // Set the activity.
1058 R_TRY(thread->SetActivity(thread_activity)); 1085 const auto set_result = thread->SetActivity(thread_activity);
1086 if (set_result.IsError()) {
1087 LOG_ERROR(Kernel_SVC, "Failed to set thread activity.");
1088 return set_result;
1089 }
1059 1090
1060 return RESULT_SUCCESS; 1091 return RESULT_SUCCESS;
1061} 1092}
@@ -1074,16 +1105,29 @@ static ResultCode GetThreadContext(Core::System& system, VAddr out_context, Hand
1074 const auto* current_process = system.Kernel().CurrentProcess(); 1105 const auto* current_process = system.Kernel().CurrentProcess();
1075 const std::shared_ptr<KThread> thread = 1106 const std::shared_ptr<KThread> thread =
1076 current_process->GetHandleTable().Get<KThread>(thread_handle); 1107 current_process->GetHandleTable().Get<KThread>(thread_handle);
1077 R_UNLESS(thread, Svc::ResultInvalidHandle); 1108 if (!thread) {
1109 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={})", thread_handle);
1110 return ResultInvalidHandle;
1111 }
1078 1112
1079 // Require the handle be to a non-current thread in the current process. 1113 // Require the handle be to a non-current thread in the current process.
1080 R_UNLESS(thread->GetOwnerProcess() == current_process, Svc::ResultInvalidHandle); 1114 if (thread->GetOwnerProcess() != current_process) {
1081 R_UNLESS(thread.get() != system.Kernel().CurrentScheduler()->GetCurrentThread(), 1115 LOG_ERROR(Kernel_SVC, "Thread owning process is not the current process.");
1082 Svc::ResultBusy); 1116 return ResultInvalidHandle;
1117 }
1118 if (thread.get() == system.Kernel().CurrentScheduler()->GetCurrentThread()) {
1119 LOG_ERROR(Kernel_SVC, "Current thread is busy.");
1120 return ResultBusy;
1121 }
1083 1122
1084 // Get the thread context. 1123 // Get the thread context.
1085 std::vector<u8> context; 1124 std::vector<u8> context;
1086 R_TRY(thread->GetThreadContext3(context)); 1125 const auto context_result = thread->GetThreadContext3(context);
1126 if (context_result.IsError()) {
1127 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve thread context (result: {})",
1128 context_result.raw);
1129 return context_result;
1130 }
1087 1131
1088 // Copy the thread context to user space. 1132 // Copy the thread context to user space.
1089 system.Memory().WriteBlock(out_context, context.data(), context.size()); 1133 system.Memory().WriteBlock(out_context, context.data(), context.size());
@@ -1102,7 +1146,10 @@ static ResultCode GetThreadPriority(Core::System& system, u32* out_priority, Han
1102 // Get the thread from its handle. 1146 // Get the thread from its handle.
1103 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1147 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1104 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1148 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1105 R_UNLESS(thread, Svc::ResultInvalidHandle); 1149 if (!thread) {
1150 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", handle);
1151 return ResultInvalidHandle;
1152 }
1106 1153
1107 // Get the thread's priority. 1154 // Get the thread's priority.
1108 *out_priority = thread->GetPriority(); 1155 *out_priority = thread->GetPriority();
@@ -1118,13 +1165,18 @@ static ResultCode SetThreadPriority(Core::System& system, Handle handle, u32 pri
1118 LOG_TRACE(Kernel_SVC, "called"); 1165 LOG_TRACE(Kernel_SVC, "called");
1119 1166
1120 // Validate the priority. 1167 // Validate the priority.
1121 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, 1168 if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
1122 Svc::ResultInvalidPriority); 1169 LOG_ERROR(Kernel_SVC, "Invalid thread priority specified (priority={})", priority);
1170 return ResultInvalidPriority;
1171 }
1123 1172
1124 // Get the thread from its handle. 1173 // Get the thread from its handle.
1125 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1174 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1126 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle); 1175 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(handle);
1127 R_UNLESS(thread, Svc::ResultInvalidHandle); 1176 if (!thread) {
1177 LOG_ERROR(Kernel_SVC, "Invalid handle provided (handle={:08X})", handle);
1178 return ResultInvalidHandle;
1179 }
1128 1180
1129 // Set the thread priority. 1181 // Set the thread priority.
1130 thread->SetBasePriority(priority); 1182 thread->SetBasePriority(priority);
@@ -1440,17 +1492,28 @@ static ResultCode CreateThread(Core::System& system, Handle* out_handle, VAddr e
1440 // Adjust core id, if it's the default magic. 1492 // Adjust core id, if it's the default magic.
1441 auto& kernel = system.Kernel(); 1493 auto& kernel = system.Kernel();
1442 auto& process = *kernel.CurrentProcess(); 1494 auto& process = *kernel.CurrentProcess();
1443 if (core_id == Svc::IdealCoreUseProcessValue) { 1495 if (core_id == IdealCoreUseProcessValue) {
1444 core_id = process.GetIdealCoreId(); 1496 core_id = process.GetIdealCoreId();
1445 } 1497 }
1446 1498
1447 // Validate arguments. 1499 // Validate arguments.
1448 R_UNLESS(IsValidCoreId(core_id), Svc::ResultInvalidCoreId); 1500 if (!IsValidCoreId(core_id)) {
1449 R_UNLESS(((1ULL << core_id) & process.GetCoreMask()) != 0, Svc::ResultInvalidCoreId); 1501 LOG_ERROR(Kernel_SVC, "Invalid Core ID specified (id={})", core_id);
1502 return ResultInvalidCoreId;
1503 }
1504 if (((1ULL << core_id) & process.GetCoreMask()) == 0) {
1505 LOG_ERROR(Kernel_SVC, "Core ID doesn't fall within allowable cores (id={})", core_id);
1506 return ResultInvalidCoreId;
1507 }
1450 1508
1451 R_UNLESS(Svc::HighestThreadPriority <= priority && priority <= Svc::LowestThreadPriority, 1509 if (HighestThreadPriority > priority || priority > LowestThreadPriority) {
1452 Svc::ResultInvalidPriority); 1510 LOG_ERROR(Kernel_SVC, "Invalid priority specified (priority={})", priority);
1453 R_UNLESS(process.CheckThreadPriority(priority), Svc::ResultInvalidPriority); 1511 return ResultInvalidPriority;
1512 }
1513 if (!process.CheckThreadPriority(priority)) {
1514 LOG_ERROR(Kernel_SVC, "Invalid allowable thread priority (priority={})", priority);
1515 return ResultInvalidPriority;
1516 }
1454 1517
1455 ASSERT(process.GetResourceLimit()->Reserve( 1518 ASSERT(process.GetResourceLimit()->Reserve(
1456 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000)); 1519 LimitableResource::Threads, 1, system.CoreTiming().GetGlobalTimeNs().count() + 100000000));
@@ -1489,10 +1552,19 @@ static ResultCode StartThread(Core::System& system, Handle thread_handle) {
1489 // Get the thread from its handle. 1552 // Get the thread from its handle.
1490 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1553 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1491 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1554 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1492 R_UNLESS(thread, Svc::ResultInvalidHandle); 1555 if (!thread) {
1556 LOG_ERROR(Kernel_SVC, "Invalid thread handle provided (handle={:08X})", thread_handle);
1557 return ResultInvalidHandle;
1558 }
1493 1559
1494 // Try to start the thread. 1560 // Try to start the thread.
1495 R_TRY(thread->Run()); 1561 const auto run_result = thread->Run();
1562 if (run_result.IsError()) {
1563 LOG_ERROR(Kernel_SVC,
1564 "Unable to successfuly start thread (thread handle={:08X}, result={})",
1565 thread_handle, run_result.raw);
1566 return run_result;
1567 }
1496 1568
1497 return RESULT_SUCCESS; 1569 return RESULT_SUCCESS;
1498} 1570}
@@ -1553,8 +1625,14 @@ static ResultCode WaitProcessWideKeyAtomic(Core::System& system, VAddr address,
1553 cv_key, tag, timeout_ns); 1625 cv_key, tag, timeout_ns);
1554 1626
1555 // Validate input. 1627 // Validate input.
1556 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1628 if (Memory::IsKernelAddress(address)) {
1557 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); 1629 LOG_ERROR(Kernel_SVC, "Attempted to wait on kernel address (address={:08X})", address);
1630 return ResultInvalidCurrentMemory;
1631 }
1632 if (!Common::IsAligned(address, sizeof(s32))) {
1633 LOG_ERROR(Kernel_SVC, "Address must be 4 byte aligned (address={:08X})", address);
1634 return ResultInvalidAddress;
1635 }
1558 1636
1559 // Convert timeout from nanoseconds to ticks. 1637 // Convert timeout from nanoseconds to ticks.
1560 s64 timeout{}; 1638 s64 timeout{};
@@ -1629,9 +1707,18 @@ static ResultCode WaitForAddress(Core::System& system, VAddr address, Svc::Arbit
1629 address, arb_type, value, timeout_ns); 1707 address, arb_type, value, timeout_ns);
1630 1708
1631 // Validate input. 1709 // Validate input.
1632 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1710 if (Memory::IsKernelAddress(address)) {
1633 R_UNLESS(Common::IsAligned(address, sizeof(int32_t)), Svc::ResultInvalidAddress); 1711 LOG_ERROR(Kernel_SVC, "Attempting to wait on kernel address (address={:08X})", address);
1634 R_UNLESS(IsValidArbitrationType(arb_type), Svc::ResultInvalidEnumValue); 1712 return ResultInvalidCurrentMemory;
1713 }
1714 if (!Common::IsAligned(address, sizeof(s32))) {
1715 LOG_ERROR(Kernel_SVC, "Wait address must be 4 byte aligned (address={:08X})", address);
1716 return ResultInvalidAddress;
1717 }
1718 if (!IsValidArbitrationType(arb_type)) {
1719 LOG_ERROR(Kernel_SVC, "Invalid arbitration type specified (type={})", arb_type);
1720 return ResultInvalidEnumValue;
1721 }
1635 1722
1636 // Convert timeout from nanoseconds to ticks. 1723 // Convert timeout from nanoseconds to ticks.
1637 s64 timeout{}; 1724 s64 timeout{};
@@ -1665,9 +1752,18 @@ static ResultCode SignalToAddress(Core::System& system, VAddr address, Svc::Sign
1665 address, signal_type, value, count); 1752 address, signal_type, value, count);
1666 1753
1667 // Validate input. 1754 // Validate input.
1668 R_UNLESS(!Memory::IsKernelAddress(address), Svc::ResultInvalidCurrentMemory); 1755 if (Memory::IsKernelAddress(address)) {
1669 R_UNLESS(Common::IsAligned(address, sizeof(s32)), Svc::ResultInvalidAddress); 1756 LOG_ERROR(Kernel_SVC, "Attempting to signal to a kernel address (address={:08X})", address);
1670 R_UNLESS(IsValidSignalType(signal_type), Svc::ResultInvalidEnumValue); 1757 return ResultInvalidCurrentMemory;
1758 }
1759 if (!Common::IsAligned(address, sizeof(s32))) {
1760 LOG_ERROR(Kernel_SVC, "Signaled address must be 4 byte aligned (address={:08X})", address);
1761 return ResultInvalidAddress;
1762 }
1763 if (!IsValidSignalType(signal_type)) {
1764 LOG_ERROR(Kernel_SVC, "Invalid signal type specified (type={})", signal_type);
1765 return ResultInvalidEnumValue;
1766 }
1671 1767
1672 return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value, 1768 return system.Kernel().CurrentProcess()->SignalAddressArbiter(address, signal_type, value,
1673 count); 1769 count);
@@ -1815,10 +1911,17 @@ static ResultCode GetThreadCoreMask(Core::System& system, Handle thread_handle,
1815 // Get the thread from its handle. 1911 // Get the thread from its handle.
1816 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1912 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1817 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1913 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1818 R_UNLESS(thread, Svc::ResultInvalidHandle); 1914 if (!thread) {
1915 LOG_ERROR(Kernel_SVC, "Invalid thread handle specified (handle={:08X})", thread_handle);
1916 return ResultInvalidHandle;
1917 }
1819 1918
1820 // Get the core mask. 1919 // Get the core mask.
1821 R_TRY(thread->GetCoreMask(out_core_id, out_affinity_mask)); 1920 const auto result = thread->GetCoreMask(out_core_id, out_affinity_mask);
1921 if (result.IsError()) {
1922 LOG_ERROR(Kernel_SVC, "Unable to successfully retrieve core mask (result={})", result.raw);
1923 return result;
1924 }
1822 1925
1823 return RESULT_SUCCESS; 1926 return RESULT_SUCCESS;
1824} 1927}
@@ -1846,26 +1949,46 @@ static ResultCode SetThreadCoreMask(Core::System& system, Handle thread_handle,
1846 } else { 1949 } else {
1847 // Validate the affinity mask. 1950 // Validate the affinity mask.
1848 const u64 process_core_mask = current_process.GetCoreMask(); 1951 const u64 process_core_mask = current_process.GetCoreMask();
1849 R_UNLESS((affinity_mask | process_core_mask) == process_core_mask, 1952 if ((affinity_mask | process_core_mask) != process_core_mask) {
1850 Svc::ResultInvalidCoreId); 1953 LOG_ERROR(Kernel_SVC,
1851 R_UNLESS(affinity_mask != 0, Svc::ResultInvalidCombination); 1954 "Affinity mask does match the process core mask (affinity mask={:016X}, core "
1955 "mask={:016X})",
1956 affinity_mask, process_core_mask);
1957 return ResultInvalidCoreId;
1958 }
1959 if (affinity_mask == 0) {
1960 LOG_ERROR(Kernel_SVC, "Affinity mask is zero.");
1961 return ResultInvalidCombination;
1962 }
1852 1963
1853 // Validate the core id. 1964 // Validate the core id.
1854 if (IsValidCoreId(core_id)) { 1965 if (IsValidCoreId(core_id)) {
1855 R_UNLESS(((1ULL << core_id) & affinity_mask) != 0, Svc::ResultInvalidCombination); 1966 if (((1ULL << core_id) & affinity_mask) == 0) {
1967 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
1968 return ResultInvalidCombination;
1969 }
1856 } else { 1970 } else {
1857 R_UNLESS(core_id == Svc::IdealCoreNoUpdate || core_id == Svc::IdealCoreDontCare, 1971 if (core_id != IdealCoreNoUpdate && core_id != IdealCoreDontCare) {
1858 Svc::ResultInvalidCoreId); 1972 LOG_ERROR(Kernel_SVC, "Invalid core ID (ID={})", core_id);
1973 return ResultInvalidCoreId;
1974 }
1859 } 1975 }
1860 } 1976 }
1861 1977
1862 // Get the thread from its handle. 1978 // Get the thread from its handle.
1863 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1979 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1864 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle); 1980 const std::shared_ptr<KThread> thread = handle_table.Get<KThread>(thread_handle);
1865 R_UNLESS(thread, Svc::ResultInvalidHandle); 1981 if (!thread) {
1982 LOG_ERROR(Kernel_SVC, "Invalid thread handle (handle={:08X})", thread_handle);
1983 return ResultInvalidHandle;
1984 }
1866 1985
1867 // Set the core mask. 1986 // Set the core mask.
1868 R_TRY(thread->SetCoreMask(core_id, affinity_mask)); 1987 const auto set_result = thread->SetCoreMask(core_id, affinity_mask);
1988 if (set_result.IsError()) {
1989 LOG_ERROR(Kernel_SVC, "Unable to successfully set core mask (result={})", set_result.raw);
1990 return set_result;
1991 }
1869 1992
1870 return RESULT_SUCCESS; 1993 return RESULT_SUCCESS;
1871} 1994}
@@ -1884,7 +2007,10 @@ static ResultCode SignalEvent(Core::System& system, Handle event_handle) {
1884 2007
1885 // Get the writable event. 2008 // Get the writable event.
1886 auto writable_event = handle_table.Get<KWritableEvent>(event_handle); 2009 auto writable_event = handle_table.Get<KWritableEvent>(event_handle);
1887 R_UNLESS(writable_event, Svc::ResultInvalidHandle); 2010 if (!writable_event) {
2011 LOG_ERROR(Kernel_SVC, "Invalid event handle provided (handle={:08X})", event_handle);
2012 return ResultInvalidHandle;
2013 }
1888 2014
1889 return writable_event->Signal(); 2015 return writable_event->Signal();
1890} 2016}
@@ -1933,7 +2059,10 @@ static ResultCode CreateEvent(Core::System& system, Handle* out_write, Handle* o
1933 2059
1934 // Create a new event. 2060 // Create a new event.
1935 const auto event = KEvent::Create(kernel, "CreateEvent"); 2061 const auto event = KEvent::Create(kernel, "CreateEvent");
1936 R_UNLESS(event != nullptr, Svc::ResultOutOfResource); 2062 if (!event) {
2063 LOG_ERROR(Kernel_SVC, "Unable to create new events. Event creation limit reached.");
2064 return ResultOutOfResource;
2065 }
1937 2066
1938 // Initialize the event. 2067 // Initialize the event.
1939 event->Initialize(); 2068 event->Initialize();
diff --git a/src/core/hle/service/lm/lm.cpp b/src/core/hle/service/lm/lm.cpp
index 2a6d43d2a..7d7542fc2 100644
--- a/src/core/hle/service/lm/lm.cpp
+++ b/src/core/hle/service/lm/lm.cpp
@@ -143,17 +143,19 @@ private:
143 rb.Push(RESULT_SUCCESS); 143 rb.Push(RESULT_SUCCESS);
144 } 144 }
145 145
146 u32 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) { 146 u64 ReadLeb128(const std::vector<u8>& data, std::size_t& offset) {
147 u32 result{}; 147 u64 result{};
148 u32 shift{}; 148 u32 shift{};
149 do { 149
150 result |= (data[offset] & 0x7f) << shift; 150 for (std::size_t i = 0; i < sizeof(u64); i++) {
151 const auto v = data[offset];
152 result |= (static_cast<u64>(v & 0x7f) << shift);
151 shift += 7; 153 shift += 7;
152 offset++; 154 offset++;
153 if (offset >= data.size()) { 155 if (offset >= data.size() || ((v & 0x80) == 0)) {
154 break; 156 break;
155 } 157 }
156 } while ((data[offset] & 0x80) != 0); 158 }
157 return result; 159 return result;
158 } 160 }
159 161
@@ -262,7 +264,7 @@ private:
262 264
263 switch (entry.severity) { 265 switch (entry.severity) {
264 case LogSeverity::Trace: 266 case LogSeverity::Trace:
265 LOG_DEBUG(Service_LM, "LogManager DEBUG ({}):\n{}", DestinationToString(destination), 267 LOG_DEBUG(Service_LM, "LogManager TRACE ({}):\n{}", DestinationToString(destination),
266 output_log); 268 output_log);
267 break; 269 break;
268 case LogSeverity::Info: 270 case LogSeverity::Info:
diff --git a/src/core/hle/service/ns/pl_u.cpp b/src/core/hle/service/ns/pl_u.cpp
index 71c7587db..b6ac0a81a 100644
--- a/src/core/hle/service/ns/pl_u.cpp
+++ b/src/core/hle/service/ns/pl_u.cpp
@@ -65,13 +65,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem
65void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) { 65void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
66 ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number"); 66 ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
67 67
68 if (input.size() < 2) {
69 LOG_ERROR(Service_NS, "Input font is empty");
70 return;
71 }
72
68 const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor 73 const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
69 std::vector<u32> transformed_font(input.size()); 74 std::vector<u32> transformed_font(input.size());
70 // TODO(ogniK): Figure out a better way to do this 75 // TODO(ogniK): Figure out a better way to do this
71 std::transform(input.begin(), input.end(), transformed_font.begin(), 76 std::transform(input.begin(), input.end(), transformed_font.begin(),
72 [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); }); 77 [&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
73 transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size 78 std::memcpy(output.data(), transformed_font.data() + 2,
74 std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32)); 79 (transformed_font.size() - 2) * sizeof(u32));
75} 80}
76 81
77void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, 82void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp
index 54def22da..903626e4b 100644
--- a/src/tests/common/ring_buffer.cpp
+++ b/src/tests/common/ring_buffer.cpp
@@ -14,7 +14,7 @@
14namespace Common { 14namespace Common {
15 15
16TEST_CASE("RingBuffer: Basic Tests", "[common]") { 16TEST_CASE("RingBuffer: Basic Tests", "[common]") {
17 RingBuffer<char, 4, 1> buf; 17 RingBuffer<char, 4> buf;
18 18
19 // Pushing values into a ring buffer with space should succeed. 19 // Pushing values into a ring buffer with space should succeed.
20 for (std::size_t i = 0; i < 4; i++) { 20 for (std::size_t i = 0; i < 4; i++) {
@@ -77,7 +77,7 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
77} 77}
78 78
79TEST_CASE("RingBuffer: Threaded Test", "[common]") { 79TEST_CASE("RingBuffer: Threaded Test", "[common]") {
80 RingBuffer<char, 4, 2> buf; 80 RingBuffer<char, 8> buf;
81 const char seed = 42; 81 const char seed = 42;
82 const std::size_t count = 1000000; 82 const std::size_t count = 1000000;
83 std::size_t full = 0; 83 std::size_t full = 0;
@@ -92,8 +92,8 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
92 std::array<char, 2> value = {seed, seed}; 92 std::array<char, 2> value = {seed, seed};
93 std::size_t i = 0; 93 std::size_t i = 0;
94 while (i < count) { 94 while (i < count) {
95 if (const std::size_t c = buf.Push(&value[0], 1); c > 0) { 95 if (const std::size_t c = buf.Push(&value[0], 2); c > 0) {
96 REQUIRE(c == 1U); 96 REQUIRE(c == 2U);
97 i++; 97 i++;
98 next_value(value); 98 next_value(value);
99 } else { 99 } else {
@@ -107,7 +107,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
107 std::array<char, 2> value = {seed, seed}; 107 std::array<char, 2> value = {seed, seed};
108 std::size_t i = 0; 108 std::size_t i = 0;
109 while (i < count) { 109 while (i < count) {
110 if (const std::vector<char> v = buf.Pop(1); v.size() > 0) { 110 if (const std::vector<char> v = buf.Pop(2); v.size() > 0) {
111 REQUIRE(v.size() == 2U); 111 REQUIRE(v.size() == 2U);
112 REQUIRE(v[0] == value[0]); 112 REQUIRE(v[0] == value[0]);
113 REQUIRE(v[1] == value[1]); 113 REQUIRE(v[1] == value[1]);
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index bb1f8491f..2cf95937e 100644
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -67,8 +67,6 @@ add_library(video_core STATIC
67 guest_driver.h 67 guest_driver.h
68 memory_manager.cpp 68 memory_manager.cpp
69 memory_manager.h 69 memory_manager.h
70 morton.cpp
71 morton.h
72 query_cache.h 70 query_cache.h
73 rasterizer_accelerated.cpp 71 rasterizer_accelerated.cpp
74 rasterizer_accelerated.h 72 rasterizer_accelerated.h
diff --git a/src/video_core/morton.cpp b/src/video_core/morton.cpp
deleted file mode 100644
index e69de29bb..000000000
--- a/src/video_core/morton.cpp
+++ /dev/null
diff --git a/src/video_core/morton.h b/src/video_core/morton.h
deleted file mode 100644
index e69de29bb..000000000
--- a/src/video_core/morton.h
+++ /dev/null
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index dd77a543c..21159e498 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -506,7 +506,7 @@ bool RendererOpenGL::Init() {
506 506
507 AddTelemetryFields(); 507 AddTelemetryFields();
508 508
509 if (!GLAD_GL_VERSION_4_3) { 509 if (!GLAD_GL_VERSION_4_6) {
510 return false; 510 return false;
511 } 511 }
512 512
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index 4528eb196..ffdf34a4a 100644
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -126,7 +126,7 @@ public:
126 /// Create the original context that should be shared from 126 /// Create the original context that should be shared from
127 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) { 127 explicit OpenGLSharedContext(QSurface* surface) : surface(surface) {
128 QSurfaceFormat format; 128 QSurfaceFormat format;
129 format.setVersion(4, 3); 129 format.setVersion(4, 6);
130 format.setProfile(QSurfaceFormat::CompatibilityProfile); 130 format.setProfile(QSurfaceFormat::CompatibilityProfile);
131 format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions); 131 format.setOption(QSurfaceFormat::FormatOption::DeprecatedFunctions);
132 if (Settings::values.renderer_debug) { 132 if (Settings::values.renderer_debug) {
@@ -651,10 +651,10 @@ bool GRenderWindow::LoadOpenGL() {
651 const QString renderer = 651 const QString renderer =
652 QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER))); 652 QString::fromUtf8(reinterpret_cast<const char*>(glGetString(GL_RENDERER)));
653 653
654 if (!GLAD_GL_VERSION_4_3) { 654 if (!GLAD_GL_VERSION_4_6) {
655 LOG_ERROR(Frontend, "GPU does not support OpenGL 4.3: {}", renderer.toStdString()); 655 LOG_ERROR(Frontend, "GPU does not support OpenGL 4.6: {}", renderer.toStdString());
656 QMessageBox::warning(this, tr("Error while initializing OpenGL 4.3!"), 656 QMessageBox::warning(this, tr("Error while initializing OpenGL 4.6!"),
657 tr("Your GPU may not support OpenGL 4.3, or you do not have the " 657 tr("Your GPU may not support OpenGL 4.6, or you do not have the "
658 "latest graphics driver.<br><br>GL Renderer:<br>%1") 658 "latest graphics driver.<br><br>GL Renderer:<br>%1")
659 .arg(renderer)); 659 .arg(renderer));
660 return false; 660 return false;
@@ -677,26 +677,13 @@ bool GRenderWindow::LoadOpenGL() {
677QStringList GRenderWindow::GetUnsupportedGLExtensions() const { 677QStringList GRenderWindow::GetUnsupportedGLExtensions() const {
678 QStringList unsupported_ext; 678 QStringList unsupported_ext;
679 679
680 if (!GLAD_GL_ARB_buffer_storage)
681 unsupported_ext.append(QStringLiteral("ARB_buffer_storage"));
682 if (!GLAD_GL_ARB_direct_state_access)
683 unsupported_ext.append(QStringLiteral("ARB_direct_state_access"));
684 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
685 unsupported_ext.append(QStringLiteral("ARB_vertex_type_10f_11f_11f_rev"));
686 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
687 unsupported_ext.append(QStringLiteral("ARB_texture_mirror_clamp_to_edge"));
688 if (!GLAD_GL_ARB_multi_bind)
689 unsupported_ext.append(QStringLiteral("ARB_multi_bind"));
690 if (!GLAD_GL_ARB_clip_control)
691 unsupported_ext.append(QStringLiteral("ARB_clip_control"));
692
693 // Extensions required to support some texture formats. 680 // Extensions required to support some texture formats.
694 if (!GLAD_GL_EXT_texture_compression_s3tc) 681 if (!GLAD_GL_EXT_texture_compression_s3tc) {
695 unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc")); 682 unsupported_ext.append(QStringLiteral("EXT_texture_compression_s3tc"));
696 if (!GLAD_GL_ARB_texture_compression_rgtc) 683 }
684 if (!GLAD_GL_ARB_texture_compression_rgtc) {
697 unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc")); 685 unsupported_ext.append(QStringLiteral("ARB_texture_compression_rgtc"));
698 if (!GLAD_GL_ARB_depth_buffer_float) 686 }
699 unsupported_ext.append(QStringLiteral("ARB_depth_buffer_float"));
700 687
701 if (!unsupported_ext.empty()) { 688 if (!unsupported_ext.empty()) {
702 LOG_ERROR(Frontend, "GPU does not support all required extensions: {}", 689 LOG_ERROR(Frontend, "GPU does not support all required extensions: {}",
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
index a103b04bd..deddea9ee 100644
--- a/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
+++ b/src/yuzu_cmd/emu_window/emu_window_sdl2_gl.cpp
@@ -59,29 +59,17 @@ private:
59bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() { 59bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
60 std::vector<std::string_view> unsupported_ext; 60 std::vector<std::string_view> unsupported_ext;
61 61
62 if (!GLAD_GL_ARB_buffer_storage)
63 unsupported_ext.push_back("ARB_buffer_storage");
64 if (!GLAD_GL_ARB_direct_state_access)
65 unsupported_ext.push_back("ARB_direct_state_access");
66 if (!GLAD_GL_ARB_vertex_type_10f_11f_11f_rev)
67 unsupported_ext.push_back("ARB_vertex_type_10f_11f_11f_rev");
68 if (!GLAD_GL_ARB_texture_mirror_clamp_to_edge)
69 unsupported_ext.push_back("ARB_texture_mirror_clamp_to_edge");
70 if (!GLAD_GL_ARB_multi_bind)
71 unsupported_ext.push_back("ARB_multi_bind");
72 if (!GLAD_GL_ARB_clip_control)
73 unsupported_ext.push_back("ARB_clip_control");
74
75 // Extensions required to support some texture formats. 62 // Extensions required to support some texture formats.
76 if (!GLAD_GL_EXT_texture_compression_s3tc) 63 if (!GLAD_GL_EXT_texture_compression_s3tc) {
77 unsupported_ext.push_back("EXT_texture_compression_s3tc"); 64 unsupported_ext.push_back("EXT_texture_compression_s3tc");
78 if (!GLAD_GL_ARB_texture_compression_rgtc) 65 }
66 if (!GLAD_GL_ARB_texture_compression_rgtc) {
79 unsupported_ext.push_back("ARB_texture_compression_rgtc"); 67 unsupported_ext.push_back("ARB_texture_compression_rgtc");
80 if (!GLAD_GL_ARB_depth_buffer_float) 68 }
81 unsupported_ext.push_back("ARB_depth_buffer_float");
82 69
83 for (const auto& extension : unsupported_ext) 70 for (const auto& extension : unsupported_ext) {
84 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension); 71 LOG_CRITICAL(Frontend, "Unsupported GL extension: {}", extension);
72 }
85 73
86 return unsupported_ext.empty(); 74 return unsupported_ext.empty();
87} 75}
@@ -89,7 +77,7 @@ bool EmuWindow_SDL2_GL::SupportsRequiredGLExtensions() {
89EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen) 77EmuWindow_SDL2_GL::EmuWindow_SDL2_GL(InputCommon::InputSubsystem* input_subsystem, bool fullscreen)
90 : EmuWindow_SDL2{input_subsystem} { 78 : EmuWindow_SDL2{input_subsystem} {
91 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4); 79 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MAJOR_VERSION, 4);
92 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 3); 80 SDL_GL_SetAttribute(SDL_GL_CONTEXT_MINOR_VERSION, 6);
93 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY); 81 SDL_GL_SetAttribute(SDL_GL_CONTEXT_PROFILE_MASK, SDL_GL_CONTEXT_PROFILE_COMPATIBILITY);
94 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1); 82 SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
95 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8); 83 SDL_GL_SetAttribute(SDL_GL_RED_SIZE, 8);