aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorpineappleEA <pineaea@gmail.com>2021-01-12 10:22:33 +0100
committerpineappleEA <pineaea@gmail.com>2021-01-12 10:22:33 +0100
commit4219fd41b91dd78cffdf70db1a07cc1bdf7c174e (patch)
tree145689d56256688aecbb41c7813637a674ddedce
parentebc2449a41ab3c8316796082658fe5b1f531c715 (diff)
early-access version 1310EA-1310
-rwxr-xr-xREADME.md2
-rw-r--r--patches/inject-git-info.patch13
-rwxr-xr-xsrc/CMakeLists.txt5
-rwxr-xr-xsrc/common/div_ceil.h10
-rwxr-xr-xsrc/common/intrusive_red_black_tree.h94
-rwxr-xr-xsrc/common/parent_of_member.h47
-rwxr-xr-xsrc/core/arm/dynarmic/arm_dynarmic_32.cpp9
-rwxr-xr-xsrc/core/file_sys/registered_cache.h8
-rwxr-xr-xsrc/core/hle/kernel/k_address_arbiter.cpp10
-rwxr-xr-xsrc/core/hle/kernel/k_address_arbiter.h7
-rwxr-xr-xsrc/core/hle/kernel/k_condition_variable.cpp11
-rwxr-xr-xsrc/core/hle/kernel/k_condition_variable.h7
-rwxr-xr-xsrc/core/hle/kernel/k_synchronization_object.cpp10
-rwxr-xr-xsrc/core/hle/kernel/k_synchronization_object.h5
-rwxr-xr-xsrc/core/hle/kernel/kernel.cpp2
-rwxr-xr-xsrc/core/hle/kernel/process.h2
-rwxr-xr-xsrc/core/hle/kernel/readable_event.h2
-rwxr-xr-xsrc/core/hle/kernel/server_port.h2
-rwxr-xr-xsrc/core/hle/kernel/server_session.h2
-rwxr-xr-xsrc/core/hle/kernel/svc.cpp1
-rwxr-xr-xsrc/core/hle/kernel/thread.cpp6
-rwxr-xr-xsrc/core/hle/kernel/thread.h38
-rwxr-xr-xsrc/core/hle/service/apm/interface.cpp10
-rwxr-xr-xsrc/core/hle/service/apm/interface.h1
-rwxr-xr-xsrc/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp3
-rwxr-xr-xsrc/core/hle/service/nvdrv/devices/nvhost_vic.cpp7
-rwxr-xr-xsrc/core/hle/service/nvflinger/buffer_queue.cpp6
-rwxr-xr-xsrc/tests/CMakeLists.txt1
-rwxr-xr-xsrc/tests/common/ring_buffer.cpp30
-rwxr-xr-xsrc/video_core/CMakeLists.txt1
-rwxr-xr-xsrc/video_core/cdma_pusher.cpp63
-rwxr-xr-xsrc/video_core/cdma_pusher.h35
-rwxr-xr-xsrc/video_core/command_classes/codecs/codec.cpp7
-rwxr-xr-xsrc/video_core/command_classes/nvdec.cpp8
-rwxr-xr-xsrc/video_core/command_classes/nvdec.h2
-rwxr-xr-xsrc/video_core/command_classes/vic.cpp45
-rwxr-xr-xsrc/video_core/command_classes/vic.h51
-rwxr-xr-xsrc/video_core/gpu.cpp6
-rwxr-xr-xsrc/video_core/gpu_thread.cpp3
-rwxr-xr-xsrc/yuzu/bootmanager.cpp7
-rwxr-xr-xsrc/yuzu/configuration/config.cpp4
-rwxr-xr-xsrc/yuzu/configuration/configure_motion_touch.cpp7
-rwxr-xr-xsrc/yuzu/debugger/wait_tree.cpp46
-rwxr-xr-xsrc/yuzu/util/url_request_interceptor.cpp2
-rwxr-xr-xsrc/yuzu_cmd/config.cpp2
-rwxr-xr-xsrc/yuzu_cmd/default_ini.h2
-rwxr-xr-xsrc/yuzu_cmd/yuzu.cpp2
-rwxr-xr-xsrc/yuzu_tester/config.cpp2
-rwxr-xr-xsrc/yuzu_tester/default_ini.h2
49 files changed, 307 insertions, 341 deletions
diff --git a/README.md b/README.md
index 979f8cd96..a744accfe 100755
--- a/README.md
+++ b/README.md
@@ -1,7 +1,7 @@
1yuzu emulator early access 1yuzu emulator early access
2============= 2=============
3 3
4This is the source code for early-access 1298. 4This is the source code for early-access 1310.
5 5
6## Legal Notice 6## Legal Notice
7 7
diff --git a/patches/inject-git-info.patch b/patches/inject-git-info.patch
index cf7b6f780..a3c7b5951 100644
--- a/patches/inject-git-info.patch
+++ b/patches/inject-git-info.patch
@@ -1,31 +1,31 @@
1diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake 1diff --git a/CMakeModules/GenerateSCMRev.cmake b/CMakeModules/GenerateSCMRev.cmake
2index 311ba1c2e..79315b198 100644
3--- a/CMakeModules/GenerateSCMRev.cmake 2--- a/CMakeModules/GenerateSCMRev.cmake
4+++ b/CMakeModules/GenerateSCMRev.cmake 3+++ b/CMakeModules/GenerateSCMRev.cmake
5@@ -11,9 +11,9 @@ find_package(Git QUIET PATHS "${GIT_EXECUTABLE}") 4@@ -11,10 +11,10 @@
6 5
7 # generate git/build information 6 # generate git/build information
8 include(GetGitRevisionDescription) 7 include(GetGitRevisionDescription)
9-get_git_head_revision(GIT_REF_SPEC GIT_REV) 8-get_git_head_revision(GIT_REF_SPEC GIT_REV)
10-git_describe(GIT_DESC --always --long --dirty) 9-git_describe(GIT_DESC --always --long --dirty)
11-git_branch_name(GIT_BRANCH) 10-git_branch_name(GIT_BRANCH)
11-get_timestamp(BUILD_DATE)
12+#get_git_head_revision(GIT_REF_SPEC GIT_REV) 12+#get_git_head_revision(GIT_REF_SPEC GIT_REV)
13+#git_describe(GIT_DESC --always --long --dirty) 13+#git_describe(GIT_DESC --always --long --dirty)
14+#git_branch_name(GIT_BRANCH) 14+#git_branch_name(GIT_BRANCH)
15 get_timestamp(BUILD_DATE) 15+#get_timestamp(BUILD_DATE)
16 16
17 # Generate cpp with Git revision from template 17 # Generate cpp with Git revision from template
18@@ -113,4 +113,5 @@ foreach (F IN LISTS HASH_FILES) 18 # Also if this is a CI build, add the build name (ie: Nightly, Canary) to the scm_rev file as well
19@@ -113,4 +113,5 @@
19 set(COMBINED "${COMBINED}${TMP}") 20 set(COMBINED "${COMBINED}${TMP}")
20 endforeach() 21 endforeach()
21 string(MD5 SHADER_CACHE_VERSION "${COMBINED}") 22 string(MD5 SHADER_CACHE_VERSION "${COMBINED}")
22+set(BUILD_FULLNAME "${BUILD_FULLNAME} ") 23+set(BUILD_FULLNAME "${BUILD_FULLNAME} ")
23 configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY) 24 configure_file("${SRC_DIR}/src/common/scm_rev.cpp.in" "scm_rev.cpp" @ONLY)
24diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt 25diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
25index d120c8d3d..bf3dcdbf6 100644
26--- a/src/common/CMakeLists.txt 26--- a/src/common/CMakeLists.txt
27+++ b/src/common/CMakeLists.txt 27+++ b/src/common/CMakeLists.txt
28@@ -28,6 +28,11 @@ add_custom_command(OUTPUT scm_rev.cpp 28@@ -28,6 +28,12 @@
29 -DBUILD_TAG="${BUILD_TAG}" 29 -DBUILD_TAG="${BUILD_TAG}"
30 -DBUILD_ID="${DISPLAY_VERSION}" 30 -DBUILD_ID="${DISPLAY_VERSION}"
31 -DGIT_EXECUTABLE="${GIT_EXECUTABLE}" 31 -DGIT_EXECUTABLE="${GIT_EXECUTABLE}"
@@ -34,6 +34,7 @@ index d120c8d3d..bf3dcdbf6 100644
34+ -DGIT_DESC="${GIT_DESC}" 34+ -DGIT_DESC="${GIT_DESC}"
35+ -DGIT_BRANCH="${GIT_BRANCH}" 35+ -DGIT_BRANCH="${GIT_BRANCH}"
36+ -DBUILD_FULLNAME="${BUILD_FULLNAME}" 36+ -DBUILD_FULLNAME="${BUILD_FULLNAME}"
37+ -DBUILD_DATE="${BUILD_DATE}"
37 -P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake" 38 -P "${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake"
38 DEPENDS 39 DEPENDS
39 # WARNING! It was too much work to try and make a common location for this list, 40 # WARNING! It was too much work to try and make a common location for this list,
diff --git a/src/CMakeLists.txt b/src/CMakeLists.txt
index 8777df751..61adbef28 100755
--- a/src/CMakeLists.txt
+++ b/src/CMakeLists.txt
@@ -45,10 +45,15 @@ if (MSVC)
45 45
46 # Warnings 46 # Warnings
47 /W3 47 /W3
48 /we4062 # enumerator 'identifier' in a switch of enum 'enumeration' is not handled
49 /we4101 # 'identifier': unreferenced local variable
50 /we4265 # 'class': class has virtual functions, but destructor is not virtual
51 /we4388 # signed/unsigned mismatch
48 /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect 52 /we4547 # 'operator' : operator before comma has no effect; expected operator with side-effect
49 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'? 53 /we4549 # 'operator1': operator before comma has no effect; did you intend 'operator2'?
50 /we4555 # Expression has no effect; expected expression with side-effect 54 /we4555 # Expression has no effect; expected expression with side-effect
51 /we4834 # Discarding return value of function with 'nodiscard' attribute 55 /we4834 # Discarding return value of function with 'nodiscard' attribute
56 /we5038 # data member 'member1' will be initialized after data member 'member2'
52 ) 57 )
53 58
54 # /GS- - No stack buffer overflow checks 59 # /GS- - No stack buffer overflow checks
diff --git a/src/common/div_ceil.h b/src/common/div_ceil.h
index 6b2c48f91..95e1489a9 100755
--- a/src/common/div_ceil.h
+++ b/src/common/div_ceil.h
@@ -11,16 +11,16 @@ namespace Common {
11 11
12/// Ceiled integer division. 12/// Ceiled integer division.
13template <typename N, typename D> 13template <typename N, typename D>
14requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr auto DivCeil( 14requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeil(N number,
15 N number, D divisor) { 15 D divisor) {
16 return (static_cast<D>(number) + divisor - 1) / divisor; 16 return static_cast<N>((static_cast<D>(number) + divisor - 1) / divisor);
17} 17}
18 18
19/// Ceiled integer division with logarithmic divisor in base 2 19/// Ceiled integer division with logarithmic divisor in base 2
20template <typename N, typename D> 20template <typename N, typename D>
21requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr auto DivCeilLog2( 21requires std::is_integral_v<N>&& std::is_unsigned_v<D>[[nodiscard]] constexpr N DivCeilLog2(
22 N value, D alignment_log2) { 22 N value, D alignment_log2) {
23 return (static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2; 23 return static_cast<N>((static_cast<D>(value) + (D(1) << alignment_log2) - 1) >> alignment_log2);
24} 24}
25 25
26} // namespace Common 26} // namespace Common
diff --git a/src/common/intrusive_red_black_tree.h b/src/common/intrusive_red_black_tree.h
index 0be90912c..fb55de94e 100755
--- a/src/common/intrusive_red_black_tree.h
+++ b/src/common/intrusive_red_black_tree.h
@@ -1,18 +1,6 @@
1/* 1// Copyright 2021 yuzu Emulator Project
2 * Copyright (c) 2018-2020 Atmosphère-NX 2// Licensed under GPLv2 or any later version
3 * 3// Refer to the license.txt file included.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16 4
17#pragma once 5#pragma once
18 6
@@ -30,7 +18,7 @@ class IntrusiveRedBlackTreeImpl;
30struct IntrusiveRedBlackTreeNode { 18struct IntrusiveRedBlackTreeNode {
31 19
32private: 20private:
33 RB_ENTRY(IntrusiveRedBlackTreeNode) entry; 21 RB_ENTRY(IntrusiveRedBlackTreeNode) entry{};
34 22
35 friend class impl::IntrusiveRedBlackTreeImpl; 23 friend class impl::IntrusiveRedBlackTreeImpl;
36 24
@@ -38,8 +26,7 @@ private:
38 friend class IntrusiveRedBlackTree; 26 friend class IntrusiveRedBlackTree;
39 27
40public: 28public:
41 constexpr IntrusiveRedBlackTreeNode() : entry() { /* ... */ 29 constexpr IntrusiveRedBlackTreeNode() = default;
42 }
43}; 30};
44 31
45template <class T, class Traits, class Comparator> 32template <class T, class Traits, class Comparator>
@@ -80,18 +67,16 @@ public:
80 using iterator_category = std::bidirectional_iterator_tag; 67 using iterator_category = std::bidirectional_iterator_tag;
81 using value_type = typename IntrusiveRedBlackTreeImpl::value_type; 68 using value_type = typename IntrusiveRedBlackTreeImpl::value_type;
82 using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type; 69 using difference_type = typename IntrusiveRedBlackTreeImpl::difference_type;
83 using pointer = typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_pointer, 70 using pointer = std::conditional_t<Const, IntrusiveRedBlackTreeImpl::const_pointer,
84 IntrusiveRedBlackTreeImpl::pointer>::type; 71 IntrusiveRedBlackTreeImpl::pointer>;
85 using reference = 72 using reference = std::conditional_t<Const, IntrusiveRedBlackTreeImpl::const_reference,
86 typename std::conditional<Const, IntrusiveRedBlackTreeImpl::const_reference, 73 IntrusiveRedBlackTreeImpl::reference>;
87 IntrusiveRedBlackTreeImpl::reference>::type;
88 74
89 private: 75 private:
90 pointer node; 76 pointer node;
91 77
92 public: 78 public:
93 explicit Iterator(pointer n) : node(n) { /* ... */ 79 explicit Iterator(pointer n) : node(n) {}
94 }
95 80
96 bool operator==(const Iterator& rhs) const { 81 bool operator==(const Iterator& rhs) const {
97 return this->node == rhs.node; 82 return this->node == rhs.node;
@@ -137,12 +122,11 @@ public:
137 }; 122 };
138 123
139protected: 124protected:
140 /* Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot. 125 // Generate static implementations for non-comparison operations for IntrusiveRedBlackTreeRoot.
141 */
142 RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry); 126 RB_GENERATE_WITHOUT_COMPARE_STATIC(IntrusiveRedBlackTreeRoot, IntrusiveRedBlackTreeNode, entry);
143 127
144private: 128private:
145 /* Define accessors using RB_* functions. */ 129 // Define accessors using RB_* functions.
146 constexpr void InitializeImpl() { 130 constexpr void InitializeImpl() {
147 RB_INIT(&this->root); 131 RB_INIT(&this->root);
148 } 132 }
@@ -174,12 +158,12 @@ public:
174 return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node); 158 return RB_PREV(IntrusiveRedBlackTreeRoot, nullptr, node);
175 } 159 }
176 160
177 static IntrusiveRedBlackTreeNode const* GetNext(IntrusiveRedBlackTreeNode const* node) { 161 static IntrusiveRedBlackTreeNode const* GetNext(const IntrusiveRedBlackTreeNode* node) {
178 return static_cast<const IntrusiveRedBlackTreeNode*>( 162 return static_cast<const IntrusiveRedBlackTreeNode*>(
179 GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node))); 163 GetNext(const_cast<IntrusiveRedBlackTreeNode*>(node)));
180 } 164 }
181 165
182 static IntrusiveRedBlackTreeNode const* GetPrev(IntrusiveRedBlackTreeNode const* node) { 166 static IntrusiveRedBlackTreeNode const* GetPrev(const IntrusiveRedBlackTreeNode* node) {
183 return static_cast<const IntrusiveRedBlackTreeNode*>( 167 return static_cast<const IntrusiveRedBlackTreeNode*>(
184 GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node))); 168 GetPrev(const_cast<IntrusiveRedBlackTreeNode*>(node)));
185 } 169 }
@@ -189,7 +173,7 @@ public:
189 this->InitializeImpl(); 173 this->InitializeImpl();
190 } 174 }
191 175
192 /* Iterator accessors. */ 176 // Iterator accessors.
193 iterator begin() { 177 iterator begin() {
194 return iterator(this->GetMinImpl()); 178 return iterator(this->GetMinImpl());
195 } 179 }
@@ -222,7 +206,7 @@ public:
222 return const_iterator(&ref); 206 return const_iterator(&ref);
223 } 207 }
224 208
225 /* Content management. */ 209 // Content management.
226 bool empty() const { 210 bool empty() const {
227 return this->EmptyImpl(); 211 return this->EmptyImpl();
228 } 212 }
@@ -273,8 +257,7 @@ consteval auto* GetLightCompareType() {
273} // namespace impl 257} // namespace impl
274 258
275template <typename T, typename Default> 259template <typename T, typename Default>
276using LightCompareType = 260using LightCompareType = std::remove_pointer_t<decltype(impl::GetLightCompareType<T, Default>())>;
277 typename std::remove_pointer<decltype(impl::GetLightCompareType<T, Default>())>::type;
278 261
279template <class T, class Traits, class Comparator> 262template <class T, class Traits, class Comparator>
280class IntrusiveRedBlackTree { 263class IntrusiveRedBlackTree {
@@ -283,7 +266,7 @@ public:
283 using ImplType = impl::IntrusiveRedBlackTreeImpl; 266 using ImplType = impl::IntrusiveRedBlackTreeImpl;
284 267
285private: 268private:
286 ImplType impl; 269 ImplType impl{};
287 270
288public: 271public:
289 struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot {}; 272 struct IntrusiveRedBlackTreeRootWithCompare : ImplType::IntrusiveRedBlackTreeRoot {};
@@ -311,27 +294,25 @@ public:
311 friend class IntrusiveRedBlackTree<T, Traits, Comparator>; 294 friend class IntrusiveRedBlackTree<T, Traits, Comparator>;
312 295
313 using ImplIterator = 296 using ImplIterator =
314 typename std::conditional<Const, ImplType::const_iterator, ImplType::iterator>::type; 297 std::conditional_t<Const, ImplType::const_iterator, ImplType::iterator>;
315 298
316 using iterator_category = std::bidirectional_iterator_tag; 299 using iterator_category = std::bidirectional_iterator_tag;
317 using value_type = typename IntrusiveRedBlackTree::value_type; 300 using value_type = typename IntrusiveRedBlackTree::value_type;
318 using difference_type = typename IntrusiveRedBlackTree::difference_type; 301 using difference_type = typename IntrusiveRedBlackTree::difference_type;
319 using pointer = typename std::conditional<Const, IntrusiveRedBlackTree::const_pointer, 302 using pointer = std::conditional_t<Const, IntrusiveRedBlackTree::const_pointer,
320 IntrusiveRedBlackTree::pointer>::type; 303 IntrusiveRedBlackTree::pointer>;
321 using reference = typename std::conditional<Const, IntrusiveRedBlackTree::const_reference, 304 using reference = std::conditional_t<Const, IntrusiveRedBlackTree::const_reference,
322 IntrusiveRedBlackTree::reference>::type; 305 IntrusiveRedBlackTree::reference>;
323 306
324 private: 307 private:
325 ImplIterator iterator; 308 ImplIterator iterator;
326 309
327 private: 310 private:
328 explicit Iterator(ImplIterator it) : iterator(it) { /* ... */ 311 explicit Iterator(ImplIterator it) : iterator(it) {}
329 }
330 312
331 explicit Iterator(typename std::conditional<Const, ImplType::const_iterator, 313 explicit Iterator(typename std::conditional<Const, ImplType::const_iterator,
332 ImplType::iterator>::type::pointer ptr) 314 ImplType::iterator>::type::pointer ptr)
333 : iterator(ptr) { /* ... */ 315 : iterator(ptr) {}
334 }
335 316
336 ImplIterator GetImplIterator() const { 317 ImplIterator GetImplIterator() const {
337 return this->iterator; 318 return this->iterator;
@@ -382,7 +363,7 @@ public:
382 }; 363 };
383 364
384private: 365private:
385 /* Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot. */ 366 // Generate static implementations for comparison operations for IntrusiveRedBlackTreeRoot.
386 RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode, 367 RB_GENERATE_WITH_COMPARE_STATIC(IntrusiveRedBlackTreeRootWithCompare, IntrusiveRedBlackTreeNode,
387 entry, CompareImpl, LightCompareImpl); 368 entry, CompareImpl, LightCompareImpl);
388 369
@@ -396,14 +377,14 @@ private:
396 return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs)); 377 return Comparator::Compare(*static_cast<const_light_pointer>(elm), *Traits::GetParent(rhs));
397 } 378 }
398 379
399 /* Define accessors using RB_* functions. */ 380 // Define accessors using RB_* functions.
400 IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) { 381 IntrusiveRedBlackTreeNode* InsertImpl(IntrusiveRedBlackTreeNode* node) {
401 return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare, 382 return RB_INSERT(IntrusiveRedBlackTreeRootWithCompare,
402 static_cast<IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root), 383 static_cast<IntrusiveRedBlackTreeRootWithCompare*>(&this->impl.root),
403 node); 384 node);
404 } 385 }
405 386
406 IntrusiveRedBlackTreeNode* FindImpl(IntrusiveRedBlackTreeNode const* node) const { 387 IntrusiveRedBlackTreeNode* FindImpl(const IntrusiveRedBlackTreeNode* node) const {
407 return RB_FIND( 388 return RB_FIND(
408 IntrusiveRedBlackTreeRootWithCompare, 389 IntrusiveRedBlackTreeRootWithCompare,
409 const_cast<IntrusiveRedBlackTreeRootWithCompare*>( 390 const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
@@ -411,7 +392,7 @@ private:
411 const_cast<IntrusiveRedBlackTreeNode*>(node)); 392 const_cast<IntrusiveRedBlackTreeNode*>(node));
412 } 393 }
413 394
414 IntrusiveRedBlackTreeNode* NFindImpl(IntrusiveRedBlackTreeNode const* node) const { 395 IntrusiveRedBlackTreeNode* NFindImpl(const IntrusiveRedBlackTreeNode* node) const {
415 return RB_NFIND( 396 return RB_NFIND(
416 IntrusiveRedBlackTreeRootWithCompare, 397 IntrusiveRedBlackTreeRootWithCompare,
417 const_cast<IntrusiveRedBlackTreeRootWithCompare*>( 398 const_cast<IntrusiveRedBlackTreeRootWithCompare*>(
@@ -436,10 +417,9 @@ private:
436 } 417 }
437 418
438public: 419public:
439 constexpr IntrusiveRedBlackTree() : impl() { /* ... */ 420 constexpr IntrusiveRedBlackTree() = default;
440 }
441 421
442 /* Iterator accessors. */ 422 // Iterator accessors.
443 iterator begin() { 423 iterator begin() {
444 return iterator(this->impl.begin()); 424 return iterator(this->impl.begin());
445 } 425 }
@@ -472,7 +452,7 @@ public:
472 return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref)))); 452 return const_iterator(this->impl.iterator_to(*Traits::GetNode(std::addressof(ref))));
473 } 453 }
474 454
475 /* Content management. */ 455 // Content management.
476 bool empty() const { 456 bool empty() const {
477 return this->impl.empty(); 457 return this->impl.empty();
478 } 458 }
@@ -548,12 +528,12 @@ private:
548 return GetParentPointer<Member, Derived>(node); 528 return GetParentPointer<Member, Derived>(node);
549 } 529 }
550 530
551 static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { 531 static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
552 return GetParentPointer<Member, Derived>(node); 532 return GetParentPointer<Member, Derived>(node);
553 } 533 }
554 534
555private: 535private:
556 static constexpr TYPED_STORAGE(Derived) DerivedStorage = {}; 536 static constexpr TypedStorage<Derived> DerivedStorage = {};
557 static_assert(GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage)); 537 static_assert(GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage));
558}; 538};
559 539
@@ -569,7 +549,7 @@ public:
569 using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl; 549 using TreeTypeImpl = impl::IntrusiveRedBlackTreeImpl;
570 550
571 static constexpr bool IsValid() { 551 static constexpr bool IsValid() {
572 TYPED_STORAGE(Derived) DerivedStorage = {}; 552 TypedStorage<Derived> DerivedStorage = {};
573 return GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage); 553 return GetParent(GetNode(GetPointer(DerivedStorage))) == GetPointer(DerivedStorage);
574 } 554 }
575 555
@@ -591,7 +571,7 @@ private:
591 return GetParentPointer<Member, Derived>(node); 571 return GetParentPointer<Member, Derived>(node);
592 } 572 }
593 573
594 static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { 574 static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
595 return GetParentPointer<Member, Derived>(node); 575 return GetParentPointer<Member, Derived>(node);
596 } 576 }
597}; 577};
@@ -639,7 +619,7 @@ private:
639 return static_cast<Derived*>(node); 619 return static_cast<Derived*>(node);
640 } 620 }
641 621
642 static constexpr Derived const* GetParent(IntrusiveRedBlackTreeNode const* node) { 622 static constexpr Derived const* GetParent(const IntrusiveRedBlackTreeNode* node) {
643 return static_cast<const Derived*>(node); 623 return static_cast<const Derived*>(node);
644 } 624 }
645}; 625};
diff --git a/src/common/parent_of_member.h b/src/common/parent_of_member.h
index fd79e11b6..d9a14529d 100755
--- a/src/common/parent_of_member.h
+++ b/src/common/parent_of_member.h
@@ -1,18 +1,6 @@
1/* 1// Copyright 2021 yuzu Emulator Project
2 * Copyright (c) 2018-2020 Atmosphère-NX 2// Licensed under GPLv2 or any later version
3 * 3// Refer to the license.txt file included.
4 * This program is free software; you can redistribute it and/or modify it
5 * under the terms and conditions of the GNU General Public License,
6 * version 2, as published by the Free Software Foundation.
7 *
8 * This program is distributed in the hope it will be useful, but WITHOUT
9 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
10 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
11 * more details.
12 *
13 * You should have received a copy of the GNU General Public License
14 * along with this program. If not, see <http://www.gnu.org/licenses/>.
15 */
16 4
17#pragma once 5#pragma once
18 6
@@ -22,22 +10,24 @@
22#include "common/common_types.h" 10#include "common/common_types.h"
23 11
24namespace Common { 12namespace Common {
25 13namespace detail {
26template <typename T, size_t Size, size_t Align> 14template <typename T, size_t Size, size_t Align>
27struct TypedStorage { 15struct TypedStorageImpl {
28 typename std::aligned_storage<Size, Align>::type _storage; 16 std::aligned_storage_t<Size, Align> storage_;
29}; 17};
18} // namespace detail
30 19
31#define TYPED_STORAGE(...) TypedStorage<__VA_ARGS__, sizeof(__VA_ARGS__), alignof(__VA_ARGS__)> 20template <typename T>
21using TypedStorage = detail::TypedStorageImpl<T, sizeof(T), alignof(T)>;
32 22
33template <typename T> 23template <typename T>
34static constexpr T* GetPointer(TYPED_STORAGE(T) & ts) { 24static constexpr T* GetPointer(TypedStorage<T>& ts) {
35 return static_cast<T*>(static_cast<void*>(std::addressof(ts._storage))); 25 return static_cast<T*>(static_cast<void*>(std::addressof(ts.storage_)));
36} 26}
37 27
38template <typename T> 28template <typename T>
39static constexpr const T* GetPointer(const TYPED_STORAGE(T) & ts) { 29static constexpr const T* GetPointer(const TypedStorage<T>& ts) {
40 return static_cast<const T*>(static_cast<const void*>(std::addressof(ts._storage))); 30 return static_cast<const T*>(static_cast<const void*>(std::addressof(ts.storage_)));
41} 31}
42 32
43namespace impl { 33namespace impl {
@@ -73,8 +63,7 @@ struct OffsetOfUnionHolder {
73 }; 63 };
74 64
75 template <typename ParentType, typename MemberType> 65 template <typename ParentType, typename MemberType>
76 union UnionImpl<ParentType, MemberType, MaxDepth> { /* Empty ... */ 66 union UnionImpl<ParentType, MemberType, MaxDepth> {};
77 };
78}; 67};
79 68
80template <typename ParentType, typename MemberType> 69template <typename ParentType, typename MemberType>
@@ -83,13 +72,11 @@ struct OffsetOfCalculator {
83 typename OffsetOfUnionHolder<sizeof(MemberType)>::template UnionImpl<ParentType, MemberType, 72 typename OffsetOfUnionHolder<sizeof(MemberType)>::template UnionImpl<ParentType, MemberType,
84 0>; 73 0>;
85 union Union { 74 union Union {
86 char c; 75 char c{};
87 UnionHolder first_union; 76 UnionHolder first_union;
88 TYPED_STORAGE(ParentType) parent; 77 TypedStorage<ParentType> parent;
89 78
90 /* This coerces the active member to be c. */ 79 constexpr Union() : c() {}
91 constexpr Union() : c() { /* ... */
92 }
93 }; 80 };
94 static constexpr Union U = {}; 81 static constexpr Union U = {};
95 82
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
index 0831dd5d2..6c4c8e9e4 100755
--- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp
+++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp
@@ -71,15 +71,8 @@ public:
71 } 71 }
72 72
73 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override { 73 void ExceptionRaised(u32 pc, Dynarmic::A32::Exception exception) override {
74 switch (exception) {
75 case Dynarmic::A32::Exception::UndefinedInstruction:
76 case Dynarmic::A32::Exception::UnpredictableInstruction:
77 break;
78 case Dynarmic::A32::Exception::Breakpoint:
79 break;
80 }
81 LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})", 74 LOG_CRITICAL(Core_ARM, "ExceptionRaised(exception = {}, pc = {:08X}, code = {:08X})",
82 static_cast<std::size_t>(exception), pc, MemoryReadCode(pc)); 75 exception, pc, MemoryReadCode(pc));
83 UNIMPLEMENTED(); 76 UNIMPLEMENTED();
84 } 77 }
85 78
diff --git a/src/core/file_sys/registered_cache.h b/src/core/file_sys/registered_cache.h
index 5b414b0f0..b08a1687a 100755
--- a/src/core/file_sys/registered_cache.h
+++ b/src/core/file_sys/registered_cache.h
@@ -67,18 +67,18 @@ public:
67 virtual void Refresh() = 0; 67 virtual void Refresh() = 0;
68 68
69 virtual bool HasEntry(u64 title_id, ContentRecordType type) const = 0; 69 virtual bool HasEntry(u64 title_id, ContentRecordType type) const = 0;
70 virtual bool HasEntry(ContentProviderEntry entry) const; 70 bool HasEntry(ContentProviderEntry entry) const;
71 71
72 virtual std::optional<u32> GetEntryVersion(u64 title_id) const = 0; 72 virtual std::optional<u32> GetEntryVersion(u64 title_id) const = 0;
73 73
74 virtual VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const = 0; 74 virtual VirtualFile GetEntryUnparsed(u64 title_id, ContentRecordType type) const = 0;
75 virtual VirtualFile GetEntryUnparsed(ContentProviderEntry entry) const; 75 VirtualFile GetEntryUnparsed(ContentProviderEntry entry) const;
76 76
77 virtual VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const = 0; 77 virtual VirtualFile GetEntryRaw(u64 title_id, ContentRecordType type) const = 0;
78 virtual VirtualFile GetEntryRaw(ContentProviderEntry entry) const; 78 VirtualFile GetEntryRaw(ContentProviderEntry entry) const;
79 79
80 virtual std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const = 0; 80 virtual std::unique_ptr<NCA> GetEntry(u64 title_id, ContentRecordType type) const = 0;
81 virtual std::unique_ptr<NCA> GetEntry(ContentProviderEntry entry) const; 81 std::unique_ptr<NCA> GetEntry(ContentProviderEntry entry) const;
82 82
83 virtual std::vector<ContentProviderEntry> ListEntries() const; 83 virtual std::vector<ContentProviderEntry> ListEntries() const;
84 84
diff --git a/src/core/hle/kernel/k_address_arbiter.cpp b/src/core/hle/kernel/k_address_arbiter.cpp
index bf5e97ef7..d9e702f13 100755
--- a/src/core/hle/kernel/k_address_arbiter.cpp
+++ b/src/core/hle/kernel/k_address_arbiter.cpp
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include "core/arm/exclusive_monitor.h" 5#include "core/arm/exclusive_monitor.h"
9#include "core/core.h" 6#include "core/core.h"
10#include "core/hle/kernel/k_address_arbiter.h" 7#include "core/hle/kernel/k_address_arbiter.h"
@@ -18,7 +15,8 @@
18 15
19namespace Kernel { 16namespace Kernel {
20 17
21KAddressArbiter::KAddressArbiter(Core::System& system) : system{system}, kernel{system.Kernel()} {} 18KAddressArbiter::KAddressArbiter(Core::System& system_)
19 : system{system_}, kernel{system.Kernel()} {}
22KAddressArbiter::~KAddressArbiter() = default; 20KAddressArbiter::~KAddressArbiter() = default;
23 21
24namespace { 22namespace {
@@ -278,6 +276,7 @@ ResultCode KAddressArbiter::WaitIfLessThan(VAddr addr, s32 value, bool decrement
278 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 276 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
279 thread_tree.insert(*cur_thread); 277 thread_tree.insert(*cur_thread);
280 cur_thread->SetState(ThreadState::Waiting); 278 cur_thread->SetState(ThreadState::Waiting);
279 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
281 } 280 }
282 281
283 // Cancel the timer wait. 282 // Cancel the timer wait.
@@ -341,6 +340,7 @@ ResultCode KAddressArbiter::WaitIfEqual(VAddr addr, s32 value, s64 timeout) {
341 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr); 340 cur_thread->SetAddressArbiter(std::addressof(thread_tree), addr);
342 thread_tree.insert(*cur_thread); 341 thread_tree.insert(*cur_thread);
343 cur_thread->SetState(ThreadState::Waiting); 342 cur_thread->SetState(ThreadState::Waiting);
343 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Arbitration);
344 } 344 }
345 345
346 // Cancel the timer wait. 346 // Cancel the timer wait.
diff --git a/src/core/hle/kernel/k_address_arbiter.h b/src/core/hle/kernel/k_address_arbiter.h
index 3a877e8a8..8d379b524 100755
--- a/src/core/hle/kernel/k_address_arbiter.h
+++ b/src/core/hle/kernel/k_address_arbiter.h
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include "common/assert.h" 7#include "common/assert.h"
@@ -26,7 +23,7 @@ class KAddressArbiter {
26public: 23public:
27 using ThreadTree = KConditionVariable::ThreadTree; 24 using ThreadTree = KConditionVariable::ThreadTree;
28 25
29 explicit KAddressArbiter(Core::System& system); 26 explicit KAddressArbiter(Core::System& system_);
30 ~KAddressArbiter(); 27 ~KAddressArbiter();
31 28
32 [[nodiscard]] ResultCode SignalToAddress(VAddr addr, Svc::SignalType type, s32 value, 29 [[nodiscard]] ResultCode SignalToAddress(VAddr addr, Svc::SignalType type, s32 value,
diff --git a/src/core/hle/kernel/k_condition_variable.cpp b/src/core/hle/kernel/k_condition_variable.cpp
index 9fde168fd..49a068310 100755
--- a/src/core/hle/kernel/k_condition_variable.cpp
+++ b/src/core/hle/kernel/k_condition_variable.cpp
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include <vector> 5#include <vector>
9 6
10#include "core/arm/exclusive_monitor.h" 7#include "core/arm/exclusive_monitor.h"
@@ -63,8 +60,8 @@ bool UpdateLockAtomic(Core::System& system, u32* out, VAddr address, u32 if_zero
63 60
64} // namespace 61} // namespace
65 62
66KConditionVariable::KConditionVariable(Core::System& system) 63KConditionVariable::KConditionVariable(Core::System& system_)
67 : system{system}, kernel{system.Kernel()} {} 64 : system{system_}, kernel{system.Kernel()} {}
68 65
69KConditionVariable::~KConditionVariable() = default; 66KConditionVariable::~KConditionVariable() = default;
70 67
@@ -136,6 +133,7 @@ ResultCode KConditionVariable::WaitForAddress(Handle handle, VAddr addr, u32 val
136 cur_thread->SetAddressKey(addr, value); 133 cur_thread->SetAddressKey(addr, value);
137 owner_thread->AddWaiter(cur_thread); 134 owner_thread->AddWaiter(cur_thread);
138 cur_thread->SetState(ThreadState::Waiting); 135 cur_thread->SetState(ThreadState::Waiting);
136 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
139 cur_thread->SetMutexWaitAddressForDebugging(addr); 137 cur_thread->SetMutexWaitAddressForDebugging(addr);
140 } 138 }
141 } 139 }
@@ -318,6 +316,7 @@ ResultCode KConditionVariable::Wait(VAddr addr, u64 key, u32 value, s64 timeout)
318 // If the timeout is non-zero, set the thread as waiting. 316 // If the timeout is non-zero, set the thread as waiting.
319 if (timeout != 0) { 317 if (timeout != 0) {
320 cur_thread->SetState(ThreadState::Waiting); 318 cur_thread->SetState(ThreadState::Waiting);
319 cur_thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::ConditionVar);
321 cur_thread->SetMutexWaitAddressForDebugging(addr); 320 cur_thread->SetMutexWaitAddressForDebugging(addr);
322 } 321 }
323 } 322 }
diff --git a/src/core/hle/kernel/k_condition_variable.h b/src/core/hle/kernel/k_condition_variable.h
index 6ed704f98..98ed5b323 100755
--- a/src/core/hle/kernel/k_condition_variable.h
+++ b/src/core/hle/kernel/k_condition_variable.h
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include "common/assert.h" 7#include "common/assert.h"
@@ -25,7 +22,7 @@ class KConditionVariable {
25public: 22public:
26 using ThreadTree = typename Thread::ConditionVariableThreadTreeType; 23 using ThreadTree = typename Thread::ConditionVariableThreadTreeType;
27 24
28 explicit KConditionVariable(Core::System& system); 25 explicit KConditionVariable(Core::System& system_);
29 ~KConditionVariable(); 26 ~KConditionVariable();
30 27
31 // Arbitration 28 // Arbitration
diff --git a/src/core/hle/kernel/k_synchronization_object.cpp b/src/core/hle/kernel/k_synchronization_object.cpp
index 1b1dda672..1c508cb55 100755
--- a/src/core/hle/kernel/k_synchronization_object.cpp
+++ b/src/core/hle/kernel/k_synchronization_object.cpp
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#include "common/assert.h" 5#include "common/assert.h"
9#include "common/common_types.h" 6#include "common/common_types.h"
10#include "core/hle/kernel/k_scheduler.h" 7#include "core/hle/kernel/k_scheduler.h"
@@ -75,12 +72,13 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
75 } 72 }
76 73
77 // For debugging only 74 // For debugging only
78 thread->SetWaitObjectsForDebugging(objects, num_objects); 75 thread->SetWaitObjectsForDebugging({objects, static_cast<std::size_t>(num_objects)});
79 76
80 // Mark the thread as waiting. 77 // Mark the thread as waiting.
81 thread->SetCancellable(); 78 thread->SetCancellable();
82 thread->SetSyncedObject(nullptr, Svc::ResultTimedOut); 79 thread->SetSyncedObject(nullptr, Svc::ResultTimedOut);
83 thread->SetState(ThreadState::Waiting); 80 thread->SetState(ThreadState::Waiting);
81 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Synchronization);
84 } 82 }
85 83
86 // The lock/sleep is done, so we should be able to get our result. 84 // The lock/sleep is done, so we should be able to get our result.
@@ -89,7 +87,7 @@ ResultCode KSynchronizationObject::Wait(KernelCore& kernel, s32* out_index,
89 thread->ClearCancellable(); 87 thread->ClearCancellable();
90 88
91 // For debugging only 89 // For debugging only
92 thread->SetWaitObjectsForDebugging(nullptr, 0); 90 thread->SetWaitObjectsForDebugging({});
93 91
94 // Cancel the timer as needed. 92 // Cancel the timer as needed.
95 if (timer != InvalidHandle) { 93 if (timer != InvalidHandle) {
diff --git a/src/core/hle/kernel/k_synchronization_object.h b/src/core/hle/kernel/k_synchronization_object.h
index 250318cb4..14d80ebf1 100755
--- a/src/core/hle/kernel/k_synchronization_object.h
+++ b/src/core/hle/kernel/k_synchronization_object.h
@@ -1,10 +1,7 @@
1// Copyright 2020 yuzu Emulator Project 1// Copyright 2021 yuzu Emulator Project
2// Licensed under GPLv2 or any later version 2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5// This file references various implementation details from Atmosphere, an open-source firmware for
6// the Nintendo Switch. Copyright 2018-2020 Atmosphere-NX.
7
8#pragma once 5#pragma once
9 6
10#include <vector> 7#include <vector>
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 8d03f16fb..c0ff287a6 100755
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -605,6 +605,8 @@ void KernelCore::Suspend(bool in_suspention) {
605 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting; 605 const auto state = should_suspend ? ThreadState::Runnable : ThreadState::Waiting;
606 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) { 606 for (std::size_t i = 0; i < Core::Hardware::NUM_CPU_CORES; i++) {
607 impl->suspend_threads[i]->SetState(state); 607 impl->suspend_threads[i]->SetState(state);
608 impl->suspend_threads[i]->SetWaitReasonForDebugging(
609 ThreadWaitReasonForDebugging::Suspended);
608 } 610 }
609 } 611 }
610} 612}
diff --git a/src/core/hle/kernel/process.h b/src/core/hle/kernel/process.h
index 21b6f9bd9..564e1f27d 100755
--- a/src/core/hle/kernel/process.h
+++ b/src/core/hle/kernel/process.h
@@ -301,7 +301,7 @@ public:
301 301
302 void LoadModule(CodeSet code_set, VAddr base_addr); 302 void LoadModule(CodeSet code_set, VAddr base_addr);
303 303
304 virtual bool IsSignaled() const override; 304 bool IsSignaled() const override;
305 305
306 /////////////////////////////////////////////////////////////////////////////////////////////// 306 ///////////////////////////////////////////////////////////////////////////////////////////////
307 // Thread-local storage management 307 // Thread-local storage management
diff --git a/src/core/hle/kernel/readable_event.h b/src/core/hle/kernel/readable_event.h
index 95894db8d..34e477274 100755
--- a/src/core/hle/kernel/readable_event.h
+++ b/src/core/hle/kernel/readable_event.h
@@ -45,7 +45,7 @@ public:
45 45
46 void Signal(); 46 void Signal();
47 47
48 virtual bool IsSignaled() const override; 48 bool IsSignaled() const override;
49 49
50private: 50private:
51 explicit ReadableEvent(KernelCore& kernel); 51 explicit ReadableEvent(KernelCore& kernel);
diff --git a/src/core/hle/kernel/server_port.h b/src/core/hle/kernel/server_port.h
index 587d01e0a..6470df993 100755
--- a/src/core/hle/kernel/server_port.h
+++ b/src/core/hle/kernel/server_port.h
@@ -79,7 +79,7 @@ public:
79 /// waiting to be accepted by this port. 79 /// waiting to be accepted by this port.
80 void AppendPendingSession(std::shared_ptr<ServerSession> pending_session); 80 void AppendPendingSession(std::shared_ptr<ServerSession> pending_session);
81 81
82 virtual bool IsSignaled() const override; 82 bool IsSignaled() const override;
83 83
84private: 84private:
85 /// ServerSessions waiting to be accepted by the port 85 /// ServerSessions waiting to be accepted by the port
diff --git a/src/core/hle/kernel/server_session.h b/src/core/hle/kernel/server_session.h
index bfeb05c8d..9155cf7f5 100755
--- a/src/core/hle/kernel/server_session.h
+++ b/src/core/hle/kernel/server_session.h
@@ -124,7 +124,7 @@ public:
124 convert_to_domain = true; 124 convert_to_domain = true;
125 } 125 }
126 126
127 virtual bool IsSignaled() const override; 127 bool IsSignaled() const override;
128 128
129private: 129private:
130 /// Queues a sync request from the emulated application. 130 /// Queues a sync request from the emulated application.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 99bb4ea20..cc8b661af 100755
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -347,6 +347,7 @@ static ResultCode SendSyncRequest(Core::System& system, Handle handle) {
347 { 347 {
348 KScopedSchedulerLock lock(kernel); 348 KScopedSchedulerLock lock(kernel);
349 thread->SetState(ThreadState::Waiting); 349 thread->SetState(ThreadState::Waiting);
350 thread->SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::IPC);
350 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming()); 351 session->SendSyncRequest(SharedFrom(thread), system.Memory(), system.CoreTiming());
351 } 352 }
352 353
diff --git a/src/core/hle/kernel/thread.cpp b/src/core/hle/kernel/thread.cpp
index eda56c31c..d97323255 100755
--- a/src/core/hle/kernel/thread.cpp
+++ b/src/core/hle/kernel/thread.cpp
@@ -215,7 +215,10 @@ VAddr Thread::GetCommandBufferAddress() const {
215void Thread::SetState(ThreadState state) { 215void Thread::SetState(ThreadState state) {
216 KScopedSchedulerLock sl(kernel); 216 KScopedSchedulerLock sl(kernel);
217 217
218 SetMutexWaitAddressForDebugging(0); 218 // Clear debugging state
219 SetMutexWaitAddressForDebugging({});
220 SetWaitReasonForDebugging({});
221
219 const ThreadState old_state = thread_state; 222 const ThreadState old_state = thread_state;
220 thread_state = 223 thread_state =
221 static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask)); 224 static_cast<ThreadState>((old_state & ~ThreadState::Mask) | (state & ThreadState::Mask));
@@ -386,6 +389,7 @@ ResultCode Thread::Sleep(s64 nanoseconds) {
386 { 389 {
387 KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds); 390 KScopedSchedulerLockAndSleep lock(kernel, event_handle, this, nanoseconds);
388 SetState(ThreadState::Waiting); 391 SetState(ThreadState::Waiting);
392 SetWaitReasonForDebugging(ThreadWaitReasonForDebugging::Sleep);
389 } 393 }
390 394
391 if (event_handle != InvalidHandle) { 395 if (event_handle != InvalidHandle) {
diff --git a/src/core/hle/kernel/thread.h b/src/core/hle/kernel/thread.h
index bf6bca2e4..6b66c9a0e 100755
--- a/src/core/hle/kernel/thread.h
+++ b/src/core/hle/kernel/thread.h
@@ -6,6 +6,7 @@
6 6
7#include <array> 7#include <array>
8#include <functional> 8#include <functional>
9#include <span>
9#include <string> 10#include <string>
10#include <utility> 11#include <utility>
11#include <vector> 12#include <vector>
@@ -113,6 +114,16 @@ enum class ThreadSchedFlags : u32 {
113 KernelInitPauseFlag = 1 << 8, 114 KernelInitPauseFlag = 1 << 8,
114}; 115};
115 116
117enum class ThreadWaitReasonForDebugging : u32 {
118 None, ///< Thread is not waiting
119 Sleep, ///< Thread is waiting due to a SleepThread SVC
120 IPC, ///< Thread is waiting for the reply from an IPC request
121 Synchronization, ///< Thread is waiting due to a WaitSynchronization SVC
122 ConditionVar, ///< Thread is waiting due to a WaitProcessWideKey SVC
123 Arbitration, ///< Thread is waiting due to a SignalToAddress/WaitForAddress SVC
124 Suspended, ///< Thread is waiting due to process suspension
125};
126
116class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> { 127class Thread final : public KSynchronizationObject, public boost::intrusive::list_base_hook<> {
117 friend class KScheduler; 128 friend class KScheduler;
118 friend class Process; 129 friend class Process;
@@ -514,11 +525,19 @@ public:
514 disable_count--; 525 disable_count--;
515 } 526 }
516 527
517 void SetWaitObjectsForDebugging(KSynchronizationObject** objects, s32 num_objects) { 528 void SetWaitReasonForDebugging(ThreadWaitReasonForDebugging reason) {
529 wait_reason_for_debugging = reason;
530 }
531
532 [[nodiscard]] ThreadWaitReasonForDebugging GetWaitReasonForDebugging() const {
533 return wait_reason_for_debugging;
534 }
535
536 void SetWaitObjectsForDebugging(const std::span<KSynchronizationObject*>& objects) {
518 wait_objects_for_debugging.clear(); 537 wait_objects_for_debugging.clear();
519 wait_objects_for_debugging.reserve(num_objects); 538 wait_objects_for_debugging.reserve(objects.size());
520 for (auto i = 0; i < num_objects; ++i) { 539 for (const auto& object : objects) {
521 wait_objects_for_debugging.emplace_back(objects[i]); 540 wait_objects_for_debugging.emplace_back(object);
522 } 541 }
523 } 542 }
524 543
@@ -548,11 +567,11 @@ public:
548 return address_key_value; 567 return address_key_value;
549 } 568 }
550 569
551 [[nodiscard]] void SetAddressKey(VAddr key) { 570 void SetAddressKey(VAddr key) {
552 address_key = key; 571 address_key = key;
553 } 572 }
554 573
555 [[nodiscard]] void SetAddressKey(VAddr key, u32 val) { 574 void SetAddressKey(VAddr key, u32 val) {
556 address_key = key; 575 address_key = key;
557 address_key_value = val; 576 address_key_value = val;
558 } 577 }
@@ -560,11 +579,11 @@ public:
560private: 579private:
561 static constexpr size_t PriorityInheritanceCountMax = 10; 580 static constexpr size_t PriorityInheritanceCountMax = 10;
562 union SyncObjectBuffer { 581 union SyncObjectBuffer {
563 std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects; 582 std::array<KSynchronizationObject*, Svc::ArgumentHandleCountMax> sync_objects{};
564 std::array<Handle, 583 std::array<Handle,
565 Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))> 584 Svc::ArgumentHandleCountMax*(sizeof(KSynchronizationObject*) / sizeof(Handle))>
566 handles; 585 handles;
567 constexpr SyncObjectBuffer() : sync_objects() {} 586 constexpr SyncObjectBuffer() {}
568 }; 587 };
569 static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles)); 588 static_assert(sizeof(SyncObjectBuffer::sync_objects) == sizeof(SyncObjectBuffer::handles));
570 589
@@ -707,6 +726,9 @@ private:
707 /// The current mutex wait address. This is used for debugging only. 726 /// The current mutex wait address. This is used for debugging only.
708 VAddr mutex_wait_address_for_debugging{}; 727 VAddr mutex_wait_address_for_debugging{};
709 728
729 /// The reason the thread is waiting. This is used for debugging only.
730 ThreadWaitReasonForDebugging wait_reason_for_debugging{};
731
710 KSynchronizationObject* signaling_object; 732 KSynchronizationObject* signaling_object;
711 ResultCode signaling_result{RESULT_SUCCESS}; 733 ResultCode signaling_result{RESULT_SUCCESS};
712 734
diff --git a/src/core/hle/service/apm/interface.cpp b/src/core/hle/service/apm/interface.cpp
index 298f6d520..0bff97a37 100755
--- a/src/core/hle/service/apm/interface.cpp
+++ b/src/core/hle/service/apm/interface.cpp
@@ -56,7 +56,7 @@ APM::APM(Core::System& system_, std::shared_ptr<Module> apm_, Controller& contro
56 static const FunctionInfo functions[] = { 56 static const FunctionInfo functions[] = {
57 {0, &APM::OpenSession, "OpenSession"}, 57 {0, &APM::OpenSession, "OpenSession"},
58 {1, &APM::GetPerformanceMode, "GetPerformanceMode"}, 58 {1, &APM::GetPerformanceMode, "GetPerformanceMode"},
59 {6, nullptr, "IsCpuOverclockEnabled"}, 59 {6, &APM::IsCpuOverclockEnabled, "IsCpuOverclockEnabled"},
60 }; 60 };
61 RegisterHandlers(functions); 61 RegisterHandlers(functions);
62} 62}
@@ -78,6 +78,14 @@ void APM::GetPerformanceMode(Kernel::HLERequestContext& ctx) {
78 rb.PushEnum(controller.GetCurrentPerformanceMode()); 78 rb.PushEnum(controller.GetCurrentPerformanceMode());
79} 79}
80 80
81void APM::IsCpuOverclockEnabled(Kernel::HLERequestContext& ctx) {
82 LOG_WARNING(Service_APM, "(STUBBED) called");
83
84 IPC::ResponseBuilder rb{ctx, 3};
85 rb.Push(RESULT_SUCCESS);
86 rb.Push(false);
87}
88
81APM_Sys::APM_Sys(Core::System& system_, Controller& controller_) 89APM_Sys::APM_Sys(Core::System& system_, Controller& controller_)
82 : ServiceFramework{system_, "apm:sys"}, controller{controller_} { 90 : ServiceFramework{system_, "apm:sys"}, controller{controller_} {
83 // clang-format off 91 // clang-format off
diff --git a/src/core/hle/service/apm/interface.h b/src/core/hle/service/apm/interface.h
index 7d57c4978..063ad5308 100755
--- a/src/core/hle/service/apm/interface.h
+++ b/src/core/hle/service/apm/interface.h
@@ -20,6 +20,7 @@ public:
20private: 20private:
21 void OpenSession(Kernel::HLERequestContext& ctx); 21 void OpenSession(Kernel::HLERequestContext& ctx);
22 void GetPerformanceMode(Kernel::HLERequestContext& ctx); 22 void GetPerformanceMode(Kernel::HLERequestContext& ctx);
23 void IsCpuOverclockEnabled(Kernel::HLERequestContext& ctx);
23 24
24 std::shared_ptr<Module> apm; 25 std::shared_ptr<Module> apm;
25 Controller& controller; 26 Controller& controller;
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
index 0ac5fc6ae..644e7a209 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_nvdec.cpp
@@ -34,8 +34,7 @@ NvResult nvhost_nvdec::Ioctl1(Ioctl command, const std::vector<u8>& input,
34 case 0xa: { 34 case 0xa: {
35 if (command.length == 0x1c) { 35 if (command.length == 0x1c) {
36 LOG_INFO(Service_NVDRV, "NVDEC video stream ended"); 36 LOG_INFO(Service_NVDRV, "NVDEC video stream ended");
37 Tegra::ChCommandHeaderList cmdlist(1); 37 Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
38 cmdlist[0] = Tegra::ChCommandHeader{0xDEADB33F};
39 system.GPU().PushCommandBuffer(cmdlist); 38 system.GPU().PushCommandBuffer(cmdlist);
40 system.GPU().MemoryManager().InvalidateQueuedCaches(); 39 system.GPU().MemoryManager().InvalidateQueuedCaches();
41 } 40 }
diff --git a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
index 9118ab254..a2a08af42 100755
--- a/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
+++ b/src/core/hle/service/nvdrv/devices/nvhost_vic.cpp
@@ -29,8 +29,13 @@ NvResult nvhost_vic::Ioctl1(Ioctl command, const std::vector<u8>& input, std::ve
29 return GetWaitbase(input, output); 29 return GetWaitbase(input, output);
30 case 0x9: 30 case 0x9:
31 return MapBuffer(input, output); 31 return MapBuffer(input, output);
32 case 0xa: 32 case 0xa: {
33 if (command.length == 0x1c) {
34 Tegra::ChCommandHeaderList cmdlist{{0xDEADB33F}};
35 system.GPU().PushCommandBuffer(cmdlist);
36 }
33 return UnmapBuffer(input, output); 37 return UnmapBuffer(input, output);
38 }
34 default: 39 default:
35 break; 40 break;
36 } 41 }
diff --git a/src/core/hle/service/nvflinger/buffer_queue.cpp b/src/core/hle/service/nvflinger/buffer_queue.cpp
index c68905e19..5578181a4 100755
--- a/src/core/hle/service/nvflinger/buffer_queue.cpp
+++ b/src/core/hle/service/nvflinger/buffer_queue.cpp
@@ -180,9 +180,11 @@ u32 BufferQueue::Query(QueryType type) {
180 switch (type) { 180 switch (type) {
181 case QueryType::NativeWindowFormat: 181 case QueryType::NativeWindowFormat:
182 return static_cast<u32>(PixelFormat::RGBA8888); 182 return static_cast<u32>(PixelFormat::RGBA8888);
183 case QueryType::NativeWindowWidth:
184 case QueryType::NativeWindowHeight:
185 break;
183 } 186 }
184 187 UNIMPLEMENTED_MSG("Unimplemented query type={}", type);
185 UNIMPLEMENTED();
186 return 0; 188 return 0;
187} 189}
188 190
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index 5b637f3c5..8a606b448 100755
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -6,7 +6,6 @@ add_executable(tests
6 common/ring_buffer.cpp 6 common/ring_buffer.cpp
7 core/core_timing.cpp 7 core/core_timing.cpp
8 tests.cpp 8 tests.cpp
9 video_core/buffer_base.cpp
10) 9)
11 10
12create_target_directory_groups(tests) 11create_target_directory_groups(tests)
diff --git a/src/tests/common/ring_buffer.cpp b/src/tests/common/ring_buffer.cpp
index c883c4d56..54def22da 100755
--- a/src/tests/common/ring_buffer.cpp
+++ b/src/tests/common/ring_buffer.cpp
@@ -20,60 +20,60 @@ TEST_CASE("RingBuffer: Basic Tests", "[common]") {
20 for (std::size_t i = 0; i < 4; i++) { 20 for (std::size_t i = 0; i < 4; i++) {
21 const char elem = static_cast<char>(i); 21 const char elem = static_cast<char>(i);
22 const std::size_t count = buf.Push(&elem, 1); 22 const std::size_t count = buf.Push(&elem, 1);
23 REQUIRE(count == 1); 23 REQUIRE(count == 1U);
24 } 24 }
25 25
26 REQUIRE(buf.Size() == 4); 26 REQUIRE(buf.Size() == 4U);
27 27
28 // Pushing values into a full ring buffer should fail. 28 // Pushing values into a full ring buffer should fail.
29 { 29 {
30 const char elem = static_cast<char>(42); 30 const char elem = static_cast<char>(42);
31 const std::size_t count = buf.Push(&elem, 1); 31 const std::size_t count = buf.Push(&elem, 1);
32 REQUIRE(count == 0); 32 REQUIRE(count == 0U);
33 } 33 }
34 34
35 REQUIRE(buf.Size() == 4); 35 REQUIRE(buf.Size() == 4U);
36 36
37 // Popping multiple values from a ring buffer with values should succeed. 37 // Popping multiple values from a ring buffer with values should succeed.
38 { 38 {
39 const std::vector<char> popped = buf.Pop(2); 39 const std::vector<char> popped = buf.Pop(2);
40 REQUIRE(popped.size() == 2); 40 REQUIRE(popped.size() == 2U);
41 REQUIRE(popped[0] == 0); 41 REQUIRE(popped[0] == 0);
42 REQUIRE(popped[1] == 1); 42 REQUIRE(popped[1] == 1);
43 } 43 }
44 44
45 REQUIRE(buf.Size() == 2); 45 REQUIRE(buf.Size() == 2U);
46 46
47 // Popping a single value from a ring buffer with values should succeed. 47 // Popping a single value from a ring buffer with values should succeed.
48 { 48 {
49 const std::vector<char> popped = buf.Pop(1); 49 const std::vector<char> popped = buf.Pop(1);
50 REQUIRE(popped.size() == 1); 50 REQUIRE(popped.size() == 1U);
51 REQUIRE(popped[0] == 2); 51 REQUIRE(popped[0] == 2);
52 } 52 }
53 53
54 REQUIRE(buf.Size() == 1); 54 REQUIRE(buf.Size() == 1U);
55 55
56 // Pushing more values than space available should partially suceed. 56 // Pushing more values than space available should partially suceed.
57 { 57 {
58 std::vector<char> to_push(6); 58 std::vector<char> to_push(6);
59 std::iota(to_push.begin(), to_push.end(), 88); 59 std::iota(to_push.begin(), to_push.end(), 88);
60 const std::size_t count = buf.Push(to_push); 60 const std::size_t count = buf.Push(to_push);
61 REQUIRE(count == 3); 61 REQUIRE(count == 3U);
62 } 62 }
63 63
64 REQUIRE(buf.Size() == 4); 64 REQUIRE(buf.Size() == 4U);
65 65
66 // Doing an unlimited pop should pop all values. 66 // Doing an unlimited pop should pop all values.
67 { 67 {
68 const std::vector<char> popped = buf.Pop(); 68 const std::vector<char> popped = buf.Pop();
69 REQUIRE(popped.size() == 4); 69 REQUIRE(popped.size() == 4U);
70 REQUIRE(popped[0] == 3); 70 REQUIRE(popped[0] == 3);
71 REQUIRE(popped[1] == 88); 71 REQUIRE(popped[1] == 88);
72 REQUIRE(popped[2] == 89); 72 REQUIRE(popped[2] == 89);
73 REQUIRE(popped[3] == 90); 73 REQUIRE(popped[3] == 90);
74 } 74 }
75 75
76 REQUIRE(buf.Size() == 0); 76 REQUIRE(buf.Size() == 0U);
77} 77}
78 78
79TEST_CASE("RingBuffer: Threaded Test", "[common]") { 79TEST_CASE("RingBuffer: Threaded Test", "[common]") {
@@ -93,7 +93,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
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], 1); c > 0) {
96 REQUIRE(c == 1); 96 REQUIRE(c == 1U);
97 i++; 97 i++;
98 next_value(value); 98 next_value(value);
99 } else { 99 } else {
@@ -108,7 +108,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
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(1); v.size() > 0) {
111 REQUIRE(v.size() == 2); 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]);
114 i++; 114 i++;
@@ -123,7 +123,7 @@ TEST_CASE("RingBuffer: Threaded Test", "[common]") {
123 producer.join(); 123 producer.join();
124 consumer.join(); 124 consumer.join();
125 125
126 REQUIRE(buf.Size() == 0); 126 REQUIRE(buf.Size() == 0U);
127 printf("RingBuffer: Threaded Test: full: %zu, empty: %zu\n", full, empty); 127 printf("RingBuffer: Threaded Test: full: %zu, empty: %zu\n", full, empty);
128} 128}
129 129
diff --git a/src/video_core/CMakeLists.txt b/src/video_core/CMakeLists.txt
index e59d6d0ad..a1953a529 100755
--- a/src/video_core/CMakeLists.txt
+++ b/src/video_core/CMakeLists.txt
@@ -1,7 +1,6 @@
1add_subdirectory(host_shaders) 1add_subdirectory(host_shaders)
2 2
3add_library(video_core STATIC 3add_library(video_core STATIC
4 buffer_cache/buffer_base.h
5 buffer_cache/buffer_block.h 4 buffer_cache/buffer_block.h
6 buffer_cache/buffer_cache.h 5 buffer_cache/buffer_cache.h
7 buffer_cache/map_interval.cpp 6 buffer_cache/map_interval.cpp
diff --git a/src/video_core/cdma_pusher.cpp b/src/video_core/cdma_pusher.cpp
index 94679d5d1..1228d38c8 100755
--- a/src/video_core/cdma_pusher.cpp
+++ b/src/video_core/cdma_pusher.cpp
@@ -37,59 +37,43 @@ CDmaPusher::CDmaPusher(GPU& gpu_)
37 37
38CDmaPusher::~CDmaPusher() = default; 38CDmaPusher::~CDmaPusher() = default;
39 39
40void CDmaPusher::Push(ChCommandHeaderList&& entries) { 40void CDmaPusher::ProcessEntries(ChCommandHeaderList&& entries) {
41 cdma_queue.push(std::move(entries)); 41 for (const auto& value : entries) {
42}
43
44void CDmaPusher::DispatchCalls() {
45 while (!cdma_queue.empty()) {
46 Step();
47 }
48}
49
50void CDmaPusher::Step() {
51 const auto entries{cdma_queue.front()};
52 cdma_queue.pop();
53
54 std::vector<u32> values(entries.size());
55 std::memcpy(values.data(), entries.data(), entries.size() * sizeof(u32));
56
57 for (const u32 value : values) {
58 if (mask != 0) { 42 if (mask != 0) {
59 const u32 lbs = Common::CountTrailingZeroes32(mask); 43 const u32 lbs = Common::CountTrailingZeroes32(mask);
60 mask &= ~(1U << lbs); 44 mask &= ~(1U << lbs);
61 ExecuteCommand(static_cast<u32>(offset + lbs), value); 45 ExecuteCommand(offset + lbs, value.raw);
62 continue; 46 continue;
63 } else if (count != 0) { 47 } else if (count != 0) {
64 --count; 48 --count;
65 ExecuteCommand(static_cast<u32>(offset), value); 49 ExecuteCommand(offset, value.raw);
66 if (incrementing) { 50 if (incrementing) {
67 ++offset; 51 ++offset;
68 } 52 }
69 continue; 53 continue;
70 } 54 }
71 const auto mode = static_cast<ChSubmissionMode>((value >> 28) & 0xf); 55 const auto mode = value.submission_mode.Value();
72 switch (mode) { 56 switch (mode) {
73 case ChSubmissionMode::SetClass: { 57 case ChSubmissionMode::SetClass: {
74 mask = value & 0x3f; 58 mask = value.value & 0x3f;
75 offset = (value >> 16) & 0xfff; 59 offset = value.method_offset;
76 current_class = static_cast<ChClassId>((value >> 6) & 0x3ff); 60 current_class = static_cast<ChClassId>((value.value >> 6) & 0x3ff);
77 break; 61 break;
78 } 62 }
79 case ChSubmissionMode::Incrementing: 63 case ChSubmissionMode::Incrementing:
80 case ChSubmissionMode::NonIncrementing: 64 case ChSubmissionMode::NonIncrementing:
81 count = value & 0xffff; 65 count = value.value;
82 offset = (value >> 16) & 0xfff; 66 offset = value.method_offset;
83 incrementing = mode == ChSubmissionMode::Incrementing; 67 incrementing = mode == ChSubmissionMode::Incrementing;
84 break; 68 break;
85 case ChSubmissionMode::Mask: 69 case ChSubmissionMode::Mask:
86 mask = value & 0xffff; 70 mask = value.value;
87 offset = (value >> 16) & 0xfff; 71 offset = value.method_offset;
88 break; 72 break;
89 case ChSubmissionMode::Immediate: { 73 case ChSubmissionMode::Immediate: {
90 const u32 data = value & 0xfff; 74 const u32 data = value.value & 0xfff;
91 offset = (value >> 16) & 0xfff; 75 offset = value.method_offset;
92 ExecuteCommand(static_cast<u32>(offset), data); 76 ExecuteCommand(offset, data);
93 break; 77 break;
94 } 78 }
95 default: 79 default:
@@ -102,8 +86,8 @@ void CDmaPusher::Step() {
102void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) { 86void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
103 switch (current_class) { 87 switch (current_class) {
104 case ChClassId::NvDec: 88 case ChClassId::NvDec:
105 ThiStateWrite(nvdec_thi_state, state_offset, {data}); 89 ThiStateWrite(nvdec_thi_state, offset, data);
106 switch (static_cast<ThiMethod>(state_offset)) { 90 switch (static_cast<ThiMethod>(offset)) {
107 case ThiMethod::IncSyncpt: { 91 case ThiMethod::IncSyncpt: {
108 LOG_DEBUG(Service_NVDRV, "NVDEC Class IncSyncpt Method"); 92 LOG_DEBUG(Service_NVDRV, "NVDEC Class IncSyncpt Method");
109 const auto syncpoint_id = static_cast<u32>(data & 0xFF); 93 const auto syncpoint_id = static_cast<u32>(data & 0xFF);
@@ -120,7 +104,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
120 LOG_DEBUG(Service_NVDRV, "NVDEC method 0x{:X}", 104 LOG_DEBUG(Service_NVDRV, "NVDEC method 0x{:X}",
121 static_cast<u32>(nvdec_thi_state.method_0)); 105 static_cast<u32>(nvdec_thi_state.method_0));
122 nvdec_processor->ProcessMethod(static_cast<Nvdec::Method>(nvdec_thi_state.method_0), 106 nvdec_processor->ProcessMethod(static_cast<Nvdec::Method>(nvdec_thi_state.method_0),
123 {data}); 107 data);
124 break; 108 break;
125 default: 109 default:
126 break; 110 break;
@@ -144,7 +128,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
144 case ThiMethod::SetMethod1: 128 case ThiMethod::SetMethod1:
145 LOG_DEBUG(Service_NVDRV, "VIC method 0x{:X}, Args=({})", 129 LOG_DEBUG(Service_NVDRV, "VIC method 0x{:X}, Args=({})",
146 static_cast<u32>(vic_thi_state.method_0), data); 130 static_cast<u32>(vic_thi_state.method_0), data);
147 vic_processor->ProcessMethod(static_cast<Vic::Method>(vic_thi_state.method_0), {data}); 131 vic_processor->ProcessMethod(static_cast<Vic::Method>(vic_thi_state.method_0), data);
148 break; 132 break;
149 default: 133 default:
150 break; 134 break;
@@ -153,7 +137,7 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
153 case ChClassId::Host1x: 137 case ChClassId::Host1x:
154 // This device is mainly for syncpoint synchronization 138 // This device is mainly for syncpoint synchronization
155 LOG_DEBUG(Service_NVDRV, "Host1X Class Method"); 139 LOG_DEBUG(Service_NVDRV, "Host1X Class Method");
156 host1x_processor->ProcessMethod(static_cast<Host1x::Method>(state_offset), {data}); 140 host1x_processor->ProcessMethod(static_cast<Host1x::Method>(offset), data);
157 break; 141 break;
158 default: 142 default:
159 UNIMPLEMENTED_MSG("Current class not implemented {:X}", static_cast<u32>(current_class)); 143 UNIMPLEMENTED_MSG("Current class not implemented {:X}", static_cast<u32>(current_class));
@@ -161,10 +145,9 @@ void CDmaPusher::ExecuteCommand(u32 state_offset, u32 data) {
161 } 145 }
162} 146}
163 147
164void CDmaPusher::ThiStateWrite(ThiRegisters& state, u32 state_offset, 148void CDmaPusher::ThiStateWrite(ThiRegisters& state, u32 state_offset, u32 argument) {
165 const std::vector<u32>& arguments) { 149 u8* const offset_ptr = reinterpret_cast<u8*>(&state) + sizeof(u32) * state_offset;
166 u8* const state_offset_ptr = reinterpret_cast<u8*>(&state) + sizeof(u32) * state_offset; 150 std::memcpy(offset_ptr, &argument, sizeof(u32));
167 std::memcpy(state_offset_ptr, arguments.data(), sizeof(u32) * arguments.size());
168} 151}
169 152
170} // namespace Tegra 153} // namespace Tegra
diff --git a/src/video_core/cdma_pusher.h b/src/video_core/cdma_pusher.h
index 8ca70b6dd..1bada44dd 100755
--- a/src/video_core/cdma_pusher.h
+++ b/src/video_core/cdma_pusher.h
@@ -5,9 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include <memory> 7#include <memory>
8#include <unordered_map>
9#include <vector> 8#include <vector>
10#include <queue>
11 9
12#include "common/bit_field.h" 10#include "common/bit_field.h"
13#include "common/common_types.h" 11#include "common/common_types.h"
@@ -16,9 +14,9 @@
16namespace Tegra { 14namespace Tegra {
17 15
18class GPU; 16class GPU;
17class Host1x;
19class Nvdec; 18class Nvdec;
20class Vic; 19class Vic;
21class Host1x;
22 20
23enum class ChSubmissionMode : u32 { 21enum class ChSubmissionMode : u32 {
24 SetClass = 0, 22 SetClass = 0,
@@ -48,16 +46,10 @@ enum class ChClassId : u32 {
48 NvDec = 0xf0 46 NvDec = 0xf0
49}; 47};
50 48
51enum class ChMethod : u32 {
52 Empty = 0,
53 SetMethod = 0x10,
54 SetData = 0x11,
55};
56
57union ChCommandHeader { 49union ChCommandHeader {
58 u32 raw; 50 u32 raw;
59 BitField<0, 16, u32> value; 51 BitField<0, 16, u32> value;
60 BitField<16, 12, ChMethod> method_offset; 52 BitField<16, 12, u32> method_offset;
61 BitField<28, 4, ChSubmissionMode> submission_mode; 53 BitField<28, 4, ChSubmissionMode> submission_mode;
62}; 54};
63static_assert(sizeof(ChCommandHeader) == sizeof(u32), "ChCommand header is an invalid size"); 55static_assert(sizeof(ChCommandHeader) == sizeof(u32), "ChCommand header is an invalid size");
@@ -99,21 +91,15 @@ public:
99 explicit CDmaPusher(GPU& gpu_); 91 explicit CDmaPusher(GPU& gpu_);
100 ~CDmaPusher(); 92 ~CDmaPusher();
101 93
102 /// Push NVDEC command buffer entries into queue 94 /// Process the command entry
103 void Push(ChCommandHeaderList&& entries); 95 void ProcessEntries(ChCommandHeaderList&& entries);
104
105 /// Process queued command buffer entries
106 void DispatchCalls();
107
108 /// Process one queue element
109 void Step();
110 96
97private:
111 /// Invoke command class devices to execute the command based on the current state 98 /// Invoke command class devices to execute the command based on the current state
112 void ExecuteCommand(u32 state_offset, u32 data); 99 void ExecuteCommand(u32 state_offset, u32 data);
113 100
114private:
115 /// Write arguments value to the ThiRegisters member at the specified offset 101 /// Write arguments value to the ThiRegisters member at the specified offset
116 void ThiStateWrite(ThiRegisters& state, u32 state_offset, const std::vector<u32>& arguments); 102 void ThiStateWrite(ThiRegisters& state, u32 offset, u32 argument);
117 103
118 GPU& gpu; 104 GPU& gpu;
119 std::shared_ptr<Tegra::Nvdec> nvdec_processor; 105 std::shared_ptr<Tegra::Nvdec> nvdec_processor;
@@ -124,13 +110,10 @@ private:
124 ThiRegisters vic_thi_state{}; 110 ThiRegisters vic_thi_state{};
125 ThiRegisters nvdec_thi_state{}; 111 ThiRegisters nvdec_thi_state{};
126 112
127 s32 count{}; 113 u32 count{};
128 s32 offset{}; 114 u32 offset{};
129 s32 mask{}; 115 u32 mask{};
130 bool incrementing{}; 116 bool incrementing{};
131
132 // Queue of command lists to be processed
133 std::queue<ChCommandHeaderList> cdma_queue;
134}; 117};
135 118
136} // namespace Tegra 119} // namespace Tegra
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp
index 39bc923a5..d02dc6260 100755
--- a/src/video_core/command_classes/codecs/codec.cpp
+++ b/src/video_core/command_classes/codecs/codec.cpp
@@ -44,8 +44,10 @@ Codec::~Codec() {
44} 44}
45 45
46void Codec::SetTargetCodec(NvdecCommon::VideoCodec codec) { 46void Codec::SetTargetCodec(NvdecCommon::VideoCodec codec) {
47 LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", codec); 47 if (current_codec != codec) {
48 current_codec = codec; 48 LOG_INFO(Service_NVDRV, "NVDEC video codec initialized to {}", static_cast<u32>(codec));
49 current_codec = codec;
50 }
49} 51}
50 52
51void Codec::StateWrite(u32 offset, u64 arguments) { 53void Codec::StateWrite(u32 offset, u64 arguments) {
@@ -55,7 +57,6 @@ void Codec::StateWrite(u32 offset, u64 arguments) {
55 57
56void Codec::Decode() { 58void Codec::Decode() {
57 bool is_first_frame = false; 59 bool is_first_frame = false;
58
59 if (!initialized) { 60 if (!initialized) {
60 if (current_codec == NvdecCommon::VideoCodec::H264) { 61 if (current_codec == NvdecCommon::VideoCodec::H264) {
61 av_codec = avcodec_find_decoder(AV_CODEC_ID_H264); 62 av_codec = avcodec_find_decoder(AV_CODEC_ID_H264);
diff --git a/src/video_core/command_classes/nvdec.cpp b/src/video_core/command_classes/nvdec.cpp
index 79e1f4e13..e4f919afd 100755
--- a/src/video_core/command_classes/nvdec.cpp
+++ b/src/video_core/command_classes/nvdec.cpp
@@ -12,16 +12,16 @@ Nvdec::Nvdec(GPU& gpu_) : gpu(gpu_), codec(std::make_unique<Codec>(gpu)) {}
12 12
13Nvdec::~Nvdec() = default; 13Nvdec::~Nvdec() = default;
14 14
15void Nvdec::ProcessMethod(Method method, const std::vector<u32>& arguments) { 15void Nvdec::ProcessMethod(Method method, u32 argument) {
16 if (method == Method::SetVideoCodec) { 16 if (method == Method::SetVideoCodec) {
17 codec->StateWrite(static_cast<u32>(method), arguments[0]); 17 codec->StateWrite(static_cast<u32>(method), argument);
18 } else { 18 } else {
19 codec->StateWrite(static_cast<u32>(method), static_cast<u64>(arguments[0]) << 8); 19 codec->StateWrite(static_cast<u32>(method), static_cast<u64>(argument) << 8);
20 } 20 }
21 21
22 switch (method) { 22 switch (method) {
23 case Method::SetVideoCodec: 23 case Method::SetVideoCodec:
24 codec->SetTargetCodec(static_cast<NvdecCommon::VideoCodec>(arguments[0])); 24 codec->SetTargetCodec(static_cast<NvdecCommon::VideoCodec>(argument));
25 break; 25 break;
26 case Method::Execute: 26 case Method::Execute:
27 Execute(); 27 Execute();
diff --git a/src/video_core/command_classes/nvdec.h b/src/video_core/command_classes/nvdec.h
index e4877c533..e66be80b8 100755
--- a/src/video_core/command_classes/nvdec.h
+++ b/src/video_core/command_classes/nvdec.h
@@ -23,7 +23,7 @@ public:
23 ~Nvdec(); 23 ~Nvdec();
24 24
25 /// Writes the method into the state, Invoke Execute() if encountered 25 /// Writes the method into the state, Invoke Execute() if encountered
26 void ProcessMethod(Method method, const std::vector<u32>& arguments); 26 void ProcessMethod(Method method, u32 argument);
27 27
28 /// Return most recently decoded frame 28 /// Return most recently decoded frame
29 [[nodiscard]] AVFramePtr GetFrame(); 29 [[nodiscard]] AVFramePtr GetFrame();
diff --git a/src/video_core/command_classes/vic.cpp b/src/video_core/command_classes/vic.cpp
index 55e632346..26ff755d0 100755
--- a/src/video_core/command_classes/vic.cpp
+++ b/src/video_core/command_classes/vic.cpp
@@ -18,18 +18,14 @@ extern "C" {
18namespace Tegra { 18namespace Tegra {
19 19
20Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_) 20Vic::Vic(GPU& gpu_, std::shared_ptr<Nvdec> nvdec_processor_)
21 : gpu(gpu_), nvdec_processor(std::move(nvdec_processor_)) {} 21 : gpu(gpu_),
22Vic::~Vic() = default; 22 nvdec_processor(std::move(nvdec_processor_)), converted_frame_buffer{nullptr, av_free} {}
23 23
24void Vic::VicStateWrite(u32 offset, u32 arguments) { 24Vic::~Vic() = default;
25 u8* const state_offset = reinterpret_cast<u8*>(&vic_state) + offset * sizeof(u32);
26 std::memcpy(state_offset, &arguments, sizeof(u32));
27}
28 25
29void Vic::ProcessMethod(Method method, const std::vector<u32>& arguments) { 26void Vic::ProcessMethod(Method method, u32 argument) {
30 LOG_DEBUG(HW_GPU, "Vic method 0x{:X}", method); 27 LOG_DEBUG(HW_GPU, "Vic method 0x{:X}", static_cast<u32>(method));
31 VicStateWrite(static_cast<u32>(method), arguments[0]); 28 const u64 arg = static_cast<u64>(argument) << 8;
32 const u64 arg = static_cast<u64>(arguments[0]) << 8;
33 switch (method) { 29 switch (method) {
34 case Method::Execute: 30 case Method::Execute:
35 Execute(); 31 Execute();
@@ -53,8 +49,7 @@ void Vic::ProcessMethod(Method method, const std::vector<u32>& arguments) {
53 49
54void Vic::Execute() { 50void Vic::Execute() {
55 if (output_surface_luma_address == 0) { 51 if (output_surface_luma_address == 0) {
56 LOG_ERROR(Service_NVDRV, "VIC Luma address not set. Received 0x{:X}", 52 LOG_ERROR(Service_NVDRV, "VIC Luma address not set.");
57 vic_state.output_surface.luma_offset);
58 return; 53 return;
59 } 54 }
60 const VicConfig config{gpu.MemoryManager().Read<u64>(config_struct_address + 0x20)}; 55 const VicConfig config{gpu.MemoryManager().Read<u64>(config_struct_address + 0x20)};
@@ -89,8 +84,10 @@ void Vic::Execute() {
89 // Get Converted frame 84 // Get Converted frame
90 const std::size_t linear_size = frame->width * frame->height * 4; 85 const std::size_t linear_size = frame->width * frame->height * 4;
91 86
92 using AVMallocPtr = std::unique_ptr<u8, decltype(&av_free)>; 87 // Only allocate frame_buffer once per stream, as the size is not expected to change
93 AVMallocPtr converted_frame_buffer{static_cast<u8*>(av_malloc(linear_size)), av_free}; 88 if (!converted_frame_buffer) {
89 converted_frame_buffer = AVMallocPtr{static_cast<u8*>(av_malloc(linear_size)), av_free};
90 }
94 91
95 const int converted_stride{frame->width * 4}; 92 const int converted_stride{frame->width * 4};
96 u8* const converted_frame_buf_addr{converted_frame_buffer.get()}; 93 u8* const converted_frame_buf_addr{converted_frame_buffer.get()};
@@ -104,12 +101,12 @@ void Vic::Execute() {
104 const u32 block_height = static_cast<u32>(config.block_linear_height_log2); 101 const u32 block_height = static_cast<u32>(config.block_linear_height_log2);
105 const auto size = Tegra::Texture::CalculateSize(true, 4, frame->width, frame->height, 1, 102 const auto size = Tegra::Texture::CalculateSize(true, 4, frame->width, frame->height, 1,
106 block_height, 0); 103 block_height, 0);
107 std::vector<u8> swizzled_data(size); 104 luma_buffer.resize(size);
108 Tegra::Texture::SwizzleSubrect(frame->width, frame->height, frame->width * 4, 105 Tegra::Texture::SwizzleSubrect(frame->width, frame->height, frame->width * 4,
109 frame->width, 4, swizzled_data.data(), 106 frame->width, 4, luma_buffer.data(),
110 converted_frame_buffer.get(), block_height, 0, 0); 107 converted_frame_buffer.get(), block_height, 0, 0);
111 108
112 gpu.MemoryManager().WriteBlock(output_surface_luma_address, swizzled_data.data(), size); 109 gpu.MemoryManager().WriteBlock(output_surface_luma_address, luma_buffer.data(), size);
113 gpu.Maxwell3D().OnMemoryWrite(); 110 gpu.Maxwell3D().OnMemoryWrite();
114 } else { 111 } else {
115 // send pitch linear frame 112 // send pitch linear frame
@@ -134,15 +131,15 @@ void Vic::Execute() {
134 const auto stride = frame->linesize[0]; 131 const auto stride = frame->linesize[0];
135 const auto half_stride = frame->linesize[1]; 132 const auto half_stride = frame->linesize[1];
136 133
137 std::vector<u8> luma_buffer(aligned_width * surface_height); 134 luma_buffer.resize(aligned_width * surface_height);
138 std::vector<u8> chroma_buffer(aligned_width * half_height); 135 chroma_buffer.resize(aligned_width * half_height);
139 136
140 // Populate luma buffer 137 // Populate luma buffer
141 for (std::size_t y = 0; y < surface_height - 1; ++y) { 138 for (std::size_t y = 0; y < surface_height - 1; ++y) {
142 std::size_t src = y * stride; 139 const std::size_t src = y * stride;
143 std::size_t dst = y * aligned_width; 140 const std::size_t dst = y * aligned_width;
144 141
145 std::size_t size = surface_width; 142 const std::size_t size = surface_width;
146 143
147 for (std::size_t offset = 0; offset < size; ++offset) { 144 for (std::size_t offset = 0; offset < size; ++offset) {
148 luma_buffer[dst + offset] = luma_ptr[src + offset]; 145 luma_buffer[dst + offset] = luma_ptr[src + offset];
@@ -153,8 +150,8 @@ void Vic::Execute() {
153 150
154 // Populate chroma buffer from both channels with interleaving. 151 // Populate chroma buffer from both channels with interleaving.
155 for (std::size_t y = 0; y < half_height; ++y) { 152 for (std::size_t y = 0; y < half_height; ++y) {
156 std::size_t src = y * half_stride; 153 const std::size_t src = y * half_stride;
157 std::size_t dst = y * aligned_width; 154 const std::size_t dst = y * aligned_width;
158 155
159 for (std::size_t x = 0; x < half_width; ++x) { 156 for (std::size_t x = 0; x < half_width; ++x) {
160 chroma_buffer[dst + x * 2] = chroma_b_ptr[src + x]; 157 chroma_buffer[dst + x * 2] = chroma_b_ptr[src + x];
diff --git a/src/video_core/command_classes/vic.h b/src/video_core/command_classes/vic.h
index 8c4e284a1..f5a2ed100 100755
--- a/src/video_core/command_classes/vic.h
+++ b/src/video_core/command_classes/vic.h
@@ -15,43 +15,6 @@ namespace Tegra {
15class GPU; 15class GPU;
16class Nvdec; 16class Nvdec;
17 17
18struct PlaneOffsets {
19 u32 luma_offset{};
20 u32 chroma_u_offset{};
21 u32 chroma_v_offset{};
22};
23
24struct VicRegisters {
25 INSERT_PADDING_WORDS(64);
26 u32 nop{};
27 INSERT_PADDING_WORDS(15);
28 u32 pm_trigger{};
29 INSERT_PADDING_WORDS(47);
30 u32 set_application_id{};
31 u32 set_watchdog_timer{};
32 INSERT_PADDING_WORDS(17);
33 u32 context_save_area{};
34 u32 context_switch{};
35 INSERT_PADDING_WORDS(43);
36 u32 execute{};
37 INSERT_PADDING_WORDS(63);
38 std::array<std::array<PlaneOffsets, 8>, 8> surfacex_slots{};
39 u32 picture_index{};
40 u32 control_params{};
41 u32 config_struct_offset{};
42 u32 filter_struct_offset{};
43 u32 palette_offset{};
44 u32 hist_offset{};
45 u32 context_id{};
46 u32 fce_ucode_size{};
47 PlaneOffsets output_surface{};
48 u32 fce_ucode_offset{};
49 INSERT_PADDING_WORDS(4);
50 std::array<u32, 8> slot_context_id{};
51 INSERT_PADDING_WORDS(16);
52};
53static_assert(sizeof(VicRegisters) == 0x7A0, "VicRegisters is an invalid size");
54
55class Vic { 18class Vic {
56public: 19public:
57 enum class Method : u32 { 20 enum class Method : u32 {
@@ -67,14 +30,11 @@ public:
67 ~Vic(); 30 ~Vic();
68 31
69 /// Write to the device state. 32 /// Write to the device state.
70 void ProcessMethod(Method method, const std::vector<u32>& arguments); 33 void ProcessMethod(Method method, u32 argument);
71 34
72private: 35private:
73 void Execute(); 36 void Execute();
74 37
75 void VicStateWrite(u32 offset, u32 arguments);
76 VicRegisters vic_state{};
77
78 enum class VideoPixelFormat : u64_le { 38 enum class VideoPixelFormat : u64_le {
79 RGBA8 = 0x1f, 39 RGBA8 = 0x1f,
80 BGRA8 = 0x20, 40 BGRA8 = 0x20,
@@ -88,8 +48,6 @@ private:
88 BitField<9, 2, u64_le> chroma_loc_vert; 48 BitField<9, 2, u64_le> chroma_loc_vert;
89 BitField<11, 4, u64_le> block_linear_kind; 49 BitField<11, 4, u64_le> block_linear_kind;
90 BitField<15, 4, u64_le> block_linear_height_log2; 50 BitField<15, 4, u64_le> block_linear_height_log2;
91 BitField<19, 3, u64_le> reserved0;
92 BitField<22, 10, u64_le> reserved1;
93 BitField<32, 14, u64_le> surface_width_minus1; 51 BitField<32, 14, u64_le> surface_width_minus1;
94 BitField<46, 14, u64_le> surface_height_minus1; 52 BitField<46, 14, u64_le> surface_height_minus1;
95 }; 53 };
@@ -97,6 +55,13 @@ private:
97 GPU& gpu; 55 GPU& gpu;
98 std::shared_ptr<Tegra::Nvdec> nvdec_processor; 56 std::shared_ptr<Tegra::Nvdec> nvdec_processor;
99 57
58 /// Avoid reallocation of the following buffers every frame, as their
59 /// size does not change during a stream
60 using AVMallocPtr = std::unique_ptr<u8, decltype(&av_free)>;
61 AVMallocPtr converted_frame_buffer;
62 std::vector<u8> luma_buffer;
63 std::vector<u8> chroma_buffer;
64
100 GPUVAddr config_struct_address{}; 65 GPUVAddr config_struct_address{};
101 GPUVAddr output_surface_luma_address{}; 66 GPUVAddr output_surface_luma_address{};
102 GPUVAddr output_surface_chroma_u_address{}; 67 GPUVAddr output_surface_chroma_u_address{};
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp
index 6ab06775f..23bd793bb 100755
--- a/src/video_core/gpu.cpp
+++ b/src/video_core/gpu.cpp
@@ -30,8 +30,7 @@ MICROPROFILE_DEFINE(GPU_wait, "GPU", "Wait for the GPU", MP_RGB(128, 128, 192));
30 30
31GPU::GPU(Core::System& system_, bool is_async_, bool use_nvdec_) 31GPU::GPU(Core::System& system_, bool is_async_, bool use_nvdec_)
32 : system{system_}, memory_manager{std::make_unique<Tegra::MemoryManager>(system)}, 32 : system{system_}, memory_manager{std::make_unique<Tegra::MemoryManager>(system)},
33 dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)}, 33 dma_pusher{std::make_unique<Tegra::DmaPusher>(system, *this)}, use_nvdec{use_nvdec_},
34 cdma_pusher{std::make_unique<Tegra::CDmaPusher>(*this)}, use_nvdec{use_nvdec_},
35 maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)}, 34 maxwell_3d{std::make_unique<Engines::Maxwell3D>(system, *memory_manager)},
36 fermi_2d{std::make_unique<Engines::Fermi2D>()}, 35 fermi_2d{std::make_unique<Engines::Fermi2D>()},
37 kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)}, 36 kepler_compute{std::make_unique<Engines::KeplerCompute>(system, *memory_manager)},
@@ -494,8 +493,7 @@ void GPU::PushCommandBuffer(Tegra::ChCommandHeaderList& entries) {
494 // TODO(ameerj): RE proper async nvdec operation 493 // TODO(ameerj): RE proper async nvdec operation
495 // gpu_thread.SubmitCommandBuffer(std::move(entries)); 494 // gpu_thread.SubmitCommandBuffer(std::move(entries));
496 495
497 cdma_pusher->Push(std::move(entries)); 496 cdma_pusher->ProcessEntries(std::move(entries));
498 cdma_pusher->DispatchCalls();
499} 497}
500 498
501void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { 499void GPU::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) {
diff --git a/src/video_core/gpu_thread.cpp b/src/video_core/gpu_thread.cpp
index 7e490bcc3..a43f725f3 100755
--- a/src/video_core/gpu_thread.cpp
+++ b/src/video_core/gpu_thread.cpp
@@ -47,8 +47,7 @@ static void RunThread(Core::System& system, VideoCore::RendererBase& renderer,
47 dma_pusher.DispatchCalls(); 47 dma_pusher.DispatchCalls();
48 } else if (auto* command_list = std::get_if<SubmitChCommandEntries>(&next.data)) { 48 } else if (auto* command_list = std::get_if<SubmitChCommandEntries>(&next.data)) {
49 // NVDEC 49 // NVDEC
50 cdma_pusher.Push(std::move(command_list->entries)); 50 cdma_pusher.ProcessEntries(std::move(command_list->entries));
51 cdma_pusher.DispatchCalls();
52 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) { 51 } else if (const auto* data = std::get_if<SwapBuffersCommand>(&next.data)) {
53 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr); 52 renderer.SwapBuffers(data->framebuffer ? &*data->framebuffer : nullptr);
54 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) { 53 } else if (std::holds_alternative<OnCommandListEndCommand>(next.data)) {
diff --git a/src/yuzu/bootmanager.cpp b/src/yuzu/bootmanager.cpp
index d134e54ba..ddfccc800 100755
--- a/src/yuzu/bootmanager.cpp
+++ b/src/yuzu/bootmanager.cpp
@@ -475,7 +475,7 @@ bool GRenderWindow::TouchStart(const QTouchEvent::TouchPoint& touch_point) {
475 475
476bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) { 476bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) {
477 for (std::size_t id = 0; id < touch_ids.size(); ++id) { 477 for (std::size_t id = 0; id < touch_ids.size(); ++id) {
478 if (touch_ids[id] == touch_point.id() + 1) { 478 if (touch_ids[id] == static_cast<std::size_t>(touch_point.id() + 1)) {
479 const auto [x, y] = ScaleTouch(touch_point.pos()); 479 const auto [x, y] = ScaleTouch(touch_point.pos());
480 this->TouchMoved(x, y, id + 1); 480 this->TouchMoved(x, y, id + 1);
481 return true; 481 return true;
@@ -486,8 +486,9 @@ bool GRenderWindow::TouchUpdate(const QTouchEvent::TouchPoint& touch_point) {
486 486
487bool GRenderWindow::TouchExist(std::size_t id, 487bool GRenderWindow::TouchExist(std::size_t id,
488 const QList<QTouchEvent::TouchPoint>& touch_points) const { 488 const QList<QTouchEvent::TouchPoint>& touch_points) const {
489 return std::any_of(touch_points.begin(), touch_points.end(), 489 return std::any_of(touch_points.begin(), touch_points.end(), [id](const auto& point) {
490 [id](const auto& point) { return id == point.id() + 1; }); 490 return id == static_cast<std::size_t>(point.id() + 1);
491 });
491} 492}
492 493
493bool GRenderWindow::event(QEvent* event) { 494bool GRenderWindow::event(QEvent* event) {
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp
index df34384df..5e4d22299 100755
--- a/src/yuzu/configuration/config.cpp
+++ b/src/yuzu/configuration/config.cpp
@@ -508,7 +508,7 @@ void Config::ReadControlValues() {
508 Settings::values.emulate_analog_keyboard = 508 Settings::values.emulate_analog_keyboard =
509 ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool(); 509 ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool();
510 510
511 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), false); 511 ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), true);
512 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), 512 ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"),
513 true); 513 true);
514 ReadSettingGlobal(Settings::values.enable_accurate_vibrations, 514 ReadSettingGlobal(Settings::values.enable_accurate_vibrations,
@@ -1168,7 +1168,7 @@ void Config::SaveControlValues() {
1168 SaveTouchscreenValues(); 1168 SaveTouchscreenValues();
1169 SaveMotionTouchValues(); 1169 SaveMotionTouchValues();
1170 1170
1171 WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, false); 1171 WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, true);
1172 WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, 1172 WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled,
1173 true); 1173 true);
1174 WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"), 1174 WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"),
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp
index d00b24048..4a09d0402 100755
--- a/src/yuzu/configuration/configure_motion_touch.cpp
+++ b/src/yuzu/configuration/configure_motion_touch.cpp
@@ -51,6 +51,8 @@ CalibrationConfigurationDialog::CalibrationConfigurationDialog(QWidget* parent,
51 case CalibrationConfigurationJob::Status::Completed: 51 case CalibrationConfigurationJob::Status::Completed:
52 text = tr("Configuration completed!"); 52 text = tr("Configuration completed!");
53 break; 53 break;
54 default:
55 break;
54 } 56 }
55 QMetaObject::invokeMethod(this, "UpdateLabelText", Q_ARG(QString, text)); 57 QMetaObject::invokeMethod(this, "UpdateLabelText", Q_ARG(QString, text));
56 if (status == CalibrationConfigurationJob::Status::Completed) { 58 if (status == CalibrationConfigurationJob::Status::Completed) {
@@ -163,8 +165,9 @@ void ConfigureMotionTouch::ConnectEvents() {
163} 165}
164 166
165void ConfigureMotionTouch::OnUDPAddServer() { 167void ConfigureMotionTouch::OnUDPAddServer() {
166 QRegExp re(tr(R"re(^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4]" 168 // Validator for IP address
167 "[0-9]|[01]?[0-9][0-9]?)$)re")); // a valid ip address 169 QRegExp re(QStringLiteral(
170 R"re(^(?:(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(?:25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)$)re"));
168 bool ok; 171 bool ok;
169 QString port_text = ui->udp_port->text(); 172 QString port_text = ui->udp_port->text();
170 QString server_text = ui->udp_server->text(); 173 QString server_text = ui->udp_server->text();
diff --git a/src/yuzu/debugger/wait_tree.cpp b/src/yuzu/debugger/wait_tree.cpp
index 3ded85720..a93b5d3c2 100755
--- a/src/yuzu/debugger/wait_tree.cpp
+++ b/src/yuzu/debugger/wait_tree.cpp
@@ -251,7 +251,29 @@ QString WaitTreeThread::GetText() const {
251 } 251 }
252 break; 252 break;
253 case Kernel::ThreadState::Waiting: 253 case Kernel::ThreadState::Waiting:
254 status = tr("waiting"); 254 switch (thread.GetWaitReasonForDebugging()) {
255 case Kernel::ThreadWaitReasonForDebugging::Sleep:
256 status = tr("sleeping");
257 break;
258 case Kernel::ThreadWaitReasonForDebugging::IPC:
259 status = tr("waiting for IPC reply");
260 break;
261 case Kernel::ThreadWaitReasonForDebugging::Synchronization:
262 status = tr("waiting for objects");
263 break;
264 case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
265 status = tr("waiting for condition variable");
266 break;
267 case Kernel::ThreadWaitReasonForDebugging::Arbitration:
268 status = tr("waiting for address arbiter");
269 break;
270 case Kernel::ThreadWaitReasonForDebugging::Suspended:
271 status = tr("waiting for suspend resume");
272 break;
273 default:
274 status = tr("waiting");
275 break;
276 }
255 break; 277 break;
256 case Kernel::ThreadState::Initialized: 278 case Kernel::ThreadState::Initialized:
257 status = tr("initialized"); 279 status = tr("initialized");
@@ -259,6 +281,9 @@ QString WaitTreeThread::GetText() const {
259 case Kernel::ThreadState::Terminated: 281 case Kernel::ThreadState::Terminated:
260 status = tr("terminated"); 282 status = tr("terminated");
261 break; 283 break;
284 default:
285 status = tr("unknown");
286 break;
262 } 287 }
263 288
264 const auto& context = thread.GetContext64(); 289 const auto& context = thread.GetContext64();
@@ -285,7 +310,20 @@ QColor WaitTreeThread::GetColor() const {
285 return QColor(WaitTreeColors[2][color_index]); 310 return QColor(WaitTreeColors[2][color_index]);
286 } 311 }
287 case Kernel::ThreadState::Waiting: 312 case Kernel::ThreadState::Waiting:
288 return QColor(WaitTreeColors[3][color_index]); 313 switch (thread.GetWaitReasonForDebugging()) {
314 case Kernel::ThreadWaitReasonForDebugging::IPC:
315 return QColor(WaitTreeColors[4][color_index]);
316 case Kernel::ThreadWaitReasonForDebugging::Sleep:
317 return QColor(WaitTreeColors[5][color_index]);
318 case Kernel::ThreadWaitReasonForDebugging::Synchronization:
319 case Kernel::ThreadWaitReasonForDebugging::ConditionVar:
320 case Kernel::ThreadWaitReasonForDebugging::Arbitration:
321 case Kernel::ThreadWaitReasonForDebugging::Suspended:
322 return QColor(WaitTreeColors[6][color_index]);
323 break;
324 default:
325 return QColor(WaitTreeColors[3][color_index]);
326 }
289 case Kernel::ThreadState::Initialized: 327 case Kernel::ThreadState::Initialized:
290 return QColor(WaitTreeColors[7][color_index]); 328 return QColor(WaitTreeColors[7][color_index]);
291 case Kernel::ThreadState::Terminated: 329 case Kernel::ThreadState::Terminated:
@@ -336,7 +374,9 @@ std::vector<std::unique_ptr<WaitTreeItem>> WaitTreeThread::GetChildren() const {
336 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex"))); 374 list.push_back(std::make_unique<WaitTreeText>(tr("not waiting for mutex")));
337 } 375 }
338 376
339 if (thread.GetState() == Kernel::ThreadState::Waiting) { 377 if (thread.GetState() == Kernel::ThreadState::Waiting &&
378 thread.GetWaitReasonForDebugging() ==
379 Kernel::ThreadWaitReasonForDebugging::Synchronization) {
340 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(), 380 list.push_back(std::make_unique<WaitTreeObjectList>(thread.GetWaitObjectsForDebugging(),
341 thread.IsCancellable())); 381 thread.IsCancellable()));
342 } 382 }
diff --git a/src/yuzu/util/url_request_interceptor.cpp b/src/yuzu/util/url_request_interceptor.cpp
index 2d491d8c0..b637e771e 100755
--- a/src/yuzu/util/url_request_interceptor.cpp
+++ b/src/yuzu/util/url_request_interceptor.cpp
@@ -22,6 +22,8 @@ void UrlRequestInterceptor::interceptRequest(QWebEngineUrlRequestInfo& info) {
22 case QWebEngineUrlRequestInfo::ResourceTypeXhr: 22 case QWebEngineUrlRequestInfo::ResourceTypeXhr:
23 emit FrameChanged(); 23 emit FrameChanged();
24 break; 24 break;
25 default:
26 break;
25 } 27 }
26} 28}
27 29
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp
index 966ebee39..f76102459 100755
--- a/src/yuzu_cmd/config.cpp
+++ b/src/yuzu_cmd/config.cpp
@@ -340,7 +340,7 @@ void Config::ReadValues() {
340 340
341 // System 341 // System
342 Settings::values.use_docked_mode.SetValue( 342 Settings::values.use_docked_mode.SetValue(
343 sdl2_config->GetBoolean("System", "use_docked_mode", false)); 343 sdl2_config->GetBoolean("System", "use_docked_mode", true));
344 344
345 Settings::values.current_user = std::clamp<int>( 345 Settings::values.current_user = std::clamp<int>(
346 sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); 346 sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1);
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h
index 2d4b98d9a..3ee0e037d 100755
--- a/src/yuzu_cmd/default_ini.h
+++ b/src/yuzu_cmd/default_ini.h
@@ -274,7 +274,7 @@ gamecard_path =
274 274
275[System] 275[System]
276# Whether the system is docked 276# Whether the system is docked
277# 1: Yes, 0 (default): No 277# 1 (default): Yes, 0: No
278use_docked_mode = 278use_docked_mode =
279 279
280# Allow the use of NFC in games 280# Allow the use of NFC in games
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp
index 39e0d35aa..4faf62ede 100755
--- a/src/yuzu_cmd/yuzu.cpp
+++ b/src/yuzu_cmd/yuzu.cpp
@@ -95,8 +95,6 @@ int main(int argc, char** argv) {
95 int option_index = 0; 95 int option_index = 0;
96 96
97 InitializeLogging(); 97 InitializeLogging();
98
99 char* endarg;
100#ifdef _WIN32 98#ifdef _WIN32
101 int argc_w; 99 int argc_w;
102 auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w); 100 auto argv_w = CommandLineToArgvW(GetCommandLineW(), &argc_w);
diff --git a/src/yuzu_tester/config.cpp b/src/yuzu_tester/config.cpp
index 4069d6027..efc795ef1 100755
--- a/src/yuzu_tester/config.cpp
+++ b/src/yuzu_tester/config.cpp
@@ -84,7 +84,7 @@ void Config::ReadValues() {
84 Settings::values.touchscreen.diameter_y = 15; 84 Settings::values.touchscreen.diameter_y = 15;
85 85
86 Settings::values.use_docked_mode.SetValue( 86 Settings::values.use_docked_mode.SetValue(
87 sdl2_config->GetBoolean("Controls", "use_docked_mode", false)); 87 sdl2_config->GetBoolean("Controls", "use_docked_mode", true));
88 88
89 // Data Storage 89 // Data Storage
90 Settings::values.use_virtual_sd = 90 Settings::values.use_virtual_sd =
diff --git a/src/yuzu_tester/default_ini.h b/src/yuzu_tester/default_ini.h
index 3eb64e9d7..779c3791b 100755
--- a/src/yuzu_tester/default_ini.h
+++ b/src/yuzu_tester/default_ini.h
@@ -116,7 +116,7 @@ use_virtual_sd =
116 116
117[System] 117[System]
118# Whether the system is docked 118# Whether the system is docked
119# 1: Yes, 0 (default): No 119# 1 (default): Yes, 0: No
120use_docked_mode = 120use_docked_mode =
121 121
122# Allow the use of NFC in games 122# Allow the use of NFC in games