diff options
Diffstat (limited to 'src')
70 files changed, 626 insertions, 185 deletions
diff --git a/src/audio_core/renderer/system.cpp b/src/audio_core/renderer/system.cpp index ad869facb..53b258c4f 100644 --- a/src/audio_core/renderer/system.cpp +++ b/src/audio_core/renderer/system.cpp | |||
| @@ -436,10 +436,7 @@ void System::Stop() { | |||
| 436 | } | 436 | } |
| 437 | 437 | ||
| 438 | if (execution_mode == ExecutionMode::Auto) { | 438 | if (execution_mode == ExecutionMode::Auto) { |
| 439 | // Should wait for the system to terminate here, but core timing (should have) already | 439 | terminate_event.Wait(); |
| 440 | // stopped, so this isn't needed. Find a way to make this definite. | ||
| 441 | |||
| 442 | // terminate_event.Wait(); | ||
| 443 | } | 440 | } |
| 444 | } | 441 | } |
| 445 | 442 | ||
diff --git a/src/common/address_space.inc b/src/common/address_space.inc index 2195dabd5..c97dc8651 100644 --- a/src/common/address_space.inc +++ b/src/common/address_space.inc | |||
| @@ -72,7 +72,7 @@ MAP_MEMBER(void)::MapLocked(VaType virt, PaType phys, VaType size, ExtraBlockInf | |||
| 72 | } | 72 | } |
| 73 | }()}; | 73 | }()}; |
| 74 | 74 | ||
| 75 | if (block_end_predecessor->virt >= virt) { | 75 | if (block_end_predecessor != blocks.begin() && block_end_predecessor->virt >= virt) { |
| 76 | // If this block's start would be overlapped by the map then reuse it as a tail | 76 | // If this block's start would be overlapped by the map then reuse it as a tail |
| 77 | // block | 77 | // block |
| 78 | block_end_predecessor->virt = virt_end; | 78 | block_end_predecessor->virt = virt_end; |
diff --git a/src/common/input.h b/src/common/input.h index 51b277c1f..66fb15f0a 100644 --- a/src/common/input.h +++ b/src/common/input.h | |||
| @@ -111,6 +111,8 @@ struct AnalogProperties { | |||
| 111 | float offset{}; | 111 | float offset{}; |
| 112 | // Invert direction of the sensor data | 112 | // Invert direction of the sensor data |
| 113 | bool inverted{}; | 113 | bool inverted{}; |
| 114 | // Invert the state if it's converted to a button | ||
| 115 | bool inverted_button{}; | ||
| 114 | // Press once to activate, press again to release | 116 | // Press once to activate, press again to release |
| 115 | bool toggle{}; | 117 | bool toggle{}; |
| 116 | }; | 118 | }; |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 77ff21128..174460c5e 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -45,6 +45,7 @@ void LogSettings() { | |||
| 45 | log_setting("System_LanguageIndex", values.language_index.GetValue()); | 45 | log_setting("System_LanguageIndex", values.language_index.GetValue()); |
| 46 | log_setting("System_RegionIndex", values.region_index.GetValue()); | 46 | log_setting("System_RegionIndex", values.region_index.GetValue()); |
| 47 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); | 47 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); |
| 48 | log_setting("System_UnsafeMemoryLayout", values.use_unsafe_extended_memory_layout.GetValue()); | ||
| 48 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); | 49 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); |
| 49 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); | 50 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); |
| 50 | log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); | 51 | log_setting("Renderer_UseResolutionScaling", values.resolution_setup.GetValue()); |
| @@ -191,7 +192,7 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 191 | 192 | ||
| 192 | // Core | 193 | // Core |
| 193 | values.use_multi_core.SetGlobal(true); | 194 | values.use_multi_core.SetGlobal(true); |
| 194 | values.use_extended_memory_layout.SetGlobal(true); | 195 | values.use_unsafe_extended_memory_layout.SetGlobal(true); |
| 195 | 196 | ||
| 196 | // CPU | 197 | // CPU |
| 197 | values.cpu_accuracy.SetGlobal(true); | 198 | values.cpu_accuracy.SetGlobal(true); |
| @@ -226,7 +227,6 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 226 | values.shader_backend.SetGlobal(true); | 227 | values.shader_backend.SetGlobal(true); |
| 227 | values.use_asynchronous_shaders.SetGlobal(true); | 228 | values.use_asynchronous_shaders.SetGlobal(true); |
| 228 | values.use_fast_gpu_time.SetGlobal(true); | 229 | values.use_fast_gpu_time.SetGlobal(true); |
| 229 | values.use_pessimistic_flushes.SetGlobal(true); | ||
| 230 | values.use_vulkan_driver_pipeline_cache.SetGlobal(true); | 230 | values.use_vulkan_driver_pipeline_cache.SetGlobal(true); |
| 231 | values.bg_red.SetGlobal(true); | 231 | values.bg_red.SetGlobal(true); |
| 232 | values.bg_green.SetGlobal(true); | 232 | values.bg_green.SetGlobal(true); |
diff --git a/src/common/settings.h b/src/common/settings.h index 5379d0dd5..55200c36f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -388,7 +388,8 @@ struct Values { | |||
| 388 | 388 | ||
| 389 | // Core | 389 | // Core |
| 390 | SwitchableSetting<bool> use_multi_core{true, "use_multi_core"}; | 390 | SwitchableSetting<bool> use_multi_core{true, "use_multi_core"}; |
| 391 | SwitchableSetting<bool> use_extended_memory_layout{false, "use_extended_memory_layout"}; | 391 | SwitchableSetting<bool> use_unsafe_extended_memory_layout{false, |
| 392 | "use_unsafe_extended_memory_layout"}; | ||
| 392 | 393 | ||
| 393 | // Cpu | 394 | // Cpu |
| 394 | SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, | 395 | SwitchableSetting<CPUAccuracy, true> cpu_accuracy{CPUAccuracy::Auto, CPUAccuracy::Auto, |
| @@ -460,7 +461,6 @@ struct Values { | |||
| 460 | ShaderBackend::SPIRV, "shader_backend"}; | 461 | ShaderBackend::SPIRV, "shader_backend"}; |
| 461 | SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | 462 | SwitchableSetting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; |
| 462 | SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | 463 | SwitchableSetting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; |
| 463 | SwitchableSetting<bool> use_pessimistic_flushes{false, "use_pessimistic_flushes"}; | ||
| 464 | SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, | 464 | SwitchableSetting<bool> use_vulkan_driver_pipeline_cache{true, |
| 465 | "use_vulkan_driver_pipeline_cache"}; | 465 | "use_vulkan_driver_pipeline_cache"}; |
| 466 | 466 | ||
diff --git a/src/common/vector_math.h b/src/common/vector_math.h index 0e2095c45..b4885835d 100644 --- a/src/common/vector_math.h +++ b/src/common/vector_math.h | |||
| @@ -259,6 +259,20 @@ public: | |||
| 259 | return *this; | 259 | return *this; |
| 260 | } | 260 | } |
| 261 | 261 | ||
| 262 | void RotateFromOrigin(float roll, float pitch, float yaw) { | ||
| 263 | float temp = y; | ||
| 264 | y = std::cos(roll) * y - std::sin(roll) * z; | ||
| 265 | z = std::sin(roll) * temp + std::cos(roll) * z; | ||
| 266 | |||
| 267 | temp = x; | ||
| 268 | x = std::cos(pitch) * x + std::sin(pitch) * z; | ||
| 269 | z = -std::sin(pitch) * temp + std::cos(pitch) * z; | ||
| 270 | |||
| 271 | temp = x; | ||
| 272 | x = std::cos(yaw) * x - std::sin(yaw) * y; | ||
| 273 | y = std::sin(yaw) * temp + std::cos(yaw) * y; | ||
| 274 | } | ||
| 275 | |||
| 262 | [[nodiscard]] constexpr T Length2() const { | 276 | [[nodiscard]] constexpr T Length2() const { |
| 263 | return x * x + y * y + z * z; | 277 | return x * x + y * y + z * z; |
| 264 | } | 278 | } |
diff --git a/src/core/core.cpp b/src/core/core.cpp index caa6a77be..06fba4ce5 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -137,7 +137,7 @@ struct System::Impl { | |||
| 137 | device_memory = std::make_unique<Core::DeviceMemory>(); | 137 | device_memory = std::make_unique<Core::DeviceMemory>(); |
| 138 | 138 | ||
| 139 | is_multicore = Settings::values.use_multi_core.GetValue(); | 139 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 140 | extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue(); | 140 | extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue(); |
| 141 | 141 | ||
| 142 | core_timing.SetMulticore(is_multicore); | 142 | core_timing.SetMulticore(is_multicore); |
| 143 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); | 143 | core_timing.Initialize([&system]() { system.RegisterHostThread(); }); |
| @@ -169,7 +169,7 @@ struct System::Impl { | |||
| 169 | void ReinitializeIfNecessary(System& system) { | 169 | void ReinitializeIfNecessary(System& system) { |
| 170 | const bool must_reinitialize = | 170 | const bool must_reinitialize = |
| 171 | is_multicore != Settings::values.use_multi_core.GetValue() || | 171 | is_multicore != Settings::values.use_multi_core.GetValue() || |
| 172 | extended_memory_layout != Settings::values.use_extended_memory_layout.GetValue(); | 172 | extended_memory_layout != Settings::values.use_unsafe_extended_memory_layout.GetValue(); |
| 173 | 173 | ||
| 174 | if (!must_reinitialize) { | 174 | if (!must_reinitialize) { |
| 175 | return; | 175 | return; |
| @@ -178,7 +178,7 @@ struct System::Impl { | |||
| 178 | LOG_DEBUG(Kernel, "Re-initializing"); | 178 | LOG_DEBUG(Kernel, "Re-initializing"); |
| 179 | 179 | ||
| 180 | is_multicore = Settings::values.use_multi_core.GetValue(); | 180 | is_multicore = Settings::values.use_multi_core.GetValue(); |
| 181 | extended_memory_layout = Settings::values.use_extended_memory_layout.GetValue(); | 181 | extended_memory_layout = Settings::values.use_unsafe_extended_memory_layout.GetValue(); |
| 182 | 182 | ||
| 183 | Initialize(system); | 183 | Initialize(system); |
| 184 | } | 184 | } |
| @@ -293,6 +293,7 @@ struct System::Impl { | |||
| 293 | ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", | 293 | ASSERT(Kernel::KProcess::Initialize(main_process, system, "main", |
| 294 | Kernel::KProcess::ProcessType::Userland, resource_limit) | 294 | Kernel::KProcess::ProcessType::Userland, resource_limit) |
| 295 | .IsSuccess()); | 295 | .IsSuccess()); |
| 296 | Kernel::KProcess::Register(system.Kernel(), main_process); | ||
| 296 | kernel.MakeApplicationProcess(main_process); | 297 | kernel.MakeApplicationProcess(main_process); |
| 297 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); | 298 | const auto [load_result, load_parameters] = app_loader->Load(*main_process, system); |
| 298 | if (load_result != Loader::ResultStatus::Success) { | 299 | if (load_result != Loader::ResultStatus::Success) { |
diff --git a/src/core/hid/emulated_controller.cpp b/src/core/hid/emulated_controller.cpp index a70f8807c..ecab85893 100644 --- a/src/core/hid/emulated_controller.cpp +++ b/src/core/hid/emulated_controller.cpp | |||
| @@ -376,6 +376,7 @@ void EmulatedController::ReloadInput() { | |||
| 376 | motion.accel = emulated_motion.GetAcceleration(); | 376 | motion.accel = emulated_motion.GetAcceleration(); |
| 377 | motion.gyro = emulated_motion.GetGyroscope(); | 377 | motion.gyro = emulated_motion.GetGyroscope(); |
| 378 | motion.rotation = emulated_motion.GetRotations(); | 378 | motion.rotation = emulated_motion.GetRotations(); |
| 379 | motion.euler = emulated_motion.GetEulerAngles(); | ||
| 379 | motion.orientation = emulated_motion.GetOrientation(); | 380 | motion.orientation = emulated_motion.GetOrientation(); |
| 380 | motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); | 381 | motion.is_at_rest = !emulated_motion.IsMoving(motion_sensitivity); |
| 381 | } | 382 | } |
| @@ -551,6 +552,8 @@ void EmulatedController::EnableSystemButtons() { | |||
| 551 | void EmulatedController::DisableSystemButtons() { | 552 | void EmulatedController::DisableSystemButtons() { |
| 552 | std::scoped_lock lock{mutex}; | 553 | std::scoped_lock lock{mutex}; |
| 553 | system_buttons_enabled = false; | 554 | system_buttons_enabled = false; |
| 555 | controller.home_button_state.raw = 0; | ||
| 556 | controller.capture_button_state.raw = 0; | ||
| 554 | } | 557 | } |
| 555 | 558 | ||
| 556 | void EmulatedController::ResetSystemButtons() { | 559 | void EmulatedController::ResetSystemButtons() { |
| @@ -734,6 +737,8 @@ void EmulatedController::SetButton(const Common::Input::CallbackStatus& callback | |||
| 734 | if (is_configuring) { | 737 | if (is_configuring) { |
| 735 | controller.npad_button_state.raw = NpadButton::None; | 738 | controller.npad_button_state.raw = NpadButton::None; |
| 736 | controller.debug_pad_button_state.raw = 0; | 739 | controller.debug_pad_button_state.raw = 0; |
| 740 | controller.home_button_state.raw = 0; | ||
| 741 | controller.capture_button_state.raw = 0; | ||
| 737 | lock.unlock(); | 742 | lock.unlock(); |
| 738 | TriggerOnChange(ControllerTriggerType::Button, false); | 743 | TriggerOnChange(ControllerTriggerType::Button, false); |
| 739 | return; | 744 | return; |
| @@ -976,14 +981,11 @@ void EmulatedController::SetMotion(const Common::Input::CallbackStatus& callback | |||
| 976 | emulated.UpdateOrientation(raw_status.delta_timestamp); | 981 | emulated.UpdateOrientation(raw_status.delta_timestamp); |
| 977 | force_update_motion = raw_status.force_update; | 982 | force_update_motion = raw_status.force_update; |
| 978 | 983 | ||
| 979 | if (is_configuring) { | ||
| 980 | return; | ||
| 981 | } | ||
| 982 | |||
| 983 | auto& motion = controller.motion_state[index]; | 984 | auto& motion = controller.motion_state[index]; |
| 984 | motion.accel = emulated.GetAcceleration(); | 985 | motion.accel = emulated.GetAcceleration(); |
| 985 | motion.gyro = emulated.GetGyroscope(); | 986 | motion.gyro = emulated.GetGyroscope(); |
| 986 | motion.rotation = emulated.GetRotations(); | 987 | motion.rotation = emulated.GetRotations(); |
| 988 | motion.euler = emulated.GetEulerAngles(); | ||
| 987 | motion.orientation = emulated.GetOrientation(); | 989 | motion.orientation = emulated.GetOrientation(); |
| 988 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); | 990 | motion.is_at_rest = !emulated.IsMoving(motion_sensitivity); |
| 989 | } | 991 | } |
diff --git a/src/core/hid/emulated_controller.h b/src/core/hid/emulated_controller.h index 429655355..6e01f4e12 100644 --- a/src/core/hid/emulated_controller.h +++ b/src/core/hid/emulated_controller.h | |||
| @@ -106,6 +106,7 @@ struct ControllerMotion { | |||
| 106 | Common::Vec3f accel{}; | 106 | Common::Vec3f accel{}; |
| 107 | Common::Vec3f gyro{}; | 107 | Common::Vec3f gyro{}; |
| 108 | Common::Vec3f rotation{}; | 108 | Common::Vec3f rotation{}; |
| 109 | Common::Vec3f euler{}; | ||
| 109 | std::array<Common::Vec3f, 3> orientation{}; | 110 | std::array<Common::Vec3f, 3> orientation{}; |
| 110 | bool is_at_rest{}; | 111 | bool is_at_rest{}; |
| 111 | }; | 112 | }; |
diff --git a/src/core/hid/input_converter.cpp b/src/core/hid/input_converter.cpp index 7cee39a53..a38e3bb3f 100644 --- a/src/core/hid/input_converter.cpp +++ b/src/core/hid/input_converter.cpp | |||
| @@ -54,6 +54,7 @@ Common::Input::ButtonStatus TransformToButton(const Common::Input::CallbackStatu | |||
| 54 | case Common::Input::InputType::Analog: | 54 | case Common::Input::InputType::Analog: |
| 55 | status.value = TransformToTrigger(callback).pressed.value; | 55 | status.value = TransformToTrigger(callback).pressed.value; |
| 56 | status.toggle = callback.analog_status.properties.toggle; | 56 | status.toggle = callback.analog_status.properties.toggle; |
| 57 | status.inverted = callback.analog_status.properties.inverted_button; | ||
| 57 | break; | 58 | break; |
| 58 | case Common::Input::InputType::Trigger: | 59 | case Common::Input::InputType::Trigger: |
| 59 | status.value = TransformToTrigger(callback).pressed.value; | 60 | status.value = TransformToTrigger(callback).pressed.value; |
diff --git a/src/core/hid/motion_input.cpp b/src/core/hid/motion_input.cpp index 0dd66c1cc..b60478dbb 100644 --- a/src/core/hid/motion_input.cpp +++ b/src/core/hid/motion_input.cpp | |||
| @@ -1,6 +1,8 @@ | |||
| 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project | 1 | // SPDX-FileCopyrightText: Copyright 2020 yuzu Emulator Project |
| 2 | // SPDX-License-Identifier: GPL-2.0-or-later | 2 | // SPDX-License-Identifier: GPL-2.0-or-later |
| 3 | 3 | ||
| 4 | #include <cmath> | ||
| 5 | |||
| 4 | #include "common/math_util.h" | 6 | #include "common/math_util.h" |
| 5 | #include "core/hid/motion_input.h" | 7 | #include "core/hid/motion_input.h" |
| 6 | 8 | ||
| @@ -51,6 +53,20 @@ void MotionInput::SetQuaternion(const Common::Quaternion<f32>& quaternion) { | |||
| 51 | quat = quaternion; | 53 | quat = quaternion; |
| 52 | } | 54 | } |
| 53 | 55 | ||
| 56 | void MotionInput::SetEulerAngles(const Common::Vec3f& euler_angles) { | ||
| 57 | const float cr = std::cos(euler_angles.x * 0.5f); | ||
| 58 | const float sr = std::sin(euler_angles.x * 0.5f); | ||
| 59 | const float cp = std::cos(euler_angles.y * 0.5f); | ||
| 60 | const float sp = std::sin(euler_angles.y * 0.5f); | ||
| 61 | const float cy = std::cos(euler_angles.z * 0.5f); | ||
| 62 | const float sy = std::sin(euler_angles.z * 0.5f); | ||
| 63 | |||
| 64 | quat.w = cr * cp * cy + sr * sp * sy; | ||
| 65 | quat.xyz.x = sr * cp * cy - cr * sp * sy; | ||
| 66 | quat.xyz.y = cr * sp * cy + sr * cp * sy; | ||
| 67 | quat.xyz.z = cr * cp * sy - sr * sp * cy; | ||
| 68 | } | ||
| 69 | |||
| 54 | void MotionInput::SetGyroBias(const Common::Vec3f& bias) { | 70 | void MotionInput::SetGyroBias(const Common::Vec3f& bias) { |
| 55 | gyro_bias = bias; | 71 | gyro_bias = bias; |
| 56 | } | 72 | } |
| @@ -222,6 +238,26 @@ Common::Vec3f MotionInput::GetRotations() const { | |||
| 222 | return rotations; | 238 | return rotations; |
| 223 | } | 239 | } |
| 224 | 240 | ||
| 241 | Common::Vec3f MotionInput::GetEulerAngles() const { | ||
| 242 | // roll (x-axis rotation) | ||
| 243 | const float sinr_cosp = 2 * (quat.w * quat.xyz.x + quat.xyz.y * quat.xyz.z); | ||
| 244 | const float cosr_cosp = 1 - 2 * (quat.xyz.x * quat.xyz.x + quat.xyz.y * quat.xyz.y); | ||
| 245 | |||
| 246 | // pitch (y-axis rotation) | ||
| 247 | const float sinp = std::sqrt(1 + 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); | ||
| 248 | const float cosp = std::sqrt(1 - 2 * (quat.w * quat.xyz.y - quat.xyz.x * quat.xyz.z)); | ||
| 249 | |||
| 250 | // yaw (z-axis rotation) | ||
| 251 | const float siny_cosp = 2 * (quat.w * quat.xyz.z + quat.xyz.x * quat.xyz.y); | ||
| 252 | const float cosy_cosp = 1 - 2 * (quat.xyz.y * quat.xyz.y + quat.xyz.z * quat.xyz.z); | ||
| 253 | |||
| 254 | return { | ||
| 255 | std::atan2(sinr_cosp, cosr_cosp), | ||
| 256 | 2 * std::atan2(sinp, cosp) - Common::PI / 2, | ||
| 257 | std::atan2(siny_cosp, cosy_cosp), | ||
| 258 | }; | ||
| 259 | } | ||
| 260 | |||
| 225 | void MotionInput::ResetOrientation() { | 261 | void MotionInput::ResetOrientation() { |
| 226 | if (!reset_enabled || only_accelerometer) { | 262 | if (!reset_enabled || only_accelerometer) { |
| 227 | return; | 263 | return; |
diff --git a/src/core/hid/motion_input.h b/src/core/hid/motion_input.h index 9f3fc1cf7..482719359 100644 --- a/src/core/hid/motion_input.h +++ b/src/core/hid/motion_input.h | |||
| @@ -35,6 +35,7 @@ public: | |||
| 35 | void SetAcceleration(const Common::Vec3f& acceleration); | 35 | void SetAcceleration(const Common::Vec3f& acceleration); |
| 36 | void SetGyroscope(const Common::Vec3f& gyroscope); | 36 | void SetGyroscope(const Common::Vec3f& gyroscope); |
| 37 | void SetQuaternion(const Common::Quaternion<f32>& quaternion); | 37 | void SetQuaternion(const Common::Quaternion<f32>& quaternion); |
| 38 | void SetEulerAngles(const Common::Vec3f& euler_angles); | ||
| 38 | void SetGyroBias(const Common::Vec3f& bias); | 39 | void SetGyroBias(const Common::Vec3f& bias); |
| 39 | void SetGyroThreshold(f32 threshold); | 40 | void SetGyroThreshold(f32 threshold); |
| 40 | 41 | ||
| @@ -54,6 +55,7 @@ public: | |||
| 54 | [[nodiscard]] Common::Vec3f GetGyroBias() const; | 55 | [[nodiscard]] Common::Vec3f GetGyroBias() const; |
| 55 | [[nodiscard]] Common::Vec3f GetRotations() const; | 56 | [[nodiscard]] Common::Vec3f GetRotations() const; |
| 56 | [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; | 57 | [[nodiscard]] Common::Quaternion<f32> GetQuaternion() const; |
| 58 | [[nodiscard]] Common::Vec3f GetEulerAngles() const; | ||
| 57 | 59 | ||
| 58 | [[nodiscard]] bool IsMoving(f32 sensitivity) const; | 60 | [[nodiscard]] bool IsMoving(f32 sensitivity) const; |
| 59 | [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; | 61 | [[nodiscard]] bool IsCalibrated(f32 sensitivity) const; |
diff --git a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp index 36d0d20d2..49bdc671e 100644 --- a/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp +++ b/src/core/hle/kernel/board/nintendo/nx/k_system_control.cpp | |||
| @@ -35,12 +35,13 @@ namespace { | |||
| 35 | using namespace Common::Literals; | 35 | using namespace Common::Literals; |
| 36 | 36 | ||
| 37 | u32 GetMemorySizeForInit() { | 37 | u32 GetMemorySizeForInit() { |
| 38 | return Settings::values.use_extended_memory_layout ? Smc::MemorySize_8GB : Smc::MemorySize_4GB; | 38 | return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemorySize_8GB |
| 39 | : Smc::MemorySize_4GB; | ||
| 39 | } | 40 | } |
| 40 | 41 | ||
| 41 | Smc::MemoryArrangement GetMemoryArrangeForInit() { | 42 | Smc::MemoryArrangement GetMemoryArrangeForInit() { |
| 42 | return Settings::values.use_extended_memory_layout ? Smc::MemoryArrangement_8GB | 43 | return Settings::values.use_unsafe_extended_memory_layout ? Smc::MemoryArrangement_8GB |
| 43 | : Smc::MemoryArrangement_4GB; | 44 | : Smc::MemoryArrangement_4GB; |
| 44 | } | 45 | } |
| 45 | } // namespace | 46 | } // namespace |
| 46 | 47 | ||
diff --git a/src/core/hle/kernel/k_auto_object.h b/src/core/hle/kernel/k_auto_object.h index 9b71fe371..f384b1568 100644 --- a/src/core/hle/kernel/k_auto_object.h +++ b/src/core/hle/kernel/k_auto_object.h | |||
| @@ -182,8 +182,8 @@ public: | |||
| 182 | explicit KAutoObjectWithList(KernelCore& kernel) : KAutoObject(kernel) {} | 182 | explicit KAutoObjectWithList(KernelCore& kernel) : KAutoObject(kernel) {} |
| 183 | 183 | ||
| 184 | static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { | 184 | static int Compare(const KAutoObjectWithList& lhs, const KAutoObjectWithList& rhs) { |
| 185 | const u64 lid = lhs.GetId(); | 185 | const uintptr_t lid = reinterpret_cast<uintptr_t>(std::addressof(lhs)); |
| 186 | const u64 rid = rhs.GetId(); | 186 | const uintptr_t rid = reinterpret_cast<uintptr_t>(std::addressof(rhs)); |
| 187 | 187 | ||
| 188 | if (lid < rid) { | 188 | if (lid < rid) { |
| 189 | return -1; | 189 | return -1; |
diff --git a/src/core/hle/kernel/kernel.cpp b/src/core/hle/kernel/kernel.cpp index 4f3366c9d..f33600ca5 100644 --- a/src/core/hle/kernel/kernel.cpp +++ b/src/core/hle/kernel/kernel.cpp | |||
| @@ -95,7 +95,7 @@ struct KernelCore::Impl { | |||
| 95 | pt_heap_region.GetSize()); | 95 | pt_heap_region.GetSize()); |
| 96 | } | 96 | } |
| 97 | 97 | ||
| 98 | InitializeHackSharedMemory(); | 98 | InitializeHackSharedMemory(kernel); |
| 99 | RegisterHostThread(nullptr); | 99 | RegisterHostThread(nullptr); |
| 100 | } | 100 | } |
| 101 | 101 | ||
| @@ -216,10 +216,12 @@ struct KernelCore::Impl { | |||
| 216 | auto* main_thread{Kernel::KThread::Create(system.Kernel())}; | 216 | auto* main_thread{Kernel::KThread::Create(system.Kernel())}; |
| 217 | main_thread->SetCurrentCore(core); | 217 | main_thread->SetCurrentCore(core); |
| 218 | ASSERT(Kernel::KThread::InitializeMainThread(system, main_thread, core).IsSuccess()); | 218 | ASSERT(Kernel::KThread::InitializeMainThread(system, main_thread, core).IsSuccess()); |
| 219 | KThread::Register(system.Kernel(), main_thread); | ||
| 219 | 220 | ||
| 220 | auto* idle_thread{Kernel::KThread::Create(system.Kernel())}; | 221 | auto* idle_thread{Kernel::KThread::Create(system.Kernel())}; |
| 221 | idle_thread->SetCurrentCore(core); | 222 | idle_thread->SetCurrentCore(core); |
| 222 | ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); | 223 | ASSERT(Kernel::KThread::InitializeIdleThread(system, idle_thread, core).IsSuccess()); |
| 224 | KThread::Register(system.Kernel(), idle_thread); | ||
| 223 | 225 | ||
| 224 | schedulers[i]->Initialize(main_thread, idle_thread, core); | 226 | schedulers[i]->Initialize(main_thread, idle_thread, core); |
| 225 | } | 227 | } |
| @@ -230,6 +232,7 @@ struct KernelCore::Impl { | |||
| 230 | const Core::Timing::CoreTiming& core_timing) { | 232 | const Core::Timing::CoreTiming& core_timing) { |
| 231 | system_resource_limit = KResourceLimit::Create(system.Kernel()); | 233 | system_resource_limit = KResourceLimit::Create(system.Kernel()); |
| 232 | system_resource_limit->Initialize(&core_timing); | 234 | system_resource_limit->Initialize(&core_timing); |
| 235 | KResourceLimit::Register(kernel, system_resource_limit); | ||
| 233 | 236 | ||
| 234 | const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()}; | 237 | const auto sizes{memory_layout->GetTotalAndKernelMemorySizes()}; |
| 235 | const auto total_size{sizes.first}; | 238 | const auto total_size{sizes.first}; |
| @@ -355,6 +358,7 @@ struct KernelCore::Impl { | |||
| 355 | ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {}, | 358 | ASSERT(KThread::InitializeHighPriorityThread(system, shutdown_threads[core_id], {}, {}, |
| 356 | core_id) | 359 | core_id) |
| 357 | .IsSuccess()); | 360 | .IsSuccess()); |
| 361 | KThread::Register(system.Kernel(), shutdown_threads[core_id]); | ||
| 358 | } | 362 | } |
| 359 | } | 363 | } |
| 360 | 364 | ||
| @@ -729,7 +733,7 @@ struct KernelCore::Impl { | |||
| 729 | memory_manager->Initialize(management_region.GetAddress(), management_region.GetSize()); | 733 | memory_manager->Initialize(management_region.GetAddress(), management_region.GetSize()); |
| 730 | } | 734 | } |
| 731 | 735 | ||
| 732 | void InitializeHackSharedMemory() { | 736 | void InitializeHackSharedMemory(KernelCore& kernel) { |
| 733 | // Setup memory regions for emulated processes | 737 | // Setup memory regions for emulated processes |
| 734 | // TODO(bunnei): These should not be hardcoded regions initialized within the kernel | 738 | // TODO(bunnei): These should not be hardcoded regions initialized within the kernel |
| 735 | constexpr std::size_t hid_size{0x40000}; | 739 | constexpr std::size_t hid_size{0x40000}; |
| @@ -746,14 +750,23 @@ struct KernelCore::Impl { | |||
| 746 | 750 | ||
| 747 | hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | 751 | hid_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, |
| 748 | Svc::MemoryPermission::Read, hid_size); | 752 | Svc::MemoryPermission::Read, hid_size); |
| 753 | KSharedMemory::Register(kernel, hid_shared_mem); | ||
| 754 | |||
| 749 | font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | 755 | font_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, |
| 750 | Svc::MemoryPermission::Read, font_size); | 756 | Svc::MemoryPermission::Read, font_size); |
| 757 | KSharedMemory::Register(kernel, font_shared_mem); | ||
| 758 | |||
| 751 | irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | 759 | irs_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, |
| 752 | Svc::MemoryPermission::Read, irs_size); | 760 | Svc::MemoryPermission::Read, irs_size); |
| 761 | KSharedMemory::Register(kernel, irs_shared_mem); | ||
| 762 | |||
| 753 | time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | 763 | time_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, |
| 754 | Svc::MemoryPermission::Read, time_size); | 764 | Svc::MemoryPermission::Read, time_size); |
| 765 | KSharedMemory::Register(kernel, time_shared_mem); | ||
| 766 | |||
| 755 | hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, | 767 | hidbus_shared_mem->Initialize(system.DeviceMemory(), nullptr, Svc::MemoryPermission::None, |
| 756 | Svc::MemoryPermission::Read, hidbus_size); | 768 | Svc::MemoryPermission::Read, hidbus_size); |
| 769 | KSharedMemory::Register(kernel, hidbus_shared_mem); | ||
| 757 | } | 770 | } |
| 758 | 771 | ||
| 759 | std::mutex registered_objects_lock; | 772 | std::mutex registered_objects_lock; |
| @@ -1072,12 +1085,15 @@ static std::jthread RunHostThreadFunc(KernelCore& kernel, KProcess* process, | |||
| 1072 | // Commit the thread reservation. | 1085 | // Commit the thread reservation. |
| 1073 | thread_reservation.Commit(); | 1086 | thread_reservation.Commit(); |
| 1074 | 1087 | ||
| 1088 | // Register the thread. | ||
| 1089 | KThread::Register(kernel, thread); | ||
| 1090 | |||
| 1075 | return std::jthread( | 1091 | return std::jthread( |
| 1076 | [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] { | 1092 | [&kernel, thread, thread_name{std::move(thread_name)}, func{std::move(func)}] { |
| 1077 | // Set the thread name. | 1093 | // Set the thread name. |
| 1078 | Common::SetCurrentThreadName(thread_name.c_str()); | 1094 | Common::SetCurrentThreadName(thread_name.c_str()); |
| 1079 | 1095 | ||
| 1080 | // Register the thread. | 1096 | // Set the thread as current. |
| 1081 | kernel.RegisterHostThread(thread); | 1097 | kernel.RegisterHostThread(thread); |
| 1082 | 1098 | ||
| 1083 | // Run the callback. | 1099 | // Run the callback. |
| @@ -1099,6 +1115,9 @@ std::jthread KernelCore::RunOnHostCoreProcess(std::string&& process_name, | |||
| 1099 | // Ensure that we don't hold onto any extra references. | 1115 | // Ensure that we don't hold onto any extra references. |
| 1100 | SCOPE_EXIT({ process->Close(); }); | 1116 | SCOPE_EXIT({ process->Close(); }); |
| 1101 | 1117 | ||
| 1118 | // Register the new process. | ||
| 1119 | KProcess::Register(*this, process); | ||
| 1120 | |||
| 1102 | // Run the host thread. | 1121 | // Run the host thread. |
| 1103 | return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func)); | 1122 | return RunHostThreadFunc(*this, process, std::move(process_name), std::move(func)); |
| 1104 | } | 1123 | } |
| @@ -1124,6 +1143,9 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function | |||
| 1124 | // Ensure that we don't hold onto any extra references. | 1143 | // Ensure that we don't hold onto any extra references. |
| 1125 | SCOPE_EXIT({ process->Close(); }); | 1144 | SCOPE_EXIT({ process->Close(); }); |
| 1126 | 1145 | ||
| 1146 | // Register the new process. | ||
| 1147 | KProcess::Register(*this, process); | ||
| 1148 | |||
| 1127 | // Reserve a new thread from the process resource limit. | 1149 | // Reserve a new thread from the process resource limit. |
| 1128 | KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); | 1150 | KScopedResourceReservation thread_reservation(process, LimitableResource::ThreadCountMax); |
| 1129 | ASSERT(thread_reservation.Succeeded()); | 1151 | ASSERT(thread_reservation.Succeeded()); |
| @@ -1136,6 +1158,9 @@ void KernelCore::RunOnGuestCoreProcess(std::string&& process_name, std::function | |||
| 1136 | // Commit the thread reservation. | 1158 | // Commit the thread reservation. |
| 1137 | thread_reservation.Commit(); | 1159 | thread_reservation.Commit(); |
| 1138 | 1160 | ||
| 1161 | // Register the new thread. | ||
| 1162 | KThread::Register(*this, thread); | ||
| 1163 | |||
| 1139 | // Begin running the thread. | 1164 | // Begin running the thread. |
| 1140 | ASSERT(R_SUCCEEDED(thread->Run())); | 1165 | ASSERT(R_SUCCEEDED(thread->Run())); |
| 1141 | } | 1166 | } |
diff --git a/src/core/hle/service/ipc_helpers.h b/src/core/hle/service/ipc_helpers.h index e4cb4e1f2..0e222362e 100644 --- a/src/core/hle/service/ipc_helpers.h +++ b/src/core/hle/service/ipc_helpers.h | |||
| @@ -156,6 +156,7 @@ public: | |||
| 156 | 156 | ||
| 157 | auto* session = Kernel::KSession::Create(kernel); | 157 | auto* session = Kernel::KSession::Create(kernel); |
| 158 | session->Initialize(nullptr, 0); | 158 | session->Initialize(nullptr, 0); |
| 159 | Kernel::KSession::Register(kernel, session); | ||
| 159 | 160 | ||
| 160 | auto next_manager = std::make_shared<Service::SessionRequestManager>( | 161 | auto next_manager = std::make_shared<Service::SessionRequestManager>( |
| 161 | kernel, manager->GetServerManager()); | 162 | kernel, manager->GetServerManager()); |
diff --git a/src/core/hle/service/kernel_helpers.cpp b/src/core/hle/service/kernel_helpers.cpp index a39ce5212..6a313a03b 100644 --- a/src/core/hle/service/kernel_helpers.cpp +++ b/src/core/hle/service/kernel_helpers.cpp | |||
| @@ -25,6 +25,9 @@ ServiceContext::ServiceContext(Core::System& system_, std::string name_) | |||
| 25 | Kernel::KProcess::ProcessType::KernelInternal, | 25 | Kernel::KProcess::ProcessType::KernelInternal, |
| 26 | kernel.GetSystemResourceLimit()) | 26 | kernel.GetSystemResourceLimit()) |
| 27 | .IsSuccess()); | 27 | .IsSuccess()); |
| 28 | |||
| 29 | // Register the process. | ||
| 30 | Kernel::KProcess::Register(kernel, process); | ||
| 28 | process_created = true; | 31 | process_created = true; |
| 29 | } | 32 | } |
| 30 | 33 | ||
diff --git a/src/core/hle/service/mutex.cpp b/src/core/hle/service/mutex.cpp index 07589a0f0..b0ff71d1b 100644 --- a/src/core/hle/service/mutex.cpp +++ b/src/core/hle/service/mutex.cpp | |||
| @@ -12,6 +12,9 @@ Mutex::Mutex(Core::System& system) : m_system(system) { | |||
| 12 | m_event = Kernel::KEvent::Create(system.Kernel()); | 12 | m_event = Kernel::KEvent::Create(system.Kernel()); |
| 13 | m_event->Initialize(nullptr); | 13 | m_event->Initialize(nullptr); |
| 14 | 14 | ||
| 15 | // Register the event. | ||
| 16 | Kernel::KEvent::Register(system.Kernel(), m_event); | ||
| 17 | |||
| 15 | ASSERT(R_SUCCEEDED(m_event->Signal())); | 18 | ASSERT(R_SUCCEEDED(m_event->Signal())); |
| 16 | } | 19 | } |
| 17 | 20 | ||
diff --git a/src/core/hle/service/server_manager.cpp b/src/core/hle/service/server_manager.cpp index 6b4a1291e..156bc27d8 100644 --- a/src/core/hle/service/server_manager.cpp +++ b/src/core/hle/service/server_manager.cpp | |||
| @@ -33,6 +33,9 @@ ServerManager::ServerManager(Core::System& system) : m_system{system}, m_serve_m | |||
| 33 | // Initialize event. | 33 | // Initialize event. |
| 34 | m_event = Kernel::KEvent::Create(system.Kernel()); | 34 | m_event = Kernel::KEvent::Create(system.Kernel()); |
| 35 | m_event->Initialize(nullptr); | 35 | m_event->Initialize(nullptr); |
| 36 | |||
| 37 | // Register event. | ||
| 38 | Kernel::KEvent::Register(system.Kernel(), m_event); | ||
| 36 | } | 39 | } |
| 37 | 40 | ||
| 38 | ServerManager::~ServerManager() { | 41 | ServerManager::~ServerManager() { |
| @@ -160,6 +163,9 @@ Result ServerManager::ManageDeferral(Kernel::KEvent** out_event) { | |||
| 160 | // Initialize the event. | 163 | // Initialize the event. |
| 161 | m_deferral_event->Initialize(nullptr); | 164 | m_deferral_event->Initialize(nullptr); |
| 162 | 165 | ||
| 166 | // Register the event. | ||
| 167 | Kernel::KEvent::Register(m_system.Kernel(), m_deferral_event); | ||
| 168 | |||
| 163 | // Set the output. | 169 | // Set the output. |
| 164 | *out_event = m_deferral_event; | 170 | *out_event = m_deferral_event; |
| 165 | 171 | ||
diff --git a/src/core/hle/service/sm/sm.cpp b/src/core/hle/service/sm/sm.cpp index c45be5726..1608fa24c 100644 --- a/src/core/hle/service/sm/sm.cpp +++ b/src/core/hle/service/sm/sm.cpp | |||
| @@ -64,6 +64,9 @@ Result ServiceManager::RegisterService(std::string name, u32 max_sessions, | |||
| 64 | auto* port = Kernel::KPort::Create(kernel); | 64 | auto* port = Kernel::KPort::Create(kernel); |
| 65 | port->Initialize(ServerSessionCountMax, false, 0); | 65 | port->Initialize(ServerSessionCountMax, false, 0); |
| 66 | 66 | ||
| 67 | // Register the port. | ||
| 68 | Kernel::KPort::Register(kernel, port); | ||
| 69 | |||
| 67 | service_ports.emplace(name, port); | 70 | service_ports.emplace(name, port); |
| 68 | registered_services.emplace(name, handler); | 71 | registered_services.emplace(name, handler); |
| 69 | if (deferral_event) { | 72 | if (deferral_event) { |
diff --git a/src/core/hle/service/sm/sm_controller.cpp b/src/core/hle/service/sm/sm_controller.cpp index 419c1df2b..7dce28fe0 100644 --- a/src/core/hle/service/sm/sm_controller.cpp +++ b/src/core/hle/service/sm/sm_controller.cpp | |||
| @@ -49,6 +49,9 @@ void Controller::CloneCurrentObject(HLERequestContext& ctx) { | |||
| 49 | // Commit the session reservation. | 49 | // Commit the session reservation. |
| 50 | session_reservation.Commit(); | 50 | session_reservation.Commit(); |
| 51 | 51 | ||
| 52 | // Register the session. | ||
| 53 | Kernel::KSession::Register(system.Kernel(), session); | ||
| 54 | |||
| 52 | // Register with server manager. | 55 | // Register with server manager. |
| 53 | session_manager->GetServerManager().RegisterSession(&session->GetServerSession(), | 56 | session_manager->GetServerManager().RegisterSession(&session->GetServerSession(), |
| 54 | session_manager); | 57 | session_manager); |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 432310632..a9667463f 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -462,7 +462,7 @@ struct Memory::Impl { | |||
| 462 | } | 462 | } |
| 463 | 463 | ||
| 464 | if (Settings::IsFastmemEnabled()) { | 464 | if (Settings::IsFastmemEnabled()) { |
| 465 | const bool is_read_enable = Settings::IsGPULevelHigh() || !cached; | 465 | const bool is_read_enable = !Settings::IsGPULevelExtreme() || !cached; |
| 466 | system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); | 466 | system.DeviceMemory().buffer.Protect(vaddr, size, is_read_enable, !cached); |
| 467 | } | 467 | } |
| 468 | 468 | ||
diff --git a/src/input_common/input_engine.cpp b/src/input_common/input_engine.cpp index 91aa96aa7..49f5e7f54 100644 --- a/src/input_common/input_engine.cpp +++ b/src/input_common/input_engine.cpp | |||
| @@ -58,6 +58,8 @@ void InputEngine::SetHatButton(const PadIdentifier& identifier, int button, u8 v | |||
| 58 | } | 58 | } |
| 59 | 59 | ||
| 60 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { | 60 | void InputEngine::SetAxis(const PadIdentifier& identifier, int axis, f32 value) { |
| 61 | value /= 2.0f; | ||
| 62 | value -= 0.5f; | ||
| 61 | { | 63 | { |
| 62 | std::scoped_lock lock{mutex}; | 64 | std::scoped_lock lock{mutex}; |
| 63 | ControllerData& controller = controller_list.at(identifier); | 65 | ControllerData& controller = controller_list.at(identifier); |
diff --git a/src/input_common/input_poller.cpp b/src/input_common/input_poller.cpp index 8c6a6521a..5c2c4a463 100644 --- a/src/input_common/input_poller.cpp +++ b/src/input_common/input_poller.cpp | |||
| @@ -939,6 +939,7 @@ std::unique_ptr<Common::Input::InputDevice> InputFactory::CreateAnalogDevice( | |||
| 939 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), | 939 | .threshold = std::clamp(params.Get("threshold", 0.5f), 0.0f, 1.0f), |
| 940 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), | 940 | .offset = std::clamp(params.Get("offset", 0.0f), -1.0f, 1.0f), |
| 941 | .inverted = params.Get("invert", "+") == "-", | 941 | .inverted = params.Get("invert", "+") == "-", |
| 942 | .inverted_button = params.Get("inverted", false) != 0, | ||
| 942 | .toggle = params.Get("toggle", false) != 0, | 943 | .toggle = params.Get("toggle", false) != 0, |
| 943 | }; | 944 | }; |
| 944 | input_engine->PreSetController(identifier); | 945 | input_engine->PreSetController(identifier); |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 7975564b5..e534e1e9c 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -1426,7 +1426,7 @@ bool BufferCache<P>::SynchronizeBufferNoModified(Buffer& buffer, VAddr cpu_addr, | |||
| 1426 | .size = sub_size, | 1426 | .size = sub_size, |
| 1427 | }); | 1427 | }); |
| 1428 | total_size_bytes += sub_size; | 1428 | total_size_bytes += sub_size; |
| 1429 | largest_copy = std::max(largest_copy, sub_size); | 1429 | largest_copy = std::max<u64>(largest_copy, sub_size); |
| 1430 | } | 1430 | } |
| 1431 | const std::span<BufferCopy> copies_span(copies.data(), copies.size()); | 1431 | const std::span<BufferCopy> copies_span(copies.data(), copies.size()); |
| 1432 | UploadMemory(buffer, total_size_bytes, largest_copy, copies_span); | 1432 | UploadMemory(buffer, total_size_bytes, largest_copy, copies_span); |
diff --git a/src/video_core/buffer_cache/memory_tracker_base.h b/src/video_core/buffer_cache/memory_tracker_base.h index 4bc59017f..dc4ebfcaa 100644 --- a/src/video_core/buffer_cache/memory_tracker_base.h +++ b/src/video_core/buffer_cache/memory_tracker_base.h | |||
| @@ -170,7 +170,8 @@ private: | |||
| 170 | std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; | 170 | std::size_t page_index{cpu_address >> HIGHER_PAGE_BITS}; |
| 171 | u64 page_offset{cpu_address & HIGHER_PAGE_MASK}; | 171 | u64 page_offset{cpu_address & HIGHER_PAGE_MASK}; |
| 172 | while (remaining_size > 0) { | 172 | while (remaining_size > 0) { |
| 173 | const std::size_t copy_amount{std::min(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; | 173 | const std::size_t copy_amount{ |
| 174 | std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; | ||
| 174 | auto* manager{top_tier[page_index]}; | 175 | auto* manager{top_tier[page_index]}; |
| 175 | if (manager) { | 176 | if (manager) { |
| 176 | if constexpr (BOOL_BREAK) { | 177 | if constexpr (BOOL_BREAK) { |
| @@ -206,7 +207,8 @@ private: | |||
| 206 | u64 begin = std::numeric_limits<u64>::max(); | 207 | u64 begin = std::numeric_limits<u64>::max(); |
| 207 | u64 end = 0; | 208 | u64 end = 0; |
| 208 | while (remaining_size > 0) { | 209 | while (remaining_size > 0) { |
| 209 | const std::size_t copy_amount{std::min(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; | 210 | const std::size_t copy_amount{ |
| 211 | std::min<std::size_t>(HIGHER_PAGE_SIZE - page_offset, remaining_size)}; | ||
| 210 | auto* manager{top_tier[page_index]}; | 212 | auto* manager{top_tier[page_index]}; |
| 211 | const auto execute = [&] { | 213 | const auto execute = [&] { |
| 212 | auto [new_begin, new_end] = func(manager, page_offset, copy_amount); | 214 | auto [new_begin, new_end] = func(manager, page_offset, copy_amount); |
diff --git a/src/video_core/compatible_formats.cpp b/src/video_core/compatible_formats.cpp index 4e75f33ca..ab4f4d407 100644 --- a/src/video_core/compatible_formats.cpp +++ b/src/video_core/compatible_formats.cpp | |||
| @@ -126,15 +126,14 @@ constexpr std::array VIEW_CLASS_ASTC_8x8_RGBA{ | |||
| 126 | PixelFormat::ASTC_2D_8X8_SRGB, | 126 | PixelFormat::ASTC_2D_8X8_SRGB, |
| 127 | }; | 127 | }; |
| 128 | 128 | ||
| 129 | // Missing formats: | 129 | constexpr std::array VIEW_CLASS_ASTC_10x5_RGBA{ |
| 130 | // PixelFormat::ASTC_2D_10X5_UNORM | 130 | PixelFormat::ASTC_2D_10X5_UNORM, |
| 131 | // PixelFormat::ASTC_2D_10X5_SRGB | 131 | PixelFormat::ASTC_2D_10X5_SRGB, |
| 132 | 132 | }; | |
| 133 | // Missing formats: | ||
| 134 | // PixelFormat::ASTC_2D_10X6_SRGB | ||
| 135 | 133 | ||
| 136 | constexpr std::array VIEW_CLASS_ASTC_10x6_RGBA{ | 134 | constexpr std::array VIEW_CLASS_ASTC_10x6_RGBA{ |
| 137 | PixelFormat::ASTC_2D_10X6_UNORM, | 135 | PixelFormat::ASTC_2D_10X6_UNORM, |
| 136 | PixelFormat::ASTC_2D_10X6_SRGB, | ||
| 138 | }; | 137 | }; |
| 139 | 138 | ||
| 140 | constexpr std::array VIEW_CLASS_ASTC_10x8_RGBA{ | 139 | constexpr std::array VIEW_CLASS_ASTC_10x8_RGBA{ |
| @@ -147,9 +146,10 @@ constexpr std::array VIEW_CLASS_ASTC_10x10_RGBA{ | |||
| 147 | PixelFormat::ASTC_2D_10X10_SRGB, | 146 | PixelFormat::ASTC_2D_10X10_SRGB, |
| 148 | }; | 147 | }; |
| 149 | 148 | ||
| 150 | // Missing formats | 149 | constexpr std::array VIEW_CLASS_ASTC_12x10_RGBA{ |
| 151 | // ASTC_2D_12X10_UNORM, | 150 | PixelFormat::ASTC_2D_12X10_UNORM, |
| 152 | // ASTC_2D_12X10_SRGB, | 151 | PixelFormat::ASTC_2D_12X10_SRGB, |
| 152 | }; | ||
| 153 | 153 | ||
| 154 | constexpr std::array VIEW_CLASS_ASTC_12x12_RGBA{ | 154 | constexpr std::array VIEW_CLASS_ASTC_12x12_RGBA{ |
| 155 | PixelFormat::ASTC_2D_12X12_UNORM, | 155 | PixelFormat::ASTC_2D_12X12_UNORM, |
| @@ -229,9 +229,11 @@ constexpr Table MakeViewTable() { | |||
| 229 | EnableRange(view, VIEW_CLASS_ASTC_6x6_RGBA); | 229 | EnableRange(view, VIEW_CLASS_ASTC_6x6_RGBA); |
| 230 | EnableRange(view, VIEW_CLASS_ASTC_8x5_RGBA); | 230 | EnableRange(view, VIEW_CLASS_ASTC_8x5_RGBA); |
| 231 | EnableRange(view, VIEW_CLASS_ASTC_8x8_RGBA); | 231 | EnableRange(view, VIEW_CLASS_ASTC_8x8_RGBA); |
| 232 | EnableRange(view, VIEW_CLASS_ASTC_10x5_RGBA); | ||
| 232 | EnableRange(view, VIEW_CLASS_ASTC_10x6_RGBA); | 233 | EnableRange(view, VIEW_CLASS_ASTC_10x6_RGBA); |
| 233 | EnableRange(view, VIEW_CLASS_ASTC_10x8_RGBA); | 234 | EnableRange(view, VIEW_CLASS_ASTC_10x8_RGBA); |
| 234 | EnableRange(view, VIEW_CLASS_ASTC_10x10_RGBA); | 235 | EnableRange(view, VIEW_CLASS_ASTC_10x10_RGBA); |
| 236 | EnableRange(view, VIEW_CLASS_ASTC_12x10_RGBA); | ||
| 235 | EnableRange(view, VIEW_CLASS_ASTC_12x12_RGBA); | 237 | EnableRange(view, VIEW_CLASS_ASTC_12x12_RGBA); |
| 236 | return view; | 238 | return view; |
| 237 | } | 239 | } |
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index c390ac91b..3b2f6aab6 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h | |||
| @@ -4,13 +4,20 @@ | |||
| 4 | #pragma once | 4 | #pragma once |
| 5 | 5 | ||
| 6 | #include <algorithm> | 6 | #include <algorithm> |
| 7 | #include <condition_variable> | ||
| 7 | #include <cstring> | 8 | #include <cstring> |
| 8 | #include <deque> | 9 | #include <deque> |
| 9 | #include <functional> | 10 | #include <functional> |
| 10 | #include <memory> | 11 | #include <memory> |
| 12 | #include <mutex> | ||
| 13 | #include <thread> | ||
| 11 | #include <queue> | 14 | #include <queue> |
| 12 | 15 | ||
| 13 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 17 | #include "common/microprofile.h" | ||
| 18 | #include "common/scope_exit.h" | ||
| 19 | #include "common/settings.h" | ||
| 20 | #include "common/thread.h" | ||
| 14 | #include "video_core/delayed_destruction_ring.h" | 21 | #include "video_core/delayed_destruction_ring.h" |
| 15 | #include "video_core/gpu.h" | 22 | #include "video_core/gpu.h" |
| 16 | #include "video_core/host1x/host1x.h" | 23 | #include "video_core/host1x/host1x.h" |
| @@ -23,15 +30,26 @@ class FenceBase { | |||
| 23 | public: | 30 | public: |
| 24 | explicit FenceBase(bool is_stubbed_) : is_stubbed{is_stubbed_} {} | 31 | explicit FenceBase(bool is_stubbed_) : is_stubbed{is_stubbed_} {} |
| 25 | 32 | ||
| 33 | bool IsStubbed() const { | ||
| 34 | return is_stubbed; | ||
| 35 | } | ||
| 36 | |||
| 26 | protected: | 37 | protected: |
| 27 | bool is_stubbed; | 38 | bool is_stubbed; |
| 28 | }; | 39 | }; |
| 29 | 40 | ||
| 30 | template <typename TFence, typename TTextureCache, typename TTBufferCache, typename TQueryCache> | 41 | template <typename Traits> |
| 31 | class FenceManager { | 42 | class FenceManager { |
| 43 | using TFence = typename Traits::FenceType; | ||
| 44 | using TTextureCache = typename Traits::TextureCacheType; | ||
| 45 | using TBufferCache = typename Traits::BufferCacheType; | ||
| 46 | using TQueryCache = typename Traits::QueryCacheType; | ||
| 47 | static constexpr bool can_async_check = Traits::HAS_ASYNC_CHECK; | ||
| 48 | |||
| 32 | public: | 49 | public: |
| 33 | /// Notify the fence manager about a new frame | 50 | /// Notify the fence manager about a new frame |
| 34 | void TickFrame() { | 51 | void TickFrame() { |
| 52 | std::unique_lock lock(ring_guard); | ||
| 35 | delayed_destruction_ring.Tick(); | 53 | delayed_destruction_ring.Tick(); |
| 36 | } | 54 | } |
| 37 | 55 | ||
| @@ -46,17 +64,33 @@ public: | |||
| 46 | } | 64 | } |
| 47 | 65 | ||
| 48 | void SignalFence(std::function<void()>&& func) { | 66 | void SignalFence(std::function<void()>&& func) { |
| 49 | TryReleasePendingFences(); | 67 | rasterizer.InvalidateGPUCache(); |
| 68 | bool delay_fence = Settings::IsGPULevelHigh(); | ||
| 69 | if constexpr (!can_async_check) { | ||
| 70 | TryReleasePendingFences<false>(); | ||
| 71 | } | ||
| 50 | const bool should_flush = ShouldFlush(); | 72 | const bool should_flush = ShouldFlush(); |
| 51 | CommitAsyncFlushes(); | 73 | CommitAsyncFlushes(); |
| 52 | uncommitted_operations.emplace_back(std::move(func)); | ||
| 53 | CommitOperations(); | ||
| 54 | TFence new_fence = CreateFence(!should_flush); | 74 | TFence new_fence = CreateFence(!should_flush); |
| 55 | fences.push(new_fence); | 75 | if constexpr (can_async_check) { |
| 76 | guard.lock(); | ||
| 77 | } | ||
| 78 | if (delay_fence) { | ||
| 79 | uncommitted_operations.emplace_back(std::move(func)); | ||
| 80 | } | ||
| 81 | pending_operations.emplace_back(std::move(uncommitted_operations)); | ||
| 56 | QueueFence(new_fence); | 82 | QueueFence(new_fence); |
| 83 | if (!delay_fence) { | ||
| 84 | func(); | ||
| 85 | } | ||
| 86 | fences.push(std::move(new_fence)); | ||
| 57 | if (should_flush) { | 87 | if (should_flush) { |
| 58 | rasterizer.FlushCommands(); | 88 | rasterizer.FlushCommands(); |
| 59 | } | 89 | } |
| 90 | if constexpr (can_async_check) { | ||
| 91 | guard.unlock(); | ||
| 92 | cv.notify_all(); | ||
| 93 | } | ||
| 60 | } | 94 | } |
| 61 | 95 | ||
| 62 | void SignalSyncPoint(u32 value) { | 96 | void SignalSyncPoint(u32 value) { |
| @@ -66,29 +100,30 @@ public: | |||
| 66 | } | 100 | } |
| 67 | 101 | ||
| 68 | void WaitPendingFences() { | 102 | void WaitPendingFences() { |
| 69 | while (!fences.empty()) { | 103 | if constexpr (!can_async_check) { |
| 70 | TFence& current_fence = fences.front(); | 104 | TryReleasePendingFences<true>(); |
| 71 | if (ShouldWait()) { | ||
| 72 | WaitFence(current_fence); | ||
| 73 | } | ||
| 74 | PopAsyncFlushes(); | ||
| 75 | auto operations = std::move(pending_operations.front()); | ||
| 76 | pending_operations.pop_front(); | ||
| 77 | for (auto& operation : operations) { | ||
| 78 | operation(); | ||
| 79 | } | ||
| 80 | PopFence(); | ||
| 81 | } | 105 | } |
| 82 | } | 106 | } |
| 83 | 107 | ||
| 84 | protected: | 108 | protected: |
| 85 | explicit FenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_, | 109 | explicit FenceManager(VideoCore::RasterizerInterface& rasterizer_, Tegra::GPU& gpu_, |
| 86 | TTextureCache& texture_cache_, TTBufferCache& buffer_cache_, | 110 | TTextureCache& texture_cache_, TBufferCache& buffer_cache_, |
| 87 | TQueryCache& query_cache_) | 111 | TQueryCache& query_cache_) |
| 88 | : rasterizer{rasterizer_}, gpu{gpu_}, syncpoint_manager{gpu.Host1x().GetSyncpointManager()}, | 112 | : rasterizer{rasterizer_}, gpu{gpu_}, syncpoint_manager{gpu.Host1x().GetSyncpointManager()}, |
| 89 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, query_cache{query_cache_} {} | 113 | texture_cache{texture_cache_}, buffer_cache{buffer_cache_}, query_cache{query_cache_} { |
| 114 | if constexpr (can_async_check) { | ||
| 115 | fence_thread = | ||
| 116 | std::jthread([this](std::stop_token token) { ReleaseThreadFunc(token); }); | ||
| 117 | } | ||
| 118 | } | ||
| 90 | 119 | ||
| 91 | virtual ~FenceManager() = default; | 120 | virtual ~FenceManager() { |
| 121 | if constexpr (can_async_check) { | ||
| 122 | fence_thread.request_stop(); | ||
| 123 | cv.notify_all(); | ||
| 124 | fence_thread.join(); | ||
| 125 | } | ||
| 126 | } | ||
| 92 | 127 | ||
| 93 | /// Creates a Fence Interface, does not create a backend fence if 'is_stubbed' is | 128 | /// Creates a Fence Interface, does not create a backend fence if 'is_stubbed' is |
| 94 | /// true | 129 | /// true |
| @@ -104,15 +139,20 @@ protected: | |||
| 104 | Tegra::GPU& gpu; | 139 | Tegra::GPU& gpu; |
| 105 | Tegra::Host1x::SyncpointManager& syncpoint_manager; | 140 | Tegra::Host1x::SyncpointManager& syncpoint_manager; |
| 106 | TTextureCache& texture_cache; | 141 | TTextureCache& texture_cache; |
| 107 | TTBufferCache& buffer_cache; | 142 | TBufferCache& buffer_cache; |
| 108 | TQueryCache& query_cache; | 143 | TQueryCache& query_cache; |
| 109 | 144 | ||
| 110 | private: | 145 | private: |
| 146 | template <bool force_wait> | ||
| 111 | void TryReleasePendingFences() { | 147 | void TryReleasePendingFences() { |
| 112 | while (!fences.empty()) { | 148 | while (!fences.empty()) { |
| 113 | TFence& current_fence = fences.front(); | 149 | TFence& current_fence = fences.front(); |
| 114 | if (ShouldWait() && !IsFenceSignaled(current_fence)) { | 150 | if (ShouldWait() && !IsFenceSignaled(current_fence)) { |
| 115 | return; | 151 | if constexpr (force_wait) { |
| 152 | WaitFence(current_fence); | ||
| 153 | } else { | ||
| 154 | return; | ||
| 155 | } | ||
| 116 | } | 156 | } |
| 117 | PopAsyncFlushes(); | 157 | PopAsyncFlushes(); |
| 118 | auto operations = std::move(pending_operations.front()); | 158 | auto operations = std::move(pending_operations.front()); |
| @@ -120,7 +160,49 @@ private: | |||
| 120 | for (auto& operation : operations) { | 160 | for (auto& operation : operations) { |
| 121 | operation(); | 161 | operation(); |
| 122 | } | 162 | } |
| 123 | PopFence(); | 163 | { |
| 164 | std::unique_lock lock(ring_guard); | ||
| 165 | delayed_destruction_ring.Push(std::move(current_fence)); | ||
| 166 | } | ||
| 167 | fences.pop(); | ||
| 168 | } | ||
| 169 | } | ||
| 170 | |||
| 171 | void ReleaseThreadFunc(std::stop_token stop_token) { | ||
| 172 | std::string name = "GPUFencingThread"; | ||
| 173 | MicroProfileOnThreadCreate(name.c_str()); | ||
| 174 | |||
| 175 | // Cleanup | ||
| 176 | SCOPE_EXIT({ MicroProfileOnThreadExit(); }); | ||
| 177 | |||
| 178 | Common::SetCurrentThreadName(name.c_str()); | ||
| 179 | Common::SetCurrentThreadPriority(Common::ThreadPriority::High); | ||
| 180 | |||
| 181 | TFence current_fence; | ||
| 182 | std::deque<std::function<void()>> current_operations; | ||
| 183 | while (!stop_token.stop_requested()) { | ||
| 184 | { | ||
| 185 | std::unique_lock lock(guard); | ||
| 186 | cv.wait(lock, [&] { return stop_token.stop_requested() || !fences.empty(); }); | ||
| 187 | if (stop_token.stop_requested()) [[unlikely]] { | ||
| 188 | return; | ||
| 189 | } | ||
| 190 | current_fence = std::move(fences.front()); | ||
| 191 | current_operations = std::move(pending_operations.front()); | ||
| 192 | fences.pop(); | ||
| 193 | pending_operations.pop_front(); | ||
| 194 | } | ||
| 195 | if (!current_fence->IsStubbed()) { | ||
| 196 | WaitFence(current_fence); | ||
| 197 | } | ||
| 198 | PopAsyncFlushes(); | ||
| 199 | for (auto& operation : current_operations) { | ||
| 200 | operation(); | ||
| 201 | } | ||
| 202 | { | ||
| 203 | std::unique_lock lock(ring_guard); | ||
| 204 | delayed_destruction_ring.Push(std::move(current_fence)); | ||
| 205 | } | ||
| 124 | } | 206 | } |
| 125 | } | 207 | } |
| 126 | 208 | ||
| @@ -154,19 +236,16 @@ private: | |||
| 154 | query_cache.CommitAsyncFlushes(); | 236 | query_cache.CommitAsyncFlushes(); |
| 155 | } | 237 | } |
| 156 | 238 | ||
| 157 | void PopFence() { | ||
| 158 | delayed_destruction_ring.Push(std::move(fences.front())); | ||
| 159 | fences.pop(); | ||
| 160 | } | ||
| 161 | |||
| 162 | void CommitOperations() { | ||
| 163 | pending_operations.emplace_back(std::move(uncommitted_operations)); | ||
| 164 | } | ||
| 165 | |||
| 166 | std::queue<TFence> fences; | 239 | std::queue<TFence> fences; |
| 167 | std::deque<std::function<void()>> uncommitted_operations; | 240 | std::deque<std::function<void()>> uncommitted_operations; |
| 168 | std::deque<std::deque<std::function<void()>>> pending_operations; | 241 | std::deque<std::deque<std::function<void()>>> pending_operations; |
| 169 | 242 | ||
| 243 | std::mutex guard; | ||
| 244 | std::mutex ring_guard; | ||
| 245 | std::condition_variable cv; | ||
| 246 | |||
| 247 | std::jthread fence_thread; | ||
| 248 | |||
| 170 | DelayedDestructionRing<TFence, 6> delayed_destruction_ring; | 249 | DelayedDestructionRing<TFence, 6> delayed_destruction_ring; |
| 171 | }; | 250 | }; |
| 172 | 251 | ||
diff --git a/src/video_core/memory_manager.cpp b/src/video_core/memory_manager.cpp index 01fb5b546..7b2cde7a7 100644 --- a/src/video_core/memory_manager.cpp +++ b/src/video_core/memory_manager.cpp | |||
| @@ -82,6 +82,7 @@ void MemoryManager::SetEntry(size_t position, MemoryManager::EntryType entry) { | |||
| 82 | } | 82 | } |
| 83 | 83 | ||
| 84 | PTEKind MemoryManager::GetPageKind(GPUVAddr gpu_addr) const { | 84 | PTEKind MemoryManager::GetPageKind(GPUVAddr gpu_addr) const { |
| 85 | std::unique_lock<std::mutex> lock(guard); | ||
| 85 | return kind_map.GetValueAt(gpu_addr); | 86 | return kind_map.GetValueAt(gpu_addr); |
| 86 | } | 87 | } |
| 87 | 88 | ||
| @@ -160,7 +161,10 @@ GPUVAddr MemoryManager::BigPageTableOp(GPUVAddr gpu_addr, [[maybe_unused]] VAddr | |||
| 160 | } | 161 | } |
| 161 | remaining_size -= big_page_size; | 162 | remaining_size -= big_page_size; |
| 162 | } | 163 | } |
| 163 | kind_map.Map(gpu_addr, gpu_addr + size, kind); | 164 | { |
| 165 | std::unique_lock<std::mutex> lock(guard); | ||
| 166 | kind_map.Map(gpu_addr, gpu_addr + size, kind); | ||
| 167 | } | ||
| 164 | return gpu_addr; | 168 | return gpu_addr; |
| 165 | } | 169 | } |
| 166 | 170 | ||
| @@ -553,6 +557,7 @@ size_t MemoryManager::MaxContinuousRange(GPUVAddr gpu_addr, size_t size) const { | |||
| 553 | } | 557 | } |
| 554 | 558 | ||
| 555 | size_t MemoryManager::GetMemoryLayoutSize(GPUVAddr gpu_addr, size_t max_size) const { | 559 | size_t MemoryManager::GetMemoryLayoutSize(GPUVAddr gpu_addr, size_t max_size) const { |
| 560 | std::unique_lock<std::mutex> lock(guard); | ||
| 556 | return kind_map.GetContinuousSizeFrom(gpu_addr); | 561 | return kind_map.GetContinuousSizeFrom(gpu_addr); |
| 557 | } | 562 | } |
| 558 | 563 | ||
| @@ -745,10 +750,10 @@ void MemoryManager::FlushCaching() { | |||
| 745 | return; | 750 | return; |
| 746 | } | 751 | } |
| 747 | accumulator->Callback([this](GPUVAddr addr, size_t size) { | 752 | accumulator->Callback([this](GPUVAddr addr, size_t size) { |
| 748 | GetSubmappedRangeImpl<false>(addr, size, page_stash); | 753 | GetSubmappedRangeImpl<false>(addr, size, page_stash2); |
| 749 | }); | 754 | }); |
| 750 | rasterizer->InnerInvalidation(page_stash); | 755 | rasterizer->InnerInvalidation(page_stash2); |
| 751 | page_stash.clear(); | 756 | page_stash2.clear(); |
| 752 | accumulator->Clear(); | 757 | accumulator->Clear(); |
| 753 | } | 758 | } |
| 754 | 759 | ||
diff --git a/src/video_core/memory_manager.h b/src/video_core/memory_manager.h index fbbe856c4..794535122 100644 --- a/src/video_core/memory_manager.h +++ b/src/video_core/memory_manager.h | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include <atomic> | 6 | #include <atomic> |
| 7 | #include <map> | 7 | #include <map> |
| 8 | #include <mutex> | ||
| 8 | #include <optional> | 9 | #include <optional> |
| 9 | #include <vector> | 10 | #include <vector> |
| 10 | 11 | ||
| @@ -215,6 +216,9 @@ private: | |||
| 215 | 216 | ||
| 216 | std::vector<u64> big_page_continuous; | 217 | std::vector<u64> big_page_continuous; |
| 217 | std::vector<std::pair<VAddr, std::size_t>> page_stash{}; | 218 | std::vector<std::pair<VAddr, std::size_t>> page_stash{}; |
| 219 | std::vector<std::pair<VAddr, std::size_t>> page_stash2{}; | ||
| 220 | |||
| 221 | mutable std::mutex guard; | ||
| 218 | 222 | ||
| 219 | static constexpr size_t continuous_bits = 64; | 223 | static constexpr size_t continuous_bits = 64; |
| 220 | 224 | ||
diff --git a/src/video_core/query_cache.h b/src/video_core/query_cache.h index 8906ba6d8..941de95c1 100644 --- a/src/video_core/query_cache.h +++ b/src/video_core/query_cache.h | |||
| @@ -6,6 +6,7 @@ | |||
| 6 | #include <algorithm> | 6 | #include <algorithm> |
| 7 | #include <array> | 7 | #include <array> |
| 8 | #include <cstring> | 8 | #include <cstring> |
| 9 | #include <functional> | ||
| 9 | #include <iterator> | 10 | #include <iterator> |
| 10 | #include <list> | 11 | #include <list> |
| 11 | #include <memory> | 12 | #include <memory> |
| @@ -17,13 +18,19 @@ | |||
| 17 | 18 | ||
| 18 | #include "common/assert.h" | 19 | #include "common/assert.h" |
| 19 | #include "common/settings.h" | 20 | #include "common/settings.h" |
| 21 | #include "core/memory.h" | ||
| 20 | #include "video_core/control/channel_state_cache.h" | 22 | #include "video_core/control/channel_state_cache.h" |
| 21 | #include "video_core/engines/maxwell_3d.h" | 23 | #include "video_core/engines/maxwell_3d.h" |
| 22 | #include "video_core/memory_manager.h" | 24 | #include "video_core/memory_manager.h" |
| 23 | #include "video_core/rasterizer_interface.h" | 25 | #include "video_core/rasterizer_interface.h" |
| 26 | #include "video_core/texture_cache/slot_vector.h" | ||
| 24 | 27 | ||
| 25 | namespace VideoCommon { | 28 | namespace VideoCommon { |
| 26 | 29 | ||
| 30 | using AsyncJobId = SlotId; | ||
| 31 | |||
| 32 | static constexpr AsyncJobId NULL_ASYNC_JOB_ID{0}; | ||
| 33 | |||
| 27 | template <class QueryCache, class HostCounter> | 34 | template <class QueryCache, class HostCounter> |
| 28 | class CounterStreamBase { | 35 | class CounterStreamBase { |
| 29 | public: | 36 | public: |
| @@ -93,9 +100,13 @@ private: | |||
| 93 | template <class QueryCache, class CachedQuery, class CounterStream, class HostCounter> | 100 | template <class QueryCache, class CachedQuery, class CounterStream, class HostCounter> |
| 94 | class QueryCacheBase : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { | 101 | class QueryCacheBase : public VideoCommon::ChannelSetupCaches<VideoCommon::ChannelInfo> { |
| 95 | public: | 102 | public: |
| 96 | explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_) | 103 | explicit QueryCacheBase(VideoCore::RasterizerInterface& rasterizer_, |
| 97 | : rasterizer{rasterizer_}, streams{{CounterStream{static_cast<QueryCache&>(*this), | 104 | Core::Memory::Memory& cpu_memory_) |
| 98 | VideoCore::QueryType::SamplesPassed}}} {} | 105 | : rasterizer{rasterizer_}, |
| 106 | cpu_memory{cpu_memory_}, streams{{CounterStream{static_cast<QueryCache&>(*this), | ||
| 107 | VideoCore::QueryType::SamplesPassed}}} { | ||
| 108 | (void)slot_async_jobs.insert(); // Null value | ||
| 109 | } | ||
| 99 | 110 | ||
| 100 | void InvalidateRegion(VAddr addr, std::size_t size) { | 111 | void InvalidateRegion(VAddr addr, std::size_t size) { |
| 101 | std::unique_lock lock{mutex}; | 112 | std::unique_lock lock{mutex}; |
| @@ -126,10 +137,15 @@ public: | |||
| 126 | query = Register(type, *cpu_addr, host_ptr, timestamp.has_value()); | 137 | query = Register(type, *cpu_addr, host_ptr, timestamp.has_value()); |
| 127 | } | 138 | } |
| 128 | 139 | ||
| 129 | query->BindCounter(Stream(type).Current(), timestamp); | 140 | auto result = query->BindCounter(Stream(type).Current(), timestamp); |
| 130 | if (Settings::values.use_asynchronous_gpu_emulation.GetValue()) { | 141 | if (result) { |
| 131 | AsyncFlushQuery(*cpu_addr); | 142 | auto async_job_id = query->GetAsyncJob(); |
| 143 | auto& async_job = slot_async_jobs[async_job_id]; | ||
| 144 | async_job.collected = true; | ||
| 145 | async_job.value = *result; | ||
| 146 | query->SetAsyncJob(NULL_ASYNC_JOB_ID); | ||
| 132 | } | 147 | } |
| 148 | AsyncFlushQuery(query, timestamp, lock); | ||
| 133 | } | 149 | } |
| 134 | 150 | ||
| 135 | /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. | 151 | /// Updates counters from GPU state. Expected to be called once per draw, clear or dispatch. |
| @@ -173,15 +189,18 @@ public: | |||
| 173 | } | 189 | } |
| 174 | 190 | ||
| 175 | void CommitAsyncFlushes() { | 191 | void CommitAsyncFlushes() { |
| 192 | std::unique_lock lock{mutex}; | ||
| 176 | committed_flushes.push_back(uncommitted_flushes); | 193 | committed_flushes.push_back(uncommitted_flushes); |
| 177 | uncommitted_flushes.reset(); | 194 | uncommitted_flushes.reset(); |
| 178 | } | 195 | } |
| 179 | 196 | ||
| 180 | bool HasUncommittedFlushes() const { | 197 | bool HasUncommittedFlushes() const { |
| 198 | std::unique_lock lock{mutex}; | ||
| 181 | return uncommitted_flushes != nullptr; | 199 | return uncommitted_flushes != nullptr; |
| 182 | } | 200 | } |
| 183 | 201 | ||
| 184 | bool ShouldWaitAsyncFlushes() const { | 202 | bool ShouldWaitAsyncFlushes() const { |
| 203 | std::unique_lock lock{mutex}; | ||
| 185 | if (committed_flushes.empty()) { | 204 | if (committed_flushes.empty()) { |
| 186 | return false; | 205 | return false; |
| 187 | } | 206 | } |
| @@ -189,6 +208,7 @@ public: | |||
| 189 | } | 208 | } |
| 190 | 209 | ||
| 191 | void PopAsyncFlushes() { | 210 | void PopAsyncFlushes() { |
| 211 | std::unique_lock lock{mutex}; | ||
| 192 | if (committed_flushes.empty()) { | 212 | if (committed_flushes.empty()) { |
| 193 | return; | 213 | return; |
| 194 | } | 214 | } |
| @@ -197,15 +217,25 @@ public: | |||
| 197 | committed_flushes.pop_front(); | 217 | committed_flushes.pop_front(); |
| 198 | return; | 218 | return; |
| 199 | } | 219 | } |
| 200 | for (VAddr query_address : *flush_list) { | 220 | for (AsyncJobId async_job_id : *flush_list) { |
| 201 | FlushAndRemoveRegion(query_address, 4); | 221 | AsyncJob& async_job = slot_async_jobs[async_job_id]; |
| 222 | if (!async_job.collected) { | ||
| 223 | FlushAndRemoveRegion(async_job.query_location, 2, true); | ||
| 224 | } | ||
| 202 | } | 225 | } |
| 203 | committed_flushes.pop_front(); | 226 | committed_flushes.pop_front(); |
| 204 | } | 227 | } |
| 205 | 228 | ||
| 206 | private: | 229 | private: |
| 230 | struct AsyncJob { | ||
| 231 | bool collected = false; | ||
| 232 | u64 value = 0; | ||
| 233 | VAddr query_location = 0; | ||
| 234 | std::optional<u64> timestamp{}; | ||
| 235 | }; | ||
| 236 | |||
| 207 | /// Flushes a memory range to guest memory and removes it from the cache. | 237 | /// Flushes a memory range to guest memory and removes it from the cache. |
| 208 | void FlushAndRemoveRegion(VAddr addr, std::size_t size) { | 238 | void FlushAndRemoveRegion(VAddr addr, std::size_t size, bool async = false) { |
| 209 | const u64 addr_begin = addr; | 239 | const u64 addr_begin = addr; |
| 210 | const u64 addr_end = addr_begin + size; | 240 | const u64 addr_end = addr_begin + size; |
| 211 | const auto in_range = [addr_begin, addr_end](const CachedQuery& query) { | 241 | const auto in_range = [addr_begin, addr_end](const CachedQuery& query) { |
| @@ -226,7 +256,16 @@ private: | |||
| 226 | continue; | 256 | continue; |
| 227 | } | 257 | } |
| 228 | rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); | 258 | rasterizer.UpdatePagesCachedCount(query.GetCpuAddr(), query.SizeInBytes(), -1); |
| 229 | query.Flush(); | 259 | AsyncJobId async_job_id = query.GetAsyncJob(); |
| 260 | auto flush_result = query.Flush(async); | ||
| 261 | if (async_job_id == NULL_ASYNC_JOB_ID) { | ||
| 262 | ASSERT_MSG(false, "This should not be reachable at all"); | ||
| 263 | continue; | ||
| 264 | } | ||
| 265 | AsyncJob& async_job = slot_async_jobs[async_job_id]; | ||
| 266 | async_job.collected = true; | ||
| 267 | async_job.value = flush_result; | ||
| 268 | query.SetAsyncJob(NULL_ASYNC_JOB_ID); | ||
| 230 | } | 269 | } |
| 231 | std::erase_if(contents, in_range); | 270 | std::erase_if(contents, in_range); |
| 232 | } | 271 | } |
| @@ -253,26 +292,60 @@ private: | |||
| 253 | return found != std::end(contents) ? &*found : nullptr; | 292 | return found != std::end(contents) ? &*found : nullptr; |
| 254 | } | 293 | } |
| 255 | 294 | ||
| 256 | void AsyncFlushQuery(VAddr addr) { | 295 | void AsyncFlushQuery(CachedQuery* query, std::optional<u64> timestamp, |
| 257 | if (!uncommitted_flushes) { | 296 | std::unique_lock<std::recursive_mutex>& lock) { |
| 258 | uncommitted_flushes = std::make_shared<std::vector<VAddr>>(); | 297 | const AsyncJobId new_async_job_id = slot_async_jobs.insert(); |
| 298 | { | ||
| 299 | AsyncJob& async_job = slot_async_jobs[new_async_job_id]; | ||
| 300 | query->SetAsyncJob(new_async_job_id); | ||
| 301 | async_job.query_location = query->GetCpuAddr(); | ||
| 302 | async_job.collected = false; | ||
| 303 | |||
| 304 | if (!uncommitted_flushes) { | ||
| 305 | uncommitted_flushes = std::make_shared<std::vector<AsyncJobId>>(); | ||
| 306 | } | ||
| 307 | uncommitted_flushes->push_back(new_async_job_id); | ||
| 259 | } | 308 | } |
| 260 | uncommitted_flushes->push_back(addr); | 309 | lock.unlock(); |
| 310 | std::function<void()> operation([this, new_async_job_id, timestamp] { | ||
| 311 | std::unique_lock local_lock{mutex}; | ||
| 312 | AsyncJob& async_job = slot_async_jobs[new_async_job_id]; | ||
| 313 | u64 value = async_job.value; | ||
| 314 | VAddr address = async_job.query_location; | ||
| 315 | slot_async_jobs.erase(new_async_job_id); | ||
| 316 | local_lock.unlock(); | ||
| 317 | if (timestamp) { | ||
| 318 | u64 timestamp_value = *timestamp; | ||
| 319 | cpu_memory.WriteBlockUnsafe(address + sizeof(u64), ×tamp_value, sizeof(u64)); | ||
| 320 | cpu_memory.WriteBlockUnsafe(address, &value, sizeof(u64)); | ||
| 321 | rasterizer.InvalidateRegion(address, sizeof(u64) * 2, | ||
| 322 | VideoCommon::CacheType::NoQueryCache); | ||
| 323 | } else { | ||
| 324 | u32 small_value = static_cast<u32>(value); | ||
| 325 | cpu_memory.WriteBlockUnsafe(address, &small_value, sizeof(u32)); | ||
| 326 | rasterizer.InvalidateRegion(address, sizeof(u32), | ||
| 327 | VideoCommon::CacheType::NoQueryCache); | ||
| 328 | } | ||
| 329 | }); | ||
| 330 | rasterizer.SyncOperation(std::move(operation)); | ||
| 261 | } | 331 | } |
| 262 | 332 | ||
| 263 | static constexpr std::uintptr_t YUZU_PAGESIZE = 4096; | 333 | static constexpr std::uintptr_t YUZU_PAGESIZE = 4096; |
| 264 | static constexpr unsigned YUZU_PAGEBITS = 12; | 334 | static constexpr unsigned YUZU_PAGEBITS = 12; |
| 265 | 335 | ||
| 336 | SlotVector<AsyncJob> slot_async_jobs; | ||
| 337 | |||
| 266 | VideoCore::RasterizerInterface& rasterizer; | 338 | VideoCore::RasterizerInterface& rasterizer; |
| 339 | Core::Memory::Memory& cpu_memory; | ||
| 267 | 340 | ||
| 268 | std::recursive_mutex mutex; | 341 | mutable std::recursive_mutex mutex; |
| 269 | 342 | ||
| 270 | std::unordered_map<u64, std::vector<CachedQuery>> cached_queries; | 343 | std::unordered_map<u64, std::vector<CachedQuery>> cached_queries; |
| 271 | 344 | ||
| 272 | std::array<CounterStream, VideoCore::NumQueryTypes> streams; | 345 | std::array<CounterStream, VideoCore::NumQueryTypes> streams; |
| 273 | 346 | ||
| 274 | std::shared_ptr<std::vector<VAddr>> uncommitted_flushes{}; | 347 | std::shared_ptr<std::vector<AsyncJobId>> uncommitted_flushes{}; |
| 275 | std::list<std::shared_ptr<std::vector<VAddr>>> committed_flushes; | 348 | std::list<std::shared_ptr<std::vector<AsyncJobId>>> committed_flushes; |
| 276 | }; | 349 | }; |
| 277 | 350 | ||
| 278 | template <class QueryCache, class HostCounter> | 351 | template <class QueryCache, class HostCounter> |
| @@ -291,12 +364,12 @@ public: | |||
| 291 | virtual ~HostCounterBase() = default; | 364 | virtual ~HostCounterBase() = default; |
| 292 | 365 | ||
| 293 | /// Returns the current value of the query. | 366 | /// Returns the current value of the query. |
| 294 | u64 Query() { | 367 | u64 Query(bool async = false) { |
| 295 | if (result) { | 368 | if (result) { |
| 296 | return *result; | 369 | return *result; |
| 297 | } | 370 | } |
| 298 | 371 | ||
| 299 | u64 value = BlockingQuery() + base_result; | 372 | u64 value = BlockingQuery(async) + base_result; |
| 300 | if (dependency) { | 373 | if (dependency) { |
| 301 | value += dependency->Query(); | 374 | value += dependency->Query(); |
| 302 | dependency = nullptr; | 375 | dependency = nullptr; |
| @@ -317,7 +390,7 @@ public: | |||
| 317 | 390 | ||
| 318 | protected: | 391 | protected: |
| 319 | /// Returns the value of query from the backend API blocking as needed. | 392 | /// Returns the value of query from the backend API blocking as needed. |
| 320 | virtual u64 BlockingQuery() const = 0; | 393 | virtual u64 BlockingQuery(bool async = false) const = 0; |
| 321 | 394 | ||
| 322 | private: | 395 | private: |
| 323 | std::shared_ptr<HostCounter> dependency; ///< Counter to add to this value. | 396 | std::shared_ptr<HostCounter> dependency; ///< Counter to add to this value. |
| @@ -340,26 +413,33 @@ public: | |||
| 340 | CachedQueryBase& operator=(const CachedQueryBase&) = delete; | 413 | CachedQueryBase& operator=(const CachedQueryBase&) = delete; |
| 341 | 414 | ||
| 342 | /// Flushes the query to guest memory. | 415 | /// Flushes the query to guest memory. |
| 343 | virtual void Flush() { | 416 | virtual u64 Flush(bool async = false) { |
| 344 | // When counter is nullptr it means that it's just been reset. We are supposed to write a | 417 | // When counter is nullptr it means that it's just been reset. We are supposed to write a |
| 345 | // zero in these cases. | 418 | // zero in these cases. |
| 346 | const u64 value = counter ? counter->Query() : 0; | 419 | const u64 value = counter ? counter->Query(async) : 0; |
| 420 | if (async) { | ||
| 421 | return value; | ||
| 422 | } | ||
| 347 | std::memcpy(host_ptr, &value, sizeof(u64)); | 423 | std::memcpy(host_ptr, &value, sizeof(u64)); |
| 348 | 424 | ||
| 349 | if (timestamp) { | 425 | if (timestamp) { |
| 350 | std::memcpy(host_ptr + TIMESTAMP_OFFSET, &*timestamp, sizeof(u64)); | 426 | std::memcpy(host_ptr + TIMESTAMP_OFFSET, &*timestamp, sizeof(u64)); |
| 351 | } | 427 | } |
| 428 | return value; | ||
| 352 | } | 429 | } |
| 353 | 430 | ||
| 354 | /// Binds a counter to this query. | 431 | /// Binds a counter to this query. |
| 355 | void BindCounter(std::shared_ptr<HostCounter> counter_, std::optional<u64> timestamp_) { | 432 | std::optional<u64> BindCounter(std::shared_ptr<HostCounter> counter_, |
| 433 | std::optional<u64> timestamp_) { | ||
| 434 | std::optional<u64> result{}; | ||
| 356 | if (counter) { | 435 | if (counter) { |
| 357 | // If there's an old counter set it means the query is being rewritten by the game. | 436 | // If there's an old counter set it means the query is being rewritten by the game. |
| 358 | // To avoid losing the data forever, flush here. | 437 | // To avoid losing the data forever, flush here. |
| 359 | Flush(); | 438 | result = std::make_optional(Flush()); |
| 360 | } | 439 | } |
| 361 | counter = std::move(counter_); | 440 | counter = std::move(counter_); |
| 362 | timestamp = timestamp_; | 441 | timestamp = timestamp_; |
| 442 | return result; | ||
| 363 | } | 443 | } |
| 364 | 444 | ||
| 365 | VAddr GetCpuAddr() const noexcept { | 445 | VAddr GetCpuAddr() const noexcept { |
| @@ -374,6 +454,14 @@ public: | |||
| 374 | return with_timestamp ? LARGE_QUERY_SIZE : SMALL_QUERY_SIZE; | 454 | return with_timestamp ? LARGE_QUERY_SIZE : SMALL_QUERY_SIZE; |
| 375 | } | 455 | } |
| 376 | 456 | ||
| 457 | void SetAsyncJob(AsyncJobId assigned_async_job_) { | ||
| 458 | assigned_async_job = assigned_async_job_; | ||
| 459 | } | ||
| 460 | |||
| 461 | AsyncJobId GetAsyncJob() const { | ||
| 462 | return assigned_async_job; | ||
| 463 | } | ||
| 464 | |||
| 377 | protected: | 465 | protected: |
| 378 | /// Returns true when querying the counter may potentially block. | 466 | /// Returns true when querying the counter may potentially block. |
| 379 | bool WaitPending() const noexcept { | 467 | bool WaitPending() const noexcept { |
| @@ -389,6 +477,7 @@ private: | |||
| 389 | u8* host_ptr; ///< Writable host pointer. | 477 | u8* host_ptr; ///< Writable host pointer. |
| 390 | std::shared_ptr<HostCounter> counter; ///< Host counter to query, owns the dependency tree. | 478 | std::shared_ptr<HostCounter> counter; ///< Host counter to query, owns the dependency tree. |
| 391 | std::optional<u64> timestamp; ///< Timestamp to flush to guest memory. | 479 | std::optional<u64> timestamp; ///< Timestamp to flush to guest memory. |
| 480 | AsyncJobId assigned_async_job; | ||
| 392 | }; | 481 | }; |
| 393 | 482 | ||
| 394 | } // namespace VideoCommon | 483 | } // namespace VideoCommon |
diff --git a/src/video_core/renderer_opengl/gl_fence_manager.h b/src/video_core/renderer_opengl/gl_fence_manager.h index f1446e732..e21b19dcc 100644 --- a/src/video_core/renderer_opengl/gl_fence_manager.h +++ b/src/video_core/renderer_opengl/gl_fence_manager.h | |||
| @@ -30,7 +30,17 @@ private: | |||
| 30 | }; | 30 | }; |
| 31 | 31 | ||
| 32 | using Fence = std::shared_ptr<GLInnerFence>; | 32 | using Fence = std::shared_ptr<GLInnerFence>; |
| 33 | using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCache, BufferCache, QueryCache>; | 33 | |
| 34 | struct FenceManagerParams { | ||
| 35 | using FenceType = Fence; | ||
| 36 | using BufferCacheType = BufferCache; | ||
| 37 | using TextureCacheType = TextureCache; | ||
| 38 | using QueryCacheType = QueryCache; | ||
| 39 | |||
| 40 | static constexpr bool HAS_ASYNC_CHECK = false; | ||
| 41 | }; | ||
| 42 | |||
| 43 | using GenericFenceManager = VideoCommon::FenceManager<FenceManagerParams>; | ||
| 34 | 44 | ||
| 35 | class FenceManagerOpenGL final : public GenericFenceManager { | 45 | class FenceManagerOpenGL final : public GenericFenceManager { |
| 36 | public: | 46 | public: |
diff --git a/src/video_core/renderer_opengl/gl_query_cache.cpp b/src/video_core/renderer_opengl/gl_query_cache.cpp index 5070db441..99d7347f5 100644 --- a/src/video_core/renderer_opengl/gl_query_cache.cpp +++ b/src/video_core/renderer_opengl/gl_query_cache.cpp | |||
| @@ -26,8 +26,8 @@ constexpr GLenum GetTarget(VideoCore::QueryType type) { | |||
| 26 | 26 | ||
| 27 | } // Anonymous namespace | 27 | } // Anonymous namespace |
| 28 | 28 | ||
| 29 | QueryCache::QueryCache(RasterizerOpenGL& rasterizer_) | 29 | QueryCache::QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_) |
| 30 | : QueryCacheBase(rasterizer_), gl_rasterizer{rasterizer_} {} | 30 | : QueryCacheBase(rasterizer_, cpu_memory_), gl_rasterizer{rasterizer_} {} |
| 31 | 31 | ||
| 32 | QueryCache::~QueryCache() = default; | 32 | QueryCache::~QueryCache() = default; |
| 33 | 33 | ||
| @@ -74,7 +74,7 @@ void HostCounter::EndQuery() { | |||
| 74 | glEndQuery(GetTarget(type)); | 74 | glEndQuery(GetTarget(type)); |
| 75 | } | 75 | } |
| 76 | 76 | ||
| 77 | u64 HostCounter::BlockingQuery() const { | 77 | u64 HostCounter::BlockingQuery([[maybe_unused]] bool async) const { |
| 78 | GLint64 value; | 78 | GLint64 value; |
| 79 | glGetQueryObjecti64v(query.handle, GL_QUERY_RESULT, &value); | 79 | glGetQueryObjecti64v(query.handle, GL_QUERY_RESULT, &value); |
| 80 | return static_cast<u64>(value); | 80 | return static_cast<u64>(value); |
| @@ -96,7 +96,7 @@ CachedQuery& CachedQuery::operator=(CachedQuery&& rhs) noexcept { | |||
| 96 | return *this; | 96 | return *this; |
| 97 | } | 97 | } |
| 98 | 98 | ||
| 99 | void CachedQuery::Flush() { | 99 | u64 CachedQuery::Flush([[maybe_unused]] bool async) { |
| 100 | // Waiting for a query while another query of the same target is enabled locks Nvidia's driver. | 100 | // Waiting for a query while another query of the same target is enabled locks Nvidia's driver. |
| 101 | // To avoid this disable and re-enable keeping the dependency stream. | 101 | // To avoid this disable and re-enable keeping the dependency stream. |
| 102 | // But we only have to do this if we have pending waits to be done. | 102 | // But we only have to do this if we have pending waits to be done. |
| @@ -106,11 +106,13 @@ void CachedQuery::Flush() { | |||
| 106 | stream.Update(false); | 106 | stream.Update(false); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | VideoCommon::CachedQueryBase<HostCounter>::Flush(); | 109 | auto result = VideoCommon::CachedQueryBase<HostCounter>::Flush(); |
| 110 | 110 | ||
| 111 | if (slice_counter) { | 111 | if (slice_counter) { |
| 112 | stream.Update(true); | 112 | stream.Update(true); |
| 113 | } | 113 | } |
| 114 | |||
| 115 | return result; | ||
| 114 | } | 116 | } |
| 115 | 117 | ||
| 116 | } // namespace OpenGL | 118 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_query_cache.h b/src/video_core/renderer_opengl/gl_query_cache.h index 14ce59990..872513f22 100644 --- a/src/video_core/renderer_opengl/gl_query_cache.h +++ b/src/video_core/renderer_opengl/gl_query_cache.h | |||
| @@ -28,7 +28,7 @@ using CounterStream = VideoCommon::CounterStreamBase<QueryCache, HostCounter>; | |||
| 28 | class QueryCache final | 28 | class QueryCache final |
| 29 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { | 29 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { |
| 30 | public: | 30 | public: |
| 31 | explicit QueryCache(RasterizerOpenGL& rasterizer_); | 31 | explicit QueryCache(RasterizerOpenGL& rasterizer_, Core::Memory::Memory& cpu_memory_); |
| 32 | ~QueryCache(); | 32 | ~QueryCache(); |
| 33 | 33 | ||
| 34 | OGLQuery AllocateQuery(VideoCore::QueryType type); | 34 | OGLQuery AllocateQuery(VideoCore::QueryType type); |
| @@ -51,7 +51,7 @@ public: | |||
| 51 | void EndQuery(); | 51 | void EndQuery(); |
| 52 | 52 | ||
| 53 | private: | 53 | private: |
| 54 | u64 BlockingQuery() const override; | 54 | u64 BlockingQuery(bool async = false) const override; |
| 55 | 55 | ||
| 56 | QueryCache& cache; | 56 | QueryCache& cache; |
| 57 | const VideoCore::QueryType type; | 57 | const VideoCore::QueryType type; |
| @@ -70,7 +70,7 @@ public: | |||
| 70 | CachedQuery(const CachedQuery&) = delete; | 70 | CachedQuery(const CachedQuery&) = delete; |
| 71 | CachedQuery& operator=(const CachedQuery&) = delete; | 71 | CachedQuery& operator=(const CachedQuery&) = delete; |
| 72 | 72 | ||
| 73 | void Flush() override; | 73 | u64 Flush(bool async = false) override; |
| 74 | 74 | ||
| 75 | private: | 75 | private: |
| 76 | QueryCache* cache; | 76 | QueryCache* cache; |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 4993d4709..0089b4b27 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -63,7 +63,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 63 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), | 63 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), |
| 64 | shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, | 64 | shader_cache(*this, emu_window_, device, texture_cache, buffer_cache, program_manager, |
| 65 | state_tracker, gpu.ShaderNotify()), | 65 | state_tracker, gpu.ShaderNotify()), |
| 66 | query_cache(*this), accelerate_dma(buffer_cache, texture_cache), | 66 | query_cache(*this, cpu_memory_), accelerate_dma(buffer_cache, texture_cache), |
| 67 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), | 67 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), |
| 68 | blit_image(program_manager_) {} | 68 | blit_image(program_manager_) {} |
| 69 | 69 | ||
diff --git a/src/video_core/renderer_opengl/gl_texture_cache.cpp b/src/video_core/renderer_opengl/gl_texture_cache.cpp index 032a8ebc5..47cccd0e5 100644 --- a/src/video_core/renderer_opengl/gl_texture_cache.cpp +++ b/src/video_core/renderer_opengl/gl_texture_cache.cpp | |||
| @@ -861,9 +861,12 @@ GLuint Image::StorageHandle() noexcept { | |||
| 861 | case PixelFormat::ASTC_2D_8X5_SRGB: | 861 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| 862 | case PixelFormat::ASTC_2D_5X4_SRGB: | 862 | case PixelFormat::ASTC_2D_5X4_SRGB: |
| 863 | case PixelFormat::ASTC_2D_5X5_SRGB: | 863 | case PixelFormat::ASTC_2D_5X5_SRGB: |
| 864 | case PixelFormat::ASTC_2D_10X5_SRGB: | ||
| 865 | case PixelFormat::ASTC_2D_10X6_SRGB: | ||
| 864 | case PixelFormat::ASTC_2D_10X8_SRGB: | 866 | case PixelFormat::ASTC_2D_10X8_SRGB: |
| 865 | case PixelFormat::ASTC_2D_6X6_SRGB: | 867 | case PixelFormat::ASTC_2D_6X6_SRGB: |
| 866 | case PixelFormat::ASTC_2D_10X10_SRGB: | 868 | case PixelFormat::ASTC_2D_10X10_SRGB: |
| 869 | case PixelFormat::ASTC_2D_12X10_SRGB: | ||
| 867 | case PixelFormat::ASTC_2D_12X12_SRGB: | 870 | case PixelFormat::ASTC_2D_12X12_SRGB: |
| 868 | case PixelFormat::ASTC_2D_8X6_SRGB: | 871 | case PixelFormat::ASTC_2D_8X6_SRGB: |
| 869 | case PixelFormat::ASTC_2D_6X5_SRGB: | 872 | case PixelFormat::ASTC_2D_6X5_SRGB: |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index ef1190e1f..c7dc7e0a1 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -100,10 +100,13 @@ constexpr std::array<FormatTuple, VideoCore::Surface::MaxPixelFormat> FORMAT_TAB | |||
| 100 | {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6_UNORM | 100 | {GL_COMPRESSED_RGBA_ASTC_6x6_KHR}, // ASTC_2D_6X6_UNORM |
| 101 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB | 101 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_6x6_KHR}, // ASTC_2D_6X6_SRGB |
| 102 | {GL_COMPRESSED_RGBA_ASTC_10x6_KHR}, // ASTC_2D_10X6_UNORM | 102 | {GL_COMPRESSED_RGBA_ASTC_10x6_KHR}, // ASTC_2D_10X6_UNORM |
| 103 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x6_KHR}, // ASTC_2D_10X6_SRGB | ||
| 103 | {GL_COMPRESSED_RGBA_ASTC_10x5_KHR}, // ASTC_2D_10X5_UNORM | 104 | {GL_COMPRESSED_RGBA_ASTC_10x5_KHR}, // ASTC_2D_10X5_UNORM |
| 104 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR}, // ASTC_2D_10X5_SRGB | 105 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x5_KHR}, // ASTC_2D_10X5_SRGB |
| 105 | {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10_UNORM | 106 | {GL_COMPRESSED_RGBA_ASTC_10x10_KHR}, // ASTC_2D_10X10_UNORM |
| 106 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB | 107 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_10x10_KHR}, // ASTC_2D_10X10_SRGB |
| 108 | {GL_COMPRESSED_RGBA_ASTC_12x10_KHR}, // ASTC_2D_12X10_UNORM | ||
| 109 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x10_KHR}, // ASTC_2D_12X10_SRGB | ||
| 107 | {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12_UNORM | 110 | {GL_COMPRESSED_RGBA_ASTC_12x12_KHR}, // ASTC_2D_12X12_UNORM |
| 108 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB | 111 | {GL_COMPRESSED_SRGB8_ALPHA8_ASTC_12x12_KHR}, // ASTC_2D_12X12_SRGB |
| 109 | {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6_UNORM | 112 | {GL_COMPRESSED_RGBA_ASTC_8x6_KHR}, // ASTC_2D_8X6_UNORM |
diff --git a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp index 5dce51be8..8853cf0f7 100644 --- a/src/video_core/renderer_vulkan/maxwell_to_vk.cpp +++ b/src/video_core/renderer_vulkan/maxwell_to_vk.cpp | |||
| @@ -197,10 +197,13 @@ struct FormatTuple { | |||
| 197 | {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6_UNORM | 197 | {VK_FORMAT_ASTC_6x6_UNORM_BLOCK}, // ASTC_2D_6X6_UNORM |
| 198 | {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB | 198 | {VK_FORMAT_ASTC_6x6_SRGB_BLOCK}, // ASTC_2D_6X6_SRGB |
| 199 | {VK_FORMAT_ASTC_10x6_UNORM_BLOCK}, // ASTC_2D_10X6_UNORM | 199 | {VK_FORMAT_ASTC_10x6_UNORM_BLOCK}, // ASTC_2D_10X6_UNORM |
| 200 | {VK_FORMAT_ASTC_10x6_SRGB_BLOCK}, // ASTC_2D_10X6_SRGB | ||
| 200 | {VK_FORMAT_ASTC_10x5_UNORM_BLOCK}, // ASTC_2D_10X5_UNORM | 201 | {VK_FORMAT_ASTC_10x5_UNORM_BLOCK}, // ASTC_2D_10X5_UNORM |
| 201 | {VK_FORMAT_ASTC_10x5_SRGB_BLOCK}, // ASTC_2D_10X5_SRGB | 202 | {VK_FORMAT_ASTC_10x5_SRGB_BLOCK}, // ASTC_2D_10X5_SRGB |
| 202 | {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10_UNORM | 203 | {VK_FORMAT_ASTC_10x10_UNORM_BLOCK}, // ASTC_2D_10X10_UNORM |
| 203 | {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB | 204 | {VK_FORMAT_ASTC_10x10_SRGB_BLOCK}, // ASTC_2D_10X10_SRGB |
| 205 | {VK_FORMAT_ASTC_12x10_UNORM_BLOCK}, // ASTC_2D_12X10_UNORM | ||
| 206 | {VK_FORMAT_ASTC_12x10_SRGB_BLOCK}, // ASTC_2D_12X10_SRGB | ||
| 204 | {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12_UNORM | 207 | {VK_FORMAT_ASTC_12x12_UNORM_BLOCK}, // ASTC_2D_12X12_UNORM |
| 205 | {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB | 208 | {VK_FORMAT_ASTC_12x12_SRGB_BLOCK}, // ASTC_2D_12X12_SRGB |
| 206 | {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6_UNORM | 209 | {VK_FORMAT_ASTC_8x6_UNORM_BLOCK}, // ASTC_2D_8X6_UNORM |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 69dc76180..908625c66 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -134,7 +134,7 @@ void RendererVulkan::SwapBuffers(const Tegra::FramebufferConfig* framebuffer) { | |||
| 134 | Frame* frame = present_manager.GetRenderFrame(); | 134 | Frame* frame = present_manager.GetRenderFrame(); |
| 135 | blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb); | 135 | blit_screen.DrawToSwapchain(frame, *framebuffer, use_accelerated, is_srgb); |
| 136 | scheduler.Flush(*frame->render_ready); | 136 | scheduler.Flush(*frame->render_ready); |
| 137 | scheduler.Record([this, frame](vk::CommandBuffer) { present_manager.PushFrame(frame); }); | 137 | present_manager.Present(frame); |
| 138 | 138 | ||
| 139 | gpu.RendererFrameEndNotify(); | 139 | gpu.RendererFrameEndNotify(); |
| 140 | rasterizer.TickFrame(); | 140 | rasterizer.TickFrame(); |
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.cpp b/src/video_core/renderer_vulkan/vk_fence_manager.cpp index 0214b103a..fad9e3832 100644 --- a/src/video_core/renderer_vulkan/vk_fence_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_fence_manager.cpp | |||
| @@ -5,6 +5,7 @@ | |||
| 5 | 5 | ||
| 6 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" | 6 | #include "video_core/renderer_vulkan/vk_buffer_cache.h" |
| 7 | #include "video_core/renderer_vulkan/vk_fence_manager.h" | 7 | #include "video_core/renderer_vulkan/vk_fence_manager.h" |
| 8 | #include "video_core/renderer_vulkan/vk_query_cache.h" | ||
| 8 | #include "video_core/renderer_vulkan/vk_scheduler.h" | 9 | #include "video_core/renderer_vulkan/vk_scheduler.h" |
| 9 | #include "video_core/renderer_vulkan/vk_texture_cache.h" | 10 | #include "video_core/renderer_vulkan/vk_texture_cache.h" |
| 10 | #include "video_core/vulkan_common/vulkan_device.h" | 11 | #include "video_core/vulkan_common/vulkan_device.h" |
diff --git a/src/video_core/renderer_vulkan/vk_fence_manager.h b/src/video_core/renderer_vulkan/vk_fence_manager.h index 7fe2afcd9..145359d4e 100644 --- a/src/video_core/renderer_vulkan/vk_fence_manager.h +++ b/src/video_core/renderer_vulkan/vk_fence_manager.h | |||
| @@ -40,7 +40,16 @@ private: | |||
| 40 | }; | 40 | }; |
| 41 | using Fence = std::shared_ptr<InnerFence>; | 41 | using Fence = std::shared_ptr<InnerFence>; |
| 42 | 42 | ||
| 43 | using GenericFenceManager = VideoCommon::FenceManager<Fence, TextureCache, BufferCache, QueryCache>; | 43 | struct FenceManagerParams { |
| 44 | using FenceType = Fence; | ||
| 45 | using BufferCacheType = BufferCache; | ||
| 46 | using TextureCacheType = TextureCache; | ||
| 47 | using QueryCacheType = QueryCache; | ||
| 48 | |||
| 49 | static constexpr bool HAS_ASYNC_CHECK = true; | ||
| 50 | }; | ||
| 51 | |||
| 52 | using GenericFenceManager = VideoCommon::FenceManager<FenceManagerParams>; | ||
| 44 | 53 | ||
| 45 | class FenceManager final : public GenericFenceManager { | 54 | class FenceManager final : public GenericFenceManager { |
| 46 | public: | 55 | public: |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.cpp b/src/video_core/renderer_vulkan/vk_present_manager.cpp index a137c66f2..c49583013 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.cpp +++ b/src/video_core/renderer_vulkan/vk_present_manager.cpp | |||
| @@ -153,16 +153,19 @@ Frame* PresentManager::GetRenderFrame() { | |||
| 153 | return frame; | 153 | return frame; |
| 154 | } | 154 | } |
| 155 | 155 | ||
| 156 | void PresentManager::PushFrame(Frame* frame) { | 156 | void PresentManager::Present(Frame* frame) { |
| 157 | if (!use_present_thread) { | 157 | if (!use_present_thread) { |
| 158 | scheduler.WaitWorker(); | ||
| 158 | CopyToSwapchain(frame); | 159 | CopyToSwapchain(frame); |
| 159 | free_queue.push(frame); | 160 | free_queue.push(frame); |
| 160 | return; | 161 | return; |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | std::unique_lock lock{queue_mutex}; | 164 | scheduler.Record([this, frame](vk::CommandBuffer) { |
| 164 | present_queue.push(frame); | 165 | std::unique_lock lock{queue_mutex}; |
| 165 | frame_cv.notify_one(); | 166 | present_queue.push(frame); |
| 167 | frame_cv.notify_one(); | ||
| 168 | }); | ||
| 166 | } | 169 | } |
| 167 | 170 | ||
| 168 | void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, | 171 | void PresentManager::RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, |
diff --git a/src/video_core/renderer_vulkan/vk_present_manager.h b/src/video_core/renderer_vulkan/vk_present_manager.h index 9885fd7c6..420a775e2 100644 --- a/src/video_core/renderer_vulkan/vk_present_manager.h +++ b/src/video_core/renderer_vulkan/vk_present_manager.h | |||
| @@ -45,7 +45,7 @@ public: | |||
| 45 | Frame* GetRenderFrame(); | 45 | Frame* GetRenderFrame(); |
| 46 | 46 | ||
| 47 | /// Pushes a frame for presentation | 47 | /// Pushes a frame for presentation |
| 48 | void PushFrame(Frame* frame); | 48 | void Present(Frame* frame); |
| 49 | 49 | ||
| 50 | /// Recreates the present frame to match the provided parameters | 50 | /// Recreates the present frame to match the provided parameters |
| 51 | void RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, | 51 | void RecreateFrame(Frame* frame, u32 width, u32 height, bool is_srgb, |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.cpp b/src/video_core/renderer_vulkan/vk_query_cache.cpp index 929c8ece6..d67490449 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_query_cache.cpp | |||
| @@ -66,9 +66,10 @@ void QueryPool::Reserve(std::pair<VkQueryPool, u32> query) { | |||
| 66 | } | 66 | } |
| 67 | } | 67 | } |
| 68 | 68 | ||
| 69 | QueryCache::QueryCache(VideoCore::RasterizerInterface& rasterizer_, const Device& device_, | 69 | QueryCache::QueryCache(VideoCore::RasterizerInterface& rasterizer_, |
| 70 | Core::Memory::Memory& cpu_memory_, const Device& device_, | ||
| 70 | Scheduler& scheduler_) | 71 | Scheduler& scheduler_) |
| 71 | : QueryCacheBase{rasterizer_}, device{device_}, scheduler{scheduler_}, | 72 | : QueryCacheBase{rasterizer_, cpu_memory_}, device{device_}, scheduler{scheduler_}, |
| 72 | query_pools{ | 73 | query_pools{ |
| 73 | QueryPool{device_, scheduler_, QueryType::SamplesPassed}, | 74 | QueryPool{device_, scheduler_, QueryType::SamplesPassed}, |
| 74 | } {} | 75 | } {} |
| @@ -98,8 +99,10 @@ HostCounter::HostCounter(QueryCache& cache_, std::shared_ptr<HostCounter> depend | |||
| 98 | query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { | 99 | query{cache_.AllocateQuery(type_)}, tick{cache_.GetScheduler().CurrentTick()} { |
| 99 | const vk::Device* logical = &cache.GetDevice().GetLogical(); | 100 | const vk::Device* logical = &cache.GetDevice().GetLogical(); |
| 100 | cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { | 101 | cache.GetScheduler().Record([logical, query = query](vk::CommandBuffer cmdbuf) { |
| 102 | const bool use_precise = Settings::IsGPULevelHigh(); | ||
| 101 | logical->ResetQueryPool(query.first, query.second, 1); | 103 | logical->ResetQueryPool(query.first, query.second, 1); |
| 102 | cmdbuf.BeginQuery(query.first, query.second, VK_QUERY_CONTROL_PRECISE_BIT); | 104 | cmdbuf.BeginQuery(query.first, query.second, |
| 105 | use_precise ? VK_QUERY_CONTROL_PRECISE_BIT : 0); | ||
| 103 | }); | 106 | }); |
| 104 | } | 107 | } |
| 105 | 108 | ||
| @@ -112,8 +115,10 @@ void HostCounter::EndQuery() { | |||
| 112 | [query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); }); | 115 | [query = query](vk::CommandBuffer cmdbuf) { cmdbuf.EndQuery(query.first, query.second); }); |
| 113 | } | 116 | } |
| 114 | 117 | ||
| 115 | u64 HostCounter::BlockingQuery() const { | 118 | u64 HostCounter::BlockingQuery(bool async) const { |
| 116 | cache.GetScheduler().Wait(tick); | 119 | if (!async) { |
| 120 | cache.GetScheduler().Wait(tick); | ||
| 121 | } | ||
| 117 | u64 data; | 122 | u64 data; |
| 118 | const VkResult query_result = cache.GetDevice().GetLogical().GetQueryResults( | 123 | const VkResult query_result = cache.GetDevice().GetLogical().GetQueryResults( |
| 119 | query.first, query.second, 1, sizeof(data), &data, sizeof(data), | 124 | query.first, query.second, 1, sizeof(data), &data, sizeof(data), |
diff --git a/src/video_core/renderer_vulkan/vk_query_cache.h b/src/video_core/renderer_vulkan/vk_query_cache.h index 26762ee09..c1b9552eb 100644 --- a/src/video_core/renderer_vulkan/vk_query_cache.h +++ b/src/video_core/renderer_vulkan/vk_query_cache.h | |||
| @@ -52,7 +52,8 @@ private: | |||
| 52 | class QueryCache final | 52 | class QueryCache final |
| 53 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { | 53 | : public VideoCommon::QueryCacheBase<QueryCache, CachedQuery, CounterStream, HostCounter> { |
| 54 | public: | 54 | public: |
| 55 | explicit QueryCache(VideoCore::RasterizerInterface& rasterizer_, const Device& device_, | 55 | explicit QueryCache(VideoCore::RasterizerInterface& rasterizer_, |
| 56 | Core::Memory::Memory& cpu_memory_, const Device& device_, | ||
| 56 | Scheduler& scheduler_); | 57 | Scheduler& scheduler_); |
| 57 | ~QueryCache(); | 58 | ~QueryCache(); |
| 58 | 59 | ||
| @@ -83,7 +84,7 @@ public: | |||
| 83 | void EndQuery(); | 84 | void EndQuery(); |
| 84 | 85 | ||
| 85 | private: | 86 | private: |
| 86 | u64 BlockingQuery() const override; | 87 | u64 BlockingQuery(bool async = false) const override; |
| 87 | 88 | ||
| 88 | QueryCache& cache; | 89 | QueryCache& cache; |
| 89 | const VideoCore::QueryType type; | 90 | const VideoCore::QueryType type; |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index 2559a3aa7..d1489fc95 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -172,7 +172,8 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 172 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), | 172 | buffer_cache(*this, cpu_memory_, buffer_cache_runtime), |
| 173 | pipeline_cache(*this, device, scheduler, descriptor_pool, update_descriptor_queue, | 173 | pipeline_cache(*this, device, scheduler, descriptor_pool, update_descriptor_queue, |
| 174 | render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), | 174 | render_pass_cache, buffer_cache, texture_cache, gpu.ShaderNotify()), |
| 175 | query_cache{*this, device, scheduler}, accelerate_dma(buffer_cache, texture_cache, scheduler), | 175 | query_cache{*this, cpu_memory_, device, scheduler}, |
| 176 | accelerate_dma(buffer_cache, texture_cache, scheduler), | ||
| 176 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), | 177 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), |
| 177 | wfi_event(device.GetLogical().CreateEvent()) { | 178 | wfi_event(device.GetLogical().CreateEvent()) { |
| 178 | scheduler.SetQueryCache(query_cache); | 179 | scheduler.SetQueryCache(query_cache); |
| @@ -675,7 +676,8 @@ bool RasterizerVulkan::AccelerateConditionalRendering() { | |||
| 675 | const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()}; | 676 | const GPUVAddr condition_address{maxwell3d->regs.render_enable.Address()}; |
| 676 | Maxwell::ReportSemaphore::Compare cmp; | 677 | Maxwell::ReportSemaphore::Compare cmp; |
| 677 | if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp), | 678 | if (gpu_memory->IsMemoryDirty(condition_address, sizeof(cmp), |
| 678 | VideoCommon::CacheType::BufferCache)) { | 679 | VideoCommon::CacheType::BufferCache | |
| 680 | VideoCommon::CacheType::QueryCache)) { | ||
| 679 | return true; | 681 | return true; |
| 680 | } | 682 | } |
| 681 | return false; | 683 | return false; |
diff --git a/src/video_core/shader_cache.cpp b/src/video_core/shader_cache.cpp index d9482371b..c5213875b 100644 --- a/src/video_core/shader_cache.cpp +++ b/src/video_core/shader_cache.cpp | |||
| @@ -228,14 +228,14 @@ const ShaderInfo* ShaderCache::MakeShaderInfo(GenericEnvironment& env, VAddr cpu | |||
| 228 | auto info = std::make_unique<ShaderInfo>(); | 228 | auto info = std::make_unique<ShaderInfo>(); |
| 229 | if (const std::optional<u64> cached_hash{env.Analyze()}) { | 229 | if (const std::optional<u64> cached_hash{env.Analyze()}) { |
| 230 | info->unique_hash = *cached_hash; | 230 | info->unique_hash = *cached_hash; |
| 231 | info->size_bytes = env.CachedSize(); | 231 | info->size_bytes = env.CachedSizeBytes(); |
| 232 | } else { | 232 | } else { |
| 233 | // Slow path, not really hit on commercial games | 233 | // Slow path, not really hit on commercial games |
| 234 | // Build a control flow graph to get the real shader size | 234 | // Build a control flow graph to get the real shader size |
| 235 | Shader::ObjectPool<Shader::Maxwell::Flow::Block> flow_block; | 235 | Shader::ObjectPool<Shader::Maxwell::Flow::Block> flow_block; |
| 236 | Shader::Maxwell::Flow::CFG cfg{env, flow_block, env.StartAddress()}; | 236 | Shader::Maxwell::Flow::CFG cfg{env, flow_block, env.StartAddress()}; |
| 237 | info->unique_hash = env.CalculateHash(); | 237 | info->unique_hash = env.CalculateHash(); |
| 238 | info->size_bytes = env.ReadSize(); | 238 | info->size_bytes = env.ReadSizeBytes(); |
| 239 | } | 239 | } |
| 240 | const size_t size_bytes{info->size_bytes}; | 240 | const size_t size_bytes{info->size_bytes}; |
| 241 | const ShaderInfo* const result{info.get()}; | 241 | const ShaderInfo* const result{info.get()}; |
diff --git a/src/video_core/shader_environment.cpp b/src/video_core/shader_environment.cpp index 574760f80..c7cb56243 100644 --- a/src/video_core/shader_environment.cpp +++ b/src/video_core/shader_environment.cpp | |||
| @@ -170,15 +170,19 @@ std::optional<u64> GenericEnvironment::Analyze() { | |||
| 170 | void GenericEnvironment::SetCachedSize(size_t size_bytes) { | 170 | void GenericEnvironment::SetCachedSize(size_t size_bytes) { |
| 171 | cached_lowest = start_address; | 171 | cached_lowest = start_address; |
| 172 | cached_highest = start_address + static_cast<u32>(size_bytes); | 172 | cached_highest = start_address + static_cast<u32>(size_bytes); |
| 173 | code.resize(CachedSize()); | 173 | code.resize(CachedSizeWords()); |
| 174 | gpu_memory->ReadBlock(program_base + cached_lowest, code.data(), code.size() * sizeof(u64)); | 174 | gpu_memory->ReadBlock(program_base + cached_lowest, code.data(), code.size() * sizeof(u64)); |
| 175 | } | 175 | } |
| 176 | 176 | ||
| 177 | size_t GenericEnvironment::CachedSize() const noexcept { | 177 | size_t GenericEnvironment::CachedSizeWords() const noexcept { |
| 178 | return cached_highest - cached_lowest + INST_SIZE; | 178 | return CachedSizeBytes() / INST_SIZE; |
| 179 | } | 179 | } |
| 180 | 180 | ||
| 181 | size_t GenericEnvironment::ReadSize() const noexcept { | 181 | size_t GenericEnvironment::CachedSizeBytes() const noexcept { |
| 182 | return static_cast<size_t>(cached_highest) - cached_lowest + INST_SIZE; | ||
| 183 | } | ||
| 184 | |||
| 185 | size_t GenericEnvironment::ReadSizeBytes() const noexcept { | ||
| 182 | return read_highest - read_lowest + INST_SIZE; | 186 | return read_highest - read_lowest + INST_SIZE; |
| 183 | } | 187 | } |
| 184 | 188 | ||
| @@ -187,7 +191,7 @@ bool GenericEnvironment::CanBeSerialized() const noexcept { | |||
| 187 | } | 191 | } |
| 188 | 192 | ||
| 189 | u64 GenericEnvironment::CalculateHash() const { | 193 | u64 GenericEnvironment::CalculateHash() const { |
| 190 | const size_t size{ReadSize()}; | 194 | const size_t size{ReadSizeBytes()}; |
| 191 | const auto data{std::make_unique<char[]>(size)}; | 195 | const auto data{std::make_unique<char[]>(size)}; |
| 192 | gpu_memory->ReadBlock(program_base + read_lowest, data.get(), size); | 196 | gpu_memory->ReadBlock(program_base + read_lowest, data.get(), size); |
| 193 | return Common::CityHash64(data.get(), size); | 197 | return Common::CityHash64(data.get(), size); |
| @@ -198,7 +202,7 @@ void GenericEnvironment::Dump(u64 hash) { | |||
| 198 | } | 202 | } |
| 199 | 203 | ||
| 200 | void GenericEnvironment::Serialize(std::ofstream& file) const { | 204 | void GenericEnvironment::Serialize(std::ofstream& file) const { |
| 201 | const u64 code_size{static_cast<u64>(CachedSize())}; | 205 | const u64 code_size{static_cast<u64>(CachedSizeBytes())}; |
| 202 | const u64 num_texture_types{static_cast<u64>(texture_types.size())}; | 206 | const u64 num_texture_types{static_cast<u64>(texture_types.size())}; |
| 203 | const u64 num_texture_pixel_formats{static_cast<u64>(texture_pixel_formats.size())}; | 207 | const u64 num_texture_pixel_formats{static_cast<u64>(texture_pixel_formats.size())}; |
| 204 | const u64 num_cbuf_values{static_cast<u64>(cbuf_values.size())}; | 208 | const u64 num_cbuf_values{static_cast<u64>(cbuf_values.size())}; |
diff --git a/src/video_core/shader_environment.h b/src/video_core/shader_environment.h index d75987a52..a0f61cbda 100644 --- a/src/video_core/shader_environment.h +++ b/src/video_core/shader_environment.h | |||
| @@ -48,9 +48,11 @@ public: | |||
| 48 | 48 | ||
| 49 | void SetCachedSize(size_t size_bytes); | 49 | void SetCachedSize(size_t size_bytes); |
| 50 | 50 | ||
| 51 | [[nodiscard]] size_t CachedSize() const noexcept; | 51 | [[nodiscard]] size_t CachedSizeWords() const noexcept; |
| 52 | 52 | ||
| 53 | [[nodiscard]] size_t ReadSize() const noexcept; | 53 | [[nodiscard]] size_t CachedSizeBytes() const noexcept; |
| 54 | |||
| 55 | [[nodiscard]] size_t ReadSizeBytes() const noexcept; | ||
| 54 | 56 | ||
| 55 | [[nodiscard]] bool CanBeSerialized() const noexcept; | 57 | [[nodiscard]] bool CanBeSerialized() const noexcept; |
| 56 | 58 | ||
diff --git a/src/video_core/surface.cpp b/src/video_core/surface.cpp index 1a76d4178..cb51529e4 100644 --- a/src/video_core/surface.cpp +++ b/src/video_core/surface.cpp | |||
| @@ -250,10 +250,13 @@ bool IsPixelFormatASTC(PixelFormat format) { | |||
| 250 | case PixelFormat::ASTC_2D_6X6_UNORM: | 250 | case PixelFormat::ASTC_2D_6X6_UNORM: |
| 251 | case PixelFormat::ASTC_2D_6X6_SRGB: | 251 | case PixelFormat::ASTC_2D_6X6_SRGB: |
| 252 | case PixelFormat::ASTC_2D_10X6_UNORM: | 252 | case PixelFormat::ASTC_2D_10X6_UNORM: |
| 253 | case PixelFormat::ASTC_2D_10X6_SRGB: | ||
| 253 | case PixelFormat::ASTC_2D_10X5_UNORM: | 254 | case PixelFormat::ASTC_2D_10X5_UNORM: |
| 254 | case PixelFormat::ASTC_2D_10X5_SRGB: | 255 | case PixelFormat::ASTC_2D_10X5_SRGB: |
| 255 | case PixelFormat::ASTC_2D_10X10_UNORM: | 256 | case PixelFormat::ASTC_2D_10X10_UNORM: |
| 256 | case PixelFormat::ASTC_2D_10X10_SRGB: | 257 | case PixelFormat::ASTC_2D_10X10_SRGB: |
| 258 | case PixelFormat::ASTC_2D_12X10_UNORM: | ||
| 259 | case PixelFormat::ASTC_2D_12X10_SRGB: | ||
| 257 | case PixelFormat::ASTC_2D_12X12_UNORM: | 260 | case PixelFormat::ASTC_2D_12X12_UNORM: |
| 258 | case PixelFormat::ASTC_2D_12X12_SRGB: | 261 | case PixelFormat::ASTC_2D_12X12_SRGB: |
| 259 | case PixelFormat::ASTC_2D_8X6_UNORM: | 262 | case PixelFormat::ASTC_2D_8X6_UNORM: |
| @@ -279,11 +282,13 @@ bool IsPixelFormatSRGB(PixelFormat format) { | |||
| 279 | case PixelFormat::ASTC_2D_8X5_SRGB: | 282 | case PixelFormat::ASTC_2D_8X5_SRGB: |
| 280 | case PixelFormat::ASTC_2D_5X4_SRGB: | 283 | case PixelFormat::ASTC_2D_5X4_SRGB: |
| 281 | case PixelFormat::ASTC_2D_5X5_SRGB: | 284 | case PixelFormat::ASTC_2D_5X5_SRGB: |
| 285 | case PixelFormat::ASTC_2D_10X6_SRGB: | ||
| 282 | case PixelFormat::ASTC_2D_10X8_SRGB: | 286 | case PixelFormat::ASTC_2D_10X8_SRGB: |
| 283 | case PixelFormat::ASTC_2D_6X6_SRGB: | 287 | case PixelFormat::ASTC_2D_6X6_SRGB: |
| 284 | case PixelFormat::ASTC_2D_10X5_SRGB: | 288 | case PixelFormat::ASTC_2D_10X5_SRGB: |
| 285 | case PixelFormat::ASTC_2D_10X10_SRGB: | 289 | case PixelFormat::ASTC_2D_10X10_SRGB: |
| 286 | case PixelFormat::ASTC_2D_12X12_SRGB: | 290 | case PixelFormat::ASTC_2D_12X12_SRGB: |
| 291 | case PixelFormat::ASTC_2D_12X10_SRGB: | ||
| 287 | case PixelFormat::ASTC_2D_8X6_SRGB: | 292 | case PixelFormat::ASTC_2D_8X6_SRGB: |
| 288 | case PixelFormat::ASTC_2D_6X5_SRGB: | 293 | case PixelFormat::ASTC_2D_6X5_SRGB: |
| 289 | return true; | 294 | return true; |
diff --git a/src/video_core/surface.h b/src/video_core/surface.h index 44b79af20..0225d3287 100644 --- a/src/video_core/surface.h +++ b/src/video_core/surface.h | |||
| @@ -95,10 +95,13 @@ enum class PixelFormat { | |||
| 95 | ASTC_2D_6X6_UNORM, | 95 | ASTC_2D_6X6_UNORM, |
| 96 | ASTC_2D_6X6_SRGB, | 96 | ASTC_2D_6X6_SRGB, |
| 97 | ASTC_2D_10X6_UNORM, | 97 | ASTC_2D_10X6_UNORM, |
| 98 | ASTC_2D_10X6_SRGB, | ||
| 98 | ASTC_2D_10X5_UNORM, | 99 | ASTC_2D_10X5_UNORM, |
| 99 | ASTC_2D_10X5_SRGB, | 100 | ASTC_2D_10X5_SRGB, |
| 100 | ASTC_2D_10X10_UNORM, | 101 | ASTC_2D_10X10_UNORM, |
| 101 | ASTC_2D_10X10_SRGB, | 102 | ASTC_2D_10X10_SRGB, |
| 103 | ASTC_2D_12X10_UNORM, | ||
| 104 | ASTC_2D_12X10_SRGB, | ||
| 102 | ASTC_2D_12X12_UNORM, | 105 | ASTC_2D_12X12_UNORM, |
| 103 | ASTC_2D_12X12_SRGB, | 106 | ASTC_2D_12X12_SRGB, |
| 104 | ASTC_2D_8X6_UNORM, | 107 | ASTC_2D_8X6_UNORM, |
| @@ -232,10 +235,13 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_WIDTH_TABLE = {{ | |||
| 232 | 6, // ASTC_2D_6X6_UNORM | 235 | 6, // ASTC_2D_6X6_UNORM |
| 233 | 6, // ASTC_2D_6X6_SRGB | 236 | 6, // ASTC_2D_6X6_SRGB |
| 234 | 10, // ASTC_2D_10X6_UNORM | 237 | 10, // ASTC_2D_10X6_UNORM |
| 238 | 10, // ASTC_2D_10X6_SRGB | ||
| 235 | 10, // ASTC_2D_10X5_UNORM | 239 | 10, // ASTC_2D_10X5_UNORM |
| 236 | 10, // ASTC_2D_10X5_SRGB | 240 | 10, // ASTC_2D_10X5_SRGB |
| 237 | 10, // ASTC_2D_10X10_UNORM | 241 | 10, // ASTC_2D_10X10_UNORM |
| 238 | 10, // ASTC_2D_10X10_SRGB | 242 | 10, // ASTC_2D_10X10_SRGB |
| 243 | 12, // ASTC_2D_12X10_UNORM | ||
| 244 | 12, // ASTC_2D_12X10_SRGB | ||
| 239 | 12, // ASTC_2D_12X12_UNORM | 245 | 12, // ASTC_2D_12X12_UNORM |
| 240 | 12, // ASTC_2D_12X12_SRGB | 246 | 12, // ASTC_2D_12X12_SRGB |
| 241 | 8, // ASTC_2D_8X6_UNORM | 247 | 8, // ASTC_2D_8X6_UNORM |
| @@ -338,10 +344,13 @@ constexpr std::array<u8, MaxPixelFormat> BLOCK_HEIGHT_TABLE = {{ | |||
| 338 | 6, // ASTC_2D_6X6_UNORM | 344 | 6, // ASTC_2D_6X6_UNORM |
| 339 | 6, // ASTC_2D_6X6_SRGB | 345 | 6, // ASTC_2D_6X6_SRGB |
| 340 | 6, // ASTC_2D_10X6_UNORM | 346 | 6, // ASTC_2D_10X6_UNORM |
| 347 | 6, // ASTC_2D_10X6_SRGB | ||
| 341 | 5, // ASTC_2D_10X5_UNORM | 348 | 5, // ASTC_2D_10X5_UNORM |
| 342 | 5, // ASTC_2D_10X5_SRGB | 349 | 5, // ASTC_2D_10X5_SRGB |
| 343 | 10, // ASTC_2D_10X10_UNORM | 350 | 10, // ASTC_2D_10X10_UNORM |
| 344 | 10, // ASTC_2D_10X10_SRGB | 351 | 10, // ASTC_2D_10X10_SRGB |
| 352 | 10, // ASTC_2D_12X10_UNORM | ||
| 353 | 10, // ASTC_2D_12X10_SRGB | ||
| 345 | 12, // ASTC_2D_12X12_UNORM | 354 | 12, // ASTC_2D_12X12_UNORM |
| 346 | 12, // ASTC_2D_12X12_SRGB | 355 | 12, // ASTC_2D_12X12_SRGB |
| 347 | 6, // ASTC_2D_8X6_UNORM | 356 | 6, // ASTC_2D_8X6_UNORM |
| @@ -444,10 +453,13 @@ constexpr std::array<u8, MaxPixelFormat> BITS_PER_BLOCK_TABLE = {{ | |||
| 444 | 128, // ASTC_2D_6X6_UNORM | 453 | 128, // ASTC_2D_6X6_UNORM |
| 445 | 128, // ASTC_2D_6X6_SRGB | 454 | 128, // ASTC_2D_6X6_SRGB |
| 446 | 128, // ASTC_2D_10X6_UNORM | 455 | 128, // ASTC_2D_10X6_UNORM |
| 456 | 128, // ASTC_2D_10X6_SRGB | ||
| 447 | 128, // ASTC_2D_10X5_UNORM | 457 | 128, // ASTC_2D_10X5_UNORM |
| 448 | 128, // ASTC_2D_10X5_SRGB | 458 | 128, // ASTC_2D_10X5_SRGB |
| 449 | 128, // ASTC_2D_10X10_UNORM | 459 | 128, // ASTC_2D_10X10_UNORM |
| 450 | 128, // ASTC_2D_10X10_SRGB | 460 | 128, // ASTC_2D_10X10_SRGB |
| 461 | 128, // ASTC_2D_12X10_UNORM | ||
| 462 | 128, // ASTC_2D_12X10_SRGB | ||
| 451 | 128, // ASTC_2D_12X12_UNORM | 463 | 128, // ASTC_2D_12X12_UNORM |
| 452 | 128, // ASTC_2D_12X12_SRGB | 464 | 128, // ASTC_2D_12X12_SRGB |
| 453 | 128, // ASTC_2D_8X6_UNORM | 465 | 128, // ASTC_2D_8X6_UNORM |
diff --git a/src/video_core/texture_cache/format_lookup_table.cpp b/src/video_core/texture_cache/format_lookup_table.cpp index 5fc2b2fec..11ced6c38 100644 --- a/src/video_core/texture_cache/format_lookup_table.cpp +++ b/src/video_core/texture_cache/format_lookup_table.cpp | |||
| @@ -210,6 +210,8 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, | |||
| 210 | return PixelFormat::ASTC_2D_6X6_SRGB; | 210 | return PixelFormat::ASTC_2D_6X6_SRGB; |
| 211 | case Hash(TextureFormat::ASTC_2D_10X6, UNORM, LINEAR): | 211 | case Hash(TextureFormat::ASTC_2D_10X6, UNORM, LINEAR): |
| 212 | return PixelFormat::ASTC_2D_10X6_UNORM; | 212 | return PixelFormat::ASTC_2D_10X6_UNORM; |
| 213 | case Hash(TextureFormat::ASTC_2D_10X6, UNORM, SRGB): | ||
| 214 | return PixelFormat::ASTC_2D_10X6_SRGB; | ||
| 213 | case Hash(TextureFormat::ASTC_2D_10X5, UNORM, LINEAR): | 215 | case Hash(TextureFormat::ASTC_2D_10X5, UNORM, LINEAR): |
| 214 | return PixelFormat::ASTC_2D_10X5_UNORM; | 216 | return PixelFormat::ASTC_2D_10X5_UNORM; |
| 215 | case Hash(TextureFormat::ASTC_2D_10X5, UNORM, SRGB): | 217 | case Hash(TextureFormat::ASTC_2D_10X5, UNORM, SRGB): |
| @@ -218,6 +220,10 @@ PixelFormat PixelFormatFromTextureInfo(TextureFormat format, ComponentType red, | |||
| 218 | return PixelFormat::ASTC_2D_10X10_UNORM; | 220 | return PixelFormat::ASTC_2D_10X10_UNORM; |
| 219 | case Hash(TextureFormat::ASTC_2D_10X10, UNORM, SRGB): | 221 | case Hash(TextureFormat::ASTC_2D_10X10, UNORM, SRGB): |
| 220 | return PixelFormat::ASTC_2D_10X10_SRGB; | 222 | return PixelFormat::ASTC_2D_10X10_SRGB; |
| 223 | case Hash(TextureFormat::ASTC_2D_12X10, UNORM, LINEAR): | ||
| 224 | return PixelFormat::ASTC_2D_12X10_UNORM; | ||
| 225 | case Hash(TextureFormat::ASTC_2D_12X10, UNORM, SRGB): | ||
| 226 | return PixelFormat::ASTC_2D_12X10_SRGB; | ||
| 221 | case Hash(TextureFormat::ASTC_2D_12X12, UNORM, LINEAR): | 227 | case Hash(TextureFormat::ASTC_2D_12X12, UNORM, LINEAR): |
| 222 | return PixelFormat::ASTC_2D_12X12_UNORM; | 228 | return PixelFormat::ASTC_2D_12X12_UNORM; |
| 223 | case Hash(TextureFormat::ASTC_2D_12X12, UNORM, SRGB): | 229 | case Hash(TextureFormat::ASTC_2D_12X12, UNORM, SRGB): |
diff --git a/src/video_core/texture_cache/formatter.h b/src/video_core/texture_cache/formatter.h index f1f0a057b..b97147797 100644 --- a/src/video_core/texture_cache/formatter.h +++ b/src/video_core/texture_cache/formatter.h | |||
| @@ -179,6 +179,8 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str | |||
| 179 | return "ASTC_2D_6X6_SRGB"; | 179 | return "ASTC_2D_6X6_SRGB"; |
| 180 | case PixelFormat::ASTC_2D_10X6_UNORM: | 180 | case PixelFormat::ASTC_2D_10X6_UNORM: |
| 181 | return "ASTC_2D_10X6_UNORM"; | 181 | return "ASTC_2D_10X6_UNORM"; |
| 182 | case PixelFormat::ASTC_2D_10X6_SRGB: | ||
| 183 | return "ASTC_2D_10X6_SRGB"; | ||
| 182 | case PixelFormat::ASTC_2D_10X5_UNORM: | 184 | case PixelFormat::ASTC_2D_10X5_UNORM: |
| 183 | return "ASTC_2D_10X5_UNORM"; | 185 | return "ASTC_2D_10X5_UNORM"; |
| 184 | case PixelFormat::ASTC_2D_10X5_SRGB: | 186 | case PixelFormat::ASTC_2D_10X5_SRGB: |
| @@ -187,6 +189,10 @@ struct fmt::formatter<VideoCore::Surface::PixelFormat> : fmt::formatter<fmt::str | |||
| 187 | return "ASTC_2D_10X10_UNORM"; | 189 | return "ASTC_2D_10X10_UNORM"; |
| 188 | case PixelFormat::ASTC_2D_10X10_SRGB: | 190 | case PixelFormat::ASTC_2D_10X10_SRGB: |
| 189 | return "ASTC_2D_10X10_SRGB"; | 191 | return "ASTC_2D_10X10_SRGB"; |
| 192 | case PixelFormat::ASTC_2D_12X10_UNORM: | ||
| 193 | return "ASTC_2D_12X10_UNORM"; | ||
| 194 | case PixelFormat::ASTC_2D_12X10_SRGB: | ||
| 195 | return "ASTC_2D_12X10_SRGB"; | ||
| 190 | case PixelFormat::ASTC_2D_12X12_UNORM: | 196 | case PixelFormat::ASTC_2D_12X12_UNORM: |
| 191 | return "ASTC_2D_12X12_UNORM"; | 197 | return "ASTC_2D_12X12_UNORM"; |
| 192 | case PixelFormat::ASTC_2D_12X12_SRGB: | 198 | case PixelFormat::ASTC_2D_12X12_SRGB: |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e601f8446..f335009d0 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -888,7 +888,7 @@ void TextureCache<P>::DownloadImageIntoBuffer(typename TextureCache<P>::Image* i | |||
| 888 | buffer, | 888 | buffer, |
| 889 | download_map.buffer, | 889 | download_map.buffer, |
| 890 | }; | 890 | }; |
| 891 | std::array buffer_offsets{ | 891 | std::array<u64, 2> buffer_offsets{ |
| 892 | buffer_offset, | 892 | buffer_offset, |
| 893 | download_map.offset, | 893 | download_map.offset, |
| 894 | }; | 894 | }; |
diff --git a/src/video_core/vulkan_common/vulkan_device.cpp b/src/video_core/vulkan_common/vulkan_device.cpp index 6f288b3f8..6ffca2af2 100644 --- a/src/video_core/vulkan_common/vulkan_device.cpp +++ b/src/video_core/vulkan_common/vulkan_device.cpp | |||
| @@ -617,7 +617,9 @@ bool Device::ShouldBoostClocks() const { | |||
| 617 | 617 | ||
| 618 | const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; | 618 | const bool is_steam_deck = vendor_id == 0x1002 && device_id == 0x163F; |
| 619 | 619 | ||
| 620 | return validated_driver && !is_steam_deck; | 620 | const bool is_debugging = this->HasDebuggingToolAttached(); |
| 621 | |||
| 622 | return validated_driver && !is_steam_deck && !is_debugging; | ||
| 621 | } | 623 | } |
| 622 | 624 | ||
| 623 | bool Device::GetSuitability(bool requires_swapchain) { | 625 | bool Device::GetSuitability(bool requires_swapchain) { |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 305891d18..0131f63e7 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -497,7 +497,7 @@ void Config::ReadCoreValues() { | |||
| 497 | qt_config->beginGroup(QStringLiteral("Core")); | 497 | qt_config->beginGroup(QStringLiteral("Core")); |
| 498 | 498 | ||
| 499 | ReadGlobalSetting(Settings::values.use_multi_core); | 499 | ReadGlobalSetting(Settings::values.use_multi_core); |
| 500 | ReadGlobalSetting(Settings::values.use_extended_memory_layout); | 500 | ReadGlobalSetting(Settings::values.use_unsafe_extended_memory_layout); |
| 501 | 501 | ||
| 502 | qt_config->endGroup(); | 502 | qt_config->endGroup(); |
| 503 | } | 503 | } |
| @@ -713,7 +713,6 @@ void Config::ReadRendererValues() { | |||
| 713 | ReadGlobalSetting(Settings::values.shader_backend); | 713 | ReadGlobalSetting(Settings::values.shader_backend); |
| 714 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); | 714 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 715 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); | 715 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); |
| 716 | ReadGlobalSetting(Settings::values.use_pessimistic_flushes); | ||
| 717 | ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | 716 | ReadGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); |
| 718 | ReadGlobalSetting(Settings::values.bg_red); | 717 | ReadGlobalSetting(Settings::values.bg_red); |
| 719 | ReadGlobalSetting(Settings::values.bg_green); | 718 | ReadGlobalSetting(Settings::values.bg_green); |
| @@ -1162,7 +1161,7 @@ void Config::SaveCoreValues() { | |||
| 1162 | qt_config->beginGroup(QStringLiteral("Core")); | 1161 | qt_config->beginGroup(QStringLiteral("Core")); |
| 1163 | 1162 | ||
| 1164 | WriteGlobalSetting(Settings::values.use_multi_core); | 1163 | WriteGlobalSetting(Settings::values.use_multi_core); |
| 1165 | WriteGlobalSetting(Settings::values.use_extended_memory_layout); | 1164 | WriteGlobalSetting(Settings::values.use_unsafe_extended_memory_layout); |
| 1166 | 1165 | ||
| 1167 | qt_config->endGroup(); | 1166 | qt_config->endGroup(); |
| 1168 | } | 1167 | } |
| @@ -1359,7 +1358,6 @@ void Config::SaveRendererValues() { | |||
| 1359 | Settings::values.shader_backend.UsingGlobal()); | 1358 | Settings::values.shader_backend.UsingGlobal()); |
| 1360 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); | 1359 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 1361 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); | 1360 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); |
| 1362 | WriteGlobalSetting(Settings::values.use_pessimistic_flushes); | ||
| 1363 | WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); | 1361 | WriteGlobalSetting(Settings::values.use_vulkan_driver_pipeline_cache); |
| 1364 | WriteGlobalSetting(Settings::values.bg_red); | 1362 | WriteGlobalSetting(Settings::values.bg_red); |
| 1365 | WriteGlobalSetting(Settings::values.bg_green); | 1363 | WriteGlobalSetting(Settings::values.bg_green); |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 207bcdc4d..26258d744 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -35,9 +35,6 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 35 | 35 | ||
| 36 | ui->use_multi_core->setEnabled(runtime_lock); | 36 | ui->use_multi_core->setEnabled(runtime_lock); |
| 37 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); | 37 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); |
| 38 | ui->use_extended_memory_layout->setEnabled(runtime_lock); | ||
| 39 | ui->use_extended_memory_layout->setChecked( | ||
| 40 | Settings::values.use_extended_memory_layout.GetValue()); | ||
| 41 | 38 | ||
| 42 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); | 39 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); |
| 43 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); | 40 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); |
| @@ -79,9 +76,6 @@ void ConfigureGeneral::ResetDefaults() { | |||
| 79 | void ConfigureGeneral::ApplyConfiguration() { | 76 | void ConfigureGeneral::ApplyConfiguration() { |
| 80 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, | 77 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_multi_core, ui->use_multi_core, |
| 81 | use_multi_core); | 78 | use_multi_core); |
| 82 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_extended_memory_layout, | ||
| 83 | ui->use_extended_memory_layout, | ||
| 84 | use_extended_memory_layout); | ||
| 85 | 79 | ||
| 86 | if (Settings::IsConfiguringGlobal()) { | 80 | if (Settings::IsConfiguringGlobal()) { |
| 87 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); | 81 | UISettings::values.confirm_before_closing = ui->toggle_check_exit->isChecked(); |
| @@ -141,9 +135,6 @@ void ConfigureGeneral::SetupPerGameUI() { | |||
| 141 | Settings::values.use_speed_limit, use_speed_limit); | 135 | Settings::values.use_speed_limit, use_speed_limit); |
| 142 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, | 136 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, |
| 143 | use_multi_core); | 137 | use_multi_core); |
| 144 | ConfigurationShared::SetColoredTristate(ui->use_extended_memory_layout, | ||
| 145 | Settings::values.use_extended_memory_layout, | ||
| 146 | use_extended_memory_layout); | ||
| 147 | 138 | ||
| 148 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { | 139 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { |
| 149 | ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && | 140 | ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && |
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index a090c1a3f..7ff63f425 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h | |||
| @@ -47,7 +47,6 @@ private: | |||
| 47 | 47 | ||
| 48 | ConfigurationShared::CheckState use_speed_limit; | 48 | ConfigurationShared::CheckState use_speed_limit; |
| 49 | ConfigurationShared::CheckState use_multi_core; | 49 | ConfigurationShared::CheckState use_multi_core; |
| 50 | ConfigurationShared::CheckState use_extended_memory_layout; | ||
| 51 | 50 | ||
| 52 | const Core::System& system; | 51 | const Core::System& system; |
| 53 | }; | 52 | }; |
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index add110bb0..986a1625b 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui | |||
| @@ -62,13 +62,6 @@ | |||
| 62 | </widget> | 62 | </widget> |
| 63 | </item> | 63 | </item> |
| 64 | <item> | 64 | <item> |
| 65 | <widget class="QCheckBox" name="use_extended_memory_layout"> | ||
| 66 | <property name="text"> | ||
| 67 | <string>Extended memory layout (8GB DRAM)</string> | ||
| 68 | </property> | ||
| 69 | </widget> | ||
| 70 | </item> | ||
| 71 | <item> | ||
| 72 | <widget class="QCheckBox" name="toggle_check_exit"> | 65 | <widget class="QCheckBox" name="toggle_check_exit"> |
| 73 | <property name="text"> | 66 | <property name="text"> |
| 74 | <string>Confirm exit while emulation is running</string> | 67 | <string>Confirm exit while emulation is running</string> |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 7f7bf0e4d..ddda79983 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -34,7 +34,6 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 34 | ui->async_astc->setChecked(Settings::values.async_astc.GetValue()); | 34 | ui->async_astc->setChecked(Settings::values.async_astc.GetValue()); |
| 35 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); | 35 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); |
| 36 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); | 36 | ui->use_fast_gpu_time->setChecked(Settings::values.use_fast_gpu_time.GetValue()); |
| 37 | ui->use_pessimistic_flushes->setChecked(Settings::values.use_pessimistic_flushes.GetValue()); | ||
| 38 | ui->use_vulkan_driver_pipeline_cache->setChecked( | 37 | ui->use_vulkan_driver_pipeline_cache->setChecked( |
| 39 | Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); | 38 | Settings::values.use_vulkan_driver_pipeline_cache.GetValue()); |
| 40 | 39 | ||
| @@ -71,8 +70,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 71 | use_asynchronous_shaders); | 70 | use_asynchronous_shaders); |
| 72 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | 71 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, |
| 73 | ui->use_fast_gpu_time, use_fast_gpu_time); | 72 | ui->use_fast_gpu_time, use_fast_gpu_time); |
| 74 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_pessimistic_flushes, | ||
| 75 | ui->use_pessimistic_flushes, use_pessimistic_flushes); | ||
| 76 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, | 73 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vulkan_driver_pipeline_cache, |
| 77 | ui->use_vulkan_driver_pipeline_cache, | 74 | ui->use_vulkan_driver_pipeline_cache, |
| 78 | use_vulkan_driver_pipeline_cache); | 75 | use_vulkan_driver_pipeline_cache); |
| @@ -102,8 +99,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 102 | ui->use_asynchronous_shaders->setEnabled( | 99 | ui->use_asynchronous_shaders->setEnabled( |
| 103 | Settings::values.use_asynchronous_shaders.UsingGlobal()); | 100 | Settings::values.use_asynchronous_shaders.UsingGlobal()); |
| 104 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); | 101 | ui->use_fast_gpu_time->setEnabled(Settings::values.use_fast_gpu_time.UsingGlobal()); |
| 105 | ui->use_pessimistic_flushes->setEnabled( | ||
| 106 | Settings::values.use_pessimistic_flushes.UsingGlobal()); | ||
| 107 | ui->use_vulkan_driver_pipeline_cache->setEnabled( | 102 | ui->use_vulkan_driver_pipeline_cache->setEnabled( |
| 108 | Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); | 103 | Settings::values.use_vulkan_driver_pipeline_cache.UsingGlobal()); |
| 109 | ui->anisotropic_filtering_combobox->setEnabled( | 104 | ui->anisotropic_filtering_combobox->setEnabled( |
| @@ -125,9 +120,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 125 | use_asynchronous_shaders); | 120 | use_asynchronous_shaders); |
| 126 | ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, | 121 | ConfigurationShared::SetColoredTristate(ui->use_fast_gpu_time, |
| 127 | Settings::values.use_fast_gpu_time, use_fast_gpu_time); | 122 | Settings::values.use_fast_gpu_time, use_fast_gpu_time); |
| 128 | ConfigurationShared::SetColoredTristate(ui->use_pessimistic_flushes, | ||
| 129 | Settings::values.use_pessimistic_flushes, | ||
| 130 | use_pessimistic_flushes); | ||
| 131 | ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, | 123 | ConfigurationShared::SetColoredTristate(ui->use_vulkan_driver_pipeline_cache, |
| 132 | Settings::values.use_vulkan_driver_pipeline_cache, | 124 | Settings::values.use_vulkan_driver_pipeline_cache, |
| 133 | use_vulkan_driver_pipeline_cache); | 125 | use_vulkan_driver_pipeline_cache); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index 5394ed40a..ff5060957 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h | |||
| @@ -42,7 +42,6 @@ private: | |||
| 42 | ConfigurationShared::CheckState async_astc; | 42 | ConfigurationShared::CheckState async_astc; |
| 43 | ConfigurationShared::CheckState use_asynchronous_shaders; | 43 | ConfigurationShared::CheckState use_asynchronous_shaders; |
| 44 | ConfigurationShared::CheckState use_fast_gpu_time; | 44 | ConfigurationShared::CheckState use_fast_gpu_time; |
| 45 | ConfigurationShared::CheckState use_pessimistic_flushes; | ||
| 46 | ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; | 45 | ConfigurationShared::CheckState use_vulkan_driver_pipeline_cache; |
| 47 | 46 | ||
| 48 | const Core::System& system; | 47 | const Core::System& system; |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index d7ec18939..1234f695c 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -127,16 +127,6 @@ | |||
| 127 | </widget> | 127 | </widget> |
| 128 | </item> | 128 | </item> |
| 129 | <item> | 129 | <item> |
| 130 | <widget class="QCheckBox" name="use_pessimistic_flushes"> | ||
| 131 | <property name="toolTip"> | ||
| 132 | <string>Enables pessimistic buffer flushes. This option will force unmodified buffers to be flushed, which can cost performance.</string> | ||
| 133 | </property> | ||
| 134 | <property name="text"> | ||
| 135 | <string>Use pessimistic buffer flushes (Hack)</string> | ||
| 136 | </property> | ||
| 137 | </widget> | ||
| 138 | </item> | ||
| 139 | <item> | ||
| 140 | <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache"> | 130 | <widget class="QCheckBox" name="use_vulkan_driver_pipeline_cache"> |
| 141 | <property name="toolTip"> | 131 | <property name="toolTip"> |
| 142 | <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string> | 132 | <string>Enables GPU vendor-specific pipeline cache. This option can improve shader loading time significantly in cases where the Vulkan driver does not store pipeline cache files internally.</string> |
diff --git a/src/yuzu/configuration/configure_input_player.cpp b/src/yuzu/configuration/configure_input_player.cpp index 50b62293e..54f42e0c9 100644 --- a/src/yuzu/configuration/configure_input_player.cpp +++ b/src/yuzu/configuration/configure_input_player.cpp | |||
| @@ -206,7 +206,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 206 | } | 206 | } |
| 207 | if (param.Has("axis")) { | 207 | if (param.Has("axis")) { |
| 208 | const QString axis = QString::fromStdString(param.Get("axis", "")); | 208 | const QString axis = QString::fromStdString(param.Get("axis", "")); |
| 209 | return QObject::tr("%1%2Axis %3").arg(toggle, invert, axis); | 209 | return QObject::tr("%1%2%3Axis %4").arg(toggle, inverted, invert, axis); |
| 210 | } | 210 | } |
| 211 | if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) { | 211 | if (param.Has("axis_x") && param.Has("axis_y") && param.Has("axis_z")) { |
| 212 | const QString axis_x = QString::fromStdString(param.Get("axis_x", "")); | 212 | const QString axis_x = QString::fromStdString(param.Get("axis_x", "")); |
| @@ -229,7 +229,7 @@ QString ConfigureInputPlayer::ButtonToText(const Common::ParamPackage& param) { | |||
| 229 | return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name); | 229 | return QObject::tr("%1%2%3Hat %4").arg(turbo, toggle, inverted, button_name); |
| 230 | } | 230 | } |
| 231 | if (param.Has("axis")) { | 231 | if (param.Has("axis")) { |
| 232 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | 232 | return QObject::tr("%1%2%3Axis %4").arg(toggle, inverted, invert, button_name); |
| 233 | } | 233 | } |
| 234 | if (param.Has("motion")) { | 234 | if (param.Has("motion")) { |
| 235 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); | 235 | return QObject::tr("%1%2Axis %3").arg(toggle, inverted, button_name); |
| @@ -410,6 +410,12 @@ ConfigureInputPlayer::ConfigureInputPlayer(QWidget* parent, std::size_t player_i | |||
| 410 | button_map[button_id]->setText(ButtonToText(param)); | 410 | button_map[button_id]->setText(ButtonToText(param)); |
| 411 | emulated_controller->SetButtonParam(button_id, param); | 411 | emulated_controller->SetButtonParam(button_id, param); |
| 412 | }); | 412 | }); |
| 413 | context_menu.addAction(tr("Invert button"), [&] { | ||
| 414 | const bool invert_value = !param.Get("inverted", false); | ||
| 415 | param.Set("inverted", invert_value); | ||
| 416 | button_map[button_id]->setText(ButtonToText(param)); | ||
| 417 | emulated_controller->SetButtonParam(button_id, param); | ||
| 418 | }); | ||
| 413 | context_menu.addAction(tr("Set threshold"), [&] { | 419 | context_menu.addAction(tr("Set threshold"), [&] { |
| 414 | const int button_threshold = | 420 | const int button_threshold = |
| 415 | static_cast<int>(param.Get("threshold", 0.5f) * 100.0f); | 421 | static_cast<int>(param.Get("threshold", 0.5f) * 100.0f); |
diff --git a/src/yuzu/configuration/configure_input_player_widget.cpp b/src/yuzu/configuration/configure_input_player_widget.cpp index c287220fc..fe1ee2289 100644 --- a/src/yuzu/configuration/configure_input_player_widget.cpp +++ b/src/yuzu/configuration/configure_input_player_widget.cpp | |||
| @@ -180,6 +180,10 @@ void PlayerControlPreview::ControllerUpdate(Core::HID::ControllerTriggerType typ | |||
| 180 | battery_values = controller->GetBatteryValues(); | 180 | battery_values = controller->GetBatteryValues(); |
| 181 | needs_redraw = true; | 181 | needs_redraw = true; |
| 182 | break; | 182 | break; |
| 183 | case Core::HID::ControllerTriggerType::Motion: | ||
| 184 | motion_values = controller->GetMotions(); | ||
| 185 | needs_redraw = true; | ||
| 186 | break; | ||
| 183 | default: | 187 | default: |
| 184 | break; | 188 | break; |
| 185 | } | 189 | } |
| @@ -313,6 +317,15 @@ void PlayerControlPreview::DrawLeftController(QPainter& p, const QPointF center) | |||
| 313 | DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0)); | 317 | DrawRawJoystick(p, center + QPointF(-140, 90), QPointF(0, 0)); |
| 314 | } | 318 | } |
| 315 | 319 | ||
| 320 | { | ||
| 321 | // Draw motion cubes | ||
| 322 | using namespace Settings::NativeMotion; | ||
| 323 | p.setPen(colors.outline); | ||
| 324 | p.setBrush(colors.transparent); | ||
| 325 | Draw3dCube(p, center + QPointF(-140, 90), | ||
| 326 | motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f); | ||
| 327 | } | ||
| 328 | |||
| 316 | using namespace Settings::NativeButton; | 329 | using namespace Settings::NativeButton; |
| 317 | 330 | ||
| 318 | // D-pad constants | 331 | // D-pad constants |
| @@ -435,6 +448,15 @@ void PlayerControlPreview::DrawRightController(QPainter& p, const QPointF center | |||
| 435 | DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90)); | 448 | DrawRawJoystick(p, QPointF(0, 0), center + QPointF(140, 90)); |
| 436 | } | 449 | } |
| 437 | 450 | ||
| 451 | { | ||
| 452 | // Draw motion cubes | ||
| 453 | using namespace Settings::NativeMotion; | ||
| 454 | p.setPen(colors.outline); | ||
| 455 | p.setBrush(colors.transparent); | ||
| 456 | Draw3dCube(p, center + QPointF(140, 90), | ||
| 457 | motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f); | ||
| 458 | } | ||
| 459 | |||
| 438 | using namespace Settings::NativeButton; | 460 | using namespace Settings::NativeButton; |
| 439 | 461 | ||
| 440 | // Face buttons constants | 462 | // Face buttons constants |
| @@ -555,6 +577,17 @@ void PlayerControlPreview::DrawDualController(QPainter& p, const QPointF center) | |||
| 555 | DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90)); | 577 | DrawRawJoystick(p, center + QPointF(-180, 90), center + QPointF(180, 90)); |
| 556 | } | 578 | } |
| 557 | 579 | ||
| 580 | { | ||
| 581 | // Draw motion cubes | ||
| 582 | using namespace Settings::NativeMotion; | ||
| 583 | p.setPen(colors.outline); | ||
| 584 | p.setBrush(colors.transparent); | ||
| 585 | Draw3dCube(p, center + QPointF(-180, -5), | ||
| 586 | motion_values[Settings::NativeMotion::MotionLeft].euler, 20.0f); | ||
| 587 | Draw3dCube(p, center + QPointF(180, -5), | ||
| 588 | motion_values[Settings::NativeMotion::MotionRight].euler, 20.0f); | ||
| 589 | } | ||
| 590 | |||
| 558 | using namespace Settings::NativeButton; | 591 | using namespace Settings::NativeButton; |
| 559 | 592 | ||
| 560 | // Face buttons constants | 593 | // Face buttons constants |
| @@ -647,6 +680,15 @@ void PlayerControlPreview::DrawHandheldController(QPainter& p, const QPointF cen | |||
| 647 | DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0)); | 680 | DrawRawJoystick(p, center + QPointF(-50, 0), center + QPointF(50, 0)); |
| 648 | } | 681 | } |
| 649 | 682 | ||
| 683 | { | ||
| 684 | // Draw motion cubes | ||
| 685 | using namespace Settings::NativeMotion; | ||
| 686 | p.setPen(colors.outline); | ||
| 687 | p.setBrush(colors.transparent); | ||
| 688 | Draw3dCube(p, center + QPointF(0, -115), | ||
| 689 | motion_values[Settings::NativeMotion::MotionLeft].euler, 15.0f); | ||
| 690 | } | ||
| 691 | |||
| 650 | using namespace Settings::NativeButton; | 692 | using namespace Settings::NativeButton; |
| 651 | 693 | ||
| 652 | // Face buttons constants | 694 | // Face buttons constants |
| @@ -750,6 +792,15 @@ void PlayerControlPreview::DrawProController(QPainter& p, const QPointF center) | |||
| 750 | DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105)); | 792 | DrawRawJoystick(p, center + QPointF(-50, 105), center + QPointF(50, 105)); |
| 751 | } | 793 | } |
| 752 | 794 | ||
| 795 | { | ||
| 796 | // Draw motion cubes | ||
| 797 | using namespace Settings::NativeMotion; | ||
| 798 | p.setPen(colors.button); | ||
| 799 | p.setBrush(colors.transparent); | ||
| 800 | Draw3dCube(p, center + QPointF(0, -100), | ||
| 801 | motion_values[Settings::NativeMotion::MotionLeft].euler, 15.0f); | ||
| 802 | } | ||
| 803 | |||
| 753 | using namespace Settings::NativeButton; | 804 | using namespace Settings::NativeButton; |
| 754 | 805 | ||
| 755 | // Face buttons constants | 806 | // Face buttons constants |
| @@ -2871,6 +2922,46 @@ void PlayerControlPreview::DrawArrow(QPainter& p, const QPointF center, const Di | |||
| 2871 | DrawPolygon(p, arrow_symbol); | 2922 | DrawPolygon(p, arrow_symbol); |
| 2872 | } | 2923 | } |
| 2873 | 2924 | ||
| 2925 | // Draw motion functions | ||
| 2926 | void PlayerControlPreview::Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, | ||
| 2927 | float size) { | ||
| 2928 | std::array<Common::Vec3f, 8> cube{ | ||
| 2929 | Common::Vec3f{-1, -1, -1}, | ||
| 2930 | {-1, 1, -1}, | ||
| 2931 | {1, 1, -1}, | ||
| 2932 | {1, -1, -1}, | ||
| 2933 | {-1, -1, 1}, | ||
| 2934 | {-1, 1, 1}, | ||
| 2935 | {1, 1, 1}, | ||
| 2936 | {1, -1, 1}, | ||
| 2937 | }; | ||
| 2938 | |||
| 2939 | for (Common::Vec3f& point : cube) { | ||
| 2940 | point.RotateFromOrigin(euler.x, euler.y, euler.z); | ||
| 2941 | point *= size; | ||
| 2942 | } | ||
| 2943 | |||
| 2944 | const std::array<QPointF, 4> front_face{ | ||
| 2945 | center + QPointF{cube[0].x, cube[0].y}, | ||
| 2946 | center + QPointF{cube[1].x, cube[1].y}, | ||
| 2947 | center + QPointF{cube[2].x, cube[2].y}, | ||
| 2948 | center + QPointF{cube[3].x, cube[3].y}, | ||
| 2949 | }; | ||
| 2950 | const std::array<QPointF, 4> back_face{ | ||
| 2951 | center + QPointF{cube[4].x, cube[4].y}, | ||
| 2952 | center + QPointF{cube[5].x, cube[5].y}, | ||
| 2953 | center + QPointF{cube[6].x, cube[6].y}, | ||
| 2954 | center + QPointF{cube[7].x, cube[7].y}, | ||
| 2955 | }; | ||
| 2956 | |||
| 2957 | DrawPolygon(p, front_face); | ||
| 2958 | DrawPolygon(p, back_face); | ||
| 2959 | p.drawLine(center + QPointF{cube[0].x, cube[0].y}, center + QPointF{cube[4].x, cube[4].y}); | ||
| 2960 | p.drawLine(center + QPointF{cube[1].x, cube[1].y}, center + QPointF{cube[5].x, cube[5].y}); | ||
| 2961 | p.drawLine(center + QPointF{cube[2].x, cube[2].y}, center + QPointF{cube[6].x, cube[6].y}); | ||
| 2962 | p.drawLine(center + QPointF{cube[3].x, cube[3].y}, center + QPointF{cube[7].x, cube[7].y}); | ||
| 2963 | } | ||
| 2964 | |||
| 2874 | template <size_t N> | 2965 | template <size_t N> |
| 2875 | void PlayerControlPreview::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) { | 2966 | void PlayerControlPreview::DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon) { |
| 2876 | p.drawPolygon(polygon.data(), static_cast<int>(polygon.size())); | 2967 | p.drawPolygon(polygon.data(), static_cast<int>(polygon.size())); |
diff --git a/src/yuzu/configuration/configure_input_player_widget.h b/src/yuzu/configuration/configure_input_player_widget.h index 267d134de..a16943c3c 100644 --- a/src/yuzu/configuration/configure_input_player_widget.h +++ b/src/yuzu/configuration/configure_input_player_widget.h | |||
| @@ -9,6 +9,7 @@ | |||
| 9 | 9 | ||
| 10 | #include "common/input.h" | 10 | #include "common/input.h" |
| 11 | #include "common/settings_input.h" | 11 | #include "common/settings_input.h" |
| 12 | #include "common/vector_math.h" | ||
| 12 | #include "core/hid/emulated_controller.h" | 13 | #include "core/hid/emulated_controller.h" |
| 13 | #include "core/hid/hid_types.h" | 14 | #include "core/hid/hid_types.h" |
| 14 | 15 | ||
| @@ -193,6 +194,9 @@ private: | |||
| 193 | void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); | 194 | void DrawSymbol(QPainter& p, QPointF center, Symbol symbol, float icon_size); |
| 194 | void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); | 195 | void DrawArrow(QPainter& p, QPointF center, Direction direction, float size); |
| 195 | 196 | ||
| 197 | // Draw motion functions | ||
| 198 | void Draw3dCube(QPainter& p, QPointF center, const Common::Vec3f& euler, float size); | ||
| 199 | |||
| 196 | // Draw primitive types | 200 | // Draw primitive types |
| 197 | template <size_t N> | 201 | template <size_t N> |
| 198 | void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon); | 202 | void DrawPolygon(QPainter& p, const std::array<QPointF, N>& polygon); |
| @@ -222,4 +226,5 @@ private: | |||
| 222 | Core::HID::SticksValues stick_values{}; | 226 | Core::HID::SticksValues stick_values{}; |
| 223 | Core::HID::TriggerValues trigger_values{}; | 227 | Core::HID::TriggerValues trigger_values{}; |
| 224 | Core::HID::BatteryValues battery_values{}; | 228 | Core::HID::BatteryValues battery_values{}; |
| 229 | Core::HID::MotionState motion_values{}; | ||
| 225 | }; | 230 | }; |
diff --git a/src/yuzu/configuration/configure_system.cpp b/src/yuzu/configuration/configure_system.cpp index 6af34f793..286ccc5cd 100644 --- a/src/yuzu/configuration/configure_system.cpp +++ b/src/yuzu/configuration/configure_system.cpp | |||
| @@ -111,6 +111,9 @@ void ConfigureSystem::SetConfiguration() { | |||
| 111 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time)); | 111 | ui->custom_rtc_edit->setDateTime(QDateTime::fromSecsSinceEpoch(rtc_time)); |
| 112 | ui->device_name_edit->setText( | 112 | ui->device_name_edit->setText( |
| 113 | QString::fromUtf8(Settings::values.device_name.GetValue().c_str())); | 113 | QString::fromUtf8(Settings::values.device_name.GetValue().c_str())); |
| 114 | ui->use_unsafe_extended_memory_layout->setEnabled(enabled); | ||
| 115 | ui->use_unsafe_extended_memory_layout->setChecked( | ||
| 116 | Settings::values.use_unsafe_extended_memory_layout.GetValue()); | ||
| 114 | 117 | ||
| 115 | if (Settings::IsConfiguringGlobal()) { | 118 | if (Settings::IsConfiguringGlobal()) { |
| 116 | ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); | 119 | ui->combo_language->setCurrentIndex(Settings::values.language_index.GetValue()); |
| @@ -160,6 +163,9 @@ void ConfigureSystem::ApplyConfiguration() { | |||
| 160 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); | 163 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.region_index, ui->combo_region); |
| 161 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, | 164 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.time_zone_index, |
| 162 | ui->combo_time_zone); | 165 | ui->combo_time_zone); |
| 166 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_unsafe_extended_memory_layout, | ||
| 167 | ui->use_unsafe_extended_memory_layout, | ||
| 168 | use_unsafe_extended_memory_layout); | ||
| 163 | 169 | ||
| 164 | if (Settings::IsConfiguringGlobal()) { | 170 | if (Settings::IsConfiguringGlobal()) { |
| 165 | // Guard if during game and set to game-specific value | 171 | // Guard if during game and set to game-specific value |
| @@ -215,6 +221,10 @@ void ConfigureSystem::SetupPerGameUI() { | |||
| 215 | Settings::values.rng_seed.GetValue().has_value(), | 221 | Settings::values.rng_seed.GetValue().has_value(), |
| 216 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); | 222 | Settings::values.rng_seed.GetValue(true).has_value(), use_rng_seed); |
| 217 | 223 | ||
| 224 | ConfigurationShared::SetColoredTristate(ui->use_unsafe_extended_memory_layout, | ||
| 225 | Settings::values.use_unsafe_extended_memory_layout, | ||
| 226 | use_unsafe_extended_memory_layout); | ||
| 227 | |||
| 218 | ui->custom_rtc_checkbox->setVisible(false); | 228 | ui->custom_rtc_checkbox->setVisible(false); |
| 219 | ui->custom_rtc_edit->setVisible(false); | 229 | ui->custom_rtc_edit->setVisible(false); |
| 220 | } | 230 | } |
diff --git a/src/yuzu/configuration/configure_system.h b/src/yuzu/configuration/configure_system.h index ec28724a1..ce1a91601 100644 --- a/src/yuzu/configuration/configure_system.h +++ b/src/yuzu/configuration/configure_system.h | |||
| @@ -41,6 +41,7 @@ private: | |||
| 41 | bool enabled = false; | 41 | bool enabled = false; |
| 42 | 42 | ||
| 43 | ConfigurationShared::CheckState use_rng_seed; | 43 | ConfigurationShared::CheckState use_rng_seed; |
| 44 | ConfigurationShared::CheckState use_unsafe_extended_memory_layout; | ||
| 44 | 45 | ||
| 45 | Core::System& system; | 46 | Core::System& system; |
| 46 | }; | 47 | }; |
diff --git a/src/yuzu/configuration/configure_system.ui b/src/yuzu/configuration/configure_system.ui index 9e7bc3b93..e0caecd5e 100644 --- a/src/yuzu/configuration/configure_system.ui +++ b/src/yuzu/configuration/configure_system.ui | |||
| @@ -478,6 +478,13 @@ | |||
| 478 | </property> | 478 | </property> |
| 479 | </widget> | 479 | </widget> |
| 480 | </item> | 480 | </item> |
| 481 | <item row="7" column="0"> | ||
| 482 | <widget class="QCheckBox" name="use_unsafe_extended_memory_layout"> | ||
| 483 | <property name="text"> | ||
| 484 | <string>Unsafe extended memory layout (8GB DRAM)</string> | ||
| 485 | </property> | ||
| 486 | </widget> | ||
| 487 | </item> | ||
| 481 | </layout> | 488 | </layout> |
| 482 | </item> | 489 | </item> |
| 483 | </layout> | 490 | </layout> |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index a2f1d3d7e..352e6a4c7 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -264,7 +264,7 @@ void Config::ReadValues() { | |||
| 264 | 264 | ||
| 265 | // Core | 265 | // Core |
| 266 | ReadSetting("Core", Settings::values.use_multi_core); | 266 | ReadSetting("Core", Settings::values.use_multi_core); |
| 267 | ReadSetting("Core", Settings::values.use_extended_memory_layout); | 267 | ReadSetting("Core", Settings::values.use_unsafe_extended_memory_layout); |
| 268 | 268 | ||
| 269 | // Cpu | 269 | // Cpu |
| 270 | ReadSetting("Cpu", Settings::values.cpu_accuracy); | 270 | ReadSetting("Cpu", Settings::values.cpu_accuracy); |
| @@ -317,7 +317,6 @@ void Config::ReadValues() { | |||
| 317 | ReadSetting("Renderer", Settings::values.accelerate_astc); | 317 | ReadSetting("Renderer", Settings::values.accelerate_astc); |
| 318 | ReadSetting("Renderer", Settings::values.async_astc); | 318 | ReadSetting("Renderer", Settings::values.async_astc); |
| 319 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); | 319 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |
| 320 | ReadSetting("Renderer", Settings::values.use_pessimistic_flushes); | ||
| 321 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); | 320 | ReadSetting("Renderer", Settings::values.use_vulkan_driver_pipeline_cache); |
| 322 | 321 | ||
| 323 | ReadSetting("Renderer", Settings::values.bg_red); | 322 | ReadSetting("Renderer", Settings::values.bg_red); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index c0c89fbb9..db6fba922 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -163,9 +163,9 @@ keyboard_enabled = | |||
| 163 | # 0: Disabled, 1 (default): Enabled | 163 | # 0: Disabled, 1 (default): Enabled |
| 164 | use_multi_core = | 164 | use_multi_core = |
| 165 | 165 | ||
| 166 | # Enable extended guest system memory layout (8GB DRAM) | 166 | # Enable unsafe extended guest system memory layout (8GB DRAM) |
| 167 | # 0 (default): Disabled, 1: Enabled | 167 | # 0 (default): Disabled, 1: Enabled |
| 168 | use_extended_memory_layout = | 168 | use_unsafe_extended_memory_layout = |
| 169 | 169 | ||
| 170 | [Cpu] | 170 | [Cpu] |
| 171 | # Adjusts various optimizations. | 171 | # Adjusts various optimizations. |
| @@ -374,10 +374,6 @@ use_asynchronous_gpu_emulation = | |||
| 374 | # 0: Off, 1 (default): On | 374 | # 0: Off, 1 (default): On |
| 375 | use_fast_gpu_time = | 375 | use_fast_gpu_time = |
| 376 | 376 | ||
| 377 | # Force unmodified buffers to be flushed, which can cost performance. | ||
| 378 | # 0: Off (default), 1: On | ||
| 379 | use_pessimistic_flushes = | ||
| 380 | |||
| 381 | # Whether to use garbage collection or not for GPU caches. | 377 | # Whether to use garbage collection or not for GPU caches. |
| 382 | # 0 (default): Off, 1: On | 378 | # 0 (default): Off, 1: On |
| 383 | use_caches_gc = | 379 | use_caches_gc = |