summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/core/frontend/applets/controller.cpp10
-rw-r--r--src/core/hid/emulated_controller.cpp12
-rw-r--r--src/core/hid/emulated_controller.h10
-rw-r--r--src/core/hle/kernel/k_memory_block.h2
-rw-r--r--src/core/hle/kernel/k_page_table.cpp194
-rw-r--r--src/core/hle/kernel/k_page_table.h20
-rw-r--r--src/core/hle/kernel/k_process.cpp8
-rw-r--r--src/core/hle/kernel/k_thread.cpp2
-rw-r--r--src/core/hle/kernel/svc.cpp55
-rw-r--r--src/core/hle/kernel/svc_common.h5
-rw-r--r--src/core/hle/kernel/svc_wrap.h8
-rw-r--r--src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp8
-rw-r--r--src/shader_recompiler/backend/spirv/emit_spirv.cpp9
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.cpp2
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h4
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp15
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h5
-rw-r--r--src/video_core/texture_cache/texture_cache.h3
-rw-r--r--src/video_core/texture_cache/util.cpp10
-rw-r--r--src/yuzu/applets/qt_controller.cpp2
-rw-r--r--src/yuzu/configuration/configure_input_player.cpp6
21 files changed, 272 insertions, 118 deletions
diff --git a/src/core/frontend/applets/controller.cpp b/src/core/frontend/applets/controller.cpp
index 6dbd38ffa..e1033b634 100644
--- a/src/core/frontend/applets/controller.cpp
+++ b/src/core/frontend/applets/controller.cpp
@@ -45,26 +45,26 @@ void DefaultControllerApplet::ReconfigureControllers(std::function<void()> callb
45 // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld 45 // Pro Controller -> Dual Joycons -> Left Joycon/Right Joycon -> Handheld
46 if (parameters.allow_pro_controller) { 46 if (parameters.allow_pro_controller) {
47 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController); 47 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::ProController);
48 controller->Connect(); 48 controller->Connect(true);
49 } else if (parameters.allow_dual_joycons) { 49 } else if (parameters.allow_dual_joycons) {
50 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual); 50 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconDual);
51 controller->Connect(); 51 controller->Connect(true);
52 } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) { 52 } else if (parameters.allow_left_joycon && parameters.allow_right_joycon) {
53 // Assign left joycons to even player indices and right joycons to odd player indices. 53 // Assign left joycons to even player indices and right joycons to odd player indices.
54 // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and 54 // We do this since Captain Toad Treasure Tracker expects a left joycon for Player 1 and
55 // a right Joycon for Player 2 in 2 Player Assist mode. 55 // a right Joycon for Player 2 in 2 Player Assist mode.
56 if (index % 2 == 0) { 56 if (index % 2 == 0) {
57 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft); 57 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconLeft);
58 controller->Connect(); 58 controller->Connect(true);
59 } else { 59 } else {
60 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight); 60 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::JoyconRight);
61 controller->Connect(); 61 controller->Connect(true);
62 } 62 }
63 } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld && 63 } else if (index == 0 && parameters.enable_single_mode && parameters.allow_handheld &&
64 !Settings::values.use_docked_mode.GetValue()) { 64 !Settings::values.use_docked_mode.GetValue()) {
65 // We should *never* reach here under any normal circumstances. 65 // We should *never* reach here under any normal circumstances.
66 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld); 66 controller->SetNpadStyleIndex(Core::HID::NpadStyleIndex::Handheld);
67 controller->Connect(); 67 controller->Connect(true);
68 } else { 68 } else {
69 UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!"); 69 UNREACHABLE_MSG("Unable to add a new controller based on the given parameters!");
70 } 70 }
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index ff9d7a7e3..2d3fce276 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -886,8 +886,9 @@ void EmulatedController::SetSupportedNpadStyleTag(NpadStyleTag supported_styles)
886 } 886 }
887} 887}
888 888
889bool EmulatedController::IsControllerSupported() const { 889bool EmulatedController::IsControllerSupported(bool use_temporary_value) const {
890 switch (npad_type) { 890 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
891 switch (type) {
891 case NpadStyleIndex::ProController: 892 case NpadStyleIndex::ProController:
892 return supported_style_tag.fullkey; 893 return supported_style_tag.fullkey;
893 case NpadStyleIndex::Handheld: 894 case NpadStyleIndex::Handheld:
@@ -915,9 +916,10 @@ bool EmulatedController::IsControllerSupported() const {
915 } 916 }
916} 917}
917 918
918void EmulatedController::Connect() { 919void EmulatedController::Connect(bool use_temporary_value) {
919 if (!IsControllerSupported()) { 920 if (!IsControllerSupported(use_temporary_value)) {
920 LOG_ERROR(Service_HID, "Controller type {} is not supported", npad_type); 921 const auto type = is_configuring && use_temporary_value ? tmp_npad_type : npad_type;
922 LOG_ERROR(Service_HID, "Controller type {} is not supported", type);
921 return; 923 return;
922 } 924 }
923 { 925 {
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h
index e42aafebc..d887eca87 100644
--- a/src/core/hid/emulated_controller.h
+++ b/src/core/hid/emulated_controller.h
@@ -167,8 +167,11 @@ public:
167 */ 167 */
168 void SetSupportedNpadStyleTag(NpadStyleTag supported_styles); 168 void SetSupportedNpadStyleTag(NpadStyleTag supported_styles);
169 169
170 /// Sets the connected status to true 170 /**
171 void Connect(); 171 * Sets the connected status to true
172 * @param use_temporary_value If true tmp_npad_type will be used
173 */
174 void Connect(bool use_temporary_value = false);
172 175
173 /// Sets the connected status to false 176 /// Sets the connected status to false
174 void Disconnect(); 177 void Disconnect();
@@ -319,9 +322,10 @@ private:
319 322
320 /** 323 /**
321 * Checks the current controller type against the supported_style_tag 324 * Checks the current controller type against the supported_style_tag
325 * @param use_temporary_value If true tmp_npad_type will be used
322 * @return true if the controller is supported 326 * @return true if the controller is supported
323 */ 327 */
324 bool IsControllerSupported() const; 328 bool IsControllerSupported(bool use_temporary_value = false) const;
325 329
326 /** 330 /**
327 * Updates the button status of the controller 331 * Updates the button status of the controller
diff --git a/src/core/hle/kernel/k_memory_block.h b/src/core/hle/kernel/k_memory_block.h
index fd491146f..9e51c33ce 100644
--- a/src/core/hle/kernel/k_memory_block.h
+++ b/src/core/hle/kernel/k_memory_block.h
@@ -120,7 +120,7 @@ static_assert(static_cast<u32>(KMemoryState::CodeOut) == 0x00402015);
120 120
121enum class KMemoryPermission : u8 { 121enum class KMemoryPermission : u8 {
122 None = 0, 122 None = 0,
123 Mask = static_cast<u8>(~None), 123 All = static_cast<u8>(~None),
124 124
125 Read = 1 << 0, 125 Read = 1 << 0,
126 Write = 1 << 1, 126 Write = 1 << 1,
diff --git a/src/core/hle/kernel/k_page_table.cpp b/src/core/hle/kernel/k_page_table.cpp
index 99982e5a3..4da509224 100644
--- a/src/core/hle/kernel/k_page_table.cpp
+++ b/src/core/hle/kernel/k_page_table.cpp
@@ -264,9 +264,9 @@ ResultCode KPageTable::InitializeForProcess(FileSys::ProgramAddressSpaceType as_
264 ASSERT(heap_last < stack_start || stack_last < heap_start); 264 ASSERT(heap_last < stack_start || stack_last < heap_start);
265 ASSERT(heap_last < kmap_start || kmap_last < heap_start); 265 ASSERT(heap_last < kmap_start || kmap_last < heap_start);
266 266
267 current_heap_addr = heap_region_start; 267 current_heap_end = heap_region_start;
268 heap_capacity = 0; 268 max_heap_size = 0;
269 physical_memory_usage = 0; 269 mapped_physical_memory_size = 0;
270 memory_pool = pool; 270 memory_pool = pool;
271 271
272 page_table_impl.Resize(address_space_width, PageBits); 272 page_table_impl.Resize(address_space_width, PageBits);
@@ -306,7 +306,7 @@ ResultCode KPageTable::MapProcessCodeMemory(VAddr dst_addr, VAddr src_addr, std:
306 KMemoryState state{}; 306 KMemoryState state{};
307 KMemoryPermission perm{}; 307 KMemoryPermission perm{};
308 CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All, 308 CASCADE_CODE(CheckMemoryState(&state, &perm, nullptr, src_addr, size, KMemoryState::All,
309 KMemoryState::Normal, KMemoryPermission::Mask, 309 KMemoryState::Normal, KMemoryPermission::All,
310 KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, 310 KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask,
311 KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); 311 KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
312 312
@@ -465,7 +465,7 @@ ResultCode KPageTable::MapPhysicalMemory(VAddr addr, std::size_t size) {
465 465
466 MapPhysicalMemory(page_linked_list, addr, end_addr); 466 MapPhysicalMemory(page_linked_list, addr, end_addr);
467 467
468 physical_memory_usage += remaining_size; 468 mapped_physical_memory_size += remaining_size;
469 469
470 const std::size_t num_pages{size / PageSize}; 470 const std::size_t num_pages{size / PageSize};
471 block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None, 471 block_manager->Update(addr, num_pages, KMemoryState::Free, KMemoryPermission::None,
@@ -507,7 +507,7 @@ ResultCode KPageTable::UnmapPhysicalMemory(VAddr addr, std::size_t size) {
507 507
508 auto process{system.Kernel().CurrentProcess()}; 508 auto process{system.Kernel().CurrentProcess()};
509 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size); 509 process->GetResourceLimit()->Release(LimitableResource::PhysicalMemory, mapped_size);
510 physical_memory_usage -= mapped_size; 510 mapped_physical_memory_size -= mapped_size;
511 511
512 return ResultSuccess; 512 return ResultSuccess;
513} 513}
@@ -554,7 +554,7 @@ ResultCode KPageTable::Map(VAddr dst_addr, VAddr src_addr, std::size_t size) {
554 KMemoryState src_state{}; 554 KMemoryState src_state{};
555 CASCADE_CODE(CheckMemoryState( 555 CASCADE_CODE(CheckMemoryState(
556 &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, 556 &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
557 KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::ReadAndWrite, 557 KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
558 KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)); 558 KMemoryAttribute::Mask, KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped));
559 559
560 if (IsRegionMapped(dst_addr, size)) { 560 if (IsRegionMapped(dst_addr, size)) {
@@ -593,7 +593,7 @@ ResultCode KPageTable::Unmap(VAddr dst_addr, VAddr src_addr, std::size_t size) {
593 KMemoryState src_state{}; 593 KMemoryState src_state{};
594 CASCADE_CODE(CheckMemoryState( 594 CASCADE_CODE(CheckMemoryState(
595 &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias, 595 &src_state, nullptr, nullptr, src_addr, size, KMemoryState::FlagCanAlias,
596 KMemoryState::FlagCanAlias, KMemoryPermission::Mask, KMemoryPermission::None, 596 KMemoryState::FlagCanAlias, KMemoryPermission::All, KMemoryPermission::None,
597 KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); 597 KMemoryAttribute::Mask, KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
598 598
599 KMemoryPermission dst_perm{}; 599 KMemoryPermission dst_perm{};
@@ -784,7 +784,7 @@ ResultCode KPageTable::ReserveTransferMemory(VAddr addr, std::size_t size, KMemo
784 CASCADE_CODE(CheckMemoryState( 784 CASCADE_CODE(CheckMemoryState(
785 &state, nullptr, &attribute, addr, size, 785 &state, nullptr, &attribute, addr, size,
786 KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, 786 KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted,
787 KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::Mask, 787 KMemoryState::FlagCanTransfer | KMemoryState::FlagReferenceCounted, KMemoryPermission::All,
788 KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None, 788 KMemoryPermission::ReadAndWrite, KMemoryAttribute::Mask, KMemoryAttribute::None,
789 KMemoryAttribute::IpcAndDeviceMapped)); 789 KMemoryAttribute::IpcAndDeviceMapped));
790 790
@@ -806,6 +806,33 @@ ResultCode KPageTable::ResetTransferMemory(VAddr addr, std::size_t size) {
806 KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped)); 806 KMemoryAttribute::Locked, KMemoryAttribute::IpcAndDeviceMapped));
807 807
808 block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite); 808 block_manager->Update(addr, size / PageSize, state, KMemoryPermission::ReadAndWrite);
809 return ResultSuccess;
810}
811
812ResultCode KPageTable::SetMemoryPermission(VAddr addr, std::size_t size,
813 Svc::MemoryPermission svc_perm) {
814 const size_t num_pages = size / PageSize;
815
816 // Lock the table.
817 std::lock_guard lock{page_table_lock};
818
819 // Verify we can change the memory permission.
820 KMemoryState old_state;
821 KMemoryPermission old_perm;
822 R_TRY(this->CheckMemoryState(
823 std::addressof(old_state), std::addressof(old_perm), nullptr, addr, size,
824 KMemoryState::FlagCanReprotect, KMemoryState::FlagCanReprotect, KMemoryPermission::None,
825 KMemoryPermission::None, KMemoryAttribute::All, KMemoryAttribute::None));
826
827 // Determine new perm.
828 const KMemoryPermission new_perm = ConvertToKMemoryPermission(svc_perm);
829 R_SUCCEED_IF(old_perm == new_perm);
830
831 // Perform mapping operation.
832 R_TRY(Operate(addr, num_pages, new_perm, OperationType::ChangePermissions));
833
834 // Update the blocks.
835 block_manager->Update(addr, num_pages, old_state, new_perm, KMemoryAttribute::None);
809 836
810 return ResultSuccess; 837 return ResultSuccess;
811} 838}
@@ -832,61 +859,125 @@ ResultCode KPageTable::SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryA
832 return ResultSuccess; 859 return ResultSuccess;
833} 860}
834 861
835ResultCode KPageTable::SetHeapCapacity(std::size_t new_heap_capacity) { 862ResultCode KPageTable::SetMaxHeapSize(std::size_t size) {
863 // Lock the table.
836 std::lock_guard lock{page_table_lock}; 864 std::lock_guard lock{page_table_lock};
837 heap_capacity = new_heap_capacity;
838 return ResultSuccess;
839}
840 865
841ResultVal<VAddr> KPageTable::SetHeapSize(std::size_t size) { 866 // Only process page tables are allowed to set heap size.
867 ASSERT(!this->IsKernel());
842 868
843 if (size > heap_region_end - heap_region_start) { 869 max_heap_size = size;
844 return ResultOutOfMemory;
845 }
846 870
847 const u64 previous_heap_size{GetHeapSize()}; 871 return ResultSuccess;
848 872}
849 UNIMPLEMENTED_IF_MSG(previous_heap_size > size, "Heap shrink is unimplemented");
850 873
851 // Increase the heap size 874ResultCode KPageTable::SetHeapSize(VAddr* out, std::size_t size) {
875 // Try to perform a reduction in heap, instead of an extension.
876 VAddr cur_address{};
877 std::size_t allocation_size{};
852 { 878 {
853 std::lock_guard lock{page_table_lock}; 879 // Lock the table.
854 880 std::lock_guard lk(page_table_lock);
855 const u64 delta{size - previous_heap_size}; 881
856 882 // Validate that setting heap size is possible at all.
857 // Reserve memory for the heap extension. 883 R_UNLESS(!is_kernel, ResultOutOfMemory);
858 KScopedResourceReservation memory_reservation( 884 R_UNLESS(size <= static_cast<std::size_t>(heap_region_end - heap_region_start),
859 system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory, 885 ResultOutOfMemory);
860 delta); 886 R_UNLESS(size <= max_heap_size, ResultOutOfMemory);
861 887
862 if (!memory_reservation.Succeeded()) { 888 if (size < GetHeapSize()) {
863 LOG_ERROR(Kernel, "Could not reserve heap extension of size {:X} bytes", delta); 889 // The size being requested is less than the current size, so we need to free the end of
864 return ResultLimitReached; 890 // the heap.
891
892 // Validate memory state.
893 std::size_t num_allocator_blocks;
894 R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks),
895 heap_region_start + size, GetHeapSize() - size,
896 KMemoryState::All, KMemoryState::Normal,
897 KMemoryPermission::All, KMemoryPermission::ReadAndWrite,
898 KMemoryAttribute::All, KMemoryAttribute::None));
899
900 // Unmap the end of the heap.
901 const auto num_pages = (GetHeapSize() - size) / PageSize;
902 R_TRY(Operate(heap_region_start + size, num_pages, KMemoryPermission::None,
903 OperationType::Unmap));
904
905 // Release the memory from the resource limit.
906 system.Kernel().CurrentProcess()->GetResourceLimit()->Release(
907 LimitableResource::PhysicalMemory, num_pages * PageSize);
908
909 // Apply the memory block update.
910 block_manager->Update(heap_region_start + size, num_pages, KMemoryState::Free,
911 KMemoryPermission::None, KMemoryAttribute::None);
912
913 // Update the current heap end.
914 current_heap_end = heap_region_start + size;
915
916 // Set the output.
917 *out = heap_region_start;
918 return ResultSuccess;
919 } else if (size == GetHeapSize()) {
920 // The size requested is exactly the current size.
921 *out = heap_region_start;
922 return ResultSuccess;
923 } else {
924 // We have to allocate memory. Determine how much to allocate and where while the table
925 // is locked.
926 cur_address = current_heap_end;
927 allocation_size = size - GetHeapSize();
865 } 928 }
929 }
866 930
867 KPageLinkedList page_linked_list; 931 // Reserve memory for the heap extension.
868 const std::size_t num_pages{delta / PageSize}; 932 KScopedResourceReservation memory_reservation(
933 system.Kernel().CurrentProcess()->GetResourceLimit(), LimitableResource::PhysicalMemory,
934 allocation_size);
935 R_UNLESS(memory_reservation.Succeeded(), ResultLimitReached);
869 936
870 CASCADE_CODE( 937 // Allocate pages for the heap extension.
871 system.Kernel().MemoryManager().Allocate(page_linked_list, num_pages, memory_pool)); 938 KPageLinkedList page_linked_list;
939 R_TRY(system.Kernel().MemoryManager().Allocate(page_linked_list, allocation_size / PageSize,
940 memory_pool));
872 941
873 if (IsRegionMapped(current_heap_addr, delta)) { 942 // Map the pages.
874 return ResultInvalidCurrentMemory; 943 {
944 // Lock the table.
945 std::lock_guard lk(page_table_lock);
946
947 // Ensure that the heap hasn't changed since we began executing.
948 ASSERT(cur_address == current_heap_end);
949
950 // Check the memory state.
951 std::size_t num_allocator_blocks{};
952 R_TRY(this->CheckMemoryState(std::addressof(num_allocator_blocks), current_heap_end,
953 allocation_size, KMemoryState::All, KMemoryState::Free,
954 KMemoryPermission::None, KMemoryPermission::None,
955 KMemoryAttribute::None, KMemoryAttribute::None));
956
957 // Map the pages.
958 const auto num_pages = allocation_size / PageSize;
959 R_TRY(Operate(current_heap_end, num_pages, page_linked_list, OperationType::MapGroup));
960
961 // Clear all the newly allocated pages.
962 for (std::size_t cur_page = 0; cur_page < num_pages; ++cur_page) {
963 std::memset(system.Memory().GetPointer(current_heap_end + (cur_page * PageSize)), 0,
964 PageSize);
875 } 965 }
876 966
877 CASCADE_CODE( 967 // We succeeded, so commit our memory reservation.
878 Operate(current_heap_addr, num_pages, page_linked_list, OperationType::MapGroup));
879
880 // Succeeded in allocation, commit the resource reservation
881 memory_reservation.Commit(); 968 memory_reservation.Commit();
882 969
883 block_manager->Update(current_heap_addr, num_pages, KMemoryState::Normal, 970 // Apply the memory block update.
884 KMemoryPermission::ReadAndWrite); 971 block_manager->Update(current_heap_end, num_pages, KMemoryState::Normal,
972 KMemoryPermission::ReadAndWrite, KMemoryAttribute::None);
885 973
886 current_heap_addr = heap_region_start + size; 974 // Update the current heap end.
887 } 975 current_heap_end = heap_region_start + size;
888 976
889 return heap_region_start; 977 // Set the output.
978 *out = heap_region_start;
979 return ResultSuccess;
980 }
890} 981}
891 982
892ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, 983ResultVal<VAddr> KPageTable::AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
@@ -978,7 +1069,7 @@ ResultCode KPageTable::LockForCodeMemory(VAddr addr, std::size_t size) {
978 1069
979 if (const ResultCode result{CheckMemoryState( 1070 if (const ResultCode result{CheckMemoryState(
980 nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory, 1071 nullptr, &old_perm, nullptr, addr, size, KMemoryState::FlagCanCodeMemory,
981 KMemoryState::FlagCanCodeMemory, KMemoryPermission::Mask, 1072 KMemoryState::FlagCanCodeMemory, KMemoryPermission::All,
982 KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)}; 1073 KMemoryPermission::UserReadWrite, KMemoryAttribute::All, KMemoryAttribute::None)};
983 result.IsError()) { 1074 result.IsError()) {
984 return result; 1075 return result;
@@ -1031,9 +1122,8 @@ ResultCode KPageTable::InitializeMemoryLayout(VAddr start, VAddr end) {
1031 1122
1032bool KPageTable::IsRegionMapped(VAddr address, u64 size) { 1123bool KPageTable::IsRegionMapped(VAddr address, u64 size) {
1033 return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free, 1124 return CheckMemoryState(address, size, KMemoryState::All, KMemoryState::Free,
1034 KMemoryPermission::Mask, KMemoryPermission::None, 1125 KMemoryPermission::All, KMemoryPermission::None, KMemoryAttribute::Mask,
1035 KMemoryAttribute::Mask, KMemoryAttribute::None, 1126 KMemoryAttribute::None, KMemoryAttribute::IpcAndDeviceMapped)
1036 KMemoryAttribute::IpcAndDeviceMapped)
1037 .IsError(); 1127 .IsError();
1038} 1128}
1039 1129
diff --git a/src/core/hle/kernel/k_page_table.h b/src/core/hle/kernel/k_page_table.h
index d784aa67e..564410dca 100644
--- a/src/core/hle/kernel/k_page_table.h
+++ b/src/core/hle/kernel/k_page_table.h
@@ -47,10 +47,11 @@ public:
47 KMemoryInfo QueryInfo(VAddr addr); 47 KMemoryInfo QueryInfo(VAddr addr);
48 ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm); 48 ResultCode ReserveTransferMemory(VAddr addr, std::size_t size, KMemoryPermission perm);
49 ResultCode ResetTransferMemory(VAddr addr, std::size_t size); 49 ResultCode ResetTransferMemory(VAddr addr, std::size_t size);
50 ResultCode SetMemoryPermission(VAddr addr, std::size_t size, Svc::MemoryPermission perm);
50 ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask, 51 ResultCode SetMemoryAttribute(VAddr addr, std::size_t size, KMemoryAttribute mask,
51 KMemoryAttribute value); 52 KMemoryAttribute value);
52 ResultCode SetHeapCapacity(std::size_t new_heap_capacity); 53 ResultCode SetMaxHeapSize(std::size_t size);
53 ResultVal<VAddr> SetHeapSize(std::size_t size); 54 ResultCode SetHeapSize(VAddr* out, std::size_t size);
54 ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align, 55 ResultVal<VAddr> AllocateAndMapMemory(std::size_t needed_num_pages, std::size_t align,
55 bool is_map_only, VAddr region_start, 56 bool is_map_only, VAddr region_start,
56 std::size_t region_num_pages, KMemoryState state, 57 std::size_t region_num_pages, KMemoryState state,
@@ -182,14 +183,15 @@ public:
182 constexpr VAddr GetAliasCodeRegionSize() const { 183 constexpr VAddr GetAliasCodeRegionSize() const {
183 return alias_code_region_end - alias_code_region_start; 184 return alias_code_region_end - alias_code_region_start;
184 } 185 }
186 size_t GetNormalMemorySize() {
187 std::lock_guard lk(page_table_lock);
188 return GetHeapSize() + mapped_physical_memory_size;
189 }
185 constexpr std::size_t GetAddressSpaceWidth() const { 190 constexpr std::size_t GetAddressSpaceWidth() const {
186 return address_space_width; 191 return address_space_width;
187 } 192 }
188 constexpr std::size_t GetHeapSize() { 193 constexpr std::size_t GetHeapSize() const {
189 return current_heap_addr - heap_region_start; 194 return current_heap_end - heap_region_start;
190 }
191 constexpr std::size_t GetTotalHeapSize() {
192 return GetHeapSize() + physical_memory_usage;
193 } 195 }
194 constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const { 196 constexpr bool IsInsideAddressSpace(VAddr address, std::size_t size) const {
195 return address_space_start <= address && address + size - 1 <= address_space_end - 1; 197 return address_space_start <= address && address + size - 1 <= address_space_end - 1;
@@ -269,10 +271,8 @@ private:
269 VAddr code_region_end{}; 271 VAddr code_region_end{};
270 VAddr alias_code_region_start{}; 272 VAddr alias_code_region_start{};
271 VAddr alias_code_region_end{}; 273 VAddr alias_code_region_end{};
272 VAddr current_heap_addr{};
273 274
274 std::size_t heap_capacity{}; 275 std::size_t mapped_physical_memory_size{};
275 std::size_t physical_memory_usage{};
276 std::size_t max_heap_size{}; 276 std::size_t max_heap_size{};
277 std::size_t max_physical_memory_size{}; 277 std::size_t max_physical_memory_size{};
278 std::size_t address_space_width{}; 278 std::size_t address_space_width{};
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index aee313995..73f8bc4fe 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -172,7 +172,7 @@ void KProcess::DecrementThreadCount() {
172 172
173u64 KProcess::GetTotalPhysicalMemoryAvailable() const { 173u64 KProcess::GetTotalPhysicalMemoryAvailable() const {
174 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) + 174 const u64 capacity{resource_limit->GetFreeValue(LimitableResource::PhysicalMemory) +
175 page_table->GetTotalHeapSize() + GetSystemResourceSize() + image_size + 175 page_table->GetNormalMemorySize() + GetSystemResourceSize() + image_size +
176 main_thread_stack_size}; 176 main_thread_stack_size};
177 if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application); 177 if (const auto pool_size = kernel.MemoryManager().GetSize(KMemoryManager::Pool::Application);
178 capacity != pool_size) { 178 capacity != pool_size) {
@@ -189,7 +189,7 @@ u64 KProcess::GetTotalPhysicalMemoryAvailableWithoutSystemResource() const {
189} 189}
190 190
191u64 KProcess::GetTotalPhysicalMemoryUsed() const { 191u64 KProcess::GetTotalPhysicalMemoryUsed() const {
192 return image_size + main_thread_stack_size + page_table->GetTotalHeapSize() + 192 return image_size + main_thread_stack_size + page_table->GetNormalMemorySize() +
193 GetSystemResourceSize(); 193 GetSystemResourceSize();
194} 194}
195 195
@@ -410,8 +410,8 @@ void KProcess::Run(s32 main_thread_priority, u64 stack_size) {
410 resource_limit->Reserve(LimitableResource::Threads, 1); 410 resource_limit->Reserve(LimitableResource::Threads, 1);
411 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size); 411 resource_limit->Reserve(LimitableResource::PhysicalMemory, main_thread_stack_size);
412 412
413 const std::size_t heap_capacity{memory_usage_capacity - main_thread_stack_size - image_size}; 413 const std::size_t heap_capacity{memory_usage_capacity - (main_thread_stack_size + image_size)};
414 ASSERT(!page_table->SetHeapCapacity(heap_capacity).IsError()); 414 ASSERT(!page_table->SetMaxHeapSize(heap_capacity).IsError());
415 415
416 ChangeStatus(ProcessStatus::Running); 416 ChangeStatus(ProcessStatus::Running);
417 417
diff --git a/src/core/hle/kernel/k_thread.cpp b/src/core/hle/kernel/k_thread.cpp
index 752592e2e..b8c993748 100644
--- a/src/core/hle/kernel/k_thread.cpp
+++ b/src/core/hle/kernel/k_thread.cpp
@@ -26,6 +26,7 @@
26#include "core/hle/kernel/k_resource_limit.h" 26#include "core/hle/kernel/k_resource_limit.h"
27#include "core/hle/kernel/k_scheduler.h" 27#include "core/hle/kernel/k_scheduler.h"
28#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h" 28#include "core/hle/kernel/k_scoped_scheduler_lock_and_sleep.h"
29#include "core/hle/kernel/k_system_control.h"
29#include "core/hle/kernel/k_thread.h" 30#include "core/hle/kernel/k_thread.h"
30#include "core/hle/kernel/k_thread_queue.h" 31#include "core/hle/kernel/k_thread_queue.h"
31#include "core/hle/kernel/kernel.h" 32#include "core/hle/kernel/kernel.h"
@@ -50,6 +51,7 @@ static void ResetThreadContext64(Core::ARM_Interface::ThreadContext64& context,
50 VAddr entry_point, u64 arg) { 51 VAddr entry_point, u64 arg) {
51 context = {}; 52 context = {};
52 context.cpu_registers[0] = arg; 53 context.cpu_registers[0] = arg;
54 context.cpu_registers[18] = Kernel::KSystemControl::GenerateRandomU64() | 1;
53 context.pc = entry_point; 55 context.pc = entry_point;
54 context.sp = stack_top; 56 context.sp = stack_top;
55 // TODO(merry): Perform a hardware test to determine the below value. 57 // TODO(merry): Perform a hardware test to determine the below value.
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index 37d67b72e..63e2dff19 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -135,24 +135,15 @@ enum class ResourceLimitValueType {
135} // Anonymous namespace 135} // Anonymous namespace
136 136
137/// Set the process heap to a given Size. It can both extend and shrink the heap. 137/// Set the process heap to a given Size. It can both extend and shrink the heap.
138static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { 138static ResultCode SetHeapSize(Core::System& system, VAddr* out_address, u64 size) {
139 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); 139 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", size);
140 140
141 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. 141 // Validate size.
142 if ((heap_size % 0x200000) != 0) { 142 R_UNLESS(Common::IsAligned(size, HeapSizeAlignment), ResultInvalidSize);
143 LOG_ERROR(Kernel_SVC, "The heap size is not a multiple of 2MB, heap_size=0x{:016X}", 143 R_UNLESS(size < MainMemorySizeMax, ResultInvalidSize);
144 heap_size);
145 return ResultInvalidSize;
146 }
147
148 if (heap_size >= 0x200000000) {
149 LOG_ERROR(Kernel_SVC, "The heap size is not less than 8GB, heap_size=0x{:016X}", heap_size);
150 return ResultInvalidSize;
151 }
152
153 auto& page_table{system.Kernel().CurrentProcess()->PageTable()};
154 144
155 CASCADE_RESULT(*heap_addr, page_table.SetHeapSize(heap_size)); 145 // Set the heap size.
146 R_TRY(system.Kernel().CurrentProcess()->PageTable().SetHeapSize(out_address, size));
156 147
157 return ResultSuccess; 148 return ResultSuccess;
158} 149}
@@ -164,6 +155,36 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
164 return result; 155 return result;
165} 156}
166 157
158constexpr bool IsValidSetMemoryPermission(MemoryPermission perm) {
159 switch (perm) {
160 case MemoryPermission::None:
161 case MemoryPermission::Read:
162 case MemoryPermission::ReadWrite:
163 return true;
164 default:
165 return false;
166 }
167}
168
169static ResultCode SetMemoryPermission(Core::System& system, VAddr address, u64 size,
170 MemoryPermission perm) {
171 // Validate address / size.
172 R_UNLESS(Common::IsAligned(address, PageSize), ResultInvalidAddress);
173 R_UNLESS(Common::IsAligned(size, PageSize), ResultInvalidSize);
174 R_UNLESS(size > 0, ResultInvalidSize);
175 R_UNLESS((address < address + size), ResultInvalidCurrentMemory);
176
177 // Validate the permission.
178 R_UNLESS(IsValidSetMemoryPermission(perm), ResultInvalidNewMemoryPermission);
179
180 // Validate that the region is in range for the current process.
181 auto& page_table = system.Kernel().CurrentProcess()->PageTable();
182 R_UNLESS(page_table.Contains(address, size), ResultInvalidCurrentMemory);
183
184 // Set the memory attribute.
185 return page_table.SetMemoryPermission(address, size, perm);
186}
187
167static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 188static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
168 u32 attribute) { 189 u32 attribute) {
169 LOG_DEBUG(Kernel_SVC, 190 LOG_DEBUG(Kernel_SVC,
@@ -2724,7 +2745,7 @@ static const FunctionDef SVC_Table_32[] = {
2724static const FunctionDef SVC_Table_64[] = { 2745static const FunctionDef SVC_Table_64[] = {
2725 {0x00, nullptr, "Unknown"}, 2746 {0x00, nullptr, "Unknown"},
2726 {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"}, 2747 {0x01, SvcWrap64<SetHeapSize>, "SetHeapSize"},
2727 {0x02, nullptr, "SetMemoryPermission"}, 2748 {0x02, SvcWrap64<SetMemoryPermission>, "SetMemoryPermission"},
2728 {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"}, 2749 {0x03, SvcWrap64<SetMemoryAttribute>, "SetMemoryAttribute"},
2729 {0x04, SvcWrap64<MapMemory>, "MapMemory"}, 2750 {0x04, SvcWrap64<MapMemory>, "MapMemory"},
2730 {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"}, 2751 {0x05, SvcWrap64<UnmapMemory>, "UnmapMemory"},
diff --git a/src/core/hle/kernel/svc_common.h b/src/core/hle/kernel/svc_common.h
index 60ea2c405..25de6e437 100644
--- a/src/core/hle/kernel/svc_common.h
+++ b/src/core/hle/kernel/svc_common.h
@@ -5,6 +5,7 @@
5#pragma once 5#pragma once
6 6
7#include "common/common_types.h" 7#include "common/common_types.h"
8#include "common/literals.h"
8 9
9namespace Kernel { 10namespace Kernel {
10using Handle = u32; 11using Handle = u32;
@@ -12,9 +13,13 @@ using Handle = u32;
12 13
13namespace Kernel::Svc { 14namespace Kernel::Svc {
14 15
16using namespace Common::Literals;
17
15constexpr s32 ArgumentHandleCountMax = 0x40; 18constexpr s32 ArgumentHandleCountMax = 0x40;
16constexpr u32 HandleWaitMask{1u << 30}; 19constexpr u32 HandleWaitMask{1u << 30};
17 20
21constexpr inline std::size_t HeapSizeAlignment = 2_MiB;
22
18constexpr inline Handle InvalidHandle = Handle(0); 23constexpr inline Handle InvalidHandle = Handle(0);
19 24
20enum PseudoHandle : Handle { 25enum PseudoHandle : Handle {
diff --git a/src/core/hle/kernel/svc_wrap.h b/src/core/hle/kernel/svc_wrap.h
index 86255fe6d..a60adfcab 100644
--- a/src/core/hle/kernel/svc_wrap.h
+++ b/src/core/hle/kernel/svc_wrap.h
@@ -249,6 +249,14 @@ void SvcWrap64(Core::System& system) {
249 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw); 249 func(system, Param(system, 0), Param(system, 1), static_cast<u32>(Param(system, 2))).raw);
250} 250}
251 251
252// Used by SetMemoryPermission
253template <ResultCode func(Core::System&, u64, u64, Svc::MemoryPermission)>
254void SvcWrap64(Core::System& system) {
255 FuncReturn(system, func(system, Param(system, 0), Param(system, 1),
256 static_cast<Svc::MemoryPermission>(Param(system, 2)))
257 .raw);
258}
259
252// Used by MapSharedMemory 260// Used by MapSharedMemory
253template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)> 261template <ResultCode func(Core::System&, Handle, u64, u64, Svc::MemoryPermission)>
254void SvcWrap64(Core::System& system) { 262void SvcWrap64(Core::System& system) {
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
index c0f5fc402..7434a1f92 100644
--- a/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
+++ b/src/shader_recompiler/backend/glasm/emit_glasm_context_get_set.cpp
@@ -86,7 +86,7 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
86 } 86 }
87 switch (attr) { 87 switch (attr) {
88 case IR::Attribute::PrimitiveId: 88 case IR::Attribute::PrimitiveId:
89 ctx.Add("MOV.S {}.x,primitive.id;", inst); 89 ctx.Add("MOV.F {}.x,primitive.id;", inst);
90 break; 90 break;
91 case IR::Attribute::PositionX: 91 case IR::Attribute::PositionX:
92 case IR::Attribute::PositionY: 92 case IR::Attribute::PositionY:
@@ -113,13 +113,13 @@ void EmitGetAttribute(EmitContext& ctx, IR::Inst& inst, IR::Attribute attr, Scal
113 ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle); 113 ctx.Add("MOV.F {}.x,vertex.tesscoord.{};", inst, swizzle);
114 break; 114 break;
115 case IR::Attribute::InstanceId: 115 case IR::Attribute::InstanceId:
116 ctx.Add("MOV.S {}.x,{}.instance;", inst, ctx.attrib_name); 116 ctx.Add("MOV.F {}.x,{}.instance;", inst, ctx.attrib_name);
117 break; 117 break;
118 case IR::Attribute::VertexId: 118 case IR::Attribute::VertexId:
119 ctx.Add("MOV.S {}.x,{}.id;", inst, ctx.attrib_name); 119 ctx.Add("MOV.F {}.x,{}.id;", inst, ctx.attrib_name);
120 break; 120 break;
121 case IR::Attribute::FrontFace: 121 case IR::Attribute::FrontFace:
122 ctx.Add("CMP.S {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name); 122 ctx.Add("CMP.F {}.x,{}.facing.x,0,-1;", inst, ctx.attrib_name);
123 break; 123 break;
124 default: 124 default:
125 throw NotImplementedException("Get attribute {}", attr); 125 throw NotImplementedException("Get attribute {}", attr);
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv.cpp b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
index 6ce7ed12a..50918317f 100644
--- a/src/shader_recompiler/backend/spirv/emit_spirv.cpp
+++ b/src/shader_recompiler/backend/spirv/emit_spirv.cpp
@@ -30,11 +30,20 @@ struct FuncTraits<ReturnType_ (*)(Args...)> {
30 using ArgType = std::tuple_element_t<I, std::tuple<Args...>>; 30 using ArgType = std::tuple_element_t<I, std::tuple<Args...>>;
31}; 31};
32 32
33#ifdef _MSC_VER
34#pragma warning(push)
35#pragma warning(disable : 4702) // Ignore unreachable code warning
36#endif
37
33template <auto func, typename... Args> 38template <auto func, typename... Args>
34void SetDefinition(EmitContext& ctx, IR::Inst* inst, Args... args) { 39void SetDefinition(EmitContext& ctx, IR::Inst* inst, Args... args) {
35 inst->SetDefinition<Id>(func(ctx, std::forward<Args>(args)...)); 40 inst->SetDefinition<Id>(func(ctx, std::forward<Args>(args)...));
36} 41}
37 42
43#ifdef _MSC_VER
44#pragma warning(pop)
45#endif
46
38template <typename ArgType> 47template <typename ArgType>
39ArgType Arg(EmitContext& ctx, const IR::Value& arg) { 48ArgType Arg(EmitContext& ctx, const IR::Value& arg) {
40 if constexpr (std::is_same_v<ArgType, Id>) { 49 if constexpr (std::is_same_v<ArgType, Id>) {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp
index 14e6522f2..3c1f79a27 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.cpp
+++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp
@@ -1047,7 +1047,7 @@ bool Image::ScaleDown(bool ignore) {
1047} 1047}
1048 1048
1049ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, 1049ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
1050 ImageId image_id_, Image& image) 1050 ImageId image_id_, Image& image, const SlotVector<Image>&)
1051 : VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} { 1051 : VideoCommon::ImageViewBase{info, image.info, image_id_}, views{runtime.null_image_views} {
1052 const Device& device = runtime.device; 1052 const Device& device = runtime.device;
1053 if (True(image.flags & ImageFlagBits::Converted)) { 1053 if (True(image.flags & ImageFlagBits::Converted)) {
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index dbf1df79c..7f425631f 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -36,6 +36,7 @@ using VideoCommon::ImageViewType;
36using VideoCommon::NUM_RT; 36using VideoCommon::NUM_RT;
37using VideoCommon::Region2D; 37using VideoCommon::Region2D;
38using VideoCommon::RenderTargets; 38using VideoCommon::RenderTargets;
39using VideoCommon::SlotVector;
39 40
40struct ImageBufferMap { 41struct ImageBufferMap {
41 ~ImageBufferMap(); 42 ~ImageBufferMap();
@@ -234,7 +235,8 @@ class ImageView : public VideoCommon::ImageViewBase {
234 friend Image; 235 friend Image;
235 236
236public: 237public:
237 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 238 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
239 const SlotVector<Image>&);
238 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, 240 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
239 const VideoCommon::ImageViewInfo&, GPUVAddr); 241 const VideoCommon::ImageViewInfo&, GPUVAddr);
240 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, 242 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 1941170cb..c3050887c 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1473,8 +1473,7 @@ bool Image::BlitScaleHelper(bool scale_up) {
1473ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, 1473ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
1474 ImageId image_id_, Image& image) 1474 ImageId image_id_, Image& image)
1475 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, 1475 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
1476 src_image{&image}, image_handle{image.Handle()}, 1476 image_handle{image.Handle()}, samples(ConvertSampleCount(image.info.num_samples)) {
1477 samples(ConvertSampleCount(image.info.num_samples)) {
1478 using Shader::TextureType; 1477 using Shader::TextureType;
1479 1478
1480 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); 1479 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1557,6 +1556,12 @@ ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewI
1557 } 1556 }
1558} 1557}
1559 1558
1559ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
1560 ImageId image_id_, Image& image, const SlotVector<Image>& slot_imgs)
1561 : ImageView{runtime, info, image_id_, image} {
1562 slot_images = &slot_imgs;
1563}
1564
1560ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info, 1565ImageView::ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo& info,
1561 const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_) 1566 const VideoCommon::ImageViewInfo& view_info, GPUVAddr gpu_addr_)
1562 : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_}, 1567 : VideoCommon::ImageViewBase{info, view_info}, gpu_addr{gpu_addr_},
@@ -1613,10 +1618,12 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
1613} 1618}
1614 1619
1615bool ImageView::IsRescaled() const noexcept { 1620bool ImageView::IsRescaled() const noexcept {
1616 if (!src_image) { 1621 if (!slot_images) {
1617 return false; 1622 return false;
1618 } 1623 }
1619 return src_image->IsRescaled(); 1624 const auto& slots = *slot_images;
1625 const auto& src_image = slots[image_id];
1626 return src_image.IsRescaled();
1620} 1627}
1621 1628
1622vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { 1629vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index c592f2666..2f12be78b 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -23,6 +23,7 @@ using VideoCommon::ImageId;
23using VideoCommon::NUM_RT; 23using VideoCommon::NUM_RT;
24using VideoCommon::Region2D; 24using VideoCommon::Region2D;
25using VideoCommon::RenderTargets; 25using VideoCommon::RenderTargets;
26using VideoCommon::SlotVector;
26using VideoCore::Surface::PixelFormat; 27using VideoCore::Surface::PixelFormat;
27 28
28class ASTCDecoderPass; 29class ASTCDecoderPass;
@@ -170,6 +171,8 @@ private:
170class ImageView : public VideoCommon::ImageViewBase { 171class ImageView : public VideoCommon::ImageViewBase {
171public: 172public:
172 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&); 173 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&);
174 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageViewInfo&, ImageId, Image&,
175 const SlotVector<Image>&);
173 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&, 176 explicit ImageView(TextureCacheRuntime&, const VideoCommon::ImageInfo&,
174 const VideoCommon::ImageViewInfo&, GPUVAddr); 177 const VideoCommon::ImageViewInfo&, GPUVAddr);
175 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&); 178 explicit ImageView(TextureCacheRuntime&, const VideoCommon::NullImageViewParams&);
@@ -226,7 +229,7 @@ private:
226 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); 229 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
227 230
228 const Device* device = nullptr; 231 const Device* device = nullptr;
229 const Image* src_image{}; 232 const SlotVector<Image>* slot_images = nullptr;
230 233
231 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; 234 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
232 std::unique_ptr<StorageViews> storage_views; 235 std::unique_ptr<StorageViews> storage_views;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 2e19fced2..b494152b8 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1397,7 +1397,8 @@ ImageViewId TextureCache<P>::FindOrEmplaceImageView(ImageId image_id, const Imag
1397 if (const ImageViewId image_view_id = image.FindView(info); image_view_id) { 1397 if (const ImageViewId image_view_id = image.FindView(info); image_view_id) {
1398 return image_view_id; 1398 return image_view_id;
1399 } 1399 }
1400 const ImageViewId image_view_id = slot_image_views.insert(runtime, info, image_id, image); 1400 const ImageViewId image_view_id =
1401 slot_image_views.insert(runtime, info, image_id, image, slot_images);
1401 image.InsertView(info, image_view_id); 1402 image.InsertView(info, image_view_id);
1402 return image_view_id; 1403 return image_view_id;
1403} 1404}
diff --git a/src/video_core/texture_cache/util.cpp b/src/video_core/texture_cache/util.cpp
index 7bd31b211..d8e19cb2f 100644
--- a/src/video_core/texture_cache/util.cpp
+++ b/src/video_core/texture_cache/util.cpp
@@ -364,14 +364,14 @@ template <u32 GOB_EXTENT>
364 364
365[[nodiscard]] std::optional<SubresourceExtent> ResolveOverlapRightAddress2D( 365[[nodiscard]] std::optional<SubresourceExtent> ResolveOverlapRightAddress2D(
366 const ImageInfo& new_info, GPUVAddr gpu_addr, const ImageBase& overlap, bool strict_size) { 366 const ImageInfo& new_info, GPUVAddr gpu_addr, const ImageBase& overlap, bool strict_size) {
367 const u32 layer_stride = new_info.layer_stride; 367 const u64 layer_stride = new_info.layer_stride;
368 const s32 new_size = layer_stride * new_info.resources.layers; 368 const u64 new_size = layer_stride * new_info.resources.layers;
369 const s32 diff = static_cast<s32>(overlap.gpu_addr - gpu_addr); 369 const u64 diff = overlap.gpu_addr - gpu_addr;
370 if (diff > new_size) { 370 if (diff > new_size) {
371 return std::nullopt; 371 return std::nullopt;
372 } 372 }
373 const s32 base_layer = diff / layer_stride; 373 const s32 base_layer = static_cast<s32>(diff / layer_stride);
374 const s32 mip_offset = diff % layer_stride; 374 const s32 mip_offset = static_cast<s32>(diff % layer_stride);
375 const std::array offsets = CalculateMipLevelOffsets(new_info); 375 const std::array offsets = CalculateMipLevelOffsets(new_info);
376 const auto end = offsets.begin() + new_info.resources.levels; 376 const auto end = offsets.begin() + new_info.resources.levels;
377 const auto it = std::find(offsets.begin(), end, static_cast<u32>(mip_offset)); 377 const auto it = std::find(offsets.begin(), end, static_cast<u32>(mip_offset));
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index c6222b571..d63193131 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -33,7 +33,7 @@ void UpdateController(Core::HID::EmulatedController* controller,
33 } 33 }
34 controller->SetNpadStyleIndex(controller_type); 34 controller->SetNpadStyleIndex(controller_type);
35 if (connected) { 35 if (connected) {
36 controller->Connect(); 36 controller->Connect(true);
37 } 37 }
38} 38}
39 39
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp
index 8a8be8e40..cb6163702 100644
--- a/src/yuzu/configuration/configure_input_player.cpp
+++ b/src/yuzu/configuration/configure_input_player.cpp
@@ -599,11 +599,11 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i
599 if (is_connected) { 599 if (is_connected) {
600 if (type == Core::HID::NpadStyleIndex::Handheld) { 600 if (type == Core::HID::NpadStyleIndex::Handheld) {
601 emulated_controller_p1->Disconnect(); 601 emulated_controller_p1->Disconnect();
602 emulated_controller_handheld->Connect(); 602 emulated_controller_handheld->Connect(true);
603 emulated_controller = emulated_controller_handheld; 603 emulated_controller = emulated_controller_handheld;
604 } else { 604 } else {
605 emulated_controller_handheld->Disconnect(); 605 emulated_controller_handheld->Disconnect();
606 emulated_controller_p1->Connect(); 606 emulated_controller_p1->Connect(true);
607 emulated_controller = emulated_controller_p1; 607 emulated_controller = emulated_controller_p1;
608 } 608 }
609 } 609 }
@@ -718,7 +718,7 @@ void ConfigureInputPlayer::LoadConfiguration() {
718void ConfigureInputPlayer::ConnectPlayer(bool connected) { 718void ConfigureInputPlayer::ConnectPlayer(bool connected) {
719 ui->groupConnectedController->setChecked(connected); 719 ui->groupConnectedController->setChecked(connected);
720 if (connected) { 720 if (connected) {
721 emulated_controller->Connect(); 721 emulated_controller->Connect(true);
722 } else { 722 } else {
723 emulated_controller->Disconnect(); 723 emulated_controller->Disconnect();
724 } 724 }