summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/common/CMakeLists.txt5
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/hid/emulated_console.cpp3
-rw-r--r--src/core/hid/emulated_console.h2
-rw-r--r--src/core/hid/emulated_controller.cpp19
-rw-r--r--src/core/hid/hid_types.h7
-rw-r--r--src/core/hid/motion_input.cpp12
-rw-r--r--src/core/hid/motion_input.h5
-rw-r--r--src/core/hle/kernel/k_process.cpp2
-rw-r--r--src/core/hle/kernel/kernel.cpp5
-rw-r--r--src/core/hle/kernel/svc.cpp9
-rw-r--r--src/core/hle/lock.cpp9
-rw-r--r--src/core/hle/lock.h18
-rw-r--r--src/core/hle/service/bcat/backend/backend.cpp12
-rw-r--r--src/core/hle/service/bcat/backend/backend.h5
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.cpp20
-rw-r--r--src/core/hle/service/hid/controllers/console_sixaxis.h10
-rw-r--r--src/core/hle/service/hid/controllers/npad.cpp7
-rw-r--r--src/core/hle/service/hid/controllers/npad.h7
-rw-r--r--src/core/hle/service/hid/hid.cpp2
-rw-r--r--src/core/hle/service/nfp/nfp.cpp2
-rw-r--r--src/core/loader/kip.cpp8
-rw-r--r--src/input_common/drivers/udp_client.cpp74
-rw-r--r--src/input_common/helpers/udp_protocol.h21
-rw-r--r--src/tests/CMakeLists.txt3
-rw-r--r--src/tests/input_common/calibration_configuration_job.cpp136
-rw-r--r--src/video_core/command_classes/codecs/codec.cpp8
-rw-r--r--src/video_core/renderer_opengl/gl_texture_cache.h2
-rw-r--r--src/video_core/renderer_opengl/renderer_opengl.cpp50
-rw-r--r--src/video_core/renderer_vulkan/blit_image.cpp123
-rw-r--r--src/video_core/renderer_vulkan/blit_image.h30
-rw-r--r--src/video_core/renderer_vulkan/vk_blit_screen.cpp37
-rw-r--r--src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp11
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.cpp34
-rw-r--r--src/video_core/renderer_vulkan/vk_texture_cache.h8
-rw-r--r--src/video_core/texture_cache/texture_cache.h15
-rw-r--r--src/video_core/vulkan_common/vulkan_device.cpp31
-rw-r--r--src/video_core/vulkan_common/vulkan_device.h13
-rw-r--r--src/yuzu/applets/qt_controller.cpp3
-rw-r--r--src/yuzu/applets/qt_error.cpp3
-rw-r--r--src/yuzu/applets/qt_profile_select.cpp3
-rw-r--r--src/yuzu/main.cpp41
42 files changed, 478 insertions, 339 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt
index 919da4a53..790193b00 100644
--- a/src/common/CMakeLists.txt
+++ b/src/common/CMakeLists.txt
@@ -22,6 +22,11 @@ add_custom_command(OUTPUT scm_rev.cpp
22 -DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING} 22 -DTITLE_BAR_FORMAT_RUNNING=${TITLE_BAR_FORMAT_RUNNING}
23 -DBUILD_TAG=${BUILD_TAG} 23 -DBUILD_TAG=${BUILD_TAG}
24 -DBUILD_ID=${DISPLAY_VERSION} 24 -DBUILD_ID=${DISPLAY_VERSION}
25 -DGIT_REF_SPEC=${GIT_REF_SPEC}
26 -DGIT_REV=${GIT_REV}
27 -DGIT_DESC=${GIT_DESC}
28 -DGIT_BRANCH=${GIT_BRANCH}
29 -DBUILD_FULLNAME=${BUILD_FULLNAME}
25 -DGIT_EXECUTABLE=${GIT_EXECUTABLE} 30 -DGIT_EXECUTABLE=${GIT_EXECUTABLE}
26 -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake 31 -P ${CMAKE_SOURCE_DIR}/CMakeModules/GenerateSCMRev.cmake
27 DEPENDS 32 DEPENDS
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 49bed614a..698c4f912 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -265,8 +265,6 @@ add_library(core STATIC
265 hle/kernel/svc_wrap.h 265 hle/kernel/svc_wrap.h
266 hle/kernel/time_manager.cpp 266 hle/kernel/time_manager.cpp
267 hle/kernel/time_manager.h 267 hle/kernel/time_manager.h
268 hle/lock.cpp
269 hle/lock.h
270 hle/result.h 268 hle/result.h
271 hle/service/acc/acc.cpp 269 hle/service/acc/acc.cpp
272 hle/service/acc/acc.h 270 hle/service/acc/acc.h
diff --git a/src/core/hid/emulated_console.cpp b/src/core/hid/emulated_console.cpp
index 685ec080c..08f8af551 100644
--- a/src/core/hid/emulated_console.cpp
+++ b/src/core/hid/emulated_console.cpp
@@ -161,7 +161,10 @@ void EmulatedConsole::SetMotion(const Common::Input::CallbackStatus& callback) {
161 motion.rotation = emulated.GetGyroscope(); 161 motion.rotation = emulated.GetGyroscope();
162 motion.orientation = emulated.GetOrientation(); 162 motion.orientation = emulated.GetOrientation();
163 motion.quaternion = emulated.GetQuaternion(); 163 motion.quaternion = emulated.GetQuaternion();
164 motion.gyro_bias = emulated.GetGyroBias();
164 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); 165 motion.is_at_rest = !emulated.IsMoving(motion_sensitivity);
166 // Find what is this value
167 motion.verticalization_error = 0.0f;
165 168
166 TriggerOnChange(ConsoleTriggerType::Motion); 169 TriggerOnChange(ConsoleTriggerType::Motion);
167} 170}
diff --git a/src/core/hid/emulated_console.h b/src/core/hid/emulated_console.h
index 3afd284d5..707419102 100644
--- a/src/core/hid/emulated_console.h
+++ b/src/core/hid/emulated_console.h
@@ -50,6 +50,8 @@ struct ConsoleMotion {
50 Common::Vec3f rotation{}; 50 Common::Vec3f rotation{};
51 std::array<Common::Vec3f, 3> orientation{}; 51 std::array<Common::Vec3f, 3> orientation{};
52 Common::Quaternion<f32> quaternion{}; 52 Common::Quaternion<f32> quaternion{};
53 Common::Vec3f gyro_bias{};
54 f32 verticalization_error{};
53 bool is_at_rest{}; 55 bool is_at_rest{};
54}; 56};
55 57
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp
index 93372445b..ff9d7a7e3 100644
--- a/src/core/hid/emulated_controller.cpp
+++ b/src/core/hid/emulated_controller.cpp
@@ -843,23 +843,18 @@ bool EmulatedController::SetVibration(std::size_t device_index, VibrationValue v
843} 843}
844 844
845bool EmulatedController::TestVibration(std::size_t device_index) { 845bool EmulatedController::TestVibration(std::size_t device_index) {
846 if (device_index >= output_devices.size()) { 846 static constexpr VibrationValue test_vibration = {
847 return false;
848 }
849 if (!output_devices[device_index]) {
850 return false;
851 }
852
853 // Send a slight vibration to test for rumble support
854 constexpr Common::Input::VibrationStatus status = {
855 .low_amplitude = 0.001f, 847 .low_amplitude = 0.001f,
856 .low_frequency = 160.0f, 848 .low_frequency = 160.0f,
857 .high_amplitude = 0.001f, 849 .high_amplitude = 0.001f,
858 .high_frequency = 320.0f, 850 .high_frequency = 320.0f,
859 .type = Common::Input::VibrationAmplificationType::Linear,
860 }; 851 };
861 return output_devices[device_index]->SetVibration(status) == 852
862 Common::Input::VibrationError::None; 853 // Send a slight vibration to test for rumble support
854 SetVibration(device_index, test_vibration);
855
856 // Stop any vibration and return the result
857 return SetVibration(device_index, DEFAULT_VIBRATION_VALUE);
863} 858}
864 859
865void EmulatedController::SetLedPattern() { 860void EmulatedController::SetLedPattern() {
diff --git a/src/core/hid/hid_types.h b/src/core/hid/hid_types.h
index 7c12f01fc..4eca68533 100644
--- a/src/core/hid/hid_types.h
+++ b/src/core/hid/hid_types.h
@@ -496,6 +496,13 @@ struct VibrationValue {
496}; 496};
497static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size."); 497static_assert(sizeof(VibrationValue) == 0x10, "VibrationValue has incorrect size.");
498 498
499constexpr VibrationValue DEFAULT_VIBRATION_VALUE{
500 .low_amplitude = 0.0f,
501 .low_frequency = 160.0f,
502 .high_amplitude = 0.0f,
503 .high_frequency = 320.0f,
504};
505
499// This is nn::hid::VibrationDeviceInfo 506// This is nn::hid::VibrationDeviceInfo
500struct VibrationDeviceInfo { 507struct VibrationDeviceInfo {
501 VibrationDeviceType type{}; 508 VibrationDeviceType type{};
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp
index c25fea966..a23f192d7 100644
--- a/src/core/hid/motion_input.cpp
+++ b/src/core/hid/motion_input.cpp
@@ -23,11 +23,11 @@ void MotionInput::SetAcceleration(const Common::Vec3f& acceleration) {
23} 23}
24 24
25void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) { 25void MotionInput::SetGyroscope(const Common::Vec3f& gyroscope) {
26 gyro = gyroscope - gyro_drift; 26 gyro = gyroscope - gyro_bias;
27 27
28 // Auto adjust drift to minimize drift 28 // Auto adjust drift to minimize drift
29 if (!IsMoving(0.1f)) { 29 if (!IsMoving(0.1f)) {
30 gyro_drift = (gyro_drift * 0.9999f) + (gyroscope * 0.0001f); 30 gyro_bias = (gyro_bias * 0.9999f) + (gyroscope * 0.0001f);
31 } 31 }
32 32
33 if (gyro.Length2() < gyro_threshold) { 33 if (gyro.Length2() < gyro_threshold) {
@@ -41,8 +41,8 @@ void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) {
41 quat = quaternion; 41 quat = quaternion;
42} 42}
43 43
44void MotionInput::SetGyroDrift(const Common::Vec3f& drift) { 44void MotionInput::SetGyroBias(const Common::Vec3f& bias) {
45 gyro_drift = drift; 45 gyro_bias = bias;
46} 46}
47 47
48void MotionInput::SetGyroThreshold(f32 threshold) { 48void MotionInput::SetGyroThreshold(f32 threshold) {
@@ -192,6 +192,10 @@ Common::Vec3f MotionInput::GetGyroscope() const {
192 return gyro; 192 return gyro;
193} 193}
194 194
195Common::Vec3f MotionInput::GetGyroBias() const {
196 return gyro_bias;
197}
198
195Common::Quaternion<f32> MotionInput::GetQuaternion() const { 199Common::Quaternion<f32> MotionInput::GetQuaternion() const {
196 return quat; 200 return quat;
197} 201}
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h
index 5b5b420bb..bca4520fa 100644
--- a/src/core/hid/motion_input.h
+++ b/src/core/hid/motion_input.h
@@ -24,7 +24,7 @@ public:
24 void SetAcceleration(const Common::Vec3f& acceleration); 24 void SetAcceleration(const Common::Vec3f& acceleration);
25 void SetGyroscope(const Common::Vec3f& gyroscope); 25 void SetGyroscope(const Common::Vec3f& gyroscope);
26 void SetQuaternion(const Common::Quaternion<f32>& quaternion); 26 void SetQuaternion(const Common::Quaternion<f32>& quaternion);
27 void SetGyroDrift(const Common::Vec3f& drift); 27 void SetGyroBias(const Common::Vec3f& bias);
28 void SetGyroThreshold(f32 threshold); 28 void SetGyroThreshold(f32 threshold);
29 29
30 void EnableReset(bool reset); 30 void EnableReset(bool reset);
@@ -36,6 +36,7 @@ public:
36 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const; 36 [[nodiscard]] std::array<Common::Vec3f, 3> GetOrientation() const;
37 [[nodiscard]] Common::Vec3f GetAcceleration() const; 37 [[nodiscard]] Common::Vec3f GetAcceleration() const;
38 [[nodiscard]] Common::Vec3f GetGyroscope() const; 38 [[nodiscard]] Common::Vec3f GetGyroscope() const;
39 [[nodiscard]] Common::Vec3f GetGyroBias() const;
39 [[nodiscard]] Common::Vec3f GetRotations() const; 40 [[nodiscard]] Common::Vec3f GetRotations() const;
40 [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; 41 [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const;
41 42
@@ -69,7 +70,7 @@ private:
69 Common::Vec3f gyro; 70 Common::Vec3f gyro;
70 71
71 // Vector to be substracted from gyro measurements 72 // Vector to be substracted from gyro measurements
72 Common::Vec3f gyro_drift; 73 Common::Vec3f gyro_bias;
73 74
74 // Minimum gyro amplitude to detect if the device is moving 75 // Minimum gyro amplitude to detect if the device is moving
75 f32 gyro_threshold = 0.0f; 76 f32 gyro_threshold = 0.0f;
diff --git a/src/core/hle/kernel/k_process.cpp b/src/core/hle/kernel/k_process.cpp
index 90dda40dc..aee313995 100644
--- a/src/core/hle/kernel/k_process.cpp
+++ b/src/core/hle/kernel/k_process.cpp
@@ -28,7 +28,6 @@
28#include "core/hle/kernel/k_thread.h" 28#include "core/hle/kernel/k_thread.h"
29#include "core/hle/kernel/kernel.h" 29#include "core/hle/kernel/kernel.h"
30#include "core/hle/kernel/svc_results.h" 30#include "core/hle/kernel/svc_results.h"
31#include "core/hle/lock.h"
32#include "core/memory.h" 31#include "core/memory.h"
33 32
34namespace Kernel { 33namespace Kernel {
@@ -543,7 +542,6 @@ void KProcess::FreeTLSRegion(VAddr tls_address) {
543} 542}
544 543
545void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) { 544void KProcess::LoadModule(CodeSet code_set, VAddr base_addr) {
546 std::lock_guard lock{HLE::g_hle_lock};
547 const auto ReprotectSegment = [&](const CodeSet::Segment& segment, 545 const auto ReprotectSegment = [&](const CodeSet::Segment& segment,
548 KMemoryPermission permission) { 546 KMemoryPermission permission) {
549 page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission); 547 page_table->SetProcessMemoryPermission(segment.addr + base_addr, segment.size, permission);
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp
index 2e4e4cb1c..1225e1fba 100644
--- a/src/core/hle/kernel/kernel.cpp
+++ b/src/core/hle/kernel/kernel.cpp
@@ -182,7 +182,10 @@ struct KernelCore::Impl {
182 // Shutdown all processes. 182 // Shutdown all processes.
183 if (current_process) { 183 if (current_process) {
184 current_process->Finalize(); 184 current_process->Finalize();
185 current_process->Close(); 185 // current_process->Close();
186 // TODO: The current process should be destroyed based on accurate ref counting after
187 // calling Close(). Adding a manual Destroy() call instead to avoid a memory leak.
188 current_process->Destroy();
186 current_process = nullptr; 189 current_process = nullptr;
187 } 190 }
188 191
diff --git a/src/core/hle/kernel/svc.cpp b/src/core/hle/kernel/svc.cpp
index a9f7438ea..bb9475c56 100644
--- a/src/core/hle/kernel/svc.cpp
+++ b/src/core/hle/kernel/svc.cpp
@@ -41,7 +41,6 @@
41#include "core/hle/kernel/svc_results.h" 41#include "core/hle/kernel/svc_results.h"
42#include "core/hle/kernel/svc_types.h" 42#include "core/hle/kernel/svc_types.h"
43#include "core/hle/kernel/svc_wrap.h" 43#include "core/hle/kernel/svc_wrap.h"
44#include "core/hle/lock.h"
45#include "core/hle/result.h" 44#include "core/hle/result.h"
46#include "core/memory.h" 45#include "core/memory.h"
47#include "core/reporter.h" 46#include "core/reporter.h"
@@ -137,7 +136,6 @@ enum class ResourceLimitValueType {
137 136
138/// 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.
139static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) { 138static ResultCode SetHeapSize(Core::System& system, VAddr* heap_addr, u64 heap_size) {
140 std::lock_guard lock{HLE::g_hle_lock};
141 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size); 139 LOG_TRACE(Kernel_SVC, "called, heap_size=0x{:X}", heap_size);
142 140
143 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB. 141 // Size must be a multiple of 0x200000 (2MB) and be equal to or less than 8GB.
@@ -168,7 +166,6 @@ static ResultCode SetHeapSize32(Core::System& system, u32* heap_addr, u32 heap_s
168 166
169static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask, 167static ResultCode SetMemoryAttribute(Core::System& system, VAddr address, u64 size, u32 mask,
170 u32 attribute) { 168 u32 attribute) {
171 std::lock_guard lock{HLE::g_hle_lock};
172 LOG_DEBUG(Kernel_SVC, 169 LOG_DEBUG(Kernel_SVC,
173 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address, 170 "called, address=0x{:016X}, size=0x{:X}, mask=0x{:08X}, attribute=0x{:08X}", address,
174 size, mask, attribute); 171 size, mask, attribute);
@@ -212,7 +209,6 @@ static ResultCode SetMemoryAttribute32(Core::System& system, u32 address, u32 si
212 209
213/// Maps a memory range into a different range. 210/// Maps a memory range into a different range.
214static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 211static ResultCode MapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
215 std::lock_guard lock{HLE::g_hle_lock};
216 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 212 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
217 src_addr, size); 213 src_addr, size);
218 214
@@ -232,7 +228,6 @@ static ResultCode MapMemory32(Core::System& system, u32 dst_addr, u32 src_addr,
232 228
233/// Unmaps a region that was previously mapped with svcMapMemory 229/// Unmaps a region that was previously mapped with svcMapMemory
234static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) { 230static ResultCode UnmapMemory(Core::System& system, VAddr dst_addr, VAddr src_addr, u64 size) {
235 std::lock_guard lock{HLE::g_hle_lock};
236 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr, 231 LOG_TRACE(Kernel_SVC, "called, dst_addr=0x{:X}, src_addr=0x{:X}, size=0x{:X}", dst_addr,
237 src_addr, size); 232 src_addr, size);
238 233
@@ -642,7 +637,6 @@ static void OutputDebugString(Core::System& system, VAddr address, u64 len) {
642/// Gets system/memory information for the current process 637/// Gets system/memory information for the current process
643static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle, 638static ResultCode GetInfo(Core::System& system, u64* result, u64 info_id, Handle handle,
644 u64 info_sub_id) { 639 u64 info_sub_id) {
645 std::lock_guard lock{HLE::g_hle_lock};
646 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id, 640 LOG_TRACE(Kernel_SVC, "called info_id=0x{:X}, info_sub_id=0x{:X}, handle=0x{:08X}", info_id,
647 info_sub_id, handle); 641 info_sub_id, handle);
648 642
@@ -924,7 +918,6 @@ static ResultCode GetInfo32(Core::System& system, u32* result_low, u32* result_h
924 918
925/// Maps memory at a desired address 919/// Maps memory at a desired address
926static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 920static ResultCode MapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
927 std::lock_guard lock{HLE::g_hle_lock};
928 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 921 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
929 922
930 if (!Common::Is4KBAligned(addr)) { 923 if (!Common::Is4KBAligned(addr)) {
@@ -978,7 +971,6 @@ static ResultCode MapPhysicalMemory32(Core::System& system, u32 addr, u32 size)
978 971
979/// Unmaps memory previously mapped via MapPhysicalMemory 972/// Unmaps memory previously mapped via MapPhysicalMemory
980static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) { 973static ResultCode UnmapPhysicalMemory(Core::System& system, VAddr addr, u64 size) {
981 std::lock_guard lock{HLE::g_hle_lock};
982 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size); 974 LOG_DEBUG(Kernel_SVC, "called, addr=0x{:016X}, size=0x{:X}", addr, size);
983 975
984 if (!Common::Is4KBAligned(addr)) { 976 if (!Common::Is4KBAligned(addr)) {
@@ -1520,7 +1512,6 @@ static ResultCode ControlCodeMemory(Core::System& system, Handle code_memory_han
1520static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address, 1512static ResultCode QueryProcessMemory(Core::System& system, VAddr memory_info_address,
1521 VAddr page_info_address, Handle process_handle, 1513 VAddr page_info_address, Handle process_handle,
1522 VAddr address) { 1514 VAddr address) {
1523 std::lock_guard lock{HLE::g_hle_lock};
1524 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address); 1515 LOG_TRACE(Kernel_SVC, "called process=0x{:08X} address={:X}", process_handle, address);
1525 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable(); 1516 const auto& handle_table = system.Kernel().CurrentProcess()->GetHandleTable();
1526 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle); 1517 KScopedAutoObject process = handle_table.GetObject<KProcess>(process_handle);
diff --git a/src/core/hle/lock.cpp b/src/core/hle/lock.cpp
deleted file mode 100644
index be4bfce3b..000000000
--- a/src/core/hle/lock.cpp
+++ /dev/null
@@ -1,9 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <core/hle/lock.h>
6
7namespace HLE {
8std::recursive_mutex g_hle_lock;
9}
diff --git a/src/core/hle/lock.h b/src/core/hle/lock.h
deleted file mode 100644
index 5c99fe996..000000000
--- a/src/core/hle/lock.h
+++ /dev/null
@@ -1,18 +0,0 @@
1// Copyright 2017 Citra Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <mutex>
8
9namespace HLE {
10/*
11 * Synchronizes access to the internal HLE kernel structures, it is acquired when a guest
12 * application thread performs a syscall. It should be acquired by any host threads that read or
13 * modify the HLE kernel state. Note: Any operation that directly or indirectly reads from or writes
14 * to the emulated memory is not protected by this mutex, and should be avoided in any threads other
15 * than the CPU thread.
16 */
17extern std::recursive_mutex g_hle_lock;
18} // namespace HLE
diff --git a/src/core/hle/service/bcat/backend/backend.cpp b/src/core/hle/service/bcat/backend/backend.cpp
index 4c7d3bb6e..ee49edbb9 100644
--- a/src/core/hle/service/bcat/backend/backend.cpp
+++ b/src/core/hle/service/bcat/backend/backend.cpp
@@ -6,7 +6,6 @@
6#include "common/logging/log.h" 6#include "common/logging/log.h"
7#include "core/core.h" 7#include "core/core.h"
8#include "core/hle/kernel/k_event.h" 8#include "core/hle/kernel/k_event.h"
9#include "core/hle/lock.h"
10#include "core/hle/service/bcat/backend/backend.h" 9#include "core/hle/service/bcat/backend/backend.h"
11 10
12namespace Service::BCAT { 11namespace Service::BCAT {
@@ -29,10 +28,6 @@ DeliveryCacheProgressImpl& ProgressServiceBackend::GetImpl() {
29 return impl; 28 return impl;
30} 29}
31 30
32void ProgressServiceBackend::SetNeedHLELock(bool need) {
33 need_hle_lock = need;
34}
35
36void ProgressServiceBackend::SetTotalSize(u64 size) { 31void ProgressServiceBackend::SetTotalSize(u64 size) {
37 impl.total_bytes = size; 32 impl.total_bytes = size;
38 SignalUpdate(); 33 SignalUpdate();
@@ -88,12 +83,7 @@ void ProgressServiceBackend::FinishDownload(ResultCode result) {
88} 83}
89 84
90void ProgressServiceBackend::SignalUpdate() { 85void ProgressServiceBackend::SignalUpdate() {
91 if (need_hle_lock) { 86 update_event->GetWritableEvent().Signal();
92 std::lock_guard lock(HLE::g_hle_lock);
93 update_event->GetWritableEvent().Signal();
94 } else {
95 update_event->GetWritableEvent().Signal();
96 }
97} 87}
98 88
99Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {} 89Backend::Backend(DirectoryGetter getter) : dir_getter(std::move(getter)) {}
diff --git a/src/core/hle/service/bcat/backend/backend.h b/src/core/hle/service/bcat/backend/backend.h
index 59c6d4740..63833c927 100644
--- a/src/core/hle/service/bcat/backend/backend.h
+++ b/src/core/hle/service/bcat/backend/backend.h
@@ -71,10 +71,6 @@ class ProgressServiceBackend {
71public: 71public:
72 ~ProgressServiceBackend(); 72 ~ProgressServiceBackend();
73 73
74 // Clients should call this with true if any of the functions are going to be called from a
75 // non-HLE thread and this class need to lock the hle mutex. (default is false)
76 void SetNeedHLELock(bool need);
77
78 // Sets the number of bytes total in the entire download. 74 // Sets the number of bytes total in the entire download.
79 void SetTotalSize(u64 size); 75 void SetTotalSize(u64 size);
80 76
@@ -109,7 +105,6 @@ private:
109 105
110 DeliveryCacheProgressImpl impl{}; 106 DeliveryCacheProgressImpl impl{};
111 Kernel::KEvent* update_event; 107 Kernel::KEvent* update_event;
112 bool need_hle_lock = false;
113}; 108};
114 109
115// A class representing an abstract backend for BCAT functionality. 110// A class representing an abstract backend for BCAT functionality.
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.cpp b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
index f0f3105dc..a727b3582 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.cpp
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.cpp
@@ -33,15 +33,14 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
33 const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state; 33 const auto& last_entry = seven_sixaxis_lifo.ReadCurrentEntry().state;
34 next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1; 34 next_seven_sixaxis_state.sampling_number = last_entry.sampling_number + 1;
35 35
36 // Try to read sixaxis sensor states
37 const auto motion_status = console->GetMotion(); 36 const auto motion_status = console->GetMotion();
37 last_global_timestamp = core_timing.GetGlobalTimeNs().count();
38 38
39 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest; 39 // This value increments every time the switch goes to sleep
40 40 next_seven_sixaxis_state.unknown = 1;
41 next_seven_sixaxis_state.timestamp = last_global_timestamp - last_saved_timestamp;
41 next_seven_sixaxis_state.accel = motion_status.accel; 42 next_seven_sixaxis_state.accel = motion_status.accel;
42 // Zero gyro values as they just mess up with the camera 43 next_seven_sixaxis_state.gyro = motion_status.gyro;
43 // Note: Probably a correct sensivity setting must be set
44 next_seven_sixaxis_state.gyro = {};
45 next_seven_sixaxis_state.quaternion = { 44 next_seven_sixaxis_state.quaternion = {
46 { 45 {
47 motion_status.quaternion.xyz.y, 46 motion_status.quaternion.xyz.y,
@@ -52,9 +51,9 @@ void Controller_ConsoleSixAxis::OnUpdate(const Core::Timing::CoreTiming& core_ti
52 }; 51 };
53 52
54 console_six_axis.sampling_number++; 53 console_six_axis.sampling_number++;
55 // TODO(German77): Find the purpose of those values 54 console_six_axis.is_seven_six_axis_sensor_at_rest = motion_status.is_at_rest;
56 console_six_axis.verticalization_error = 0.0f; 55 console_six_axis.verticalization_error = motion_status.verticalization_error;
57 console_six_axis.gyro_bias = {0.0f, 0.0f, 0.0f}; 56 console_six_axis.gyro_bias = motion_status.gyro_bias;
58 57
59 // Update console six axis shared memory 58 // Update console six axis shared memory
60 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis)); 59 std::memcpy(data + SHARED_MEMORY_OFFSET, &console_six_axis, sizeof(console_six_axis));
@@ -69,7 +68,6 @@ void Controller_ConsoleSixAxis::SetTransferMemoryPointer(u8* t_mem) {
69} 68}
70 69
71void Controller_ConsoleSixAxis::ResetTimestamp() { 70void Controller_ConsoleSixAxis::ResetTimestamp() {
72 seven_sixaxis_lifo.buffer_count = 0; 71 last_saved_timestamp = last_global_timestamp;
73 seven_sixaxis_lifo.buffer_tail = 0;
74} 72}
75} // namespace Service::HID 73} // namespace Service::HID
diff --git a/src/core/hle/service/hid/controllers/console_sixaxis.h b/src/core/hle/service/hid/controllers/console_sixaxis.h
index 279241858..26d153f0c 100644
--- a/src/core/hle/service/hid/controllers/console_sixaxis.h
+++ b/src/core/hle/service/hid/controllers/console_sixaxis.h
@@ -39,8 +39,9 @@ public:
39 39
40private: 40private:
41 struct SevenSixAxisState { 41 struct SevenSixAxisState {
42 INSERT_PADDING_WORDS(4); // unused 42 INSERT_PADDING_WORDS(2); // unused
43 s64 sampling_number{}; 43 u64 timestamp{};
44 u64 sampling_number{};
44 u64 unknown{}; 45 u64 unknown{};
45 Common::Vec3f accel{}; 46 Common::Vec3f accel{};
46 Common::Vec3f gyro{}; 47 Common::Vec3f gyro{};
@@ -52,9 +53,10 @@ private:
52 struct ConsoleSharedMemory { 53 struct ConsoleSharedMemory {
53 u64 sampling_number{}; 54 u64 sampling_number{};
54 bool is_seven_six_axis_sensor_at_rest{}; 55 bool is_seven_six_axis_sensor_at_rest{};
55 INSERT_PADDING_BYTES(4); // padding 56 INSERT_PADDING_BYTES(3); // padding
56 f32 verticalization_error{}; 57 f32 verticalization_error{};
57 Common::Vec3f gyro_bias{}; 58 Common::Vec3f gyro_bias{};
59 INSERT_PADDING_BYTES(4); // padding
58 }; 60 };
59 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size"); 61 static_assert(sizeof(ConsoleSharedMemory) == 0x20, "ConsoleSharedMemory is an invalid size");
60 62
@@ -64,6 +66,8 @@ private:
64 Core::HID::EmulatedConsole* console; 66 Core::HID::EmulatedConsole* console;
65 u8* transfer_memory = nullptr; 67 u8* transfer_memory = nullptr;
66 bool is_transfer_memory_set = false; 68 bool is_transfer_memory_set = false;
69 u64 last_saved_timestamp{};
70 u64 last_global_timestamp{};
67 ConsoleSharedMemory console_six_axis{}; 71 ConsoleSharedMemory console_six_axis{};
68 SevenSixAxisState next_seven_sixaxis_state{}; 72 SevenSixAxisState next_seven_sixaxis_state{};
69}; 73};
diff --git a/src/core/hle/service/hid/controllers/npad.cpp b/src/core/hle/service/hid/controllers/npad.cpp
index 2705e9dcb..e5c951e06 100644
--- a/src/core/hle/service/hid/controllers/npad.cpp
+++ b/src/core/hle/service/hid/controllers/npad.cpp
@@ -66,9 +66,9 @@ Controller_NPad::Controller_NPad(Core::HID::HIDCore& hid_core_,
66 auto& controller = controller_data[i]; 66 auto& controller = controller_data[i];
67 controller.device = hid_core.GetEmulatedControllerByIndex(i); 67 controller.device = hid_core.GetEmulatedControllerByIndex(i);
68 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value = 68 controller.vibration[Core::HID::EmulatedDeviceIndex::LeftIndex].latest_vibration_value =
69 DEFAULT_VIBRATION_VALUE; 69 Core::HID::DEFAULT_VIBRATION_VALUE;
70 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value = 70 controller.vibration[Core::HID::EmulatedDeviceIndex::RightIndex].latest_vibration_value =
71 DEFAULT_VIBRATION_VALUE; 71 Core::HID::DEFAULT_VIBRATION_VALUE;
72 Core::HID::ControllerUpdateCallback engine_callback{ 72 Core::HID::ControllerUpdateCallback engine_callback{
73 .on_change = [this, 73 .on_change = [this,
74 i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); }, 74 i](Core::HID::ControllerTriggerType type) { ControllerUpdate(type, i); },
@@ -781,7 +781,8 @@ bool Controller_NPad::VibrateControllerAtIndex(Core::HID::NpadIdType npad_id,
781 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f}; 781 Core::HID::VibrationValue vibration{0.0f, 160.0f, 0.0f, 320.0f};
782 controller.device->SetVibration(device_index, vibration); 782 controller.device->SetVibration(device_index, vibration);
783 // Then reset the vibration value to its default value. 783 // Then reset the vibration value to its default value.
784 controller.vibration[device_index].latest_vibration_value = DEFAULT_VIBRATION_VALUE; 784 controller.vibration[device_index].latest_vibration_value =
785 Core::HID::DEFAULT_VIBRATION_VALUE;
785 } 786 }
786 787
787 return false; 788 return false;
diff --git a/src/core/hle/service/hid/controllers/npad.h b/src/core/hle/service/hid/controllers/npad.h
index 63281cb35..6b2872bad 100644
--- a/src/core/hle/service/hid/controllers/npad.h
+++ b/src/core/hle/service/hid/controllers/npad.h
@@ -90,13 +90,6 @@ public:
90 Default = 3, 90 Default = 3,
91 }; 91 };
92 92
93 static constexpr Core::HID::VibrationValue DEFAULT_VIBRATION_VALUE{
94 .low_amplitude = 0.0f,
95 .low_frequency = 160.0f,
96 .high_amplitude = 0.0f,
97 .high_frequency = 320.0f,
98 };
99
100 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set); 93 void SetSupportedStyleSet(Core::HID::NpadStyleTag style_set);
101 Core::HID::NpadStyleTag GetSupportedStyleSet() const; 94 Core::HID::NpadStyleTag GetSupportedStyleSet() const;
102 95
diff --git a/src/core/hle/service/hid/hid.cpp b/src/core/hle/service/hid/hid.cpp
index 7163e1a4e..6e12381fb 100644
--- a/src/core/hle/service/hid/hid.cpp
+++ b/src/core/hle/service/hid/hid.cpp
@@ -1404,7 +1404,7 @@ void Hid::SendVibrationGcErmCommand(Kernel::HLERequestContext& ctx) {
1404 .high_frequency = 0.0f, 1404 .high_frequency = 0.0f,
1405 }; 1405 };
1406 default: 1406 default:
1407 return Controller_NPad::DEFAULT_VIBRATION_VALUE; 1407 return Core::HID::DEFAULT_VIBRATION_VALUE;
1408 } 1408 }
1409 }(); 1409 }();
1410 1410
diff --git a/src/core/hle/service/nfp/nfp.cpp b/src/core/hle/service/nfp/nfp.cpp
index 693ffc71a..761d0d3c6 100644
--- a/src/core/hle/service/nfp/nfp.cpp
+++ b/src/core/hle/service/nfp/nfp.cpp
@@ -9,7 +9,6 @@
9#include "core/core.h" 9#include "core/core.h"
10#include "core/hle/ipc_helpers.h" 10#include "core/hle/ipc_helpers.h"
11#include "core/hle/kernel/k_event.h" 11#include "core/hle/kernel/k_event.h"
12#include "core/hle/lock.h"
13#include "core/hle/service/nfp/nfp.h" 12#include "core/hle/service/nfp/nfp.h"
14#include "core/hle/service/nfp/nfp_user.h" 13#include "core/hle/service/nfp/nfp_user.h"
15 14
@@ -337,7 +336,6 @@ void Module::Interface::CreateUserInterface(Kernel::HLERequestContext& ctx) {
337} 336}
338 337
339bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) { 338bool Module::Interface::LoadAmiibo(const std::vector<u8>& buffer) {
340 std::lock_guard lock{HLE::g_hle_lock};
341 if (buffer.size() < sizeof(AmiiboFile)) { 339 if (buffer.size() < sizeof(AmiiboFile)) {
342 return false; 340 return false;
343 } 341 }
diff --git a/src/core/loader/kip.cpp b/src/core/loader/kip.cpp
index 3ae9e6e0e..99ed34b00 100644
--- a/src/core/loader/kip.cpp
+++ b/src/core/loader/kip.cpp
@@ -71,7 +71,6 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
71 kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000, 71 kip->GetTitleID(), 0xFFFFFFFFFFFFFFFF, 0x1FE00000,
72 kip->GetKernelCapabilities()); 72 kip->GetKernelCapabilities());
73 73
74 const VAddr base_address = process.PageTable().GetCodeRegionStart();
75 Kernel::CodeSet codeset; 74 Kernel::CodeSet codeset;
76 Kernel::PhysicalMemory program_image; 75 Kernel::PhysicalMemory program_image;
77 76
@@ -91,7 +90,14 @@ AppLoader::LoadResult AppLoader_KIP::Load(Kernel::KProcess& process,
91 program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize()); 90 program_image.resize(PageAlignSize(kip->GetBSSOffset()) + kip->GetBSSSize());
92 codeset.DataSegment().size += kip->GetBSSSize(); 91 codeset.DataSegment().size += kip->GetBSSSize();
93 92
93 // Setup the process code layout
94 if (process.LoadFromMetadata(FileSys::ProgramMetadata::GetDefault(), program_image.size())
95 .IsError()) {
96 return {ResultStatus::ErrorNotInitialized, {}};
97 }
98
94 codeset.memory = std::move(program_image); 99 codeset.memory = std::move(program_image);
100 const VAddr base_address = process.PageTable().GetCodeRegionStart();
95 process.LoadModule(std::move(codeset), base_address); 101 process.LoadModule(std::move(codeset), base_address);
96 102
97 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address); 103 LOG_DEBUG(Loader, "loaded module {} @ 0x{:X}", kip->GetName(), base_address);
diff --git a/src/input_common/drivers/udp_client.cpp b/src/input_common/drivers/udp_client.cpp
index 4ab991a7d..a1ce4525d 100644
--- a/src/input_common/drivers/udp_client.cpp
+++ b/src/input_common/drivers/udp_client.cpp
@@ -536,42 +536,46 @@ CalibrationConfigurationJob::CalibrationConfigurationJob(
536 std::function<void(u16, u16, u16, u16)> data_callback) { 536 std::function<void(u16, u16, u16, u16)> data_callback) {
537 537
538 std::thread([=, this] { 538 std::thread([=, this] {
539 u16 min_x{UINT16_MAX};
540 u16 min_y{UINT16_MAX};
541 u16 max_x{};
542 u16 max_y{};
543
539 Status current_status{Status::Initialized}; 544 Status current_status{Status::Initialized};
540 SocketCallback callback{ 545 SocketCallback callback{[](Response::Version) {}, [](Response::PortInfo) {},
541 [](Response::Version) {}, [](Response::PortInfo) {}, 546 [&](Response::PadData data) {
542 [&](Response::PadData data) { 547 constexpr u16 CALIBRATION_THRESHOLD = 100;
543 static constexpr u16 CALIBRATION_THRESHOLD = 100; 548
544 static constexpr u16 MAX_VALUE = UINT16_MAX; 549 if (current_status == Status::Initialized) {
545 550 // Receiving data means the communication is ready now
546 if (current_status == Status::Initialized) { 551 current_status = Status::Ready;
547 // Receiving data means the communication is ready now 552 status_callback(current_status);
548 current_status = Status::Ready; 553 }
549 status_callback(current_status); 554 if (data.touch[0].is_active == 0) {
550 } 555 return;
551 const auto& touchpad_0 = data.touch[0]; 556 }
552 if (touchpad_0.is_active == 0) { 557 LOG_DEBUG(Input, "Current touch: {} {}", data.touch[0].x,
553 return; 558 data.touch[0].y);
554 } 559 min_x = std::min(min_x, static_cast<u16>(data.touch[0].x));
555 LOG_DEBUG(Input, "Current touch: {} {}", touchpad_0.x, touchpad_0.y); 560 min_y = std::min(min_y, static_cast<u16>(data.touch[0].y));
556 const u16 min_x = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.x)); 561 if (current_status == Status::Ready) {
557 const u16 min_y = std::min(MAX_VALUE, static_cast<u16>(touchpad_0.y)); 562 // First touch - min data (min_x/min_y)
558 if (current_status == Status::Ready) { 563 current_status = Status::Stage1Completed;
559 // First touch - min data (min_x/min_y) 564 status_callback(current_status);
560 current_status = Status::Stage1Completed; 565 }
561 status_callback(current_status); 566 if (data.touch[0].x - min_x > CALIBRATION_THRESHOLD &&
562 } 567 data.touch[0].y - min_y > CALIBRATION_THRESHOLD) {
563 if (touchpad_0.x - min_x > CALIBRATION_THRESHOLD && 568 // Set the current position as max value and finishes
564 touchpad_0.y - min_y > CALIBRATION_THRESHOLD) { 569 // configuration
565 // Set the current position as max value and finishes configuration 570 max_x = data.touch[0].x;
566 const u16 max_x = touchpad_0.x; 571 max_y = data.touch[0].y;
567 const u16 max_y = touchpad_0.y; 572 current_status = Status::Completed;
568 current_status = Status::Completed; 573 data_callback(min_x, min_y, max_x, max_y);
569 data_callback(min_x, min_y, max_x, max_y); 574 status_callback(current_status);
570 status_callback(current_status); 575
571 576 complete_event.Set();
572 complete_event.Set(); 577 }
573 } 578 }};
574 }};
575 Socket socket{host, port, std::move(callback)}; 579 Socket socket{host, port, std::move(callback)};
576 std::thread worker_thread{SocketLoop, &socket}; 580 std::thread worker_thread{SocketLoop, &socket};
577 complete_event.Wait(); 581 complete_event.Wait();
diff --git a/src/input_common/helpers/udp_protocol.h b/src/input_common/helpers/udp_protocol.h
index bcba12c58..2d5d54ddb 100644
--- a/src/input_common/helpers/udp_protocol.h
+++ b/src/input_common/helpers/udp_protocol.h
@@ -54,6 +54,18 @@ struct Message {
54template <typename T> 54template <typename T>
55constexpr Type GetMessageType(); 55constexpr Type GetMessageType();
56 56
57template <typename T>
58Message<T> CreateMessage(const u32 magic, const T data, const u32 sender_id) {
59 boost::crc_32_type crc;
60 Header header{
61 magic, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, sender_id, GetMessageType<T>(),
62 };
63 Message<T> message{header, data};
64 crc.process_bytes(&message, sizeof(Message<T>));
65 message.header.crc = crc.checksum();
66 return message;
67}
68
57namespace Request { 69namespace Request {
58 70
59enum RegisterFlags : u8 { 71enum RegisterFlags : u8 {
@@ -101,14 +113,7 @@ static_assert(std::is_trivially_copyable_v<PadData>,
101 */ 113 */
102template <typename T> 114template <typename T>
103Message<T> Create(const T data, const u32 client_id = 0) { 115Message<T> Create(const T data, const u32 client_id = 0) {
104 boost::crc_32_type crc; 116 return CreateMessage(CLIENT_MAGIC, data, client_id);
105 Header header{
106 CLIENT_MAGIC, PROTOCOL_VERSION, sizeof(T) + sizeof(Type), 0, client_id, GetMessageType<T>(),
107 };
108 Message<T> message{header, data};
109 crc.process_bytes(&message, sizeof(Message<T>));
110 message.header.crc = crc.checksum();
111 return message;
112} 117}
113} // namespace Request 118} // namespace Request
114 119
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt
index c4c012f3d..4a20c0768 100644
--- a/src/tests/CMakeLists.txt
+++ b/src/tests/CMakeLists.txt
@@ -10,11 +10,12 @@ add_executable(tests
10 core/network/network.cpp 10 core/network/network.cpp
11 tests.cpp 11 tests.cpp
12 video_core/buffer_base.cpp 12 video_core/buffer_base.cpp
13 input_common/calibration_configuration_job.cpp
13) 14)
14 15
15create_target_directory_groups(tests) 16create_target_directory_groups(tests)
16 17
17target_link_libraries(tests PRIVATE common core) 18target_link_libraries(tests PRIVATE common core input_common)
18target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads) 19target_link_libraries(tests PRIVATE ${PLATFORM_LIBRARIES} catch-single-include Threads::Threads)
19 20
20add_test(NAME tests COMMAND tests) 21add_test(NAME tests COMMAND tests)
diff --git a/src/tests/input_common/calibration_configuration_job.cpp b/src/tests/input_common/calibration_configuration_job.cpp
new file mode 100644
index 000000000..8c77d81e9
--- /dev/null
+++ b/src/tests/input_common/calibration_configuration_job.cpp
@@ -0,0 +1,136 @@
1// Copyright 2020 yuzu Emulator Project
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include <array>
6#include <string>
7#include <thread>
8#include <boost/asio.hpp>
9#include <boost/crc.hpp>
10#include <catch2/catch.hpp>
11
12#include "input_common/drivers/udp_client.h"
13#include "input_common/helpers/udp_protocol.h"
14
15class FakeCemuhookServer {
16public:
17 FakeCemuhookServer()
18 : socket(io_service, boost::asio::ip::udp::endpoint(boost::asio::ip::udp::v4(), 0)) {}
19
20 ~FakeCemuhookServer() {
21 is_running = false;
22 boost::system::error_code error_code;
23 socket.shutdown(boost::asio::socket_base::shutdown_both, error_code);
24 socket.close();
25 if (handler.joinable()) {
26 handler.join();
27 }
28 }
29
30 u16 GetPort() {
31 return socket.local_endpoint().port();
32 }
33
34 std::string GetHost() {
35 return socket.local_endpoint().address().to_string();
36 }
37
38 void Run(const std::vector<InputCommon::CemuhookUDP::Response::TouchPad> touch_movement_path) {
39 constexpr size_t HeaderSize = sizeof(InputCommon::CemuhookUDP::Header);
40 constexpr size_t PadDataSize =
41 sizeof(InputCommon::CemuhookUDP::Message<InputCommon::CemuhookUDP::Response::PadData>);
42
43 REQUIRE(touch_movement_path.size() > 0);
44 is_running = true;
45 handler = std::thread([touch_movement_path, this]() {
46 auto current_touch_position = touch_movement_path.begin();
47 while (is_running) {
48 boost::asio::ip::udp::endpoint sender_endpoint;
49 boost::system::error_code error_code;
50 auto received_size = socket.receive_from(boost::asio::buffer(receive_buffer),
51 sender_endpoint, 0, error_code);
52
53 if (received_size < HeaderSize) {
54 continue;
55 }
56
57 InputCommon::CemuhookUDP::Header header{};
58 std::memcpy(&header, receive_buffer.data(), HeaderSize);
59 switch (header.type) {
60 case InputCommon::CemuhookUDP::Type::PadData: {
61 InputCommon::CemuhookUDP::Response::PadData pad_data{};
62 pad_data.touch[0] = *current_touch_position;
63 const auto pad_message = InputCommon::CemuhookUDP::CreateMessage(
64 InputCommon::CemuhookUDP::SERVER_MAGIC, pad_data, 0);
65 std::memcpy(send_buffer.data(), &pad_message, PadDataSize);
66 socket.send_to(boost::asio::buffer(send_buffer, PadDataSize), sender_endpoint,
67 0, error_code);
68
69 bool can_advance =
70 std::next(current_touch_position) != touch_movement_path.end();
71 if (can_advance) {
72 std::advance(current_touch_position, 1);
73 }
74 break;
75 }
76 case InputCommon::CemuhookUDP::Type::PortInfo:
77 case InputCommon::CemuhookUDP::Type::Version:
78 default:
79 break;
80 }
81 }
82 });
83 }
84
85private:
86 boost::asio::io_service io_service;
87 boost::asio::ip::udp::socket socket;
88 std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> send_buffer;
89 std::array<u8, InputCommon::CemuhookUDP::MAX_PACKET_SIZE> receive_buffer;
90 bool is_running = false;
91 std::thread handler;
92};
93
94TEST_CASE("CalibrationConfigurationJob completed", "[input_common]") {
95 Common::Event complete_event;
96 FakeCemuhookServer server;
97 server.Run({{
98 .is_active = 1,
99 .x = 0,
100 .y = 0,
101 },
102 {
103 .is_active = 1,
104 .x = 200,
105 .y = 200,
106 }});
107
108 InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status{};
109 u16 min_x{};
110 u16 min_y{};
111 u16 max_x{};
112 u16 max_y{};
113 InputCommon::CemuhookUDP::CalibrationConfigurationJob job(
114 server.GetHost(), server.GetPort(),
115 [&status,
116 &complete_event](InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status status_) {
117 status = status_;
118 if (status ==
119 InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed) {
120 complete_event.Set();
121 }
122 },
123 [&](u16 min_x_, u16 min_y_, u16 max_x_, u16 max_y_) {
124 min_x = min_x_;
125 min_y = min_y_;
126 max_x = max_x_;
127 max_y = max_y_;
128 });
129
130 complete_event.WaitUntil(std::chrono::system_clock::now() + std::chrono::seconds(10));
131 REQUIRE(status == InputCommon::CemuhookUDP::CalibrationConfigurationJob::Status::Completed);
132 REQUIRE(min_x == 0);
133 REQUIRE(min_y == 0);
134 REQUIRE(max_x == 200);
135 REQUIRE(max_y == 200);
136}
diff --git a/src/video_core/command_classes/codecs/codec.cpp b/src/video_core/command_classes/codecs/codec.cpp
index 2a532b883..04d0f3a2f 100644
--- a/src/video_core/command_classes/codecs/codec.cpp
+++ b/src/video_core/command_classes/codecs/codec.cpp
@@ -32,7 +32,7 @@ constexpr std::array PREFERRED_GPU_DECODERS = {
32#ifdef _WIN32 32#ifdef _WIN32
33 AV_HWDEVICE_TYPE_D3D11VA, 33 AV_HWDEVICE_TYPE_D3D11VA,
34 AV_HWDEVICE_TYPE_DXVA2, 34 AV_HWDEVICE_TYPE_DXVA2,
35#elif defined(__linux__) 35#elif defined(__unix__)
36 AV_HWDEVICE_TYPE_VAAPI, 36 AV_HWDEVICE_TYPE_VAAPI,
37 AV_HWDEVICE_TYPE_VDPAU, 37 AV_HWDEVICE_TYPE_VDPAU,
38#endif 38#endif
@@ -130,6 +130,12 @@ bool Codec::CreateGpuAvDevice() {
130 } 130 }
131 if (config->methods & HW_CONFIG_METHOD && config->device_type == type) { 131 if (config->methods & HW_CONFIG_METHOD && config->device_type == type) {
132 av_codec_ctx->pix_fmt = config->pix_fmt; 132 av_codec_ctx->pix_fmt = config->pix_fmt;
133 if (config->methods & AV_CODEC_HW_CONFIG_METHOD_HW_FRAMES_CTX) {
134 // skip zero-copy decoders, we don't currently support them
135 LOG_DEBUG(Service_NVDRV, "Skipping decoder {} with unsupported capability {}.",
136 av_hwdevice_get_type_name(type), config->methods);
137 continue;
138 }
133 LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type)); 139 LOG_INFO(Service_NVDRV, "Using {} GPU decoder", av_hwdevice_get_type_name(type));
134 return true; 140 return true;
135 } 141 }
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.h b/src/video_core/renderer_opengl/gl_texture_cache.h
index 37d5e6a6b..dbf1df79c 100644
--- a/src/video_core/renderer_opengl/gl_texture_cache.h
+++ b/src/video_core/renderer_opengl/gl_texture_cache.h
@@ -92,7 +92,7 @@ public:
92 92
93 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 93 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
94 94
95 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled) { 95 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
96 UNIMPLEMENTED(); 96 UNIMPLEMENTED();
97 } 97 }
98 98
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp
index 28daacd82..f81c1b233 100644
--- a/src/video_core/renderer_opengl/renderer_opengl.cpp
+++ b/src/video_core/renderer_opengl/renderer_opengl.cpp
@@ -437,39 +437,29 @@ void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) {
437 437
438 glBindTextureUnit(0, fxaa_texture.handle); 438 glBindTextureUnit(0, fxaa_texture.handle);
439 } 439 }
440
441 // Set projection matrix
442 const std::array ortho_matrix = 440 const std::array ortho_matrix =
443 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height)); 441 MakeOrthographicMatrix(static_cast<float>(layout.width), static_cast<float>(layout.height));
444 442
445 GLuint fragment_handle; 443 const auto fragment_handle = [this]() {
446 const auto filter = Settings::values.scaling_filter.GetValue(); 444 switch (Settings::values.scaling_filter.GetValue()) {
447 switch (filter) { 445 case Settings::ScalingFilter::NearestNeighbor:
448 case Settings::ScalingFilter::NearestNeighbor: 446 case Settings::ScalingFilter::Bilinear:
449 fragment_handle = present_bilinear_fragment.handle; 447 return present_bilinear_fragment.handle;
450 break; 448 case Settings::ScalingFilter::Bicubic:
451 case Settings::ScalingFilter::Bilinear: 449 return present_bicubic_fragment.handle;
452 fragment_handle = present_bilinear_fragment.handle; 450 case Settings::ScalingFilter::Gaussian:
453 break; 451 return present_gaussian_fragment.handle;
454 case Settings::ScalingFilter::Bicubic: 452 case Settings::ScalingFilter::ScaleForce:
455 fragment_handle = present_bicubic_fragment.handle; 453 return present_scaleforce_fragment.handle;
456 break; 454 case Settings::ScalingFilter::Fsr:
457 case Settings::ScalingFilter::Gaussian: 455 LOG_WARNING(
458 fragment_handle = present_gaussian_fragment.handle; 456 Render_OpenGL,
459 break; 457 "FidelityFX Super Resolution is not supported in OpenGL, changing to ScaleForce");
460 case Settings::ScalingFilter::ScaleForce: 458 return present_scaleforce_fragment.handle;
461 fragment_handle = present_scaleforce_fragment.handle; 459 default:
462 break; 460 return present_bilinear_fragment.handle;
463 case Settings::ScalingFilter::Fsr: 461 }
464 LOG_WARNING( 462 }();
465 Render_OpenGL,
466 "FidelityFX FSR Super Sampling is not supported in OpenGL, changing to ScaleForce");
467 fragment_handle = present_scaleforce_fragment.handle;
468 break;
469 default:
470 fragment_handle = present_bilinear_fragment.handle;
471 break;
472 }
473 program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle); 463 program_manager.BindPresentPrograms(present_vertex.handle, fragment_handle);
474 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE, 464 glProgramUniformMatrix3x2fv(present_vertex.handle, ModelViewMatrixLocation, 1, GL_FALSE,
475 ortho_matrix.data()); 465 ortho_matrix.data());
diff --git a/src/video_core/renderer_vulkan/blit_image.cpp b/src/video_core/renderer_vulkan/blit_image.cpp
index 9a38b6b34..cd5995897 100644
--- a/src/video_core/renderer_vulkan/blit_image.cpp
+++ b/src/video_core/renderer_vulkan/blit_image.cpp
@@ -4,6 +4,7 @@
4 4
5#include <algorithm> 5#include <algorithm>
6 6
7#include "common/settings.h"
7#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h" 8#include "video_core/host_shaders/convert_abgr8_to_d24s8_frag_spv.h"
8#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h" 9#include "video_core/host_shaders/convert_d24s8_to_abgr8_frag_spv.h"
9#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h" 10#include "video_core/host_shaders/convert_depth_to_float_frag_spv.h"
@@ -335,6 +336,17 @@ void BindBlitState(vk::CommandBuffer cmdbuf, VkPipelineLayout layout, const Regi
335 cmdbuf.SetScissor(0, scissor); 336 cmdbuf.SetScissor(0, scissor);
336 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants); 337 cmdbuf.PushConstants(layout, VK_SHADER_STAGE_VERTEX_BIT, push_constants);
337} 338}
339
340VkExtent2D GetConversionExtent(const ImageView& src_image_view) {
341 const auto& resolution = Settings::values.resolution_info;
342 const bool is_rescaled = src_image_view.IsRescaled();
343 u32 width = src_image_view.size.width;
344 u32 height = src_image_view.size.height;
345 return VkExtent2D{
346 .width = is_rescaled ? resolution.ScaleUp(width) : width,
347 .height = is_rescaled ? resolution.ScaleUp(height) : height,
348 };
349}
338} // Anonymous namespace 350} // Anonymous namespace
339 351
340BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_, 352BlitImageHelper::BlitImageHelper(const Device& device_, VKScheduler& scheduler_,
@@ -425,61 +437,52 @@ void BlitImageHelper::BlitDepthStencil(const Framebuffer* dst_framebuffer,
425} 437}
426 438
427void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer, 439void BlitImageHelper::ConvertD32ToR32(const Framebuffer* dst_framebuffer,
428 const ImageView& src_image_view, u32 up_scale, 440 const ImageView& src_image_view) {
429 u32 down_shift) {
430 ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass()); 441 ConvertDepthToColorPipeline(convert_d32_to_r32_pipeline, dst_framebuffer->RenderPass());
431 Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 442 Convert(*convert_d32_to_r32_pipeline, dst_framebuffer, src_image_view);
432} 443}
433 444
434void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer, 445void BlitImageHelper::ConvertR32ToD32(const Framebuffer* dst_framebuffer,
435 const ImageView& src_image_view, u32 up_scale, 446 const ImageView& src_image_view) {
436 u32 down_shift) {
437 ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass()); 447 ConvertColorToDepthPipeline(convert_r32_to_d32_pipeline, dst_framebuffer->RenderPass());
438 Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 448 Convert(*convert_r32_to_d32_pipeline, dst_framebuffer, src_image_view);
439} 449}
440 450
441void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer, 451void BlitImageHelper::ConvertD16ToR16(const Framebuffer* dst_framebuffer,
442 const ImageView& src_image_view, u32 up_scale, 452 const ImageView& src_image_view) {
443 u32 down_shift) {
444 ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass()); 453 ConvertDepthToColorPipeline(convert_d16_to_r16_pipeline, dst_framebuffer->RenderPass());
445 Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 454 Convert(*convert_d16_to_r16_pipeline, dst_framebuffer, src_image_view);
446} 455}
447 456
448void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer, 457void BlitImageHelper::ConvertR16ToD16(const Framebuffer* dst_framebuffer,
449 const ImageView& src_image_view, u32 up_scale, 458 const ImageView& src_image_view) {
450 u32 down_shift) {
451 ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass()); 459 ConvertColorToDepthPipeline(convert_r16_to_d16_pipeline, dst_framebuffer->RenderPass());
452 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view, up_scale, down_shift); 460 Convert(*convert_r16_to_d16_pipeline, dst_framebuffer, src_image_view);
453} 461}
454 462
455void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, 463void BlitImageHelper::ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer,
456 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 464 const ImageView& src_image_view) {
457 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(), 465 ConvertPipelineDepthTargetEx(convert_abgr8_to_d24s8_pipeline, dst_framebuffer->RenderPass(),
458 convert_abgr8_to_d24s8_frag, true); 466 convert_abgr8_to_d24s8_frag);
459 ConvertColor(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view, up_scale, 467 Convert(*convert_abgr8_to_d24s8_pipeline, dst_framebuffer, src_image_view);
460 down_shift);
461} 468}
462 469
463void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, 470void BlitImageHelper::ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer,
464 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 471 ImageView& src_image_view) {
465 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(), 472 ConvertPipelineColorTargetEx(convert_d24s8_to_abgr8_pipeline, dst_framebuffer->RenderPass(),
466 convert_d24s8_to_abgr8_frag, false); 473 convert_d24s8_to_abgr8_frag);
467 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view, up_scale, 474 ConvertDepthStencil(*convert_d24s8_to_abgr8_pipeline, dst_framebuffer, src_image_view);
468 down_shift);
469} 475}
470 476
471void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 477void BlitImageHelper::Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
472 const ImageView& src_image_view, u32 up_scale, u32 down_shift) { 478 const ImageView& src_image_view) {
473 const VkPipelineLayout layout = *one_texture_pipeline_layout; 479 const VkPipelineLayout layout = *one_texture_pipeline_layout;
474 const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D); 480 const VkImageView src_view = src_image_view.Handle(Shader::TextureType::Color2D);
475 const VkSampler sampler = *nearest_sampler; 481 const VkSampler sampler = *nearest_sampler;
476 const VkExtent2D extent{ 482 const VkExtent2D extent = GetConversionExtent(src_image_view);
477 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), 483
478 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
479 };
480 scheduler.RequestRenderpass(dst_framebuffer); 484 scheduler.RequestRenderpass(dst_framebuffer);
481 scheduler.Record([pipeline, layout, sampler, src_view, extent, up_scale, down_shift, 485 scheduler.Record([pipeline, layout, sampler, src_view, extent, this](vk::CommandBuffer cmdbuf) {
482 this](vk::CommandBuffer cmdbuf) {
483 const VkOffset2D offset{ 486 const VkOffset2D offset{
484 .x = 0, 487 .x = 0,
485 .y = 0, 488 .y = 0,
@@ -563,18 +566,16 @@ void BlitImageHelper::ConvertColor(VkPipeline pipeline, const Framebuffer* dst_f
563} 566}
564 567
565void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 568void BlitImageHelper::ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
566 ImageView& src_image_view, u32 up_scale, u32 down_shift) { 569 ImageView& src_image_view) {
567 const VkPipelineLayout layout = *two_textures_pipeline_layout; 570 const VkPipelineLayout layout = *two_textures_pipeline_layout;
568 const VkImageView src_depth_view = src_image_view.DepthView(); 571 const VkImageView src_depth_view = src_image_view.DepthView();
569 const VkImageView src_stencil_view = src_image_view.StencilView(); 572 const VkImageView src_stencil_view = src_image_view.StencilView();
570 const VkSampler sampler = *nearest_sampler; 573 const VkSampler sampler = *nearest_sampler;
571 const VkExtent2D extent{ 574 const VkExtent2D extent = GetConversionExtent(src_image_view);
572 .width = std::max((src_image_view.size.width * up_scale) >> down_shift, 1U), 575
573 .height = std::max((src_image_view.size.height * up_scale) >> down_shift, 1U),
574 };
575 scheduler.RequestRenderpass(dst_framebuffer); 576 scheduler.RequestRenderpass(dst_framebuffer);
576 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent, up_scale, 577 scheduler.Record([pipeline, layout, sampler, src_depth_view, src_stencil_view, extent,
577 down_shift, this](vk::CommandBuffer cmdbuf) { 578 this](vk::CommandBuffer cmdbuf) {
578 const VkOffset2D offset{ 579 const VkOffset2D offset{
579 .x = 0, 580 .x = 0,
580 .y = 0, 581 .y = 0,
@@ -695,11 +696,14 @@ VkPipeline BlitImageHelper::FindOrEmplaceDepthStencilPipeline(const BlitImagePip
695 return *blit_depth_stencil_pipelines.back(); 696 return *blit_depth_stencil_pipelines.back();
696} 697}
697 698
698void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { 699void BlitImageHelper::ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass,
700 bool is_target_depth) {
699 if (pipeline) { 701 if (pipeline) {
700 return; 702 return;
701 } 703 }
702 const std::array stages = MakeStages(*full_screen_vert, *convert_depth_to_float_frag); 704 VkShaderModule frag_shader =
705 is_target_depth ? *convert_float_to_depth_frag : *convert_depth_to_float_frag;
706 const std::array stages = MakeStages(*full_screen_vert, frag_shader);
703 pipeline = device.GetLogical().CreateGraphicsPipeline({ 707 pipeline = device.GetLogical().CreateGraphicsPipeline({
704 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO, 708 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
705 .pNext = nullptr, 709 .pNext = nullptr,
@@ -712,8 +716,9 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
712 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO, 716 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
713 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO, 717 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
714 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO, 718 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
715 .pDepthStencilState = nullptr, 719 .pDepthStencilState = is_target_depth ? &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO : nullptr,
716 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO, 720 .pColorBlendState = is_target_depth ? &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO
721 : &PIPELINE_COLOR_BLEND_STATE_GENERIC_CREATE_INFO,
717 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO, 722 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
718 .layout = *one_texture_pipeline_layout, 723 .layout = *one_texture_pipeline_layout,
719 .renderPass = renderpass, 724 .renderPass = renderpass,
@@ -723,37 +728,17 @@ void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRend
723 }); 728 });
724} 729}
725 730
731void BlitImageHelper::ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
732 ConvertPipeline(pipeline, renderpass, false);
733}
734
726void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) { 735void BlitImageHelper::ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass) {
727 if (pipeline) { 736 ConvertPipeline(pipeline, renderpass, true);
728 return;
729 }
730 const std::array stages = MakeStages(*full_screen_vert, *convert_float_to_depth_frag);
731 pipeline = device.GetLogical().CreateGraphicsPipeline({
732 .sType = VK_STRUCTURE_TYPE_GRAPHICS_PIPELINE_CREATE_INFO,
733 .pNext = nullptr,
734 .flags = 0,
735 .stageCount = static_cast<u32>(stages.size()),
736 .pStages = stages.data(),
737 .pVertexInputState = &PIPELINE_VERTEX_INPUT_STATE_CREATE_INFO,
738 .pInputAssemblyState = &PIPELINE_INPUT_ASSEMBLY_STATE_CREATE_INFO,
739 .pTessellationState = nullptr,
740 .pViewportState = &PIPELINE_VIEWPORT_STATE_CREATE_INFO,
741 .pRasterizationState = &PIPELINE_RASTERIZATION_STATE_CREATE_INFO,
742 .pMultisampleState = &PIPELINE_MULTISAMPLE_STATE_CREATE_INFO,
743 .pDepthStencilState = &PIPELINE_DEPTH_STENCIL_STATE_CREATE_INFO,
744 .pColorBlendState = &PIPELINE_COLOR_BLEND_STATE_EMPTY_CREATE_INFO,
745 .pDynamicState = &PIPELINE_DYNAMIC_STATE_CREATE_INFO,
746 .layout = *one_texture_pipeline_layout,
747 .renderPass = renderpass,
748 .subpass = 0,
749 .basePipelineHandle = VK_NULL_HANDLE,
750 .basePipelineIndex = 0,
751 });
752} 737}
753 738
754void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 739void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
755 vk::ShaderModule& module, bool is_target_depth, 740 vk::ShaderModule& module, bool single_texture,
756 bool single_texture) { 741 bool is_target_depth) {
757 if (pipeline) { 742 if (pipeline) {
758 return; 743 return;
759 } 744 }
@@ -782,13 +767,13 @@ void BlitImageHelper::ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass ren
782} 767}
783 768
784void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 769void BlitImageHelper::ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
785 vk::ShaderModule& module, bool single_texture) { 770 vk::ShaderModule& module) {
786 ConvertPipelineEx(pipeline, renderpass, module, false, single_texture); 771 ConvertPipelineEx(pipeline, renderpass, module, false, false);
787} 772}
788 773
789void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 774void BlitImageHelper::ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
790 vk::ShaderModule& module, bool single_texture) { 775 vk::ShaderModule& module) {
791 ConvertPipelineEx(pipeline, renderpass, module, true, single_texture); 776 ConvertPipelineEx(pipeline, renderpass, module, true, true);
792} 777}
793 778
794} // namespace Vulkan 779} // namespace Vulkan
diff --git a/src/video_core/renderer_vulkan/blit_image.h b/src/video_core/renderer_vulkan/blit_image.h
index b1a717090..1d9f61a52 100644
--- a/src/video_core/renderer_vulkan/blit_image.h
+++ b/src/video_core/renderer_vulkan/blit_image.h
@@ -44,50 +44,46 @@ public:
44 const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter, 44 const Region2D& src_region, Tegra::Engines::Fermi2D::Filter filter,
45 Tegra::Engines::Fermi2D::Operation operation); 45 Tegra::Engines::Fermi2D::Operation operation);
46 46
47 void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 47 void ConvertD32ToR32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
48 u32 up_scale, u32 down_shift);
49 48
50 void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 49 void ConvertR32ToD32(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
51 u32 up_scale, u32 down_shift);
52 50
53 void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 51 void ConvertD16ToR16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
54 u32 up_scale, u32 down_shift);
55 52
56 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view, 53 void ConvertR16ToD16(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
57 u32 up_scale, u32 down_shift);
58 54
59 void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, 55 void ConvertABGR8ToD24S8(const Framebuffer* dst_framebuffer, const ImageView& src_image_view);
60 u32 up_scale, u32 down_shift);
61 56
62 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view, 57 void ConvertD24S8ToABGR8(const Framebuffer* dst_framebuffer, ImageView& src_image_view);
63 u32 up_scale, u32 down_shift);
64 58
65private: 59private:
66 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 60 void Convert(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
67 const ImageView& src_image_view, u32 up_scale, u32 down_shift); 61 const ImageView& src_image_view);
68 62
69 void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 63 void ConvertColor(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
70 ImageView& src_image_view, u32 up_scale, u32 down_shift); 64 ImageView& src_image_view, u32 up_scale, u32 down_shift);
71 65
72 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer, 66 void ConvertDepthStencil(VkPipeline pipeline, const Framebuffer* dst_framebuffer,
73 ImageView& src_image_view, u32 up_scale, u32 down_shift); 67 ImageView& src_image_view);
74 68
75 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key); 69 [[nodiscard]] VkPipeline FindOrEmplaceColorPipeline(const BlitImagePipelineKey& key);
76 70
77 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key); 71 [[nodiscard]] VkPipeline FindOrEmplaceDepthStencilPipeline(const BlitImagePipelineKey& key);
78 72
73 void ConvertPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass, bool is_target_depth);
74
79 void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 75 void ConvertDepthToColorPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
80 76
81 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass); 77 void ConvertColorToDepthPipeline(vk::Pipeline& pipeline, VkRenderPass renderpass);
82 78
83 void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 79 void ConvertPipelineEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
84 vk::ShaderModule& module, bool is_target_depth, bool single_texture); 80 vk::ShaderModule& module, bool single_texture, bool is_target_depth);
85 81
86 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 82 void ConvertPipelineColorTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
87 vk::ShaderModule& module, bool single_texture); 83 vk::ShaderModule& module);
88 84
89 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass, 85 void ConvertPipelineDepthTargetEx(vk::Pipeline& pipeline, VkRenderPass renderpass,
90 vk::ShaderModule& module, bool single_texture); 86 vk::ShaderModule& module);
91 87
92 const Device& device; 88 const Device& device;
93 VKScheduler& scheduler; 89 VKScheduler& scheduler;
diff --git a/src/video_core/renderer_vulkan/vk_blit_screen.cpp b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
index 1e447e621..c71a1f44d 100644
--- a/src/video_core/renderer_vulkan/vk_blit_screen.cpp
+++ b/src/video_core/renderer_vulkan/vk_blit_screen.cpp
@@ -391,28 +391,23 @@ VkSemaphore VKBlitScreen::Draw(const Tegra::FramebufferConfig& framebuffer,
391 .offset = {0, 0}, 391 .offset = {0, 0},
392 .extent = size, 392 .extent = size,
393 }; 393 };
394 const auto filter = Settings::values.scaling_filter.GetValue();
395 cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE); 394 cmdbuf.BeginRenderPass(renderpass_bi, VK_SUBPASS_CONTENTS_INLINE);
396 switch (filter) { 395 auto graphics_pipeline = [this]() {
397 case Settings::ScalingFilter::NearestNeighbor: 396 switch (Settings::values.scaling_filter.GetValue()) {
398 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); 397 case Settings::ScalingFilter::NearestNeighbor:
399 break; 398 case Settings::ScalingFilter::Bilinear:
400 case Settings::ScalingFilter::Bilinear: 399 return *bilinear_pipeline;
401 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline); 400 case Settings::ScalingFilter::Bicubic:
402 break; 401 return *bicubic_pipeline;
403 case Settings::ScalingFilter::Bicubic: 402 case Settings::ScalingFilter::Gaussian:
404 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bicubic_pipeline); 403 return *gaussian_pipeline;
405 break; 404 case Settings::ScalingFilter::ScaleForce:
406 case Settings::ScalingFilter::Gaussian: 405 return *scaleforce_pipeline;
407 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *gaussian_pipeline); 406 default:
408 break; 407 return *bilinear_pipeline;
409 case Settings::ScalingFilter::ScaleForce: 408 }
410 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *scaleforce_pipeline); 409 }();
411 break; 410 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, graphics_pipeline);
412 default:
413 cmdbuf.BindPipeline(VK_PIPELINE_BIND_POINT_GRAPHICS, *bilinear_pipeline);
414 break;
415 }
416 cmdbuf.SetViewport(0, viewport); 411 cmdbuf.SetViewport(0, viewport);
417 cmdbuf.SetScissor(0, scissor); 412 cmdbuf.SetScissor(0, scissor);
418 413
diff --git a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
index 616a7b457..d514b71d0 100644
--- a/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
+++ b/src/video_core/renderer_vulkan/vk_graphics_pipeline.cpp
@@ -605,7 +605,11 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
605 .flags = 0, 605 .flags = 0,
606 .topology = input_assembly_topology, 606 .topology = input_assembly_topology,
607 .primitiveRestartEnable = key.state.primitive_restart_enable != 0 && 607 .primitiveRestartEnable = key.state.primitive_restart_enable != 0 &&
608 SupportsPrimitiveRestart(input_assembly_topology), 608 ((input_assembly_topology != VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
609 device.IsTopologyListPrimitiveRestartSupported()) ||
610 SupportsPrimitiveRestart(input_assembly_topology) ||
611 (input_assembly_topology == VK_PRIMITIVE_TOPOLOGY_PATCH_LIST &&
612 device.IsPatchListPrimitiveRestartSupported())),
609 }; 613 };
610 const VkPipelineTessellationStateCreateInfo tessellation_ci{ 614 const VkPipelineTessellationStateCreateInfo tessellation_ci{
611 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO, 615 .sType = VK_STRUCTURE_TYPE_PIPELINE_TESSELLATION_STATE_CREATE_INFO,
@@ -613,7 +617,6 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
613 .flags = 0, 617 .flags = 0,
614 .patchControlPoints = key.state.patch_control_points_minus_one.Value() + 1, 618 .patchControlPoints = key.state.patch_control_points_minus_one.Value() + 1,
615 }; 619 };
616
617 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles; 620 std::array<VkViewportSwizzleNV, Maxwell::NumViewports> swizzles;
618 std::ranges::transform(key.state.viewport_swizzles, swizzles.begin(), UnpackViewportSwizzle); 621 std::ranges::transform(key.state.viewport_swizzles, swizzles.begin(), UnpackViewportSwizzle);
619 const VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{ 622 const VkPipelineViewportSwizzleStateCreateInfoNV swizzle_ci{
@@ -748,8 +751,8 @@ void GraphicsPipeline::MakePipeline(VkRenderPass render_pass) {
748 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO, 751 .sType = VK_STRUCTURE_TYPE_PIPELINE_COLOR_BLEND_STATE_CREATE_INFO,
749 .pNext = nullptr, 752 .pNext = nullptr,
750 .flags = 0, 753 .flags = 0,
751 .logicOpEnable = VK_FALSE, 754 .logicOpEnable = key.state.logic_op_enable != 0,
752 .logicOp = VK_LOGIC_OP_COPY, 755 .logicOp = static_cast<VkLogicOp>(key.state.logic_op.Value()),
753 .attachmentCount = static_cast<u32>(cb_attachments.size()), 756 .attachmentCount = static_cast<u32>(cb_attachments.size()),
754 .pAttachments = cb_attachments.data(), 757 .pAttachments = cb_attachments.data(),
755 .blendConstants = {}, 758 .blendConstants = {},
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.cpp b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
index 197cba8e3..1941170cb 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.cpp
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.cpp
@@ -1057,37 +1057,37 @@ void TextureCacheRuntime::BlitImage(Framebuffer* dst_framebuffer, ImageView& dst
1057 }); 1057 });
1058} 1058}
1059 1059
1060void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, 1060void TextureCacheRuntime::ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view) {
1061 bool rescaled) {
1062 const u32 up_scale = rescaled ? resolution.up_scale : 1;
1063 const u32 down_shift = rescaled ? resolution.down_shift : 0;
1064 switch (dst_view.format) { 1061 switch (dst_view.format) {
1065 case PixelFormat::R16_UNORM: 1062 case PixelFormat::R16_UNORM:
1066 if (src_view.format == PixelFormat::D16_UNORM) { 1063 if (src_view.format == PixelFormat::D16_UNORM) {
1067 return blit_image_helper.ConvertD16ToR16(dst, src_view, up_scale, down_shift); 1064 return blit_image_helper.ConvertD16ToR16(dst, src_view);
1068 } 1065 }
1069 break; 1066 break;
1070 case PixelFormat::A8B8G8R8_UNORM: 1067 case PixelFormat::A8B8G8R8_UNORM:
1071 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) { 1068 if (src_view.format == PixelFormat::S8_UINT_D24_UNORM) {
1072 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view, up_scale, down_shift); 1069 return blit_image_helper.ConvertD24S8ToABGR8(dst, src_view);
1073 } 1070 }
1074 break; 1071 break;
1075 case PixelFormat::R32_FLOAT: 1072 case PixelFormat::R32_FLOAT:
1076 if (src_view.format == PixelFormat::D32_FLOAT) { 1073 if (src_view.format == PixelFormat::D32_FLOAT) {
1077 return blit_image_helper.ConvertD32ToR32(dst, src_view, up_scale, down_shift); 1074 return blit_image_helper.ConvertD32ToR32(dst, src_view);
1078 } 1075 }
1079 break; 1076 break;
1080 case PixelFormat::D16_UNORM: 1077 case PixelFormat::D16_UNORM:
1081 if (src_view.format == PixelFormat::R16_UNORM) { 1078 if (src_view.format == PixelFormat::R16_UNORM) {
1082 return blit_image_helper.ConvertR16ToD16(dst, src_view, up_scale, down_shift); 1079 return blit_image_helper.ConvertR16ToD16(dst, src_view);
1083 } 1080 }
1084 break; 1081 break;
1085 case PixelFormat::S8_UINT_D24_UNORM: 1082 case PixelFormat::S8_UINT_D24_UNORM:
1086 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view, up_scale, down_shift); 1083 if (src_view.format == PixelFormat::A8B8G8R8_UNORM ||
1084 src_view.format == PixelFormat::B8G8R8A8_UNORM) {
1085 return blit_image_helper.ConvertABGR8ToD24S8(dst, src_view);
1086 }
1087 break; 1087 break;
1088 case PixelFormat::D32_FLOAT: 1088 case PixelFormat::D32_FLOAT:
1089 if (src_view.format == PixelFormat::R32_FLOAT) { 1089 if (src_view.format == PixelFormat::R32_FLOAT) {
1090 return blit_image_helper.ConvertR32ToD32(dst, src_view, up_scale, down_shift); 1090 return blit_image_helper.ConvertR32ToD32(dst, src_view);
1091 } 1091 }
1092 break; 1092 break;
1093 default: 1093 default:
@@ -1329,6 +1329,10 @@ void Image::DownloadMemory(const StagingBufferRef& map, std::span<const BufferIm
1329 } 1329 }
1330} 1330}
1331 1331
1332bool Image::IsRescaled() const noexcept {
1333 return True(flags & ImageFlagBits::Rescaled);
1334}
1335
1332bool Image::ScaleUp(bool ignore) { 1336bool Image::ScaleUp(bool ignore) {
1333 if (True(flags & ImageFlagBits::Rescaled)) { 1337 if (True(flags & ImageFlagBits::Rescaled)) {
1334 return false; 1338 return false;
@@ -1469,7 +1473,8 @@ bool Image::BlitScaleHelper(bool scale_up) {
1469ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info, 1473ImageView::ImageView(TextureCacheRuntime& runtime, const VideoCommon::ImageViewInfo& info,
1470 ImageId image_id_, Image& image) 1474 ImageId image_id_, Image& image)
1471 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device}, 1475 : VideoCommon::ImageViewBase{info, image.info, image_id_}, device{&runtime.device},
1472 image_handle{image.Handle()}, samples{ConvertSampleCount(image.info.num_samples)} { 1476 src_image{&image}, image_handle{image.Handle()},
1477 samples(ConvertSampleCount(image.info.num_samples)) {
1473 using Shader::TextureType; 1478 using Shader::TextureType;
1474 1479
1475 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info); 1480 const VkImageAspectFlags aspect_mask = ImageViewAspectMask(info);
@@ -1607,6 +1612,13 @@ VkImageView ImageView::StorageView(Shader::TextureType texture_type,
1607 return *view; 1612 return *view;
1608} 1613}
1609 1614
1615bool ImageView::IsRescaled() const noexcept {
1616 if (!src_image) {
1617 return false;
1618 }
1619 return src_image->IsRescaled();
1620}
1621
1610vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) { 1622vk::ImageView ImageView::MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask) {
1611 return device->GetLogical().CreateImageView({ 1623 return device->GetLogical().CreateImageView({
1612 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO, 1624 .sType = VK_STRUCTURE_TYPE_IMAGE_VIEW_CREATE_INFO,
diff --git a/src/video_core/renderer_vulkan/vk_texture_cache.h b/src/video_core/renderer_vulkan/vk_texture_cache.h
index 753e3e8a1..c592f2666 100644
--- a/src/video_core/renderer_vulkan/vk_texture_cache.h
+++ b/src/video_core/renderer_vulkan/vk_texture_cache.h
@@ -65,7 +65,7 @@ public:
65 65
66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies); 66 void ReinterpretImage(Image& dst, Image& src, std::span<const VideoCommon::ImageCopy> copies);
67 67
68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view, bool rescaled); 68 void ConvertImage(Framebuffer* dst, ImageView& dst_view, ImageView& src_view);
69 69
70 bool CanAccelerateImageUpload(Image&) const noexcept { 70 bool CanAccelerateImageUpload(Image&) const noexcept {
71 return false; 71 return false;
@@ -139,6 +139,8 @@ public:
139 return std::exchange(initialized, true); 139 return std::exchange(initialized, true);
140 } 140 }
141 141
142 bool IsRescaled() const noexcept;
143
142 bool ScaleUp(bool ignore = false); 144 bool ScaleUp(bool ignore = false);
143 145
144 bool ScaleDown(bool ignore = false); 146 bool ScaleDown(bool ignore = false);
@@ -189,6 +191,8 @@ public:
189 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type, 191 [[nodiscard]] VkImageView StorageView(Shader::TextureType texture_type,
190 Shader::ImageFormat image_format); 192 Shader::ImageFormat image_format);
191 193
194 [[nodiscard]] bool IsRescaled() const noexcept;
195
192 [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept { 196 [[nodiscard]] VkImageView Handle(Shader::TextureType texture_type) const noexcept {
193 return *image_views[static_cast<size_t>(texture_type)]; 197 return *image_views[static_cast<size_t>(texture_type)];
194 } 198 }
@@ -222,6 +226,8 @@ private:
222 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask); 226 [[nodiscard]] vk::ImageView MakeView(VkFormat vk_format, VkImageAspectFlags aspect_mask);
223 227
224 const Device* device = nullptr; 228 const Device* device = nullptr;
229 const Image* src_image{};
230
225 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views; 231 std::array<vk::ImageView, Shader::NUM_TEXTURE_TYPES> image_views;
226 std::unique_ptr<StorageViews> storage_views; 232 std::unique_ptr<StorageViews> storage_views;
227 vk::ImageView depth_view; 233 vk::ImageView depth_view;
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h
index 5aaeb16ca..2e19fced2 100644
--- a/src/video_core/texture_cache/texture_cache.h
+++ b/src/video_core/texture_cache/texture_cache.h
@@ -1855,9 +1855,20 @@ void TextureCache<P>::CopyImage(ImageId dst_id, ImageId src_id, std::vector<Imag
1855 .height = std::min(dst_view.size.height, src_view.size.height), 1855 .height = std::min(dst_view.size.height, src_view.size.height),
1856 .depth = std::min(dst_view.size.depth, src_view.size.depth), 1856 .depth = std::min(dst_view.size.depth, src_view.size.depth),
1857 }; 1857 };
1858 UNIMPLEMENTED_IF(copy.extent != expected_size); 1858 const Extent3D scaled_extent = [is_rescaled, expected_size]() {
1859 if (!is_rescaled) {
1860 return expected_size;
1861 }
1862 const auto& resolution = Settings::values.resolution_info;
1863 return Extent3D{
1864 .width = resolution.ScaleUp(expected_size.width),
1865 .height = resolution.ScaleUp(expected_size.height),
1866 .depth = expected_size.depth,
1867 };
1868 }();
1869 UNIMPLEMENTED_IF(copy.extent != scaled_extent);
1859 1870
1860 runtime.ConvertImage(dst_framebuffer, dst_view, src_view, is_rescaled); 1871 runtime.ConvertImage(dst_framebuffer, dst_view, src_view);
1861 } 1872 }
1862} 1873}
1863 1874
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp
index 7bf5b6578..9862b815b 100644
--- a/src/video_core/vulkan_common/vulkan_device.cpp
+++ b/src/video_core/vulkan_common/vulkan_device.cpp
@@ -271,7 +271,7 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
271 .tessellationShader = true, 271 .tessellationShader = true,
272 .sampleRateShading = true, 272 .sampleRateShading = true,
273 .dualSrcBlend = true, 273 .dualSrcBlend = true,
274 .logicOp = false, 274 .logicOp = true,
275 .multiDrawIndirect = false, 275 .multiDrawIndirect = false,
276 .drawIndirectFirstInstance = false, 276 .drawIndirectFirstInstance = false,
277 .depthClamp = true, 277 .depthClamp = true,
@@ -433,6 +433,19 @@ Device::Device(VkInstance instance_, vk::PhysicalDevice physical_, VkSurfaceKHR
433 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes"); 433 LOG_INFO(Render_Vulkan, "Device doesn't support uint8 indexes");
434 } 434 }
435 435
436 VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT primitive_topology_list_restart;
437 if (is_topology_list_restart_supported || is_patch_list_restart_supported) {
438 primitive_topology_list_restart = {
439 .sType = VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT,
440 .pNext = nullptr,
441 .primitiveTopologyListRestart = is_topology_list_restart_supported,
442 .primitiveTopologyPatchListRestart = is_patch_list_restart_supported,
443 };
444 SetNext(next, primitive_topology_list_restart);
445 } else {
446 LOG_INFO(Render_Vulkan, "Device doesn't support list topology primitive restart");
447 }
448
436 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback; 449 VkPhysicalDeviceTransformFeedbackFeaturesEXT transform_feedback;
437 if (ext_transform_feedback) { 450 if (ext_transform_feedback) {
438 transform_feedback = { 451 transform_feedback = {
@@ -891,6 +904,7 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
891 bool has_ext_provoking_vertex{}; 904 bool has_ext_provoking_vertex{};
892 bool has_ext_vertex_input_dynamic_state{}; 905 bool has_ext_vertex_input_dynamic_state{};
893 bool has_ext_line_rasterization{}; 906 bool has_ext_line_rasterization{};
907 bool has_ext_primitive_topology_list_restart{};
894 for (const std::string& extension : supported_extensions) { 908 for (const std::string& extension : supported_extensions) {
895 const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name, 909 const auto test = [&](std::optional<std::reference_wrapper<bool>> status, const char* name,
896 bool push) { 910 bool push) {
@@ -915,6 +929,8 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
915 test(has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false); 929 test(has_khr_shader_float16_int8, VK_KHR_SHADER_FLOAT16_INT8_EXTENSION_NAME, false);
916 test(ext_depth_range_unrestricted, VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true); 930 test(ext_depth_range_unrestricted, VK_EXT_DEPTH_RANGE_UNRESTRICTED_EXTENSION_NAME, true);
917 test(ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true); 931 test(ext_index_type_uint8, VK_EXT_INDEX_TYPE_UINT8_EXTENSION_NAME, true);
932 test(has_ext_primitive_topology_list_restart,
933 VK_EXT_PRIMITIVE_TOPOLOGY_LIST_RESTART_EXTENSION_NAME, true);
918 test(ext_sampler_filter_minmax, VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, true); 934 test(ext_sampler_filter_minmax, VK_EXT_SAMPLER_FILTER_MINMAX_EXTENSION_NAME, true);
919 test(ext_shader_viewport_index_layer, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME, 935 test(ext_shader_viewport_index_layer, VK_EXT_SHADER_VIEWPORT_INDEX_LAYER_EXTENSION_NAME,
920 true); 936 true);
@@ -1113,6 +1129,19 @@ std::vector<const char*> Device::LoadExtensions(bool requires_surface) {
1113 khr_pipeline_executable_properties = true; 1129 khr_pipeline_executable_properties = true;
1114 } 1130 }
1115 } 1131 }
1132 if (has_ext_primitive_topology_list_restart) {
1133 VkPhysicalDevicePrimitiveTopologyListRestartFeaturesEXT primitive_topology_list_restart{};
1134 primitive_topology_list_restart.sType =
1135 VK_STRUCTURE_TYPE_PHYSICAL_DEVICE_PRIMITIVE_TOPOLOGY_LIST_RESTART_FEATURES_EXT;
1136 primitive_topology_list_restart.pNext = nullptr;
1137 features.pNext = &primitive_topology_list_restart;
1138 physical.GetFeatures2KHR(features);
1139
1140 is_topology_list_restart_supported =
1141 primitive_topology_list_restart.primitiveTopologyListRestart;
1142 is_patch_list_restart_supported =
1143 primitive_topology_list_restart.primitiveTopologyPatchListRestart;
1144 }
1116 if (has_khr_image_format_list && has_khr_swapchain_mutable_format) { 1145 if (has_khr_image_format_list && has_khr_swapchain_mutable_format) {
1117 extensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME); 1146 extensions.push_back(VK_KHR_IMAGE_FORMAT_LIST_EXTENSION_NAME);
1118 extensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME); 1147 extensions.push_back(VK_KHR_SWAPCHAIN_MUTABLE_FORMAT_EXTENSION_NAME);
diff --git a/src/video_core/vulkan_common/vulkan_device.h b/src/video_core/vulkan_common/vulkan_device.h
index 10653ac6b..4c9d86aad 100644
--- a/src/video_core/vulkan_common/vulkan_device.h
+++ b/src/video_core/vulkan_common/vulkan_device.h
@@ -238,6 +238,16 @@ public:
238 return khr_workgroup_memory_explicit_layout; 238 return khr_workgroup_memory_explicit_layout;
239 } 239 }
240 240
241 /// Returns true if the device supports VK_EXT_primitive_topology_list_restart.
242 bool IsTopologyListPrimitiveRestartSupported() const {
243 return is_topology_list_restart_supported;
244 }
245
246 /// Returns true if the device supports VK_EXT_primitive_topology_list_restart.
247 bool IsPatchListPrimitiveRestartSupported() const {
248 return is_patch_list_restart_supported;
249 }
250
241 /// Returns true if the device supports VK_EXT_index_type_uint8. 251 /// Returns true if the device supports VK_EXT_index_type_uint8.
242 bool IsExtIndexTypeUint8Supported() const { 252 bool IsExtIndexTypeUint8Supported() const {
243 return ext_index_type_uint8; 253 return ext_index_type_uint8;
@@ -401,6 +411,9 @@ private:
401 bool is_shader_int16_supported{}; ///< Support for int16. 411 bool is_shader_int16_supported{}; ///< Support for int16.
402 bool is_shader_storage_image_multisample{}; ///< Support for image operations on MSAA images. 412 bool is_shader_storage_image_multisample{}; ///< Support for image operations on MSAA images.
403 bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil. 413 bool is_blit_depth_stencil_supported{}; ///< Support for blitting from and to depth stencil.
414 bool is_topology_list_restart_supported{}; ///< Support for primitive restart with list
415 ///< topologies.
416 bool is_patch_list_restart_supported{}; ///< Support for primitive restart with list patch.
404 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle. 417 bool nv_viewport_swizzle{}; ///< Support for VK_NV_viewport_swizzle.
405 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2. 418 bool nv_viewport_array2{}; ///< Support for VK_NV_viewport_array2.
406 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough. 419 bool nv_geometry_shader_passthrough{}; ///< Support for VK_NV_geometry_shader_passthrough.
diff --git a/src/yuzu/applets/qt_controller.cpp b/src/yuzu/applets/qt_controller.cpp
index c5685db2e..c6222b571 100644
--- a/src/yuzu/applets/qt_controller.cpp
+++ b/src/yuzu/applets/qt_controller.cpp
@@ -12,7 +12,6 @@
12#include "core/hid/emulated_controller.h" 12#include "core/hid/emulated_controller.h"
13#include "core/hid/hid_core.h" 13#include "core/hid/hid_core.h"
14#include "core/hid/hid_types.h" 14#include "core/hid/hid_types.h"
15#include "core/hle/lock.h"
16#include "core/hle/service/hid/controllers/npad.h" 15#include "core/hle/service/hid/controllers/npad.h"
17#include "core/hle/service/hid/hid.h" 16#include "core/hle/service/hid/hid.h"
18#include "core/hle/service/sm/sm.h" 17#include "core/hle/service/sm/sm.h"
@@ -664,7 +663,5 @@ void QtControllerSelector::ReconfigureControllers(
664} 663}
665 664
666void QtControllerSelector::MainWindowReconfigureFinished() { 665void QtControllerSelector::MainWindowReconfigureFinished() {
667 // Acquire the HLE mutex
668 std::lock_guard lock(HLE::g_hle_lock);
669 callback(); 666 callback();
670} 667}
diff --git a/src/yuzu/applets/qt_error.cpp b/src/yuzu/applets/qt_error.cpp
index 45cf64603..879e73660 100644
--- a/src/yuzu/applets/qt_error.cpp
+++ b/src/yuzu/applets/qt_error.cpp
@@ -3,7 +3,6 @@
3// Refer to the license.txt file included. 3// Refer to the license.txt file included.
4 4
5#include <QDateTime> 5#include <QDateTime>
6#include "core/hle/lock.h"
7#include "yuzu/applets/qt_error.h" 6#include "yuzu/applets/qt_error.h"
8#include "yuzu/main.h" 7#include "yuzu/main.h"
9 8
@@ -57,7 +56,5 @@ void QtErrorDisplay::ShowCustomErrorText(ResultCode error, std::string dialog_te
57} 56}
58 57
59void QtErrorDisplay::MainWindowFinishedError() { 58void QtErrorDisplay::MainWindowFinishedError() {
60 // Acquire the HLE mutex
61 std::lock_guard lock{HLE::g_hle_lock};
62 callback(); 59 callback();
63} 60}
diff --git a/src/yuzu/applets/qt_profile_select.cpp b/src/yuzu/applets/qt_profile_select.cpp
index 7b19f1f8d..5b32da923 100644
--- a/src/yuzu/applets/qt_profile_select.cpp
+++ b/src/yuzu/applets/qt_profile_select.cpp
@@ -14,7 +14,6 @@
14#include "common/fs/path_util.h" 14#include "common/fs/path_util.h"
15#include "common/string_util.h" 15#include "common/string_util.h"
16#include "core/constants.h" 16#include "core/constants.h"
17#include "core/hle/lock.h"
18#include "yuzu/applets/qt_profile_select.h" 17#include "yuzu/applets/qt_profile_select.h"
19#include "yuzu/main.h" 18#include "yuzu/main.h"
20#include "yuzu/util/controller_navigation.h" 19#include "yuzu/util/controller_navigation.h"
@@ -170,7 +169,5 @@ void QtProfileSelector::SelectProfile(
170} 169}
171 170
172void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) { 171void QtProfileSelector::MainWindowFinishedSelection(std::optional<Common::UUID> uuid) {
173 // Acquire the HLE mutex
174 std::lock_guard lock{HLE::g_hle_lock};
175 callback(uuid); 172 callback(uuid);
176} 173}
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp
index b7bb43348..a7271e075 100644
--- a/src/yuzu/main.cpp
+++ b/src/yuzu/main.cpp
@@ -2546,39 +2546,30 @@ void GMainWindow::ToggleFullscreen() {
2546} 2546}
2547 2547
2548void GMainWindow::ShowFullscreen() { 2548void GMainWindow::ShowFullscreen() {
2549 const auto show_fullscreen = [](QWidget* window) {
2550 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
2551 window->showFullScreen();
2552 return;
2553 }
2554 window->hide();
2555 window->setWindowFlags(window->windowFlags() | Qt::FramelessWindowHint);
2556 const auto screen_geometry = QApplication::desktop()->screenGeometry(window);
2557 window->setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2558 screen_geometry.height() + 1);
2559 window->raise();
2560 window->showNormal();
2561 };
2562
2549 if (ui->action_Single_Window_Mode->isChecked()) { 2563 if (ui->action_Single_Window_Mode->isChecked()) {
2550 UISettings::values.geometry = saveGeometry(); 2564 UISettings::values.geometry = saveGeometry();
2551 2565
2552 ui->menubar->hide(); 2566 ui->menubar->hide();
2553 statusBar()->hide(); 2567 statusBar()->hide();
2554 2568
2555 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { 2569 show_fullscreen(this);
2556 showFullScreen();
2557 return;
2558 }
2559
2560 hide();
2561 setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2562 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2563 setGeometry(screen_geometry.x(), screen_geometry.y(), screen_geometry.width(),
2564 screen_geometry.height() + 1);
2565 raise();
2566 showNormal();
2567 } else { 2570 } else {
2568 UISettings::values.renderwindow_geometry = render_window->saveGeometry(); 2571 UISettings::values.renderwindow_geometry = render_window->saveGeometry();
2569 2572 show_fullscreen(render_window);
2570 if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) {
2571 render_window->showFullScreen();
2572 return;
2573 }
2574
2575 render_window->hide();
2576 render_window->setWindowFlags(windowFlags() | Qt::FramelessWindowHint);
2577 const auto screen_geometry = QApplication::desktop()->screenGeometry(this);
2578 render_window->setGeometry(screen_geometry.x(), screen_geometry.y(),
2579 screen_geometry.width(), screen_geometry.height() + 1);
2580 render_window->raise();
2581 render_window->showNormal();
2582 } 2573 }
2583} 2574}
2584 2575