diff options
56 files changed, 238 insertions, 492 deletions
diff --git a/CMakeLists.txt b/CMakeLists.txt index 857550e71..d98ba7767 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt | |||
| @@ -496,7 +496,7 @@ endif() | |||
| 496 | # Ensure libusb is properly configured (based on dolphin libusb include) | 496 | # Ensure libusb is properly configured (based on dolphin libusb include) |
| 497 | if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB) | 497 | if(NOT APPLE AND NOT YUZU_USE_BUNDLED_LIBUSB) |
| 498 | include(FindPkgConfig) | 498 | include(FindPkgConfig) |
| 499 | if (PKG_CONFIG_FOUND) | 499 | if (PKG_CONFIG_FOUND AND NOT CMAKE_SYSTEM_NAME MATCHES "DragonFly|FreeBSD") |
| 500 | pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24) | 500 | pkg_check_modules(LIBUSB QUIET libusb-1.0>=1.0.24) |
| 501 | else() | 501 | else() |
| 502 | find_package(LibUSB) | 502 | find_package(LibUSB) |
diff --git a/src/common/fs/fs_util.cpp b/src/common/fs/fs_util.cpp index 357cf5855..9f8671982 100644 --- a/src/common/fs/fs_util.cpp +++ b/src/common/fs/fs_util.cpp | |||
| @@ -20,6 +20,10 @@ std::string ToUTF8String(std::u8string_view u8_string) { | |||
| 20 | return std::string{u8_string.begin(), u8_string.end()}; | 20 | return std::string{u8_string.begin(), u8_string.end()}; |
| 21 | } | 21 | } |
| 22 | 22 | ||
| 23 | std::string BufferToUTF8String(std::span<const u8> buffer) { | ||
| 24 | return std::string{buffer.begin(), std::ranges::find(buffer, u8{0})}; | ||
| 25 | } | ||
| 26 | |||
| 23 | std::string PathToUTF8String(const std::filesystem::path& path) { | 27 | std::string PathToUTF8String(const std::filesystem::path& path) { |
| 24 | return ToUTF8String(path.u8string()); | 28 | return ToUTF8String(path.u8string()); |
| 25 | } | 29 | } |
diff --git a/src/common/fs/fs_util.h b/src/common/fs/fs_util.h index ec9950ee7..1ec82eb35 100644 --- a/src/common/fs/fs_util.h +++ b/src/common/fs/fs_util.h | |||
| @@ -47,6 +47,17 @@ concept IsChar = std::same_as<T, char>; | |||
| 47 | [[nodiscard]] std::string ToUTF8String(std::u8string_view u8_string); | 47 | [[nodiscard]] std::string ToUTF8String(std::u8string_view u8_string); |
| 48 | 48 | ||
| 49 | /** | 49 | /** |
| 50 | * Converts a buffer of bytes to a UTF8-encoded std::string. | ||
| 51 | * This converts from the start of the buffer until the first encountered null-terminator. | ||
| 52 | * If no null-terminator is found, this converts the entire buffer instead. | ||
| 53 | * | ||
| 54 | * @param buffer Buffer of bytes | ||
| 55 | * | ||
| 56 | * @returns UTF-8 encoded std::string. | ||
| 57 | */ | ||
| 58 | [[nodiscard]] std::string BufferToUTF8String(std::span<const u8> buffer); | ||
| 59 | |||
| 60 | /** | ||
| 50 | * Converts a filesystem path to a UTF-8 encoded std::string. | 61 | * Converts a filesystem path to a UTF-8 encoded std::string. |
| 51 | * | 62 | * |
| 52 | * @param path Filesystem path | 63 | * @param path Filesystem path |
diff --git a/src/common/host_memory.cpp b/src/common/host_memory.cpp index 2a5a7596c..6661244cf 100644 --- a/src/common/host_memory.cpp +++ b/src/common/host_memory.cpp | |||
| @@ -6,7 +6,7 @@ | |||
| 6 | #include <windows.h> | 6 | #include <windows.h> |
| 7 | #include "common/dynamic_library.h" | 7 | #include "common/dynamic_library.h" |
| 8 | 8 | ||
| 9 | #elif defined(__linux__) // ^^^ Windows ^^^ vvv Linux vvv | 9 | #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv |
| 10 | 10 | ||
| 11 | #ifndef _GNU_SOURCE | 11 | #ifndef _GNU_SOURCE |
| 12 | #define _GNU_SOURCE | 12 | #define _GNU_SOURCE |
| @@ -343,7 +343,7 @@ private: | |||
| 343 | std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset | 343 | std::unordered_map<size_t, size_t> placeholder_host_pointers; ///< Placeholder backing offset |
| 344 | }; | 344 | }; |
| 345 | 345 | ||
| 346 | #elif defined(__linux__) // ^^^ Windows ^^^ vvv Linux vvv | 346 | #elif defined(__linux__) || defined(__FreeBSD__) // ^^^ Windows ^^^ vvv Linux vvv |
| 347 | 347 | ||
| 348 | class HostMemory::Impl { | 348 | class HostMemory::Impl { |
| 349 | public: | 349 | public: |
| @@ -357,7 +357,12 @@ public: | |||
| 357 | }); | 357 | }); |
| 358 | 358 | ||
| 359 | // Backing memory initialization | 359 | // Backing memory initialization |
| 360 | #if defined(__FreeBSD__) && __FreeBSD__ < 13 | ||
| 361 | // XXX Drop after FreeBSD 12.* reaches EOL on 2024-06-30 | ||
| 362 | fd = shm_open(SHM_ANON, O_RDWR, 0600); | ||
| 363 | #else | ||
| 360 | fd = memfd_create("HostMemory", 0); | 364 | fd = memfd_create("HostMemory", 0); |
| 365 | #endif | ||
| 361 | if (fd == -1) { | 366 | if (fd == -1) { |
| 362 | LOG_CRITICAL(HW_Memory, "memfd_create failed: {}", strerror(errno)); | 367 | LOG_CRITICAL(HW_Memory, "memfd_create failed: {}", strerror(errno)); |
| 363 | throw std::bad_alloc{}; | 368 | throw std::bad_alloc{}; |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index 66268ea0f..996315999 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -48,8 +48,8 @@ void LogSettings() { | |||
| 48 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); | 48 | log_setting("Core_UseMultiCore", values.use_multi_core.GetValue()); |
| 49 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); | 49 | log_setting("CPU_Accuracy", values.cpu_accuracy.GetValue()); |
| 50 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); | 50 | log_setting("Renderer_UseResolutionFactor", values.resolution_factor.GetValue()); |
| 51 | log_setting("Renderer_UseFrameLimit", values.use_frame_limit.GetValue()); | 51 | log_setting("Renderer_UseSpeedLimit", values.use_speed_limit.GetValue()); |
| 52 | log_setting("Renderer_FrameLimit", values.frame_limit.GetValue()); | 52 | log_setting("Renderer_SpeedLimit", values.speed_limit.GetValue()); |
| 53 | log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); | 53 | log_setting("Renderer_UseDiskShaderCache", values.use_disk_shader_cache.GetValue()); |
| 54 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); | 54 | log_setting("Renderer_GPUAccuracyLevel", values.gpu_accuracy.GetValue()); |
| 55 | log_setting("Renderer_UseAsynchronousGpuEmulation", | 55 | log_setting("Renderer_UseAsynchronousGpuEmulation", |
| @@ -132,8 +132,8 @@ void RestoreGlobalState(bool is_powered_on) { | |||
| 132 | values.vulkan_device.SetGlobal(true); | 132 | values.vulkan_device.SetGlobal(true); |
| 133 | values.aspect_ratio.SetGlobal(true); | 133 | values.aspect_ratio.SetGlobal(true); |
| 134 | values.max_anisotropy.SetGlobal(true); | 134 | values.max_anisotropy.SetGlobal(true); |
| 135 | values.use_frame_limit.SetGlobal(true); | 135 | values.use_speed_limit.SetGlobal(true); |
| 136 | values.frame_limit.SetGlobal(true); | 136 | values.speed_limit.SetGlobal(true); |
| 137 | values.use_disk_shader_cache.SetGlobal(true); | 137 | values.use_disk_shader_cache.SetGlobal(true); |
| 138 | values.gpu_accuracy.SetGlobal(true); | 138 | values.gpu_accuracy.SetGlobal(true); |
| 139 | values.use_asynchronous_gpu_emulation.SetGlobal(true); | 139 | values.use_asynchronous_gpu_emulation.SetGlobal(true); |
diff --git a/src/common/settings.h b/src/common/settings.h index df1762d1b..cfc1ab46f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -42,6 +42,11 @@ enum class CPUAccuracy : u32 { | |||
| 42 | Unsafe = 2, | 42 | Unsafe = 2, |
| 43 | }; | 43 | }; |
| 44 | 44 | ||
| 45 | enum class FullscreenMode : u32 { | ||
| 46 | Borderless = 0, | ||
| 47 | Exclusive = 1, | ||
| 48 | }; | ||
| 49 | |||
| 45 | /** The BasicSetting class is a simple resource manager. It defines a label and default value | 50 | /** The BasicSetting class is a simple resource manager. It defines a label and default value |
| 46 | * alongside the actual value of the setting for simpler and less-error prone use with frontend | 51 | * alongside the actual value of the setting for simpler and less-error prone use with frontend |
| 47 | * configurations. Setting a default value and label is required, though subclasses may deviate from | 52 | * configurations. Setting a default value and label is required, though subclasses may deviate from |
| @@ -322,17 +327,17 @@ struct Values { | |||
| 322 | Setting<u16> resolution_factor{1, "resolution_factor"}; | 327 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
| 323 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 328 | // *nix platforms may have issues with the borderless windowed fullscreen mode. |
| 324 | // Default to exclusive fullscreen on these platforms for now. | 329 | // Default to exclusive fullscreen on these platforms for now. |
| 325 | Setting<int> fullscreen_mode{ | 330 | Setting<FullscreenMode> fullscreen_mode{ |
| 326 | #ifdef _WIN32 | 331 | #ifdef _WIN32 |
| 327 | 0, | 332 | FullscreenMode::Borderless, |
| 328 | #else | 333 | #else |
| 329 | 1, | 334 | FullscreenMode::Exclusive, |
| 330 | #endif | 335 | #endif |
| 331 | "fullscreen_mode"}; | 336 | "fullscreen_mode"}; |
| 332 | Setting<int> aspect_ratio{0, "aspect_ratio"}; | 337 | Setting<int> aspect_ratio{0, "aspect_ratio"}; |
| 333 | Setting<int> max_anisotropy{0, "max_anisotropy"}; | 338 | Setting<int> max_anisotropy{0, "max_anisotropy"}; |
| 334 | Setting<bool> use_frame_limit{true, "use_frame_limit"}; | 339 | Setting<bool> use_speed_limit{true, "use_speed_limit"}; |
| 335 | Setting<u16> frame_limit{100, "frame_limit"}; | 340 | Setting<u16> speed_limit{100, "speed_limit"}; |
| 336 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; | 341 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; |
| 337 | Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"}; | 342 | Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"}; |
| 338 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; | 343 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; |
diff --git a/src/common/uuid.cpp b/src/common/uuid.cpp index 26db03fba..18303a1e3 100644 --- a/src/common/uuid.cpp +++ b/src/common/uuid.cpp | |||
| @@ -18,7 +18,7 @@ UUID UUID::Generate() { | |||
| 18 | } | 18 | } |
| 19 | 19 | ||
| 20 | std::string UUID::Format() const { | 20 | std::string UUID::Format() const { |
| 21 | return fmt::format("0x{:016X}{:016X}", uuid[1], uuid[0]); | 21 | return fmt::format("{:016x}{:016x}", uuid[1], uuid[0]); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | std::string UUID::FormatSwitch() const { | 24 | std::string UUID::FormatSwitch() const { |
diff --git a/src/core/core.cpp b/src/core/core.cpp index 15226cf41..d3e84c4ef 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -411,7 +411,7 @@ struct System::Impl { | |||
| 411 | std::string status_details = ""; | 411 | std::string status_details = ""; |
| 412 | 412 | ||
| 413 | std::unique_ptr<Core::PerfStats> perf_stats; | 413 | std::unique_ptr<Core::PerfStats> perf_stats; |
| 414 | Core::FrameLimiter frame_limiter; | 414 | Core::SpeedLimiter speed_limiter; |
| 415 | 415 | ||
| 416 | bool is_multicore{}; | 416 | bool is_multicore{}; |
| 417 | bool is_async_gpu{}; | 417 | bool is_async_gpu{}; |
| @@ -606,12 +606,12 @@ const Core::PerfStats& System::GetPerfStats() const { | |||
| 606 | return *impl->perf_stats; | 606 | return *impl->perf_stats; |
| 607 | } | 607 | } |
| 608 | 608 | ||
| 609 | Core::FrameLimiter& System::FrameLimiter() { | 609 | Core::SpeedLimiter& System::SpeedLimiter() { |
| 610 | return impl->frame_limiter; | 610 | return impl->speed_limiter; |
| 611 | } | 611 | } |
| 612 | 612 | ||
| 613 | const Core::FrameLimiter& System::FrameLimiter() const { | 613 | const Core::SpeedLimiter& System::SpeedLimiter() const { |
| 614 | return impl->frame_limiter; | 614 | return impl->speed_limiter; |
| 615 | } | 615 | } |
| 616 | 616 | ||
| 617 | Loader::ResultStatus System::GetGameName(std::string& out) const { | 617 | Loader::ResultStatus System::GetGameName(std::string& out) const { |
diff --git a/src/core/core.h b/src/core/core.h index b93c32e60..ea143043c 100644 --- a/src/core/core.h +++ b/src/core/core.h | |||
| @@ -94,7 +94,7 @@ class ARM_Interface; | |||
| 94 | class CpuManager; | 94 | class CpuManager; |
| 95 | class DeviceMemory; | 95 | class DeviceMemory; |
| 96 | class ExclusiveMonitor; | 96 | class ExclusiveMonitor; |
| 97 | class FrameLimiter; | 97 | class SpeedLimiter; |
| 98 | class PerfStats; | 98 | class PerfStats; |
| 99 | class Reporter; | 99 | class Reporter; |
| 100 | class TelemetrySession; | 100 | class TelemetrySession; |
| @@ -292,11 +292,11 @@ public: | |||
| 292 | /// Provides a constant reference to the internal PerfStats instance. | 292 | /// Provides a constant reference to the internal PerfStats instance. |
| 293 | [[nodiscard]] const Core::PerfStats& GetPerfStats() const; | 293 | [[nodiscard]] const Core::PerfStats& GetPerfStats() const; |
| 294 | 294 | ||
| 295 | /// Provides a reference to the frame limiter; | 295 | /// Provides a reference to the speed limiter; |
| 296 | [[nodiscard]] Core::FrameLimiter& FrameLimiter(); | 296 | [[nodiscard]] Core::SpeedLimiter& SpeedLimiter(); |
| 297 | 297 | ||
| 298 | /// Provides a constant referent to the frame limiter | 298 | /// Provides a constant reference to the speed limiter |
| 299 | [[nodiscard]] const Core::FrameLimiter& FrameLimiter() const; | 299 | [[nodiscard]] const Core::SpeedLimiter& SpeedLimiter() const; |
| 300 | 300 | ||
| 301 | /// Gets the name of the current game | 301 | /// Gets the name of the current game |
| 302 | [[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const; | 302 | [[nodiscard]] Loader::ResultStatus GetGameName(std::string& out) const; |
diff --git a/src/core/hle/service/acc/acc.cpp b/src/core/hle/service/acc/acc.cpp index 2e969f2a8..882fc1492 100644 --- a/src/core/hle/service/acc/acc.cpp +++ b/src/core/hle/service/acc/acc.cpp | |||
| @@ -292,7 +292,7 @@ public: | |||
| 292 | 292 | ||
| 293 | protected: | 293 | protected: |
| 294 | void Get(Kernel::HLERequestContext& ctx) { | 294 | void Get(Kernel::HLERequestContext& ctx) { |
| 295 | LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); | 295 | LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format()); |
| 296 | ProfileBase profile_base{}; | 296 | ProfileBase profile_base{}; |
| 297 | ProfileData data{}; | 297 | ProfileData data{}; |
| 298 | if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) { | 298 | if (profile_manager.GetProfileBaseAndData(user_id, profile_base, data)) { |
| @@ -301,7 +301,7 @@ protected: | |||
| 301 | rb.Push(ResultSuccess); | 301 | rb.Push(ResultSuccess); |
| 302 | rb.PushRaw(profile_base); | 302 | rb.PushRaw(profile_base); |
| 303 | } else { | 303 | } else { |
| 304 | LOG_ERROR(Service_ACC, "Failed to get profile base and data for user={}", | 304 | LOG_ERROR(Service_ACC, "Failed to get profile base and data for user=0x{}", |
| 305 | user_id.Format()); | 305 | user_id.Format()); |
| 306 | IPC::ResponseBuilder rb{ctx, 2}; | 306 | IPC::ResponseBuilder rb{ctx, 2}; |
| 307 | rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code | 307 | rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code |
| @@ -309,14 +309,14 @@ protected: | |||
| 309 | } | 309 | } |
| 310 | 310 | ||
| 311 | void GetBase(Kernel::HLERequestContext& ctx) { | 311 | void GetBase(Kernel::HLERequestContext& ctx) { |
| 312 | LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); | 312 | LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format()); |
| 313 | ProfileBase profile_base{}; | 313 | ProfileBase profile_base{}; |
| 314 | if (profile_manager.GetProfileBase(user_id, profile_base)) { | 314 | if (profile_manager.GetProfileBase(user_id, profile_base)) { |
| 315 | IPC::ResponseBuilder rb{ctx, 16}; | 315 | IPC::ResponseBuilder rb{ctx, 16}; |
| 316 | rb.Push(ResultSuccess); | 316 | rb.Push(ResultSuccess); |
| 317 | rb.PushRaw(profile_base); | 317 | rb.PushRaw(profile_base); |
| 318 | } else { | 318 | } else { |
| 319 | LOG_ERROR(Service_ACC, "Failed to get profile base for user={}", user_id.Format()); | 319 | LOG_ERROR(Service_ACC, "Failed to get profile base for user=0x{}", user_id.Format()); |
| 320 | IPC::ResponseBuilder rb{ctx, 2}; | 320 | IPC::ResponseBuilder rb{ctx, 2}; |
| 321 | rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code | 321 | rb.Push(ResultUnknown); // TODO(ogniK): Get actual error code |
| 322 | } | 322 | } |
| @@ -372,7 +372,7 @@ protected: | |||
| 372 | 372 | ||
| 373 | const auto user_data = ctx.ReadBuffer(); | 373 | const auto user_data = ctx.ReadBuffer(); |
| 374 | 374 | ||
| 375 | LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}", | 375 | LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid=0x{}", |
| 376 | Common::StringFromFixedZeroTerminatedBuffer( | 376 | Common::StringFromFixedZeroTerminatedBuffer( |
| 377 | reinterpret_cast<const char*>(base.username.data()), base.username.size()), | 377 | reinterpret_cast<const char*>(base.username.data()), base.username.size()), |
| 378 | base.timestamp, base.user_uuid.Format()); | 378 | base.timestamp, base.user_uuid.Format()); |
| @@ -405,7 +405,7 @@ protected: | |||
| 405 | const auto user_data = ctx.ReadBuffer(); | 405 | const auto user_data = ctx.ReadBuffer(); |
| 406 | const auto image_data = ctx.ReadBuffer(1); | 406 | const auto image_data = ctx.ReadBuffer(1); |
| 407 | 407 | ||
| 408 | LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid={}", | 408 | LOG_DEBUG(Service_ACC, "called, username='{}', timestamp={:016X}, uuid=0x{}", |
| 409 | Common::StringFromFixedZeroTerminatedBuffer( | 409 | Common::StringFromFixedZeroTerminatedBuffer( |
| 410 | reinterpret_cast<const char*>(base.username.data()), base.username.size()), | 410 | reinterpret_cast<const char*>(base.username.data()), base.username.size()), |
| 411 | base.timestamp, base.user_uuid.Format()); | 411 | base.timestamp, base.user_uuid.Format()); |
| @@ -662,7 +662,7 @@ void Module::Interface::GetUserCount(Kernel::HLERequestContext& ctx) { | |||
| 662 | void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { | 662 | void Module::Interface::GetUserExistence(Kernel::HLERequestContext& ctx) { |
| 663 | IPC::RequestParser rp{ctx}; | 663 | IPC::RequestParser rp{ctx}; |
| 664 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); | 664 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); |
| 665 | LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); | 665 | LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format()); |
| 666 | 666 | ||
| 667 | IPC::ResponseBuilder rb{ctx, 3}; | 667 | IPC::ResponseBuilder rb{ctx, 3}; |
| 668 | rb.Push(ResultSuccess); | 668 | rb.Push(ResultSuccess); |
| @@ -693,7 +693,7 @@ void Module::Interface::GetLastOpenedUser(Kernel::HLERequestContext& ctx) { | |||
| 693 | void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { | 693 | void Module::Interface::GetProfile(Kernel::HLERequestContext& ctx) { |
| 694 | IPC::RequestParser rp{ctx}; | 694 | IPC::RequestParser rp{ctx}; |
| 695 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); | 695 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); |
| 696 | LOG_DEBUG(Service_ACC, "called user_id={}", user_id.Format()); | 696 | LOG_DEBUG(Service_ACC, "called user_id=0x{}", user_id.Format()); |
| 697 | 697 | ||
| 698 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 698 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 699 | rb.Push(ResultSuccess); | 699 | rb.Push(ResultSuccess); |
| @@ -802,7 +802,7 @@ void Module::Interface::GetProfileEditor(Kernel::HLERequestContext& ctx) { | |||
| 802 | IPC::RequestParser rp{ctx}; | 802 | IPC::RequestParser rp{ctx}; |
| 803 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); | 803 | Common::UUID user_id = rp.PopRaw<Common::UUID>(); |
| 804 | 804 | ||
| 805 | LOG_DEBUG(Service_ACC, "called, user_id={}", user_id.Format()); | 805 | LOG_DEBUG(Service_ACC, "called, user_id=0x{}", user_id.Format()); |
| 806 | 806 | ||
| 807 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 807 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 808 | rb.Push(ResultSuccess); | 808 | rb.Push(ResultSuccess); |
| @@ -844,7 +844,7 @@ void Module::Interface::StoreSaveDataThumbnailApplication(Kernel::HLERequestCont | |||
| 844 | IPC::RequestParser rp{ctx}; | 844 | IPC::RequestParser rp{ctx}; |
| 845 | const auto uuid = rp.PopRaw<Common::UUID>(); | 845 | const auto uuid = rp.PopRaw<Common::UUID>(); |
| 846 | 846 | ||
| 847 | LOG_WARNING(Service_ACC, "(STUBBED) called, uuid={}", uuid.Format()); | 847 | LOG_WARNING(Service_ACC, "(STUBBED) called, uuid=0x{}", uuid.Format()); |
| 848 | 848 | ||
| 849 | // TODO(ogniK): Check if application ID is zero on acc initialize. As we don't have a reliable | 849 | // TODO(ogniK): Check if application ID is zero on acc initialize. As we don't have a reliable |
| 850 | // way of confirming things like the TID, we're going to assume a non zero value for the time | 850 | // way of confirming things like the TID, we're going to assume a non zero value for the time |
| @@ -858,7 +858,7 @@ void Module::Interface::StoreSaveDataThumbnailSystem(Kernel::HLERequestContext& | |||
| 858 | const auto uuid = rp.PopRaw<Common::UUID>(); | 858 | const auto uuid = rp.PopRaw<Common::UUID>(); |
| 859 | const auto tid = rp.Pop<u64_le>(); | 859 | const auto tid = rp.Pop<u64_le>(); |
| 860 | 860 | ||
| 861 | LOG_WARNING(Service_ACC, "(STUBBED) called, uuid={}, tid={:016X}", uuid.Format(), tid); | 861 | LOG_WARNING(Service_ACC, "(STUBBED) called, uuid=0x{}, tid={:016X}", uuid.Format(), tid); |
| 862 | StoreSaveDataThumbnail(ctx, uuid, tid); | 862 | StoreSaveDataThumbnail(ctx, uuid, tid); |
| 863 | } | 863 | } |
| 864 | 864 | ||
diff --git a/src/core/hle/service/friend/friend.cpp b/src/core/hle/service/friend/friend.cpp index a3c939c0c..b58c152ce 100644 --- a/src/core/hle/service/friend/friend.cpp +++ b/src/core/hle/service/friend/friend.cpp | |||
| @@ -158,7 +158,7 @@ private: | |||
| 158 | const auto local_play = rp.Pop<bool>(); | 158 | const auto local_play = rp.Pop<bool>(); |
| 159 | const auto uuid = rp.PopRaw<Common::UUID>(); | 159 | const auto uuid = rp.PopRaw<Common::UUID>(); |
| 160 | 160 | ||
| 161 | LOG_WARNING(Service_Friend, "(STUBBED) called local_play={} uuid={}", local_play, | 161 | LOG_WARNING(Service_Friend, "(STUBBED) called, local_play={}, uuid=0x{}", local_play, |
| 162 | uuid.Format()); | 162 | uuid.Format()); |
| 163 | 163 | ||
| 164 | IPC::ResponseBuilder rb{ctx, 2}; | 164 | IPC::ResponseBuilder rb{ctx, 2}; |
| @@ -171,7 +171,7 @@ private: | |||
| 171 | const auto uuid = rp.PopRaw<Common::UUID>(); | 171 | const auto uuid = rp.PopRaw<Common::UUID>(); |
| 172 | [[maybe_unused]] const auto filter = rp.PopRaw<SizedFriendFilter>(); | 172 | [[maybe_unused]] const auto filter = rp.PopRaw<SizedFriendFilter>(); |
| 173 | const auto pid = rp.Pop<u64>(); | 173 | const auto pid = rp.Pop<u64>(); |
| 174 | LOG_WARNING(Service_Friend, "(STUBBED) called, offset={}, uuid={}, pid={}", friend_offset, | 174 | LOG_WARNING(Service_Friend, "(STUBBED) called, offset={}, uuid=0x{}, pid={}", friend_offset, |
| 175 | uuid.Format(), pid); | 175 | uuid.Format(), pid); |
| 176 | 176 | ||
| 177 | IPC::ResponseBuilder rb{ctx, 3}; | 177 | IPC::ResponseBuilder rb{ctx, 3}; |
| @@ -289,7 +289,7 @@ void Module::Interface::CreateNotificationService(Kernel::HLERequestContext& ctx | |||
| 289 | IPC::RequestParser rp{ctx}; | 289 | IPC::RequestParser rp{ctx}; |
| 290 | auto uuid = rp.PopRaw<Common::UUID>(); | 290 | auto uuid = rp.PopRaw<Common::UUID>(); |
| 291 | 291 | ||
| 292 | LOG_DEBUG(Service_Friend, "called, uuid={}", uuid.Format()); | 292 | LOG_DEBUG(Service_Friend, "called, uuid=0x{}", uuid.Format()); |
| 293 | 293 | ||
| 294 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; | 294 | IPC::ResponseBuilder rb{ctx, 2, 0, 1}; |
| 295 | rb.Push(ResultSuccess); | 295 | rb.Push(ResultSuccess); |
diff --git a/src/core/hle/service/ns/language.cpp b/src/core/hle/service/ns/language.cpp index 29c4a820c..54b644830 100644 --- a/src/core/hle/service/ns/language.cpp +++ b/src/core/hle/service/ns/language.cpp | |||
| @@ -344,8 +344,10 @@ std::optional<ApplicationLanguage> ConvertToApplicationLanguage( | |||
| 344 | return ApplicationLanguage::Russian; | 344 | return ApplicationLanguage::Russian; |
| 345 | case Set::LanguageCode::KO: | 345 | case Set::LanguageCode::KO: |
| 346 | return ApplicationLanguage::Korean; | 346 | return ApplicationLanguage::Korean; |
| 347 | case Set::LanguageCode::ZH_TW: | ||
| 347 | case Set::LanguageCode::ZH_HANT: | 348 | case Set::LanguageCode::ZH_HANT: |
| 348 | return ApplicationLanguage::TraditionalChinese; | 349 | return ApplicationLanguage::TraditionalChinese; |
| 350 | case Set::LanguageCode::ZH_CN: | ||
| 349 | case Set::LanguageCode::ZH_HANS: | 351 | case Set::LanguageCode::ZH_HANS: |
| 350 | return ApplicationLanguage::SimplifiedChinese; | 352 | return ApplicationLanguage::SimplifiedChinese; |
| 351 | default: | 353 | default: |
diff --git a/src/core/hle/service/ns/ns_language.h b/src/core/hle/service/ns/ns_language.h deleted file mode 100644 index 59ac85a19..000000000 --- a/src/core/hle/service/ns/ns_language.h +++ /dev/null | |||
| @@ -1,42 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | #include <optional> | ||
| 7 | #include <string> | ||
| 8 | #include "common/common_types.h" | ||
| 9 | #include "core/hle/service/set/set.h" | ||
| 10 | |||
| 11 | namespace Service::NS { | ||
| 12 | /// This is nn::ns::detail::ApplicationLanguage | ||
| 13 | enum class ApplicationLanguage : u8 { | ||
| 14 | AmericanEnglish = 0, | ||
| 15 | BritishEnglish, | ||
| 16 | Japanese, | ||
| 17 | French, | ||
| 18 | German, | ||
| 19 | LatinAmericanSpanish, | ||
| 20 | Spanish, | ||
| 21 | Italian, | ||
| 22 | Dutch, | ||
| 23 | CanadianFrench, | ||
| 24 | Portuguese, | ||
| 25 | Russian, | ||
| 26 | Korean, | ||
| 27 | TraditionalChinese, | ||
| 28 | SimplifiedChinese, | ||
| 29 | Count | ||
| 30 | }; | ||
| 31 | using ApplicationLanguagePriorityList = | ||
| 32 | const std::array<ApplicationLanguage, static_cast<std::size_t>(ApplicationLanguage::Count)>; | ||
| 33 | |||
| 34 | constexpr u32 GetSupportedLanguageFlag(const ApplicationLanguage lang) { | ||
| 35 | return 1U << static_cast<u32>(lang); | ||
| 36 | } | ||
| 37 | |||
| 38 | const ApplicationLanguagePriorityList* GetApplicationLanguagePriorityList(ApplicationLanguage lang); | ||
| 39 | std::optional<ApplicationLanguage> ConvertToApplicationLanguage( | ||
| 40 | Service::Set::LanguageCode language_code); | ||
| 41 | std::optional<Service::Set::LanguageCode> ConvertToLanguageCode(ApplicationLanguage lang); | ||
| 42 | } // namespace Service::NS \ No newline at end of file | ||
diff --git a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp index 2cc0da124..ce6065db2 100644 --- a/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp +++ b/src/core/hle/service/nvdrv/devices/nvdisp_disp0.cpp | |||
| @@ -54,7 +54,7 @@ void nvdisp_disp0::flip(u32 buffer_handle, u32 offset, u32 format, u32 width, u3 | |||
| 54 | 54 | ||
| 55 | system.GetPerfStats().EndSystemFrame(); | 55 | system.GetPerfStats().EndSystemFrame(); |
| 56 | system.GPU().SwapBuffers(&framebuffer); | 56 | system.GPU().SwapBuffers(&framebuffer); |
| 57 | system.FrameLimiter().DoFrameLimiting(system.CoreTiming().GetGlobalTimeUs()); | 57 | system.SpeedLimiter().DoSpeedLimiting(system.CoreTiming().GetGlobalTimeUs()); |
| 58 | system.GetPerfStats().BeginSystemFrame(); | 58 | system.GetPerfStats().BeginSystemFrame(); |
| 59 | } | 59 | } |
| 60 | 60 | ||
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 6635a1339..c9ded49d0 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -127,15 +127,15 @@ double PerfStats::GetLastFrameTimeScale() const { | |||
| 127 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; | 127 | return duration_cast<DoubleSecs>(previous_frame_length).count() / FRAME_LENGTH; |
| 128 | } | 128 | } |
| 129 | 129 | ||
| 130 | void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { | 130 | void SpeedLimiter::DoSpeedLimiting(microseconds current_system_time_us) { |
| 131 | if (!Settings::values.use_frame_limit.GetValue() || | 131 | if (!Settings::values.use_speed_limit.GetValue() || |
| 132 | Settings::values.use_multi_core.GetValue()) { | 132 | Settings::values.use_multi_core.GetValue()) { |
| 133 | return; | 133 | return; |
| 134 | } | 134 | } |
| 135 | 135 | ||
| 136 | auto now = Clock::now(); | 136 | auto now = Clock::now(); |
| 137 | 137 | ||
| 138 | const double sleep_scale = Settings::values.frame_limit.GetValue() / 100.0; | 138 | const double sleep_scale = Settings::values.speed_limit.GetValue() / 100.0; |
| 139 | 139 | ||
| 140 | // Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current | 140 | // Max lag caused by slow frames. Shouldn't be more than the length of a frame at the current |
| 141 | // speed percent or it will clamp too much and prevent this from properly limiting to that | 141 | // speed percent or it will clamp too much and prevent this from properly limiting to that |
| @@ -143,17 +143,17 @@ void FrameLimiter::DoFrameLimiting(microseconds current_system_time_us) { | |||
| 143 | // limiting | 143 | // limiting |
| 144 | const microseconds max_lag_time_us = duration_cast<microseconds>( | 144 | const microseconds max_lag_time_us = duration_cast<microseconds>( |
| 145 | std::chrono::duration<double, std::chrono::microseconds::period>(25ms / sleep_scale)); | 145 | std::chrono::duration<double, std::chrono::microseconds::period>(25ms / sleep_scale)); |
| 146 | frame_limiting_delta_err += duration_cast<microseconds>( | 146 | speed_limiting_delta_err += duration_cast<microseconds>( |
| 147 | std::chrono::duration<double, std::chrono::microseconds::period>( | 147 | std::chrono::duration<double, std::chrono::microseconds::period>( |
| 148 | (current_system_time_us - previous_system_time_us) / sleep_scale)); | 148 | (current_system_time_us - previous_system_time_us) / sleep_scale)); |
| 149 | frame_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime); | 149 | speed_limiting_delta_err -= duration_cast<microseconds>(now - previous_walltime); |
| 150 | frame_limiting_delta_err = | 150 | speed_limiting_delta_err = |
| 151 | std::clamp(frame_limiting_delta_err, -max_lag_time_us, max_lag_time_us); | 151 | std::clamp(speed_limiting_delta_err, -max_lag_time_us, max_lag_time_us); |
| 152 | 152 | ||
| 153 | if (frame_limiting_delta_err > microseconds::zero()) { | 153 | if (speed_limiting_delta_err > microseconds::zero()) { |
| 154 | std::this_thread::sleep_for(frame_limiting_delta_err); | 154 | std::this_thread::sleep_for(speed_limiting_delta_err); |
| 155 | auto now_after_sleep = Clock::now(); | 155 | auto now_after_sleep = Clock::now(); |
| 156 | frame_limiting_delta_err -= duration_cast<microseconds>(now_after_sleep - now); | 156 | speed_limiting_delta_err -= duration_cast<microseconds>(now_after_sleep - now); |
| 157 | now = now_after_sleep; | 157 | now = now_after_sleep; |
| 158 | } | 158 | } |
| 159 | 159 | ||
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index e5d603717..a2541906f 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h | |||
| @@ -85,11 +85,11 @@ private: | |||
| 85 | double previous_fps = 0; | 85 | double previous_fps = 0; |
| 86 | }; | 86 | }; |
| 87 | 87 | ||
| 88 | class FrameLimiter { | 88 | class SpeedLimiter { |
| 89 | public: | 89 | public: |
| 90 | using Clock = std::chrono::high_resolution_clock; | 90 | using Clock = std::chrono::high_resolution_clock; |
| 91 | 91 | ||
| 92 | void DoFrameLimiting(std::chrono::microseconds current_system_time_us); | 92 | void DoSpeedLimiting(std::chrono::microseconds current_system_time_us); |
| 93 | 93 | ||
| 94 | private: | 94 | private: |
| 95 | /// Emulated system time (in microseconds) at the last limiter invocation | 95 | /// Emulated system time (in microseconds) at the last limiter invocation |
| @@ -98,7 +98,7 @@ private: | |||
| 98 | Clock::time_point previous_walltime = Clock::now(); | 98 | Clock::time_point previous_walltime = Clock::now(); |
| 99 | 99 | ||
| 100 | /// Accumulated difference between walltime and emulated time | 100 | /// Accumulated difference between walltime and emulated time |
| 101 | std::chrono::microseconds frame_limiting_delta_err{0}; | 101 | std::chrono::microseconds speed_limiting_delta_err{0}; |
| 102 | }; | 102 | }; |
| 103 | 103 | ||
| 104 | } // namespace Core | 104 | } // namespace Core |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index 422de3a7d..5a8cfd301 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -221,8 +221,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 221 | TranslateRenderer(Settings::values.renderer_backend.GetValue())); | 221 | TranslateRenderer(Settings::values.renderer_backend.GetValue())); |
| 222 | AddField(field_type, "Renderer_ResolutionFactor", | 222 | AddField(field_type, "Renderer_ResolutionFactor", |
| 223 | Settings::values.resolution_factor.GetValue()); | 223 | Settings::values.resolution_factor.GetValue()); |
| 224 | AddField(field_type, "Renderer_UseFrameLimit", Settings::values.use_frame_limit.GetValue()); | 224 | AddField(field_type, "Renderer_UseSpeedLimit", Settings::values.use_speed_limit.GetValue()); |
| 225 | AddField(field_type, "Renderer_FrameLimit", Settings::values.frame_limit.GetValue()); | 225 | AddField(field_type, "Renderer_SpeedLimit", Settings::values.speed_limit.GetValue()); |
| 226 | AddField(field_type, "Renderer_UseDiskShaderCache", | 226 | AddField(field_type, "Renderer_UseDiskShaderCache", |
| 227 | Settings::values.use_disk_shader_cache.GetValue()); | 227 | Settings::values.use_disk_shader_cache.GetValue()); |
| 228 | AddField(field_type, "Renderer_GPUAccuracyLevel", | 228 | AddField(field_type, "Renderer_GPUAccuracyLevel", |
diff --git a/src/shader_recompiler/backend/glasm/emit_glasm.cpp b/src/shader_recompiler/backend/glasm/emit_glasm.cpp index a5e8c9b6e..4ce1c4f54 100644 --- a/src/shader_recompiler/backend/glasm/emit_glasm.cpp +++ b/src/shader_recompiler/backend/glasm/emit_glasm.cpp | |||
| @@ -350,7 +350,7 @@ std::string_view InputPrimitive(InputTopology topology) { | |||
| 350 | case InputTopology::Lines: | 350 | case InputTopology::Lines: |
| 351 | return "LINES"; | 351 | return "LINES"; |
| 352 | case InputTopology::LinesAdjacency: | 352 | case InputTopology::LinesAdjacency: |
| 353 | return "LINESS_ADJACENCY"; | 353 | return "LINES_ADJACENCY"; |
| 354 | case InputTopology::Triangles: | 354 | case InputTopology::Triangles: |
| 355 | return "TRIANGLES"; | 355 | return "TRIANGLES"; |
| 356 | case InputTopology::TrianglesAdjacency: | 356 | case InputTopology::TrianglesAdjacency: |
diff --git a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h index f99c02848..c9db1c164 100644 --- a/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h +++ b/src/shader_recompiler/backend/spirv/emit_spirv_instructions.h | |||
| @@ -2,6 +2,8 @@ | |||
| 2 | // Licensed under GPLv2 or any later version | 2 | // Licensed under GPLv2 or any later version |
| 3 | // Refer to the license.txt file included. | 3 | // Refer to the license.txt file included. |
| 4 | 4 | ||
| 5 | #pragma once | ||
| 6 | |||
| 5 | #include <sirit/sirit.h> | 7 | #include <sirit/sirit.h> |
| 6 | 8 | ||
| 7 | #include "common/common_types.h" | 9 | #include "common/common_types.h" |
diff --git a/src/shader_recompiler/exception.h b/src/shader_recompiler/exception.h index 337e7f0c8..277be8541 100644 --- a/src/shader_recompiler/exception.h +++ b/src/shader_recompiler/exception.h | |||
| @@ -4,7 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <stdexcept> | 7 | #include <exception> |
| 8 | #include <string> | 8 | #include <string> |
| 9 | #include <string_view> | 9 | #include <string_view> |
| 10 | #include <utility> | 10 | #include <utility> |
| @@ -17,7 +17,7 @@ class Exception : public std::exception { | |||
| 17 | public: | 17 | public: |
| 18 | explicit Exception(std::string message) noexcept : err_message{std::move(message)} {} | 18 | explicit Exception(std::string message) noexcept : err_message{std::move(message)} {} |
| 19 | 19 | ||
| 20 | const char* what() const noexcept override { | 20 | [[nodiscard]] const char* what() const noexcept override { |
| 21 | return err_message.c_str(); | 21 | return err_message.c_str(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| @@ -36,21 +36,21 @@ private: | |||
| 36 | class LogicError : public Exception { | 36 | class LogicError : public Exception { |
| 37 | public: | 37 | public: |
| 38 | template <typename... Args> | 38 | template <typename... Args> |
| 39 | LogicError(const char* message, Args&&... args) | 39 | explicit LogicError(const char* message, Args&&... args) |
| 40 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} | 40 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} |
| 41 | }; | 41 | }; |
| 42 | 42 | ||
| 43 | class RuntimeError : public Exception { | 43 | class RuntimeError : public Exception { |
| 44 | public: | 44 | public: |
| 45 | template <typename... Args> | 45 | template <typename... Args> |
| 46 | RuntimeError(const char* message, Args&&... args) | 46 | explicit RuntimeError(const char* message, Args&&... args) |
| 47 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} | 47 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} |
| 48 | }; | 48 | }; |
| 49 | 49 | ||
| 50 | class NotImplementedException : public Exception { | 50 | class NotImplementedException : public Exception { |
| 51 | public: | 51 | public: |
| 52 | template <typename... Args> | 52 | template <typename... Args> |
| 53 | NotImplementedException(const char* message, Args&&... args) | 53 | explicit NotImplementedException(const char* message, Args&&... args) |
| 54 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} { | 54 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} { |
| 55 | Append(" is not implemented"); | 55 | Append(" is not implemented"); |
| 56 | } | 56 | } |
| @@ -59,7 +59,7 @@ public: | |||
| 59 | class InvalidArgument : public Exception { | 59 | class InvalidArgument : public Exception { |
| 60 | public: | 60 | public: |
| 61 | template <typename... Args> | 61 | template <typename... Args> |
| 62 | InvalidArgument(const char* message, Args&&... args) | 62 | explicit InvalidArgument(const char* message, Args&&... args) |
| 63 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} | 63 | : Exception{fmt::format(fmt::runtime(message), std::forward<Args>(args)...)} {} |
| 64 | }; | 64 | }; |
| 65 | 65 | ||
diff --git a/src/shader_recompiler/frontend/ir/ir_emitter.h b/src/shader_recompiler/frontend/ir/ir_emitter.h index 53f7b3b06..1b89ca5a0 100644 --- a/src/shader_recompiler/frontend/ir/ir_emitter.h +++ b/src/shader_recompiler/frontend/ir/ir_emitter.h | |||
| @@ -327,8 +327,8 @@ public: | |||
| 327 | const Value& derivates, const Value& offset, | 327 | const Value& derivates, const Value& offset, |
| 328 | const F32& lod_clamp, TextureInstInfo info); | 328 | const F32& lod_clamp, TextureInstInfo info); |
| 329 | [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); | 329 | [[nodiscard]] Value ImageRead(const Value& handle, const Value& coords, TextureInstInfo info); |
| 330 | [[nodiscard]] void ImageWrite(const Value& handle, const Value& coords, const Value& color, | 330 | void ImageWrite(const Value& handle, const Value& coords, const Value& color, |
| 331 | TextureInstInfo info); | 331 | TextureInstInfo info); |
| 332 | 332 | ||
| 333 | [[nodiscard]] Value ImageAtomicIAdd(const Value& handle, const Value& coords, | 333 | [[nodiscard]] Value ImageAtomicIAdd(const Value& handle, const Value& coords, |
| 334 | const Value& value, TextureInstInfo info); | 334 | const Value& value, TextureInstInfo info); |
diff --git a/src/shader_recompiler/frontend/ir/value.h b/src/shader_recompiler/frontend/ir/value.h index dbea20115..334bb47aa 100644 --- a/src/shader_recompiler/frontend/ir/value.h +++ b/src/shader_recompiler/frontend/ir/value.h | |||
| @@ -198,8 +198,8 @@ public: | |||
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | template <typename FlagsType> | 200 | template <typename FlagsType> |
| 201 | requires(sizeof(FlagsType) <= sizeof(u32) && std::is_trivially_copyable_v<FlagsType>) | 201 | requires(sizeof(FlagsType) <= sizeof(u32) && |
| 202 | [[nodiscard]] void SetFlags(FlagsType value) noexcept { | 202 | std::is_trivially_copyable_v<FlagsType>) void SetFlags(FlagsType value) noexcept { |
| 203 | std::memcpy(&flags, &value, sizeof(value)); | 203 | std::memcpy(&flags, &value, sizeof(value)); |
| 204 | } | 204 | } |
| 205 | 205 | ||
diff --git a/src/shader_recompiler/frontend/maxwell/control_flow.cpp b/src/shader_recompiler/frontend/maxwell/control_flow.cpp index 1a954a509..efe457baa 100644 --- a/src/shader_recompiler/frontend/maxwell/control_flow.cpp +++ b/src/shader_recompiler/frontend/maxwell/control_flow.cpp | |||
| @@ -73,7 +73,7 @@ Token OpcodeToken(Opcode opcode) { | |||
| 73 | return Token::PBK; | 73 | return Token::PBK; |
| 74 | case Opcode::PCNT: | 74 | case Opcode::PCNT: |
| 75 | case Opcode::CONT: | 75 | case Opcode::CONT: |
| 76 | return Token::PBK; | 76 | return Token::PCNT; |
| 77 | case Opcode::PEXIT: | 77 | case Opcode::PEXIT: |
| 78 | case Opcode::EXIT: | 78 | case Opcode::EXIT: |
| 79 | return Token::PEXIT; | 79 | return Token::PEXIT; |
diff --git a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp index 5ead930f1..f69e1c9cc 100644 --- a/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp +++ b/src/shader_recompiler/ir_opt/collect_shader_info_pass.cpp | |||
| @@ -111,6 +111,8 @@ void VisitUsages(Info& info, IR::Inst& inst) { | |||
| 111 | case IR::Opcode::ConvertF16U16: | 111 | case IR::Opcode::ConvertF16U16: |
| 112 | case IR::Opcode::ConvertF16U32: | 112 | case IR::Opcode::ConvertF16U32: |
| 113 | case IR::Opcode::ConvertF16U64: | 113 | case IR::Opcode::ConvertF16U64: |
| 114 | case IR::Opcode::ConvertF16F32: | ||
| 115 | case IR::Opcode::ConvertF32F16: | ||
| 114 | case IR::Opcode::FPAbs16: | 116 | case IR::Opcode::FPAbs16: |
| 115 | case IR::Opcode::FPAdd16: | 117 | case IR::Opcode::FPAdd16: |
| 116 | case IR::Opcode::FPCeil16: | 118 | case IR::Opcode::FPCeil16: |
diff --git a/src/shader_recompiler/object_pool.h b/src/shader_recompiler/object_pool.h index f8b255b66..f3b12d04b 100644 --- a/src/shader_recompiler/object_pool.h +++ b/src/shader_recompiler/object_pool.h | |||
| @@ -63,6 +63,7 @@ private: | |||
| 63 | used_objects = std::exchange(rhs.used_objects, 0); | 63 | used_objects = std::exchange(rhs.used_objects, 0); |
| 64 | num_objects = std::exchange(rhs.num_objects, 0); | 64 | num_objects = std::exchange(rhs.num_objects, 0); |
| 65 | storage = std::move(rhs.storage); | 65 | storage = std::move(rhs.storage); |
| 66 | return *this; | ||
| 66 | } | 67 | } |
| 67 | 68 | ||
| 68 | Chunk(Chunk&& rhs) noexcept | 69 | Chunk(Chunk&& rhs) noexcept |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index 24c858104..3b43554f9 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -817,7 +817,6 @@ void BufferCache<P>::CommitAsyncFlushesHigh() { | |||
| 817 | const std::size_t size = interval.upper() - interval.lower(); | 817 | const std::size_t size = interval.upper() - interval.lower(); |
| 818 | const VAddr cpu_addr = interval.lower(); | 818 | const VAddr cpu_addr = interval.lower(); |
| 819 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { | 819 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { |
| 820 | boost::container::small_vector<BufferCopy, 1> copies; | ||
| 821 | buffer.ForEachDownloadRangeAndClear( | 820 | buffer.ForEachDownloadRangeAndClear( |
| 822 | cpu_addr, size, [&](u64 range_offset, u64 range_size) { | 821 | cpu_addr, size, [&](u64 range_offset, u64 range_size) { |
| 823 | const VAddr buffer_addr = buffer.CpuAddr(); | 822 | const VAddr buffer_addr = buffer.CpuAddr(); |
diff --git a/src/video_core/engines/fermi_2d.h b/src/video_core/engines/fermi_2d.h index a4170ffff..d76c5ed56 100644 --- a/src/video_core/engines/fermi_2d.h +++ b/src/video_core/engines/fermi_2d.h | |||
| @@ -299,7 +299,7 @@ public: | |||
| 299 | }; | 299 | }; |
| 300 | 300 | ||
| 301 | private: | 301 | private: |
| 302 | VideoCore::RasterizerInterface* rasterizer; | 302 | VideoCore::RasterizerInterface* rasterizer = nullptr; |
| 303 | 303 | ||
| 304 | /// Performs the copy from the source surface to the destination surface as configured in the | 304 | /// Performs the copy from the source surface to the destination surface as configured in the |
| 305 | /// registers. | 305 | /// registers. |
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index d3329b0f8..9e457ae16 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h | |||
| @@ -227,7 +227,7 @@ private: | |||
| 227 | Core::System& system; | 227 | Core::System& system; |
| 228 | 228 | ||
| 229 | MemoryManager& memory_manager; | 229 | MemoryManager& memory_manager; |
| 230 | VideoCore::RasterizerInterface* rasterizer; | 230 | VideoCore::RasterizerInterface* rasterizer = nullptr; |
| 231 | 231 | ||
| 232 | std::vector<u8> read_buffer; | 232 | std::vector<u8> read_buffer; |
| 233 | std::vector<u8> write_buffer; | 233 | std::vector<u8> write_buffer; |
diff --git a/src/video_core/renderer_base.cpp b/src/video_core/renderer_base.cpp index c9a360aaf..3ea72fda9 100644 --- a/src/video_core/renderer_base.cpp +++ b/src/video_core/renderer_base.cpp | |||
| @@ -19,9 +19,6 @@ RendererBase::~RendererBase() = default; | |||
| 19 | 19 | ||
| 20 | void RendererBase::RefreshBaseSettings() { | 20 | void RendererBase::RefreshBaseSettings() { |
| 21 | UpdateCurrentFramebufferLayout(); | 21 | UpdateCurrentFramebufferLayout(); |
| 22 | |||
| 23 | renderer_settings.use_framelimiter = Settings::values.use_frame_limit.GetValue(); | ||
| 24 | renderer_settings.set_background_color = true; | ||
| 25 | } | 22 | } |
| 26 | 23 | ||
| 27 | void RendererBase::UpdateCurrentFramebufferLayout() { | 24 | void RendererBase::UpdateCurrentFramebufferLayout() { |
diff --git a/src/video_core/renderer_base.h b/src/video_core/renderer_base.h index 63d8ad42a..22b80c328 100644 --- a/src/video_core/renderer_base.h +++ b/src/video_core/renderer_base.h | |||
| @@ -21,9 +21,6 @@ class GraphicsContext; | |||
| 21 | namespace VideoCore { | 21 | namespace VideoCore { |
| 22 | 22 | ||
| 23 | struct RendererSettings { | 23 | struct RendererSettings { |
| 24 | std::atomic_bool use_framelimiter{false}; | ||
| 25 | std::atomic_bool set_background_color{false}; | ||
| 26 | |||
| 27 | // Screenshot | 24 | // Screenshot |
| 28 | std::atomic<bool> screenshot_requested{false}; | 25 | std::atomic<bool> screenshot_requested{false}; |
| 29 | void* screenshot_bits{}; | 26 | void* screenshot_bits{}; |
diff --git a/src/video_core/renderer_opengl/gl_shader_cache.cpp b/src/video_core/renderer_opengl/gl_shader_cache.cpp index 8d6cc074c..1f4dda17e 100644 --- a/src/video_core/renderer_opengl/gl_shader_cache.cpp +++ b/src/video_core/renderer_opengl/gl_shader_cache.cpp | |||
| @@ -441,7 +441,6 @@ std::unique_ptr<GraphicsPipeline> ShaderCache::CreateGraphicsPipeline( | |||
| 441 | 441 | ||
| 442 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; | 442 | std::array<const Shader::Info*, Maxwell::MaxShaderStage> infos{}; |
| 443 | 443 | ||
| 444 | OGLProgram source_program; | ||
| 445 | std::array<std::string, 5> sources; | 444 | std::array<std::string, 5> sources; |
| 446 | std::array<std::vector<u32>, 5> sources_spirv; | 445 | std::array<std::vector<u32>, 5> sources_spirv; |
| 447 | Shader::Backend::Bindings binding; | 446 | Shader::Backend::Bindings binding; |
diff --git a/src/video_core/renderer_opengl/renderer_opengl.cpp b/src/video_core/renderer_opengl/renderer_opengl.cpp index 285e78384..f1b00c24c 100644 --- a/src/video_core/renderer_opengl/renderer_opengl.cpp +++ b/src/video_core/renderer_opengl/renderer_opengl.cpp | |||
| @@ -328,12 +328,10 @@ void RendererOpenGL::ConfigureFramebufferTexture(TextureInfo& texture, | |||
| 328 | } | 328 | } |
| 329 | 329 | ||
| 330 | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { | 330 | void RendererOpenGL::DrawScreen(const Layout::FramebufferLayout& layout) { |
| 331 | if (renderer_settings.set_background_color) { | 331 | // Update background color before drawing |
| 332 | // Update background color before drawing | 332 | glClearColor(Settings::values.bg_red.GetValue() / 255.0f, |
| 333 | glClearColor(Settings::values.bg_red.GetValue() / 255.0f, | 333 | Settings::values.bg_green.GetValue() / 255.0f, |
| 334 | Settings::values.bg_green.GetValue() / 255.0f, | 334 | Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); |
| 335 | Settings::values.bg_blue.GetValue() / 255.0f, 1.0f); | ||
| 336 | } | ||
| 337 | 335 | ||
| 338 | // Set projection matrix | 336 | // Set projection matrix |
| 339 | const std::array ortho_matrix = | 337 | const std::array ortho_matrix = |
diff --git a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp index f4b3ee95c..8ac58bc2f 100644 --- a/src/video_core/renderer_vulkan/vk_buffer_cache.cpp +++ b/src/video_core/renderer_vulkan/vk_buffer_cache.cpp | |||
| @@ -358,7 +358,7 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 358 | if (null_buffer) { | 358 | if (null_buffer) { |
| 359 | return; | 359 | return; |
| 360 | } | 360 | } |
| 361 | null_buffer = device.GetLogical().CreateBuffer(VkBufferCreateInfo{ | 361 | VkBufferCreateInfo create_info{ |
| 362 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | 362 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, |
| 363 | .pNext = nullptr, | 363 | .pNext = nullptr, |
| 364 | .flags = 0, | 364 | .flags = 0, |
| @@ -367,9 +367,13 @@ void BufferCacheRuntime::ReserveNullBuffer() { | |||
| 367 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | 367 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, |
| 368 | .queueFamilyIndexCount = 0, | 368 | .queueFamilyIndexCount = 0, |
| 369 | .pQueueFamilyIndices = nullptr, | 369 | .pQueueFamilyIndices = nullptr, |
| 370 | }); | 370 | }; |
| 371 | if (device.IsExtTransformFeedbackSupported()) { | ||
| 372 | create_info.usage |= VK_BUFFER_USAGE_TRANSFORM_FEEDBACK_BUFFER_BIT_EXT; | ||
| 373 | } | ||
| 374 | null_buffer = device.GetLogical().CreateBuffer(create_info); | ||
| 371 | if (device.HasDebuggingToolAttached()) { | 375 | if (device.HasDebuggingToolAttached()) { |
| 372 | null_buffer.SetObjectNameEXT("Null index buffer"); | 376 | null_buffer.SetObjectNameEXT("Null buffer"); |
| 373 | } | 377 | } |
| 374 | null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal); | 378 | null_buffer_commit = memory_allocator.Commit(null_buffer, MemoryUsage::DeviceLocal); |
| 375 | 379 | ||
diff --git a/src/video_core/renderer_vulkan/vk_compute_pass.cpp b/src/video_core/renderer_vulkan/vk_compute_pass.cpp index 8e426ce2c..561cf5e11 100644 --- a/src/video_core/renderer_vulkan/vk_compute_pass.cpp +++ b/src/video_core/renderer_vulkan/vk_compute_pass.cpp | |||
| @@ -258,10 +258,9 @@ std::pair<VkBuffer, VkDeviceSize> Uint8Pass::Assemble(u32 num_vertices, VkBuffer | |||
| 258 | update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices); | 258 | update_descriptor_queue.AddBuffer(src_buffer, src_offset, num_vertices); |
| 259 | update_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size); | 259 | update_descriptor_queue.AddBuffer(staging.buffer, staging.offset, staging_size); |
| 260 | const void* const descriptor_data{update_descriptor_queue.UpdateData()}; | 260 | const void* const descriptor_data{update_descriptor_queue.UpdateData()}; |
| 261 | const VkBuffer buffer{staging.buffer}; | ||
| 262 | 261 | ||
| 263 | scheduler.RequestOutsideRenderPassOperationContext(); | 262 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 264 | scheduler.Record([this, buffer, descriptor_data, num_vertices](vk::CommandBuffer cmdbuf) { | 263 | scheduler.Record([this, descriptor_data, num_vertices](vk::CommandBuffer cmdbuf) { |
| 265 | static constexpr u32 DISPATCH_SIZE = 1024; | 264 | static constexpr u32 DISPATCH_SIZE = 1024; |
| 266 | static constexpr VkMemoryBarrier WRITE_BARRIER{ | 265 | static constexpr VkMemoryBarrier WRITE_BARRIER{ |
| 267 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | 266 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, |
| @@ -319,14 +318,14 @@ std::pair<VkBuffer, VkDeviceSize> QuadIndexedPass::Assemble( | |||
| 319 | const void* const descriptor_data{update_descriptor_queue.UpdateData()}; | 318 | const void* const descriptor_data{update_descriptor_queue.UpdateData()}; |
| 320 | 319 | ||
| 321 | scheduler.RequestOutsideRenderPassOperationContext(); | 320 | scheduler.RequestOutsideRenderPassOperationContext(); |
| 322 | scheduler.Record([this, buffer = staging.buffer, descriptor_data, num_tri_vertices, base_vertex, | 321 | scheduler.Record([this, descriptor_data, num_tri_vertices, base_vertex, |
| 323 | index_shift](vk::CommandBuffer cmdbuf) { | 322 | index_shift](vk::CommandBuffer cmdbuf) { |
| 324 | static constexpr u32 DISPATCH_SIZE = 1024; | 323 | static constexpr u32 DISPATCH_SIZE = 1024; |
| 325 | static constexpr VkMemoryBarrier WRITE_BARRIER{ | 324 | static constexpr VkMemoryBarrier WRITE_BARRIER{ |
| 326 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, | 325 | .sType = VK_STRUCTURE_TYPE_MEMORY_BARRIER, |
| 327 | .pNext = nullptr, | 326 | .pNext = nullptr, |
| 328 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, | 327 | .srcAccessMask = VK_ACCESS_SHADER_WRITE_BIT, |
| 329 | .dstAccessMask = VK_ACCESS_VERTEX_ATTRIBUTE_READ_BIT, | 328 | .dstAccessMask = VK_ACCESS_INDEX_READ_BIT, |
| 330 | }; | 329 | }; |
| 331 | const std::array push_constants{base_vertex, index_shift}; | 330 | const std::array push_constants{base_vertex, index_shift}; |
| 332 | const VkDescriptorSet set = descriptor_allocator.Commit(); | 331 | const VkDescriptorSet set = descriptor_allocator.Commit(); |
diff --git a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp index 555b12ed7..5d5329abf 100644 --- a/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp +++ b/src/video_core/renderer_vulkan/vk_staging_buffer_pool.cpp | |||
| @@ -61,11 +61,15 @@ std::optional<u32> FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& p | |||
| 61 | return std::nullopt; | 61 | return std::nullopt; |
| 62 | } | 62 | } |
| 63 | 63 | ||
| 64 | u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask) { | 64 | u32 FindMemoryTypeIndex(const VkPhysicalDeviceMemoryProperties& props, u32 type_mask, |
| 65 | // Try to find a DEVICE_LOCAL_BIT type, Nvidia and AMD have a dedicated heap for this | 65 | bool try_device_local) { |
| 66 | std::optional<u32> type = FindMemoryTypeIndex(props, type_mask, STREAM_FLAGS); | 66 | std::optional<u32> type; |
| 67 | if (type) { | 67 | if (try_device_local) { |
| 68 | return *type; | 68 | // Try to find a DEVICE_LOCAL_BIT type, Nvidia and AMD have a dedicated heap for this |
| 69 | type = FindMemoryTypeIndex(props, type_mask, STREAM_FLAGS); | ||
| 70 | if (type) { | ||
| 71 | return *type; | ||
| 72 | } | ||
| 69 | } | 73 | } |
| 70 | // Otherwise try without the DEVICE_LOCAL_BIT | 74 | // Otherwise try without the DEVICE_LOCAL_BIT |
| 71 | type = FindMemoryTypeIndex(props, type_mask, HOST_FLAGS); | 75 | type = FindMemoryTypeIndex(props, type_mask, HOST_FLAGS); |
| @@ -115,12 +119,21 @@ StagingBufferPool::StagingBufferPool(const Device& device_, MemoryAllocator& mem | |||
| 115 | .buffer = *stream_buffer, | 119 | .buffer = *stream_buffer, |
| 116 | }; | 120 | }; |
| 117 | const auto memory_properties = device.GetPhysical().GetMemoryProperties(); | 121 | const auto memory_properties = device.GetPhysical().GetMemoryProperties(); |
| 118 | stream_memory = dev.AllocateMemory(VkMemoryAllocateInfo{ | 122 | VkMemoryAllocateInfo stream_memory_info{ |
| 119 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | 123 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, |
| 120 | .pNext = make_dedicated ? &dedicated_info : nullptr, | 124 | .pNext = make_dedicated ? &dedicated_info : nullptr, |
| 121 | .allocationSize = requirements.size, | 125 | .allocationSize = requirements.size, |
| 122 | .memoryTypeIndex = FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits), | 126 | .memoryTypeIndex = |
| 123 | }); | 127 | FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, true), |
| 128 | }; | ||
| 129 | stream_memory = dev.TryAllocateMemory(stream_memory_info); | ||
| 130 | if (!stream_memory) { | ||
| 131 | LOG_INFO(Render_Vulkan, "Dynamic memory allocation failed, trying with system memory"); | ||
| 132 | stream_memory_info.memoryTypeIndex = | ||
| 133 | FindMemoryTypeIndex(memory_properties, requirements.memoryTypeBits, false); | ||
| 134 | stream_memory = dev.AllocateMemory(stream_memory_info); | ||
| 135 | } | ||
| 136 | |||
| 124 | if (device.HasDebuggingToolAttached()) { | 137 | if (device.HasDebuggingToolAttached()) { |
| 125 | stream_memory.SetObjectNameEXT("Stream Buffer Memory"); | 138 | stream_memory.SetObjectNameEXT("Stream Buffer Memory"); |
| 126 | } | 139 | } |
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp b/src/video_core/renderer_vulkan/vk_stream_buffer.cpp deleted file mode 100644 index 7b4875d0e..000000000 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.cpp +++ /dev/null | |||
| @@ -1,168 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <algorithm> | ||
| 6 | #include <limits> | ||
| 7 | #include <optional> | ||
| 8 | #include <tuple> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "common/alignment.h" | ||
| 12 | #include "common/assert.h" | ||
| 13 | #include "common/literals.h" | ||
| 14 | #include "video_core/renderer_vulkan/vk_scheduler.h" | ||
| 15 | #include "video_core/renderer_vulkan/vk_stream_buffer.h" | ||
| 16 | #include "video_core/vulkan_common/vulkan_device.h" | ||
| 17 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 18 | |||
| 19 | namespace Vulkan { | ||
| 20 | |||
| 21 | namespace { | ||
| 22 | |||
| 23 | using namespace Common::Literals; | ||
| 24 | |||
| 25 | constexpr VkBufferUsageFlags BUFFER_USAGE = | ||
| 26 | VK_BUFFER_USAGE_VERTEX_BUFFER_BIT | VK_BUFFER_USAGE_INDEX_BUFFER_BIT | | ||
| 27 | VK_BUFFER_USAGE_UNIFORM_BUFFER_BIT | VK_BUFFER_USAGE_STORAGE_BUFFER_BIT; | ||
| 28 | |||
| 29 | constexpr u64 WATCHES_INITIAL_RESERVE = 0x4000; | ||
| 30 | constexpr u64 WATCHES_RESERVE_CHUNK = 0x1000; | ||
| 31 | |||
| 32 | constexpr u64 PREFERRED_STREAM_BUFFER_SIZE = 256_MiB; | ||
| 33 | |||
| 34 | /// Find a memory type with the passed requirements | ||
| 35 | std::optional<u32> FindMemoryType(const VkPhysicalDeviceMemoryProperties& properties, | ||
| 36 | VkMemoryPropertyFlags wanted, | ||
| 37 | u32 filter = std::numeric_limits<u32>::max()) { | ||
| 38 | for (u32 i = 0; i < properties.memoryTypeCount; ++i) { | ||
| 39 | const auto flags = properties.memoryTypes[i].propertyFlags; | ||
| 40 | if ((flags & wanted) == wanted && (filter & (1U << i)) != 0) { | ||
| 41 | return i; | ||
| 42 | } | ||
| 43 | } | ||
| 44 | return std::nullopt; | ||
| 45 | } | ||
| 46 | |||
| 47 | /// Get the preferred host visible memory type. | ||
| 48 | u32 GetMemoryType(const VkPhysicalDeviceMemoryProperties& properties, | ||
| 49 | u32 filter = std::numeric_limits<u32>::max()) { | ||
| 50 | // Prefer device local host visible allocations. Both AMD and Nvidia now provide one. | ||
| 51 | // Otherwise search for a host visible allocation. | ||
| 52 | static constexpr auto HOST_MEMORY = | ||
| 53 | VK_MEMORY_PROPERTY_HOST_VISIBLE_BIT | VK_MEMORY_PROPERTY_HOST_COHERENT_BIT; | ||
| 54 | static constexpr auto DYNAMIC_MEMORY = HOST_MEMORY | VK_MEMORY_PROPERTY_DEVICE_LOCAL_BIT; | ||
| 55 | |||
| 56 | std::optional preferred_type = FindMemoryType(properties, DYNAMIC_MEMORY); | ||
| 57 | if (!preferred_type) { | ||
| 58 | preferred_type = FindMemoryType(properties, HOST_MEMORY); | ||
| 59 | ASSERT_MSG(preferred_type, "No host visible and coherent memory type found"); | ||
| 60 | } | ||
| 61 | return preferred_type.value_or(0); | ||
| 62 | } | ||
| 63 | |||
| 64 | } // Anonymous namespace | ||
| 65 | |||
| 66 | VKStreamBuffer::VKStreamBuffer(const Device& device_, VKScheduler& scheduler_) | ||
| 67 | : device{device_}, scheduler{scheduler_} { | ||
| 68 | CreateBuffers(); | ||
| 69 | ReserveWatches(current_watches, WATCHES_INITIAL_RESERVE); | ||
| 70 | ReserveWatches(previous_watches, WATCHES_INITIAL_RESERVE); | ||
| 71 | } | ||
| 72 | |||
| 73 | VKStreamBuffer::~VKStreamBuffer() = default; | ||
| 74 | |||
| 75 | std::pair<u8*, u64> VKStreamBuffer::Map(u64 size, u64 alignment) { | ||
| 76 | ASSERT(size <= stream_buffer_size); | ||
| 77 | mapped_size = size; | ||
| 78 | |||
| 79 | if (alignment > 0) { | ||
| 80 | offset = Common::AlignUp(offset, alignment); | ||
| 81 | } | ||
| 82 | |||
| 83 | WaitPendingOperations(offset); | ||
| 84 | |||
| 85 | if (offset + size > stream_buffer_size) { | ||
| 86 | // The buffer would overflow, save the amount of used watches and reset the state. | ||
| 87 | invalidation_mark = current_watch_cursor; | ||
| 88 | current_watch_cursor = 0; | ||
| 89 | offset = 0; | ||
| 90 | |||
| 91 | // Swap watches and reset waiting cursors. | ||
| 92 | std::swap(previous_watches, current_watches); | ||
| 93 | wait_cursor = 0; | ||
| 94 | wait_bound = 0; | ||
| 95 | |||
| 96 | // Ensure that we don't wait for uncommitted fences. | ||
| 97 | scheduler.Flush(); | ||
| 98 | } | ||
| 99 | |||
| 100 | return std::make_pair(memory.Map(offset, size), offset); | ||
| 101 | } | ||
| 102 | |||
| 103 | void VKStreamBuffer::Unmap(u64 size) { | ||
| 104 | ASSERT_MSG(size <= mapped_size, "Reserved size is too small"); | ||
| 105 | |||
| 106 | memory.Unmap(); | ||
| 107 | |||
| 108 | offset += size; | ||
| 109 | |||
| 110 | if (current_watch_cursor + 1 >= current_watches.size()) { | ||
| 111 | // Ensure that there are enough watches. | ||
| 112 | ReserveWatches(current_watches, WATCHES_RESERVE_CHUNK); | ||
| 113 | } | ||
| 114 | auto& watch = current_watches[current_watch_cursor++]; | ||
| 115 | watch.upper_bound = offset; | ||
| 116 | watch.tick = scheduler.CurrentTick(); | ||
| 117 | } | ||
| 118 | |||
| 119 | void VKStreamBuffer::CreateBuffers() { | ||
| 120 | const auto memory_properties = device.GetPhysical().GetMemoryProperties(); | ||
| 121 | const u32 preferred_type = GetMemoryType(memory_properties); | ||
| 122 | const u32 preferred_heap = memory_properties.memoryTypes[preferred_type].heapIndex; | ||
| 123 | |||
| 124 | // Substract from the preferred heap size some bytes to avoid getting out of memory. | ||
| 125 | const VkDeviceSize heap_size = memory_properties.memoryHeaps[preferred_heap].size; | ||
| 126 | // As per DXVK's example, using `heap_size / 2` | ||
| 127 | const VkDeviceSize allocable_size = heap_size / 2; | ||
| 128 | buffer = device.GetLogical().CreateBuffer({ | ||
| 129 | .sType = VK_STRUCTURE_TYPE_BUFFER_CREATE_INFO, | ||
| 130 | .pNext = nullptr, | ||
| 131 | .flags = 0, | ||
| 132 | .size = std::min(PREFERRED_STREAM_BUFFER_SIZE, allocable_size), | ||
| 133 | .usage = BUFFER_USAGE, | ||
| 134 | .sharingMode = VK_SHARING_MODE_EXCLUSIVE, | ||
| 135 | .queueFamilyIndexCount = 0, | ||
| 136 | .pQueueFamilyIndices = nullptr, | ||
| 137 | }); | ||
| 138 | |||
| 139 | const auto requirements = device.GetLogical().GetBufferMemoryRequirements(*buffer); | ||
| 140 | const u32 required_flags = requirements.memoryTypeBits; | ||
| 141 | stream_buffer_size = static_cast<u64>(requirements.size); | ||
| 142 | |||
| 143 | memory = device.GetLogical().AllocateMemory({ | ||
| 144 | .sType = VK_STRUCTURE_TYPE_MEMORY_ALLOCATE_INFO, | ||
| 145 | .pNext = nullptr, | ||
| 146 | .allocationSize = requirements.size, | ||
| 147 | .memoryTypeIndex = GetMemoryType(memory_properties, required_flags), | ||
| 148 | }); | ||
| 149 | buffer.BindMemory(*memory, 0); | ||
| 150 | } | ||
| 151 | |||
| 152 | void VKStreamBuffer::ReserveWatches(std::vector<Watch>& watches, std::size_t grow_size) { | ||
| 153 | watches.resize(watches.size() + grow_size); | ||
| 154 | } | ||
| 155 | |||
| 156 | void VKStreamBuffer::WaitPendingOperations(u64 requested_upper_bound) { | ||
| 157 | if (!invalidation_mark) { | ||
| 158 | return; | ||
| 159 | } | ||
| 160 | while (requested_upper_bound < wait_bound && wait_cursor < *invalidation_mark) { | ||
| 161 | auto& watch = previous_watches[wait_cursor]; | ||
| 162 | wait_bound = watch.upper_bound; | ||
| 163 | scheduler.Wait(watch.tick); | ||
| 164 | ++wait_cursor; | ||
| 165 | } | ||
| 166 | } | ||
| 167 | |||
| 168 | } // namespace Vulkan | ||
diff --git a/src/video_core/renderer_vulkan/vk_stream_buffer.h b/src/video_core/renderer_vulkan/vk_stream_buffer.h deleted file mode 100644 index 2e9c8cb46..000000000 --- a/src/video_core/renderer_vulkan/vk_stream_buffer.h +++ /dev/null | |||
| @@ -1,76 +0,0 @@ | |||
| 1 | // Copyright 2019 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <optional> | ||
| 8 | #include <utility> | ||
| 9 | #include <vector> | ||
| 10 | |||
| 11 | #include "common/common_types.h" | ||
| 12 | #include "video_core/vulkan_common/vulkan_wrapper.h" | ||
| 13 | |||
| 14 | namespace Vulkan { | ||
| 15 | |||
| 16 | class Device; | ||
| 17 | class VKFenceWatch; | ||
| 18 | class VKScheduler; | ||
| 19 | |||
| 20 | class VKStreamBuffer final { | ||
| 21 | public: | ||
| 22 | explicit VKStreamBuffer(const Device& device, VKScheduler& scheduler); | ||
| 23 | ~VKStreamBuffer(); | ||
| 24 | |||
| 25 | /** | ||
| 26 | * Reserves a region of memory from the stream buffer. | ||
| 27 | * @param size Size to reserve. | ||
| 28 | * @returns A pair of a raw memory pointer (with offset added), and the buffer offset | ||
| 29 | */ | ||
| 30 | std::pair<u8*, u64> Map(u64 size, u64 alignment); | ||
| 31 | |||
| 32 | /// Ensures that "size" bytes of memory are available to the GPU, potentially recording a copy. | ||
| 33 | void Unmap(u64 size); | ||
| 34 | |||
| 35 | VkBuffer Handle() const noexcept { | ||
| 36 | return *buffer; | ||
| 37 | } | ||
| 38 | |||
| 39 | u64 Address() const noexcept { | ||
| 40 | return 0; | ||
| 41 | } | ||
| 42 | |||
| 43 | private: | ||
| 44 | struct Watch { | ||
| 45 | u64 tick{}; | ||
| 46 | u64 upper_bound{}; | ||
| 47 | }; | ||
| 48 | |||
| 49 | /// Creates Vulkan buffer handles committing the required the required memory. | ||
| 50 | void CreateBuffers(); | ||
| 51 | |||
| 52 | /// Increases the amount of watches available. | ||
| 53 | void ReserveWatches(std::vector<Watch>& watches, std::size_t grow_size); | ||
| 54 | |||
| 55 | void WaitPendingOperations(u64 requested_upper_bound); | ||
| 56 | |||
| 57 | const Device& device; ///< Vulkan device manager. | ||
| 58 | VKScheduler& scheduler; ///< Command scheduler. | ||
| 59 | |||
| 60 | vk::Buffer buffer; ///< Mapped buffer. | ||
| 61 | vk::DeviceMemory memory; ///< Memory allocation. | ||
| 62 | u64 stream_buffer_size{}; ///< Stream buffer size. | ||
| 63 | |||
| 64 | u64 offset{}; ///< Buffer iterator. | ||
| 65 | u64 mapped_size{}; ///< Size reserved for the current copy. | ||
| 66 | |||
| 67 | std::vector<Watch> current_watches; ///< Watches recorded in the current iteration. | ||
| 68 | std::size_t current_watch_cursor{}; ///< Count of watches, reset on invalidation. | ||
| 69 | std::optional<std::size_t> invalidation_mark; ///< Number of watches used in the previous cycle. | ||
| 70 | |||
| 71 | std::vector<Watch> previous_watches; ///< Watches used in the previous iteration. | ||
| 72 | std::size_t wait_cursor{}; ///< Last watch being waited for completion. | ||
| 73 | u64 wait_bound{}; ///< Highest offset being watched for completion. | ||
| 74 | }; | ||
| 75 | |||
| 76 | } // namespace Vulkan | ||
diff --git a/src/video_core/texture_cache/render_targets.h b/src/video_core/texture_cache/render_targets.h index 9b9544b07..0cb227d69 100644 --- a/src/video_core/texture_cache/render_targets.h +++ b/src/video_core/texture_cache/render_targets.h | |||
| @@ -24,10 +24,10 @@ struct RenderTargets { | |||
| 24 | return std::ranges::any_of(color_buffer_ids, contains) || contains(depth_buffer_id); | 24 | return std::ranges::any_of(color_buffer_ids, contains) || contains(depth_buffer_id); |
| 25 | } | 25 | } |
| 26 | 26 | ||
| 27 | std::array<ImageViewId, NUM_RT> color_buffer_ids; | 27 | std::array<ImageViewId, NUM_RT> color_buffer_ids{}; |
| 28 | ImageViewId depth_buffer_id; | 28 | ImageViewId depth_buffer_id{}; |
| 29 | std::array<u8, NUM_RT> draw_buffers{}; | 29 | std::array<u8, NUM_RT> draw_buffers{}; |
| 30 | Extent2D size; | 30 | Extent2D size{}; |
| 31 | }; | 31 | }; |
| 32 | 32 | ||
| 33 | } // namespace VideoCommon | 33 | } // namespace VideoCommon |
diff --git a/src/video_core/vulkan_common/vulkan_wrapper.cpp b/src/video_core/vulkan_common/vulkan_wrapper.cpp index bbf0fccae..70898004a 100644 --- a/src/video_core/vulkan_common/vulkan_wrapper.cpp +++ b/src/video_core/vulkan_common/vulkan_wrapper.cpp | |||
| @@ -202,7 +202,7 @@ void SetObjectName(const DeviceDispatch* dld, VkDevice device, T handle, VkObjec | |||
| 202 | const VkDebugUtilsObjectNameInfoEXT name_info{ | 202 | const VkDebugUtilsObjectNameInfoEXT name_info{ |
| 203 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, | 203 | .sType = VK_STRUCTURE_TYPE_DEBUG_UTILS_OBJECT_NAME_INFO_EXT, |
| 204 | .pNext = nullptr, | 204 | .pNext = nullptr, |
| 205 | .objectType = VK_OBJECT_TYPE_IMAGE, | 205 | .objectType = type, |
| 206 | .objectHandle = reinterpret_cast<u64>(handle), | 206 | .objectHandle = reinterpret_cast<u64>(handle), |
| 207 | .pObjectName = name, | 207 | .pObjectName = name, |
| 208 | }; | 208 | }; |
diff --git a/src/yuzu/applets/qt_web_browser.cpp b/src/yuzu/applets/qt_web_browser.cpp index b112dd7b0..652d99570 100644 --- a/src/yuzu/applets/qt_web_browser.cpp +++ b/src/yuzu/applets/qt_web_browser.cpp | |||
| @@ -107,6 +107,7 @@ void QtNXWebEngineView::LoadLocalWebPage(const std::string& main_url, | |||
| 107 | is_local = true; | 107 | is_local = true; |
| 108 | 108 | ||
| 109 | LoadExtractedFonts(); | 109 | LoadExtractedFonts(); |
| 110 | FocusFirstLinkElement(); | ||
| 110 | SetUserAgent(UserAgent::WebApplet); | 111 | SetUserAgent(UserAgent::WebApplet); |
| 111 | SetFinished(false); | 112 | SetFinished(false); |
| 112 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); | 113 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); |
| @@ -121,6 +122,7 @@ void QtNXWebEngineView::LoadExternalWebPage(const std::string& main_url, | |||
| 121 | const std::string& additional_args) { | 122 | const std::string& additional_args) { |
| 122 | is_local = false; | 123 | is_local = false; |
| 123 | 124 | ||
| 125 | FocusFirstLinkElement(); | ||
| 124 | SetUserAgent(UserAgent::WebApplet); | 126 | SetUserAgent(UserAgent::WebApplet); |
| 125 | SetFinished(false); | 127 | SetFinished(false); |
| 126 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); | 128 | SetExitReason(Service::AM::Applets::WebExitReason::EndButtonPressed); |
| @@ -208,7 +210,7 @@ void QtNXWebEngineView::HandleWindowFooterButtonPressedOnce() { | |||
| 208 | if (input_interpreter->IsButtonPressedOnce(button)) { | 210 | if (input_interpreter->IsButtonPressedOnce(button)) { |
| 209 | page()->runJavaScript( | 211 | page()->runJavaScript( |
| 210 | QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast<u8>(button)), | 212 | QStringLiteral("yuzu_key_callbacks[%1] == null;").arg(static_cast<u8>(button)), |
| 211 | [&](const QVariant& variant) { | 213 | [this, button](const QVariant& variant) { |
| 212 | if (variant.toBool()) { | 214 | if (variant.toBool()) { |
| 213 | switch (button) { | 215 | switch (button) { |
| 214 | case HIDButton::A: | 216 | case HIDButton::A: |
| @@ -364,6 +366,17 @@ void QtNXWebEngineView::LoadExtractedFonts() { | |||
| 364 | Qt::QueuedConnection); | 366 | Qt::QueuedConnection); |
| 365 | } | 367 | } |
| 366 | 368 | ||
| 369 | void QtNXWebEngineView::FocusFirstLinkElement() { | ||
| 370 | QWebEngineScript focus_link_element; | ||
| 371 | |||
| 372 | focus_link_element.setName(QStringLiteral("focus_link_element.js")); | ||
| 373 | focus_link_element.setSourceCode(QString::fromStdString(FOCUS_LINK_ELEMENT_SCRIPT)); | ||
| 374 | focus_link_element.setWorldId(QWebEngineScript::MainWorld); | ||
| 375 | focus_link_element.setInjectionPoint(QWebEngineScript::Deferred); | ||
| 376 | focus_link_element.setRunsOnSubFrames(true); | ||
| 377 | default_profile->scripts()->insert(focus_link_element); | ||
| 378 | } | ||
| 379 | |||
| 367 | #endif | 380 | #endif |
| 368 | 381 | ||
| 369 | QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { | 382 | QtWebBrowser::QtWebBrowser(GMainWindow& main_window) { |
diff --git a/src/yuzu/applets/qt_web_browser.h b/src/yuzu/applets/qt_web_browser.h index 7ad07409f..7e9f703fc 100644 --- a/src/yuzu/applets/qt_web_browser.h +++ b/src/yuzu/applets/qt_web_browser.h | |||
| @@ -161,6 +161,9 @@ private: | |||
| 161 | /// Loads the extracted fonts using JavaScript. | 161 | /// Loads the extracted fonts using JavaScript. |
| 162 | void LoadExtractedFonts(); | 162 | void LoadExtractedFonts(); |
| 163 | 163 | ||
| 164 | /// Brings focus to the first available link element. | ||
| 165 | void FocusFirstLinkElement(); | ||
| 166 | |||
| 164 | InputCommon::InputSubsystem* input_subsystem; | 167 | InputCommon::InputSubsystem* input_subsystem; |
| 165 | 168 | ||
| 166 | std::unique_ptr<UrlRequestInterceptor> url_interceptor; | 169 | std::unique_ptr<UrlRequestInterceptor> url_interceptor; |
diff --git a/src/yuzu/applets/qt_web_browser_scripts.h b/src/yuzu/applets/qt_web_browser_scripts.h index 992837a85..c4ba8d40f 100644 --- a/src/yuzu/applets/qt_web_browser_scripts.h +++ b/src/yuzu/applets/qt_web_browser_scripts.h | |||
| @@ -73,6 +73,12 @@ constexpr char LOAD_NX_FONT[] = R"( | |||
| 73 | })(); | 73 | })(); |
| 74 | )"; | 74 | )"; |
| 75 | 75 | ||
| 76 | constexpr char FOCUS_LINK_ELEMENT_SCRIPT[] = R"( | ||
| 77 | if (document.getElementsByTagName("a").length > 0) { | ||
| 78 | document.getElementsByTagName("a")[0].focus(); | ||
| 79 | } | ||
| 80 | )"; | ||
| 81 | |||
| 76 | constexpr char GAMEPAD_SCRIPT[] = R"( | 82 | constexpr char GAMEPAD_SCRIPT[] = R"( |
| 77 | window.addEventListener("gamepadconnected", function(e) { | 83 | window.addEventListener("gamepadconnected", function(e) { |
| 78 | console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", | 84 | console.log("Gamepad connected at index %d: %s. %d buttons, %d axes.", |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 4d89b00e9..ecd5dfac1 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -806,8 +806,8 @@ void Config::ReadRendererValues() { | |||
| 806 | ReadGlobalSetting(Settings::values.fullscreen_mode); | 806 | ReadGlobalSetting(Settings::values.fullscreen_mode); |
| 807 | ReadGlobalSetting(Settings::values.aspect_ratio); | 807 | ReadGlobalSetting(Settings::values.aspect_ratio); |
| 808 | ReadGlobalSetting(Settings::values.max_anisotropy); | 808 | ReadGlobalSetting(Settings::values.max_anisotropy); |
| 809 | ReadGlobalSetting(Settings::values.use_frame_limit); | 809 | ReadGlobalSetting(Settings::values.use_speed_limit); |
| 810 | ReadGlobalSetting(Settings::values.frame_limit); | 810 | ReadGlobalSetting(Settings::values.speed_limit); |
| 811 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); | 811 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); |
| 812 | ReadGlobalSetting(Settings::values.gpu_accuracy); | 812 | ReadGlobalSetting(Settings::values.gpu_accuracy); |
| 813 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); | 813 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); |
| @@ -1332,11 +1332,14 @@ void Config::SaveRendererValues() { | |||
| 1332 | static_cast<u32>(Settings::values.renderer_backend.GetDefault()), | 1332 | static_cast<u32>(Settings::values.renderer_backend.GetDefault()), |
| 1333 | Settings::values.renderer_backend.UsingGlobal()); | 1333 | Settings::values.renderer_backend.UsingGlobal()); |
| 1334 | WriteGlobalSetting(Settings::values.vulkan_device); | 1334 | WriteGlobalSetting(Settings::values.vulkan_device); |
| 1335 | WriteGlobalSetting(Settings::values.fullscreen_mode); | 1335 | WriteSetting(QString::fromStdString(Settings::values.fullscreen_mode.GetLabel()), |
| 1336 | static_cast<u32>(Settings::values.fullscreen_mode.GetValue(global)), | ||
| 1337 | static_cast<u32>(Settings::values.fullscreen_mode.GetDefault()), | ||
| 1338 | Settings::values.fullscreen_mode.UsingGlobal()); | ||
| 1336 | WriteGlobalSetting(Settings::values.aspect_ratio); | 1339 | WriteGlobalSetting(Settings::values.aspect_ratio); |
| 1337 | WriteGlobalSetting(Settings::values.max_anisotropy); | 1340 | WriteGlobalSetting(Settings::values.max_anisotropy); |
| 1338 | WriteGlobalSetting(Settings::values.use_frame_limit); | 1341 | WriteGlobalSetting(Settings::values.use_speed_limit); |
| 1339 | WriteGlobalSetting(Settings::values.frame_limit); | 1342 | WriteGlobalSetting(Settings::values.speed_limit); |
| 1340 | WriteGlobalSetting(Settings::values.use_disk_shader_cache); | 1343 | WriteGlobalSetting(Settings::values.use_disk_shader_cache); |
| 1341 | WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()), | 1344 | WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()), |
| 1342 | static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)), | 1345 | static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)), |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 4bbb9f1cd..c1d7feb9f 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -181,5 +181,6 @@ private: | |||
| 181 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT | 181 | // These metatype declarations cannot be in common/settings.h because core is devoid of QT |
| 182 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); | 182 | Q_DECLARE_METATYPE(Settings::CPUAccuracy); |
| 183 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); | 183 | Q_DECLARE_METATYPE(Settings::GPUAccuracy); |
| 184 | Q_DECLARE_METATYPE(Settings::FullscreenMode); | ||
| 184 | Q_DECLARE_METATYPE(Settings::RendererBackend); | 185 | Q_DECLARE_METATYPE(Settings::RendererBackend); |
| 185 | Q_DECLARE_METATYPE(Settings::ShaderBackend); | 186 | Q_DECLARE_METATYPE(Settings::ShaderBackend); |
diff --git a/src/yuzu/configuration/configuration_shared.cpp b/src/yuzu/configuration/configuration_shared.cpp index 096e42e94..251aab912 100644 --- a/src/yuzu/configuration/configuration_shared.cpp +++ b/src/yuzu/configuration/configuration_shared.cpp | |||
| @@ -25,20 +25,6 @@ void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<bool>* setting, | |||
| 25 | } | 25 | } |
| 26 | } | 26 | } |
| 27 | 27 | ||
| 28 | void ConfigurationShared::ApplyPerGameSetting(Settings::Setting<int>* setting, | ||
| 29 | const QComboBox* combobox) { | ||
| 30 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||
| 31 | setting->SetValue(combobox->currentIndex()); | ||
| 32 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 33 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 34 | setting->SetGlobal(true); | ||
| 35 | } else { | ||
| 36 | setting->SetGlobal(false); | ||
| 37 | setting->SetValue(combobox->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 38 | } | ||
| 39 | } | ||
| 40 | } | ||
| 41 | |||
| 42 | void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, | 28 | void ConfigurationShared::SetPerGameSetting(QCheckBox* checkbox, |
| 43 | const Settings::Setting<bool>* setting) { | 29 | const Settings::Setting<bool>* setting) { |
| 44 | if (setting->UsingGlobal()) { | 30 | if (setting->UsingGlobal()) { |
diff --git a/src/yuzu/configuration/configuration_shared.h b/src/yuzu/configuration/configuration_shared.h index 1e0ef01ca..5423dbc92 100644 --- a/src/yuzu/configuration/configuration_shared.h +++ b/src/yuzu/configuration/configuration_shared.h | |||
| @@ -28,7 +28,20 @@ enum class CheckState { | |||
| 28 | // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting | 28 | // ApplyPerGameSetting, given a Settings::Setting and a Qt UI element, properly applies a Setting |
| 29 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, | 29 | void ApplyPerGameSetting(Settings::Setting<bool>* setting, const QCheckBox* checkbox, |
| 30 | const CheckState& tracker); | 30 | const CheckState& tracker); |
| 31 | void ApplyPerGameSetting(Settings::Setting<int>* setting, const QComboBox* combobox); | 31 | template <typename Type> |
| 32 | void ApplyPerGameSetting(Settings::Setting<Type>* setting, const QComboBox* combobox) { | ||
| 33 | if (Settings::IsConfiguringGlobal() && setting->UsingGlobal()) { | ||
| 34 | setting->SetValue(static_cast<Type>(combobox->currentIndex())); | ||
| 35 | } else if (!Settings::IsConfiguringGlobal()) { | ||
| 36 | if (combobox->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 37 | setting->SetGlobal(true); | ||
| 38 | } else { | ||
| 39 | setting->SetGlobal(false); | ||
| 40 | setting->SetValue(static_cast<Type>(combobox->currentIndex() - | ||
| 41 | ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 42 | } | ||
| 43 | } | ||
| 44 | } | ||
| 32 | 45 | ||
| 33 | // Sets a Qt UI element given a Settings::Setting | 46 | // Sets a Qt UI element given a Settings::Setting |
| 34 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); | 47 | void SetPerGameSetting(QCheckBox* checkbox, const Settings::Setting<bool>* setting); |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 8d7171487..784b6484e 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -65,6 +65,7 @@ void ConfigureCpu::UpdateGroup(int index) { | |||
| 65 | } | 65 | } |
| 66 | 66 | ||
| 67 | void ConfigureCpu::ApplyConfiguration() { | 67 | void ConfigureCpu::ApplyConfiguration() { |
| 68 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpu_accuracy, ui->accuracy); | ||
| 68 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma, | 69 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_unfuse_fma, |
| 69 | ui->cpuopt_unsafe_unfuse_fma, | 70 | ui->cpuopt_unsafe_unfuse_fma, |
| 70 | cpuopt_unsafe_unfuse_fma); | 71 | cpuopt_unsafe_unfuse_fma); |
| @@ -80,22 +81,6 @@ void ConfigureCpu::ApplyConfiguration() { | |||
| 80 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_fastmem_check, | 81 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.cpuopt_unsafe_fastmem_check, |
| 81 | ui->cpuopt_unsafe_fastmem_check, | 82 | ui->cpuopt_unsafe_fastmem_check, |
| 82 | cpuopt_unsafe_fastmem_check); | 83 | cpuopt_unsafe_fastmem_check); |
| 83 | |||
| 84 | if (Settings::IsConfiguringGlobal()) { | ||
| 85 | // Guard if during game and set to game-specific value | ||
| 86 | if (Settings::values.cpu_accuracy.UsingGlobal()) { | ||
| 87 | Settings::values.cpu_accuracy.SetValue( | ||
| 88 | static_cast<Settings::CPUAccuracy>(ui->accuracy->currentIndex())); | ||
| 89 | } | ||
| 90 | } else { | ||
| 91 | if (ui->accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 92 | Settings::values.cpu_accuracy.SetGlobal(true); | ||
| 93 | } else { | ||
| 94 | Settings::values.cpu_accuracy.SetGlobal(false); | ||
| 95 | Settings::values.cpu_accuracy.SetValue(static_cast<Settings::CPUAccuracy>( | ||
| 96 | ui->accuracy->currentIndex() - ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 97 | } | ||
| 98 | } | ||
| 99 | } | 84 | } |
| 100 | 85 | ||
| 101 | void ConfigureCpu::changeEvent(QEvent* event) { | 86 | void ConfigureCpu::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index d79d2e23e..1f647a0d1 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -24,8 +24,8 @@ ConfigureGeneral::ConfigureGeneral(QWidget* parent) | |||
| 24 | SetConfiguration(); | 24 | SetConfiguration(); |
| 25 | 25 | ||
| 26 | if (Settings::IsConfiguringGlobal()) { | 26 | if (Settings::IsConfiguringGlobal()) { |
| 27 | connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, | 27 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, |
| 28 | [this]() { ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked()); }); | 28 | [this]() { ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked()); }); |
| 29 | } | 29 | } |
| 30 | 30 | ||
| 31 | connect(ui->button_reset_defaults, &QPushButton::clicked, this, | 31 | connect(ui->button_reset_defaults, &QPushButton::clicked, this, |
| @@ -45,18 +45,18 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 45 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); | 45 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); |
| 46 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue()); | 46 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse.GetValue()); |
| 47 | 47 | ||
| 48 | ui->toggle_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); | 48 | ui->toggle_speed_limit->setChecked(Settings::values.use_speed_limit.GetValue()); |
| 49 | ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); | 49 | ui->speed_limit->setValue(Settings::values.speed_limit.GetValue()); |
| 50 | 50 | ||
| 51 | ui->fps_cap->setValue(Settings::values.fps_cap.GetValue()); | 51 | ui->fps_cap->setValue(Settings::values.fps_cap.GetValue()); |
| 52 | 52 | ||
| 53 | ui->button_reset_defaults->setEnabled(runtime_lock); | 53 | ui->button_reset_defaults->setEnabled(runtime_lock); |
| 54 | 54 | ||
| 55 | if (Settings::IsConfiguringGlobal()) { | 55 | if (Settings::IsConfiguringGlobal()) { |
| 56 | ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue()); | 56 | ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue()); |
| 57 | } else { | 57 | } else { |
| 58 | ui->frame_limit->setEnabled(Settings::values.use_frame_limit.GetValue() && | 58 | ui->speed_limit->setEnabled(Settings::values.use_speed_limit.GetValue() && |
| 59 | use_frame_limit != ConfigurationShared::CheckState::Global); | 59 | use_speed_limit != ConfigurationShared::CheckState::Global); |
| 60 | } | 60 | } |
| 61 | } | 61 | } |
| 62 | 62 | ||
| @@ -92,19 +92,19 @@ void ConfigureGeneral::ApplyConfiguration() { | |||
| 92 | Settings::values.fps_cap.SetValue(ui->fps_cap->value()); | 92 | Settings::values.fps_cap.SetValue(ui->fps_cap->value()); |
| 93 | 93 | ||
| 94 | // Guard if during game and set to game-specific value | 94 | // Guard if during game and set to game-specific value |
| 95 | if (Settings::values.use_frame_limit.UsingGlobal()) { | 95 | if (Settings::values.use_speed_limit.UsingGlobal()) { |
| 96 | Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() == | 96 | Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() == |
| 97 | Qt::Checked); | 97 | Qt::Checked); |
| 98 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | 98 | Settings::values.speed_limit.SetValue(ui->speed_limit->value()); |
| 99 | } | 99 | } |
| 100 | } else { | 100 | } else { |
| 101 | bool global_frame_limit = use_frame_limit == ConfigurationShared::CheckState::Global; | 101 | bool global_speed_limit = use_speed_limit == ConfigurationShared::CheckState::Global; |
| 102 | Settings::values.use_frame_limit.SetGlobal(global_frame_limit); | 102 | Settings::values.use_speed_limit.SetGlobal(global_speed_limit); |
| 103 | Settings::values.frame_limit.SetGlobal(global_frame_limit); | 103 | Settings::values.speed_limit.SetGlobal(global_speed_limit); |
| 104 | if (!global_frame_limit) { | 104 | if (!global_speed_limit) { |
| 105 | Settings::values.use_frame_limit.SetValue(ui->toggle_frame_limit->checkState() == | 105 | Settings::values.use_speed_limit.SetValue(ui->toggle_speed_limit->checkState() == |
| 106 | Qt::Checked); | 106 | Qt::Checked); |
| 107 | Settings::values.frame_limit.SetValue(ui->frame_limit->value()); | 107 | Settings::values.speed_limit.SetValue(ui->speed_limit->value()); |
| 108 | } | 108 | } |
| 109 | } | 109 | } |
| 110 | } | 110 | } |
| @@ -126,8 +126,8 @@ void ConfigureGeneral::SetupPerGameUI() { | |||
| 126 | // Disables each setting if: | 126 | // Disables each setting if: |
| 127 | // - A game is running (thus settings in use), and | 127 | // - A game is running (thus settings in use), and |
| 128 | // - A non-global setting is applied. | 128 | // - A non-global setting is applied. |
| 129 | ui->toggle_frame_limit->setEnabled(Settings::values.use_frame_limit.UsingGlobal()); | 129 | ui->toggle_speed_limit->setEnabled(Settings::values.use_speed_limit.UsingGlobal()); |
| 130 | ui->frame_limit->setEnabled(Settings::values.frame_limit.UsingGlobal()); | 130 | ui->speed_limit->setEnabled(Settings::values.speed_limit.UsingGlobal()); |
| 131 | 131 | ||
| 132 | return; | 132 | return; |
| 133 | } | 133 | } |
| @@ -139,13 +139,13 @@ void ConfigureGeneral::SetupPerGameUI() { | |||
| 139 | 139 | ||
| 140 | ui->button_reset_defaults->setVisible(false); | 140 | ui->button_reset_defaults->setVisible(false); |
| 141 | 141 | ||
| 142 | ConfigurationShared::SetColoredTristate(ui->toggle_frame_limit, | 142 | ConfigurationShared::SetColoredTristate(ui->toggle_speed_limit, |
| 143 | Settings::values.use_frame_limit, use_frame_limit); | 143 | Settings::values.use_speed_limit, use_speed_limit); |
| 144 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, | 144 | ConfigurationShared::SetColoredTristate(ui->use_multi_core, Settings::values.use_multi_core, |
| 145 | use_multi_core); | 145 | use_multi_core); |
| 146 | 146 | ||
| 147 | connect(ui->toggle_frame_limit, &QCheckBox::clicked, ui->frame_limit, [this]() { | 147 | connect(ui->toggle_speed_limit, &QCheckBox::clicked, ui->speed_limit, [this]() { |
| 148 | ui->frame_limit->setEnabled(ui->toggle_frame_limit->isChecked() && | 148 | ui->speed_limit->setEnabled(ui->toggle_speed_limit->isChecked() && |
| 149 | (use_frame_limit != ConfigurationShared::CheckState::Global)); | 149 | (use_speed_limit != ConfigurationShared::CheckState::Global)); |
| 150 | }); | 150 | }); |
| 151 | } | 151 | } |
diff --git a/src/yuzu/configuration/configure_general.h b/src/yuzu/configuration/configure_general.h index a0fd52492..c9df37d73 100644 --- a/src/yuzu/configuration/configure_general.h +++ b/src/yuzu/configuration/configure_general.h | |||
| @@ -43,6 +43,6 @@ private: | |||
| 43 | 43 | ||
| 44 | std::unique_ptr<Ui::ConfigureGeneral> ui; | 44 | std::unique_ptr<Ui::ConfigureGeneral> ui; |
| 45 | 45 | ||
| 46 | ConfigurationShared::CheckState use_frame_limit; | 46 | ConfigurationShared::CheckState use_speed_limit; |
| 47 | ConfigurationShared::CheckState use_multi_core; | 47 | ConfigurationShared::CheckState use_multi_core; |
| 48 | }; | 48 | }; |
diff --git a/src/yuzu/configuration/configure_general.ui b/src/yuzu/configuration/configure_general.ui index bc3c4b481..8ce97edec 100644 --- a/src/yuzu/configuration/configure_general.ui +++ b/src/yuzu/configuration/configure_general.ui | |||
| @@ -27,14 +27,14 @@ | |||
| 27 | <item> | 27 | <item> |
| 28 | <layout class="QHBoxLayout" name="horizontalLayout_2"> | 28 | <layout class="QHBoxLayout" name="horizontalLayout_2"> |
| 29 | <item> | 29 | <item> |
| 30 | <widget class="QCheckBox" name="toggle_frame_limit"> | 30 | <widget class="QCheckBox" name="toggle_speed_limit"> |
| 31 | <property name="text"> | 31 | <property name="text"> |
| 32 | <string>Limit Speed Percent</string> | 32 | <string>Limit Speed Percent</string> |
| 33 | </property> | 33 | </property> |
| 34 | </widget> | 34 | </widget> |
| 35 | </item> | 35 | </item> |
| 36 | <item> | 36 | <item> |
| 37 | <widget class="QSpinBox" name="frame_limit"> | 37 | <widget class="QSpinBox" name="speed_limit"> |
| 38 | <property name="suffix"> | 38 | <property name="suffix"> |
| 39 | <string>%</string> | 39 | <string>%</string> |
| 40 | </property> | 40 | </property> |
diff --git a/src/yuzu/configuration/configure_graphics.cpp b/src/yuzu/configuration/configure_graphics.cpp index fef211707..37e896258 100644 --- a/src/yuzu/configuration/configure_graphics.cpp +++ b/src/yuzu/configuration/configure_graphics.cpp | |||
| @@ -31,7 +31,7 @@ ConfigureGraphics::ConfigureGraphics(QWidget* parent) | |||
| 31 | } | 31 | } |
| 32 | 32 | ||
| 33 | ui->backend->addItem(QStringLiteral("GLSL")); | 33 | ui->backend->addItem(QStringLiteral("GLSL")); |
| 34 | ui->backend->addItem(tr("GLASM (NVIDIA Only)")); | 34 | ui->backend->addItem(tr("GLASM (Assembly Shaders, NVIDIA Only)")); |
| 35 | ui->backend->addItem(QStringLiteral("SPIR-V (Experimental, Mesa Only)")); | 35 | ui->backend->addItem(QStringLiteral("SPIR-V (Experimental, Mesa Only)")); |
| 36 | 36 | ||
| 37 | SetupPerGameUI(); | 37 | SetupPerGameUI(); |
| @@ -98,7 +98,8 @@ void ConfigureGraphics::SetConfiguration() { | |||
| 98 | 98 | ||
| 99 | if (Settings::IsConfiguringGlobal()) { | 99 | if (Settings::IsConfiguringGlobal()) { |
| 100 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); | 100 | ui->api->setCurrentIndex(static_cast<int>(Settings::values.renderer_backend.GetValue())); |
| 101 | ui->fullscreen_mode_combobox->setCurrentIndex(Settings::values.fullscreen_mode.GetValue()); | 101 | ui->fullscreen_mode_combobox->setCurrentIndex( |
| 102 | static_cast<int>(Settings::values.fullscreen_mode.GetValue())); | ||
| 102 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); | 103 | ui->aspect_ratio_combobox->setCurrentIndex(Settings::values.aspect_ratio.GetValue()); |
| 103 | } else { | 104 | } else { |
| 104 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); | 105 | ConfigurationShared::SetPerGameSetting(ui->api, &Settings::values.renderer_backend); |
| @@ -310,8 +311,9 @@ void ConfigureGraphics::SetupPerGameUI() { | |||
| 310 | 311 | ||
| 311 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, | 312 | ConfigurationShared::SetColoredComboBox(ui->aspect_ratio_combobox, ui->ar_label, |
| 312 | Settings::values.aspect_ratio.GetValue(true)); | 313 | Settings::values.aspect_ratio.GetValue(true)); |
| 313 | ConfigurationShared::SetColoredComboBox(ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, | 314 | ConfigurationShared::SetColoredComboBox( |
| 314 | Settings::values.fullscreen_mode.GetValue(true)); | 315 | ui->fullscreen_mode_combobox, ui->fullscreen_mode_label, |
| 316 | static_cast<int>(Settings::values.fullscreen_mode.GetValue(true))); | ||
| 315 | ConfigurationShared::InsertGlobalItem( | 317 | ConfigurationShared::InsertGlobalItem( |
| 316 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); | 318 | ui->api, static_cast<int>(Settings::values.renderer_backend.GetValue(true))); |
| 317 | } | 319 | } |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 38276feb1..a31b8e192 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -48,11 +48,7 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 48 | } | 48 | } |
| 49 | 49 | ||
| 50 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { | 50 | void ConfigureGraphicsAdvanced::ApplyConfiguration() { |
| 51 | // Subtract 2 if configuring per-game (separator and "use global configuration" take 2 slots) | 51 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.gpu_accuracy, ui->gpu_accuracy); |
| 52 | const auto gpu_accuracy = static_cast<Settings::GPUAccuracy>( | ||
| 53 | ui->gpu_accuracy->currentIndex() - | ||
| 54 | ((Settings::IsConfiguringGlobal()) ? 0 : ConfigurationShared::USE_GLOBAL_OFFSET)); | ||
| 55 | |||
| 56 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | 52 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, |
| 57 | ui->anisotropic_filtering_combobox); | 53 | ui->anisotropic_filtering_combobox); |
| 58 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); | 54 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); |
| @@ -63,20 +59,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 63 | use_caches_gc); | 59 | use_caches_gc); |
| 64 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, | 60 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_fast_gpu_time, |
| 65 | ui->use_fast_gpu_time, use_fast_gpu_time); | 61 | ui->use_fast_gpu_time, use_fast_gpu_time); |
| 66 | |||
| 67 | if (Settings::IsConfiguringGlobal()) { | ||
| 68 | // Must guard in case of a during-game configuration when set to be game-specific. | ||
| 69 | if (Settings::values.gpu_accuracy.UsingGlobal()) { | ||
| 70 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | ||
| 71 | } | ||
| 72 | } else { | ||
| 73 | if (ui->gpu_accuracy->currentIndex() == ConfigurationShared::USE_GLOBAL_INDEX) { | ||
| 74 | Settings::values.gpu_accuracy.SetGlobal(true); | ||
| 75 | } else { | ||
| 76 | Settings::values.gpu_accuracy.SetGlobal(false); | ||
| 77 | Settings::values.gpu_accuracy.SetValue(gpu_accuracy); | ||
| 78 | } | ||
| 79 | } | ||
| 80 | } | 62 | } |
| 81 | 63 | ||
| 82 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { | 64 | void ConfigureGraphicsAdvanced::changeEvent(QEvent* event) { |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index 3d747e8d9..9544f0fb0 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -972,23 +972,23 @@ void GMainWindow::InitializeHotkeys() { | |||
| 972 | }); | 972 | }); |
| 973 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this), | 973 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Toggle Speed Limit"), this), |
| 974 | &QShortcut::activated, this, [&] { | 974 | &QShortcut::activated, this, [&] { |
| 975 | Settings::values.use_frame_limit.SetValue( | 975 | Settings::values.use_speed_limit.SetValue( |
| 976 | !Settings::values.use_frame_limit.GetValue()); | 976 | !Settings::values.use_speed_limit.GetValue()); |
| 977 | UpdateStatusBar(); | 977 | UpdateStatusBar(); |
| 978 | }); | 978 | }); |
| 979 | constexpr u16 SPEED_LIMIT_STEP = 5; | 979 | constexpr u16 SPEED_LIMIT_STEP = 5; |
| 980 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), | 980 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Increase Speed Limit"), this), |
| 981 | &QShortcut::activated, this, [&] { | 981 | &QShortcut::activated, this, [&] { |
| 982 | if (Settings::values.frame_limit.GetValue() < 9999 - SPEED_LIMIT_STEP) { | 982 | if (Settings::values.speed_limit.GetValue() < 9999 - SPEED_LIMIT_STEP) { |
| 983 | Settings::values.frame_limit.SetValue(SPEED_LIMIT_STEP + | 983 | Settings::values.speed_limit.SetValue(SPEED_LIMIT_STEP + |
| 984 | Settings::values.frame_limit.GetValue()); | 984 | Settings::values.speed_limit.GetValue()); |
| 985 | UpdateStatusBar(); | 985 | UpdateStatusBar(); |
| 986 | } | 986 | } |
| 987 | }); | 987 | }); |
| 988 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), | 988 | connect(hotkey_registry.GetHotkey(main_window, QStringLiteral("Decrease Speed Limit"), this), |
| 989 | &QShortcut::activated, this, [&] { | 989 | &QShortcut::activated, this, [&] { |
| 990 | if (Settings::values.frame_limit.GetValue() > SPEED_LIMIT_STEP) { | 990 | if (Settings::values.speed_limit.GetValue() > SPEED_LIMIT_STEP) { |
| 991 | Settings::values.frame_limit.SetValue(Settings::values.frame_limit.GetValue() - | 991 | Settings::values.speed_limit.SetValue(Settings::values.speed_limit.GetValue() - |
| 992 | SPEED_LIMIT_STEP); | 992 | SPEED_LIMIT_STEP); |
| 993 | UpdateStatusBar(); | 993 | UpdateStatusBar(); |
| 994 | } | 994 | } |
| @@ -2513,7 +2513,7 @@ void GMainWindow::ShowFullscreen() { | |||
| 2513 | ui.menubar->hide(); | 2513 | ui.menubar->hide(); |
| 2514 | statusBar()->hide(); | 2514 | statusBar()->hide(); |
| 2515 | 2515 | ||
| 2516 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | 2516 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { |
| 2517 | showFullScreen(); | 2517 | showFullScreen(); |
| 2518 | return; | 2518 | return; |
| 2519 | } | 2519 | } |
| @@ -2528,7 +2528,7 @@ void GMainWindow::ShowFullscreen() { | |||
| 2528 | } else { | 2528 | } else { |
| 2529 | UISettings::values.renderwindow_geometry = render_window->saveGeometry(); | 2529 | UISettings::values.renderwindow_geometry = render_window->saveGeometry(); |
| 2530 | 2530 | ||
| 2531 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | 2531 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { |
| 2532 | render_window->showFullScreen(); | 2532 | render_window->showFullScreen(); |
| 2533 | return; | 2533 | return; |
| 2534 | } | 2534 | } |
| @@ -2545,7 +2545,7 @@ void GMainWindow::ShowFullscreen() { | |||
| 2545 | 2545 | ||
| 2546 | void GMainWindow::HideFullscreen() { | 2546 | void GMainWindow::HideFullscreen() { |
| 2547 | if (ui.action_Single_Window_Mode->isChecked()) { | 2547 | if (ui.action_Single_Window_Mode->isChecked()) { |
| 2548 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | 2548 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { |
| 2549 | showNormal(); | 2549 | showNormal(); |
| 2550 | restoreGeometry(UISettings::values.geometry); | 2550 | restoreGeometry(UISettings::values.geometry); |
| 2551 | } else { | 2551 | } else { |
| @@ -2559,7 +2559,7 @@ void GMainWindow::HideFullscreen() { | |||
| 2559 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); | 2559 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); |
| 2560 | ui.menubar->show(); | 2560 | ui.menubar->show(); |
| 2561 | } else { | 2561 | } else { |
| 2562 | if (Settings::values.fullscreen_mode.GetValue() == 1) { | 2562 | if (Settings::values.fullscreen_mode.GetValue() == Settings::FullscreenMode::Exclusive) { |
| 2563 | render_window->showNormal(); | 2563 | render_window->showNormal(); |
| 2564 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | 2564 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); |
| 2565 | } else { | 2565 | } else { |
| @@ -2910,10 +2910,10 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2910 | shader_building_label->setVisible(false); | 2910 | shader_building_label->setVisible(false); |
| 2911 | } | 2911 | } |
| 2912 | 2912 | ||
| 2913 | if (Settings::values.use_frame_limit.GetValue()) { | 2913 | if (Settings::values.use_speed_limit.GetValue()) { |
| 2914 | emu_speed_label->setText(tr("Speed: %1% / %2%") | 2914 | emu_speed_label->setText(tr("Speed: %1% / %2%") |
| 2915 | .arg(results.emulation_speed * 100.0, 0, 'f', 0) | 2915 | .arg(results.emulation_speed * 100.0, 0, 'f', 0) |
| 2916 | .arg(Settings::values.frame_limit.GetValue())); | 2916 | .arg(Settings::values.speed_limit.GetValue())); |
| 2917 | } else { | 2917 | } else { |
| 2918 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | 2918 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |
| 2919 | } | 2919 | } |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index d4ca6bb57..5af1ee6a8 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -451,8 +451,8 @@ void Config::ReadValues() { | |||
| 451 | ReadSetting("Renderer", Settings::values.fullscreen_mode); | 451 | ReadSetting("Renderer", Settings::values.fullscreen_mode); |
| 452 | ReadSetting("Renderer", Settings::values.aspect_ratio); | 452 | ReadSetting("Renderer", Settings::values.aspect_ratio); |
| 453 | ReadSetting("Renderer", Settings::values.max_anisotropy); | 453 | ReadSetting("Renderer", Settings::values.max_anisotropy); |
| 454 | ReadSetting("Renderer", Settings::values.use_frame_limit); | 454 | ReadSetting("Renderer", Settings::values.use_speed_limit); |
| 455 | ReadSetting("Renderer", Settings::values.frame_limit); | 455 | ReadSetting("Renderer", Settings::values.speed_limit); |
| 456 | ReadSetting("Renderer", Settings::values.use_disk_shader_cache); | 456 | ReadSetting("Renderer", Settings::values.use_disk_shader_cache); |
| 457 | ReadSetting("Renderer", Settings::values.gpu_accuracy); | 457 | ReadSetting("Renderer", Settings::values.gpu_accuracy); |
| 458 | ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); | 458 | ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index b2b2095d1..e646e2d2f 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -265,13 +265,13 @@ use_nvdec_emulation = | |||
| 265 | # 0: Off, 1 (default): On | 265 | # 0: Off, 1 (default): On |
| 266 | accelerate_astc = | 266 | accelerate_astc = |
| 267 | 267 | ||
| 268 | # Turns on the frame limiter, which will limit frames output to the target game speed | 268 | # Turns on the speed limiter, which will limit the emulation speed to the desired speed limit value |
| 269 | # 0: Off, 1: On (default) | 269 | # 0: Off, 1: On (default) |
| 270 | use_frame_limit = | 270 | use_speed_limit = |
| 271 | 271 | ||
| 272 | # Limits the speed of the game to run no faster than this value as a percentage of target speed | 272 | # Limits the speed of the game to run no faster than this value as a percentage of target speed |
| 273 | # 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) | 273 | # 1 - 9999: Speed limit as a percentage of target game speed. 100 (default) |
| 274 | frame_limit = | 274 | speed_limit = |
| 275 | 275 | ||
| 276 | # Whether to use disk based shader cache | 276 | # Whether to use disk based shader cache |
| 277 | # 0: Off, 1 (default): On | 277 | # 0: Off, 1 (default): On |
diff --git a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp index 353e51ea7..ea3e0ada4 100644 --- a/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp +++ b/src/yuzu_cmd/emu_window/emu_window_sdl2.cpp | |||
| @@ -124,7 +124,7 @@ void EmuWindow_SDL2::OnResize() { | |||
| 124 | 124 | ||
| 125 | void EmuWindow_SDL2::Fullscreen() { | 125 | void EmuWindow_SDL2::Fullscreen() { |
| 126 | switch (Settings::values.fullscreen_mode.GetValue()) { | 126 | switch (Settings::values.fullscreen_mode.GetValue()) { |
| 127 | case 1: // Exclusive fullscreen | 127 | case Settings::FullscreenMode::Exclusive: |
| 128 | // Set window size to render size before entering fullscreen -- SDL does not resize to | 128 | // Set window size to render size before entering fullscreen -- SDL does not resize to |
| 129 | // display dimensions in this mode. | 129 | // display dimensions in this mode. |
| 130 | // TODO: Multiply the window size by resolution_factor (for both docked modes) | 130 | // TODO: Multiply the window size by resolution_factor (for both docked modes) |
| @@ -140,7 +140,7 @@ void EmuWindow_SDL2::Fullscreen() { | |||
| 140 | LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError()); | 140 | LOG_ERROR(Frontend, "Fullscreening failed: {}", SDL_GetError()); |
| 141 | LOG_INFO(Frontend, "Attempting to use borderless fullscreen..."); | 141 | LOG_INFO(Frontend, "Attempting to use borderless fullscreen..."); |
| 142 | [[fallthrough]]; | 142 | [[fallthrough]]; |
| 143 | case 0: // Borderless window | 143 | case Settings::FullscreenMode::Borderless: |
| 144 | if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { | 144 | if (SDL_SetWindowFullscreen(render_window, SDL_WINDOW_FULLSCREEN_DESKTOP) == 0) { |
| 145 | return; | 145 | return; |
| 146 | } | 146 | } |