diff options
Diffstat (limited to 'src')
80 files changed, 1970 insertions, 1195 deletions
diff --git a/src/audio_core/audio_out.cpp b/src/audio_core/audio_out.cpp index 20a756dce..44a899d08 100644 --- a/src/audio_core/audio_out.cpp +++ b/src/audio_core/audio_out.cpp | |||
| @@ -30,7 +30,8 @@ StreamPtr AudioOut::OpenStream(Core::Timing::CoreTiming& core_timing, u32 sample | |||
| 30 | u32 num_channels, std::string&& name, | 30 | u32 num_channels, std::string&& name, |
| 31 | Stream::ReleaseCallback&& release_callback) { | 31 | Stream::ReleaseCallback&& release_callback) { |
| 32 | if (!sink) { | 32 | if (!sink) { |
| 33 | sink = CreateSinkFromID(Settings::values.sink_id, Settings::values.audio_device_id); | 33 | sink = CreateSinkFromID(Settings::values.sink_id.GetValue(), |
| 34 | Settings::values.audio_device_id.GetValue()); | ||
| 34 | } | 35 | } |
| 35 | 36 | ||
| 36 | return std::make_shared<Stream>( | 37 | return std::make_shared<Stream>( |
diff --git a/src/audio_core/command_generator.cpp b/src/audio_core/command_generator.cpp index 02c6e6f6a..45b2eef52 100644 --- a/src/audio_core/command_generator.cpp +++ b/src/audio_core/command_generator.cpp | |||
| @@ -412,7 +412,10 @@ void CommandGenerator::GenerateDataSourceCommand(ServerVoiceInfo& voice_info, Vo | |||
| 412 | } | 412 | } |
| 413 | } else { | 413 | } else { |
| 414 | switch (in_params.sample_format) { | 414 | switch (in_params.sample_format) { |
| 415 | case SampleFormat::Pcm8: | ||
| 415 | case SampleFormat::Pcm16: | 416 | case SampleFormat::Pcm16: |
| 417 | case SampleFormat::Pcm32: | ||
| 418 | case SampleFormat::PcmFloat: | ||
| 416 | DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel, | 419 | DecodeFromWaveBuffers(voice_info, GetChannelMixBuffer(channel), dsp_state, channel, |
| 417 | worker_params.sample_rate, worker_params.sample_count, | 420 | worker_params.sample_rate, worker_params.sample_count, |
| 418 | in_params.node_id); | 421 | in_params.node_id); |
| @@ -1018,9 +1021,10 @@ void CommandGenerator::GenerateFinalMixCommand() { | |||
| 1018 | } | 1021 | } |
| 1019 | } | 1022 | } |
| 1020 | 1023 | ||
| 1021 | s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state, | 1024 | template <typename T> |
| 1022 | s32 sample_start_offset, s32 sample_end_offset, s32 sample_count, | 1025 | s32 CommandGenerator::DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, |
| 1023 | s32 channel, std::size_t mix_offset) { | 1026 | s32 sample_start_offset, s32 sample_end_offset, s32 sample_count, |
| 1027 | s32 channel, std::size_t mix_offset) { | ||
| 1024 | const auto& in_params = voice_info.GetInParams(); | 1028 | const auto& in_params = voice_info.GetInParams(); |
| 1025 | const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index]; | 1029 | const auto& wave_buffer = in_params.wave_buffer[dsp_state.wave_buffer_index]; |
| 1026 | if (wave_buffer.buffer_address == 0) { | 1030 | if (wave_buffer.buffer_address == 0) { |
| @@ -1034,24 +1038,37 @@ s32 CommandGenerator::DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_s | |||
| 1034 | } | 1038 | } |
| 1035 | const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset; | 1039 | const auto samples_remaining = (sample_end_offset - sample_start_offset) - dsp_state.offset; |
| 1036 | const auto start_offset = | 1040 | const auto start_offset = |
| 1037 | ((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(s16); | 1041 | ((dsp_state.offset + sample_start_offset) * in_params.channel_count) * sizeof(T); |
| 1038 | const auto buffer_pos = wave_buffer.buffer_address + start_offset; | 1042 | const auto buffer_pos = wave_buffer.buffer_address + start_offset; |
| 1039 | const auto samples_processed = std::min(sample_count, samples_remaining); | 1043 | const auto samples_processed = std::min(sample_count, samples_remaining); |
| 1040 | 1044 | ||
| 1041 | if (in_params.channel_count == 1) { | 1045 | const auto channel_count = in_params.channel_count; |
| 1042 | std::vector<s16> buffer(samples_processed); | 1046 | std::vector<T> buffer(samples_processed * channel_count); |
| 1043 | memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16)); | 1047 | memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(T)); |
| 1044 | for (std::size_t i = 0; i < buffer.size(); i++) { | ||
| 1045 | sample_buffer[mix_offset + i] = buffer[i]; | ||
| 1046 | } | ||
| 1047 | } else { | ||
| 1048 | const auto channel_count = in_params.channel_count; | ||
| 1049 | std::vector<s16> buffer(samples_processed * channel_count); | ||
| 1050 | memory.ReadBlock(buffer_pos, buffer.data(), buffer.size() * sizeof(s16)); | ||
| 1051 | 1048 | ||
| 1049 | if constexpr (std::is_floating_point_v<T>) { | ||
| 1050 | for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) { | ||
| 1051 | sample_buffer[mix_offset + i] = static_cast<s32>(buffer[i * channel_count + channel] * | ||
| 1052 | std::numeric_limits<s16>::max()); | ||
| 1053 | } | ||
| 1054 | } else if constexpr (sizeof(T) == 1) { | ||
| 1055 | for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) { | ||
| 1056 | sample_buffer[mix_offset + i] = | ||
| 1057 | static_cast<s32>(static_cast<f32>(buffer[i * channel_count + channel] / | ||
| 1058 | std::numeric_limits<s8>::max()) * | ||
| 1059 | std::numeric_limits<s16>::max()); | ||
| 1060 | } | ||
| 1061 | } else if constexpr (sizeof(T) == 2) { | ||
| 1052 | for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) { | 1062 | for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) { |
| 1053 | sample_buffer[mix_offset + i] = buffer[i * channel_count + channel]; | 1063 | sample_buffer[mix_offset + i] = buffer[i * channel_count + channel]; |
| 1054 | } | 1064 | } |
| 1065 | } else { | ||
| 1066 | for (std::size_t i = 0; i < static_cast<std::size_t>(samples_processed); i++) { | ||
| 1067 | sample_buffer[mix_offset + i] = | ||
| 1068 | static_cast<s32>(static_cast<f32>(buffer[i * channel_count + channel] / | ||
| 1069 | std::numeric_limits<s32>::max()) * | ||
| 1070 | std::numeric_limits<s16>::max()); | ||
| 1071 | } | ||
| 1055 | } | 1072 | } |
| 1056 | 1073 | ||
| 1057 | return samples_processed; | 1074 | return samples_processed; |
| @@ -1267,10 +1284,25 @@ void CommandGenerator::DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, std::s | |||
| 1267 | 1284 | ||
| 1268 | s32 samples_decoded{0}; | 1285 | s32 samples_decoded{0}; |
| 1269 | switch (in_params.sample_format) { | 1286 | switch (in_params.sample_format) { |
| 1287 | case SampleFormat::Pcm8: | ||
| 1288 | samples_decoded = | ||
| 1289 | DecodePcm<s8>(voice_info, dsp_state, samples_offset_start, samples_offset_end, | ||
| 1290 | samples_to_read - samples_read, channel, temp_mix_offset); | ||
| 1291 | break; | ||
| 1270 | case SampleFormat::Pcm16: | 1292 | case SampleFormat::Pcm16: |
| 1271 | samples_decoded = | 1293 | samples_decoded = |
| 1272 | DecodePcm16(voice_info, dsp_state, samples_offset_start, samples_offset_end, | 1294 | DecodePcm<s16>(voice_info, dsp_state, samples_offset_start, samples_offset_end, |
| 1273 | samples_to_read - samples_read, channel, temp_mix_offset); | 1295 | samples_to_read - samples_read, channel, temp_mix_offset); |
| 1296 | break; | ||
| 1297 | case SampleFormat::Pcm32: | ||
| 1298 | samples_decoded = | ||
| 1299 | DecodePcm<s32>(voice_info, dsp_state, samples_offset_start, samples_offset_end, | ||
| 1300 | samples_to_read - samples_read, channel, temp_mix_offset); | ||
| 1301 | break; | ||
| 1302 | case SampleFormat::PcmFloat: | ||
| 1303 | samples_decoded = | ||
| 1304 | DecodePcm<f32>(voice_info, dsp_state, samples_offset_start, samples_offset_end, | ||
| 1305 | samples_to_read - samples_read, channel, temp_mix_offset); | ||
| 1274 | break; | 1306 | break; |
| 1275 | case SampleFormat::Adpcm: | 1307 | case SampleFormat::Adpcm: |
| 1276 | samples_decoded = | 1308 | samples_decoded = |
diff --git a/src/audio_core/command_generator.h b/src/audio_core/command_generator.h index ac034b0a5..59a33ba76 100644 --- a/src/audio_core/command_generator.h +++ b/src/audio_core/command_generator.h | |||
| @@ -88,8 +88,9 @@ private: | |||
| 88 | std::vector<u8>& work_buffer); | 88 | std::vector<u8>& work_buffer); |
| 89 | void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear); | 89 | void UpdateI3dl2Reverb(I3dl2ReverbParams& info, I3dl2ReverbState& state, bool should_clear); |
| 90 | // DSP Code | 90 | // DSP Code |
| 91 | s32 DecodePcm16(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset, | 91 | template <typename T> |
| 92 | s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset); | 92 | s32 DecodePcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset, |
| 93 | s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset); | ||
| 93 | s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset, | 94 | s32 DecodeAdpcm(ServerVoiceInfo& voice_info, VoiceState& dsp_state, s32 sample_start_offset, |
| 94 | s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset); | 95 | s32 sample_end_offset, s32 sample_count, s32 channel, std::size_t mix_offset); |
| 95 | void DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, std::span<s32> output, | 96 | void DecodeFromWaveBuffers(ServerVoiceInfo& voice_info, std::span<s32> output, |
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index a6fa9a85d..e03fffd8d 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt | |||
| @@ -180,7 +180,6 @@ add_library(common STATIC | |||
| 180 | thread.cpp | 180 | thread.cpp |
| 181 | thread.h | 181 | thread.h |
| 182 | thread_queue_list.h | 182 | thread_queue_list.h |
| 183 | thread_worker.cpp | ||
| 184 | thread_worker.h | 183 | thread_worker.h |
| 185 | threadsafe_queue.h | 184 | threadsafe_queue.h |
| 186 | time_zone.cpp | 185 | time_zone.cpp |
| @@ -188,6 +187,7 @@ add_library(common STATIC | |||
| 188 | tiny_mt.h | 187 | tiny_mt.h |
| 189 | tree.h | 188 | tree.h |
| 190 | uint128.h | 189 | uint128.h |
| 190 | unique_function.h | ||
| 191 | uuid.cpp | 191 | uuid.cpp |
| 192 | uuid.h | 192 | uuid.h |
| 193 | vector_math.h | 193 | vector_math.h |
diff --git a/src/common/settings.cpp b/src/common/settings.cpp index e1bb4b7ff..e1973af85 100644 --- a/src/common/settings.cpp +++ b/src/common/settings.cpp | |||
| @@ -41,7 +41,7 @@ void LogSettings() { | |||
| 41 | LOG_INFO(Config, "yuzu Configuration:"); | 41 | LOG_INFO(Config, "yuzu Configuration:"); |
| 42 | log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); | 42 | log_setting("Controls_UseDockedMode", values.use_docked_mode.GetValue()); |
| 43 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); | 43 | log_setting("System_RngSeed", values.rng_seed.GetValue().value_or(0)); |
| 44 | log_setting("System_CurrentUser", values.current_user); | 44 | log_setting("System_CurrentUser", values.current_user.GetValue()); |
| 45 | log_setting("System_LanguageIndex", values.language_index.GetValue()); | 45 | log_setting("System_LanguageIndex", values.language_index.GetValue()); |
| 46 | log_setting("System_RegionIndex", values.region_index.GetValue()); | 46 | log_setting("System_RegionIndex", values.region_index.GetValue()); |
| 47 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); | 47 | log_setting("System_TimeZoneIndex", values.time_zone_index.GetValue()); |
| @@ -61,18 +61,18 @@ void LogSettings() { | |||
| 61 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); | 61 | log_setting("Renderer_UseAsynchronousShaders", values.use_asynchronous_shaders.GetValue()); |
| 62 | log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue()); | 62 | log_setting("Renderer_UseGarbageCollection", values.use_caches_gc.GetValue()); |
| 63 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); | 63 | log_setting("Renderer_AnisotropicFilteringLevel", values.max_anisotropy.GetValue()); |
| 64 | log_setting("Audio_OutputEngine", values.sink_id); | 64 | log_setting("Audio_OutputEngine", values.sink_id.GetValue()); |
| 65 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); | 65 | log_setting("Audio_EnableAudioStretching", values.enable_audio_stretching.GetValue()); |
| 66 | log_setting("Audio_OutputDevice", values.audio_device_id); | 66 | log_setting("Audio_OutputDevice", values.audio_device_id.GetValue()); |
| 67 | log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd); | 67 | log_setting("DataStorage_UseVirtualSd", values.use_virtual_sd.GetValue()); |
| 68 | log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir)); | 68 | log_path("DataStorage_CacheDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::CacheDir)); |
| 69 | log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir)); | 69 | log_path("DataStorage_ConfigDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::ConfigDir)); |
| 70 | log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir)); | 70 | log_path("DataStorage_LoadDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::LoadDir)); |
| 71 | log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir)); | 71 | log_path("DataStorage_NANDDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::NANDDir)); |
| 72 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); | 72 | log_path("DataStorage_SDMCDir", Common::FS::GetYuzuPath(Common::FS::YuzuPath::SDMCDir)); |
| 73 | log_setting("Debugging_ProgramArgs", values.program_args); | 73 | log_setting("Debugging_ProgramArgs", values.program_args.GetValue()); |
| 74 | log_setting("Services_BCATBackend", values.bcat_backend); | 74 | log_setting("Services_BCATBackend", values.bcat_backend.GetValue()); |
| 75 | log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local); | 75 | log_setting("Services_BCATBoxcatLocal", values.bcat_boxcat_local.GetValue()); |
| 76 | } | 76 | } |
| 77 | 77 | ||
| 78 | bool IsConfiguringGlobal() { | 78 | bool IsConfiguringGlobal() { |
| @@ -93,8 +93,8 @@ bool IsGPULevelHigh() { | |||
| 93 | } | 93 | } |
| 94 | 94 | ||
| 95 | bool IsFastmemEnabled() { | 95 | bool IsFastmemEnabled() { |
| 96 | if (values.cpu_accuracy.GetValue() == CPUAccuracy::DebugMode) { | 96 | if (values.cpu_debug_mode) { |
| 97 | return values.cpuopt_fastmem; | 97 | return static_cast<bool>(values.cpuopt_fastmem); |
| 98 | } | 98 | } |
| 99 | return true; | 99 | return true; |
| 100 | } | 100 | } |
diff --git a/src/common/settings.h b/src/common/settings.h index 82ec18e27..71d0f864f 100644 --- a/src/common/settings.h +++ b/src/common/settings.h | |||
| @@ -10,10 +10,12 @@ | |||
| 10 | #include <map> | 10 | #include <map> |
| 11 | #include <optional> | 11 | #include <optional> |
| 12 | #include <string> | 12 | #include <string> |
| 13 | #include <utility> | ||
| 13 | #include <vector> | 14 | #include <vector> |
| 14 | 15 | ||
| 15 | #include "common/common_types.h" | 16 | #include "common/common_types.h" |
| 16 | #include "common/settings_input.h" | 17 | #include "common/settings_input.h" |
| 18 | #include "input_common/udp/client.h" | ||
| 17 | 19 | ||
| 18 | namespace Settings { | 20 | namespace Settings { |
| 19 | 21 | ||
| @@ -29,73 +31,240 @@ enum class GPUAccuracy : u32 { | |||
| 29 | }; | 31 | }; |
| 30 | 32 | ||
| 31 | enum class CPUAccuracy : u32 { | 33 | enum class CPUAccuracy : u32 { |
| 32 | Accurate = 0, | 34 | Auto = 0, |
| 33 | Unsafe = 1, | 35 | Accurate = 1, |
| 34 | DebugMode = 2, | 36 | Unsafe = 2, |
| 35 | }; | 37 | }; |
| 36 | 38 | ||
| 39 | /** The BasicSetting class is a simple resource manager. It defines a label and default value | ||
| 40 | * alongside the actual value of the setting for simpler and less-error prone use with frontend | ||
| 41 | * configurations. Setting a default value and label is required, though subclasses may deviate from | ||
| 42 | * this requirement. | ||
| 43 | */ | ||
| 44 | template <typename Type> | ||
| 45 | class BasicSetting { | ||
| 46 | protected: | ||
| 47 | BasicSetting() = default; | ||
| 48 | |||
| 49 | /** | ||
| 50 | * Only sets the setting to the given initializer, leaving the other members to their default | ||
| 51 | * initializers. | ||
| 52 | * | ||
| 53 | * @param global_val Initial value of the setting | ||
| 54 | */ | ||
| 55 | explicit BasicSetting(const Type& global_val) : global{global_val} {} | ||
| 56 | |||
| 57 | public: | ||
| 58 | /** | ||
| 59 | * Sets a default value, label, and setting value. | ||
| 60 | * | ||
| 61 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 62 | * @param name Label for the setting | ||
| 63 | */ | ||
| 64 | explicit BasicSetting(const Type& default_val, const std::string& name) | ||
| 65 | : default_value{default_val}, global{default_val}, label{name} {} | ||
| 66 | ~BasicSetting() = default; | ||
| 67 | |||
| 68 | /** | ||
| 69 | * Returns a reference to the setting's value. | ||
| 70 | * | ||
| 71 | * @returns A reference to the setting | ||
| 72 | */ | ||
| 73 | [[nodiscard]] const Type& GetValue() const { | ||
| 74 | return global; | ||
| 75 | } | ||
| 76 | |||
| 77 | /** | ||
| 78 | * Sets the setting to the given value. | ||
| 79 | * | ||
| 80 | * @param value The desired value | ||
| 81 | */ | ||
| 82 | void SetValue(const Type& value) { | ||
| 83 | Type temp{value}; | ||
| 84 | std::swap(global, temp); | ||
| 85 | } | ||
| 86 | |||
| 87 | /** | ||
| 88 | * Returns the value that this setting was created with. | ||
| 89 | * | ||
| 90 | * @returns A reference to the default value | ||
| 91 | */ | ||
| 92 | [[nodiscard]] const Type& GetDefault() const { | ||
| 93 | return default_value; | ||
| 94 | } | ||
| 95 | |||
| 96 | /** | ||
| 97 | * Returns the label this setting was created with. | ||
| 98 | * | ||
| 99 | * @returns A reference to the label | ||
| 100 | */ | ||
| 101 | [[nodiscard]] const std::string& GetLabel() const { | ||
| 102 | return label; | ||
| 103 | } | ||
| 104 | |||
| 105 | /** | ||
| 106 | * Assigns a value to the setting. | ||
| 107 | * | ||
| 108 | * @param value The desired setting value | ||
| 109 | * | ||
| 110 | * @returns A reference to the setting | ||
| 111 | */ | ||
| 112 | const Type& operator=(const Type& value) { | ||
| 113 | Type temp{value}; | ||
| 114 | std::swap(global, temp); | ||
| 115 | return global; | ||
| 116 | } | ||
| 117 | |||
| 118 | /** | ||
| 119 | * Returns a reference to the setting. | ||
| 120 | * | ||
| 121 | * @returns A reference to the setting | ||
| 122 | */ | ||
| 123 | explicit operator const Type&() const { | ||
| 124 | return global; | ||
| 125 | } | ||
| 126 | |||
| 127 | protected: | ||
| 128 | const Type default_value{}; ///< The default value | ||
| 129 | Type global{}; ///< The setting | ||
| 130 | const std::string label{}; ///< The setting's label | ||
| 131 | }; | ||
| 132 | |||
| 133 | /** | ||
| 134 | * The Setting class is a slightly more complex version of the BasicSetting class. This adds a | ||
| 135 | * custom setting to switch to when a guest application specifically requires it. The effect is that | ||
| 136 | * other components of the emulator can access the setting's intended value without any need for the | ||
| 137 | * component to ask whether the custom or global setting is needed at the moment. | ||
| 138 | * | ||
| 139 | * By default, the global setting is used. | ||
| 140 | * | ||
| 141 | * Like the BasicSetting, this requires setting a default value and label to use. | ||
| 142 | */ | ||
| 37 | template <typename Type> | 143 | template <typename Type> |
| 38 | class Setting final { | 144 | class Setting final : public BasicSetting<Type> { |
| 39 | public: | 145 | public: |
| 40 | Setting() = default; | 146 | /** |
| 41 | explicit Setting(Type val) : global{val} {} | 147 | * Sets a default value, label, and setting value. |
| 148 | * | ||
| 149 | * @param default_val Intial value of the setting, and default value of the setting | ||
| 150 | * @param name Label for the setting | ||
| 151 | */ | ||
| 152 | explicit Setting(const Type& default_val, const std::string& name) | ||
| 153 | : BasicSetting<Type>(default_val, name) {} | ||
| 42 | ~Setting() = default; | 154 | ~Setting() = default; |
| 155 | |||
| 156 | /** | ||
| 157 | * Tells this setting to represent either the global or custom setting when other member | ||
| 158 | * functions are used. | ||
| 159 | * | ||
| 160 | * @param to_global Whether to use the global or custom setting. | ||
| 161 | */ | ||
| 43 | void SetGlobal(bool to_global) { | 162 | void SetGlobal(bool to_global) { |
| 44 | use_global = to_global; | 163 | use_global = to_global; |
| 45 | } | 164 | } |
| 46 | bool UsingGlobal() const { | 165 | |
| 166 | /** | ||
| 167 | * Returns whether this setting is using the global setting or not. | ||
| 168 | * | ||
| 169 | * @returns The global state | ||
| 170 | */ | ||
| 171 | [[nodiscard]] bool UsingGlobal() const { | ||
| 47 | return use_global; | 172 | return use_global; |
| 48 | } | 173 | } |
| 49 | Type GetValue(bool need_global = false) const { | 174 | |
| 175 | /** | ||
| 176 | * Returns either the global or custom setting depending on the values of this setting's global | ||
| 177 | * state or if the global value was specifically requested. | ||
| 178 | * | ||
| 179 | * @param need_global Request global value regardless of setting's state; defaults to false | ||
| 180 | * | ||
| 181 | * @returns The required value of the setting | ||
| 182 | */ | ||
| 183 | [[nodiscard]] const Type& GetValue(bool need_global = false) const { | ||
| 50 | if (use_global || need_global) { | 184 | if (use_global || need_global) { |
| 51 | return global; | 185 | return this->global; |
| 52 | } | 186 | } |
| 53 | return local; | 187 | return custom; |
| 54 | } | 188 | } |
| 189 | |||
| 190 | /** | ||
| 191 | * Sets the current setting value depending on the global state. | ||
| 192 | * | ||
| 193 | * @param value The new value | ||
| 194 | */ | ||
| 55 | void SetValue(const Type& value) { | 195 | void SetValue(const Type& value) { |
| 196 | Type temp{value}; | ||
| 56 | if (use_global) { | 197 | if (use_global) { |
| 57 | global = value; | 198 | std::swap(this->global, temp); |
| 58 | } else { | 199 | } else { |
| 59 | local = value; | 200 | std::swap(custom, temp); |
| 201 | } | ||
| 202 | } | ||
| 203 | |||
| 204 | /** | ||
| 205 | * Assigns the current setting value depending on the global state. | ||
| 206 | * | ||
| 207 | * @param value The new value | ||
| 208 | * | ||
| 209 | * @returns A reference to the current setting value | ||
| 210 | */ | ||
| 211 | const Type& operator=(const Type& value) { | ||
| 212 | Type temp{value}; | ||
| 213 | if (use_global) { | ||
| 214 | std::swap(this->global, temp); | ||
| 215 | return this->global; | ||
| 216 | } | ||
| 217 | std::swap(custom, temp); | ||
| 218 | return custom; | ||
| 219 | } | ||
| 220 | |||
| 221 | /** | ||
| 222 | * Returns the current setting value depending on the global state. | ||
| 223 | * | ||
| 224 | * @returns A reference to the current setting value | ||
| 225 | */ | ||
| 226 | explicit operator const Type&() const { | ||
| 227 | if (use_global) { | ||
| 228 | return this->global; | ||
| 60 | } | 229 | } |
| 230 | return custom; | ||
| 61 | } | 231 | } |
| 62 | 232 | ||
| 63 | private: | 233 | private: |
| 64 | bool use_global = true; | 234 | bool use_global{true}; ///< The setting's global state |
| 65 | Type global{}; | 235 | Type custom{}; ///< The custom value of the setting |
| 66 | Type local{}; | ||
| 67 | }; | 236 | }; |
| 68 | 237 | ||
| 69 | /** | 238 | /** |
| 70 | * The InputSetting class allows for getting a reference to either the global or local members. | 239 | * The InputSetting class allows for getting a reference to either the global or custom members. |
| 71 | * This is required as we cannot easily modify the values of user-defined types within containers | 240 | * This is required as we cannot easily modify the values of user-defined types within containers |
| 72 | * using the SetValue() member function found in the Setting class. The primary purpose of this | 241 | * using the SetValue() member function found in the Setting class. The primary purpose of this |
| 73 | * class is to store an array of 10 PlayerInput structs for both the global and local (per-game) | 242 | * class is to store an array of 10 PlayerInput structs for both the global and custom setting and |
| 74 | * setting and allows for easily accessing and modifying both settings. | 243 | * allows for easily accessing and modifying both settings. |
| 75 | */ | 244 | */ |
| 76 | template <typename Type> | 245 | template <typename Type> |
| 77 | class InputSetting final { | 246 | class InputSetting final { |
| 78 | public: | 247 | public: |
| 79 | InputSetting() = default; | 248 | InputSetting() = default; |
| 80 | explicit InputSetting(Type val) : global{val} {} | 249 | explicit InputSetting(Type val) : BasicSetting<Type>(val) {} |
| 81 | ~InputSetting() = default; | 250 | ~InputSetting() = default; |
| 82 | void SetGlobal(bool to_global) { | 251 | void SetGlobal(bool to_global) { |
| 83 | use_global = to_global; | 252 | use_global = to_global; |
| 84 | } | 253 | } |
| 85 | bool UsingGlobal() const { | 254 | [[nodiscard]] bool UsingGlobal() const { |
| 86 | return use_global; | 255 | return use_global; |
| 87 | } | 256 | } |
| 88 | Type& GetValue(bool need_global = false) { | 257 | [[nodiscard]] Type& GetValue(bool need_global = false) { |
| 89 | if (use_global || need_global) { | 258 | if (use_global || need_global) { |
| 90 | return global; | 259 | return global; |
| 91 | } | 260 | } |
| 92 | return local; | 261 | return custom; |
| 93 | } | 262 | } |
| 94 | 263 | ||
| 95 | private: | 264 | private: |
| 96 | bool use_global = true; | 265 | bool use_global{true}; ///< The setting's global state |
| 97 | Type global{}; | 266 | Type global{}; ///< The setting |
| 98 | Type local{}; | 267 | Type custom{}; ///< The custom setting value |
| 99 | }; | 268 | }; |
| 100 | 269 | ||
| 101 | struct TouchFromButtonMap { | 270 | struct TouchFromButtonMap { |
| @@ -105,144 +274,158 @@ struct TouchFromButtonMap { | |||
| 105 | 274 | ||
| 106 | struct Values { | 275 | struct Values { |
| 107 | // Audio | 276 | // Audio |
| 108 | std::string audio_device_id; | 277 | BasicSetting<std::string> audio_device_id{"auto", "output_device"}; |
| 109 | std::string sink_id; | 278 | BasicSetting<std::string> sink_id{"auto", "output_engine"}; |
| 110 | bool audio_muted; | 279 | BasicSetting<bool> audio_muted{false, "audio_muted"}; |
| 111 | Setting<bool> enable_audio_stretching; | 280 | Setting<bool> enable_audio_stretching{true, "enable_audio_stretching"}; |
| 112 | Setting<float> volume; | 281 | Setting<float> volume{1.0f, "volume"}; |
| 113 | 282 | ||
| 114 | // Core | 283 | // Core |
| 115 | Setting<bool> use_multi_core; | 284 | Setting<bool> use_multi_core{true, "use_multi_core"}; |
| 116 | 285 | ||
| 117 | // Cpu | 286 | // Cpu |
| 118 | Setting<CPUAccuracy> cpu_accuracy; | 287 | Setting<CPUAccuracy> cpu_accuracy{CPUAccuracy::Auto, "cpu_accuracy"}; |
| 119 | 288 | // TODO: remove cpu_accuracy_first_time, migration setting added 8 July 2021 | |
| 120 | bool cpuopt_page_tables; | 289 | BasicSetting<bool> cpu_accuracy_first_time{true, "cpu_accuracy_first_time"}; |
| 121 | bool cpuopt_block_linking; | 290 | BasicSetting<bool> cpu_debug_mode{false, "cpu_debug_mode"}; |
| 122 | bool cpuopt_return_stack_buffer; | 291 | |
| 123 | bool cpuopt_fast_dispatcher; | 292 | BasicSetting<bool> cpuopt_page_tables{true, "cpuopt_page_tables"}; |
| 124 | bool cpuopt_context_elimination; | 293 | BasicSetting<bool> cpuopt_block_linking{true, "cpuopt_block_linking"}; |
| 125 | bool cpuopt_const_prop; | 294 | BasicSetting<bool> cpuopt_return_stack_buffer{true, "cpuopt_return_stack_buffer"}; |
| 126 | bool cpuopt_misc_ir; | 295 | BasicSetting<bool> cpuopt_fast_dispatcher{true, "cpuopt_fast_dispatcher"}; |
| 127 | bool cpuopt_reduce_misalign_checks; | 296 | BasicSetting<bool> cpuopt_context_elimination{true, "cpuopt_context_elimination"}; |
| 128 | bool cpuopt_fastmem; | 297 | BasicSetting<bool> cpuopt_const_prop{true, "cpuopt_const_prop"}; |
| 129 | 298 | BasicSetting<bool> cpuopt_misc_ir{true, "cpuopt_misc_ir"}; | |
| 130 | Setting<bool> cpuopt_unsafe_unfuse_fma; | 299 | BasicSetting<bool> cpuopt_reduce_misalign_checks{true, "cpuopt_reduce_misalign_checks"}; |
| 131 | Setting<bool> cpuopt_unsafe_reduce_fp_error; | 300 | BasicSetting<bool> cpuopt_fastmem{true, "cpuopt_fastmem"}; |
| 132 | Setting<bool> cpuopt_unsafe_ignore_standard_fpcr; | 301 | |
| 133 | Setting<bool> cpuopt_unsafe_inaccurate_nan; | 302 | Setting<bool> cpuopt_unsafe_unfuse_fma{true, "cpuopt_unsafe_unfuse_fma"}; |
| 134 | Setting<bool> cpuopt_unsafe_fastmem_check; | 303 | Setting<bool> cpuopt_unsafe_reduce_fp_error{true, "cpuopt_unsafe_reduce_fp_error"}; |
| 304 | Setting<bool> cpuopt_unsafe_ignore_standard_fpcr{true, "cpuopt_unsafe_ignore_standard_fpcr"}; | ||
| 305 | Setting<bool> cpuopt_unsafe_inaccurate_nan{true, "cpuopt_unsafe_inaccurate_nan"}; | ||
| 306 | Setting<bool> cpuopt_unsafe_fastmem_check{true, "cpuopt_unsafe_fastmem_check"}; | ||
| 135 | 307 | ||
| 136 | // Renderer | 308 | // Renderer |
| 137 | Setting<RendererBackend> renderer_backend; | 309 | Setting<RendererBackend> renderer_backend{RendererBackend::OpenGL, "backend"}; |
| 138 | bool renderer_debug; | 310 | BasicSetting<bool> renderer_debug{false, "debug"}; |
| 139 | Setting<int> vulkan_device; | 311 | Setting<int> vulkan_device{0, "vulkan_device"}; |
| 140 | 312 | ||
| 141 | Setting<u16> resolution_factor{1}; | 313 | Setting<u16> resolution_factor{1, "resolution_factor"}; |
| 142 | Setting<int> fullscreen_mode; | 314 | // *nix platforms may have issues with the borderless windowed fullscreen mode. |
| 143 | Setting<int> aspect_ratio; | 315 | // Default to exclusive fullscreen on these platforms for now. |
| 144 | Setting<int> max_anisotropy; | 316 | Setting<int> fullscreen_mode{ |
| 145 | Setting<bool> use_frame_limit; | 317 | #ifdef _WIN32 |
| 146 | Setting<u16> frame_limit; | 318 | 0, |
| 147 | Setting<bool> use_disk_shader_cache; | 319 | #else |
| 148 | Setting<GPUAccuracy> gpu_accuracy; | 320 | 1, |
| 149 | Setting<bool> use_asynchronous_gpu_emulation; | 321 | #endif |
| 150 | Setting<bool> use_nvdec_emulation; | 322 | "fullscreen_mode"}; |
| 151 | Setting<bool> accelerate_astc; | 323 | Setting<int> aspect_ratio{0, "aspect_ratio"}; |
| 152 | Setting<bool> use_vsync; | 324 | Setting<int> max_anisotropy{0, "max_anisotropy"}; |
| 153 | Setting<bool> disable_fps_limit; | 325 | Setting<bool> use_frame_limit{true, "use_frame_limit"}; |
| 154 | Setting<bool> use_assembly_shaders; | 326 | Setting<u16> frame_limit{100, "frame_limit"}; |
| 155 | Setting<bool> use_asynchronous_shaders; | 327 | Setting<bool> use_disk_shader_cache{true, "use_disk_shader_cache"}; |
| 156 | Setting<bool> use_fast_gpu_time; | 328 | Setting<GPUAccuracy> gpu_accuracy{GPUAccuracy::High, "gpu_accuracy"}; |
| 157 | Setting<bool> use_caches_gc; | 329 | Setting<bool> use_asynchronous_gpu_emulation{true, "use_asynchronous_gpu_emulation"}; |
| 158 | 330 | Setting<bool> use_nvdec_emulation{true, "use_nvdec_emulation"}; | |
| 159 | Setting<float> bg_red; | 331 | Setting<bool> accelerate_astc{true, "accelerate_astc"}; |
| 160 | Setting<float> bg_green; | 332 | Setting<bool> use_vsync{true, "use_vsync"}; |
| 161 | Setting<float> bg_blue; | 333 | BasicSetting<bool> disable_fps_limit{false, "disable_fps_limit"}; |
| 334 | Setting<bool> use_assembly_shaders{false, "use_assembly_shaders"}; | ||
| 335 | Setting<bool> use_asynchronous_shaders{false, "use_asynchronous_shaders"}; | ||
| 336 | Setting<bool> use_fast_gpu_time{true, "use_fast_gpu_time"}; | ||
| 337 | Setting<bool> use_caches_gc{false, "use_caches_gc"}; | ||
| 338 | |||
| 339 | Setting<float> bg_red{0.0f, "bg_red"}; | ||
| 340 | Setting<float> bg_green{0.0f, "bg_green"}; | ||
| 341 | Setting<float> bg_blue{0.0f, "bg_blue"}; | ||
| 162 | 342 | ||
| 163 | // System | 343 | // System |
| 164 | Setting<std::optional<u32>> rng_seed; | 344 | Setting<std::optional<u32>> rng_seed{std::optional<u32>(), "rng_seed"}; |
| 165 | // Measured in seconds since epoch | 345 | // Measured in seconds since epoch |
| 166 | std::optional<std::chrono::seconds> custom_rtc; | 346 | std::optional<std::chrono::seconds> custom_rtc; |
| 167 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` | 347 | // Set on game boot, reset on stop. Seconds difference between current time and `custom_rtc` |
| 168 | std::chrono::seconds custom_rtc_differential; | 348 | std::chrono::seconds custom_rtc_differential; |
| 169 | 349 | ||
| 170 | s32 current_user; | 350 | BasicSetting<s32> current_user{0, "current_user"}; |
| 171 | Setting<s32> language_index; | 351 | Setting<s32> language_index{1, "language_index"}; |
| 172 | Setting<s32> region_index; | 352 | Setting<s32> region_index{1, "region_index"}; |
| 173 | Setting<s32> time_zone_index; | 353 | Setting<s32> time_zone_index{0, "time_zone_index"}; |
| 174 | Setting<s32> sound_index; | 354 | Setting<s32> sound_index{1, "sound_index"}; |
| 175 | 355 | ||
| 176 | // Controls | 356 | // Controls |
| 177 | InputSetting<std::array<PlayerInput, 10>> players; | 357 | InputSetting<std::array<PlayerInput, 10>> players; |
| 178 | 358 | ||
| 179 | Setting<bool> use_docked_mode; | 359 | Setting<bool> use_docked_mode{true, "use_docked_mode"}; |
| 180 | 360 | ||
| 181 | Setting<bool> vibration_enabled; | 361 | Setting<bool> vibration_enabled{true, "vibration_enabled"}; |
| 182 | Setting<bool> enable_accurate_vibrations; | 362 | Setting<bool> enable_accurate_vibrations{false, "enable_accurate_vibrations"}; |
| 183 | 363 | ||
| 184 | Setting<bool> motion_enabled; | 364 | Setting<bool> motion_enabled{true, "motion_enabled"}; |
| 185 | std::string motion_device; | 365 | BasicSetting<std::string> motion_device{"engine:motion_emu,update_period:100,sensitivity:0.01", |
| 186 | std::string udp_input_servers; | 366 | "motion_device"}; |
| 367 | BasicSetting<std::string> udp_input_servers{InputCommon::CemuhookUDP::DEFAULT_SRV, | ||
| 368 | "udp_input_servers"}; | ||
| 187 | 369 | ||
| 188 | bool mouse_panning; | 370 | BasicSetting<bool> mouse_panning{false, "mouse_panning"}; |
| 189 | float mouse_panning_sensitivity; | 371 | BasicSetting<float> mouse_panning_sensitivity{1.0f, "mouse_panning_sensitivity"}; |
| 190 | bool mouse_enabled; | 372 | BasicSetting<bool> mouse_enabled{false, "mouse_enabled"}; |
| 191 | std::string mouse_device; | 373 | std::string mouse_device; |
| 192 | MouseButtonsRaw mouse_buttons; | 374 | MouseButtonsRaw mouse_buttons; |
| 193 | 375 | ||
| 194 | bool emulate_analog_keyboard; | 376 | BasicSetting<bool> emulate_analog_keyboard{false, "emulate_analog_keyboard"}; |
| 195 | bool keyboard_enabled; | 377 | BasicSetting<bool> keyboard_enabled{false, "keyboard_enabled"}; |
| 196 | KeyboardKeysRaw keyboard_keys; | 378 | KeyboardKeysRaw keyboard_keys; |
| 197 | KeyboardModsRaw keyboard_mods; | 379 | KeyboardModsRaw keyboard_mods; |
| 198 | 380 | ||
| 199 | bool debug_pad_enabled; | 381 | BasicSetting<bool> debug_pad_enabled{false, "debug_pad_enabled"}; |
| 200 | ButtonsRaw debug_pad_buttons; | 382 | ButtonsRaw debug_pad_buttons; |
| 201 | AnalogsRaw debug_pad_analogs; | 383 | AnalogsRaw debug_pad_analogs; |
| 202 | 384 | ||
| 203 | TouchscreenInput touchscreen; | 385 | TouchscreenInput touchscreen; |
| 204 | 386 | ||
| 205 | bool use_touch_from_button; | 387 | BasicSetting<bool> use_touch_from_button{false, "use_touch_from_button"}; |
| 206 | std::string touch_device; | 388 | BasicSetting<std::string> touch_device{"min_x:100,min_y:50,max_x:1800,max_y:850", |
| 207 | int touch_from_button_map_index; | 389 | "touch_device"}; |
| 390 | BasicSetting<int> touch_from_button_map_index{0, "touch_from_button_map"}; | ||
| 208 | std::vector<TouchFromButtonMap> touch_from_button_maps; | 391 | std::vector<TouchFromButtonMap> touch_from_button_maps; |
| 209 | 392 | ||
| 210 | std::atomic_bool is_device_reload_pending{true}; | 393 | std::atomic_bool is_device_reload_pending{true}; |
| 211 | 394 | ||
| 212 | // Data Storage | 395 | // Data Storage |
| 213 | bool use_virtual_sd; | 396 | BasicSetting<bool> use_virtual_sd{true, "use_virtual_sd"}; |
| 214 | bool gamecard_inserted; | 397 | BasicSetting<bool> gamecard_inserted{false, "gamecard_inserted"}; |
| 215 | bool gamecard_current_game; | 398 | BasicSetting<bool> gamecard_current_game{false, "gamecard_current_game"}; |
| 216 | std::string gamecard_path; | 399 | BasicSetting<std::string> gamecard_path{std::string(), "gamecard_path"}; |
| 217 | 400 | ||
| 218 | // Debugging | 401 | // Debugging |
| 219 | bool record_frame_times; | 402 | bool record_frame_times; |
| 220 | bool use_gdbstub; | 403 | BasicSetting<bool> use_gdbstub{false, "use_gdbstub"}; |
| 221 | u16 gdbstub_port; | 404 | BasicSetting<u16> gdbstub_port{0, "gdbstub_port"}; |
| 222 | std::string program_args; | 405 | BasicSetting<std::string> program_args{std::string(), "program_args"}; |
| 223 | bool dump_exefs; | 406 | BasicSetting<bool> dump_exefs{false, "dump_exefs"}; |
| 224 | bool dump_nso; | 407 | BasicSetting<bool> dump_nso{false, "dump_nso"}; |
| 225 | bool enable_fs_access_log; | 408 | BasicSetting<bool> enable_fs_access_log{false, "enable_fs_access_log"}; |
| 226 | bool reporting_services; | 409 | BasicSetting<bool> reporting_services{false, "reporting_services"}; |
| 227 | bool quest_flag; | 410 | BasicSetting<bool> quest_flag{false, "quest_flag"}; |
| 228 | bool disable_macro_jit; | 411 | BasicSetting<bool> disable_macro_jit{false, "disable_macro_jit"}; |
| 229 | bool extended_logging; | 412 | BasicSetting<bool> extended_logging{false, "extended_logging"}; |
| 230 | bool use_debug_asserts; | 413 | BasicSetting<bool> use_debug_asserts{false, "use_debug_asserts"}; |
| 231 | bool use_auto_stub; | 414 | BasicSetting<bool> use_auto_stub{false, "use_auto_stub"}; |
| 232 | 415 | ||
| 233 | // Miscellaneous | 416 | // Miscellaneous |
| 234 | std::string log_filter; | 417 | BasicSetting<std::string> log_filter{"*:Info", "log_filter"}; |
| 235 | bool use_dev_keys; | 418 | BasicSetting<bool> use_dev_keys{false, "use_dev_keys"}; |
| 236 | 419 | ||
| 237 | // Services | 420 | // Services |
| 238 | std::string bcat_backend; | 421 | BasicSetting<std::string> bcat_backend{"none", "bcat_backend"}; |
| 239 | bool bcat_boxcat_local; | 422 | BasicSetting<bool> bcat_boxcat_local{false, "bcat_boxcat_local"}; |
| 240 | 423 | ||
| 241 | // WebService | 424 | // WebService |
| 242 | bool enable_telemetry; | 425 | BasicSetting<bool> enable_telemetry{true, "enable_telemetry"}; |
| 243 | std::string web_api_url; | 426 | BasicSetting<std::string> web_api_url{"https://api.yuzu-emu.org", "web_api_url"}; |
| 244 | std::string yuzu_username; | 427 | BasicSetting<std::string> yuzu_username{std::string(), "yuzu_username"}; |
| 245 | std::string yuzu_token; | 428 | BasicSetting<std::string> yuzu_token{std::string(), "yuzu_token"}; |
| 246 | 429 | ||
| 247 | // Add-Ons | 430 | // Add-Ons |
| 248 | std::map<u64, std::vector<std::string>> disabled_addons; | 431 | std::map<u64, std::vector<std::string>> disabled_addons; |
diff --git a/src/common/thread_worker.cpp b/src/common/thread_worker.cpp deleted file mode 100644 index 8f9bf447a..000000000 --- a/src/common/thread_worker.cpp +++ /dev/null | |||
| @@ -1,58 +0,0 @@ | |||
| 1 | // Copyright 2020 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "common/thread.h" | ||
| 6 | #include "common/thread_worker.h" | ||
| 7 | |||
| 8 | namespace Common { | ||
| 9 | |||
| 10 | ThreadWorker::ThreadWorker(std::size_t num_workers, const std::string& name) { | ||
| 11 | for (std::size_t i = 0; i < num_workers; ++i) | ||
| 12 | threads.emplace_back([this, thread_name{std::string{name}}] { | ||
| 13 | Common::SetCurrentThreadName(thread_name.c_str()); | ||
| 14 | |||
| 15 | // Wait for first request | ||
| 16 | { | ||
| 17 | std::unique_lock lock{queue_mutex}; | ||
| 18 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | ||
| 19 | } | ||
| 20 | |||
| 21 | while (true) { | ||
| 22 | std::function<void()> task; | ||
| 23 | |||
| 24 | { | ||
| 25 | std::unique_lock lock{queue_mutex}; | ||
| 26 | condition.wait(lock, [this] { return stop || !requests.empty(); }); | ||
| 27 | if (stop || requests.empty()) { | ||
| 28 | return; | ||
| 29 | } | ||
| 30 | task = std::move(requests.front()); | ||
| 31 | requests.pop(); | ||
| 32 | } | ||
| 33 | |||
| 34 | task(); | ||
| 35 | } | ||
| 36 | }); | ||
| 37 | } | ||
| 38 | |||
| 39 | ThreadWorker::~ThreadWorker() { | ||
| 40 | { | ||
| 41 | std::unique_lock lock{queue_mutex}; | ||
| 42 | stop = true; | ||
| 43 | } | ||
| 44 | condition.notify_all(); | ||
| 45 | for (std::thread& thread : threads) { | ||
| 46 | thread.join(); | ||
| 47 | } | ||
| 48 | } | ||
| 49 | |||
| 50 | void ThreadWorker::QueueWork(std::function<void()>&& work) { | ||
| 51 | { | ||
| 52 | std::unique_lock lock{queue_mutex}; | ||
| 53 | requests.emplace(work); | ||
| 54 | } | ||
| 55 | condition.notify_one(); | ||
| 56 | } | ||
| 57 | |||
| 58 | } // namespace Common | ||
diff --git a/src/common/thread_worker.h b/src/common/thread_worker.h index f1859971f..8272985ff 100644 --- a/src/common/thread_worker.h +++ b/src/common/thread_worker.h | |||
| @@ -7,24 +7,110 @@ | |||
| 7 | #include <atomic> | 7 | #include <atomic> |
| 8 | #include <functional> | 8 | #include <functional> |
| 9 | #include <mutex> | 9 | #include <mutex> |
| 10 | #include <stop_token> | ||
| 10 | #include <string> | 11 | #include <string> |
| 12 | #include <thread> | ||
| 13 | #include <type_traits> | ||
| 11 | #include <vector> | 14 | #include <vector> |
| 12 | #include <queue> | 15 | #include <queue> |
| 13 | 16 | ||
| 17 | #include "common/thread.h" | ||
| 18 | #include "common/unique_function.h" | ||
| 19 | |||
| 14 | namespace Common { | 20 | namespace Common { |
| 15 | 21 | ||
| 16 | class ThreadWorker final { | 22 | template <class StateType = void> |
| 23 | class StatefulThreadWorker { | ||
| 24 | static constexpr bool with_state = !std::is_same_v<StateType, void>; | ||
| 25 | |||
| 26 | struct DummyCallable { | ||
| 27 | int operator()() const noexcept { | ||
| 28 | return 0; | ||
| 29 | } | ||
| 30 | }; | ||
| 31 | |||
| 32 | using Task = | ||
| 33 | std::conditional_t<with_state, UniqueFunction<void, StateType*>, UniqueFunction<void>>; | ||
| 34 | using StateMaker = std::conditional_t<with_state, std::function<StateType()>, DummyCallable>; | ||
| 35 | |||
| 17 | public: | 36 | public: |
| 18 | explicit ThreadWorker(std::size_t num_workers, const std::string& name); | 37 | explicit StatefulThreadWorker(size_t num_workers, std::string name, StateMaker func = {}) |
| 19 | ~ThreadWorker(); | 38 | : workers_queued{num_workers}, thread_name{std::move(name)} { |
| 20 | void QueueWork(std::function<void()>&& work); | 39 | const auto lambda = [this, func](std::stop_token stop_token) { |
| 40 | Common::SetCurrentThreadName(thread_name.c_str()); | ||
| 41 | { | ||
| 42 | std::conditional_t<with_state, StateType, int> state{func()}; | ||
| 43 | while (!stop_token.stop_requested()) { | ||
| 44 | Task task; | ||
| 45 | { | ||
| 46 | std::unique_lock lock{queue_mutex}; | ||
| 47 | if (requests.empty()) { | ||
| 48 | wait_condition.notify_all(); | ||
| 49 | } | ||
| 50 | condition.wait(lock, stop_token, [this] { return !requests.empty(); }); | ||
| 51 | if (stop_token.stop_requested()) { | ||
| 52 | break; | ||
| 53 | } | ||
| 54 | task = std::move(requests.front()); | ||
| 55 | requests.pop(); | ||
| 56 | } | ||
| 57 | if constexpr (with_state) { | ||
| 58 | task(&state); | ||
| 59 | } else { | ||
| 60 | task(); | ||
| 61 | } | ||
| 62 | ++work_done; | ||
| 63 | } | ||
| 64 | } | ||
| 65 | ++workers_stopped; | ||
| 66 | wait_condition.notify_all(); | ||
| 67 | }; | ||
| 68 | threads.reserve(num_workers); | ||
| 69 | for (size_t i = 0; i < num_workers; ++i) { | ||
| 70 | threads.emplace_back(lambda); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | |||
| 74 | StatefulThreadWorker& operator=(const StatefulThreadWorker&) = delete; | ||
| 75 | StatefulThreadWorker(const StatefulThreadWorker&) = delete; | ||
| 76 | |||
| 77 | StatefulThreadWorker& operator=(StatefulThreadWorker&&) = delete; | ||
| 78 | StatefulThreadWorker(StatefulThreadWorker&&) = delete; | ||
| 79 | |||
| 80 | void QueueWork(Task work) { | ||
| 81 | { | ||
| 82 | std::unique_lock lock{queue_mutex}; | ||
| 83 | requests.emplace(std::move(work)); | ||
| 84 | ++work_scheduled; | ||
| 85 | } | ||
| 86 | condition.notify_one(); | ||
| 87 | } | ||
| 88 | |||
| 89 | void WaitForRequests(std::stop_token stop_token = {}) { | ||
| 90 | std::stop_callback callback(stop_token, [this] { | ||
| 91 | for (auto& thread : threads) { | ||
| 92 | thread.request_stop(); | ||
| 93 | } | ||
| 94 | }); | ||
| 95 | std::unique_lock lock{queue_mutex}; | ||
| 96 | wait_condition.wait(lock, [this] { | ||
| 97 | return workers_stopped >= workers_queued || work_done >= work_scheduled; | ||
| 98 | }); | ||
| 99 | } | ||
| 21 | 100 | ||
| 22 | private: | 101 | private: |
| 23 | std::vector<std::thread> threads; | 102 | std::queue<Task> requests; |
| 24 | std::queue<std::function<void()>> requests; | ||
| 25 | std::mutex queue_mutex; | 103 | std::mutex queue_mutex; |
| 26 | std::condition_variable condition; | 104 | std::condition_variable_any condition; |
| 27 | std::atomic_bool stop{}; | 105 | std::condition_variable wait_condition; |
| 106 | std::atomic<size_t> work_scheduled{}; | ||
| 107 | std::atomic<size_t> work_done{}; | ||
| 108 | std::atomic<size_t> workers_stopped{}; | ||
| 109 | std::atomic<size_t> workers_queued{}; | ||
| 110 | std::string thread_name; | ||
| 111 | std::vector<std::jthread> threads; | ||
| 28 | }; | 112 | }; |
| 29 | 113 | ||
| 114 | using ThreadWorker = StatefulThreadWorker<>; | ||
| 115 | |||
| 30 | } // namespace Common | 116 | } // namespace Common |
diff --git a/src/common/unique_function.h b/src/common/unique_function.h new file mode 100644 index 000000000..ca0559071 --- /dev/null +++ b/src/common/unique_function.h | |||
| @@ -0,0 +1,62 @@ | |||
| 1 | // Copyright 2021 yuzu emulator team | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #pragma once | ||
| 6 | |||
| 7 | #include <memory> | ||
| 8 | #include <utility> | ||
| 9 | |||
| 10 | namespace Common { | ||
| 11 | |||
| 12 | /// General purpose function wrapper similar to std::function. | ||
| 13 | /// Unlike std::function, the captured values don't have to be copyable. | ||
| 14 | /// This class can be moved but not copied. | ||
| 15 | template <typename ResultType, typename... Args> | ||
| 16 | class UniqueFunction { | ||
| 17 | class CallableBase { | ||
| 18 | public: | ||
| 19 | virtual ~CallableBase() = default; | ||
| 20 | virtual ResultType operator()(Args&&...) = 0; | ||
| 21 | }; | ||
| 22 | |||
| 23 | template <typename Functor> | ||
| 24 | class Callable final : public CallableBase { | ||
| 25 | public: | ||
| 26 | Callable(Functor&& functor_) : functor{std::move(functor_)} {} | ||
| 27 | ~Callable() override = default; | ||
| 28 | |||
| 29 | ResultType operator()(Args&&... args) override { | ||
| 30 | return functor(std::forward<Args>(args)...); | ||
| 31 | } | ||
| 32 | |||
| 33 | private: | ||
| 34 | Functor functor; | ||
| 35 | }; | ||
| 36 | |||
| 37 | public: | ||
| 38 | UniqueFunction() = default; | ||
| 39 | |||
| 40 | template <typename Functor> | ||
| 41 | UniqueFunction(Functor&& functor) | ||
| 42 | : callable{std::make_unique<Callable<Functor>>(std::move(functor))} {} | ||
| 43 | |||
| 44 | UniqueFunction& operator=(UniqueFunction&& rhs) noexcept = default; | ||
| 45 | UniqueFunction(UniqueFunction&& rhs) noexcept = default; | ||
| 46 | |||
| 47 | UniqueFunction& operator=(const UniqueFunction&) = delete; | ||
| 48 | UniqueFunction(const UniqueFunction&) = delete; | ||
| 49 | |||
| 50 | ResultType operator()(Args&&... args) const { | ||
| 51 | return (*callable)(std::forward<Args>(args)...); | ||
| 52 | } | ||
| 53 | |||
| 54 | explicit operator bool() const noexcept { | ||
| 55 | return static_cast<bool>(callable); | ||
| 56 | } | ||
| 57 | |||
| 58 | private: | ||
| 59 | std::unique_ptr<CallableBase> callable; | ||
| 60 | }; | ||
| 61 | |||
| 62 | } // namespace Common | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_32.cpp b/src/core/arm/dynarmic/arm_dynarmic_32.cpp index 77a44f862..b0d89c539 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_32.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_32.cpp | |||
| @@ -150,7 +150,7 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 150 | config.far_code_offset = 400_MiB; | 150 | config.far_code_offset = 400_MiB; |
| 151 | 151 | ||
| 152 | // Safe optimizations | 152 | // Safe optimizations |
| 153 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { | 153 | if (Settings::values.cpu_debug_mode) { |
| 154 | if (!Settings::values.cpuopt_page_tables) { | 154 | if (!Settings::values.cpuopt_page_tables) { |
| 155 | config.page_table = nullptr; | 155 | config.page_table = nullptr; |
| 156 | } | 156 | } |
| @@ -183,20 +183,28 @@ std::shared_ptr<Dynarmic::A32::Jit> ARM_Dynarmic_32::MakeJit(Common::PageTable* | |||
| 183 | // Unsafe optimizations | 183 | // Unsafe optimizations |
| 184 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 184 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 185 | config.unsafe_optimizations = true; | 185 | config.unsafe_optimizations = true; |
| 186 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { | 186 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { |
| 187 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 187 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 188 | } | 188 | } |
| 189 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { | 189 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { |
| 190 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 190 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 191 | } | 191 | } |
| 192 | if (Settings::values.cpuopt_unsafe_ignore_standard_fpcr.GetValue()) { | 192 | if (Settings::values.cpuopt_unsafe_ignore_standard_fpcr) { |
| 193 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; | 193 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; |
| 194 | } | 194 | } |
| 195 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { | 195 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { |
| 196 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 196 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 197 | } | 197 | } |
| 198 | } | 198 | } |
| 199 | 199 | ||
| 200 | // Curated optimizations | ||
| 201 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { | ||
| 202 | config.unsafe_optimizations = true; | ||
| 203 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | ||
| 204 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_IgnoreStandardFPCRValue; | ||
| 205 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | ||
| 206 | } | ||
| 207 | |||
| 200 | return std::make_unique<Dynarmic::A32::Jit>(config); | 208 | return std::make_unique<Dynarmic::A32::Jit>(config); |
| 201 | } | 209 | } |
| 202 | 210 | ||
diff --git a/src/core/arm/dynarmic/arm_dynarmic_64.cpp b/src/core/arm/dynarmic/arm_dynarmic_64.cpp index 75332e348..bf27ffe71 100644 --- a/src/core/arm/dynarmic/arm_dynarmic_64.cpp +++ b/src/core/arm/dynarmic/arm_dynarmic_64.cpp | |||
| @@ -190,7 +190,7 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 190 | config.far_code_offset = 400_MiB; | 190 | config.far_code_offset = 400_MiB; |
| 191 | 191 | ||
| 192 | // Safe optimizations | 192 | // Safe optimizations |
| 193 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::DebugMode) { | 193 | if (Settings::values.cpu_debug_mode) { |
| 194 | if (!Settings::values.cpuopt_page_tables) { | 194 | if (!Settings::values.cpuopt_page_tables) { |
| 195 | config.page_table = nullptr; | 195 | config.page_table = nullptr; |
| 196 | } | 196 | } |
| @@ -223,20 +223,28 @@ std::shared_ptr<Dynarmic::A64::Jit> ARM_Dynarmic_64::MakeJit(Common::PageTable* | |||
| 223 | // Unsafe optimizations | 223 | // Unsafe optimizations |
| 224 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { | 224 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Unsafe) { |
| 225 | config.unsafe_optimizations = true; | 225 | config.unsafe_optimizations = true; |
| 226 | if (Settings::values.cpuopt_unsafe_unfuse_fma.GetValue()) { | 226 | if (Settings::values.cpuopt_unsafe_unfuse_fma) { |
| 227 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | 227 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; |
| 228 | } | 228 | } |
| 229 | if (Settings::values.cpuopt_unsafe_reduce_fp_error.GetValue()) { | 229 | if (Settings::values.cpuopt_unsafe_reduce_fp_error) { |
| 230 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; | 230 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_ReducedErrorFP; |
| 231 | } | 231 | } |
| 232 | if (Settings::values.cpuopt_unsafe_inaccurate_nan.GetValue()) { | 232 | if (Settings::values.cpuopt_unsafe_inaccurate_nan) { |
| 233 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | 233 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; |
| 234 | } | 234 | } |
| 235 | if (Settings::values.cpuopt_unsafe_fastmem_check.GetValue()) { | 235 | if (Settings::values.cpuopt_unsafe_fastmem_check) { |
| 236 | config.fastmem_address_space_bits = 64; | 236 | config.fastmem_address_space_bits = 64; |
| 237 | } | 237 | } |
| 238 | } | 238 | } |
| 239 | 239 | ||
| 240 | // Curated optimizations | ||
| 241 | if (Settings::values.cpu_accuracy.GetValue() == Settings::CPUAccuracy::Auto) { | ||
| 242 | config.unsafe_optimizations = true; | ||
| 243 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_UnfuseFMA; | ||
| 244 | config.optimizations |= Dynarmic::OptimizationFlag::Unsafe_InaccurateNaN; | ||
| 245 | config.fastmem_address_space_bits = 64; | ||
| 246 | } | ||
| 247 | |||
| 240 | return std::make_shared<Dynarmic::A64::Jit>(config); | 248 | return std::make_shared<Dynarmic::A64::Jit>(config); |
| 241 | } | 249 | } |
| 242 | 250 | ||
diff --git a/src/core/core.cpp b/src/core/core.cpp index e6f1aa0e7..891f1cb49 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -263,9 +263,9 @@ struct System::Impl { | |||
| 263 | if (Settings::values.gamecard_inserted) { | 263 | if (Settings::values.gamecard_inserted) { |
| 264 | if (Settings::values.gamecard_current_game) { | 264 | if (Settings::values.gamecard_current_game) { |
| 265 | fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, filepath)); | 265 | fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, filepath)); |
| 266 | } else if (!Settings::values.gamecard_path.empty()) { | 266 | } else if (!Settings::values.gamecard_path.GetValue().empty()) { |
| 267 | fs_controller.SetGameCard( | 267 | const auto gamecard_path = Settings::values.gamecard_path.GetValue(); |
| 268 | GetGameFileFromPath(virtual_filesystem, Settings::values.gamecard_path)); | 268 | fs_controller.SetGameCard(GetGameFileFromPath(virtual_filesystem, gamecard_path)); |
| 269 | } | 269 | } |
| 270 | } | 270 | } |
| 271 | 271 | ||
diff --git a/src/core/frontend/applets/profile_select.cpp b/src/core/frontend/applets/profile_select.cpp index 8d960d1ca..4c58c310f 100644 --- a/src/core/frontend/applets/profile_select.cpp +++ b/src/core/frontend/applets/profile_select.cpp | |||
| @@ -13,7 +13,7 @@ ProfileSelectApplet::~ProfileSelectApplet() = default; | |||
| 13 | void DefaultProfileSelectApplet::SelectProfile( | 13 | void DefaultProfileSelectApplet::SelectProfile( |
| 14 | std::function<void(std::optional<Common::UUID>)> callback) const { | 14 | std::function<void(std::optional<Common::UUID>)> callback) const { |
| 15 | Service::Account::ProfileManager manager; | 15 | Service::Account::ProfileManager manager; |
| 16 | callback(manager.GetUser(Settings::values.current_user).value_or(Common::UUID{})); | 16 | callback(manager.GetUser(Settings::values.current_user.GetValue()).value_or(Common::UUID{})); |
| 17 | LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); | 17 | LOG_INFO(Service_ACC, "called, selecting current user instead of prompting..."); |
| 18 | } | 18 | } |
| 19 | 19 | ||
diff --git a/src/core/hle/service/acc/profile_manager.cpp b/src/core/hle/service/acc/profile_manager.cpp index f72d5d561..24a1c9157 100644 --- a/src/core/hle/service/acc/profile_manager.cpp +++ b/src/core/hle/service/acc/profile_manager.cpp | |||
| @@ -48,7 +48,8 @@ ProfileManager::ProfileManager() { | |||
| 48 | CreateNewUser(UUID::Generate(), "yuzu"); | 48 | CreateNewUser(UUID::Generate(), "yuzu"); |
| 49 | } | 49 | } |
| 50 | 50 | ||
| 51 | auto current = std::clamp<int>(Settings::values.current_user, 0, MAX_USERS - 1); | 51 | auto current = |
| 52 | std::clamp<int>(static_cast<s32>(Settings::values.current_user), 0, MAX_USERS - 1); | ||
| 52 | 53 | ||
| 53 | // If user index don't exist. Load the first user and change the active user | 54 | // If user index don't exist. Load the first user and change the active user |
| 54 | if (!UserExistsIndex(current)) { | 55 | if (!UserExistsIndex(current)) { |
diff --git a/src/core/hle/service/am/am.cpp b/src/core/hle/service/am/am.cpp index b578153d3..23ebc1138 100644 --- a/src/core/hle/service/am/am.cpp +++ b/src/core/hle/service/am/am.cpp | |||
| @@ -1443,7 +1443,7 @@ void IApplicationFunctions::PopLaunchParameter(Kernel::HLERequestContext& ctx) { | |||
| 1443 | params.is_account_selected = 1; | 1443 | params.is_account_selected = 1; |
| 1444 | 1444 | ||
| 1445 | Account::ProfileManager profile_manager{}; | 1445 | Account::ProfileManager profile_manager{}; |
| 1446 | const auto uuid = profile_manager.GetUser(Settings::values.current_user); | 1446 | const auto uuid = profile_manager.GetUser(static_cast<s32>(Settings::values.current_user)); |
| 1447 | ASSERT(uuid); | 1447 | ASSERT(uuid); |
| 1448 | params.current_user = uuid->uuid; | 1448 | params.current_user = uuid->uuid; |
| 1449 | 1449 | ||
diff --git a/src/core/hle/service/bcat/module.cpp b/src/core/hle/service/bcat/module.cpp index 44e4d0509..f85444da8 100644 --- a/src/core/hle/service/bcat/module.cpp +++ b/src/core/hle/service/bcat/module.cpp | |||
| @@ -579,7 +579,7 @@ void Module::Interface::CreateDeliveryCacheStorageServiceWithApplicationId( | |||
| 579 | std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System& system, | 579 | std::unique_ptr<Backend> CreateBackendFromSettings([[maybe_unused]] Core::System& system, |
| 580 | DirectoryGetter getter) { | 580 | DirectoryGetter getter) { |
| 581 | #ifdef YUZU_ENABLE_BOXCAT | 581 | #ifdef YUZU_ENABLE_BOXCAT |
| 582 | if (Settings::values.bcat_backend == "boxcat") { | 582 | if (Settings::values.bcat_backend.GetValue() == "boxcat") { |
| 583 | return std::make_unique<Boxcat>(system.GetAppletManager(), std::move(getter)); | 583 | return std::make_unique<Boxcat>(system.GetAppletManager(), std::move(getter)); |
| 584 | } | 584 | } |
| 585 | #endif | 585 | #endif |
diff --git a/src/core/hle/service/nifm/nifm.cpp b/src/core/hle/service/nifm/nifm.cpp index f03b2666a..e742db48f 100644 --- a/src/core/hle/service/nifm/nifm.cpp +++ b/src/core/hle/service/nifm/nifm.cpp | |||
| @@ -179,7 +179,7 @@ private: | |||
| 179 | IPC::ResponseBuilder rb{ctx, 3}; | 179 | IPC::ResponseBuilder rb{ctx, 3}; |
| 180 | rb.Push(ResultSuccess); | 180 | rb.Push(ResultSuccess); |
| 181 | 181 | ||
| 182 | if (Settings::values.bcat_backend == "none") { | 182 | if (Settings::values.bcat_backend.GetValue() == "none") { |
| 183 | rb.PushEnum(RequestState::NotSubmitted); | 183 | rb.PushEnum(RequestState::NotSubmitted); |
| 184 | } else { | 184 | } else { |
| 185 | rb.PushEnum(RequestState::Connected); | 185 | rb.PushEnum(RequestState::Connected); |
| @@ -384,7 +384,7 @@ private: | |||
| 384 | 384 | ||
| 385 | IPC::ResponseBuilder rb{ctx, 3}; | 385 | IPC::ResponseBuilder rb{ctx, 3}; |
| 386 | rb.Push(ResultSuccess); | 386 | rb.Push(ResultSuccess); |
| 387 | if (Settings::values.bcat_backend == "none") { | 387 | if (Settings::values.bcat_backend.GetValue() == "none") { |
| 388 | rb.Push<u8>(0); | 388 | rb.Push<u8>(0); |
| 389 | } else { | 389 | } else { |
| 390 | rb.Push<u8>(1); | 390 | rb.Push<u8>(1); |
| @@ -395,7 +395,7 @@ private: | |||
| 395 | 395 | ||
| 396 | IPC::ResponseBuilder rb{ctx, 3}; | 396 | IPC::ResponseBuilder rb{ctx, 3}; |
| 397 | rb.Push(ResultSuccess); | 397 | rb.Push(ResultSuccess); |
| 398 | if (Settings::values.bcat_backend == "none") { | 398 | if (Settings::values.bcat_backend.GetValue() == "none") { |
| 399 | rb.Push<u8>(0); | 399 | rb.Push<u8>(0); |
| 400 | } else { | 400 | } else { |
| 401 | rb.Push<u8>(1); | 401 | rb.Push<u8>(1); |
diff --git a/src/core/hle/service/set/set.cpp b/src/core/hle/service/set/set.cpp index ece2a74c6..522a604a5 100644 --- a/src/core/hle/service/set/set.cpp +++ b/src/core/hle/service/set/set.cpp | |||
| @@ -160,7 +160,7 @@ void SET::GetQuestFlag(Kernel::HLERequestContext& ctx) { | |||
| 160 | 160 | ||
| 161 | IPC::ResponseBuilder rb{ctx, 3}; | 161 | IPC::ResponseBuilder rb{ctx, 3}; |
| 162 | rb.Push(ResultSuccess); | 162 | rb.Push(ResultSuccess); |
| 163 | rb.Push(static_cast<u32>(Settings::values.quest_flag)); | 163 | rb.Push(static_cast<u32>(Settings::values.quest_flag.GetValue())); |
| 164 | } | 164 | } |
| 165 | 165 | ||
| 166 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { | 166 | void SET::GetLanguageCode(Kernel::HLERequestContext& ctx) { |
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp index 618555202..951ea966e 100644 --- a/src/core/loader/nro.cpp +++ b/src/core/loader/nro.cpp | |||
| @@ -155,8 +155,8 @@ static bool LoadNroImpl(Kernel::KProcess& process, const std::vector<u8>& data) | |||
| 155 | codeset.segments[i].size = PageAlignSize(nro_header.segments[i].size); | 155 | codeset.segments[i].size = PageAlignSize(nro_header.segments[i].size); |
| 156 | } | 156 | } |
| 157 | 157 | ||
| 158 | if (!Settings::values.program_args.empty()) { | 158 | if (!Settings::values.program_args.GetValue().empty()) { |
| 159 | const auto arg_data = Settings::values.program_args; | 159 | const auto arg_data = Settings::values.program_args.GetValue(); |
| 160 | codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; | 160 | codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; |
| 161 | NSOArgumentHeader args_header{ | 161 | NSOArgumentHeader args_header{ |
| 162 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; | 162 | NSO_ARGUMENT_DATA_ALLOCATION_SIZE, static_cast<u32_le>(arg_data.size()), {}}; |
diff --git a/src/core/loader/nso.cpp b/src/core/loader/nso.cpp index 0f5cfda68..4a2224c02 100644 --- a/src/core/loader/nso.cpp +++ b/src/core/loader/nso.cpp | |||
| @@ -104,8 +104,8 @@ std::optional<VAddr> AppLoader_NSO::LoadModule(Kernel::KProcess& process, Core:: | |||
| 104 | codeset.segments[i].size = nso_header.segments[i].size; | 104 | codeset.segments[i].size = nso_header.segments[i].size; |
| 105 | } | 105 | } |
| 106 | 106 | ||
| 107 | if (should_pass_arguments && !Settings::values.program_args.empty()) { | 107 | if (should_pass_arguments && !Settings::values.program_args.GetValue().empty()) { |
| 108 | const auto arg_data{Settings::values.program_args}; | 108 | const auto arg_data{Settings::values.program_args.GetValue()}; |
| 109 | 109 | ||
| 110 | codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; | 110 | codeset.DataSegment().size += NSO_ARGUMENT_DATA_ALLOCATION_SIZE; |
| 111 | NSOArgumentHeader args_header{ | 111 | NSOArgumentHeader args_header{ |
diff --git a/src/core/reporter.cpp b/src/core/reporter.cpp index 82b0f535a..cfaf50105 100644 --- a/src/core/reporter.cpp +++ b/src/core/reporter.cpp | |||
| @@ -397,7 +397,7 @@ void Reporter::ClearFSAccessLog() const { | |||
| 397 | } | 397 | } |
| 398 | 398 | ||
| 399 | bool Reporter::IsReportingEnabled() const { | 399 | bool Reporter::IsReportingEnabled() const { |
| 400 | return Settings::values.reporting_services; | 400 | return Settings::values.reporting_services.GetValue(); |
| 401 | } | 401 | } |
| 402 | 402 | ||
| 403 | } // namespace Core | 403 | } // namespace Core |
diff --git a/src/core/telemetry_session.cpp b/src/core/telemetry_session.cpp index d4c23ced2..066cb23e4 100644 --- a/src/core/telemetry_session.cpp +++ b/src/core/telemetry_session.cpp | |||
| @@ -135,7 +135,7 @@ u64 RegenerateTelemetryId() { | |||
| 135 | 135 | ||
| 136 | bool VerifyLogin(const std::string& username, const std::string& token) { | 136 | bool VerifyLogin(const std::string& username, const std::string& token) { |
| 137 | #ifdef ENABLE_WEB_SERVICE | 137 | #ifdef ENABLE_WEB_SERVICE |
| 138 | return WebService::VerifyLogin(Settings::values.web_api_url, username, token); | 138 | return WebService::VerifyLogin(Settings::values.web_api_url.GetValue(), username, token); |
| 139 | #else | 139 | #else |
| 140 | return false; | 140 | return false; |
| 141 | #endif | 141 | #endif |
| @@ -152,7 +152,8 @@ TelemetrySession::~TelemetrySession() { | |||
| 152 | 152 | ||
| 153 | #ifdef ENABLE_WEB_SERVICE | 153 | #ifdef ENABLE_WEB_SERVICE |
| 154 | auto backend = std::make_unique<WebService::TelemetryJson>( | 154 | auto backend = std::make_unique<WebService::TelemetryJson>( |
| 155 | Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); | 155 | Settings::values.web_api_url.GetValue(), Settings::values.yuzu_username.GetValue(), |
| 156 | Settings::values.yuzu_token.GetValue()); | ||
| 156 | #else | 157 | #else |
| 157 | auto backend = std::make_unique<Telemetry::NullVisitor>(); | 158 | auto backend = std::make_unique<Telemetry::NullVisitor>(); |
| 158 | #endif | 159 | #endif |
| @@ -212,7 +213,7 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 212 | 213 | ||
| 213 | // Log user configuration information | 214 | // Log user configuration information |
| 214 | constexpr auto field_type = Telemetry::FieldType::UserConfig; | 215 | constexpr auto field_type = Telemetry::FieldType::UserConfig; |
| 215 | AddField(field_type, "Audio_SinkId", Settings::values.sink_id); | 216 | AddField(field_type, "Audio_SinkId", Settings::values.sink_id.GetValue()); |
| 216 | AddField(field_type, "Audio_EnableAudioStretching", | 217 | AddField(field_type, "Audio_EnableAudioStretching", |
| 217 | Settings::values.enable_audio_stretching.GetValue()); | 218 | Settings::values.enable_audio_stretching.GetValue()); |
| 218 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); | 219 | AddField(field_type, "Core_UseMultiCore", Settings::values.use_multi_core.GetValue()); |
| @@ -242,7 +243,8 @@ void TelemetrySession::AddInitialInfo(Loader::AppLoader& app_loader, | |||
| 242 | bool TelemetrySession::SubmitTestcase() { | 243 | bool TelemetrySession::SubmitTestcase() { |
| 243 | #ifdef ENABLE_WEB_SERVICE | 244 | #ifdef ENABLE_WEB_SERVICE |
| 244 | auto backend = std::make_unique<WebService::TelemetryJson>( | 245 | auto backend = std::make_unique<WebService::TelemetryJson>( |
| 245 | Settings::values.web_api_url, Settings::values.yuzu_username, Settings::values.yuzu_token); | 246 | Settings::values.web_api_url.GetValue(), Settings::values.yuzu_username.GetValue(), |
| 247 | Settings::values.yuzu_token.GetValue()); | ||
| 246 | field_collection.Accept(*backend); | 248 | field_collection.Accept(*backend); |
| 247 | return backend->SubmitTestcase(); | 249 | return backend->SubmitTestcase(); |
| 248 | #else | 250 | #else |
diff --git a/src/input_common/mouse/mouse_poller.cpp b/src/input_common/mouse/mouse_poller.cpp index 758f7af1f..45b3d7340 100644 --- a/src/input_common/mouse/mouse_poller.cpp +++ b/src/input_common/mouse/mouse_poller.cpp | |||
| @@ -84,7 +84,8 @@ public: | |||
| 84 | std::lock_guard lock{mutex}; | 84 | std::lock_guard lock{mutex}; |
| 85 | const auto axis_value = | 85 | const auto axis_value = |
| 86 | static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); | 86 | static_cast<float>(mouse_input->GetMouseState(button).axis.at(axis)); |
| 87 | return axis_value * Settings::values.mouse_panning_sensitivity / (100.0f * range); | 87 | const float sensitivity = Settings::values.mouse_panning_sensitivity.GetValue(); |
| 88 | return axis_value * sensitivity / (100.0f * range); | ||
| 88 | } | 89 | } |
| 89 | 90 | ||
| 90 | std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { | 91 | std::pair<float, float> GetAnalog(u32 analog_axis_x, u32 analog_axis_y) const { |
diff --git a/src/input_common/touch_from_button.cpp b/src/input_common/touch_from_button.cpp index 5b24fd8bf..7878a56d7 100644 --- a/src/input_common/touch_from_button.cpp +++ b/src/input_common/touch_from_button.cpp | |||
| @@ -13,7 +13,7 @@ class TouchFromButtonDevice final : public Input::TouchDevice { | |||
| 13 | public: | 13 | public: |
| 14 | TouchFromButtonDevice() { | 14 | TouchFromButtonDevice() { |
| 15 | const auto button_index = | 15 | const auto button_index = |
| 16 | static_cast<std::size_t>(Settings::values.touch_from_button_map_index); | 16 | static_cast<u64>(Settings::values.touch_from_button_map_index.GetValue()); |
| 17 | const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons; | 17 | const auto& buttons = Settings::values.touch_from_button_maps[button_index].buttons; |
| 18 | 18 | ||
| 19 | for (const auto& config_entry : buttons) { | 19 | for (const auto& config_entry : buttons) { |
diff --git a/src/input_common/udp/client.cpp b/src/input_common/udp/client.cpp index bc1dfab3d..9b0aec797 100644 --- a/src/input_common/udp/client.cpp +++ b/src/input_common/udp/client.cpp | |||
| @@ -201,7 +201,7 @@ bool Client::DeviceConnected(std::size_t pad) const { | |||
| 201 | void Client::ReloadSockets() { | 201 | void Client::ReloadSockets() { |
| 202 | Reset(); | 202 | Reset(); |
| 203 | 203 | ||
| 204 | std::stringstream servers_ss(Settings::values.udp_input_servers); | 204 | std::stringstream servers_ss(static_cast<std::string>(Settings::values.udp_input_servers)); |
| 205 | std::string server_token; | 205 | std::string server_token; |
| 206 | std::size_t client = 0; | 206 | std::size_t client = 0; |
| 207 | while (std::getline(servers_ss, server_token, ',')) { | 207 | while (std::getline(servers_ss, server_token, ',')) { |
| @@ -370,7 +370,7 @@ std::optional<std::size_t> Client::GetUnusedFingerID() const { | |||
| 370 | 370 | ||
| 371 | void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) { | 371 | void Client::UpdateTouchInput(Response::TouchPad& touch_pad, std::size_t client, std::size_t id) { |
| 372 | // TODO: Use custom calibration per device | 372 | // TODO: Use custom calibration per device |
| 373 | const Common::ParamPackage touch_param(Settings::values.touch_device); | 373 | const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); |
| 374 | const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); | 374 | const u16 min_x = static_cast<u16>(touch_param.Get("min_x", 100)); |
| 375 | const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50)); | 375 | const u16 min_y = static_cast<u16>(touch_param.Get("min_y", 50)); |
| 376 | const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800)); | 376 | const u16 max_x = static_cast<u16>(touch_param.Get("max_x", 1800)); |
diff --git a/src/tests/CMakeLists.txt b/src/tests/CMakeLists.txt index 96bc30cac..c4c012f3d 100644 --- a/src/tests/CMakeLists.txt +++ b/src/tests/CMakeLists.txt | |||
| @@ -5,6 +5,7 @@ add_executable(tests | |||
| 5 | common/host_memory.cpp | 5 | common/host_memory.cpp |
| 6 | common/param_package.cpp | 6 | common/param_package.cpp |
| 7 | common/ring_buffer.cpp | 7 | common/ring_buffer.cpp |
| 8 | common/unique_function.cpp | ||
| 8 | core/core_timing.cpp | 9 | core/core_timing.cpp |
| 9 | core/network/network.cpp | 10 | core/network/network.cpp |
| 10 | tests.cpp | 11 | tests.cpp |
diff --git a/src/tests/common/unique_function.cpp b/src/tests/common/unique_function.cpp new file mode 100644 index 000000000..ac9912738 --- /dev/null +++ b/src/tests/common/unique_function.cpp | |||
| @@ -0,0 +1,108 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include <string> | ||
| 6 | |||
| 7 | #include <catch2/catch.hpp> | ||
| 8 | |||
| 9 | #include "common/unique_function.h" | ||
| 10 | |||
| 11 | namespace { | ||
| 12 | struct Noisy { | ||
| 13 | Noisy() : state{"Default constructed"} {} | ||
| 14 | Noisy(Noisy&& rhs) noexcept : state{"Move constructed"} { | ||
| 15 | rhs.state = "Moved away"; | ||
| 16 | } | ||
| 17 | Noisy& operator=(Noisy&& rhs) noexcept { | ||
| 18 | state = "Move assigned"; | ||
| 19 | rhs.state = "Moved away"; | ||
| 20 | } | ||
| 21 | Noisy(const Noisy&) : state{"Copied constructed"} {} | ||
| 22 | Noisy& operator=(const Noisy&) { | ||
| 23 | state = "Copied assigned"; | ||
| 24 | } | ||
| 25 | |||
| 26 | std::string state; | ||
| 27 | }; | ||
| 28 | } // Anonymous namespace | ||
| 29 | |||
| 30 | TEST_CASE("UniqueFunction", "[common]") { | ||
| 31 | SECTION("Capture reference") { | ||
| 32 | int value = 0; | ||
| 33 | Common::UniqueFunction<void> func = [&value] { value = 5; }; | ||
| 34 | func(); | ||
| 35 | REQUIRE(value == 5); | ||
| 36 | } | ||
| 37 | SECTION("Capture pointer") { | ||
| 38 | int value = 0; | ||
| 39 | int* pointer = &value; | ||
| 40 | Common::UniqueFunction<void> func = [pointer] { *pointer = 5; }; | ||
| 41 | func(); | ||
| 42 | REQUIRE(value == 5); | ||
| 43 | } | ||
| 44 | SECTION("Move object") { | ||
| 45 | Noisy noisy; | ||
| 46 | REQUIRE(noisy.state == "Default constructed"); | ||
| 47 | |||
| 48 | Common::UniqueFunction<void> func = [noisy = std::move(noisy)] { | ||
| 49 | REQUIRE(noisy.state == "Move constructed"); | ||
| 50 | }; | ||
| 51 | REQUIRE(noisy.state == "Moved away"); | ||
| 52 | func(); | ||
| 53 | } | ||
| 54 | SECTION("Move construct function") { | ||
| 55 | int value = 0; | ||
| 56 | Common::UniqueFunction<void> func = [&value] { value = 5; }; | ||
| 57 | Common::UniqueFunction<void> new_func = std::move(func); | ||
| 58 | new_func(); | ||
| 59 | REQUIRE(value == 5); | ||
| 60 | } | ||
| 61 | SECTION("Move assign function") { | ||
| 62 | int value = 0; | ||
| 63 | Common::UniqueFunction<void> func = [&value] { value = 5; }; | ||
| 64 | Common::UniqueFunction<void> new_func; | ||
| 65 | new_func = std::move(func); | ||
| 66 | new_func(); | ||
| 67 | REQUIRE(value == 5); | ||
| 68 | } | ||
| 69 | SECTION("Default construct then assign function") { | ||
| 70 | int value = 0; | ||
| 71 | Common::UniqueFunction<void> func; | ||
| 72 | func = [&value] { value = 5; }; | ||
| 73 | func(); | ||
| 74 | REQUIRE(value == 5); | ||
| 75 | } | ||
| 76 | SECTION("Pass arguments") { | ||
| 77 | int result = 0; | ||
| 78 | Common::UniqueFunction<void, int, int> func = [&result](int a, int b) { result = a + b; }; | ||
| 79 | func(5, 4); | ||
| 80 | REQUIRE(result == 9); | ||
| 81 | } | ||
| 82 | SECTION("Pass arguments and return value") { | ||
| 83 | Common::UniqueFunction<int, int, int> func = [](int a, int b) { return a + b; }; | ||
| 84 | REQUIRE(func(5, 4) == 9); | ||
| 85 | } | ||
| 86 | SECTION("Destructor") { | ||
| 87 | int num_destroyed = 0; | ||
| 88 | struct Foo { | ||
| 89 | Foo(int* num_) : num{num_} {} | ||
| 90 | Foo(Foo&& rhs) : num{std::exchange(rhs.num, nullptr)} {} | ||
| 91 | Foo(const Foo&) = delete; | ||
| 92 | |||
| 93 | ~Foo() { | ||
| 94 | if (num) { | ||
| 95 | ++*num; | ||
| 96 | } | ||
| 97 | } | ||
| 98 | |||
| 99 | int* num = nullptr; | ||
| 100 | }; | ||
| 101 | Foo object{&num_destroyed}; | ||
| 102 | { | ||
| 103 | Common::UniqueFunction<void> func = [object = std::move(object)] {}; | ||
| 104 | REQUIRE(num_destroyed == 0); | ||
| 105 | } | ||
| 106 | REQUIRE(num_destroyed == 1); | ||
| 107 | } | ||
| 108 | } | ||
diff --git a/src/tests/video_core/buffer_base.cpp b/src/tests/video_core/buffer_base.cpp index edced69bb..9f5a54de4 100644 --- a/src/tests/video_core/buffer_base.cpp +++ b/src/tests/video_core/buffer_base.cpp | |||
| @@ -536,7 +536,7 @@ TEST_CASE("BufferBase: Cached write downloads") { | |||
| 536 | REQUIRE(rasterizer.Count() == 63); | 536 | REQUIRE(rasterizer.Count() == 63); |
| 537 | buffer.MarkRegionAsGpuModified(c + PAGE, PAGE); | 537 | buffer.MarkRegionAsGpuModified(c + PAGE, PAGE); |
| 538 | int num = 0; | 538 | int num = 0; |
| 539 | buffer.ForEachDownloadRange(c, WORD, [&](u64 offset, u64 size) { ++num; }); | 539 | buffer.ForEachDownloadRangeAndClear(c, WORD, [&](u64 offset, u64 size) { ++num; }); |
| 540 | buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { ++num; }); | 540 | buffer.ForEachUploadRange(c, WORD, [&](u64 offset, u64 size) { ++num; }); |
| 541 | REQUIRE(num == 0); | 541 | REQUIRE(num == 0); |
| 542 | REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); | 542 | REQUIRE(!buffer.IsRegionCpuModified(c + PAGE, PAGE)); |
diff --git a/src/video_core/buffer_cache/buffer_base.h b/src/video_core/buffer_cache/buffer_base.h index b121d36a3..c3318095c 100644 --- a/src/video_core/buffer_cache/buffer_base.h +++ b/src/video_core/buffer_cache/buffer_base.h | |||
| @@ -226,19 +226,24 @@ public: | |||
| 226 | /// Call 'func' for each CPU modified range and unmark those pages as CPU modified | 226 | /// Call 'func' for each CPU modified range and unmark those pages as CPU modified |
| 227 | template <typename Func> | 227 | template <typename Func> |
| 228 | void ForEachUploadRange(VAddr query_cpu_range, u64 size, Func&& func) { | 228 | void ForEachUploadRange(VAddr query_cpu_range, u64 size, Func&& func) { |
| 229 | ForEachModifiedRange<Type::CPU>(query_cpu_range, size, func); | 229 | ForEachModifiedRange<Type::CPU>(query_cpu_range, size, true, func); |
| 230 | } | 230 | } |
| 231 | 231 | ||
| 232 | /// Call 'func' for each GPU modified range and unmark those pages as GPU modified | 232 | /// Call 'func' for each GPU modified range and unmark those pages as GPU modified |
| 233 | template <typename Func> | 233 | template <typename Func> |
| 234 | void ForEachDownloadRange(VAddr query_cpu_range, u64 size, Func&& func) { | 234 | void ForEachDownloadRange(VAddr query_cpu_range, u64 size, bool clear, Func&& func) { |
| 235 | ForEachModifiedRange<Type::GPU>(query_cpu_range, size, func); | 235 | ForEachModifiedRange<Type::GPU>(query_cpu_range, size, clear, func); |
| 236 | } | ||
| 237 | |||
| 238 | template <typename Func> | ||
| 239 | void ForEachDownloadRangeAndClear(VAddr query_cpu_range, u64 size, Func&& func) { | ||
| 240 | ForEachModifiedRange<Type::GPU>(query_cpu_range, size, true, func); | ||
| 236 | } | 241 | } |
| 237 | 242 | ||
| 238 | /// Call 'func' for each GPU modified range and unmark those pages as GPU modified | 243 | /// Call 'func' for each GPU modified range and unmark those pages as GPU modified |
| 239 | template <typename Func> | 244 | template <typename Func> |
| 240 | void ForEachDownloadRange(Func&& func) { | 245 | void ForEachDownloadRange(Func&& func) { |
| 241 | ForEachModifiedRange<Type::GPU>(cpu_addr, SizeBytes(), func); | 246 | ForEachModifiedRange<Type::GPU>(cpu_addr, SizeBytes(), true, func); |
| 242 | } | 247 | } |
| 243 | 248 | ||
| 244 | /// Mark buffer as picked | 249 | /// Mark buffer as picked |
| @@ -415,7 +420,7 @@ private: | |||
| 415 | * @param func Function to call for each turned off region | 420 | * @param func Function to call for each turned off region |
| 416 | */ | 421 | */ |
| 417 | template <Type type, typename Func> | 422 | template <Type type, typename Func> |
| 418 | void ForEachModifiedRange(VAddr query_cpu_range, s64 size, Func&& func) { | 423 | void ForEachModifiedRange(VAddr query_cpu_range, s64 size, bool clear, Func&& func) { |
| 419 | static_assert(type != Type::Untracked); | 424 | static_assert(type != Type::Untracked); |
| 420 | 425 | ||
| 421 | const s64 difference = query_cpu_range - cpu_addr; | 426 | const s64 difference = query_cpu_range - cpu_addr; |
| @@ -467,7 +472,9 @@ private: | |||
| 467 | bits = (bits << left_offset) >> left_offset; | 472 | bits = (bits << left_offset) >> left_offset; |
| 468 | 473 | ||
| 469 | const u64 current_word = state_words[word_index] & bits; | 474 | const u64 current_word = state_words[word_index] & bits; |
| 470 | state_words[word_index] &= ~bits; | 475 | if (clear) { |
| 476 | state_words[word_index] &= ~bits; | ||
| 477 | } | ||
| 471 | 478 | ||
| 472 | if constexpr (type == Type::CPU) { | 479 | if constexpr (type == Type::CPU) { |
| 473 | const u64 current_bits = untracked_words[word_index] & bits; | 480 | const u64 current_bits = untracked_words[word_index] & bits; |
diff --git a/src/video_core/buffer_cache/buffer_cache.h b/src/video_core/buffer_cache/buffer_cache.h index cad7f902d..2871682f6 100644 --- a/src/video_core/buffer_cache/buffer_cache.h +++ b/src/video_core/buffer_cache/buffer_cache.h | |||
| @@ -15,6 +15,7 @@ | |||
| 15 | #include <vector> | 15 | #include <vector> |
| 16 | 16 | ||
| 17 | #include <boost/container/small_vector.hpp> | 17 | #include <boost/container/small_vector.hpp> |
| 18 | #include <boost/icl/interval_set.hpp> | ||
| 18 | 19 | ||
| 19 | #include "common/common_types.h" | 20 | #include "common/common_types.h" |
| 20 | #include "common/div_ceil.h" | 21 | #include "common/div_ceil.h" |
| @@ -77,6 +78,9 @@ class BufferCache { | |||
| 77 | using Runtime = typename P::Runtime; | 78 | using Runtime = typename P::Runtime; |
| 78 | using Buffer = typename P::Buffer; | 79 | using Buffer = typename P::Buffer; |
| 79 | 80 | ||
| 81 | using IntervalSet = boost::icl::interval_set<VAddr>; | ||
| 82 | using IntervalType = typename IntervalSet::interval_type; | ||
| 83 | |||
| 80 | struct Empty {}; | 84 | struct Empty {}; |
| 81 | 85 | ||
| 82 | struct OverlapResult { | 86 | struct OverlapResult { |
| @@ -148,18 +152,26 @@ public: | |||
| 148 | /// Return true when there are uncommitted buffers to be downloaded | 152 | /// Return true when there are uncommitted buffers to be downloaded |
| 149 | [[nodiscard]] bool HasUncommittedFlushes() const noexcept; | 153 | [[nodiscard]] bool HasUncommittedFlushes() const noexcept; |
| 150 | 154 | ||
| 155 | void AccumulateFlushes(); | ||
| 156 | |||
| 151 | /// Return true when the caller should wait for async downloads | 157 | /// Return true when the caller should wait for async downloads |
| 152 | [[nodiscard]] bool ShouldWaitAsyncFlushes() const noexcept; | 158 | [[nodiscard]] bool ShouldWaitAsyncFlushes() const noexcept; |
| 153 | 159 | ||
| 154 | /// Commit asynchronous downloads | 160 | /// Commit asynchronous downloads |
| 155 | void CommitAsyncFlushes(); | 161 | void CommitAsyncFlushes(); |
| 162 | void CommitAsyncFlushesHigh(); | ||
| 156 | 163 | ||
| 157 | /// Pop asynchronous downloads | 164 | /// Pop asynchronous downloads |
| 158 | void PopAsyncFlushes(); | 165 | void PopAsyncFlushes(); |
| 159 | 166 | ||
| 167 | [[nodiscard]] bool DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount); | ||
| 168 | |||
| 160 | /// Return true when a CPU region is modified from the GPU | 169 | /// Return true when a CPU region is modified from the GPU |
| 161 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); | 170 | [[nodiscard]] bool IsRegionGpuModified(VAddr addr, size_t size); |
| 162 | 171 | ||
| 172 | /// Return true when a CPU region is modified from the CPU | ||
| 173 | [[nodiscard]] bool IsRegionCpuModified(VAddr addr, size_t size); | ||
| 174 | |||
| 163 | std::mutex mutex; | 175 | std::mutex mutex; |
| 164 | 176 | ||
| 165 | private: | 177 | private: |
| @@ -190,6 +202,36 @@ private: | |||
| 190 | } | 202 | } |
| 191 | } | 203 | } |
| 192 | 204 | ||
| 205 | template <typename Func> | ||
| 206 | void ForEachWrittenRange(VAddr cpu_addr, u64 size, Func&& func) { | ||
| 207 | const VAddr start_address = cpu_addr; | ||
| 208 | const VAddr end_address = start_address + size; | ||
| 209 | const VAddr search_base = | ||
| 210 | static_cast<VAddr>(std::min<s64>(0LL, static_cast<s64>(start_address - size))); | ||
| 211 | const IntervalType search_interval{search_base, search_base + 1}; | ||
| 212 | auto it = common_ranges.lower_bound(search_interval); | ||
| 213 | if (it == common_ranges.end()) { | ||
| 214 | it = common_ranges.begin(); | ||
| 215 | } | ||
| 216 | for (; it != common_ranges.end(); it++) { | ||
| 217 | VAddr inter_addr_end = it->upper(); | ||
| 218 | VAddr inter_addr = it->lower(); | ||
| 219 | if (inter_addr >= end_address) { | ||
| 220 | break; | ||
| 221 | } | ||
| 222 | if (inter_addr_end <= start_address) { | ||
| 223 | continue; | ||
| 224 | } | ||
| 225 | if (inter_addr_end > end_address) { | ||
| 226 | inter_addr_end = end_address; | ||
| 227 | } | ||
| 228 | if (inter_addr < start_address) { | ||
| 229 | inter_addr = start_address; | ||
| 230 | } | ||
| 231 | func(inter_addr, inter_addr_end); | ||
| 232 | } | ||
| 233 | } | ||
| 234 | |||
| 193 | static bool IsRangeGranular(VAddr cpu_addr, size_t size) { | 235 | static bool IsRangeGranular(VAddr cpu_addr, size_t size) { |
| 194 | return (cpu_addr & ~Core::Memory::PAGE_MASK) == | 236 | return (cpu_addr & ~Core::Memory::PAGE_MASK) == |
| 195 | ((cpu_addr + size) & ~Core::Memory::PAGE_MASK); | 237 | ((cpu_addr + size) & ~Core::Memory::PAGE_MASK); |
| @@ -272,8 +314,6 @@ private: | |||
| 272 | 314 | ||
| 273 | void DeleteBuffer(BufferId buffer_id); | 315 | void DeleteBuffer(BufferId buffer_id); |
| 274 | 316 | ||
| 275 | void ReplaceBufferDownloads(BufferId old_buffer_id, BufferId new_buffer_id); | ||
| 276 | |||
| 277 | void NotifyBufferDeletion(); | 317 | void NotifyBufferDeletion(); |
| 278 | 318 | ||
| 279 | [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const; | 319 | [[nodiscard]] Binding StorageBufferBinding(GPUVAddr ssbo_addr) const; |
| @@ -327,9 +367,9 @@ private: | |||
| 327 | 367 | ||
| 328 | std::vector<BufferId> cached_write_buffer_ids; | 368 | std::vector<BufferId> cached_write_buffer_ids; |
| 329 | 369 | ||
| 330 | // TODO: This data structure is not optimal and it should be reworked | 370 | IntervalSet uncommitted_ranges; |
| 331 | std::vector<BufferId> uncommitted_downloads; | 371 | IntervalSet common_ranges; |
| 332 | std::deque<std::vector<BufferId>> committed_downloads; | 372 | std::deque<IntervalSet> committed_ranges; |
| 333 | 373 | ||
| 334 | size_t immediate_buffer_capacity = 0; | 374 | size_t immediate_buffer_capacity = 0; |
| 335 | std::unique_ptr<u8[]> immediate_buffer_alloc; | 375 | std::unique_ptr<u8[]> immediate_buffer_alloc; |
| @@ -352,6 +392,7 @@ BufferCache<P>::BufferCache(VideoCore::RasterizerInterface& rasterizer_, | |||
| 352 | // Ensure the first slot is used for the null buffer | 392 | // Ensure the first slot is used for the null buffer |
| 353 | void(slot_buffers.insert(runtime, NullBufferParams{})); | 393 | void(slot_buffers.insert(runtime, NullBufferParams{})); |
| 354 | deletion_iterator = slot_buffers.end(); | 394 | deletion_iterator = slot_buffers.end(); |
| 395 | common_ranges.clear(); | ||
| 355 | } | 396 | } |
| 356 | 397 | ||
| 357 | template <class P> | 398 | template <class P> |
| @@ -422,6 +463,68 @@ void BufferCache<P>::DownloadMemory(VAddr cpu_addr, u64 size) { | |||
| 422 | } | 463 | } |
| 423 | 464 | ||
| 424 | template <class P> | 465 | template <class P> |
| 466 | bool BufferCache<P>::DMACopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { | ||
| 467 | const std::optional<VAddr> cpu_src_address = gpu_memory.GpuToCpuAddress(src_address); | ||
| 468 | const std::optional<VAddr> cpu_dest_address = gpu_memory.GpuToCpuAddress(dest_address); | ||
| 469 | if (!cpu_src_address || !cpu_dest_address) { | ||
| 470 | return false; | ||
| 471 | } | ||
| 472 | const bool source_dirty = IsRegionGpuModified(*cpu_src_address, amount); | ||
| 473 | const bool dest_dirty = IsRegionGpuModified(*cpu_dest_address, amount); | ||
| 474 | if (!source_dirty && !dest_dirty) { | ||
| 475 | return false; | ||
| 476 | } | ||
| 477 | |||
| 478 | const IntervalType subtract_interval{*cpu_dest_address, *cpu_dest_address + amount}; | ||
| 479 | uncommitted_ranges.subtract(subtract_interval); | ||
| 480 | for (auto& interval_set : committed_ranges) { | ||
| 481 | interval_set.subtract(subtract_interval); | ||
| 482 | } | ||
| 483 | |||
| 484 | BufferId buffer_a; | ||
| 485 | BufferId buffer_b; | ||
| 486 | do { | ||
| 487 | has_deleted_buffers = false; | ||
| 488 | buffer_a = FindBuffer(*cpu_src_address, static_cast<u32>(amount)); | ||
| 489 | buffer_b = FindBuffer(*cpu_dest_address, static_cast<u32>(amount)); | ||
| 490 | } while (has_deleted_buffers); | ||
| 491 | auto& src_buffer = slot_buffers[buffer_a]; | ||
| 492 | auto& dest_buffer = slot_buffers[buffer_b]; | ||
| 493 | SynchronizeBuffer(src_buffer, *cpu_src_address, static_cast<u32>(amount)); | ||
| 494 | SynchronizeBuffer(dest_buffer, *cpu_dest_address, static_cast<u32>(amount)); | ||
| 495 | std::array copies{BufferCopy{ | ||
| 496 | .src_offset = src_buffer.Offset(*cpu_src_address), | ||
| 497 | .dst_offset = dest_buffer.Offset(*cpu_dest_address), | ||
| 498 | .size = amount, | ||
| 499 | }}; | ||
| 500 | |||
| 501 | boost::container::small_vector<IntervalType, 4> tmp_intervals; | ||
| 502 | auto mirror = [&](VAddr base_address, VAddr base_address_end) { | ||
| 503 | const u64 size = base_address_end - base_address; | ||
| 504 | const VAddr diff = base_address - *cpu_src_address; | ||
| 505 | const VAddr new_base_address = *cpu_dest_address + diff; | ||
| 506 | const IntervalType add_interval{new_base_address, new_base_address + size}; | ||
| 507 | uncommitted_ranges.add(add_interval); | ||
| 508 | tmp_intervals.push_back(add_interval); | ||
| 509 | }; | ||
| 510 | ForEachWrittenRange(*cpu_src_address, amount, mirror); | ||
| 511 | // This subtraction in this order is important for overlapping copies. | ||
| 512 | common_ranges.subtract(subtract_interval); | ||
| 513 | for (const IntervalType add_interval : tmp_intervals) { | ||
| 514 | common_ranges.add(add_interval); | ||
| 515 | } | ||
| 516 | |||
| 517 | runtime.CopyBuffer(dest_buffer, src_buffer, copies); | ||
| 518 | if (source_dirty) { | ||
| 519 | dest_buffer.MarkRegionAsGpuModified(*cpu_dest_address, amount); | ||
| 520 | } | ||
| 521 | std::vector<u8> tmp_buffer(amount); | ||
| 522 | cpu_memory.ReadBlockUnsafe(*cpu_src_address, tmp_buffer.data(), amount); | ||
| 523 | cpu_memory.WriteBlockUnsafe(*cpu_dest_address, tmp_buffer.data(), amount); | ||
| 524 | return true; | ||
| 525 | } | ||
| 526 | |||
| 527 | template <class P> | ||
| 425 | void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, | 528 | void BufferCache<P>::BindGraphicsUniformBuffer(size_t stage, u32 index, GPUVAddr gpu_addr, |
| 426 | u32 size) { | 529 | u32 size) { |
| 427 | const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); | 530 | const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr); |
| @@ -547,29 +650,30 @@ void BufferCache<P>::FlushCachedWrites() { | |||
| 547 | 650 | ||
| 548 | template <class P> | 651 | template <class P> |
| 549 | bool BufferCache<P>::HasUncommittedFlushes() const noexcept { | 652 | bool BufferCache<P>::HasUncommittedFlushes() const noexcept { |
| 550 | return !uncommitted_downloads.empty(); | 653 | return !uncommitted_ranges.empty() || !committed_ranges.empty(); |
| 551 | } | 654 | } |
| 552 | 655 | ||
| 553 | template <class P> | 656 | template <class P> |
| 554 | bool BufferCache<P>::ShouldWaitAsyncFlushes() const noexcept { | 657 | void BufferCache<P>::AccumulateFlushes() { |
| 555 | return !committed_downloads.empty() && !committed_downloads.front().empty(); | 658 | if (Settings::values.gpu_accuracy.GetValue() != Settings::GPUAccuracy::High) { |
| 659 | uncommitted_ranges.clear(); | ||
| 660 | return; | ||
| 661 | } | ||
| 662 | if (uncommitted_ranges.empty()) { | ||
| 663 | return; | ||
| 664 | } | ||
| 665 | committed_ranges.emplace_back(std::move(uncommitted_ranges)); | ||
| 556 | } | 666 | } |
| 557 | 667 | ||
| 558 | template <class P> | 668 | template <class P> |
| 559 | void BufferCache<P>::CommitAsyncFlushes() { | 669 | bool BufferCache<P>::ShouldWaitAsyncFlushes() const noexcept { |
| 560 | // This is intentionally passing the value by copy | 670 | return false; |
| 561 | committed_downloads.push_front(uncommitted_downloads); | ||
| 562 | uncommitted_downloads.clear(); | ||
| 563 | } | 671 | } |
| 564 | 672 | ||
| 565 | template <class P> | 673 | template <class P> |
| 566 | void BufferCache<P>::PopAsyncFlushes() { | 674 | void BufferCache<P>::CommitAsyncFlushesHigh() { |
| 567 | if (committed_downloads.empty()) { | 675 | AccumulateFlushes(); |
| 568 | return; | 676 | if (committed_ranges.empty()) { |
| 569 | } | ||
| 570 | auto scope_exit_pop_download = detail::ScopeExit([this] { committed_downloads.pop_back(); }); | ||
| 571 | const std::span<const BufferId> download_ids = committed_downloads.back(); | ||
| 572 | if (download_ids.empty()) { | ||
| 573 | return; | 677 | return; |
| 574 | } | 678 | } |
| 575 | MICROPROFILE_SCOPE(GPU_DownloadMemory); | 679 | MICROPROFILE_SCOPE(GPU_DownloadMemory); |
| @@ -577,20 +681,43 @@ void BufferCache<P>::PopAsyncFlushes() { | |||
| 577 | boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads; | 681 | boost::container::small_vector<std::pair<BufferCopy, BufferId>, 1> downloads; |
| 578 | u64 total_size_bytes = 0; | 682 | u64 total_size_bytes = 0; |
| 579 | u64 largest_copy = 0; | 683 | u64 largest_copy = 0; |
| 580 | for (const BufferId buffer_id : download_ids) { | 684 | for (const IntervalSet& intervals : committed_ranges) { |
| 581 | slot_buffers[buffer_id].ForEachDownloadRange([&](u64 range_offset, u64 range_size) { | 685 | for (auto& interval : intervals) { |
| 582 | downloads.push_back({ | 686 | const std::size_t size = interval.upper() - interval.lower(); |
| 583 | BufferCopy{ | 687 | const VAddr cpu_addr = interval.lower(); |
| 584 | .src_offset = range_offset, | 688 | ForEachBufferInRange(cpu_addr, size, [&](BufferId buffer_id, Buffer& buffer) { |
| 585 | .dst_offset = total_size_bytes, | 689 | boost::container::small_vector<BufferCopy, 1> copies; |
| 586 | .size = range_size, | 690 | buffer.ForEachDownloadRangeAndClear( |
| 587 | }, | 691 | cpu_addr, size, [&](u64 range_offset, u64 range_size) { |
| 588 | buffer_id, | 692 | const VAddr buffer_addr = buffer.CpuAddr(); |
| 693 | const auto add_download = [&](VAddr start, VAddr end) { | ||
| 694 | const u64 new_offset = start - buffer_addr; | ||
| 695 | const u64 new_size = end - start; | ||
| 696 | downloads.push_back({ | ||
| 697 | BufferCopy{ | ||
| 698 | .src_offset = new_offset, | ||
| 699 | .dst_offset = total_size_bytes, | ||
| 700 | .size = new_size, | ||
| 701 | }, | ||
| 702 | buffer_id, | ||
| 703 | }); | ||
| 704 | // Align up to avoid cache conflicts | ||
| 705 | constexpr u64 align = 256ULL; | ||
| 706 | constexpr u64 mask = ~(align - 1ULL); | ||
| 707 | total_size_bytes += (new_size + align - 1) & mask; | ||
| 708 | largest_copy = std::max(largest_copy, new_size); | ||
| 709 | }; | ||
| 710 | |||
| 711 | const VAddr start_address = buffer_addr + range_offset; | ||
| 712 | const VAddr end_address = start_address + range_size; | ||
| 713 | ForEachWrittenRange(start_address, range_size, add_download); | ||
| 714 | const IntervalType subtract_interval{start_address, end_address}; | ||
| 715 | common_ranges.subtract(subtract_interval); | ||
| 716 | }); | ||
| 589 | }); | 717 | }); |
| 590 | total_size_bytes += range_size; | 718 | } |
| 591 | largest_copy = std::max(largest_copy, range_size); | ||
| 592 | }); | ||
| 593 | } | 719 | } |
| 720 | committed_ranges.clear(); | ||
| 594 | if (downloads.empty()) { | 721 | if (downloads.empty()) { |
| 595 | return; | 722 | return; |
| 596 | } | 723 | } |
| @@ -623,6 +750,19 @@ void BufferCache<P>::PopAsyncFlushes() { | |||
| 623 | } | 750 | } |
| 624 | 751 | ||
| 625 | template <class P> | 752 | template <class P> |
| 753 | void BufferCache<P>::CommitAsyncFlushes() { | ||
| 754 | if (Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High) { | ||
| 755 | CommitAsyncFlushesHigh(); | ||
| 756 | } else { | ||
| 757 | uncommitted_ranges.clear(); | ||
| 758 | committed_ranges.clear(); | ||
| 759 | } | ||
| 760 | } | ||
| 761 | |||
| 762 | template <class P> | ||
| 763 | void BufferCache<P>::PopAsyncFlushes() {} | ||
| 764 | |||
| 765 | template <class P> | ||
| 626 | bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { | 766 | bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { |
| 627 | const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE); | 767 | const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE); |
| 628 | for (u64 page = addr >> PAGE_BITS; page < page_end;) { | 768 | for (u64 page = addr >> PAGE_BITS; page < page_end;) { |
| @@ -642,6 +782,25 @@ bool BufferCache<P>::IsRegionGpuModified(VAddr addr, size_t size) { | |||
| 642 | } | 782 | } |
| 643 | 783 | ||
| 644 | template <class P> | 784 | template <class P> |
| 785 | bool BufferCache<P>::IsRegionCpuModified(VAddr addr, size_t size) { | ||
| 786 | const u64 page_end = Common::DivCeil(addr + size, PAGE_SIZE); | ||
| 787 | for (u64 page = addr >> PAGE_BITS; page < page_end;) { | ||
| 788 | const BufferId image_id = page_table[page]; | ||
| 789 | if (!image_id) { | ||
| 790 | ++page; | ||
| 791 | continue; | ||
| 792 | } | ||
| 793 | Buffer& buffer = slot_buffers[image_id]; | ||
| 794 | if (buffer.IsRegionCpuModified(addr, size)) { | ||
| 795 | return true; | ||
| 796 | } | ||
| 797 | const VAddr end_addr = buffer.CpuAddr() + buffer.SizeBytes(); | ||
| 798 | page = Common::DivCeil(end_addr, PAGE_SIZE); | ||
| 799 | } | ||
| 800 | return false; | ||
| 801 | } | ||
| 802 | |||
| 803 | template <class P> | ||
| 645 | void BufferCache<P>::BindHostIndexBuffer() { | 804 | void BufferCache<P>::BindHostIndexBuffer() { |
| 646 | Buffer& buffer = slot_buffers[index_buffer.buffer_id]; | 805 | Buffer& buffer = slot_buffers[index_buffer.buffer_id]; |
| 647 | TouchBuffer(buffer); | 806 | TouchBuffer(buffer); |
| @@ -649,7 +808,9 @@ void BufferCache<P>::BindHostIndexBuffer() { | |||
| 649 | const u32 size = index_buffer.size; | 808 | const u32 size = index_buffer.size; |
| 650 | SynchronizeBuffer(buffer, index_buffer.cpu_addr, size); | 809 | SynchronizeBuffer(buffer, index_buffer.cpu_addr, size); |
| 651 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { | 810 | if constexpr (HAS_FULL_INDEX_AND_PRIMITIVE_SUPPORT) { |
| 652 | runtime.BindIndexBuffer(buffer, offset, size); | 811 | const u32 new_offset = offset + maxwell3d.regs.index_array.first * |
| 812 | maxwell3d.regs.index_array.FormatSizeInBytes(); | ||
| 813 | runtime.BindIndexBuffer(buffer, new_offset, size); | ||
| 653 | } else { | 814 | } else { |
| 654 | runtime.BindIndexBuffer(maxwell3d.regs.draw.topology, maxwell3d.regs.index_array.format, | 815 | runtime.BindIndexBuffer(maxwell3d.regs.draw.topology, maxwell3d.regs.index_array.format, |
| 655 | maxwell3d.regs.index_array.first, maxwell3d.regs.index_array.count, | 816 | maxwell3d.regs.index_array.first, maxwell3d.regs.index_array.count, |
| @@ -863,7 +1024,7 @@ void BufferCache<P>::UpdateIndexBuffer() { | |||
| 863 | const GPUVAddr gpu_addr_end = index_array.EndAddress(); | 1024 | const GPUVAddr gpu_addr_end = index_array.EndAddress(); |
| 864 | const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr_begin); | 1025 | const std::optional<VAddr> cpu_addr = gpu_memory.GpuToCpuAddress(gpu_addr_begin); |
| 865 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); | 1026 | const u32 address_size = static_cast<u32>(gpu_addr_end - gpu_addr_begin); |
| 866 | const u32 draw_size = index_array.count * index_array.FormatSizeInBytes(); | 1027 | const u32 draw_size = (index_array.count + index_array.first) * index_array.FormatSizeInBytes(); |
| 867 | const u32 size = std::min(address_size, draw_size); | 1028 | const u32 size = std::min(address_size, draw_size); |
| 868 | if (size == 0 || !cpu_addr) { | 1029 | if (size == 0 || !cpu_addr) { |
| 869 | index_buffer = NULL_BINDING; | 1030 | index_buffer = NULL_BINDING; |
| @@ -1010,16 +1171,16 @@ void BufferCache<P>::MarkWrittenBuffer(BufferId buffer_id, VAddr cpu_addr, u32 s | |||
| 1010 | Buffer& buffer = slot_buffers[buffer_id]; | 1171 | Buffer& buffer = slot_buffers[buffer_id]; |
| 1011 | buffer.MarkRegionAsGpuModified(cpu_addr, size); | 1172 | buffer.MarkRegionAsGpuModified(cpu_addr, size); |
| 1012 | 1173 | ||
| 1013 | const bool is_accuracy_high = Settings::IsGPULevelHigh(); | 1174 | const IntervalType base_interval{cpu_addr, cpu_addr + size}; |
| 1175 | common_ranges.add(base_interval); | ||
| 1176 | |||
| 1177 | const bool is_accuracy_high = | ||
| 1178 | Settings::values.gpu_accuracy.GetValue() == Settings::GPUAccuracy::High; | ||
| 1014 | const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); | 1179 | const bool is_async = Settings::values.use_asynchronous_gpu_emulation.GetValue(); |
| 1015 | if (!is_accuracy_high || !is_async) { | 1180 | if (!is_async && !is_accuracy_high) { |
| 1016 | return; | ||
| 1017 | } | ||
| 1018 | if (std::ranges::find(uncommitted_downloads, buffer_id) != uncommitted_downloads.end()) { | ||
| 1019 | // Already inserted | ||
| 1020 | return; | 1181 | return; |
| 1021 | } | 1182 | } |
| 1022 | uncommitted_downloads.push_back(buffer_id); | 1183 | uncommitted_ranges.add(base_interval); |
| 1023 | } | 1184 | } |
| 1024 | 1185 | ||
| 1025 | template <class P> | 1186 | template <class P> |
| @@ -1103,7 +1264,6 @@ void BufferCache<P>::JoinOverlap(BufferId new_buffer_id, BufferId overlap_id, | |||
| 1103 | if (!copies.empty()) { | 1264 | if (!copies.empty()) { |
| 1104 | runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); | 1265 | runtime.CopyBuffer(slot_buffers[new_buffer_id], overlap, copies); |
| 1105 | } | 1266 | } |
| 1106 | ReplaceBufferDownloads(overlap_id, new_buffer_id); | ||
| 1107 | DeleteBuffer(overlap_id); | 1267 | DeleteBuffer(overlap_id); |
| 1108 | } | 1268 | } |
| 1109 | 1269 | ||
| @@ -1244,14 +1404,28 @@ void BufferCache<P>::DownloadBufferMemory(Buffer& buffer, VAddr cpu_addr, u64 si | |||
| 1244 | boost::container::small_vector<BufferCopy, 1> copies; | 1404 | boost::container::small_vector<BufferCopy, 1> copies; |
| 1245 | u64 total_size_bytes = 0; | 1405 | u64 total_size_bytes = 0; |
| 1246 | u64 largest_copy = 0; | 1406 | u64 largest_copy = 0; |
| 1247 | buffer.ForEachDownloadRange(cpu_addr, size, [&](u64 range_offset, u64 range_size) { | 1407 | buffer.ForEachDownloadRangeAndClear(cpu_addr, size, [&](u64 range_offset, u64 range_size) { |
| 1248 | copies.push_back(BufferCopy{ | 1408 | const VAddr buffer_addr = buffer.CpuAddr(); |
| 1249 | .src_offset = range_offset, | 1409 | const auto add_download = [&](VAddr start, VAddr end) { |
| 1250 | .dst_offset = total_size_bytes, | 1410 | const u64 new_offset = start - buffer_addr; |
| 1251 | .size = range_size, | 1411 | const u64 new_size = end - start; |
| 1252 | }); | 1412 | copies.push_back(BufferCopy{ |
| 1253 | total_size_bytes += range_size; | 1413 | .src_offset = new_offset, |
| 1254 | largest_copy = std::max(largest_copy, range_size); | 1414 | .dst_offset = total_size_bytes, |
| 1415 | .size = new_size, | ||
| 1416 | }); | ||
| 1417 | // Align up to avoid cache conflicts | ||
| 1418 | constexpr u64 align = 256ULL; | ||
| 1419 | constexpr u64 mask = ~(align - 1ULL); | ||
| 1420 | total_size_bytes += (new_size + align - 1) & mask; | ||
| 1421 | largest_copy = std::max(largest_copy, new_size); | ||
| 1422 | }; | ||
| 1423 | |||
| 1424 | const VAddr start_address = buffer_addr + range_offset; | ||
| 1425 | const VAddr end_address = start_address + range_size; | ||
| 1426 | ForEachWrittenRange(start_address, range_size, add_download); | ||
| 1427 | const IntervalType subtract_interval{start_address, end_address}; | ||
| 1428 | common_ranges.subtract(subtract_interval); | ||
| 1255 | }); | 1429 | }); |
| 1256 | if (total_size_bytes == 0) { | 1430 | if (total_size_bytes == 0) { |
| 1257 | return; | 1431 | return; |
| @@ -1316,18 +1490,6 @@ void BufferCache<P>::DeleteBuffer(BufferId buffer_id) { | |||
| 1316 | } | 1490 | } |
| 1317 | 1491 | ||
| 1318 | template <class P> | 1492 | template <class P> |
| 1319 | void BufferCache<P>::ReplaceBufferDownloads(BufferId old_buffer_id, BufferId new_buffer_id) { | ||
| 1320 | const auto replace = [old_buffer_id, new_buffer_id](std::vector<BufferId>& buffers) { | ||
| 1321 | std::ranges::replace(buffers, old_buffer_id, new_buffer_id); | ||
| 1322 | if (auto it = std::ranges::find(buffers, new_buffer_id); it != buffers.end()) { | ||
| 1323 | buffers.erase(std::remove(it + 1, buffers.end(), new_buffer_id), buffers.end()); | ||
| 1324 | } | ||
| 1325 | }; | ||
| 1326 | replace(uncommitted_downloads); | ||
| 1327 | std::ranges::for_each(committed_downloads, replace); | ||
| 1328 | } | ||
| 1329 | |||
| 1330 | template <class P> | ||
| 1331 | void BufferCache<P>::NotifyBufferDeletion() { | 1493 | void BufferCache<P>::NotifyBufferDeletion() { |
| 1332 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { | 1494 | if constexpr (HAS_PERSISTENT_UNIFORM_BUFFER_BINDINGS) { |
| 1333 | dirty_uniform_buffers.fill(~u32{0}); | 1495 | dirty_uniform_buffers.fill(~u32{0}); |
| @@ -1349,15 +1511,9 @@ typename BufferCache<P>::Binding BufferCache<P>::StorageBufferBinding(GPUVAddr s | |||
| 1349 | if (!cpu_addr || size == 0) { | 1511 | if (!cpu_addr || size == 0) { |
| 1350 | return NULL_BINDING; | 1512 | return NULL_BINDING; |
| 1351 | } | 1513 | } |
| 1352 | // HACK(Rodrigo): This is the number of bytes bound in host beyond the guest API's range. | ||
| 1353 | // It exists due to some games like Astral Chain operate out of bounds. | ||
| 1354 | // Binding the whole map range would be technically correct, but games have large maps that make | ||
| 1355 | // this approach unaffordable for now. | ||
| 1356 | static constexpr u32 arbitrary_extra_bytes = 0xc000; | ||
| 1357 | const u32 bytes_to_map_end = static_cast<u32>(gpu_memory.BytesToMapEnd(gpu_addr)); | ||
| 1358 | const Binding binding{ | 1514 | const Binding binding{ |
| 1359 | .cpu_addr = *cpu_addr, | 1515 | .cpu_addr = *cpu_addr, |
| 1360 | .size = std::min(size + arbitrary_extra_bytes, bytes_to_map_end), | 1516 | .size = size, |
| 1361 | .buffer_id = BufferId{}, | 1517 | .buffer_id = BufferId{}, |
| 1362 | }; | 1518 | }; |
| 1363 | return binding; | 1519 | return binding; |
diff --git a/src/video_core/dma_pusher.cpp b/src/video_core/dma_pusher.cpp index 8b33c04ab..8d28bd884 100644 --- a/src/video_core/dma_pusher.cpp +++ b/src/video_core/dma_pusher.cpp | |||
| @@ -4,6 +4,7 @@ | |||
| 4 | 4 | ||
| 5 | #include "common/cityhash.h" | 5 | #include "common/cityhash.h" |
| 6 | #include "common/microprofile.h" | 6 | #include "common/microprofile.h" |
| 7 | #include "common/settings.h" | ||
| 7 | #include "core/core.h" | 8 | #include "core/core.h" |
| 8 | #include "core/memory.h" | 9 | #include "core/memory.h" |
| 9 | #include "video_core/dma_pusher.h" | 10 | #include "video_core/dma_pusher.h" |
| @@ -76,8 +77,13 @@ bool DmaPusher::Step() { | |||
| 76 | 77 | ||
| 77 | // Push buffer non-empty, read a word | 78 | // Push buffer non-empty, read a word |
| 78 | command_headers.resize(command_list_header.size); | 79 | command_headers.resize(command_list_header.size); |
| 79 | gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(), | 80 | if (Settings::IsGPULevelHigh()) { |
| 80 | command_list_header.size * sizeof(u32)); | 81 | gpu.MemoryManager().ReadBlock(dma_get, command_headers.data(), |
| 82 | command_list_header.size * sizeof(u32)); | ||
| 83 | } else { | ||
| 84 | gpu.MemoryManager().ReadBlockUnsafe(dma_get, command_headers.data(), | ||
| 85 | command_list_header.size * sizeof(u32)); | ||
| 86 | } | ||
| 81 | } | 87 | } |
| 82 | for (std::size_t index = 0; index < command_headers.size();) { | 88 | for (std::size_t index = 0; index < command_headers.size();) { |
| 83 | const CommandHeader& command_header = command_headers[index]; | 89 | const CommandHeader& command_header = command_headers[index]; |
diff --git a/src/video_core/engines/fermi_2d.cpp b/src/video_core/engines/fermi_2d.cpp index 0f640fdae..f26530ede 100644 --- a/src/video_core/engines/fermi_2d.cpp +++ b/src/video_core/engines/fermi_2d.cpp | |||
| @@ -7,6 +7,10 @@ | |||
| 7 | #include "video_core/engines/fermi_2d.h" | 7 | #include "video_core/engines/fermi_2d.h" |
| 8 | #include "video_core/memory_manager.h" | 8 | #include "video_core/memory_manager.h" |
| 9 | #include "video_core/rasterizer_interface.h" | 9 | #include "video_core/rasterizer_interface.h" |
| 10 | #include "video_core/surface.h" | ||
| 11 | |||
| 12 | using VideoCore::Surface::BytesPerBlock; | ||
| 13 | using VideoCore::Surface::PixelFormatFromRenderTargetFormat; | ||
| 10 | 14 | ||
| 11 | namespace Tegra::Engines { | 15 | namespace Tegra::Engines { |
| 12 | 16 | ||
| @@ -49,7 +53,7 @@ void Fermi2D::Blit() { | |||
| 49 | UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); | 53 | UNIMPLEMENTED_IF_MSG(regs.clip_enable != 0, "Clipped blit enabled"); |
| 50 | 54 | ||
| 51 | const auto& args = regs.pixels_from_memory; | 55 | const auto& args = regs.pixels_from_memory; |
| 52 | const Config config{ | 56 | Config config{ |
| 53 | .operation = regs.operation, | 57 | .operation = regs.operation, |
| 54 | .filter = args.sample_mode.filter, | 58 | .filter = args.sample_mode.filter, |
| 55 | .dst_x0 = args.dst_x0, | 59 | .dst_x0 = args.dst_x0, |
| @@ -61,7 +65,21 @@ void Fermi2D::Blit() { | |||
| 61 | .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32), | 65 | .src_x1 = static_cast<s32>((args.du_dx * args.dst_width + args.src_x0) >> 32), |
| 62 | .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32), | 66 | .src_y1 = static_cast<s32>((args.dv_dy * args.dst_height + args.src_y0) >> 32), |
| 63 | }; | 67 | }; |
| 64 | if (!rasterizer->AccelerateSurfaceCopy(regs.src, regs.dst, config)) { | 68 | Surface src = regs.src; |
| 69 | const auto bytes_per_pixel = BytesPerBlock(PixelFormatFromRenderTargetFormat(src.format)); | ||
| 70 | const auto need_align_to_pitch = | ||
| 71 | src.linear == Tegra::Engines::Fermi2D::MemoryLayout::Pitch && | ||
| 72 | static_cast<s32>(src.width) == config.src_x1 && | ||
| 73 | config.src_x1 > static_cast<s32>(src.pitch / bytes_per_pixel) && config.src_x0 > 0; | ||
| 74 | if (need_align_to_pitch) { | ||
| 75 | auto address = src.Address() + config.src_x0 * bytes_per_pixel; | ||
| 76 | src.addr_upper = static_cast<u32>(address >> 32); | ||
| 77 | src.addr_lower = static_cast<u32>(address); | ||
| 78 | src.width -= config.src_x0; | ||
| 79 | config.src_x1 -= config.src_x0; | ||
| 80 | config.src_x0 = 0; | ||
| 81 | } | ||
| 82 | if (!rasterizer->AccelerateSurfaceCopy(src, regs.dst, config)) { | ||
| 65 | UNIMPLEMENTED(); | 83 | UNIMPLEMENTED(); |
| 66 | } | 84 | } |
| 67 | } | 85 | } |
diff --git a/src/video_core/engines/maxwell_dma.cpp b/src/video_core/engines/maxwell_dma.cpp index 2ee980bab..24481952b 100644 --- a/src/video_core/engines/maxwell_dma.cpp +++ b/src/video_core/engines/maxwell_dma.cpp | |||
| @@ -21,6 +21,10 @@ MaxwellDMA::MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_) | |||
| 21 | 21 | ||
| 22 | MaxwellDMA::~MaxwellDMA() = default; | 22 | MaxwellDMA::~MaxwellDMA() = default; |
| 23 | 23 | ||
| 24 | void MaxwellDMA::BindRasterizer(VideoCore::RasterizerInterface* rasterizer_) { | ||
| 25 | rasterizer = rasterizer_; | ||
| 26 | } | ||
| 27 | |||
| 24 | void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) { | 28 | void MaxwellDMA::CallMethod(u32 method, u32 method_argument, bool is_last_call) { |
| 25 | ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register"); | 29 | ASSERT_MSG(method < NUM_REGS, "Invalid MaxwellDMA register"); |
| 26 | 30 | ||
| @@ -44,7 +48,6 @@ void MaxwellDMA::Launch() { | |||
| 44 | 48 | ||
| 45 | // TODO(Subv): Perform more research and implement all features of this engine. | 49 | // TODO(Subv): Perform more research and implement all features of this engine. |
| 46 | const LaunchDMA& launch = regs.launch_dma; | 50 | const LaunchDMA& launch = regs.launch_dma; |
| 47 | ASSERT(launch.remap_enable == 0); | ||
| 48 | ASSERT(launch.semaphore_type == LaunchDMA::SemaphoreType::NONE); | 51 | ASSERT(launch.semaphore_type == LaunchDMA::SemaphoreType::NONE); |
| 49 | ASSERT(launch.interrupt_type == LaunchDMA::InterruptType::NONE); | 52 | ASSERT(launch.interrupt_type == LaunchDMA::InterruptType::NONE); |
| 50 | ASSERT(launch.data_transfer_type == LaunchDMA::DataTransferType::NON_PIPELINED); | 53 | ASSERT(launch.data_transfer_type == LaunchDMA::DataTransferType::NON_PIPELINED); |
| @@ -77,11 +80,29 @@ void MaxwellDMA::CopyPitchToPitch() { | |||
| 77 | // When `multi_line_enable` bit is disabled the copy is performed as if we were copying a 1D | 80 | // When `multi_line_enable` bit is disabled the copy is performed as if we were copying a 1D |
| 78 | // buffer of length `line_length_in`. | 81 | // buffer of length `line_length_in`. |
| 79 | // Otherwise we copy a 2D image of dimensions (line_length_in, line_count). | 82 | // Otherwise we copy a 2D image of dimensions (line_length_in, line_count). |
| 83 | auto& accelerate = rasterizer->AccessAccelerateDMA(); | ||
| 80 | if (!regs.launch_dma.multi_line_enable) { | 84 | if (!regs.launch_dma.multi_line_enable) { |
| 81 | memory_manager.CopyBlock(regs.offset_out, regs.offset_in, regs.line_length_in); | 85 | const bool is_buffer_clear = regs.launch_dma.remap_enable != 0 && |
| 86 | regs.remap_const.dst_x == RemapConst::Swizzle::CONST_A; | ||
| 87 | // TODO: allow multisized components. | ||
| 88 | if (is_buffer_clear) { | ||
| 89 | ASSERT(regs.remap_const.component_size_minus_one == 3); | ||
| 90 | std::vector<u32> tmp_buffer(regs.line_length_in, regs.remap_consta_value); | ||
| 91 | memory_manager.WriteBlock(regs.offset_out, reinterpret_cast<u8*>(tmp_buffer.data()), | ||
| 92 | regs.line_length_in * sizeof(u32)); | ||
| 93 | return; | ||
| 94 | } | ||
| 95 | UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0); | ||
| 96 | if (!accelerate.BufferCopy(regs.offset_in, regs.offset_out, regs.line_length_in)) { | ||
| 97 | std::vector<u8> tmp_buffer(regs.line_length_in); | ||
| 98 | memory_manager.ReadBlockUnsafe(regs.offset_in, tmp_buffer.data(), regs.line_length_in); | ||
| 99 | memory_manager.WriteBlock(regs.offset_out, tmp_buffer.data(), regs.line_length_in); | ||
| 100 | } | ||
| 82 | return; | 101 | return; |
| 83 | } | 102 | } |
| 84 | 103 | ||
| 104 | UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0); | ||
| 105 | |||
| 85 | // Perform a line-by-line copy. | 106 | // Perform a line-by-line copy. |
| 86 | // We're going to take a subrect of size (line_length_in, line_count) from the source rectangle. | 107 | // We're going to take a subrect of size (line_length_in, line_count) from the source rectangle. |
| 87 | // There is no need to manually flush/invalidate the regions because CopyBlock does that for us. | 108 | // There is no need to manually flush/invalidate the regions because CopyBlock does that for us. |
| @@ -105,6 +126,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 105 | } | 126 | } |
| 106 | 127 | ||
| 107 | // Deswizzle the input and copy it over. | 128 | // Deswizzle the input and copy it over. |
| 129 | UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0); | ||
| 108 | const u32 bytes_per_pixel = regs.pitch_out / regs.line_length_in; | 130 | const u32 bytes_per_pixel = regs.pitch_out / regs.line_length_in; |
| 109 | const Parameters& src_params = regs.src_params; | 131 | const Parameters& src_params = regs.src_params; |
| 110 | const u32 width = src_params.width; | 132 | const u32 width = src_params.width; |
| @@ -134,6 +156,7 @@ void MaxwellDMA::CopyBlockLinearToPitch() { | |||
| 134 | 156 | ||
| 135 | void MaxwellDMA::CopyPitchToBlockLinear() { | 157 | void MaxwellDMA::CopyPitchToBlockLinear() { |
| 136 | UNIMPLEMENTED_IF_MSG(regs.dst_params.block_size.width != 0, "Block width is not one"); | 158 | UNIMPLEMENTED_IF_MSG(regs.dst_params.block_size.width != 0, "Block width is not one"); |
| 159 | UNIMPLEMENTED_IF(regs.launch_dma.remap_enable != 0); | ||
| 137 | 160 | ||
| 138 | const auto& dst_params = regs.dst_params; | 161 | const auto& dst_params = regs.dst_params; |
| 139 | const u32 bytes_per_pixel = regs.pitch_in / regs.line_length_in; | 162 | const u32 bytes_per_pixel = regs.pitch_in / regs.line_length_in; |
| @@ -156,13 +179,8 @@ void MaxwellDMA::CopyPitchToBlockLinear() { | |||
| 156 | write_buffer.resize(dst_size); | 179 | write_buffer.resize(dst_size); |
| 157 | } | 180 | } |
| 158 | 181 | ||
| 159 | if (Settings::IsGPULevelExtreme()) { | 182 | memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size); |
| 160 | memory_manager.ReadBlock(regs.offset_in, read_buffer.data(), src_size); | 183 | memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size); |
| 161 | memory_manager.ReadBlock(regs.offset_out, write_buffer.data(), dst_size); | ||
| 162 | } else { | ||
| 163 | memory_manager.ReadBlockUnsafe(regs.offset_in, read_buffer.data(), src_size); | ||
| 164 | memory_manager.ReadBlockUnsafe(regs.offset_out, write_buffer.data(), dst_size); | ||
| 165 | } | ||
| 166 | 184 | ||
| 167 | // If the input is linear and the output is tiled, swizzle the input and copy it over. | 185 | // If the input is linear and the output is tiled, swizzle the input and copy it over. |
| 168 | if (regs.dst_params.block_size.depth > 0) { | 186 | if (regs.dst_params.block_size.depth > 0) { |
diff --git a/src/video_core/engines/maxwell_dma.h b/src/video_core/engines/maxwell_dma.h index c77f02a22..4ed0d0996 100644 --- a/src/video_core/engines/maxwell_dma.h +++ b/src/video_core/engines/maxwell_dma.h | |||
| @@ -21,8 +21,18 @@ namespace Tegra { | |||
| 21 | class MemoryManager; | 21 | class MemoryManager; |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | namespace VideoCore { | ||
| 25 | class RasterizerInterface; | ||
| 26 | } | ||
| 27 | |||
| 24 | namespace Tegra::Engines { | 28 | namespace Tegra::Engines { |
| 25 | 29 | ||
| 30 | class AccelerateDMAInterface { | ||
| 31 | public: | ||
| 32 | /// Write the value to the register identified by method. | ||
| 33 | virtual bool BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) = 0; | ||
| 34 | }; | ||
| 35 | |||
| 26 | /** | 36 | /** |
| 27 | * This engine is known as gk104_copy. Documentation can be found in: | 37 | * This engine is known as gk104_copy. Documentation can be found in: |
| 28 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h | 38 | * https://github.com/NVIDIA/open-gpu-doc/blob/master/classes/dma-copy/clb0b5.h |
| @@ -187,6 +197,8 @@ public: | |||
| 187 | }; | 197 | }; |
| 188 | static_assert(sizeof(RemapConst) == 12); | 198 | static_assert(sizeof(RemapConst) == 12); |
| 189 | 199 | ||
| 200 | void BindRasterizer(VideoCore::RasterizerInterface* rasterizer); | ||
| 201 | |||
| 190 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); | 202 | explicit MaxwellDMA(Core::System& system_, MemoryManager& memory_manager_); |
| 191 | ~MaxwellDMA() override; | 203 | ~MaxwellDMA() override; |
| 192 | 204 | ||
| @@ -213,6 +225,7 @@ private: | |||
| 213 | Core::System& system; | 225 | Core::System& system; |
| 214 | 226 | ||
| 215 | MemoryManager& memory_manager; | 227 | MemoryManager& memory_manager; |
| 228 | VideoCore::RasterizerInterface* rasterizer; | ||
| 216 | 229 | ||
| 217 | std::vector<u8> read_buffer; | 230 | std::vector<u8> read_buffer; |
| 218 | std::vector<u8> write_buffer; | 231 | std::vector<u8> write_buffer; |
| @@ -240,7 +253,9 @@ private: | |||
| 240 | u32 pitch_out; | 253 | u32 pitch_out; |
| 241 | u32 line_length_in; | 254 | u32 line_length_in; |
| 242 | u32 line_count; | 255 | u32 line_count; |
| 243 | u32 reserved06[0xb8]; | 256 | u32 reserved06[0xb6]; |
| 257 | u32 remap_consta_value; | ||
| 258 | u32 remap_constb_value; | ||
| 244 | RemapConst remap_const; | 259 | RemapConst remap_const; |
| 245 | Parameters dst_params; | 260 | Parameters dst_params; |
| 246 | u32 reserved07[0x1]; | 261 | u32 reserved07[0x1]; |
diff --git a/src/video_core/fence_manager.h b/src/video_core/fence_manager.h index f055b61e9..34dc6c596 100644 --- a/src/video_core/fence_manager.h +++ b/src/video_core/fence_manager.h | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <queue> | 8 | #include <queue> |
| 9 | 9 | ||
| 10 | #include "common/common_types.h" | 10 | #include "common/common_types.h" |
| 11 | #include "common/settings.h" | ||
| 11 | #include "core/core.h" | 12 | #include "core/core.h" |
| 12 | #include "video_core/delayed_destruction_ring.h" | 13 | #include "video_core/delayed_destruction_ring.h" |
| 13 | #include "video_core/gpu.h" | 14 | #include "video_core/gpu.h" |
| @@ -53,6 +54,12 @@ public: | |||
| 53 | delayed_destruction_ring.Tick(); | 54 | delayed_destruction_ring.Tick(); |
| 54 | } | 55 | } |
| 55 | 56 | ||
| 57 | // Unlike other fences, this one doesn't | ||
| 58 | void SignalOrdering() { | ||
| 59 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 60 | buffer_cache.AccumulateFlushes(); | ||
| 61 | } | ||
| 62 | |||
| 56 | void SignalSemaphore(GPUVAddr addr, u32 value) { | 63 | void SignalSemaphore(GPUVAddr addr, u32 value) { |
| 57 | TryReleasePendingFences(); | 64 | TryReleasePendingFences(); |
| 58 | const bool should_flush = ShouldFlush(); | 65 | const bool should_flush = ShouldFlush(); |
diff --git a/src/video_core/gpu.cpp b/src/video_core/gpu.cpp index 35cc561be..ff024f530 100644 --- a/src/video_core/gpu.cpp +++ b/src/video_core/gpu.cpp | |||
| @@ -50,6 +50,7 @@ void GPU::BindRenderer(std::unique_ptr<VideoCore::RendererBase> renderer_) { | |||
| 50 | maxwell_3d->BindRasterizer(rasterizer); | 50 | maxwell_3d->BindRasterizer(rasterizer); |
| 51 | fermi_2d->BindRasterizer(rasterizer); | 51 | fermi_2d->BindRasterizer(rasterizer); |
| 52 | kepler_compute->BindRasterizer(rasterizer); | 52 | kepler_compute->BindRasterizer(rasterizer); |
| 53 | maxwell_dma->BindRasterizer(rasterizer); | ||
| 53 | } | 54 | } |
| 54 | 55 | ||
| 55 | Engines::Maxwell3D& GPU::Maxwell3D() { | 56 | Engines::Maxwell3D& GPU::Maxwell3D() { |
| @@ -268,11 +269,13 @@ void GPU::CallPullerMethod(const MethodCall& method_call) { | |||
| 268 | case BufferMethods::SemaphoreAddressHigh: | 269 | case BufferMethods::SemaphoreAddressHigh: |
| 269 | case BufferMethods::SemaphoreAddressLow: | 270 | case BufferMethods::SemaphoreAddressLow: |
| 270 | case BufferMethods::SemaphoreSequence: | 271 | case BufferMethods::SemaphoreSequence: |
| 271 | case BufferMethods::RefCnt: | ||
| 272 | case BufferMethods::UnkCacheFlush: | 272 | case BufferMethods::UnkCacheFlush: |
| 273 | case BufferMethods::WrcacheFlush: | 273 | case BufferMethods::WrcacheFlush: |
| 274 | case BufferMethods::FenceValue: | 274 | case BufferMethods::FenceValue: |
| 275 | break; | 275 | break; |
| 276 | case BufferMethods::RefCnt: | ||
| 277 | rasterizer->SignalReference(); | ||
| 278 | break; | ||
| 276 | case BufferMethods::FenceAction: | 279 | case BufferMethods::FenceAction: |
| 277 | ProcessFenceActionMethod(); | 280 | ProcessFenceActionMethod(); |
| 278 | break; | 281 | break; |
diff --git a/src/video_core/rasterizer_interface.h b/src/video_core/rasterizer_interface.h index 0cec4225b..58014c1c3 100644 --- a/src/video_core/rasterizer_interface.h +++ b/src/video_core/rasterizer_interface.h | |||
| @@ -15,7 +15,10 @@ | |||
| 15 | 15 | ||
| 16 | namespace Tegra { | 16 | namespace Tegra { |
| 17 | class MemoryManager; | 17 | class MemoryManager; |
| 18 | namespace Engines { | ||
| 19 | class AccelerateDMAInterface; | ||
| 18 | } | 20 | } |
| 21 | } // namespace Tegra | ||
| 19 | 22 | ||
| 20 | namespace VideoCore { | 23 | namespace VideoCore { |
| 21 | 24 | ||
| @@ -63,6 +66,9 @@ public: | |||
| 63 | /// Signal a GPU based syncpoint as a fence | 66 | /// Signal a GPU based syncpoint as a fence |
| 64 | virtual void SignalSyncPoint(u32 value) = 0; | 67 | virtual void SignalSyncPoint(u32 value) = 0; |
| 65 | 68 | ||
| 69 | /// Signal a GPU based reference as point | ||
| 70 | virtual void SignalReference() = 0; | ||
| 71 | |||
| 66 | /// Release all pending fences. | 72 | /// Release all pending fences. |
| 67 | virtual void ReleaseFences() = 0; | 73 | virtual void ReleaseFences() = 0; |
| 68 | 74 | ||
| @@ -116,6 +122,8 @@ public: | |||
| 116 | return false; | 122 | return false; |
| 117 | } | 123 | } |
| 118 | 124 | ||
| 125 | [[nodiscard]] virtual Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() = 0; | ||
| 126 | |||
| 119 | /// Attempt to use a faster method to display the framebuffer to screen | 127 | /// Attempt to use a faster method to display the framebuffer to screen |
| 120 | [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, | 128 | [[nodiscard]] virtual bool AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 121 | VAddr framebuffer_addr, u32 pixel_stride) { | 129 | VAddr framebuffer_addr, u32 pixel_stride) { |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.cpp b/src/video_core/renderer_opengl/gl_rasterizer.cpp index 07ad0e205..82c84127a 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.cpp +++ b/src/video_core/renderer_opengl/gl_rasterizer.cpp | |||
| @@ -171,7 +171,7 @@ RasterizerOpenGL::RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 171 | buffer_cache_runtime(device), | 171 | buffer_cache_runtime(device), |
| 172 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), | 172 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), |
| 173 | shader_cache(*this, emu_window_, gpu, maxwell3d, kepler_compute, gpu_memory, device), | 173 | shader_cache(*this, emu_window_, gpu, maxwell3d, kepler_compute, gpu_memory, device), |
| 174 | query_cache(*this, maxwell3d, gpu_memory), | 174 | query_cache(*this, maxwell3d, gpu_memory), accelerate_dma(buffer_cache), |
| 175 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), | 175 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache), |
| 176 | async_shaders(emu_window_) { | 176 | async_shaders(emu_window_) { |
| 177 | if (device.UseAsynchronousShaders()) { | 177 | if (device.UseAsynchronousShaders()) { |
| @@ -634,6 +634,13 @@ void RasterizerOpenGL::SignalSyncPoint(u32 value) { | |||
| 634 | fence_manager.SignalSyncPoint(value); | 634 | fence_manager.SignalSyncPoint(value); |
| 635 | } | 635 | } |
| 636 | 636 | ||
| 637 | void RasterizerOpenGL::SignalReference() { | ||
| 638 | if (!gpu.IsAsync()) { | ||
| 639 | return; | ||
| 640 | } | ||
| 641 | fence_manager.SignalOrdering(); | ||
| 642 | } | ||
| 643 | |||
| 637 | void RasterizerOpenGL::ReleaseFences() { | 644 | void RasterizerOpenGL::ReleaseFences() { |
| 638 | if (!gpu.IsAsync()) { | 645 | if (!gpu.IsAsync()) { |
| 639 | return; | 646 | return; |
| @@ -650,6 +657,7 @@ void RasterizerOpenGL::FlushAndInvalidateRegion(VAddr addr, u64 size) { | |||
| 650 | 657 | ||
| 651 | void RasterizerOpenGL::WaitForIdle() { | 658 | void RasterizerOpenGL::WaitForIdle() { |
| 652 | glMemoryBarrier(GL_ALL_BARRIER_BITS); | 659 | glMemoryBarrier(GL_ALL_BARRIER_BITS); |
| 660 | SignalReference(); | ||
| 653 | } | 661 | } |
| 654 | 662 | ||
| 655 | void RasterizerOpenGL::FragmentBarrier() { | 663 | void RasterizerOpenGL::FragmentBarrier() { |
| @@ -693,6 +701,10 @@ bool RasterizerOpenGL::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surf | |||
| 693 | return true; | 701 | return true; |
| 694 | } | 702 | } |
| 695 | 703 | ||
| 704 | Tegra::Engines::AccelerateDMAInterface& RasterizerOpenGL::AccessAccelerateDMA() { | ||
| 705 | return accelerate_dma; | ||
| 706 | } | ||
| 707 | |||
| 696 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 708 | bool RasterizerOpenGL::AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 697 | VAddr framebuffer_addr, u32 pixel_stride) { | 709 | VAddr framebuffer_addr, u32 pixel_stride) { |
| 698 | if (framebuffer_addr == 0) { | 710 | if (framebuffer_addr == 0) { |
| @@ -1388,4 +1400,11 @@ void RasterizerOpenGL::EndTransformFeedback() { | |||
| 1388 | glEndTransformFeedback(); | 1400 | glEndTransformFeedback(); |
| 1389 | } | 1401 | } |
| 1390 | 1402 | ||
| 1403 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} | ||
| 1404 | |||
| 1405 | bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { | ||
| 1406 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 1407 | return buffer_cache.DMACopy(src_address, dest_address, amount); | ||
| 1408 | } | ||
| 1409 | |||
| 1391 | } // namespace OpenGL | 1410 | } // namespace OpenGL |
diff --git a/src/video_core/renderer_opengl/gl_rasterizer.h b/src/video_core/renderer_opengl/gl_rasterizer.h index 482efed7a..ccee9ba33 100644 --- a/src/video_core/renderer_opengl/gl_rasterizer.h +++ b/src/video_core/renderer_opengl/gl_rasterizer.h | |||
| @@ -19,6 +19,7 @@ | |||
| 19 | #include "common/common_types.h" | 19 | #include "common/common_types.h" |
| 20 | #include "video_core/engines/const_buffer_info.h" | 20 | #include "video_core/engines/const_buffer_info.h" |
| 21 | #include "video_core/engines/maxwell_3d.h" | 21 | #include "video_core/engines/maxwell_3d.h" |
| 22 | #include "video_core/engines/maxwell_dma.h" | ||
| 22 | #include "video_core/rasterizer_accelerated.h" | 23 | #include "video_core/rasterizer_accelerated.h" |
| 23 | #include "video_core/rasterizer_interface.h" | 24 | #include "video_core/rasterizer_interface.h" |
| 24 | #include "video_core/renderer_opengl/gl_buffer_cache.h" | 25 | #include "video_core/renderer_opengl/gl_buffer_cache.h" |
| @@ -58,6 +59,16 @@ struct BindlessSSBO { | |||
| 58 | }; | 59 | }; |
| 59 | static_assert(sizeof(BindlessSSBO) * CHAR_BIT == 128); | 60 | static_assert(sizeof(BindlessSSBO) * CHAR_BIT == 128); |
| 60 | 61 | ||
| 62 | class AccelerateDMA : public Tegra::Engines::AccelerateDMAInterface { | ||
| 63 | public: | ||
| 64 | explicit AccelerateDMA(BufferCache& buffer_cache); | ||
| 65 | |||
| 66 | bool BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) override; | ||
| 67 | |||
| 68 | private: | ||
| 69 | BufferCache& buffer_cache; | ||
| 70 | }; | ||
| 71 | |||
| 61 | class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { | 72 | class RasterizerOpenGL : public VideoCore::RasterizerAccelerated { |
| 62 | public: | 73 | public: |
| 63 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 74 | explicit RasterizerOpenGL(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| @@ -83,6 +94,7 @@ public: | |||
| 83 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; | 94 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; |
| 84 | void SignalSemaphore(GPUVAddr addr, u32 value) override; | 95 | void SignalSemaphore(GPUVAddr addr, u32 value) override; |
| 85 | void SignalSyncPoint(u32 value) override; | 96 | void SignalSyncPoint(u32 value) override; |
| 97 | void SignalReference() override; | ||
| 86 | void ReleaseFences() override; | 98 | void ReleaseFences() override; |
| 87 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | 99 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; |
| 88 | void WaitForIdle() override; | 100 | void WaitForIdle() override; |
| @@ -93,6 +105,7 @@ public: | |||
| 93 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | 105 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, |
| 94 | const Tegra::Engines::Fermi2D::Surface& dst, | 106 | const Tegra::Engines::Fermi2D::Surface& dst, |
| 95 | const Tegra::Engines::Fermi2D::Config& copy_config) override; | 107 | const Tegra::Engines::Fermi2D::Config& copy_config) override; |
| 108 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | ||
| 96 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 109 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, |
| 97 | u32 pixel_stride) override; | 110 | u32 pixel_stride) override; |
| 98 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, | 111 | void LoadDiskResources(u64 title_id, std::stop_token stop_loading, |
| @@ -233,6 +246,7 @@ private: | |||
| 233 | BufferCache buffer_cache; | 246 | BufferCache buffer_cache; |
| 234 | ShaderCacheOpenGL shader_cache; | 247 | ShaderCacheOpenGL shader_cache; |
| 235 | QueryCache query_cache; | 248 | QueryCache query_cache; |
| 249 | AccelerateDMA accelerate_dma; | ||
| 236 | FenceManagerOpenGL fence_manager; | 250 | FenceManagerOpenGL fence_manager; |
| 237 | 251 | ||
| 238 | VideoCommon::Shader::AsyncShaders async_shaders; | 252 | VideoCommon::Shader::AsyncShaders async_shaders; |
diff --git a/src/video_core/renderer_vulkan/renderer_vulkan.cpp b/src/video_core/renderer_vulkan/renderer_vulkan.cpp index 3986eb172..bec3a81d9 100644 --- a/src/video_core/renderer_vulkan/renderer_vulkan.cpp +++ b/src/video_core/renderer_vulkan/renderer_vulkan.cpp | |||
| @@ -103,7 +103,7 @@ RendererVulkan::RendererVulkan(Core::TelemetrySession& telemetry_session_, | |||
| 103 | gpu(gpu_), | 103 | gpu(gpu_), |
| 104 | library(OpenLibrary()), | 104 | library(OpenLibrary()), |
| 105 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, | 105 | instance(CreateInstance(library, dld, VK_API_VERSION_1_1, render_window.GetWindowInfo().type, |
| 106 | true, Settings::values.renderer_debug)), | 106 | true, Settings::values.renderer_debug.GetValue())), |
| 107 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), | 107 | debug_callback(Settings::values.renderer_debug ? CreateDebugCallback(instance) : nullptr), |
| 108 | surface(CreateSurface(instance, render_window)), | 108 | surface(CreateSurface(instance, render_window)), |
| 109 | device(CreateDevice(instance, dld, *surface)), | 109 | device(CreateDevice(instance, dld, *surface)), |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.cpp b/src/video_core/renderer_vulkan/vk_rasterizer.cpp index bd4d649cc..e378a5679 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.cpp +++ b/src/video_core/renderer_vulkan/vk_rasterizer.cpp | |||
| @@ -251,7 +251,7 @@ RasterizerVulkan::RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra | |||
| 251 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), | 251 | buffer_cache(*this, maxwell3d, kepler_compute, gpu_memory, cpu_memory_, buffer_cache_runtime), |
| 252 | pipeline_cache(*this, gpu, maxwell3d, kepler_compute, gpu_memory, device, scheduler, | 252 | pipeline_cache(*this, gpu, maxwell3d, kepler_compute, gpu_memory, device, scheduler, |
| 253 | descriptor_pool, update_descriptor_queue), | 253 | descriptor_pool, update_descriptor_queue), |
| 254 | query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, | 254 | query_cache{*this, maxwell3d, gpu_memory, device, scheduler}, accelerate_dma{buffer_cache}, |
| 255 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), | 255 | fence_manager(*this, gpu, texture_cache, buffer_cache, query_cache, device, scheduler), |
| 256 | wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) { | 256 | wfi_event(device.GetLogical().CreateEvent()), async_shaders(emu_window_) { |
| 257 | scheduler.SetQueryCache(query_cache); | 257 | scheduler.SetQueryCache(query_cache); |
| @@ -580,6 +580,13 @@ void RasterizerVulkan::SignalSyncPoint(u32 value) { | |||
| 580 | fence_manager.SignalSyncPoint(value); | 580 | fence_manager.SignalSyncPoint(value); |
| 581 | } | 581 | } |
| 582 | 582 | ||
| 583 | void RasterizerVulkan::SignalReference() { | ||
| 584 | if (!gpu.IsAsync()) { | ||
| 585 | return; | ||
| 586 | } | ||
| 587 | fence_manager.SignalOrdering(); | ||
| 588 | } | ||
| 589 | |||
| 583 | void RasterizerVulkan::ReleaseFences() { | 590 | void RasterizerVulkan::ReleaseFences() { |
| 584 | if (!gpu.IsAsync()) { | 591 | if (!gpu.IsAsync()) { |
| 585 | return; | 592 | return; |
| @@ -612,6 +619,7 @@ void RasterizerVulkan::WaitForIdle() { | |||
| 612 | cmdbuf.SetEvent(event, flags); | 619 | cmdbuf.SetEvent(event, flags); |
| 613 | cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {}); | 620 | cmdbuf.WaitEvents(event, flags, VK_PIPELINE_STAGE_TOP_OF_PIPE_BIT, {}, {}, {}); |
| 614 | }); | 621 | }); |
| 622 | SignalReference(); | ||
| 615 | } | 623 | } |
| 616 | 624 | ||
| 617 | void RasterizerVulkan::FragmentBarrier() { | 625 | void RasterizerVulkan::FragmentBarrier() { |
| @@ -652,6 +660,10 @@ bool RasterizerVulkan::AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surf | |||
| 652 | return true; | 660 | return true; |
| 653 | } | 661 | } |
| 654 | 662 | ||
| 663 | Tegra::Engines::AccelerateDMAInterface& RasterizerVulkan::AccessAccelerateDMA() { | ||
| 664 | return accelerate_dma; | ||
| 665 | } | ||
| 666 | |||
| 655 | bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, | 667 | bool RasterizerVulkan::AccelerateDisplay(const Tegra::FramebufferConfig& config, |
| 656 | VAddr framebuffer_addr, u32 pixel_stride) { | 668 | VAddr framebuffer_addr, u32 pixel_stride) { |
| 657 | if (!framebuffer_addr) { | 669 | if (!framebuffer_addr) { |
| @@ -690,6 +702,13 @@ void RasterizerVulkan::FlushWork() { | |||
| 690 | draw_counter = 0; | 702 | draw_counter = 0; |
| 691 | } | 703 | } |
| 692 | 704 | ||
| 705 | AccelerateDMA::AccelerateDMA(BufferCache& buffer_cache_) : buffer_cache{buffer_cache_} {} | ||
| 706 | |||
| 707 | bool AccelerateDMA::BufferCopy(GPUVAddr src_address, GPUVAddr dest_address, u64 amount) { | ||
| 708 | std::scoped_lock lock{buffer_cache.mutex}; | ||
| 709 | return buffer_cache.DMACopy(src_address, dest_address, amount); | ||
| 710 | } | ||
| 711 | |||
| 693 | void RasterizerVulkan::SetupShaderDescriptors( | 712 | void RasterizerVulkan::SetupShaderDescriptors( |
| 694 | const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders, bool is_indexed) { | 713 | const std::array<Shader*, Maxwell::MaxShaderProgram>& shaders, bool is_indexed) { |
| 695 | image_view_indices.clear(); | 714 | image_view_indices.clear(); |
diff --git a/src/video_core/renderer_vulkan/vk_rasterizer.h b/src/video_core/renderer_vulkan/vk_rasterizer.h index 41459c5c5..3a78de258 100644 --- a/src/video_core/renderer_vulkan/vk_rasterizer.h +++ b/src/video_core/renderer_vulkan/vk_rasterizer.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <boost/container/static_vector.hpp> | 13 | #include <boost/container/static_vector.hpp> |
| 14 | 14 | ||
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "video_core/engines/maxwell_dma.h" | ||
| 16 | #include "video_core/rasterizer_accelerated.h" | 17 | #include "video_core/rasterizer_accelerated.h" |
| 17 | #include "video_core/rasterizer_interface.h" | 18 | #include "video_core/rasterizer_interface.h" |
| 18 | #include "video_core/renderer_vulkan/blit_image.h" | 19 | #include "video_core/renderer_vulkan/blit_image.h" |
| @@ -49,6 +50,16 @@ struct VKScreenInfo; | |||
| 49 | 50 | ||
| 50 | class StateTracker; | 51 | class StateTracker; |
| 51 | 52 | ||
| 53 | class AccelerateDMA : public Tegra::Engines::AccelerateDMAInterface { | ||
| 54 | public: | ||
| 55 | explicit AccelerateDMA(BufferCache& buffer_cache); | ||
| 56 | |||
| 57 | bool BufferCopy(GPUVAddr start_address, GPUVAddr end_address, u64 amount) override; | ||
| 58 | |||
| 59 | private: | ||
| 60 | BufferCache& buffer_cache; | ||
| 61 | }; | ||
| 62 | |||
| 52 | class RasterizerVulkan final : public VideoCore::RasterizerAccelerated { | 63 | class RasterizerVulkan final : public VideoCore::RasterizerAccelerated { |
| 53 | public: | 64 | public: |
| 54 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, | 65 | explicit RasterizerVulkan(Core::Frontend::EmuWindow& emu_window_, Tegra::GPU& gpu_, |
| @@ -75,6 +86,7 @@ public: | |||
| 75 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; | 86 | void ModifyGPUMemory(GPUVAddr addr, u64 size) override; |
| 76 | void SignalSemaphore(GPUVAddr addr, u32 value) override; | 87 | void SignalSemaphore(GPUVAddr addr, u32 value) override; |
| 77 | void SignalSyncPoint(u32 value) override; | 88 | void SignalSyncPoint(u32 value) override; |
| 89 | void SignalReference() override; | ||
| 78 | void ReleaseFences() override; | 90 | void ReleaseFences() override; |
| 79 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; | 91 | void FlushAndInvalidateRegion(VAddr addr, u64 size) override; |
| 80 | void WaitForIdle() override; | 92 | void WaitForIdle() override; |
| @@ -85,6 +97,7 @@ public: | |||
| 85 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, | 97 | bool AccelerateSurfaceCopy(const Tegra::Engines::Fermi2D::Surface& src, |
| 86 | const Tegra::Engines::Fermi2D::Surface& dst, | 98 | const Tegra::Engines::Fermi2D::Surface& dst, |
| 87 | const Tegra::Engines::Fermi2D::Config& copy_config) override; | 99 | const Tegra::Engines::Fermi2D::Config& copy_config) override; |
| 100 | Tegra::Engines::AccelerateDMAInterface& AccessAccelerateDMA() override; | ||
| 88 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, | 101 | bool AccelerateDisplay(const Tegra::FramebufferConfig& config, VAddr framebuffer_addr, |
| 89 | u32 pixel_stride) override; | 102 | u32 pixel_stride) override; |
| 90 | 103 | ||
| @@ -185,6 +198,7 @@ private: | |||
| 185 | BufferCache buffer_cache; | 198 | BufferCache buffer_cache; |
| 186 | VKPipelineCache pipeline_cache; | 199 | VKPipelineCache pipeline_cache; |
| 187 | VKQueryCache query_cache; | 200 | VKQueryCache query_cache; |
| 201 | AccelerateDMA accelerate_dma; | ||
| 188 | VKFenceManager fence_manager; | 202 | VKFenceManager fence_manager; |
| 189 | 203 | ||
| 190 | vk::Event wfi_event; | 204 | vk::Event wfi_event; |
diff --git a/src/video_core/texture_cache/texture_cache.h b/src/video_core/texture_cache/texture_cache.h index e3542301e..01de2d498 100644 --- a/src/video_core/texture_cache/texture_cache.h +++ b/src/video_core/texture_cache/texture_cache.h | |||
| @@ -159,9 +159,7 @@ public: | |||
| 159 | /// Blit an image with the given parameters | 159 | /// Blit an image with the given parameters |
| 160 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 160 | void BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 161 | const Tegra::Engines::Fermi2D::Surface& src, | 161 | const Tegra::Engines::Fermi2D::Surface& src, |
| 162 | const Tegra::Engines::Fermi2D::Config& copy, | 162 | const Tegra::Engines::Fermi2D::Config& copy); |
| 163 | std::optional<Region2D> src_region_override = {}, | ||
| 164 | std::optional<Region2D> dst_region_override = {}); | ||
| 165 | 163 | ||
| 166 | /// Invalidate the contents of the color buffer index | 164 | /// Invalidate the contents of the color buffer index |
| 167 | /// These contents become unspecified, the cache can assume aggressive optimizations. | 165 | /// These contents become unspecified, the cache can assume aggressive optimizations. |
| @@ -760,9 +758,7 @@ void TextureCache<P>::UnmapGPUMemory(GPUVAddr gpu_addr, size_t size) { | |||
| 760 | template <class P> | 758 | template <class P> |
| 761 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | 759 | void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, |
| 762 | const Tegra::Engines::Fermi2D::Surface& src, | 760 | const Tegra::Engines::Fermi2D::Surface& src, |
| 763 | const Tegra::Engines::Fermi2D::Config& copy, | 761 | const Tegra::Engines::Fermi2D::Config& copy) { |
| 764 | std::optional<Region2D> src_override, | ||
| 765 | std::optional<Region2D> dst_override) { | ||
| 766 | const BlitImages images = GetBlitImages(dst, src); | 762 | const BlitImages images = GetBlitImages(dst, src); |
| 767 | const ImageId dst_id = images.dst_id; | 763 | const ImageId dst_id = images.dst_id; |
| 768 | const ImageId src_id = images.src_id; | 764 | const ImageId src_id = images.src_id; |
| @@ -773,47 +769,25 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 773 | const ImageBase& src_image = slot_images[src_id]; | 769 | const ImageBase& src_image = slot_images[src_id]; |
| 774 | 770 | ||
| 775 | // TODO: Deduplicate | 771 | // TODO: Deduplicate |
| 776 | const std::optional dst_base = dst_image.TryFindBase(dst.Address()); | ||
| 777 | const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}}; | ||
| 778 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); | ||
| 779 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); | ||
| 780 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); | ||
| 781 | |||
| 782 | // out of bounds texture blit checking | ||
| 783 | const bool use_override = src_override.has_value(); | ||
| 784 | const s32 src_x0 = copy.src_x0 >> src_samples_x; | ||
| 785 | s32 src_x1 = use_override ? src_override->end.x : copy.src_x1 >> src_samples_x; | ||
| 786 | const s32 src_y0 = copy.src_y0 >> src_samples_y; | ||
| 787 | const s32 src_y1 = copy.src_y1 >> src_samples_y; | ||
| 788 | |||
| 789 | const auto src_width = static_cast<s32>(src_image.info.size.width); | ||
| 790 | const bool width_oob = src_x1 > src_width; | ||
| 791 | const auto width_diff = width_oob ? src_x1 - src_width : 0; | ||
| 792 | if (width_oob) { | ||
| 793 | src_x1 = src_width; | ||
| 794 | } | ||
| 795 | |||
| 796 | const Region2D src_dimensions{ | ||
| 797 | Offset2D{.x = src_x0, .y = src_y0}, | ||
| 798 | Offset2D{.x = src_x1, .y = src_y1}, | ||
| 799 | }; | ||
| 800 | const auto src_region = use_override ? *src_override : src_dimensions; | ||
| 801 | |||
| 802 | const std::optional src_base = src_image.TryFindBase(src.Address()); | 772 | const std::optional src_base = src_image.TryFindBase(src.Address()); |
| 803 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; | 773 | const SubresourceRange src_range{.base = src_base.value(), .extent = {1, 1}}; |
| 804 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); | 774 | const ImageViewInfo src_view_info(ImageViewType::e2D, images.src_format, src_range); |
| 805 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); | 775 | const auto [src_framebuffer_id, src_view_id] = RenderTargetFromImage(src_id, src_view_info); |
| 806 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); | 776 | const auto [src_samples_x, src_samples_y] = SamplesLog2(src_image.info.num_samples); |
| 777 | const Region2D src_region{ | ||
| 778 | Offset2D{.x = copy.src_x0 >> src_samples_x, .y = copy.src_y0 >> src_samples_y}, | ||
| 779 | Offset2D{.x = copy.src_x1 >> src_samples_x, .y = copy.src_y1 >> src_samples_y}, | ||
| 780 | }; | ||
| 807 | 781 | ||
| 808 | const s32 dst_x0 = copy.dst_x0 >> dst_samples_x; | 782 | const std::optional dst_base = dst_image.TryFindBase(dst.Address()); |
| 809 | const s32 dst_x1 = copy.dst_x1 >> dst_samples_x; | 783 | const SubresourceRange dst_range{.base = dst_base.value(), .extent = {1, 1}}; |
| 810 | const s32 dst_y0 = copy.dst_y0 >> dst_samples_y; | 784 | const ImageViewInfo dst_view_info(ImageViewType::e2D, images.dst_format, dst_range); |
| 811 | const s32 dst_y1 = copy.dst_y1 >> dst_samples_y; | 785 | const auto [dst_framebuffer_id, dst_view_id] = RenderTargetFromImage(dst_id, dst_view_info); |
| 812 | const Region2D dst_dimensions{ | 786 | const auto [dst_samples_x, dst_samples_y] = SamplesLog2(dst_image.info.num_samples); |
| 813 | Offset2D{.x = dst_x0, .y = dst_y0}, | 787 | const Region2D dst_region{ |
| 814 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y1}, | 788 | Offset2D{.x = copy.dst_x0 >> dst_samples_x, .y = copy.dst_y0 >> dst_samples_y}, |
| 789 | Offset2D{.x = copy.dst_x1 >> dst_samples_x, .y = copy.dst_y1 >> dst_samples_y}, | ||
| 815 | }; | 790 | }; |
| 816 | const auto dst_region = use_override ? *dst_override : dst_dimensions; | ||
| 817 | 791 | ||
| 818 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. | 792 | // Always call this after src_framebuffer_id was queried, as the address might be invalidated. |
| 819 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; | 793 | Framebuffer* const dst_framebuffer = &slot_framebuffers[dst_framebuffer_id]; |
| @@ -830,21 +804,6 @@ void TextureCache<P>::BlitImage(const Tegra::Engines::Fermi2D::Surface& dst, | |||
| 830 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, | 804 | runtime.BlitImage(dst_framebuffer, dst_view, src_view, dst_region, src_region, copy.filter, |
| 831 | copy.operation); | 805 | copy.operation); |
| 832 | } | 806 | } |
| 833 | |||
| 834 | if (width_oob) { | ||
| 835 | // Continue copy of the oob region of the texture on the next row | ||
| 836 | auto oob_src = src; | ||
| 837 | oob_src.height++; | ||
| 838 | const Region2D src_region_override{ | ||
| 839 | Offset2D{.x = 0, .y = src_y0 + 1}, | ||
| 840 | Offset2D{.x = width_diff, .y = src_y1 + 1}, | ||
| 841 | }; | ||
| 842 | const Region2D dst_region_override{ | ||
| 843 | Offset2D{.x = dst_x1 - width_diff, .y = dst_y0}, | ||
| 844 | Offset2D{.x = dst_x1, .y = dst_y1}, | ||
| 845 | }; | ||
| 846 | BlitImage(dst, oob_src, copy, src_region_override, dst_region_override); | ||
| 847 | } | ||
| 848 | } | 807 | } |
| 849 | 808 | ||
| 850 | template <class P> | 809 | template <class P> |
diff --git a/src/video_core/texture_cache/types.h b/src/video_core/texture_cache/types.h index 9fbdc1ac6..47a11cb2f 100644 --- a/src/video_core/texture_cache/types.h +++ b/src/video_core/texture_cache/types.h | |||
| @@ -133,8 +133,8 @@ struct BufferImageCopy { | |||
| 133 | }; | 133 | }; |
| 134 | 134 | ||
| 135 | struct BufferCopy { | 135 | struct BufferCopy { |
| 136 | size_t src_offset; | 136 | u64 src_offset; |
| 137 | size_t dst_offset; | 137 | u64 dst_offset; |
| 138 | size_t size; | 138 | size_t size; |
| 139 | }; | 139 | }; |
| 140 | 140 | ||
diff --git a/src/yuzu/CMakeLists.txt b/src/yuzu/CMakeLists.txt index 634fe66a5..f870b33b1 100644 --- a/src/yuzu/CMakeLists.txt +++ b/src/yuzu/CMakeLists.txt | |||
| @@ -52,6 +52,9 @@ add_executable(yuzu | |||
| 52 | configuration/configure_debug_controller.cpp | 52 | configuration/configure_debug_controller.cpp |
| 53 | configuration/configure_debug_controller.h | 53 | configuration/configure_debug_controller.h |
| 54 | configuration/configure_debug_controller.ui | 54 | configuration/configure_debug_controller.ui |
| 55 | configuration/configure_debug_tab.cpp | ||
| 56 | configuration/configure_debug_tab.h | ||
| 57 | configuration/configure_debug_tab.ui | ||
| 55 | configuration/configure_dialog.cpp | 58 | configuration/configure_dialog.cpp |
| 56 | configuration/configure_dialog.h | 59 | configuration/configure_dialog.h |
| 57 | configuration/configure_filesystem.cpp | 60 | configuration/configure_filesystem.cpp |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index 62bafc453..8c71ad5c1 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -272,6 +272,91 @@ void Config::Initialize(const std::string& config_name) { | |||
| 272 | } | 272 | } |
| 273 | } | 273 | } |
| 274 | 274 | ||
| 275 | /* {Read,Write}BasicSetting and WriteGlobalSetting templates must be defined here before their | ||
| 276 | * usages later in this file. This allows explicit definition of some types that don't work | ||
| 277 | * nicely with the general version. | ||
| 278 | */ | ||
| 279 | |||
| 280 | // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant, nor | ||
| 281 | // can it implicitly convert a QVariant back to a {std::,Q}string | ||
| 282 | template <> | ||
| 283 | void Config::ReadBasicSetting(Settings::BasicSetting<std::string>& setting) { | ||
| 284 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 285 | const auto default_value = QString::fromStdString(setting.GetDefault()); | ||
| 286 | if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||
| 287 | setting.SetValue(default_value.toStdString()); | ||
| 288 | } else { | ||
| 289 | setting.SetValue(qt_config->value(name, default_value).toString().toStdString()); | ||
| 290 | } | ||
| 291 | } | ||
| 292 | |||
| 293 | template <typename Type> | ||
| 294 | void Config::ReadBasicSetting(Settings::BasicSetting<Type>& setting) { | ||
| 295 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 296 | const Type default_value = setting.GetDefault(); | ||
| 297 | if (qt_config->value(name + QStringLiteral("/default"), false).toBool()) { | ||
| 298 | setting.SetValue(default_value); | ||
| 299 | } else { | ||
| 300 | setting.SetValue( | ||
| 301 | static_cast<QVariant>(qt_config->value(name, default_value)).value<Type>()); | ||
| 302 | } | ||
| 303 | } | ||
| 304 | |||
| 305 | // Explicit std::string definition: Qt can't implicitly convert a std::string to a QVariant | ||
| 306 | template <> | ||
| 307 | void Config::WriteBasicSetting(const Settings::BasicSetting<std::string>& setting) { | ||
| 308 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 309 | const std::string& value = setting.GetValue(); | ||
| 310 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 311 | qt_config->setValue(name, QString::fromStdString(value)); | ||
| 312 | } | ||
| 313 | |||
| 314 | // Explicit float definition: use a double as Qt doesn't write legible floats to config files | ||
| 315 | template <> | ||
| 316 | void Config::WriteBasicSetting(const Settings::BasicSetting<float>& setting) { | ||
| 317 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 318 | const double value = setting.GetValue(); | ||
| 319 | qt_config->setValue(name + QStringLiteral("/default"), | ||
| 320 | setting.GetValue() == setting.GetDefault()); | ||
| 321 | qt_config->setValue(name, value); | ||
| 322 | } | ||
| 323 | |||
| 324 | template <typename Type> | ||
| 325 | void Config::WriteBasicSetting(const Settings::BasicSetting<Type>& setting) { | ||
| 326 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 327 | const Type value = setting.GetValue(); | ||
| 328 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 329 | qt_config->setValue(name, value); | ||
| 330 | } | ||
| 331 | |||
| 332 | // Explicit float definition: use a double as Qt doesn't write legible floats to config files | ||
| 333 | template <> | ||
| 334 | void Config::WriteGlobalSetting(const Settings::Setting<float>& setting) { | ||
| 335 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 336 | const double value = setting.GetValue(global); | ||
| 337 | if (!global) { | ||
| 338 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 339 | } | ||
| 340 | if (global || !setting.UsingGlobal()) { | ||
| 341 | qt_config->setValue(name + QStringLiteral("/default"), | ||
| 342 | setting.GetValue(global) == setting.GetDefault()); | ||
| 343 | qt_config->setValue(name, value); | ||
| 344 | } | ||
| 345 | } | ||
| 346 | |||
| 347 | template <typename Type> | ||
| 348 | void Config::WriteGlobalSetting(const Settings::Setting<Type>& setting) { | ||
| 349 | const QString name = QString::fromStdString(setting.GetLabel()); | ||
| 350 | const Type& value = setting.GetValue(global); | ||
| 351 | if (!global) { | ||
| 352 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 353 | } | ||
| 354 | if (global || !setting.UsingGlobal()) { | ||
| 355 | qt_config->setValue(name + QStringLiteral("/default"), value == setting.GetDefault()); | ||
| 356 | qt_config->setValue(name, value); | ||
| 357 | } | ||
| 358 | } | ||
| 359 | |||
| 275 | void Config::ReadPlayerValue(std::size_t player_index) { | 360 | void Config::ReadPlayerValue(std::size_t player_index) { |
| 276 | const QString player_prefix = [this, player_index] { | 361 | const QString player_prefix = [this, player_index] { |
| 277 | if (type == ConfigType::InputProfile) { | 362 | if (type == ConfigType::InputProfile) { |
| @@ -395,8 +480,7 @@ void Config::ReadPlayerValue(std::size_t player_index) { | |||
| 395 | } | 480 | } |
| 396 | 481 | ||
| 397 | void Config::ReadDebugValues() { | 482 | void Config::ReadDebugValues() { |
| 398 | Settings::values.debug_pad_enabled = | 483 | ReadBasicSetting(Settings::values.debug_pad_enabled); |
| 399 | ReadSetting(QStringLiteral("debug_pad_enabled"), false).toBool(); | ||
| 400 | 484 | ||
| 401 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 485 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 402 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 486 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| @@ -432,8 +516,7 @@ void Config::ReadDebugValues() { | |||
| 432 | } | 516 | } |
| 433 | 517 | ||
| 434 | void Config::ReadKeyboardValues() { | 518 | void Config::ReadKeyboardValues() { |
| 435 | Settings::values.keyboard_enabled = | 519 | ReadBasicSetting(Settings::values.keyboard_enabled); |
| 436 | ReadSetting(QStringLiteral("keyboard_enabled"), false).toBool(); | ||
| 437 | 520 | ||
| 438 | std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), | 521 | std::transform(default_keyboard_keys.begin(), default_keyboard_keys.end(), |
| 439 | Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); | 522 | Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); |
| @@ -446,7 +529,7 @@ void Config::ReadKeyboardValues() { | |||
| 446 | } | 529 | } |
| 447 | 530 | ||
| 448 | void Config::ReadMouseValues() { | 531 | void Config::ReadMouseValues() { |
| 449 | Settings::values.mouse_enabled = ReadSetting(QStringLiteral("mouse_enabled"), false).toBool(); | 532 | ReadBasicSetting(Settings::values.mouse_enabled); |
| 450 | 533 | ||
| 451 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { | 534 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { |
| 452 | const std::string default_param = | 535 | const std::string default_param = |
| @@ -481,18 +564,11 @@ void Config::ReadAudioValues() { | |||
| 481 | qt_config->beginGroup(QStringLiteral("Audio")); | 564 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 482 | 565 | ||
| 483 | if (global) { | 566 | if (global) { |
| 484 | Settings::values.sink_id = | 567 | ReadBasicSetting(Settings::values.audio_device_id); |
| 485 | ReadSetting(QStringLiteral("output_engine"), QStringLiteral("auto")) | 568 | ReadBasicSetting(Settings::values.sink_id); |
| 486 | .toString() | ||
| 487 | .toStdString(); | ||
| 488 | Settings::values.audio_device_id = | ||
| 489 | ReadSetting(QStringLiteral("output_device"), QStringLiteral("auto")) | ||
| 490 | .toString() | ||
| 491 | .toStdString(); | ||
| 492 | } | 569 | } |
| 493 | ReadSettingGlobal(Settings::values.enable_audio_stretching, | 570 | ReadGlobalSetting(Settings::values.enable_audio_stretching); |
| 494 | QStringLiteral("enable_audio_stretching"), true); | 571 | ReadGlobalSetting(Settings::values.volume); |
| 495 | ReadSettingGlobal(Settings::values.volume, QStringLiteral("volume"), 1); | ||
| 496 | 572 | ||
| 497 | qt_config->endGroup(); | 573 | qt_config->endGroup(); |
| 498 | } | 574 | } |
| @@ -509,13 +585,11 @@ void Config::ReadControlValues() { | |||
| 509 | ReadTouchscreenValues(); | 585 | ReadTouchscreenValues(); |
| 510 | ReadMotionTouchValues(); | 586 | ReadMotionTouchValues(); |
| 511 | 587 | ||
| 512 | Settings::values.emulate_analog_keyboard = | 588 | ReadBasicSetting(Settings::values.emulate_analog_keyboard); |
| 513 | ReadSetting(QStringLiteral("emulate_analog_keyboard"), false).toBool(); | ||
| 514 | Settings::values.mouse_panning = false; | 589 | Settings::values.mouse_panning = false; |
| 515 | Settings::values.mouse_panning_sensitivity = | 590 | ReadBasicSetting(Settings::values.mouse_panning_sensitivity); |
| 516 | ReadSetting(QStringLiteral("mouse_panning_sensitivity"), 1).toFloat(); | ||
| 517 | 591 | ||
| 518 | ReadSettingGlobal(Settings::values.use_docked_mode, QStringLiteral("use_docked_mode"), true); | 592 | ReadGlobalSetting(Settings::values.use_docked_mode); |
| 519 | 593 | ||
| 520 | // Disable docked mode if handheld is selected | 594 | // Disable docked mode if handheld is selected |
| 521 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; | 595 | const auto controller_type = Settings::values.players.GetValue()[0].controller_type; |
| @@ -523,11 +597,9 @@ void Config::ReadControlValues() { | |||
| 523 | Settings::values.use_docked_mode.SetValue(false); | 597 | Settings::values.use_docked_mode.SetValue(false); |
| 524 | } | 598 | } |
| 525 | 599 | ||
| 526 | ReadSettingGlobal(Settings::values.vibration_enabled, QStringLiteral("vibration_enabled"), | 600 | ReadGlobalSetting(Settings::values.vibration_enabled); |
| 527 | true); | 601 | ReadGlobalSetting(Settings::values.enable_accurate_vibrations); |
| 528 | ReadSettingGlobal(Settings::values.enable_accurate_vibrations, | 602 | ReadGlobalSetting(Settings::values.motion_enabled); |
| 529 | QStringLiteral("enable_accurate_vibrations"), false); | ||
| 530 | ReadSettingGlobal(Settings::values.motion_enabled, QStringLiteral("motion_enabled"), true); | ||
| 531 | 603 | ||
| 532 | qt_config->endGroup(); | 604 | qt_config->endGroup(); |
| 533 | } | 605 | } |
| @@ -565,33 +637,19 @@ void Config::ReadMotionTouchValues() { | |||
| 565 | } | 637 | } |
| 566 | qt_config->endArray(); | 638 | qt_config->endArray(); |
| 567 | 639 | ||
| 568 | Settings::values.motion_device = | 640 | ReadBasicSetting(Settings::values.motion_device); |
| 569 | ReadSetting(QStringLiteral("motion_device"), | 641 | ReadBasicSetting(Settings::values.touch_device); |
| 570 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")) | 642 | ReadBasicSetting(Settings::values.use_touch_from_button); |
| 571 | .toString() | 643 | ReadBasicSetting(Settings::values.touch_from_button_map_index); |
| 572 | .toStdString(); | 644 | Settings::values.touch_from_button_map_index = std::clamp( |
| 573 | Settings::values.touch_device = | 645 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); |
| 574 | ReadSetting(QStringLiteral("touch_device"), | 646 | ReadBasicSetting(Settings::values.udp_input_servers); |
| 575 | QStringLiteral("min_x:100,min_y:50,max_x:1800,max_y:850")) | ||
| 576 | .toString() | ||
| 577 | .toStdString(); | ||
| 578 | Settings::values.use_touch_from_button = | ||
| 579 | ReadSetting(QStringLiteral("use_touch_from_button"), false).toBool(); | ||
| 580 | Settings::values.touch_from_button_map_index = | ||
| 581 | ReadSetting(QStringLiteral("touch_from_button_map"), 0).toInt(); | ||
| 582 | Settings::values.touch_from_button_map_index = | ||
| 583 | std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1); | ||
| 584 | Settings::values.udp_input_servers = | ||
| 585 | ReadSetting(QStringLiteral("udp_input_servers"), | ||
| 586 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_SRV)) | ||
| 587 | .toString() | ||
| 588 | .toStdString(); | ||
| 589 | } | 647 | } |
| 590 | 648 | ||
| 591 | void Config::ReadCoreValues() { | 649 | void Config::ReadCoreValues() { |
| 592 | qt_config->beginGroup(QStringLiteral("Core")); | 650 | qt_config->beginGroup(QStringLiteral("Core")); |
| 593 | 651 | ||
| 594 | ReadSettingGlobal(Settings::values.use_multi_core, QStringLiteral("use_multi_core"), true); | 652 | ReadGlobalSetting(Settings::values.use_multi_core); |
| 595 | 653 | ||
| 596 | qt_config->endGroup(); | 654 | qt_config->endGroup(); |
| 597 | } | 655 | } |
| @@ -599,7 +657,7 @@ void Config::ReadCoreValues() { | |||
| 599 | void Config::ReadDataStorageValues() { | 657 | void Config::ReadDataStorageValues() { |
| 600 | qt_config->beginGroup(QStringLiteral("Data Storage")); | 658 | qt_config->beginGroup(QStringLiteral("Data Storage")); |
| 601 | 659 | ||
| 602 | Settings::values.use_virtual_sd = ReadSetting(QStringLiteral("use_virtual_sd"), true).toBool(); | 660 | ReadBasicSetting(Settings::values.use_virtual_sd); |
| 603 | FS::SetYuzuPath( | 661 | FS::SetYuzuPath( |
| 604 | FS::YuzuPath::NANDDir, | 662 | FS::YuzuPath::NANDDir, |
| 605 | qt_config | 663 | qt_config |
| @@ -628,12 +686,9 @@ void Config::ReadDataStorageValues() { | |||
| 628 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))) | 686 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))) |
| 629 | .toString() | 687 | .toString() |
| 630 | .toStdString()); | 688 | .toStdString()); |
| 631 | Settings::values.gamecard_inserted = | 689 | ReadBasicSetting(Settings::values.gamecard_inserted); |
| 632 | ReadSetting(QStringLiteral("gamecard_inserted"), false).toBool(); | 690 | ReadBasicSetting(Settings::values.gamecard_current_game); |
| 633 | Settings::values.gamecard_current_game = | 691 | ReadBasicSetting(Settings::values.gamecard_path); |
| 634 | ReadSetting(QStringLiteral("gamecard_current_game"), false).toBool(); | ||
| 635 | Settings::values.gamecard_path = | ||
| 636 | ReadSetting(QStringLiteral("gamecard_path"), QString{}).toString().toStdString(); | ||
| 637 | 692 | ||
| 638 | qt_config->endGroup(); | 693 | qt_config->endGroup(); |
| 639 | } | 694 | } |
| @@ -644,34 +699,24 @@ void Config::ReadDebuggingValues() { | |||
| 644 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | 699 | // Intentionally not using the QT default setting as this is intended to be changed in the ini |
| 645 | Settings::values.record_frame_times = | 700 | Settings::values.record_frame_times = |
| 646 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); | 701 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); |
| 647 | Settings::values.program_args = | 702 | ReadBasicSetting(Settings::values.program_args); |
| 648 | ReadSetting(QStringLiteral("program_args"), QString{}).toString().toStdString(); | 703 | ReadBasicSetting(Settings::values.dump_exefs); |
| 649 | Settings::values.dump_exefs = ReadSetting(QStringLiteral("dump_exefs"), false).toBool(); | 704 | ReadBasicSetting(Settings::values.dump_nso); |
| 650 | Settings::values.dump_nso = ReadSetting(QStringLiteral("dump_nso"), false).toBool(); | 705 | ReadBasicSetting(Settings::values.enable_fs_access_log); |
| 651 | Settings::values.enable_fs_access_log = | 706 | ReadBasicSetting(Settings::values.reporting_services); |
| 652 | ReadSetting(QStringLiteral("enable_fs_access_log"), false).toBool(); | 707 | ReadBasicSetting(Settings::values.quest_flag); |
| 653 | Settings::values.reporting_services = | 708 | ReadBasicSetting(Settings::values.disable_macro_jit); |
| 654 | ReadSetting(QStringLiteral("reporting_services"), false).toBool(); | 709 | ReadBasicSetting(Settings::values.extended_logging); |
| 655 | Settings::values.quest_flag = ReadSetting(QStringLiteral("quest_flag"), false).toBool(); | 710 | ReadBasicSetting(Settings::values.use_debug_asserts); |
| 656 | Settings::values.disable_macro_jit = | 711 | ReadBasicSetting(Settings::values.use_auto_stub); |
| 657 | ReadSetting(QStringLiteral("disable_macro_jit"), false).toBool(); | ||
| 658 | Settings::values.extended_logging = | ||
| 659 | ReadSetting(QStringLiteral("extended_logging"), false).toBool(); | ||
| 660 | Settings::values.use_debug_asserts = | ||
| 661 | ReadSetting(QStringLiteral("use_debug_asserts"), false).toBool(); | ||
| 662 | Settings::values.use_auto_stub = ReadSetting(QStringLiteral("use_auto_stub"), false).toBool(); | ||
| 663 | 712 | ||
| 664 | qt_config->endGroup(); | 713 | qt_config->endGroup(); |
| 665 | } | 714 | } |
| 666 | 715 | ||
| 667 | void Config::ReadServiceValues() { | 716 | void Config::ReadServiceValues() { |
| 668 | qt_config->beginGroup(QStringLiteral("Services")); | 717 | qt_config->beginGroup(QStringLiteral("Services")); |
| 669 | Settings::values.bcat_backend = | 718 | ReadBasicSetting(Settings::values.bcat_backend); |
| 670 | ReadSetting(QStringLiteral("bcat_backend"), QStringLiteral("none")) | 719 | ReadBasicSetting(Settings::values.bcat_boxcat_local); |
| 671 | .toString() | ||
| 672 | .toStdString(); | ||
| 673 | Settings::values.bcat_boxcat_local = | ||
| 674 | ReadSetting(QStringLiteral("bcat_boxcat_local"), false).toBool(); | ||
| 675 | qt_config->endGroup(); | 720 | qt_config->endGroup(); |
| 676 | } | 721 | } |
| 677 | 722 | ||
| @@ -697,11 +742,8 @@ void Config::ReadDisabledAddOnValues() { | |||
| 697 | void Config::ReadMiscellaneousValues() { | 742 | void Config::ReadMiscellaneousValues() { |
| 698 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | 743 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); |
| 699 | 744 | ||
| 700 | Settings::values.log_filter = | 745 | ReadBasicSetting(Settings::values.log_filter); |
| 701 | ReadSetting(QStringLiteral("log_filter"), QStringLiteral("*:Info")) | 746 | ReadBasicSetting(Settings::values.use_dev_keys); |
| 702 | .toString() | ||
| 703 | .toStdString(); | ||
| 704 | Settings::values.use_dev_keys = ReadSetting(QStringLiteral("use_dev_keys"), false).toBool(); | ||
| 705 | 747 | ||
| 706 | qt_config->endGroup(); | 748 | qt_config->endGroup(); |
| 707 | } | 749 | } |
| @@ -751,38 +793,31 @@ void Config::ReadPathValues() { | |||
| 751 | void Config::ReadCpuValues() { | 793 | void Config::ReadCpuValues() { |
| 752 | qt_config->beginGroup(QStringLiteral("Cpu")); | 794 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 753 | 795 | ||
| 754 | ReadSettingGlobal(Settings::values.cpu_accuracy, QStringLiteral("cpu_accuracy"), 0); | 796 | ReadBasicSetting(Settings::values.cpu_accuracy_first_time); |
| 797 | if (Settings::values.cpu_accuracy_first_time) { | ||
| 798 | Settings::values.cpu_accuracy.SetValue(Settings::values.cpu_accuracy.GetDefault()); | ||
| 799 | Settings::values.cpu_accuracy_first_time.SetValue(false); | ||
| 800 | } else { | ||
| 801 | ReadGlobalSetting(Settings::values.cpu_accuracy); | ||
| 802 | } | ||
| 755 | 803 | ||
| 756 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_unfuse_fma, | 804 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma); |
| 757 | QStringLiteral("cpuopt_unsafe_unfuse_fma"), true); | 805 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error); |
| 758 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_reduce_fp_error, | 806 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr); |
| 759 | QStringLiteral("cpuopt_unsafe_reduce_fp_error"), true); | 807 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan); |
| 760 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_ignore_standard_fpcr, | 808 | ReadGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); |
| 761 | QStringLiteral("cpuopt_unsafe_ignore_standard_fpcr"), true); | ||
| 762 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_inaccurate_nan, | ||
| 763 | QStringLiteral("cpuopt_unsafe_inaccurate_nan"), true); | ||
| 764 | ReadSettingGlobal(Settings::values.cpuopt_unsafe_fastmem_check, | ||
| 765 | QStringLiteral("cpuopt_unsafe_fastmem_check"), true); | ||
| 766 | 809 | ||
| 767 | if (global) { | 810 | if (global) { |
| 768 | Settings::values.cpuopt_page_tables = | 811 | ReadBasicSetting(Settings::values.cpu_debug_mode); |
| 769 | ReadSetting(QStringLiteral("cpuopt_page_tables"), true).toBool(); | 812 | ReadBasicSetting(Settings::values.cpuopt_page_tables); |
| 770 | Settings::values.cpuopt_block_linking = | 813 | ReadBasicSetting(Settings::values.cpuopt_block_linking); |
| 771 | ReadSetting(QStringLiteral("cpuopt_block_linking"), true).toBool(); | 814 | ReadBasicSetting(Settings::values.cpuopt_return_stack_buffer); |
| 772 | Settings::values.cpuopt_return_stack_buffer = | 815 | ReadBasicSetting(Settings::values.cpuopt_fast_dispatcher); |
| 773 | ReadSetting(QStringLiteral("cpuopt_return_stack_buffer"), true).toBool(); | 816 | ReadBasicSetting(Settings::values.cpuopt_context_elimination); |
| 774 | Settings::values.cpuopt_fast_dispatcher = | 817 | ReadBasicSetting(Settings::values.cpuopt_const_prop); |
| 775 | ReadSetting(QStringLiteral("cpuopt_fast_dispatcher"), true).toBool(); | 818 | ReadBasicSetting(Settings::values.cpuopt_misc_ir); |
| 776 | Settings::values.cpuopt_context_elimination = | 819 | ReadBasicSetting(Settings::values.cpuopt_reduce_misalign_checks); |
| 777 | ReadSetting(QStringLiteral("cpuopt_context_elimination"), true).toBool(); | 820 | ReadBasicSetting(Settings::values.cpuopt_fastmem); |
| 778 | Settings::values.cpuopt_const_prop = | ||
| 779 | ReadSetting(QStringLiteral("cpuopt_const_prop"), true).toBool(); | ||
| 780 | Settings::values.cpuopt_misc_ir = | ||
| 781 | ReadSetting(QStringLiteral("cpuopt_misc_ir"), true).toBool(); | ||
| 782 | Settings::values.cpuopt_reduce_misalign_checks = | ||
| 783 | ReadSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), true).toBool(); | ||
| 784 | Settings::values.cpuopt_fastmem = | ||
| 785 | ReadSetting(QStringLiteral("cpuopt_fastmem"), true).toBool(); | ||
| 786 | } | 821 | } |
| 787 | 822 | ||
| 788 | qt_config->endGroup(); | 823 | qt_config->endGroup(); |
| @@ -791,41 +826,30 @@ void Config::ReadCpuValues() { | |||
| 791 | void Config::ReadRendererValues() { | 826 | void Config::ReadRendererValues() { |
| 792 | qt_config->beginGroup(QStringLiteral("Renderer")); | 827 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 793 | 828 | ||
| 794 | ReadSettingGlobal(Settings::values.renderer_backend, QStringLiteral("backend"), 0); | 829 | ReadGlobalSetting(Settings::values.renderer_backend); |
| 795 | ReadSettingGlobal(Settings::values.renderer_debug, QStringLiteral("debug"), false); | 830 | ReadGlobalSetting(Settings::values.vulkan_device); |
| 796 | ReadSettingGlobal(Settings::values.vulkan_device, QStringLiteral("vulkan_device"), 0); | 831 | ReadGlobalSetting(Settings::values.fullscreen_mode); |
| 797 | #ifdef _WIN32 | 832 | ReadGlobalSetting(Settings::values.aspect_ratio); |
| 798 | ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 0); | 833 | ReadGlobalSetting(Settings::values.max_anisotropy); |
| 799 | #else | 834 | ReadGlobalSetting(Settings::values.use_frame_limit); |
| 800 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 835 | ReadGlobalSetting(Settings::values.frame_limit); |
| 801 | // Default to exclusive fullscreen on these platforms for now. | 836 | ReadGlobalSetting(Settings::values.use_disk_shader_cache); |
| 802 | ReadSettingGlobal(Settings::values.fullscreen_mode, QStringLiteral("fullscreen_mode"), 1); | 837 | ReadGlobalSetting(Settings::values.gpu_accuracy); |
| 803 | #endif | 838 | ReadGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); |
| 804 | ReadSettingGlobal(Settings::values.aspect_ratio, QStringLiteral("aspect_ratio"), 0); | 839 | ReadGlobalSetting(Settings::values.use_nvdec_emulation); |
| 805 | ReadSettingGlobal(Settings::values.max_anisotropy, QStringLiteral("max_anisotropy"), 0); | 840 | ReadGlobalSetting(Settings::values.accelerate_astc); |
| 806 | ReadSettingGlobal(Settings::values.use_frame_limit, QStringLiteral("use_frame_limit"), true); | 841 | ReadGlobalSetting(Settings::values.use_vsync); |
| 807 | ReadSettingGlobal(Settings::values.frame_limit, QStringLiteral("frame_limit"), 100); | 842 | ReadGlobalSetting(Settings::values.use_assembly_shaders); |
| 808 | ReadSettingGlobal(Settings::values.use_disk_shader_cache, | 843 | ReadGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 809 | QStringLiteral("use_disk_shader_cache"), true); | 844 | ReadGlobalSetting(Settings::values.use_fast_gpu_time); |
| 810 | ReadSettingGlobal(Settings::values.gpu_accuracy, QStringLiteral("gpu_accuracy"), 1); | 845 | ReadGlobalSetting(Settings::values.use_caches_gc); |
| 811 | ReadSettingGlobal(Settings::values.use_asynchronous_gpu_emulation, | 846 | ReadGlobalSetting(Settings::values.bg_red); |
| 812 | QStringLiteral("use_asynchronous_gpu_emulation"), true); | 847 | ReadGlobalSetting(Settings::values.bg_green); |
| 813 | ReadSettingGlobal(Settings::values.use_nvdec_emulation, QStringLiteral("use_nvdec_emulation"), | 848 | ReadGlobalSetting(Settings::values.bg_blue); |
| 814 | true); | 849 | |
| 815 | ReadSettingGlobal(Settings::values.accelerate_astc, QStringLiteral("accelerate_astc"), true); | 850 | if (global) { |
| 816 | ReadSettingGlobal(Settings::values.use_vsync, QStringLiteral("use_vsync"), true); | 851 | ReadBasicSetting(Settings::values.renderer_debug); |
| 817 | ReadSettingGlobal(Settings::values.disable_fps_limit, QStringLiteral("disable_fps_limit"), | 852 | } |
| 818 | false); | ||
| 819 | ReadSettingGlobal(Settings::values.use_assembly_shaders, QStringLiteral("use_assembly_shaders"), | ||
| 820 | false); | ||
| 821 | ReadSettingGlobal(Settings::values.use_asynchronous_shaders, | ||
| 822 | QStringLiteral("use_asynchronous_shaders"), false); | ||
| 823 | ReadSettingGlobal(Settings::values.use_fast_gpu_time, QStringLiteral("use_fast_gpu_time"), | ||
| 824 | true); | ||
| 825 | ReadSettingGlobal(Settings::values.use_caches_gc, QStringLiteral("use_caches_gc"), false); | ||
| 826 | ReadSettingGlobal(Settings::values.bg_red, QStringLiteral("bg_red"), 0.0); | ||
| 827 | ReadSettingGlobal(Settings::values.bg_green, QStringLiteral("bg_green"), 0.0); | ||
| 828 | ReadSettingGlobal(Settings::values.bg_blue, QStringLiteral("bg_blue"), 0.0); | ||
| 829 | 853 | ||
| 830 | qt_config->endGroup(); | 854 | qt_config->endGroup(); |
| 831 | } | 855 | } |
| @@ -870,15 +894,15 @@ void Config::ReadShortcutValues() { | |||
| 870 | void Config::ReadSystemValues() { | 894 | void Config::ReadSystemValues() { |
| 871 | qt_config->beginGroup(QStringLiteral("System")); | 895 | qt_config->beginGroup(QStringLiteral("System")); |
| 872 | 896 | ||
| 873 | ReadSettingGlobal(Settings::values.current_user, QStringLiteral("current_user"), 0); | 897 | ReadBasicSetting(Settings::values.current_user); |
| 874 | Settings::values.current_user = | 898 | Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0, |
| 875 | std::clamp<int>(Settings::values.current_user, 0, Service::Account::MAX_USERS - 1); | 899 | Service::Account::MAX_USERS - 1); |
| 876 | 900 | ||
| 877 | ReadSettingGlobal(Settings::values.language_index, QStringLiteral("language_index"), 1); | 901 | ReadGlobalSetting(Settings::values.language_index); |
| 878 | 902 | ||
| 879 | ReadSettingGlobal(Settings::values.region_index, QStringLiteral("region_index"), 1); | 903 | ReadGlobalSetting(Settings::values.region_index); |
| 880 | 904 | ||
| 881 | ReadSettingGlobal(Settings::values.time_zone_index, QStringLiteral("time_zone_index"), 0); | 905 | ReadGlobalSetting(Settings::values.time_zone_index); |
| 882 | 906 | ||
| 883 | bool rng_seed_enabled; | 907 | bool rng_seed_enabled; |
| 884 | ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false); | 908 | ReadSettingGlobal(rng_seed_enabled, QStringLiteral("rng_seed_enabled"), false); |
| @@ -904,7 +928,7 @@ void Config::ReadSystemValues() { | |||
| 904 | } | 928 | } |
| 905 | } | 929 | } |
| 906 | 930 | ||
| 907 | ReadSettingGlobal(Settings::values.sound_index, QStringLiteral("sound_index"), 1); | 931 | ReadGlobalSetting(Settings::values.sound_index); |
| 908 | 932 | ||
| 909 | qt_config->endGroup(); | 933 | qt_config->endGroup(); |
| 910 | } | 934 | } |
| @@ -915,10 +939,8 @@ void Config::ReadUIValues() { | |||
| 915 | UISettings::values.theme = | 939 | UISettings::values.theme = |
| 916 | ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) | 940 | ReadSetting(QStringLiteral("theme"), QString::fromUtf8(UISettings::themes[0].second)) |
| 917 | .toString(); | 941 | .toString(); |
| 918 | UISettings::values.enable_discord_presence = | 942 | ReadBasicSetting(UISettings::values.enable_discord_presence); |
| 919 | ReadSetting(QStringLiteral("enable_discord_presence"), true).toBool(); | 943 | ReadBasicSetting(UISettings::values.select_user_on_boot); |
| 920 | UISettings::values.select_user_on_boot = | ||
| 921 | ReadSetting(QStringLiteral("select_user_on_boot"), false).toBool(); | ||
| 922 | 944 | ||
| 923 | ReadUIGamelistValues(); | 945 | ReadUIGamelistValues(); |
| 924 | ReadUILayoutValues(); | 946 | ReadUILayoutValues(); |
| @@ -926,24 +948,17 @@ void Config::ReadUIValues() { | |||
| 926 | ReadScreenshotValues(); | 948 | ReadScreenshotValues(); |
| 927 | ReadShortcutValues(); | 949 | ReadShortcutValues(); |
| 928 | 950 | ||
| 929 | UISettings::values.single_window_mode = | 951 | ReadBasicSetting(UISettings::values.single_window_mode); |
| 930 | ReadSetting(QStringLiteral("singleWindowMode"), true).toBool(); | 952 | ReadBasicSetting(UISettings::values.fullscreen); |
| 931 | UISettings::values.fullscreen = ReadSetting(QStringLiteral("fullscreen"), false).toBool(); | 953 | ReadBasicSetting(UISettings::values.display_titlebar); |
| 932 | UISettings::values.display_titlebar = | 954 | ReadBasicSetting(UISettings::values.show_filter_bar); |
| 933 | ReadSetting(QStringLiteral("displayTitleBars"), true).toBool(); | 955 | ReadBasicSetting(UISettings::values.show_status_bar); |
| 934 | UISettings::values.show_filter_bar = | 956 | ReadBasicSetting(UISettings::values.confirm_before_closing); |
| 935 | ReadSetting(QStringLiteral("showFilterBar"), true).toBool(); | 957 | ReadBasicSetting(UISettings::values.first_start); |
| 936 | UISettings::values.show_status_bar = | 958 | ReadBasicSetting(UISettings::values.callout_flags); |
| 937 | ReadSetting(QStringLiteral("showStatusBar"), true).toBool(); | 959 | ReadBasicSetting(UISettings::values.show_console); |
| 938 | UISettings::values.confirm_before_closing = | 960 | ReadBasicSetting(UISettings::values.pause_when_in_background); |
| 939 | ReadSetting(QStringLiteral("confirmClose"), true).toBool(); | 961 | ReadBasicSetting(UISettings::values.hide_mouse); |
| 940 | UISettings::values.first_start = ReadSetting(QStringLiteral("firstStart"), true).toBool(); | ||
| 941 | UISettings::values.callout_flags = ReadSetting(QStringLiteral("calloutFlags"), 0).toUInt(); | ||
| 942 | UISettings::values.show_console = ReadSetting(QStringLiteral("showConsole"), false).toBool(); | ||
| 943 | UISettings::values.pause_when_in_background = | ||
| 944 | ReadSetting(QStringLiteral("pauseWhenInBackground"), false).toBool(); | ||
| 945 | UISettings::values.hide_mouse = | ||
| 946 | ReadSetting(QStringLiteral("hideInactiveMouse"), false).toBool(); | ||
| 947 | 962 | ||
| 948 | qt_config->endGroup(); | 963 | qt_config->endGroup(); |
| 949 | } | 964 | } |
| @@ -951,12 +966,11 @@ void Config::ReadUIValues() { | |||
| 951 | void Config::ReadUIGamelistValues() { | 966 | void Config::ReadUIGamelistValues() { |
| 952 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 967 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 953 | 968 | ||
| 954 | UISettings::values.show_add_ons = ReadSetting(QStringLiteral("show_add_ons"), true).toBool(); | 969 | ReadBasicSetting(UISettings::values.show_add_ons); |
| 955 | UISettings::values.icon_size = ReadSetting(QStringLiteral("icon_size"), 64).toUInt(); | 970 | ReadBasicSetting(UISettings::values.icon_size); |
| 956 | UISettings::values.row_1_text_id = ReadSetting(QStringLiteral("row_1_text_id"), 3).toUInt(); | 971 | ReadBasicSetting(UISettings::values.row_1_text_id); |
| 957 | UISettings::values.row_2_text_id = ReadSetting(QStringLiteral("row_2_text_id"), 2).toUInt(); | 972 | ReadBasicSetting(UISettings::values.row_2_text_id); |
| 958 | UISettings::values.cache_game_list = | 973 | ReadBasicSetting(UISettings::values.cache_game_list); |
| 959 | ReadSetting(QStringLiteral("cache_game_list"), true).toBool(); | ||
| 960 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); | 974 | const int favorites_size = qt_config->beginReadArray(QStringLiteral("favorites")); |
| 961 | for (int i = 0; i < favorites_size; i++) { | 975 | for (int i = 0; i < favorites_size; i++) { |
| 962 | qt_config->setArrayIndex(i); | 976 | qt_config->setArrayIndex(i); |
| @@ -979,8 +993,7 @@ void Config::ReadUILayoutValues() { | |||
| 979 | ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); | 993 | ReadSetting(QStringLiteral("gameListHeaderState")).toByteArray(); |
| 980 | UISettings::values.microprofile_geometry = | 994 | UISettings::values.microprofile_geometry = |
| 981 | ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); | 995 | ReadSetting(QStringLiteral("microProfileDialogGeometry")).toByteArray(); |
| 982 | UISettings::values.microprofile_visible = | 996 | ReadBasicSetting(UISettings::values.microprofile_visible); |
| 983 | ReadSetting(QStringLiteral("microProfileDialogVisible"), false).toBool(); | ||
| 984 | 997 | ||
| 985 | qt_config->endGroup(); | 998 | qt_config->endGroup(); |
| 986 | } | 999 | } |
| @@ -988,16 +1001,10 @@ void Config::ReadUILayoutValues() { | |||
| 988 | void Config::ReadWebServiceValues() { | 1001 | void Config::ReadWebServiceValues() { |
| 989 | qt_config->beginGroup(QStringLiteral("WebService")); | 1002 | qt_config->beginGroup(QStringLiteral("WebService")); |
| 990 | 1003 | ||
| 991 | Settings::values.enable_telemetry = | 1004 | ReadBasicSetting(Settings::values.enable_telemetry); |
| 992 | ReadSetting(QStringLiteral("enable_telemetry"), true).toBool(); | 1005 | ReadBasicSetting(Settings::values.web_api_url); |
| 993 | Settings::values.web_api_url = | 1006 | ReadBasicSetting(Settings::values.yuzu_username); |
| 994 | ReadSetting(QStringLiteral("web_api_url"), QStringLiteral("https://api.yuzu-emu.org")) | 1007 | ReadBasicSetting(Settings::values.yuzu_token); |
| 995 | .toString() | ||
| 996 | .toStdString(); | ||
| 997 | Settings::values.yuzu_username = | ||
| 998 | ReadSetting(QStringLiteral("yuzu_username")).toString().toStdString(); | ||
| 999 | Settings::values.yuzu_token = | ||
| 1000 | ReadSetting(QStringLiteral("yuzu_token")).toString().toStdString(); | ||
| 1001 | 1008 | ||
| 1002 | qt_config->endGroup(); | 1009 | qt_config->endGroup(); |
| 1003 | } | 1010 | } |
| @@ -1083,7 +1090,7 @@ void Config::SavePlayerValue(std::size_t player_index) { | |||
| 1083 | } | 1090 | } |
| 1084 | 1091 | ||
| 1085 | void Config::SaveDebugValues() { | 1092 | void Config::SaveDebugValues() { |
| 1086 | WriteSetting(QStringLiteral("debug_pad_enabled"), Settings::values.debug_pad_enabled, false); | 1093 | WriteBasicSetting(Settings::values.debug_pad_enabled); |
| 1087 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 1094 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 1088 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 1095 | const std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 1089 | WriteSetting(QStringLiteral("debug_pad_") + | 1096 | WriteSetting(QStringLiteral("debug_pad_") + |
| @@ -1103,7 +1110,7 @@ void Config::SaveDebugValues() { | |||
| 1103 | } | 1110 | } |
| 1104 | 1111 | ||
| 1105 | void Config::SaveMouseValues() { | 1112 | void Config::SaveMouseValues() { |
| 1106 | WriteSetting(QStringLiteral("mouse_enabled"), Settings::values.mouse_enabled, false); | 1113 | WriteBasicSetting(Settings::values.mouse_enabled); |
| 1107 | 1114 | ||
| 1108 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { | 1115 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { |
| 1109 | const std::string default_param = | 1116 | const std::string default_param = |
| @@ -1126,19 +1133,11 @@ void Config::SaveTouchscreenValues() { | |||
| 1126 | } | 1133 | } |
| 1127 | 1134 | ||
| 1128 | void Config::SaveMotionTouchValues() { | 1135 | void Config::SaveMotionTouchValues() { |
| 1129 | WriteSetting(QStringLiteral("motion_device"), | 1136 | WriteBasicSetting(Settings::values.motion_device); |
| 1130 | QString::fromStdString(Settings::values.motion_device), | 1137 | WriteBasicSetting(Settings::values.touch_device); |
| 1131 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | 1138 | WriteBasicSetting(Settings::values.use_touch_from_button); |
| 1132 | WriteSetting(QStringLiteral("touch_device"), | 1139 | WriteBasicSetting(Settings::values.touch_from_button_map_index); |
| 1133 | QString::fromStdString(Settings::values.touch_device), | 1140 | WriteBasicSetting(Settings::values.udp_input_servers); |
| 1134 | QStringLiteral("engine:emu_window")); | ||
| 1135 | WriteSetting(QStringLiteral("use_touch_from_button"), Settings::values.use_touch_from_button, | ||
| 1136 | false); | ||
| 1137 | WriteSetting(QStringLiteral("touch_from_button_map"), | ||
| 1138 | Settings::values.touch_from_button_map_index, 0); | ||
| 1139 | WriteSetting(QStringLiteral("udp_input_servers"), | ||
| 1140 | QString::fromStdString(Settings::values.udp_input_servers), | ||
| 1141 | QString::fromUtf8(InputCommon::CemuhookUDP::DEFAULT_SRV)); | ||
| 1142 | 1141 | ||
| 1143 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); | 1142 | qt_config->beginWriteArray(QStringLiteral("touch_from_button_maps")); |
| 1144 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { | 1143 | for (std::size_t p = 0; p < Settings::values.touch_from_button_maps.size(); ++p) { |
| @@ -1181,15 +1180,11 @@ void Config::SaveAudioValues() { | |||
| 1181 | qt_config->beginGroup(QStringLiteral("Audio")); | 1180 | qt_config->beginGroup(QStringLiteral("Audio")); |
| 1182 | 1181 | ||
| 1183 | if (global) { | 1182 | if (global) { |
| 1184 | WriteSetting(QStringLiteral("output_engine"), | 1183 | WriteBasicSetting(Settings::values.sink_id); |
| 1185 | QString::fromStdString(Settings::values.sink_id), QStringLiteral("auto")); | 1184 | WriteBasicSetting(Settings::values.audio_device_id); |
| 1186 | WriteSetting(QStringLiteral("output_device"), | ||
| 1187 | QString::fromStdString(Settings::values.audio_device_id), | ||
| 1188 | QStringLiteral("auto")); | ||
| 1189 | } | 1185 | } |
| 1190 | WriteSettingGlobal(QStringLiteral("enable_audio_stretching"), | 1186 | WriteGlobalSetting(Settings::values.enable_audio_stretching); |
| 1191 | Settings::values.enable_audio_stretching, true); | 1187 | WriteGlobalSetting(Settings::values.volume); |
| 1192 | WriteSettingGlobal(QStringLiteral("volume"), Settings::values.volume, 1.0f); | ||
| 1193 | 1188 | ||
| 1194 | qt_config->endGroup(); | 1189 | qt_config->endGroup(); |
| 1195 | } | 1190 | } |
| @@ -1205,30 +1200,21 @@ void Config::SaveControlValues() { | |||
| 1205 | SaveTouchscreenValues(); | 1200 | SaveTouchscreenValues(); |
| 1206 | SaveMotionTouchValues(); | 1201 | SaveMotionTouchValues(); |
| 1207 | 1202 | ||
| 1208 | WriteSettingGlobal(QStringLiteral("use_docked_mode"), Settings::values.use_docked_mode, true); | 1203 | WriteGlobalSetting(Settings::values.use_docked_mode); |
| 1209 | WriteSettingGlobal(QStringLiteral("vibration_enabled"), Settings::values.vibration_enabled, | 1204 | WriteGlobalSetting(Settings::values.vibration_enabled); |
| 1210 | true); | 1205 | WriteGlobalSetting(Settings::values.enable_accurate_vibrations); |
| 1211 | WriteSettingGlobal(QStringLiteral("enable_accurate_vibrations"), | 1206 | WriteGlobalSetting(Settings::values.motion_enabled); |
| 1212 | Settings::values.enable_accurate_vibrations, false); | 1207 | WriteBasicSetting(Settings::values.keyboard_enabled); |
| 1213 | WriteSettingGlobal(QStringLiteral("motion_enabled"), Settings::values.motion_enabled, true); | 1208 | WriteBasicSetting(Settings::values.emulate_analog_keyboard); |
| 1214 | WriteSetting(QStringLiteral("motion_device"), | 1209 | WriteBasicSetting(Settings::values.mouse_panning_sensitivity); |
| 1215 | QString::fromStdString(Settings::values.motion_device), | 1210 | |
| 1216 | QStringLiteral("engine:motion_emu,update_period:100,sensitivity:0.01")); | ||
| 1217 | WriteSetting(QStringLiteral("touch_device"), | ||
| 1218 | QString::fromStdString(Settings::values.touch_device), | ||
| 1219 | QStringLiteral("engine:emu_window")); | ||
| 1220 | WriteSetting(QStringLiteral("keyboard_enabled"), Settings::values.keyboard_enabled, false); | ||
| 1221 | WriteSetting(QStringLiteral("emulate_analog_keyboard"), | ||
| 1222 | Settings::values.emulate_analog_keyboard, false); | ||
| 1223 | WriteSetting(QStringLiteral("mouse_panning_sensitivity"), | ||
| 1224 | Settings::values.mouse_panning_sensitivity, 1.0f); | ||
| 1225 | qt_config->endGroup(); | 1211 | qt_config->endGroup(); |
| 1226 | } | 1212 | } |
| 1227 | 1213 | ||
| 1228 | void Config::SaveCoreValues() { | 1214 | void Config::SaveCoreValues() { |
| 1229 | qt_config->beginGroup(QStringLiteral("Core")); | 1215 | qt_config->beginGroup(QStringLiteral("Core")); |
| 1230 | 1216 | ||
| 1231 | WriteSettingGlobal(QStringLiteral("use_multi_core"), Settings::values.use_multi_core, true); | 1217 | WriteGlobalSetting(Settings::values.use_multi_core); |
| 1232 | 1218 | ||
| 1233 | qt_config->endGroup(); | 1219 | qt_config->endGroup(); |
| 1234 | } | 1220 | } |
| @@ -1236,7 +1222,7 @@ void Config::SaveCoreValues() { | |||
| 1236 | void Config::SaveDataStorageValues() { | 1222 | void Config::SaveDataStorageValues() { |
| 1237 | qt_config->beginGroup(QStringLiteral("Data Storage")); | 1223 | qt_config->beginGroup(QStringLiteral("Data Storage")); |
| 1238 | 1224 | ||
| 1239 | WriteSetting(QStringLiteral("use_virtual_sd"), Settings::values.use_virtual_sd, true); | 1225 | WriteBasicSetting(Settings::values.use_virtual_sd); |
| 1240 | WriteSetting(QStringLiteral("nand_directory"), | 1226 | WriteSetting(QStringLiteral("nand_directory"), |
| 1241 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), | 1227 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir)), |
| 1242 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | 1228 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); |
| @@ -1249,11 +1235,9 @@ void Config::SaveDataStorageValues() { | |||
| 1249 | WriteSetting(QStringLiteral("dump_directory"), | 1235 | WriteSetting(QStringLiteral("dump_directory"), |
| 1250 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)), | 1236 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir)), |
| 1251 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | 1237 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); |
| 1252 | WriteSetting(QStringLiteral("gamecard_inserted"), Settings::values.gamecard_inserted, false); | 1238 | WriteBasicSetting(Settings::values.gamecard_inserted); |
| 1253 | WriteSetting(QStringLiteral("gamecard_current_game"), Settings::values.gamecard_current_game, | 1239 | WriteBasicSetting(Settings::values.gamecard_current_game); |
| 1254 | false); | 1240 | WriteBasicSetting(Settings::values.gamecard_path); |
| 1255 | WriteSetting(QStringLiteral("gamecard_path"), | ||
| 1256 | QString::fromStdString(Settings::values.gamecard_path), QString{}); | ||
| 1257 | 1241 | ||
| 1258 | qt_config->endGroup(); | 1242 | qt_config->endGroup(); |
| 1259 | } | 1243 | } |
| @@ -1263,24 +1247,23 @@ void Config::SaveDebuggingValues() { | |||
| 1263 | 1247 | ||
| 1264 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | 1248 | // Intentionally not using the QT default setting as this is intended to be changed in the ini |
| 1265 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); | 1249 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); |
| 1266 | WriteSetting(QStringLiteral("program_args"), | 1250 | WriteBasicSetting(Settings::values.program_args); |
| 1267 | QString::fromStdString(Settings::values.program_args), QString{}); | 1251 | WriteBasicSetting(Settings::values.dump_exefs); |
| 1268 | WriteSetting(QStringLiteral("dump_exefs"), Settings::values.dump_exefs, false); | 1252 | WriteBasicSetting(Settings::values.dump_nso); |
| 1269 | WriteSetting(QStringLiteral("dump_nso"), Settings::values.dump_nso, false); | 1253 | WriteBasicSetting(Settings::values.enable_fs_access_log); |
| 1270 | WriteSetting(QStringLiteral("enable_fs_access_log"), Settings::values.enable_fs_access_log, | 1254 | WriteBasicSetting(Settings::values.quest_flag); |
| 1271 | false); | 1255 | WriteBasicSetting(Settings::values.use_debug_asserts); |
| 1272 | WriteSetting(QStringLiteral("quest_flag"), Settings::values.quest_flag, false); | 1256 | WriteBasicSetting(Settings::values.disable_macro_jit); |
| 1273 | WriteSetting(QStringLiteral("use_debug_asserts"), Settings::values.use_debug_asserts, false); | ||
| 1274 | WriteSetting(QStringLiteral("disable_macro_jit"), Settings::values.disable_macro_jit, false); | ||
| 1275 | 1257 | ||
| 1276 | qt_config->endGroup(); | 1258 | qt_config->endGroup(); |
| 1277 | } | 1259 | } |
| 1278 | 1260 | ||
| 1279 | void Config::SaveServiceValues() { | 1261 | void Config::SaveServiceValues() { |
| 1280 | qt_config->beginGroup(QStringLiteral("Services")); | 1262 | qt_config->beginGroup(QStringLiteral("Services")); |
| 1281 | WriteSetting(QStringLiteral("bcat_backend"), | 1263 | |
| 1282 | QString::fromStdString(Settings::values.bcat_backend), QStringLiteral("none")); | 1264 | WriteBasicSetting(Settings::values.bcat_backend); |
| 1283 | WriteSetting(QStringLiteral("bcat_boxcat_local"), Settings::values.bcat_boxcat_local, false); | 1265 | WriteBasicSetting(Settings::values.bcat_boxcat_local); |
| 1266 | |||
| 1284 | qt_config->endGroup(); | 1267 | qt_config->endGroup(); |
| 1285 | } | 1268 | } |
| 1286 | 1269 | ||
| @@ -1306,9 +1289,8 @@ void Config::SaveDisabledAddOnValues() { | |||
| 1306 | void Config::SaveMiscellaneousValues() { | 1289 | void Config::SaveMiscellaneousValues() { |
| 1307 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); | 1290 | qt_config->beginGroup(QStringLiteral("Miscellaneous")); |
| 1308 | 1291 | ||
| 1309 | WriteSetting(QStringLiteral("log_filter"), QString::fromStdString(Settings::values.log_filter), | 1292 | WriteBasicSetting(Settings::values.log_filter); |
| 1310 | QStringLiteral("*:Info")); | 1293 | WriteBasicSetting(Settings::values.use_dev_keys); |
| 1311 | WriteSetting(QStringLiteral("use_dev_keys"), Settings::values.use_dev_keys, false); | ||
| 1312 | 1294 | ||
| 1313 | qt_config->endGroup(); | 1295 | qt_config->endGroup(); |
| 1314 | } | 1296 | } |
| @@ -1336,38 +1318,29 @@ void Config::SavePathValues() { | |||
| 1336 | void Config::SaveCpuValues() { | 1318 | void Config::SaveCpuValues() { |
| 1337 | qt_config->beginGroup(QStringLiteral("Cpu")); | 1319 | qt_config->beginGroup(QStringLiteral("Cpu")); |
| 1338 | 1320 | ||
| 1339 | WriteSettingGlobal(QStringLiteral("cpu_accuracy"), | 1321 | WriteBasicSetting(Settings::values.cpu_accuracy_first_time); |
| 1340 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)), | 1322 | WriteSetting(QStringLiteral("cpu_accuracy"), |
| 1341 | Settings::values.cpu_accuracy.UsingGlobal(), | 1323 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(global)), |
| 1342 | static_cast<u32>(Settings::CPUAccuracy::Accurate)); | 1324 | static_cast<u32>(Settings::values.cpu_accuracy.GetDefault()), |
| 1343 | 1325 | Settings::values.cpu_accuracy.UsingGlobal()); | |
| 1344 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_unfuse_fma"), | 1326 | |
| 1345 | Settings::values.cpuopt_unsafe_unfuse_fma, true); | 1327 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_unfuse_fma); |
| 1346 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_reduce_fp_error"), | 1328 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_reduce_fp_error); |
| 1347 | Settings::values.cpuopt_unsafe_reduce_fp_error, true); | 1329 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_ignore_standard_fpcr); |
| 1348 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_ignore_standard_fpcr"), | 1330 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_inaccurate_nan); |
| 1349 | Settings::values.cpuopt_unsafe_ignore_standard_fpcr, true); | 1331 | WriteGlobalSetting(Settings::values.cpuopt_unsafe_fastmem_check); |
| 1350 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_inaccurate_nan"), | ||
| 1351 | Settings::values.cpuopt_unsafe_inaccurate_nan, true); | ||
| 1352 | WriteSettingGlobal(QStringLiteral("cpuopt_unsafe_fastmem_check"), | ||
| 1353 | Settings::values.cpuopt_unsafe_fastmem_check, true); | ||
| 1354 | 1332 | ||
| 1355 | if (global) { | 1333 | if (global) { |
| 1356 | WriteSetting(QStringLiteral("cpuopt_page_tables"), Settings::values.cpuopt_page_tables, | 1334 | WriteBasicSetting(Settings::values.cpu_debug_mode); |
| 1357 | true); | 1335 | WriteBasicSetting(Settings::values.cpuopt_page_tables); |
| 1358 | WriteSetting(QStringLiteral("cpuopt_block_linking"), Settings::values.cpuopt_block_linking, | 1336 | WriteBasicSetting(Settings::values.cpuopt_block_linking); |
| 1359 | true); | 1337 | WriteBasicSetting(Settings::values.cpuopt_return_stack_buffer); |
| 1360 | WriteSetting(QStringLiteral("cpuopt_return_stack_buffer"), | 1338 | WriteBasicSetting(Settings::values.cpuopt_fast_dispatcher); |
| 1361 | Settings::values.cpuopt_return_stack_buffer, true); | 1339 | WriteBasicSetting(Settings::values.cpuopt_context_elimination); |
| 1362 | WriteSetting(QStringLiteral("cpuopt_fast_dispatcher"), | 1340 | WriteBasicSetting(Settings::values.cpuopt_const_prop); |
| 1363 | Settings::values.cpuopt_fast_dispatcher, true); | 1341 | WriteBasicSetting(Settings::values.cpuopt_misc_ir); |
| 1364 | WriteSetting(QStringLiteral("cpuopt_context_elimination"), | 1342 | WriteBasicSetting(Settings::values.cpuopt_reduce_misalign_checks); |
| 1365 | Settings::values.cpuopt_context_elimination, true); | 1343 | WriteBasicSetting(Settings::values.cpuopt_fastmem); |
| 1366 | WriteSetting(QStringLiteral("cpuopt_const_prop"), Settings::values.cpuopt_const_prop, true); | ||
| 1367 | WriteSetting(QStringLiteral("cpuopt_misc_ir"), Settings::values.cpuopt_misc_ir, true); | ||
| 1368 | WriteSetting(QStringLiteral("cpuopt_reduce_misalign_checks"), | ||
| 1369 | Settings::values.cpuopt_reduce_misalign_checks, true); | ||
| 1370 | WriteSetting(QStringLiteral("cpuopt_fastmem"), Settings::values.cpuopt_fastmem, true); | ||
| 1371 | } | 1344 | } |
| 1372 | 1345 | ||
| 1373 | qt_config->endGroup(); | 1346 | qt_config->endGroup(); |
| @@ -1376,46 +1349,36 @@ void Config::SaveCpuValues() { | |||
| 1376 | void Config::SaveRendererValues() { | 1349 | void Config::SaveRendererValues() { |
| 1377 | qt_config->beginGroup(QStringLiteral("Renderer")); | 1350 | qt_config->beginGroup(QStringLiteral("Renderer")); |
| 1378 | 1351 | ||
| 1379 | WriteSettingGlobal(QStringLiteral("backend"), | 1352 | WriteSetting(QString::fromStdString(Settings::values.renderer_backend.GetLabel()), |
| 1380 | static_cast<int>(Settings::values.renderer_backend.GetValue(global)), | 1353 | static_cast<u32>(Settings::values.renderer_backend.GetValue(global)), |
| 1381 | Settings::values.renderer_backend.UsingGlobal(), 0); | 1354 | static_cast<u32>(Settings::values.renderer_backend.GetDefault()), |
| 1382 | WriteSetting(QStringLiteral("debug"), Settings::values.renderer_debug, false); | 1355 | Settings::values.renderer_backend.UsingGlobal()); |
| 1383 | WriteSettingGlobal(QStringLiteral("vulkan_device"), Settings::values.vulkan_device, 0); | 1356 | WriteGlobalSetting(Settings::values.vulkan_device); |
| 1384 | #ifdef _WIN32 | 1357 | WriteGlobalSetting(Settings::values.fullscreen_mode); |
| 1385 | WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 0); | 1358 | WriteGlobalSetting(Settings::values.aspect_ratio); |
| 1386 | #else | 1359 | WriteGlobalSetting(Settings::values.max_anisotropy); |
| 1387 | // *nix platforms may have issues with the borderless windowed fullscreen mode. | 1360 | WriteGlobalSetting(Settings::values.use_frame_limit); |
| 1388 | // Default to exclusive fullscreen on these platforms for now. | 1361 | WriteGlobalSetting(Settings::values.frame_limit); |
| 1389 | WriteSettingGlobal(QStringLiteral("fullscreen_mode"), Settings::values.fullscreen_mode, 1); | 1362 | WriteGlobalSetting(Settings::values.use_disk_shader_cache); |
| 1390 | #endif | 1363 | WriteSetting(QString::fromStdString(Settings::values.gpu_accuracy.GetLabel()), |
| 1391 | WriteSettingGlobal(QStringLiteral("aspect_ratio"), Settings::values.aspect_ratio, 0); | 1364 | static_cast<u32>(Settings::values.gpu_accuracy.GetValue(global)), |
| 1392 | WriteSettingGlobal(QStringLiteral("max_anisotropy"), Settings::values.max_anisotropy, 0); | 1365 | static_cast<u32>(Settings::values.gpu_accuracy.GetDefault()), |
| 1393 | WriteSettingGlobal(QStringLiteral("use_frame_limit"), Settings::values.use_frame_limit, true); | 1366 | Settings::values.gpu_accuracy.UsingGlobal()); |
| 1394 | WriteSettingGlobal(QStringLiteral("frame_limit"), Settings::values.frame_limit, 100); | 1367 | WriteGlobalSetting(Settings::values.use_asynchronous_gpu_emulation); |
| 1395 | WriteSettingGlobal(QStringLiteral("use_disk_shader_cache"), | 1368 | WriteGlobalSetting(Settings::values.use_nvdec_emulation); |
| 1396 | Settings::values.use_disk_shader_cache, true); | 1369 | WriteGlobalSetting(Settings::values.accelerate_astc); |
| 1397 | WriteSettingGlobal(QStringLiteral("gpu_accuracy"), | 1370 | WriteGlobalSetting(Settings::values.use_vsync); |
| 1398 | static_cast<int>(Settings::values.gpu_accuracy.GetValue(global)), | 1371 | WriteGlobalSetting(Settings::values.use_assembly_shaders); |
| 1399 | Settings::values.gpu_accuracy.UsingGlobal(), 1); | 1372 | WriteGlobalSetting(Settings::values.use_asynchronous_shaders); |
| 1400 | WriteSettingGlobal(QStringLiteral("use_asynchronous_gpu_emulation"), | 1373 | WriteGlobalSetting(Settings::values.use_fast_gpu_time); |
| 1401 | Settings::values.use_asynchronous_gpu_emulation, true); | 1374 | WriteGlobalSetting(Settings::values.use_caches_gc); |
| 1402 | WriteSettingGlobal(QStringLiteral("use_nvdec_emulation"), Settings::values.use_nvdec_emulation, | 1375 | WriteGlobalSetting(Settings::values.bg_red); |
| 1403 | true); | 1376 | WriteGlobalSetting(Settings::values.bg_green); |
| 1404 | WriteSettingGlobal(QStringLiteral("accelerate_astc"), Settings::values.accelerate_astc, true); | 1377 | WriteGlobalSetting(Settings::values.bg_blue); |
| 1405 | WriteSettingGlobal(QStringLiteral("use_vsync"), Settings::values.use_vsync, true); | 1378 | |
| 1406 | WriteSettingGlobal(QStringLiteral("disable_fps_limit"), Settings::values.disable_fps_limit, | 1379 | if (global) { |
| 1407 | false); | 1380 | WriteBasicSetting(Settings::values.renderer_debug); |
| 1408 | WriteSettingGlobal(QStringLiteral("use_assembly_shaders"), | 1381 | } |
| 1409 | Settings::values.use_assembly_shaders, false); | ||
| 1410 | WriteSettingGlobal(QStringLiteral("use_asynchronous_shaders"), | ||
| 1411 | Settings::values.use_asynchronous_shaders, false); | ||
| 1412 | WriteSettingGlobal(QStringLiteral("use_fast_gpu_time"), Settings::values.use_fast_gpu_time, | ||
| 1413 | true); | ||
| 1414 | WriteSettingGlobal(QStringLiteral("use_caches_gc"), Settings::values.use_caches_gc, false); | ||
| 1415 | // Cast to double because Qt's written float values are not human-readable | ||
| 1416 | WriteSettingGlobal(QStringLiteral("bg_red"), Settings::values.bg_red, 0.0); | ||
| 1417 | WriteSettingGlobal(QStringLiteral("bg_green"), Settings::values.bg_green, 0.0); | ||
| 1418 | WriteSettingGlobal(QStringLiteral("bg_blue"), Settings::values.bg_blue, 0.0); | ||
| 1419 | 1382 | ||
| 1420 | qt_config->endGroup(); | 1383 | qt_config->endGroup(); |
| 1421 | } | 1384 | } |
| @@ -1423,8 +1386,7 @@ void Config::SaveRendererValues() { | |||
| 1423 | void Config::SaveScreenshotValues() { | 1386 | void Config::SaveScreenshotValues() { |
| 1424 | qt_config->beginGroup(QStringLiteral("Screenshots")); | 1387 | qt_config->beginGroup(QStringLiteral("Screenshots")); |
| 1425 | 1388 | ||
| 1426 | WriteSetting(QStringLiteral("enable_screenshot_save_as"), | 1389 | WriteBasicSetting(UISettings::values.enable_screenshot_save_as); |
| 1427 | UISettings::values.enable_screenshot_save_as); | ||
| 1428 | WriteSetting(QStringLiteral("screenshot_path"), | 1390 | WriteSetting(QStringLiteral("screenshot_path"), |
| 1429 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); | 1391 | QString::fromStdString(FS::GetYuzuPathString(FS::YuzuPath::ScreenshotsDir))); |
| 1430 | 1392 | ||
| @@ -1454,17 +1416,16 @@ void Config::SaveShortcutValues() { | |||
| 1454 | void Config::SaveSystemValues() { | 1416 | void Config::SaveSystemValues() { |
| 1455 | qt_config->beginGroup(QStringLiteral("System")); | 1417 | qt_config->beginGroup(QStringLiteral("System")); |
| 1456 | 1418 | ||
| 1457 | WriteSetting(QStringLiteral("current_user"), Settings::values.current_user, 0); | 1419 | WriteBasicSetting(Settings::values.current_user); |
| 1458 | WriteSettingGlobal(QStringLiteral("language_index"), Settings::values.language_index, 1); | 1420 | WriteGlobalSetting(Settings::values.language_index); |
| 1459 | WriteSettingGlobal(QStringLiteral("region_index"), Settings::values.region_index, 1); | 1421 | WriteGlobalSetting(Settings::values.region_index); |
| 1460 | WriteSettingGlobal(QStringLiteral("time_zone_index"), Settings::values.time_zone_index, 0); | 1422 | WriteGlobalSetting(Settings::values.time_zone_index); |
| 1461 | 1423 | ||
| 1462 | WriteSettingGlobal(QStringLiteral("rng_seed_enabled"), | 1424 | WriteSetting(QStringLiteral("rng_seed_enabled"), |
| 1463 | Settings::values.rng_seed.GetValue(global).has_value(), | 1425 | Settings::values.rng_seed.GetValue(global).has_value(), false, |
| 1464 | Settings::values.rng_seed.UsingGlobal(), false); | 1426 | Settings::values.rng_seed.UsingGlobal()); |
| 1465 | WriteSettingGlobal(QStringLiteral("rng_seed"), | 1427 | WriteSetting(QStringLiteral("rng_seed"), Settings::values.rng_seed.GetValue(global).value_or(0), |
| 1466 | Settings::values.rng_seed.GetValue(global).value_or(0), | 1428 | 0, Settings::values.rng_seed.UsingGlobal()); |
| 1467 | Settings::values.rng_seed.UsingGlobal(), 0); | ||
| 1468 | 1429 | ||
| 1469 | if (global) { | 1430 | if (global) { |
| 1470 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), | 1431 | WriteSetting(QStringLiteral("custom_rtc_enabled"), Settings::values.custom_rtc.has_value(), |
| @@ -1475,7 +1436,7 @@ void Config::SaveSystemValues() { | |||
| 1475 | 0); | 1436 | 0); |
| 1476 | } | 1437 | } |
| 1477 | 1438 | ||
| 1478 | WriteSettingGlobal(QStringLiteral("sound_index"), Settings::values.sound_index, 1); | 1439 | WriteGlobalSetting(Settings::values.sound_index); |
| 1479 | 1440 | ||
| 1480 | qt_config->endGroup(); | 1441 | qt_config->endGroup(); |
| 1481 | } | 1442 | } |
| @@ -1485,10 +1446,8 @@ void Config::SaveUIValues() { | |||
| 1485 | 1446 | ||
| 1486 | WriteSetting(QStringLiteral("theme"), UISettings::values.theme, | 1447 | WriteSetting(QStringLiteral("theme"), UISettings::values.theme, |
| 1487 | QString::fromUtf8(UISettings::themes[0].second)); | 1448 | QString::fromUtf8(UISettings::themes[0].second)); |
| 1488 | WriteSetting(QStringLiteral("enable_discord_presence"), | 1449 | WriteBasicSetting(UISettings::values.enable_discord_presence); |
| 1489 | UISettings::values.enable_discord_presence, true); | 1450 | WriteBasicSetting(UISettings::values.select_user_on_boot); |
| 1490 | WriteSetting(QStringLiteral("select_user_on_boot"), UISettings::values.select_user_on_boot, | ||
| 1491 | false); | ||
| 1492 | 1451 | ||
| 1493 | SaveUIGamelistValues(); | 1452 | SaveUIGamelistValues(); |
| 1494 | SaveUILayoutValues(); | 1453 | SaveUILayoutValues(); |
| @@ -1496,18 +1455,17 @@ void Config::SaveUIValues() { | |||
| 1496 | SaveScreenshotValues(); | 1455 | SaveScreenshotValues(); |
| 1497 | SaveShortcutValues(); | 1456 | SaveShortcutValues(); |
| 1498 | 1457 | ||
| 1499 | WriteSetting(QStringLiteral("singleWindowMode"), UISettings::values.single_window_mode, true); | 1458 | WriteBasicSetting(UISettings::values.single_window_mode); |
| 1500 | WriteSetting(QStringLiteral("fullscreen"), UISettings::values.fullscreen, false); | 1459 | WriteBasicSetting(UISettings::values.fullscreen); |
| 1501 | WriteSetting(QStringLiteral("displayTitleBars"), UISettings::values.display_titlebar, true); | 1460 | WriteBasicSetting(UISettings::values.display_titlebar); |
| 1502 | WriteSetting(QStringLiteral("showFilterBar"), UISettings::values.show_filter_bar, true); | 1461 | WriteBasicSetting(UISettings::values.show_filter_bar); |
| 1503 | WriteSetting(QStringLiteral("showStatusBar"), UISettings::values.show_status_bar, true); | 1462 | WriteBasicSetting(UISettings::values.show_status_bar); |
| 1504 | WriteSetting(QStringLiteral("confirmClose"), UISettings::values.confirm_before_closing, true); | 1463 | WriteBasicSetting(UISettings::values.confirm_before_closing); |
| 1505 | WriteSetting(QStringLiteral("firstStart"), UISettings::values.first_start, true); | 1464 | WriteBasicSetting(UISettings::values.first_start); |
| 1506 | WriteSetting(QStringLiteral("calloutFlags"), UISettings::values.callout_flags, 0); | 1465 | WriteBasicSetting(UISettings::values.callout_flags); |
| 1507 | WriteSetting(QStringLiteral("showConsole"), UISettings::values.show_console, false); | 1466 | WriteBasicSetting(UISettings::values.show_console); |
| 1508 | WriteSetting(QStringLiteral("pauseWhenInBackground"), | 1467 | WriteBasicSetting(UISettings::values.pause_when_in_background); |
| 1509 | UISettings::values.pause_when_in_background, false); | 1468 | WriteBasicSetting(UISettings::values.hide_mouse); |
| 1510 | WriteSetting(QStringLiteral("hideInactiveMouse"), UISettings::values.hide_mouse, false); | ||
| 1511 | 1469 | ||
| 1512 | qt_config->endGroup(); | 1470 | qt_config->endGroup(); |
| 1513 | } | 1471 | } |
| @@ -1515,11 +1473,11 @@ void Config::SaveUIValues() { | |||
| 1515 | void Config::SaveUIGamelistValues() { | 1473 | void Config::SaveUIGamelistValues() { |
| 1516 | qt_config->beginGroup(QStringLiteral("UIGameList")); | 1474 | qt_config->beginGroup(QStringLiteral("UIGameList")); |
| 1517 | 1475 | ||
| 1518 | WriteSetting(QStringLiteral("show_add_ons"), UISettings::values.show_add_ons, true); | 1476 | WriteBasicSetting(UISettings::values.show_add_ons); |
| 1519 | WriteSetting(QStringLiteral("icon_size"), UISettings::values.icon_size, 64); | 1477 | WriteBasicSetting(UISettings::values.icon_size); |
| 1520 | WriteSetting(QStringLiteral("row_1_text_id"), UISettings::values.row_1_text_id, 3); | 1478 | WriteBasicSetting(UISettings::values.row_1_text_id); |
| 1521 | WriteSetting(QStringLiteral("row_2_text_id"), UISettings::values.row_2_text_id, 2); | 1479 | WriteBasicSetting(UISettings::values.row_2_text_id); |
| 1522 | WriteSetting(QStringLiteral("cache_game_list"), UISettings::values.cache_game_list, true); | 1480 | WriteBasicSetting(UISettings::values.cache_game_list); |
| 1523 | qt_config->beginWriteArray(QStringLiteral("favorites")); | 1481 | qt_config->beginWriteArray(QStringLiteral("favorites")); |
| 1524 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { | 1482 | for (int i = 0; i < UISettings::values.favorited_ids.size(); i++) { |
| 1525 | qt_config->setArrayIndex(i); | 1483 | qt_config->setArrayIndex(i); |
| @@ -1540,8 +1498,7 @@ void Config::SaveUILayoutValues() { | |||
| 1540 | WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); | 1498 | WriteSetting(QStringLiteral("gameListHeaderState"), UISettings::values.gamelist_header_state); |
| 1541 | WriteSetting(QStringLiteral("microProfileDialogGeometry"), | 1499 | WriteSetting(QStringLiteral("microProfileDialogGeometry"), |
| 1542 | UISettings::values.microprofile_geometry); | 1500 | UISettings::values.microprofile_geometry); |
| 1543 | WriteSetting(QStringLiteral("microProfileDialogVisible"), | 1501 | WriteBasicSetting(UISettings::values.microprofile_visible); |
| 1544 | UISettings::values.microprofile_visible, false); | ||
| 1545 | 1502 | ||
| 1546 | qt_config->endGroup(); | 1503 | qt_config->endGroup(); |
| 1547 | } | 1504 | } |
| @@ -1549,13 +1506,10 @@ void Config::SaveUILayoutValues() { | |||
| 1549 | void Config::SaveWebServiceValues() { | 1506 | void Config::SaveWebServiceValues() { |
| 1550 | qt_config->beginGroup(QStringLiteral("WebService")); | 1507 | qt_config->beginGroup(QStringLiteral("WebService")); |
| 1551 | 1508 | ||
| 1552 | WriteSetting(QStringLiteral("enable_telemetry"), Settings::values.enable_telemetry, true); | 1509 | WriteBasicSetting(Settings::values.enable_telemetry); |
| 1553 | WriteSetting(QStringLiteral("web_api_url"), | 1510 | WriteBasicSetting(Settings::values.web_api_url); |
| 1554 | QString::fromStdString(Settings::values.web_api_url), | 1511 | WriteBasicSetting(Settings::values.yuzu_username); |
| 1555 | QStringLiteral("https://api.yuzu-emu.org")); | 1512 | WriteBasicSetting(Settings::values.yuzu_token); |
| 1556 | WriteSetting(QStringLiteral("yuzu_username"), | ||
| 1557 | QString::fromStdString(Settings::values.yuzu_username)); | ||
| 1558 | WriteSetting(QStringLiteral("yuzu_token"), QString::fromStdString(Settings::values.yuzu_token)); | ||
| 1559 | 1513 | ||
| 1560 | qt_config->endGroup(); | 1514 | qt_config->endGroup(); |
| 1561 | } | 1515 | } |
| @@ -1575,21 +1529,14 @@ QVariant Config::ReadSetting(const QString& name, const QVariant& default_value) | |||
| 1575 | } | 1529 | } |
| 1576 | 1530 | ||
| 1577 | template <typename Type> | 1531 | template <typename Type> |
| 1578 | void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name) { | 1532 | void Config::ReadGlobalSetting(Settings::Setting<Type>& setting) { |
| 1579 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | 1533 | QString name = QString::fromStdString(setting.GetLabel()); |
| 1580 | setting.SetGlobal(use_global); | ||
| 1581 | if (global || !use_global) { | ||
| 1582 | setting.SetValue(ReadSetting(name).value<Type>()); | ||
| 1583 | } | ||
| 1584 | } | ||
| 1585 | |||
| 1586 | template <typename Type> | ||
| 1587 | void Config::ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name, | ||
| 1588 | const QVariant& default_value) { | ||
| 1589 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); | 1534 | const bool use_global = qt_config->value(name + QStringLiteral("/use_global"), true).toBool(); |
| 1590 | setting.SetGlobal(use_global); | 1535 | setting.SetGlobal(use_global); |
| 1591 | if (global || !use_global) { | 1536 | if (global || !use_global) { |
| 1592 | setting.SetValue(ReadSetting(name, default_value).value<Type>()); | 1537 | setting.SetValue(static_cast<QVariant>( |
| 1538 | ReadSetting(name, QVariant::fromValue<Type>(setting.GetDefault()))) | ||
| 1539 | .value<Type>()); | ||
| 1593 | } | 1540 | } |
| 1594 | } | 1541 | } |
| 1595 | 1542 | ||
| @@ -1612,31 +1559,8 @@ void Config::WriteSetting(const QString& name, const QVariant& value, | |||
| 1612 | qt_config->setValue(name, value); | 1559 | qt_config->setValue(name, value); |
| 1613 | } | 1560 | } |
| 1614 | 1561 | ||
| 1615 | template <typename Type> | 1562 | void Config::WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, |
| 1616 | void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting) { | 1563 | bool use_global) { |
| 1617 | if (!global) { | ||
| 1618 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 1619 | } | ||
| 1620 | if (global || !setting.UsingGlobal()) { | ||
| 1621 | qt_config->setValue(name, setting.GetValue(global)); | ||
| 1622 | } | ||
| 1623 | } | ||
| 1624 | |||
| 1625 | template <typename Type> | ||
| 1626 | void Config::WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting, | ||
| 1627 | const QVariant& default_value) { | ||
| 1628 | if (!global) { | ||
| 1629 | qt_config->setValue(name + QStringLiteral("/use_global"), setting.UsingGlobal()); | ||
| 1630 | } | ||
| 1631 | if (global || !setting.UsingGlobal()) { | ||
| 1632 | qt_config->setValue(name + QStringLiteral("/default"), | ||
| 1633 | setting.GetValue(global) == default_value.value<Type>()); | ||
| 1634 | qt_config->setValue(name, setting.GetValue(global)); | ||
| 1635 | } | ||
| 1636 | } | ||
| 1637 | |||
| 1638 | void Config::WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | ||
| 1639 | const QVariant& default_value) { | ||
| 1640 | if (!global) { | 1564 | if (!global) { |
| 1641 | qt_config->setValue(name + QStringLiteral("/use_global"), use_global); | 1565 | qt_config->setValue(name + QStringLiteral("/use_global"), use_global); |
| 1642 | } | 1566 | } |
diff --git a/src/yuzu/configuration/config.h b/src/yuzu/configuration/config.h index 3c1de0ac9..96f9b6de1 100644 --- a/src/yuzu/configuration/config.h +++ b/src/yuzu/configuration/config.h | |||
| @@ -102,28 +102,75 @@ private: | |||
| 102 | void SaveUILayoutValues(); | 102 | void SaveUILayoutValues(); |
| 103 | void SaveWebServiceValues(); | 103 | void SaveWebServiceValues(); |
| 104 | 104 | ||
| 105 | /** | ||
| 106 | * Reads a setting from the qt_config. | ||
| 107 | * | ||
| 108 | * @param name The setting's identifier | ||
| 109 | * @param default_value The value to use when the setting is not already present in the config | ||
| 110 | */ | ||
| 105 | QVariant ReadSetting(const QString& name) const; | 111 | QVariant ReadSetting(const QString& name) const; |
| 106 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; | 112 | QVariant ReadSetting(const QString& name, const QVariant& default_value) const; |
| 107 | // Templated ReadSettingGlobal functions will also look for the use_global setting and set | 113 | |
| 108 | // both the value and the global state properly | 114 | /** |
| 109 | template <typename Type> | 115 | * Only reads a setting from the qt_config if the current config is a global config, or if the |
| 110 | void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name); | 116 | * current config is a custom config and the setting is overriding the global setting. Otherwise |
| 111 | template <typename Type> | 117 | * it does nothing. |
| 112 | void ReadSettingGlobal(Settings::Setting<Type>& setting, const QString& name, | 118 | * |
| 113 | const QVariant& default_value); | 119 | * @param setting The variable to be modified |
| 120 | * @param name The setting's identifier | ||
| 121 | * @param default_value The value to use when the setting is not already present in the config | ||
| 122 | */ | ||
| 114 | template <typename Type> | 123 | template <typename Type> |
| 115 | void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const; | 124 | void ReadSettingGlobal(Type& setting, const QString& name, const QVariant& default_value) const; |
| 116 | // Templated WriteSettingGlobal functions will also write the global state if needed and will | 125 | |
| 117 | // skip writing the actual setting if it defers to the global value | 126 | /** |
| 127 | * Writes a setting to the qt_config. | ||
| 128 | * | ||
| 129 | * @param name The setting's idetentifier | ||
| 130 | * @param value Value of the setting | ||
| 131 | * @param default_value Default of the setting if not present in qt_config | ||
| 132 | * @param use_global Specifies if the custom or global config should be in use, for custom | ||
| 133 | * configs | ||
| 134 | */ | ||
| 118 | void WriteSetting(const QString& name, const QVariant& value); | 135 | void WriteSetting(const QString& name, const QVariant& value); |
| 119 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); | 136 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value); |
| 137 | void WriteSetting(const QString& name, const QVariant& value, const QVariant& default_value, | ||
| 138 | bool use_global); | ||
| 139 | |||
| 140 | /** | ||
| 141 | * Reads a value from the qt_config and applies it to the setting, using its label and default | ||
| 142 | * value. If the config is a custom config, this will also read the global state of the setting | ||
| 143 | * and apply that information to it. | ||
| 144 | * | ||
| 145 | * @param The setting | ||
| 146 | */ | ||
| 120 | template <typename Type> | 147 | template <typename Type> |
| 121 | void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting); | 148 | void ReadGlobalSetting(Settings::Setting<Type>& setting); |
| 149 | |||
| 150 | /** | ||
| 151 | * Sets a value to the qt_config using the setting's label and default value. If the config is a | ||
| 152 | * custom config, it will apply the global state, and the custom value if needed. | ||
| 153 | * | ||
| 154 | * @param The setting | ||
| 155 | */ | ||
| 156 | template <typename Type> | ||
| 157 | void WriteGlobalSetting(const Settings::Setting<Type>& setting); | ||
| 158 | |||
| 159 | /** | ||
| 160 | * Reads a value from the qt_config using the setting's label and default value and applies the | ||
| 161 | * value to the setting. | ||
| 162 | * | ||
| 163 | * @param The setting | ||
| 164 | */ | ||
| 165 | template <typename Type> | ||
| 166 | void ReadBasicSetting(Settings::BasicSetting<Type>& setting); | ||
| 167 | |||
| 168 | /** Sets a value from the setting in the qt_config using the setting's label and default value. | ||
| 169 | * | ||
| 170 | * @param The setting | ||
| 171 | */ | ||
| 122 | template <typename Type> | 172 | template <typename Type> |
| 123 | void WriteSettingGlobal(const QString& name, const Settings::Setting<Type>& setting, | 173 | void WriteBasicSetting(const Settings::BasicSetting<Type>& setting); |
| 124 | const QVariant& default_value); | ||
| 125 | void WriteSettingGlobal(const QString& name, const QVariant& value, bool use_global, | ||
| 126 | const QVariant& default_value); | ||
| 127 | 174 | ||
| 128 | ConfigType type; | 175 | ConfigType type; |
| 129 | std::unique_ptr<QSettings> qt_config; | 176 | std::unique_ptr<QSettings> qt_config; |
diff --git a/src/yuzu/configuration/configure.ui b/src/yuzu/configuration/configure.ui index f92c3aff3..fca9aed5f 100644 --- a/src/yuzu/configuration/configure.ui +++ b/src/yuzu/configuration/configure.ui | |||
| @@ -41,7 +41,7 @@ | |||
| 41 | <item> | 41 | <item> |
| 42 | <widget class="QTabWidget" name="tabWidget"> | 42 | <widget class="QTabWidget" name="tabWidget"> |
| 43 | <property name="currentIndex"> | 43 | <property name="currentIndex"> |
| 44 | <number>0</number> | 44 | <number>11</number> |
| 45 | </property> | 45 | </property> |
| 46 | <widget class="ConfigureGeneral" name="generalTab"> | 46 | <widget class="ConfigureGeneral" name="generalTab"> |
| 47 | <property name="accessibleName"> | 47 | <property name="accessibleName"> |
| @@ -107,14 +107,6 @@ | |||
| 107 | <string>CPU</string> | 107 | <string>CPU</string> |
| 108 | </attribute> | 108 | </attribute> |
| 109 | </widget> | 109 | </widget> |
| 110 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> | ||
| 111 | <property name="accessibleName"> | ||
| 112 | <string>Debug</string> | ||
| 113 | </property> | ||
| 114 | <attribute name="title"> | ||
| 115 | <string>Debug</string> | ||
| 116 | </attribute> | ||
| 117 | </widget> | ||
| 118 | <widget class="ConfigureGraphics" name="graphicsTab"> | 110 | <widget class="ConfigureGraphics" name="graphicsTab"> |
| 119 | <property name="accessibleName"> | 111 | <property name="accessibleName"> |
| 120 | <string>Graphics</string> | 112 | <string>Graphics</string> |
| @@ -139,7 +131,7 @@ | |||
| 139 | <string>Audio</string> | 131 | <string>Audio</string> |
| 140 | </attribute> | 132 | </attribute> |
| 141 | </widget> | 133 | </widget> |
| 142 | <widget class="ConfigureDebug" name="debugTab"> | 134 | <widget class="ConfigureDebugTab" name="debugTab"> |
| 143 | <property name="accessibleName"> | 135 | <property name="accessibleName"> |
| 144 | <string>Debug</string> | 136 | <string>Debug</string> |
| 145 | </property> | 137 | </property> |
| @@ -208,24 +200,12 @@ | |||
| 208 | <container>1</container> | 200 | <container>1</container> |
| 209 | </customwidget> | 201 | </customwidget> |
| 210 | <customwidget> | 202 | <customwidget> |
| 211 | <class>ConfigureDebug</class> | ||
| 212 | <extends>QWidget</extends> | ||
| 213 | <header>configuration/configure_debug.h</header> | ||
| 214 | <container>1</container> | ||
| 215 | </customwidget> | ||
| 216 | <customwidget> | ||
| 217 | <class>ConfigureCpu</class> | 203 | <class>ConfigureCpu</class> |
| 218 | <extends>QWidget</extends> | 204 | <extends>QWidget</extends> |
| 219 | <header>configuration/configure_cpu.h</header> | 205 | <header>configuration/configure_cpu.h</header> |
| 220 | <container>1</container> | 206 | <container>1</container> |
| 221 | </customwidget> | 207 | </customwidget> |
| 222 | <customwidget> | 208 | <customwidget> |
| 223 | <class>ConfigureCpuDebug</class> | ||
| 224 | <extends>QWidget</extends> | ||
| 225 | <header>configuration/configure_cpu_debug.h</header> | ||
| 226 | <container>1</container> | ||
| 227 | </customwidget> | ||
| 228 | <customwidget> | ||
| 229 | <class>ConfigureGraphics</class> | 209 | <class>ConfigureGraphics</class> |
| 230 | <extends>QWidget</extends> | 210 | <extends>QWidget</extends> |
| 231 | <header>configuration/configure_graphics.h</header> | 211 | <header>configuration/configure_graphics.h</header> |
| @@ -267,6 +247,12 @@ | |||
| 267 | <header>configuration/configure_service.h</header> | 247 | <header>configuration/configure_service.h</header> |
| 268 | <container>1</container> | 248 | <container>1</container> |
| 269 | </customwidget> | 249 | </customwidget> |
| 250 | <customwidget> | ||
| 251 | <class>ConfigureDebugTab</class> | ||
| 252 | <extends>QWidget</extends> | ||
| 253 | <header>configuration/configure_debug_tab.h</header> | ||
| 254 | <container>1</container> | ||
| 255 | </customwidget> | ||
| 270 | </customwidgets> | 256 | </customwidgets> |
| 271 | <resources/> | 257 | <resources/> |
| 272 | <connections> | 258 | <connections> |
| @@ -275,12 +261,32 @@ | |||
| 275 | <signal>accepted()</signal> | 261 | <signal>accepted()</signal> |
| 276 | <receiver>ConfigureDialog</receiver> | 262 | <receiver>ConfigureDialog</receiver> |
| 277 | <slot>accept()</slot> | 263 | <slot>accept()</slot> |
| 264 | <hints> | ||
| 265 | <hint type="sourcelabel"> | ||
| 266 | <x>20</x> | ||
| 267 | <y>20</y> | ||
| 268 | </hint> | ||
| 269 | <hint type="destinationlabel"> | ||
| 270 | <x>20</x> | ||
| 271 | <y>20</y> | ||
| 272 | </hint> | ||
| 273 | </hints> | ||
| 278 | </connection> | 274 | </connection> |
| 279 | <connection> | 275 | <connection> |
| 280 | <sender>buttonBox</sender> | 276 | <sender>buttonBox</sender> |
| 281 | <signal>rejected()</signal> | 277 | <signal>rejected()</signal> |
| 282 | <receiver>ConfigureDialog</receiver> | 278 | <receiver>ConfigureDialog</receiver> |
| 283 | <slot>reject()</slot> | 279 | <slot>reject()</slot> |
| 280 | <hints> | ||
| 281 | <hint type="sourcelabel"> | ||
| 282 | <x>20</x> | ||
| 283 | <y>20</y> | ||
| 284 | </hint> | ||
| 285 | <hint type="destinationlabel"> | ||
| 286 | <x>20</x> | ||
| 287 | <y>20</y> | ||
| 288 | </hint> | ||
| 289 | </hints> | ||
| 284 | </connection> | 290 | </connection> |
| 285 | </connections> | 291 | </connections> |
| 286 | </ui> | 292 | </ui> |
diff --git a/src/yuzu/configuration/configure_audio.cpp b/src/yuzu/configuration/configure_audio.cpp index fc0191432..5aba1a3b2 100644 --- a/src/yuzu/configuration/configure_audio.cpp +++ b/src/yuzu/configuration/configure_audio.cpp | |||
| @@ -69,7 +69,7 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| 69 | [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box); | 69 | [[maybe_unused]] const QSignalBlocker blocker(ui->output_sink_combo_box); |
| 70 | 70 | ||
| 71 | int new_sink_index = 0; | 71 | int new_sink_index = 0; |
| 72 | const QString sink_id = QString::fromStdString(Settings::values.sink_id); | 72 | const QString sink_id = QString::fromStdString(Settings::values.sink_id.GetValue()); |
| 73 | for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { | 73 | for (int index = 0; index < ui->output_sink_combo_box->count(); index++) { |
| 74 | if (ui->output_sink_combo_box->itemText(index) == sink_id) { | 74 | if (ui->output_sink_combo_box->itemText(index) == sink_id) { |
| 75 | new_sink_index = index; | 75 | new_sink_index = index; |
| @@ -83,7 +83,7 @@ void ConfigureAudio::SetOutputSinkFromSinkID() { | |||
| 83 | void ConfigureAudio::SetAudioDeviceFromDeviceID() { | 83 | void ConfigureAudio::SetAudioDeviceFromDeviceID() { |
| 84 | int new_device_index = -1; | 84 | int new_device_index = -1; |
| 85 | 85 | ||
| 86 | const QString device_id = QString::fromStdString(Settings::values.audio_device_id); | 86 | const QString device_id = QString::fromStdString(Settings::values.audio_device_id.GetValue()); |
| 87 | for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { | 87 | for (int index = 0; index < ui->audio_device_combo_box->count(); index++) { |
| 88 | if (ui->audio_device_combo_box->itemText(index) == device_id) { | 88 | if (ui->audio_device_combo_box->itemText(index) == device_id) { |
| 89 | new_device_index = index; | 89 | new_device_index = index; |
| @@ -106,9 +106,9 @@ void ConfigureAudio::ApplyConfiguration() { | |||
| 106 | Settings::values.sink_id = | 106 | Settings::values.sink_id = |
| 107 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) | 107 | ui->output_sink_combo_box->itemText(ui->output_sink_combo_box->currentIndex()) |
| 108 | .toStdString(); | 108 | .toStdString(); |
| 109 | Settings::values.audio_device_id = | 109 | Settings::values.audio_device_id.SetValue( |
| 110 | ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) | 110 | ui->audio_device_combo_box->itemText(ui->audio_device_combo_box->currentIndex()) |
| 111 | .toStdString(); | 111 | .toStdString()); |
| 112 | 112 | ||
| 113 | // Guard if during game and set to game-specific value | 113 | // Guard if during game and set to game-specific value |
| 114 | if (Settings::values.volume.UsingGlobal()) { | 114 | if (Settings::values.volume.UsingGlobal()) { |
diff --git a/src/yuzu/configuration/configure_cpu.cpp b/src/yuzu/configuration/configure_cpu.cpp index 13db2ba98..8d7171487 100644 --- a/src/yuzu/configuration/configure_cpu.cpp +++ b/src/yuzu/configuration/configure_cpu.cpp | |||
| @@ -20,8 +20,6 @@ ConfigureCpu::ConfigureCpu(QWidget* parent) : QWidget(parent), ui(new Ui::Config | |||
| 20 | 20 | ||
| 21 | SetConfiguration(); | 21 | SetConfiguration(); |
| 22 | 22 | ||
| 23 | connect(ui->accuracy, qOverload<int>(&QComboBox::activated), this, | ||
| 24 | &ConfigureCpu::AccuracyUpdated); | ||
| 25 | connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this, | 23 | connect(ui->accuracy, qOverload<int>(&QComboBox::currentIndexChanged), this, |
| 26 | &ConfigureCpu::UpdateGroup); | 24 | &ConfigureCpu::UpdateGroup); |
| 27 | } | 25 | } |
| @@ -58,20 +56,6 @@ void ConfigureCpu::SetConfiguration() { | |||
| 58 | UpdateGroup(ui->accuracy->currentIndex()); | 56 | UpdateGroup(ui->accuracy->currentIndex()); |
| 59 | } | 57 | } |
| 60 | 58 | ||
| 61 | void ConfigureCpu::AccuracyUpdated(int index) { | ||
| 62 | if (Settings::IsConfiguringGlobal() && | ||
| 63 | static_cast<Settings::CPUAccuracy>(index) == Settings::CPUAccuracy::DebugMode) { | ||
| 64 | const auto result = QMessageBox::warning(this, tr("Setting CPU to Debug Mode"), | ||
| 65 | tr("CPU Debug Mode is only intended for developer " | ||
| 66 | "use. Are you sure you want to enable this?"), | ||
| 67 | QMessageBox::Yes | QMessageBox::No); | ||
| 68 | if (result == QMessageBox::No) { | ||
| 69 | ui->accuracy->setCurrentIndex(static_cast<int>(Settings::CPUAccuracy::Accurate)); | ||
| 70 | UpdateGroup(static_cast<int>(Settings::CPUAccuracy::Accurate)); | ||
| 71 | } | ||
| 72 | } | ||
| 73 | } | ||
| 74 | |||
| 75 | void ConfigureCpu::UpdateGroup(int index) { | 59 | void ConfigureCpu::UpdateGroup(int index) { |
| 76 | if (!Settings::IsConfiguringGlobal()) { | 60 | if (!Settings::IsConfiguringGlobal()) { |
| 77 | index -= ConfigurationShared::USE_GLOBAL_OFFSET; | 61 | index -= ConfigurationShared::USE_GLOBAL_OFFSET; |
| @@ -134,8 +118,6 @@ void ConfigureCpu::SetupPerGameUI() { | |||
| 134 | ConfigurationShared::SetColoredComboBox( | 118 | ConfigurationShared::SetColoredComboBox( |
| 135 | ui->accuracy, ui->widget_accuracy, | 119 | ui->accuracy, ui->widget_accuracy, |
| 136 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true))); | 120 | static_cast<u32>(Settings::values.cpu_accuracy.GetValue(true))); |
| 137 | ui->accuracy->removeItem(static_cast<u32>(Settings::CPUAccuracy::DebugMode) + | ||
| 138 | ConfigurationShared::USE_GLOBAL_OFFSET); | ||
| 139 | 121 | ||
| 140 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma, | 122 | ConfigurationShared::SetColoredTristate(ui->cpuopt_unsafe_unfuse_fma, |
| 141 | Settings::values.cpuopt_unsafe_unfuse_fma, | 123 | Settings::values.cpuopt_unsafe_unfuse_fma, |
diff --git a/src/yuzu/configuration/configure_cpu.h b/src/yuzu/configuration/configure_cpu.h index b2b5f1671..154931482 100644 --- a/src/yuzu/configuration/configure_cpu.h +++ b/src/yuzu/configuration/configure_cpu.h | |||
| @@ -29,7 +29,6 @@ private: | |||
| 29 | void changeEvent(QEvent* event) override; | 29 | void changeEvent(QEvent* event) override; |
| 30 | void RetranslateUI(); | 30 | void RetranslateUI(); |
| 31 | 31 | ||
| 32 | void AccuracyUpdated(int index); | ||
| 33 | void UpdateGroup(int index); | 32 | void UpdateGroup(int index); |
| 34 | 33 | ||
| 35 | void SetConfiguration(); | 34 | void SetConfiguration(); |
diff --git a/src/yuzu/configuration/configure_cpu.ui b/src/yuzu/configuration/configure_cpu.ui index 0e296d4e5..5b9457faf 100644 --- a/src/yuzu/configuration/configure_cpu.ui +++ b/src/yuzu/configuration/configure_cpu.ui | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>400</width> | 9 | <width>448</width> |
| 10 | <height>321</height> | 10 | <height>433</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| @@ -17,7 +17,7 @@ | |||
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout"> | 18 | <layout class="QVBoxLayout"> |
| 19 | <item> | 19 | <item> |
| 20 | <widget class="QGroupBox"> | 20 | <widget class="QGroupBox" name="groupBox"> |
| 21 | <property name="title"> | 21 | <property name="title"> |
| 22 | <string>General</string> | 22 | <string>General</string> |
| 23 | </property> | 23 | </property> |
| @@ -36,17 +36,17 @@ | |||
| 36 | <widget class="QComboBox" name="accuracy"> | 36 | <widget class="QComboBox" name="accuracy"> |
| 37 | <item> | 37 | <item> |
| 38 | <property name="text"> | 38 | <property name="text"> |
| 39 | <string>Accurate</string> | 39 | <string>Auto</string> |
| 40 | </property> | 40 | </property> |
| 41 | </item> | 41 | </item> |
| 42 | <item> | 42 | <item> |
| 43 | <property name="text"> | 43 | <property name="text"> |
| 44 | <string>Unsafe</string> | 44 | <string>Accurate</string> |
| 45 | </property> | 45 | </property> |
| 46 | </item> | 46 | </item> |
| 47 | <item> | 47 | <item> |
| 48 | <property name="text"> | 48 | <property name="text"> |
| 49 | <string>Enable Debug Mode</string> | 49 | <string>Unsafe</string> |
| 50 | </property> | 50 | </property> |
| 51 | </item> | 51 | </item> |
| 52 | </widget> | 52 | </widget> |
| @@ -57,7 +57,7 @@ | |||
| 57 | <item> | 57 | <item> |
| 58 | <widget class="QLabel" name="label_recommended_accuracy"> | 58 | <widget class="QLabel" name="label_recommended_accuracy"> |
| 59 | <property name="text"> | 59 | <property name="text"> |
| 60 | <string>We recommend setting accuracy to "Accurate".</string> | 60 | <string>We recommend setting accuracy to "Auto".</string> |
| 61 | </property> | 61 | </property> |
| 62 | <property name="wordWrap"> | 62 | <property name="wordWrap"> |
| 63 | <bool>false</bool> | 63 | <bool>false</bool> |
diff --git a/src/yuzu/configuration/configure_cpu_debug.cpp b/src/yuzu/configuration/configure_cpu_debug.cpp index e25c52baf..98e2d2be5 100644 --- a/src/yuzu/configuration/configure_cpu_debug.cpp +++ b/src/yuzu/configuration/configure_cpu_debug.cpp | |||
| @@ -24,23 +24,26 @@ void ConfigureCpuDebug::SetConfiguration() { | |||
| 24 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 24 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 25 | 25 | ||
| 26 | ui->cpuopt_page_tables->setEnabled(runtime_lock); | 26 | ui->cpuopt_page_tables->setEnabled(runtime_lock); |
| 27 | ui->cpuopt_page_tables->setChecked(Settings::values.cpuopt_page_tables); | 27 | ui->cpuopt_page_tables->setChecked(Settings::values.cpuopt_page_tables.GetValue()); |
| 28 | ui->cpuopt_block_linking->setEnabled(runtime_lock); | 28 | ui->cpuopt_block_linking->setEnabled(runtime_lock); |
| 29 | ui->cpuopt_block_linking->setChecked(Settings::values.cpuopt_block_linking); | 29 | ui->cpuopt_block_linking->setChecked(Settings::values.cpuopt_block_linking.GetValue()); |
| 30 | ui->cpuopt_return_stack_buffer->setEnabled(runtime_lock); | 30 | ui->cpuopt_return_stack_buffer->setEnabled(runtime_lock); |
| 31 | ui->cpuopt_return_stack_buffer->setChecked(Settings::values.cpuopt_return_stack_buffer); | 31 | ui->cpuopt_return_stack_buffer->setChecked( |
| 32 | Settings::values.cpuopt_return_stack_buffer.GetValue()); | ||
| 32 | ui->cpuopt_fast_dispatcher->setEnabled(runtime_lock); | 33 | ui->cpuopt_fast_dispatcher->setEnabled(runtime_lock); |
| 33 | ui->cpuopt_fast_dispatcher->setChecked(Settings::values.cpuopt_fast_dispatcher); | 34 | ui->cpuopt_fast_dispatcher->setChecked(Settings::values.cpuopt_fast_dispatcher.GetValue()); |
| 34 | ui->cpuopt_context_elimination->setEnabled(runtime_lock); | 35 | ui->cpuopt_context_elimination->setEnabled(runtime_lock); |
| 35 | ui->cpuopt_context_elimination->setChecked(Settings::values.cpuopt_context_elimination); | 36 | ui->cpuopt_context_elimination->setChecked( |
| 37 | Settings::values.cpuopt_context_elimination.GetValue()); | ||
| 36 | ui->cpuopt_const_prop->setEnabled(runtime_lock); | 38 | ui->cpuopt_const_prop->setEnabled(runtime_lock); |
| 37 | ui->cpuopt_const_prop->setChecked(Settings::values.cpuopt_const_prop); | 39 | ui->cpuopt_const_prop->setChecked(Settings::values.cpuopt_const_prop.GetValue()); |
| 38 | ui->cpuopt_misc_ir->setEnabled(runtime_lock); | 40 | ui->cpuopt_misc_ir->setEnabled(runtime_lock); |
| 39 | ui->cpuopt_misc_ir->setChecked(Settings::values.cpuopt_misc_ir); | 41 | ui->cpuopt_misc_ir->setChecked(Settings::values.cpuopt_misc_ir.GetValue()); |
| 40 | ui->cpuopt_reduce_misalign_checks->setEnabled(runtime_lock); | 42 | ui->cpuopt_reduce_misalign_checks->setEnabled(runtime_lock); |
| 41 | ui->cpuopt_reduce_misalign_checks->setChecked(Settings::values.cpuopt_reduce_misalign_checks); | 43 | ui->cpuopt_reduce_misalign_checks->setChecked( |
| 44 | Settings::values.cpuopt_reduce_misalign_checks.GetValue()); | ||
| 42 | ui->cpuopt_fastmem->setEnabled(runtime_lock); | 45 | ui->cpuopt_fastmem->setEnabled(runtime_lock); |
| 43 | ui->cpuopt_fastmem->setChecked(Settings::values.cpuopt_fastmem); | 46 | ui->cpuopt_fastmem->setChecked(Settings::values.cpuopt_fastmem.GetValue()); |
| 44 | } | 47 | } |
| 45 | 48 | ||
| 46 | void ConfigureCpuDebug::ApplyConfiguration() { | 49 | void ConfigureCpuDebug::ApplyConfiguration() { |
diff --git a/src/yuzu/configuration/configure_cpu_debug.h b/src/yuzu/configuration/configure_cpu_debug.h index 10de55099..1b0d8050c 100644 --- a/src/yuzu/configuration/configure_cpu_debug.h +++ b/src/yuzu/configuration/configure_cpu_debug.h | |||
| @@ -6,7 +6,6 @@ | |||
| 6 | 6 | ||
| 7 | #include <memory> | 7 | #include <memory> |
| 8 | #include <QWidget> | 8 | #include <QWidget> |
| 9 | #include "common/settings.h" | ||
| 10 | 9 | ||
| 11 | namespace Ui { | 10 | namespace Ui { |
| 12 | class ConfigureCpuDebug; | 11 | class ConfigureCpuDebug; |
diff --git a/src/yuzu/configuration/configure_cpu_debug.ui b/src/yuzu/configuration/configure_cpu_debug.ui index c43f89a5a..abf469b55 100644 --- a/src/yuzu/configuration/configure_cpu_debug.ui +++ b/src/yuzu/configuration/configure_cpu_debug.ui | |||
| @@ -6,8 +6,8 @@ | |||
| 6 | <rect> | 6 | <rect> |
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>400</width> | 9 | <width>592</width> |
| 10 | <height>321</height> | 10 | <height>503</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| @@ -17,140 +17,132 @@ | |||
| 17 | <item> | 17 | <item> |
| 18 | <layout class="QVBoxLayout"> | 18 | <layout class="QVBoxLayout"> |
| 19 | <item> | 19 | <item> |
| 20 | <widget class="QGroupBox"> | 20 | <widget class="QGroupBox" name="groupBox"> |
| 21 | <property name="title"> | 21 | <property name="title"> |
| 22 | <string>Toggle CPU Optimizations</string> | 22 | <string>Toggle CPU Optimizations</string> |
| 23 | </property> | 23 | </property> |
| 24 | <layout class="QVBoxLayout"> | 24 | <layout class="QVBoxLayout"> |
| 25 | <item> | 25 | <item> |
| 26 | <widget class="QLabel"> | 26 | <widget class="QLabel" name="label"> |
| 27 | <property name="wordWrap"> | ||
| 28 | <bool>1</bool> | ||
| 29 | </property> | ||
| 30 | <property name="text"> | 27 | <property name="text"> |
| 31 | <string> | 28 | <string><html><head/><body><p><span style=" font-weight:600;">For debugging only.</span><br/>If you're not sure what these do, keep all of these enabled. <br/>These settings, when disabled, only take effect when CPU Debugging is enabled. </p></body></html></string> |
| 32 | <div> | 29 | </property> |
| 33 | <b>For debugging only.</b> | 30 | <property name="wordWrap"> |
| 34 | <br> | 31 | <bool>false</bool> |
| 35 | If you're not sure what these do, keep all of these enabled. | ||
| 36 | <br> | ||
| 37 | These settings, when disabled, only take effect when CPU Accuracy is "Debug Mode". | ||
| 38 | </div> | ||
| 39 | </string> | ||
| 40 | </property> | 32 | </property> |
| 41 | </widget> | 33 | </widget> |
| 42 | </item> | 34 | </item> |
| 43 | <item> | 35 | <item> |
| 44 | <widget class="QCheckBox" name="cpuopt_page_tables"> | 36 | <widget class="QCheckBox" name="cpuopt_page_tables"> |
| 45 | <property name="text"> | ||
| 46 | <string>Enable inline page tables</string> | ||
| 47 | </property> | ||
| 48 | <property name="toolTip"> | 37 | <property name="toolTip"> |
| 49 | <string> | 38 | <string> |
| 50 | <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div> | 39 | <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div> |
| 51 | <div style="white-space: nowrap">Enabling it inlines accesses to PageTable::pointers into emitted code.</div> | 40 | <div style="white-space: nowrap">Enabling it inlines accesses to PageTable::pointers into emitted code.</div> |
| 52 | <div style="white-space: nowrap">Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.</div> | 41 | <div style="white-space: nowrap">Disabling this forces all memory accesses to go through the Memory::Read/Memory::Write functions.</div> |
| 53 | </string> | 42 | </string> |
| 54 | </property> | 43 | </property> |
| 44 | <property name="text"> | ||
| 45 | <string>Enable inline page tables</string> | ||
| 46 | </property> | ||
| 55 | </widget> | 47 | </widget> |
| 56 | </item> | 48 | </item> |
| 57 | <item> | 49 | <item> |
| 58 | <widget class="QCheckBox" name="cpuopt_block_linking"> | 50 | <widget class="QCheckBox" name="cpuopt_block_linking"> |
| 59 | <property name="text"> | ||
| 60 | <string>Enable block linking</string> | ||
| 61 | </property> | ||
| 62 | <property name="toolTip"> | 51 | <property name="toolTip"> |
| 63 | <string> | 52 | <string> |
| 64 | <div>This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.</div> | 53 | <div>This optimization avoids dispatcher lookups by allowing emitted basic blocks to jump directly to other basic blocks if the destination PC is static.</div> |
| 65 | </string> | 54 | </string> |
| 66 | </property> | 55 | </property> |
| 56 | <property name="text"> | ||
| 57 | <string>Enable block linking</string> | ||
| 58 | </property> | ||
| 67 | </widget> | 59 | </widget> |
| 68 | </item> | 60 | </item> |
| 69 | <item> | 61 | <item> |
| 70 | <widget class="QCheckBox" name="cpuopt_return_stack_buffer"> | 62 | <widget class="QCheckBox" name="cpuopt_return_stack_buffer"> |
| 71 | <property name="text"> | ||
| 72 | <string>Enable return stack buffer</string> | ||
| 73 | </property> | ||
| 74 | <property name="toolTip"> | 63 | <property name="toolTip"> |
| 75 | <string> | 64 | <string> |
| 76 | <div>This optimization avoids dispatcher lookups by keeping track potential return addresses of BL instructions. This approximates what happens with a return stack buffer on a real CPU.</div> | 65 | <div>This optimization avoids dispatcher lookups by keeping track potential return addresses of BL instructions. This approximates what happens with a return stack buffer on a real CPU.</div> |
| 77 | </string> | 66 | </string> |
| 78 | </property> | 67 | </property> |
| 68 | <property name="text"> | ||
| 69 | <string>Enable return stack buffer</string> | ||
| 70 | </property> | ||
| 79 | </widget> | 71 | </widget> |
| 80 | </item> | 72 | </item> |
| 81 | <item> | 73 | <item> |
| 82 | <widget class="QCheckBox" name="cpuopt_fast_dispatcher"> | 74 | <widget class="QCheckBox" name="cpuopt_fast_dispatcher"> |
| 83 | <property name="text"> | ||
| 84 | <string>Enable fast dispatcher</string> | ||
| 85 | </property> | ||
| 86 | <property name="toolTip"> | 75 | <property name="toolTip"> |
| 87 | <string> | 76 | <string> |
| 88 | <div>Enable a two-tiered dispatch system. A faster dispatcher written in assembly has a small MRU cache of jump destinations is used first. If that fails, dispatch falls back to the slower C++ dispatcher.</div> | 77 | <div>Enable a two-tiered dispatch system. A faster dispatcher written in assembly has a small MRU cache of jump destinations is used first. If that fails, dispatch falls back to the slower C++ dispatcher.</div> |
| 89 | </string> | 78 | </string> |
| 90 | </property> | 79 | </property> |
| 80 | <property name="text"> | ||
| 81 | <string>Enable fast dispatcher</string> | ||
| 82 | </property> | ||
| 91 | </widget> | 83 | </widget> |
| 92 | </item> | 84 | </item> |
| 93 | <item> | 85 | <item> |
| 94 | <widget class="QCheckBox" name="cpuopt_context_elimination"> | 86 | <widget class="QCheckBox" name="cpuopt_context_elimination"> |
| 95 | <property name="text"> | ||
| 96 | <string>Enable context elimination</string> | ||
| 97 | </property> | ||
| 98 | <property name="toolTip"> | 87 | <property name="toolTip"> |
| 99 | <string> | 88 | <string> |
| 100 | <div>Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.</div> | 89 | <div>Enables an IR optimization that reduces unnecessary accesses to the CPU context structure.</div> |
| 101 | </string> | 90 | </string> |
| 102 | </property> | 91 | </property> |
| 92 | <property name="text"> | ||
| 93 | <string>Enable context elimination</string> | ||
| 94 | </property> | ||
| 103 | </widget> | 95 | </widget> |
| 104 | </item> | 96 | </item> |
| 105 | <item> | 97 | <item> |
| 106 | <widget class="QCheckBox" name="cpuopt_const_prop"> | 98 | <widget class="QCheckBox" name="cpuopt_const_prop"> |
| 107 | <property name="text"> | ||
| 108 | <string>Enable constant propagation</string> | ||
| 109 | </property> | ||
| 110 | <property name="toolTip"> | 99 | <property name="toolTip"> |
| 111 | <string> | 100 | <string> |
| 112 | <div>Enables IR optimizations that involve constant propagation.</div> | 101 | <div>Enables IR optimizations that involve constant propagation.</div> |
| 113 | </string> | 102 | </string> |
| 114 | </property> | 103 | </property> |
| 104 | <property name="text"> | ||
| 105 | <string>Enable constant propagation</string> | ||
| 106 | </property> | ||
| 115 | </widget> | 107 | </widget> |
| 116 | </item> | 108 | </item> |
| 117 | <item> | 109 | <item> |
| 118 | <widget class="QCheckBox" name="cpuopt_misc_ir"> | 110 | <widget class="QCheckBox" name="cpuopt_misc_ir"> |
| 119 | <property name="text"> | ||
| 120 | <string>Enable miscellaneous optimizations</string> | ||
| 121 | </property> | ||
| 122 | <property name="toolTip"> | 111 | <property name="toolTip"> |
| 123 | <string> | 112 | <string> |
| 124 | <div>Enables miscellaneous IR optimizations.</div> | 113 | <div>Enables miscellaneous IR optimizations.</div> |
| 125 | </string> | 114 | </string> |
| 126 | </property> | 115 | </property> |
| 116 | <property name="text"> | ||
| 117 | <string>Enable miscellaneous optimizations</string> | ||
| 118 | </property> | ||
| 127 | </widget> | 119 | </widget> |
| 128 | </item> | 120 | </item> |
| 129 | <item> | 121 | <item> |
| 130 | <widget class="QCheckBox" name="cpuopt_reduce_misalign_checks"> | 122 | <widget class="QCheckBox" name="cpuopt_reduce_misalign_checks"> |
| 131 | <property name="text"> | ||
| 132 | <string>Enable misalignment check reduction</string> | ||
| 133 | </property> | ||
| 134 | <property name="toolTip"> | 123 | <property name="toolTip"> |
| 135 | <string> | 124 | <string> |
| 136 | <div style="white-space: nowrap">When enabled, a misalignment is only triggered when an access crosses a page boundary.</div> | 125 | <div style="white-space: nowrap">When enabled, a misalignment is only triggered when an access crosses a page boundary.</div> |
| 137 | <div style="white-space: nowrap">When disabled, a misalignment is triggered on all misaligned accesses.</div> | 126 | <div style="white-space: nowrap">When disabled, a misalignment is triggered on all misaligned accesses.</div> |
| 138 | </string> | 127 | </string> |
| 139 | </property> | 128 | </property> |
| 129 | <property name="text"> | ||
| 130 | <string>Enable misalignment check reduction</string> | ||
| 131 | </property> | ||
| 140 | </widget> | 132 | </widget> |
| 141 | </item> | 133 | </item> |
| 142 | <item> | 134 | <item> |
| 143 | <widget class="QCheckBox" name="cpuopt_fastmem"> | 135 | <widget class="QCheckBox" name="cpuopt_fastmem"> |
| 144 | <property name="text"> | ||
| 145 | <string>Enable Host MMU Emulation</string> | ||
| 146 | </property> | ||
| 147 | <property name="toolTip"> | 136 | <property name="toolTip"> |
| 148 | <string> | 137 | <string> |
| 149 | <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div> | 138 | <div style="white-space: nowrap">This optimization speeds up memory accesses by the guest program.</div> |
| 150 | <div style="white-space: nowrap">Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.</div> | 139 | <div style="white-space: nowrap">Enabling it causes guest memory reads/writes to be done directly into memory and make use of Host's MMU.</div> |
| 151 | <div style="white-space: nowrap">Disabling this forces all memory accesses to use Software MMU Emulation.</div> | 140 | <div style="white-space: nowrap">Disabling this forces all memory accesses to use Software MMU Emulation.</div> |
| 152 | </string> | 141 | </string> |
| 153 | </property> | 142 | </property> |
| 143 | <property name="text"> | ||
| 144 | <string>Enable Host MMU Emulation</string> | ||
| 145 | </property> | ||
| 154 | </widget> | 146 | </widget> |
| 155 | </item> | 147 | </item> |
| 156 | </layout> | 148 | </layout> |
diff --git a/src/yuzu/configuration/configure_debug.cpp b/src/yuzu/configuration/configure_debug.cpp index 15d6a5ad7..8fceb3878 100644 --- a/src/yuzu/configuration/configure_debug.cpp +++ b/src/yuzu/configuration/configure_debug.cpp | |||
| @@ -31,20 +31,23 @@ void ConfigureDebug::SetConfiguration() { | |||
| 31 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); | 31 | const bool runtime_lock = !Core::System::GetInstance().IsPoweredOn(); |
| 32 | 32 | ||
| 33 | ui->toggle_console->setEnabled(runtime_lock); | 33 | ui->toggle_console->setEnabled(runtime_lock); |
| 34 | ui->toggle_console->setChecked(UISettings::values.show_console); | 34 | ui->toggle_console->setChecked(UISettings::values.show_console.GetValue()); |
| 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter)); | 35 | ui->log_filter_edit->setText(QString::fromStdString(Settings::values.log_filter.GetValue())); |
| 36 | ui->homebrew_args_edit->setText(QString::fromStdString(Settings::values.program_args)); | 36 | ui->homebrew_args_edit->setText( |
| 37 | QString::fromStdString(Settings::values.program_args.GetValue())); | ||
| 37 | ui->fs_access_log->setEnabled(runtime_lock); | 38 | ui->fs_access_log->setEnabled(runtime_lock); |
| 38 | ui->fs_access_log->setChecked(Settings::values.enable_fs_access_log); | 39 | ui->fs_access_log->setChecked(Settings::values.enable_fs_access_log.GetValue()); |
| 39 | ui->reporting_services->setChecked(Settings::values.reporting_services); | 40 | ui->reporting_services->setChecked(Settings::values.reporting_services.GetValue()); |
| 40 | ui->quest_flag->setChecked(Settings::values.quest_flag); | 41 | ui->quest_flag->setChecked(Settings::values.quest_flag.GetValue()); |
| 41 | ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts); | 42 | ui->use_debug_asserts->setChecked(Settings::values.use_debug_asserts.GetValue()); |
| 42 | ui->use_auto_stub->setChecked(Settings::values.use_auto_stub); | 43 | ui->use_auto_stub->setChecked(Settings::values.use_auto_stub.GetValue()); |
| 43 | ui->enable_graphics_debugging->setEnabled(runtime_lock); | 44 | ui->enable_graphics_debugging->setEnabled(runtime_lock); |
| 44 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug); | 45 | ui->enable_graphics_debugging->setChecked(Settings::values.renderer_debug.GetValue()); |
| 46 | ui->enable_cpu_debugging->setEnabled(runtime_lock); | ||
| 47 | ui->enable_cpu_debugging->setChecked(Settings::values.cpu_debug_mode.GetValue()); | ||
| 45 | ui->disable_macro_jit->setEnabled(runtime_lock); | 48 | ui->disable_macro_jit->setEnabled(runtime_lock); |
| 46 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit); | 49 | ui->disable_macro_jit->setChecked(Settings::values.disable_macro_jit.GetValue()); |
| 47 | ui->extended_logging->setChecked(Settings::values.extended_logging); | 50 | ui->extended_logging->setChecked(Settings::values.extended_logging.GetValue()); |
| 48 | } | 51 | } |
| 49 | 52 | ||
| 50 | void ConfigureDebug::ApplyConfiguration() { | 53 | void ConfigureDebug::ApplyConfiguration() { |
| @@ -57,11 +60,12 @@ void ConfigureDebug::ApplyConfiguration() { | |||
| 57 | Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); | 60 | Settings::values.use_debug_asserts = ui->use_debug_asserts->isChecked(); |
| 58 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); | 61 | Settings::values.use_auto_stub = ui->use_auto_stub->isChecked(); |
| 59 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); | 62 | Settings::values.renderer_debug = ui->enable_graphics_debugging->isChecked(); |
| 63 | Settings::values.cpu_debug_mode = ui->enable_cpu_debugging->isChecked(); | ||
| 60 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); | 64 | Settings::values.disable_macro_jit = ui->disable_macro_jit->isChecked(); |
| 61 | Settings::values.extended_logging = ui->extended_logging->isChecked(); | 65 | Settings::values.extended_logging = ui->extended_logging->isChecked(); |
| 62 | Debugger::ToggleConsole(); | 66 | Debugger::ToggleConsole(); |
| 63 | Common::Log::Filter filter; | 67 | Common::Log::Filter filter; |
| 64 | filter.ParseFilterString(Settings::values.log_filter); | 68 | filter.ParseFilterString(Settings::values.log_filter.GetValue()); |
| 65 | Common::Log::SetGlobalFilter(filter); | 69 | Common::Log::SetGlobalFilter(filter); |
| 66 | } | 70 | } |
| 67 | 71 | ||
diff --git a/src/yuzu/configuration/configure_debug.ui b/src/yuzu/configuration/configure_debug.ui index c8087542f..1260ad6f0 100644 --- a/src/yuzu/configuration/configure_debug.ui +++ b/src/yuzu/configuration/configure_debug.ui | |||
| @@ -7,7 +7,7 @@ | |||
| 7 | <x>0</x> | 7 | <x>0</x> |
| 8 | <y>0</y> | 8 | <y>0</y> |
| 9 | <width>400</width> | 9 | <width>400</width> |
| 10 | <height>486</height> | 10 | <height>777</height> |
| 11 | </rect> | 11 | </rect> |
| 12 | </property> | 12 | </property> |
| 13 | <property name="windowTitle"> | 13 | <property name="windowTitle"> |
| @@ -192,34 +192,41 @@ | |||
| 192 | </property> | 192 | </property> |
| 193 | </widget> | 193 | </widget> |
| 194 | </item> | 194 | </item> |
| 195 | <item> | ||
| 196 | <widget class="QCheckBox" name="use_debug_asserts"> | ||
| 197 | <property name="text"> | ||
| 198 | <string>Enable Debug Asserts</string> | ||
| 199 | </property> | ||
| 200 | </widget> | ||
| 201 | </item> | ||
| 202 | <item> | ||
| 203 | <widget class="QCheckBox" name="use_auto_stub"> | ||
| 204 | <property name="text"> | ||
| 205 | <string>Enable Auto-Stub</string> | ||
| 206 | </property> | ||
| 207 | </widget> | ||
| 208 | </item> | ||
| 209 | <item> | 195 | <item> |
| 210 | <widget class="QLabel" name="label_5"> | 196 | <widget class="QCheckBox" name="enable_cpu_debugging"> |
| 211 | <property name="font"> | 197 | <property name="text"> |
| 212 | <font> | 198 | <string>Enable CPU Debugging</string> |
| 213 | <italic>true</italic> | 199 | </property> |
| 214 | </font> | 200 | </widget> |
| 215 | </property> | 201 | </item> |
| 216 | <property name="text"> | 202 | <item> |
| 217 | <string>This will be reset automatically when yuzu closes.</string> | 203 | <widget class="QCheckBox" name="use_debug_asserts"> |
| 218 | </property> | 204 | <property name="text"> |
| 219 | <property name="indent"> | 205 | <string>Enable Debug Asserts</string> |
| 220 | <number>20</number> | 206 | </property> |
| 221 | </property> | 207 | </widget> |
| 222 | </widget> | 208 | </item> |
| 209 | <item> | ||
| 210 | <widget class="QCheckBox" name="use_auto_stub"> | ||
| 211 | <property name="text"> | ||
| 212 | <string>Enable Auto-Stub</string> | ||
| 213 | </property> | ||
| 214 | </widget> | ||
| 215 | </item> | ||
| 216 | <item> | ||
| 217 | <widget class="QLabel" name="label_5"> | ||
| 218 | <property name="font"> | ||
| 219 | <font> | ||
| 220 | <italic>true</italic> | ||
| 221 | </font> | ||
| 222 | </property> | ||
| 223 | <property name="text"> | ||
| 224 | <string>This will be reset automatically when yuzu closes.</string> | ||
| 225 | </property> | ||
| 226 | <property name="indent"> | ||
| 227 | <number>20</number> | ||
| 228 | </property> | ||
| 229 | </widget> | ||
| 223 | </item> | 230 | </item> |
| 224 | </layout> | 231 | </layout> |
| 225 | </widget> | 232 | </widget> |
diff --git a/src/yuzu/configuration/configure_debug_tab.cpp b/src/yuzu/configuration/configure_debug_tab.cpp new file mode 100644 index 000000000..67d369249 --- /dev/null +++ b/src/yuzu/configuration/configure_debug_tab.cpp | |||
| @@ -0,0 +1,38 @@ | |||
| 1 | // Copyright 2021 yuzu Emulator Project | ||
| 2 | // Licensed under GPLv2 or any later version | ||
| 3 | // Refer to the license.txt file included. | ||
| 4 | |||
| 5 | #include "ui_configure_debug_tab.h" | ||
| 6 | #include "yuzu/configuration/configure_debug_tab.h" | ||
| 7 | |||
| 8 | ConfigureDebugTab::ConfigureDebugTab(QWidget* parent) | ||
| 9 | : QWidget(parent), ui(new Ui::ConfigureDebugTab) { | ||
| 10 | ui->setupUi(this); | ||
| 11 | |||
| 12 | SetConfiguration(); | ||
| 13 | } | ||
| 14 | |||
| 15 | ConfigureDebugTab::~ConfigureDebugTab() = default; | ||
| 16 | |||
| 17 | void ConfigureDebugTab::ApplyConfiguration() { | ||
| 18 | ui->debugTab->ApplyConfiguration(); | ||
| 19 | ui->cpuDebugTab->ApplyConfiguration(); | ||
| 20 | } | ||
| 21 | |||
| 22 | void ConfigureDebugTab::SetCurrentIndex(int index) { | ||
| 23 | ui->tabWidget->setCurrentIndex(index); | ||
| 24 | } | ||
| 25 | |||
| 26 | void ConfigureDebugTab::changeEvent(QEvent* event) { | ||
| 27 | if (event->type() == QEvent::LanguageChange) { | ||
| 28 | RetranslateUI(); | ||
| 29 | } | ||
| 30 | |||
| 31 | QWidget::changeEvent(event); | ||
| 32 | } | ||
| 33 | |||
| 34 | void ConfigureDebugTab::RetranslateUI() { | ||
| 35 | ui->retranslateUi(this); | ||
| 36 | } | ||
| 37 | |||
| 38 | void ConfigureDebugTab::SetConfiguration() {} | ||
diff --git a/src/yuzu/configuration/configure_debug_tab.h b/src/yuzu/configuration/configure_debug_tab.h new file mode 100644 index 000000000..0a96d43d0 --- /dev/null +++ b/src/yuzu/configuration/configure_debug_tab.h | |||
| @@ -0,0 +1,32 @@ | |||
| 1 | // Copyright 2021 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 <memory> | ||
| 8 | #include <QWidget> | ||
| 9 | |||
| 10 | namespace Ui { | ||
| 11 | class ConfigureDebugTab; | ||
| 12 | } | ||
| 13 | |||
| 14 | class ConfigureDebugTab : public QWidget { | ||
| 15 | Q_OBJECT | ||
| 16 | |||
| 17 | public: | ||
| 18 | explicit ConfigureDebugTab(QWidget* parent = nullptr); | ||
| 19 | ~ConfigureDebugTab() override; | ||
| 20 | |||
| 21 | void ApplyConfiguration(); | ||
| 22 | |||
| 23 | void SetCurrentIndex(int index); | ||
| 24 | |||
| 25 | private: | ||
| 26 | void changeEvent(QEvent* event) override; | ||
| 27 | void RetranslateUI(); | ||
| 28 | |||
| 29 | void SetConfiguration(); | ||
| 30 | |||
| 31 | std::unique_ptr<Ui::ConfigureDebugTab> ui; | ||
| 32 | }; | ||
diff --git a/src/yuzu/configuration/configure_debug_tab.ui b/src/yuzu/configuration/configure_debug_tab.ui new file mode 100644 index 000000000..7dc6dd704 --- /dev/null +++ b/src/yuzu/configuration/configure_debug_tab.ui | |||
| @@ -0,0 +1,52 @@ | |||
| 1 | <?xml version="1.0" encoding="UTF-8"?> | ||
| 2 | <ui version="4.0"> | ||
| 3 | <class>ConfigureDebugTab</class> | ||
| 4 | <widget class="QWidget" name="ConfigureDebugTab"> | ||
| 5 | <property name="geometry"> | ||
| 6 | <rect> | ||
| 7 | <x>0</x> | ||
| 8 | <y>0</y> | ||
| 9 | <width>320</width> | ||
| 10 | <height>240</height> | ||
| 11 | </rect> | ||
| 12 | </property> | ||
| 13 | <property name="windowTitle"> | ||
| 14 | <string>Form</string> | ||
| 15 | </property> | ||
| 16 | <layout class="QVBoxLayout" name="verticalLayout"> | ||
| 17 | <item> | ||
| 18 | <widget class="QTabWidget" name="tabWidget"> | ||
| 19 | <property name="currentIndex"> | ||
| 20 | <number>1</number> | ||
| 21 | </property> | ||
| 22 | <widget class="ConfigureDebug" name="debugTab"> | ||
| 23 | <attribute name="title"> | ||
| 24 | <string>General</string> | ||
| 25 | </attribute> | ||
| 26 | </widget> | ||
| 27 | <widget class="ConfigureCpuDebug" name="cpuDebugTab"> | ||
| 28 | <attribute name="title"> | ||
| 29 | <string>CPU</string> | ||
| 30 | </attribute> | ||
| 31 | </widget> | ||
| 32 | </widget> | ||
| 33 | </item> | ||
| 34 | </layout> | ||
| 35 | </widget> | ||
| 36 | <customwidgets> | ||
| 37 | <customwidget> | ||
| 38 | <class>ConfigureDebug</class> | ||
| 39 | <extends>QWidget</extends> | ||
| 40 | <header>configuration/configure_debug.h</header> | ||
| 41 | <container>1</container> | ||
| 42 | </customwidget> | ||
| 43 | <customwidget> | ||
| 44 | <class>ConfigureCpuDebug</class> | ||
| 45 | <extends>QWidget</extends> | ||
| 46 | <header>configuration/configure_cpu_debug.h</header> | ||
| 47 | <container>1</container> | ||
| 48 | </customwidget> | ||
| 49 | </customwidgets> | ||
| 50 | <resources/> | ||
| 51 | <connections/> | ||
| 52 | </ui> | ||
diff --git a/src/yuzu/configuration/configure_dialog.cpp b/src/yuzu/configuration/configure_dialog.cpp index 371bc01b1..bc009b6b3 100644 --- a/src/yuzu/configuration/configure_dialog.cpp +++ b/src/yuzu/configuration/configure_dialog.cpp | |||
| @@ -8,6 +8,7 @@ | |||
| 8 | #include <QListWidgetItem> | 8 | #include <QListWidgetItem> |
| 9 | #include <QPushButton> | 9 | #include <QPushButton> |
| 10 | #include <QSignalBlocker> | 10 | #include <QSignalBlocker> |
| 11 | #include <QTabWidget> | ||
| 11 | #include "common/settings.h" | 12 | #include "common/settings.h" |
| 12 | #include "core/core.h" | 13 | #include "core/core.h" |
| 13 | #include "ui_configure.h" | 14 | #include "ui_configure.h" |
| @@ -32,6 +33,8 @@ ConfigureDialog::ConfigureDialog(QWidget* parent, HotkeyRegistry& registry, | |||
| 32 | SetConfiguration(); | 33 | SetConfiguration(); |
| 33 | PopulateSelectionList(); | 34 | PopulateSelectionList(); |
| 34 | 35 | ||
| 36 | connect(ui->tabWidget, &QTabWidget::currentChanged, this, | ||
| 37 | [this]() { ui->debugTab->SetCurrentIndex(0); }); | ||
| 35 | connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); | 38 | connect(ui->uiTab, &ConfigureUi::LanguageChanged, this, &ConfigureDialog::OnLanguageChanged); |
| 36 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, | 39 | connect(ui->selectorList, &QListWidget::itemSelectionChanged, this, |
| 37 | &ConfigureDialog::UpdateVisibleTabs); | 40 | &ConfigureDialog::UpdateVisibleTabs); |
| @@ -59,7 +62,6 @@ void ConfigureDialog::ApplyConfiguration() { | |||
| 59 | ui->inputTab->ApplyConfiguration(); | 62 | ui->inputTab->ApplyConfiguration(); |
| 60 | ui->hotkeysTab->ApplyConfiguration(registry); | 63 | ui->hotkeysTab->ApplyConfiguration(registry); |
| 61 | ui->cpuTab->ApplyConfiguration(); | 64 | ui->cpuTab->ApplyConfiguration(); |
| 62 | ui->cpuDebugTab->ApplyConfiguration(); | ||
| 63 | ui->graphicsTab->ApplyConfiguration(); | 65 | ui->graphicsTab->ApplyConfiguration(); |
| 64 | ui->graphicsAdvancedTab->ApplyConfiguration(); | 66 | ui->graphicsAdvancedTab->ApplyConfiguration(); |
| 65 | ui->audioTab->ApplyConfiguration(); | 67 | ui->audioTab->ApplyConfiguration(); |
| @@ -102,7 +104,7 @@ void ConfigureDialog::PopulateSelectionList() { | |||
| 102 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ | 104 | const std::array<std::pair<QString, QList<QWidget*>>, 6> items{ |
| 103 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, | 105 | {{tr("General"), {ui->generalTab, ui->hotkeysTab, ui->uiTab, ui->webTab, ui->debugTab}}, |
| 104 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, | 106 | {tr("System"), {ui->systemTab, ui->profileManagerTab, ui->serviceTab, ui->filesystemTab}}, |
| 105 | {tr("CPU"), {ui->cpuTab, ui->cpuDebugTab}}, | 107 | {tr("CPU"), {ui->cpuTab}}, |
| 106 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, | 108 | {tr("Graphics"), {ui->graphicsTab, ui->graphicsAdvancedTab}}, |
| 107 | {tr("Audio"), {ui->audioTab}}, | 109 | {tr("Audio"), {ui->audioTab}}, |
| 108 | {tr("Controls"), ui->inputTab->GetSubTabs()}}, | 110 | {tr("Controls"), ui->inputTab->GetSubTabs()}}, |
diff --git a/src/yuzu/configuration/configure_filesystem.cpp b/src/yuzu/configuration/configure_filesystem.cpp index d223c40ea..9cb317822 100644 --- a/src/yuzu/configuration/configure_filesystem.cpp +++ b/src/yuzu/configuration/configure_filesystem.cpp | |||
| @@ -43,18 +43,19 @@ void ConfigureFilesystem::setConfiguration() { | |||
| 43 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir))); | 43 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::NANDDir))); |
| 44 | ui->sdmc_directory_edit->setText( | 44 | ui->sdmc_directory_edit->setText( |
| 45 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::SDMCDir))); | 45 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::SDMCDir))); |
| 46 | ui->gamecard_path_edit->setText(QString::fromStdString(Settings::values.gamecard_path)); | 46 | ui->gamecard_path_edit->setText( |
| 47 | QString::fromStdString(Settings::values.gamecard_path.GetValue())); | ||
| 47 | ui->dump_path_edit->setText( | 48 | ui->dump_path_edit->setText( |
| 48 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::DumpDir))); | 49 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::DumpDir))); |
| 49 | ui->load_path_edit->setText( | 50 | ui->load_path_edit->setText( |
| 50 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LoadDir))); | 51 | QString::fromStdString(Common::FS::GetYuzuPathString(Common::FS::YuzuPath::LoadDir))); |
| 51 | 52 | ||
| 52 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted); | 53 | ui->gamecard_inserted->setChecked(Settings::values.gamecard_inserted.GetValue()); |
| 53 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game); | 54 | ui->gamecard_current_game->setChecked(Settings::values.gamecard_current_game.GetValue()); |
| 54 | ui->dump_exefs->setChecked(Settings::values.dump_exefs); | 55 | ui->dump_exefs->setChecked(Settings::values.dump_exefs.GetValue()); |
| 55 | ui->dump_nso->setChecked(Settings::values.dump_nso); | 56 | ui->dump_nso->setChecked(Settings::values.dump_nso.GetValue()); |
| 56 | 57 | ||
| 57 | ui->cache_game_list->setChecked(UISettings::values.cache_game_list); | 58 | ui->cache_game_list->setChecked(UISettings::values.cache_game_list.GetValue()); |
| 58 | 59 | ||
| 59 | UpdateEnabledControls(); | 60 | UpdateEnabledControls(); |
| 60 | } | 61 | } |
diff --git a/src/yuzu/configuration/configure_general.cpp b/src/yuzu/configuration/configure_general.cpp index 38edb4d8d..18f25def6 100644 --- a/src/yuzu/configuration/configure_general.cpp +++ b/src/yuzu/configuration/configure_general.cpp | |||
| @@ -40,10 +40,10 @@ void ConfigureGeneral::SetConfiguration() { | |||
| 40 | ui->use_multi_core->setEnabled(runtime_lock); | 40 | ui->use_multi_core->setEnabled(runtime_lock); |
| 41 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); | 41 | ui->use_multi_core->setChecked(Settings::values.use_multi_core.GetValue()); |
| 42 | 42 | ||
| 43 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing); | 43 | ui->toggle_check_exit->setChecked(UISettings::values.confirm_before_closing.GetValue()); |
| 44 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot); | 44 | ui->toggle_user_on_boot->setChecked(UISettings::values.select_user_on_boot.GetValue()); |
| 45 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background); | 45 | ui->toggle_background_pause->setChecked(UISettings::values.pause_when_in_background.GetValue()); |
| 46 | ui->toggle_hide_mouse->setChecked(UISettings::values.hide_mouse); | 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_frame_limit->setChecked(Settings::values.use_frame_limit.GetValue()); |
| 49 | ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); | 49 | ui->frame_limit->setValue(Settings::values.frame_limit.GetValue()); |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.cpp b/src/yuzu/configuration/configure_graphics_advanced.cpp index 8d13c9857..a9e611125 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.cpp +++ b/src/yuzu/configuration/configure_graphics_advanced.cpp | |||
| @@ -28,7 +28,6 @@ void ConfigureGraphicsAdvanced::SetConfiguration() { | |||
| 28 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); | 28 | ui->anisotropic_filtering_combobox->setEnabled(runtime_lock); |
| 29 | 29 | ||
| 30 | ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); | 30 | ui->use_vsync->setChecked(Settings::values.use_vsync.GetValue()); |
| 31 | ui->disable_fps_limit->setChecked(Settings::values.disable_fps_limit.GetValue()); | ||
| 32 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); | 31 | ui->use_assembly_shaders->setChecked(Settings::values.use_assembly_shaders.GetValue()); |
| 33 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); | 32 | ui->use_asynchronous_shaders->setChecked(Settings::values.use_asynchronous_shaders.GetValue()); |
| 34 | ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue()); | 33 | ui->use_caches_gc->setChecked(Settings::values.use_caches_gc.GetValue()); |
| @@ -59,8 +58,6 @@ void ConfigureGraphicsAdvanced::ApplyConfiguration() { | |||
| 59 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, | 58 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.max_anisotropy, |
| 60 | ui->anisotropic_filtering_combobox); | 59 | ui->anisotropic_filtering_combobox); |
| 61 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); | 60 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_vsync, ui->use_vsync, use_vsync); |
| 62 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.disable_fps_limit, | ||
| 63 | ui->disable_fps_limit, disable_fps_limit); | ||
| 64 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, | 61 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_assembly_shaders, |
| 65 | ui->use_assembly_shaders, use_assembly_shaders); | 62 | ui->use_assembly_shaders, use_assembly_shaders); |
| 66 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, | 63 | ConfigurationShared::ApplyPerGameSetting(&Settings::values.use_asynchronous_shaders, |
| @@ -103,7 +100,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 103 | if (Settings::IsConfiguringGlobal()) { | 100 | if (Settings::IsConfiguringGlobal()) { |
| 104 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); | 101 | ui->gpu_accuracy->setEnabled(Settings::values.gpu_accuracy.UsingGlobal()); |
| 105 | ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); | 102 | ui->use_vsync->setEnabled(Settings::values.use_vsync.UsingGlobal()); |
| 106 | ui->disable_fps_limit->setEnabled(Settings::values.disable_fps_limit.UsingGlobal()); | ||
| 107 | ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); | 103 | ui->use_assembly_shaders->setEnabled(Settings::values.use_assembly_shaders.UsingGlobal()); |
| 108 | ui->use_asynchronous_shaders->setEnabled( | 104 | ui->use_asynchronous_shaders->setEnabled( |
| 109 | Settings::values.use_asynchronous_shaders.UsingGlobal()); | 105 | Settings::values.use_asynchronous_shaders.UsingGlobal()); |
| @@ -116,8 +112,6 @@ void ConfigureGraphicsAdvanced::SetupPerGameUI() { | |||
| 116 | } | 112 | } |
| 117 | 113 | ||
| 118 | ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); | 114 | ConfigurationShared::SetColoredTristate(ui->use_vsync, Settings::values.use_vsync, use_vsync); |
| 119 | ConfigurationShared::SetColoredTristate(ui->disable_fps_limit, | ||
| 120 | Settings::values.disable_fps_limit, disable_fps_limit); | ||
| 121 | ConfigurationShared::SetColoredTristate( | 115 | ConfigurationShared::SetColoredTristate( |
| 122 | ui->use_assembly_shaders, Settings::values.use_assembly_shaders, use_assembly_shaders); | 116 | ui->use_assembly_shaders, Settings::values.use_assembly_shaders, use_assembly_shaders); |
| 123 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, | 117 | ConfigurationShared::SetColoredTristate(ui->use_asynchronous_shaders, |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.h b/src/yuzu/configuration/configure_graphics_advanced.h index 6ac5f20ec..9148aacf2 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.h +++ b/src/yuzu/configuration/configure_graphics_advanced.h | |||
| @@ -35,7 +35,6 @@ private: | |||
| 35 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; | 35 | std::unique_ptr<Ui::ConfigureGraphicsAdvanced> ui; |
| 36 | 36 | ||
| 37 | ConfigurationShared::CheckState use_vsync; | 37 | ConfigurationShared::CheckState use_vsync; |
| 38 | ConfigurationShared::CheckState disable_fps_limit; | ||
| 39 | ConfigurationShared::CheckState use_assembly_shaders; | 38 | ConfigurationShared::CheckState use_assembly_shaders; |
| 40 | ConfigurationShared::CheckState use_asynchronous_shaders; | 39 | ConfigurationShared::CheckState use_asynchronous_shaders; |
| 41 | ConfigurationShared::CheckState use_fast_gpu_time; | 40 | ConfigurationShared::CheckState use_fast_gpu_time; |
diff --git a/src/yuzu/configuration/configure_graphics_advanced.ui b/src/yuzu/configuration/configure_graphics_advanced.ui index 18c43629e..ad0840355 100644 --- a/src/yuzu/configuration/configure_graphics_advanced.ui +++ b/src/yuzu/configuration/configure_graphics_advanced.ui | |||
| @@ -77,24 +77,6 @@ | |||
| 77 | </widget> | 77 | </widget> |
| 78 | </item> | 78 | </item> |
| 79 | <item> | 79 | <item> |
| 80 | <widget class="QCheckBox" name="disable_fps_limit"> | ||
| 81 | <property name="enabled"> | ||
| 82 | <bool>true</bool> | ||
| 83 | </property> | ||
| 84 | <property name="toolTip"> | ||
| 85 | <string> | ||
| 86 | <html><head/><body> | ||
| 87 | <p>Presents guest frames as they become available, disabling the FPS limit in most titles.</p> | ||
| 88 | <p>NOTE: Will cause instabilities.</p> | ||
| 89 | </body></html> | ||
| 90 | </string> | ||
| 91 | </property> | ||
| 92 | <property name="text"> | ||
| 93 | <string>Disable framerate limit (experimental)</string> | ||
| 94 | </property> | ||
| 95 | </widget> | ||
| 96 | </item> | ||
| 97 | <item> | ||
| 98 | <widget class="QCheckBox" name="use_assembly_shaders"> | 80 | <widget class="QCheckBox" name="use_assembly_shaders"> |
| 99 | <property name="toolTip"> | 81 | <property name="toolTip"> |
| 100 | <string>Enabling this reduces shader stutter. Enables OpenGL assembly shaders on supported Nvidia devices (NV_gpu_program5 is required). This feature is experimental.</string> | 82 | <string>Enabling this reduces shader stutter. Enables OpenGL assembly shaders on supported Nvidia devices (NV_gpu_program5 is required). This feature is experimental.</string> |
diff --git a/src/yuzu/configuration/configure_input_advanced.cpp b/src/yuzu/configuration/configure_input_advanced.cpp index d8d3b83dc..2f1419b5b 100644 --- a/src/yuzu/configuration/configure_input_advanced.cpp +++ b/src/yuzu/configuration/configure_input_advanced.cpp | |||
| @@ -148,12 +148,12 @@ void ConfigureInputAdvanced::LoadConfiguration() { | |||
| 148 | } | 148 | } |
| 149 | } | 149 | } |
| 150 | 150 | ||
| 151 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled); | 151 | ui->debug_enabled->setChecked(Settings::values.debug_pad_enabled.GetValue()); |
| 152 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled); | 152 | ui->mouse_enabled->setChecked(Settings::values.mouse_enabled.GetValue()); |
| 153 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled); | 153 | ui->keyboard_enabled->setChecked(Settings::values.keyboard_enabled.GetValue()); |
| 154 | ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard); | 154 | ui->emulate_analog_keyboard->setChecked(Settings::values.emulate_analog_keyboard.GetValue()); |
| 155 | ui->mouse_panning->setChecked(Settings::values.mouse_panning); | 155 | ui->mouse_panning->setChecked(Settings::values.mouse_panning.GetValue()); |
| 156 | ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity); | 156 | ui->mouse_panning_sensitivity->setValue(Settings::values.mouse_panning_sensitivity.GetValue()); |
| 157 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); | 157 | ui->touchscreen_enabled->setChecked(Settings::values.touchscreen.enabled); |
| 158 | 158 | ||
| 159 | UpdateUIEnabled(); | 159 | UpdateUIEnabled(); |
diff --git a/src/yuzu/configuration/configure_motion_touch.cpp b/src/yuzu/configuration/configure_motion_touch.cpp index 6a5d625df..f8e08c422 100644 --- a/src/yuzu/configuration/configure_motion_touch.cpp +++ b/src/yuzu/configuration/configure_motion_touch.cpp | |||
| @@ -101,15 +101,16 @@ ConfigureMotionTouch::ConfigureMotionTouch(QWidget* parent, | |||
| 101 | ConfigureMotionTouch::~ConfigureMotionTouch() = default; | 101 | ConfigureMotionTouch::~ConfigureMotionTouch() = default; |
| 102 | 102 | ||
| 103 | void ConfigureMotionTouch::SetConfiguration() { | 103 | void ConfigureMotionTouch::SetConfiguration() { |
| 104 | const Common::ParamPackage motion_param(Settings::values.motion_device); | 104 | const Common::ParamPackage motion_param(Settings::values.motion_device.GetValue()); |
| 105 | const Common::ParamPackage touch_param(Settings::values.touch_device); | 105 | const Common::ParamPackage touch_param(Settings::values.touch_device.GetValue()); |
| 106 | 106 | ||
| 107 | ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button); | 107 | ui->touch_from_button_checkbox->setChecked(Settings::values.use_touch_from_button.GetValue()); |
| 108 | touch_from_button_maps = Settings::values.touch_from_button_maps; | 108 | touch_from_button_maps = Settings::values.touch_from_button_maps; |
| 109 | for (const auto& touch_map : touch_from_button_maps) { | 109 | for (const auto& touch_map : touch_from_button_maps) { |
| 110 | ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); | 110 | ui->touch_from_button_map->addItem(QString::fromStdString(touch_map.name)); |
| 111 | } | 111 | } |
| 112 | ui->touch_from_button_map->setCurrentIndex(Settings::values.touch_from_button_map_index); | 112 | ui->touch_from_button_map->setCurrentIndex( |
| 113 | Settings::values.touch_from_button_map_index.GetValue()); | ||
| 113 | ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f)); | 114 | ui->motion_sensitivity->setValue(motion_param.Get("sensitivity", 0.01f)); |
| 114 | 115 | ||
| 115 | min_x = touch_param.Get("min_x", 100); | 116 | min_x = touch_param.Get("min_x", 100); |
| @@ -124,7 +125,7 @@ void ConfigureMotionTouch::SetConfiguration() { | |||
| 124 | udp_server_list_model->setStringList({}); | 125 | udp_server_list_model->setStringList({}); |
| 125 | ui->udp_server_list->setModel(udp_server_list_model); | 126 | ui->udp_server_list->setModel(udp_server_list_model); |
| 126 | 127 | ||
| 127 | std::stringstream ss(Settings::values.udp_input_servers); | 128 | std::stringstream ss(Settings::values.udp_input_servers.GetValue()); |
| 128 | std::string token; | 129 | std::string token; |
| 129 | 130 | ||
| 130 | while (std::getline(ss, token, ',')) { | 131 | while (std::getline(ss, token, ',')) { |
diff --git a/src/yuzu/configuration/configure_profile_manager.cpp b/src/yuzu/configuration/configure_profile_manager.cpp index f5881e58d..ac849b01d 100644 --- a/src/yuzu/configuration/configure_profile_manager.cpp +++ b/src/yuzu/configuration/configure_profile_manager.cpp | |||
| @@ -166,7 +166,7 @@ void ConfigureProfileManager::PopulateUserList() { | |||
| 166 | void ConfigureProfileManager::UpdateCurrentUser() { | 166 | void ConfigureProfileManager::UpdateCurrentUser() { |
| 167 | ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS); | 167 | ui->pm_add->setEnabled(profile_manager->GetUserCount() < Service::Account::MAX_USERS); |
| 168 | 168 | ||
| 169 | const auto& current_user = profile_manager->GetUser(Settings::values.current_user); | 169 | const auto& current_user = profile_manager->GetUser(Settings::values.current_user.GetValue()); |
| 170 | ASSERT(current_user); | 170 | ASSERT(current_user); |
| 171 | const auto username = GetAccountUsername(*profile_manager, *current_user); | 171 | const auto username = GetAccountUsername(*profile_manager, *current_user); |
| 172 | 172 | ||
| @@ -245,15 +245,18 @@ void ConfigureProfileManager::DeleteUser() { | |||
| 245 | this, tr("Confirm Delete"), | 245 | this, tr("Confirm Delete"), |
| 246 | tr("You are about to delete user with name \"%1\". Are you sure?").arg(username)); | 246 | tr("You are about to delete user with name \"%1\". Are you sure?").arg(username)); |
| 247 | 247 | ||
| 248 | if (confirm == QMessageBox::No) | 248 | if (confirm == QMessageBox::No) { |
| 249 | return; | 249 | return; |
| 250 | } | ||
| 250 | 251 | ||
| 251 | if (Settings::values.current_user == tree_view->currentIndex().row()) | 252 | if (Settings::values.current_user.GetValue() == tree_view->currentIndex().row()) { |
| 252 | Settings::values.current_user = 0; | 253 | Settings::values.current_user = 0; |
| 254 | } | ||
| 253 | UpdateCurrentUser(); | 255 | UpdateCurrentUser(); |
| 254 | 256 | ||
| 255 | if (!profile_manager->RemoveUser(*uuid)) | 257 | if (!profile_manager->RemoveUser(*uuid)) { |
| 256 | return; | 258 | return; |
| 259 | } | ||
| 257 | 260 | ||
| 258 | item_model->removeRows(tree_view->currentIndex().row(), 1); | 261 | item_model->removeRows(tree_view->currentIndex().row(), 1); |
| 259 | tree_view->clearSelection(); | 262 | tree_view->clearSelection(); |
diff --git a/src/yuzu/configuration/configure_service.cpp b/src/yuzu/configuration/configure_service.cpp index 6d954a67f..4aa424803 100644 --- a/src/yuzu/configuration/configure_service.cpp +++ b/src/yuzu/configuration/configure_service.cpp | |||
| @@ -65,7 +65,7 @@ void ConfigureService::RetranslateUi() { | |||
| 65 | 65 | ||
| 66 | void ConfigureService::SetConfiguration() { | 66 | void ConfigureService::SetConfiguration() { |
| 67 | const int index = | 67 | const int index = |
| 68 | ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend)); | 68 | ui->bcat_source->findData(QString::fromStdString(Settings::values.bcat_backend.GetValue())); |
| 69 | ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); | 69 | ui->bcat_source->setCurrentIndex(index == -1 ? 0 : index); |
| 70 | } | 70 | } |
| 71 | 71 | ||
diff --git a/src/yuzu/configuration/configure_ui.cpp b/src/yuzu/configuration/configure_ui.cpp index 9674119e1..e8f41bf65 100644 --- a/src/yuzu/configuration/configure_ui.cpp +++ b/src/yuzu/configuration/configure_ui.cpp | |||
| @@ -113,11 +113,12 @@ void ConfigureUi::SetConfiguration() { | |||
| 113 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); | 113 | ui->theme_combobox->setCurrentIndex(ui->theme_combobox->findData(UISettings::values.theme)); |
| 114 | ui->language_combobox->setCurrentIndex( | 114 | ui->language_combobox->setCurrentIndex( |
| 115 | ui->language_combobox->findData(UISettings::values.language)); | 115 | ui->language_combobox->findData(UISettings::values.language)); |
| 116 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons); | 116 | ui->show_add_ons->setChecked(UISettings::values.show_add_ons.GetValue()); |
| 117 | ui->icon_size_combobox->setCurrentIndex( | 117 | ui->icon_size_combobox->setCurrentIndex( |
| 118 | ui->icon_size_combobox->findData(UISettings::values.icon_size)); | 118 | ui->icon_size_combobox->findData(UISettings::values.icon_size.GetValue())); |
| 119 | 119 | ||
| 120 | ui->enable_screenshot_save_as->setChecked(UISettings::values.enable_screenshot_save_as); | 120 | ui->enable_screenshot_save_as->setChecked( |
| 121 | UISettings::values.enable_screenshot_save_as.GetValue()); | ||
| 121 | ui->screenshot_path_edit->setText(QString::fromStdString( | 122 | ui->screenshot_path_edit->setText(QString::fromStdString( |
| 122 | Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir))); | 123 | Common::FS::GetYuzuPathString(Common::FS::YuzuPath::ScreenshotsDir))); |
| 123 | } | 124 | } |
| @@ -178,7 +179,7 @@ void ConfigureUi::InitializeRowComboBoxes() { | |||
| 178 | 179 | ||
| 179 | void ConfigureUi::UpdateFirstRowComboBox(bool init) { | 180 | void ConfigureUi::UpdateFirstRowComboBox(bool init) { |
| 180 | const int currentIndex = | 181 | const int currentIndex = |
| 181 | init ? UISettings::values.row_1_text_id | 182 | init ? UISettings::values.row_1_text_id.GetValue() |
| 182 | : ui->row_1_text_combobox->findData(ui->row_1_text_combobox->currentData()); | 183 | : ui->row_1_text_combobox->findData(ui->row_1_text_combobox->currentData()); |
| 183 | 184 | ||
| 184 | ui->row_1_text_combobox->clear(); | 185 | ui->row_1_text_combobox->clear(); |
| @@ -197,7 +198,7 @@ void ConfigureUi::UpdateFirstRowComboBox(bool init) { | |||
| 197 | 198 | ||
| 198 | void ConfigureUi::UpdateSecondRowComboBox(bool init) { | 199 | void ConfigureUi::UpdateSecondRowComboBox(bool init) { |
| 199 | const int currentIndex = | 200 | const int currentIndex = |
| 200 | init ? UISettings::values.row_2_text_id | 201 | init ? UISettings::values.row_2_text_id.GetValue() |
| 201 | : ui->row_2_text_combobox->findData(ui->row_2_text_combobox->currentData()); | 202 | : ui->row_2_text_combobox->findData(ui->row_2_text_combobox->currentData()); |
| 202 | 203 | ||
| 203 | ui->row_2_text_combobox->clear(); | 204 | ui->row_2_text_combobox->clear(); |
diff --git a/src/yuzu/configuration/configure_web.cpp b/src/yuzu/configuration/configure_web.cpp index f3f3b54d6..d779251b4 100644 --- a/src/yuzu/configuration/configure_web.cpp +++ b/src/yuzu/configuration/configure_web.cpp | |||
| @@ -88,22 +88,22 @@ void ConfigureWeb::SetConfiguration() { | |||
| 88 | ui->web_signup_link->setOpenExternalLinks(true); | 88 | ui->web_signup_link->setOpenExternalLinks(true); |
| 89 | ui->web_token_info_link->setOpenExternalLinks(true); | 89 | ui->web_token_info_link->setOpenExternalLinks(true); |
| 90 | 90 | ||
| 91 | if (Settings::values.yuzu_username.empty()) { | 91 | if (Settings::values.yuzu_username.GetValue().empty()) { |
| 92 | ui->username->setText(tr("Unspecified")); | 92 | ui->username->setText(tr("Unspecified")); |
| 93 | } else { | 93 | } else { |
| 94 | ui->username->setText(QString::fromStdString(Settings::values.yuzu_username)); | 94 | ui->username->setText(QString::fromStdString(Settings::values.yuzu_username.GetValue())); |
| 95 | } | 95 | } |
| 96 | 96 | ||
| 97 | ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry); | 97 | ui->toggle_telemetry->setChecked(Settings::values.enable_telemetry.GetValue()); |
| 98 | ui->edit_token->setText(QString::fromStdString( | 98 | ui->edit_token->setText(QString::fromStdString(GenerateDisplayToken( |
| 99 | GenerateDisplayToken(Settings::values.yuzu_username, Settings::values.yuzu_token))); | 99 | Settings::values.yuzu_username.GetValue(), Settings::values.yuzu_token.GetValue()))); |
| 100 | 100 | ||
| 101 | // Connect after setting the values, to avoid calling OnLoginChanged now | 101 | // Connect after setting the values, to avoid calling OnLoginChanged now |
| 102 | connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged); | 102 | connect(ui->edit_token, &QLineEdit::textChanged, this, &ConfigureWeb::OnLoginChanged); |
| 103 | 103 | ||
| 104 | user_verified = true; | 104 | user_verified = true; |
| 105 | 105 | ||
| 106 | ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence); | 106 | ui->toggle_discordrpc->setChecked(UISettings::values.enable_discord_presence.GetValue()); |
| 107 | } | 107 | } |
| 108 | 108 | ||
| 109 | void ConfigureWeb::ApplyConfiguration() { | 109 | void ConfigureWeb::ApplyConfiguration() { |
diff --git a/src/yuzu/debugger/console.cpp b/src/yuzu/debugger/console.cpp index c11a326ac..22ca1285d 100644 --- a/src/yuzu/debugger/console.cpp +++ b/src/yuzu/debugger/console.cpp | |||
| @@ -15,10 +15,10 @@ | |||
| 15 | namespace Debugger { | 15 | namespace Debugger { |
| 16 | void ToggleConsole() { | 16 | void ToggleConsole() { |
| 17 | static bool console_shown = false; | 17 | static bool console_shown = false; |
| 18 | if (console_shown == UISettings::values.show_console) { | 18 | if (console_shown == UISettings::values.show_console.GetValue()) { |
| 19 | return; | 19 | return; |
| 20 | } else { | 20 | } else { |
| 21 | console_shown = UISettings::values.show_console; | 21 | console_shown = UISettings::values.show_console.GetValue(); |
| 22 | } | 22 | } |
| 23 | 23 | ||
| 24 | #if defined(_WIN32) && !defined(_DEBUG) | 24 | #if defined(_WIN32) && !defined(_DEBUG) |
diff --git a/src/yuzu/game_list.cpp b/src/yuzu/game_list.cpp index e44907be8..218b4782b 100644 --- a/src/yuzu/game_list.cpp +++ b/src/yuzu/game_list.cpp | |||
| @@ -244,7 +244,8 @@ void GameList::OnUpdateThemedIcons() { | |||
| 244 | for (int i = 0; i < item_model->invisibleRootItem()->rowCount(); i++) { | 244 | for (int i = 0; i < item_model->invisibleRootItem()->rowCount(); i++) { |
| 245 | QStandardItem* child = item_model->invisibleRootItem()->child(i); | 245 | QStandardItem* child = item_model->invisibleRootItem()->child(i); |
| 246 | 246 | ||
| 247 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); | 247 | const int icon_size = |
| 248 | std::min(static_cast<int>(UISettings::values.icon_size.GetValue()), 64); | ||
| 248 | switch (child->data(GameListItem::TypeRole).value<GameListItemType>()) { | 249 | switch (child->data(GameListItem::TypeRole).value<GameListItemType>()) { |
| 249 | case GameListItemType::SdmcDir: | 250 | case GameListItemType::SdmcDir: |
| 250 | child->setData( | 251 | child->setData( |
diff --git a/src/yuzu/game_list_p.h b/src/yuzu/game_list_p.h index 978d27325..982c0789d 100644 --- a/src/yuzu/game_list_p.h +++ b/src/yuzu/game_list_p.h | |||
| @@ -80,7 +80,7 @@ public: | |||
| 80 | setData(qulonglong(program_id), ProgramIdRole); | 80 | setData(qulonglong(program_id), ProgramIdRole); |
| 81 | setData(game_type, FileTypeRole); | 81 | setData(game_type, FileTypeRole); |
| 82 | 82 | ||
| 83 | const u32 size = UISettings::values.icon_size; | 83 | const u32 size = UISettings::values.icon_size.GetValue(); |
| 84 | 84 | ||
| 85 | QPixmap picture; | 85 | QPixmap picture; |
| 86 | if (!picture.loadFromData(picture_data.data(), static_cast<u32>(picture_data.size()))) { | 86 | if (!picture.loadFromData(picture_data.data(), static_cast<u32>(picture_data.size()))) { |
| @@ -108,8 +108,8 @@ public: | |||
| 108 | data(TitleRole).toString(), | 108 | data(TitleRole).toString(), |
| 109 | }}; | 109 | }}; |
| 110 | 110 | ||
| 111 | const auto& row1 = row_data.at(UISettings::values.row_1_text_id); | 111 | const auto& row1 = row_data.at(UISettings::values.row_1_text_id.GetValue()); |
| 112 | const int row2_id = UISettings::values.row_2_text_id; | 112 | const int row2_id = UISettings::values.row_2_text_id.GetValue(); |
| 113 | 113 | ||
| 114 | if (role == SortRole) { | 114 | if (role == SortRole) { |
| 115 | return row1.toLower(); | 115 | return row1.toLower(); |
| @@ -233,7 +233,8 @@ public: | |||
| 233 | UISettings::GameDir* game_dir = &directory; | 233 | UISettings::GameDir* game_dir = &directory; |
| 234 | setData(QVariant(UISettings::values.game_dirs.indexOf(directory)), GameDirRole); | 234 | setData(QVariant(UISettings::values.game_dirs.indexOf(directory)), GameDirRole); |
| 235 | 235 | ||
| 236 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); | 236 | const int icon_size = |
| 237 | std::min(static_cast<int>(UISettings::values.icon_size.GetValue()), 64); | ||
| 237 | switch (dir_type) { | 238 | switch (dir_type) { |
| 238 | case GameListItemType::SdmcDir: | 239 | case GameListItemType::SdmcDir: |
| 239 | setData( | 240 | setData( |
| @@ -294,7 +295,8 @@ public: | |||
| 294 | explicit GameListAddDir() { | 295 | explicit GameListAddDir() { |
| 295 | setData(type(), TypeRole); | 296 | setData(type(), TypeRole); |
| 296 | 297 | ||
| 297 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); | 298 | const int icon_size = |
| 299 | std::min(static_cast<int>(UISettings::values.icon_size.GetValue()), 64); | ||
| 298 | setData(QIcon::fromTheme(QStringLiteral("plus")) | 300 | setData(QIcon::fromTheme(QStringLiteral("plus")) |
| 299 | .pixmap(icon_size) | 301 | .pixmap(icon_size) |
| 300 | .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), | 302 | .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), |
| @@ -316,7 +318,8 @@ public: | |||
| 316 | explicit GameListFavorites() { | 318 | explicit GameListFavorites() { |
| 317 | setData(type(), TypeRole); | 319 | setData(type(), TypeRole); |
| 318 | 320 | ||
| 319 | const int icon_size = std::min(static_cast<int>(UISettings::values.icon_size), 64); | 321 | const int icon_size = |
| 322 | std::min(static_cast<int>(UISettings::values.icon_size.GetValue()), 64); | ||
| 320 | setData(QIcon::fromTheme(QStringLiteral("star")) | 323 | setData(QIcon::fromTheme(QStringLiteral("star")) |
| 321 | .pixmap(icon_size) | 324 | .pixmap(icon_size) |
| 322 | .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), | 325 | .scaled(icon_size, icon_size, Qt::IgnoreAspectRatio, Qt::SmoothTransformation), |
diff --git a/src/yuzu/main.cpp b/src/yuzu/main.cpp index f462cd072..cb9c01154 100644 --- a/src/yuzu/main.cpp +++ b/src/yuzu/main.cpp | |||
| @@ -156,11 +156,13 @@ enum class CalloutFlag : uint32_t { | |||
| 156 | }; | 156 | }; |
| 157 | 157 | ||
| 158 | void GMainWindow::ShowTelemetryCallout() { | 158 | void GMainWindow::ShowTelemetryCallout() { |
| 159 | if (UISettings::values.callout_flags & static_cast<uint32_t>(CalloutFlag::Telemetry)) { | 159 | if (UISettings::values.callout_flags.GetValue() & |
| 160 | static_cast<uint32_t>(CalloutFlag::Telemetry)) { | ||
| 160 | return; | 161 | return; |
| 161 | } | 162 | } |
| 162 | 163 | ||
| 163 | UISettings::values.callout_flags |= static_cast<uint32_t>(CalloutFlag::Telemetry); | 164 | UISettings::values.callout_flags = |
| 165 | UISettings::values.callout_flags.GetValue() | static_cast<uint32_t>(CalloutFlag::Telemetry); | ||
| 164 | const QString telemetry_message = | 166 | const QString telemetry_message = |
| 165 | tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous " | 167 | tr("<a href='https://yuzu-emu.org/help/feature/telemetry/'>Anonymous " |
| 166 | "data is collected</a> to help improve yuzu. " | 168 | "data is collected</a> to help improve yuzu. " |
| @@ -177,7 +179,7 @@ static void InitializeLogging() { | |||
| 177 | using namespace Common; | 179 | using namespace Common; |
| 178 | 180 | ||
| 179 | Log::Filter log_filter; | 181 | Log::Filter log_filter; |
| 180 | log_filter.ParseFilterString(Settings::values.log_filter); | 182 | log_filter.ParseFilterString(Settings::values.log_filter.GetValue()); |
| 181 | Log::SetGlobalFilter(log_filter); | 183 | Log::SetGlobalFilter(log_filter); |
| 182 | 184 | ||
| 183 | const auto log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir); | 185 | const auto log_dir = FS::GetYuzuPath(FS::YuzuPath::LogDir); |
| @@ -216,7 +218,7 @@ GMainWindow::GMainWindow() | |||
| 216 | default_theme_paths = QIcon::themeSearchPaths(); | 218 | default_theme_paths = QIcon::themeSearchPaths(); |
| 217 | UpdateUITheme(); | 219 | UpdateUITheme(); |
| 218 | 220 | ||
| 219 | SetDiscordEnabled(UISettings::values.enable_discord_presence); | 221 | SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); |
| 220 | discord_rpc->Update(); | 222 | discord_rpc->Update(); |
| 221 | 223 | ||
| 222 | RegisterMetaTypes(); | 224 | RegisterMetaTypes(); |
| @@ -1060,23 +1062,24 @@ void GMainWindow::RestoreUIState() { | |||
| 1060 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); | 1062 | render_window->restoreGeometry(UISettings::values.renderwindow_geometry); |
| 1061 | #if MICROPROFILE_ENABLED | 1063 | #if MICROPROFILE_ENABLED |
| 1062 | microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); | 1064 | microProfileDialog->restoreGeometry(UISettings::values.microprofile_geometry); |
| 1063 | microProfileDialog->setVisible(UISettings::values.microprofile_visible); | 1065 | microProfileDialog->setVisible(UISettings::values.microprofile_visible.GetValue()); |
| 1064 | #endif | 1066 | #endif |
| 1065 | 1067 | ||
| 1066 | game_list->LoadInterfaceLayout(); | 1068 | game_list->LoadInterfaceLayout(); |
| 1067 | 1069 | ||
| 1068 | ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode); | 1070 | ui.action_Single_Window_Mode->setChecked(UISettings::values.single_window_mode.GetValue()); |
| 1069 | ToggleWindowMode(); | 1071 | ToggleWindowMode(); |
| 1070 | 1072 | ||
| 1071 | ui.action_Fullscreen->setChecked(UISettings::values.fullscreen); | 1073 | ui.action_Fullscreen->setChecked(UISettings::values.fullscreen.GetValue()); |
| 1072 | 1074 | ||
| 1073 | ui.action_Display_Dock_Widget_Headers->setChecked(UISettings::values.display_titlebar); | 1075 | ui.action_Display_Dock_Widget_Headers->setChecked( |
| 1076 | UISettings::values.display_titlebar.GetValue()); | ||
| 1074 | OnDisplayTitleBars(ui.action_Display_Dock_Widget_Headers->isChecked()); | 1077 | OnDisplayTitleBars(ui.action_Display_Dock_Widget_Headers->isChecked()); |
| 1075 | 1078 | ||
| 1076 | ui.action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar); | 1079 | ui.action_Show_Filter_Bar->setChecked(UISettings::values.show_filter_bar.GetValue()); |
| 1077 | game_list->SetFilterVisible(ui.action_Show_Filter_Bar->isChecked()); | 1080 | game_list->SetFilterVisible(ui.action_Show_Filter_Bar->isChecked()); |
| 1078 | 1081 | ||
| 1079 | ui.action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar); | 1082 | ui.action_Show_Status_Bar->setChecked(UISettings::values.show_status_bar.GetValue()); |
| 1080 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); | 1083 | statusBar()->setVisible(ui.action_Show_Status_Bar->isChecked()); |
| 1081 | Debugger::ToggleConsole(); | 1084 | Debugger::ToggleConsole(); |
| 1082 | } | 1085 | } |
| @@ -1243,13 +1246,14 @@ bool GMainWindow::LoadROM(const QString& filename, std::size_t program_index) { | |||
| 1243 | const Core::System::ResultStatus result{ | 1246 | const Core::System::ResultStatus result{ |
| 1244 | system.Load(*render_window, filename.toStdString(), program_index)}; | 1247 | system.Load(*render_window, filename.toStdString(), program_index)}; |
| 1245 | 1248 | ||
| 1246 | const auto drd_callout = | 1249 | const auto drd_callout = (UISettings::values.callout_flags.GetValue() & |
| 1247 | (UISettings::values.callout_flags & static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; | 1250 | static_cast<u32>(CalloutFlag::DRDDeprecation)) == 0; |
| 1248 | 1251 | ||
| 1249 | if (result == Core::System::ResultStatus::Success && | 1252 | if (result == Core::System::ResultStatus::Success && |
| 1250 | system.GetAppLoader().GetFileType() == Loader::FileType::DeconstructedRomDirectory && | 1253 | system.GetAppLoader().GetFileType() == Loader::FileType::DeconstructedRomDirectory && |
| 1251 | drd_callout) { | 1254 | drd_callout) { |
| 1252 | UISettings::values.callout_flags |= static_cast<u32>(CalloutFlag::DRDDeprecation); | 1255 | UISettings::values.callout_flags = UISettings::values.callout_flags.GetValue() | |
| 1256 | static_cast<u32>(CalloutFlag::DRDDeprecation); | ||
| 1253 | QMessageBox::warning( | 1257 | QMessageBox::warning( |
| 1254 | this, tr("Warning Outdated Game Format"), | 1258 | this, tr("Warning Outdated Game Format"), |
| 1255 | tr("You are using the deconstructed ROM directory format for this game, which is an " | 1259 | tr("You are using the deconstructed ROM directory format for this game, which is an " |
| @@ -1351,6 +1355,9 @@ void GMainWindow::BootGame(const QString& filename, std::size_t program_index, S | |||
| 1351 | 1355 | ||
| 1352 | ConfigureVibration::SetAllVibrationDevices(); | 1356 | ConfigureVibration::SetAllVibrationDevices(); |
| 1353 | 1357 | ||
| 1358 | // Disable fps limit toggle when booting a new title | ||
| 1359 | Settings::values.disable_fps_limit.SetValue(false); | ||
| 1360 | |||
| 1354 | // Save configurations | 1361 | // Save configurations |
| 1355 | UpdateUISettings(); | 1362 | UpdateUISettings(); |
| 1356 | game_list->SaveInterfaceLayout(); | 1363 | game_list->SaveInterfaceLayout(); |
| @@ -2453,7 +2460,8 @@ void GMainWindow::ErrorDisplayDisplayError(QString error_code, QString error_tex | |||
| 2453 | } | 2460 | } |
| 2454 | 2461 | ||
| 2455 | void GMainWindow::OnMenuReportCompatibility() { | 2462 | void GMainWindow::OnMenuReportCompatibility() { |
| 2456 | if (!Settings::values.yuzu_token.empty() && !Settings::values.yuzu_username.empty()) { | 2463 | if (!Settings::values.yuzu_token.GetValue().empty() && |
| 2464 | !Settings::values.yuzu_username.GetValue().empty()) { | ||
| 2457 | CompatDB compatdb{this}; | 2465 | CompatDB compatdb{this}; |
| 2458 | compatdb.exec(); | 2466 | compatdb.exec(); |
| 2459 | } else { | 2467 | } else { |
| @@ -2618,7 +2626,7 @@ void GMainWindow::ResetWindowSize1080() { | |||
| 2618 | 2626 | ||
| 2619 | void GMainWindow::OnConfigure() { | 2627 | void GMainWindow::OnConfigure() { |
| 2620 | const auto old_theme = UISettings::values.theme; | 2628 | const auto old_theme = UISettings::values.theme; |
| 2621 | const bool old_discord_presence = UISettings::values.enable_discord_presence; | 2629 | const bool old_discord_presence = UISettings::values.enable_discord_presence.GetValue(); |
| 2622 | 2630 | ||
| 2623 | ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get()); | 2631 | ConfigureDialog configure_dialog(this, hotkey_registry, input_subsystem.get()); |
| 2624 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, | 2632 | connect(&configure_dialog, &ConfigureDialog::LanguageChanged, this, |
| @@ -2675,8 +2683,8 @@ void GMainWindow::OnConfigure() { | |||
| 2675 | if (UISettings::values.theme != old_theme) { | 2683 | if (UISettings::values.theme != old_theme) { |
| 2676 | UpdateUITheme(); | 2684 | UpdateUITheme(); |
| 2677 | } | 2685 | } |
| 2678 | if (UISettings::values.enable_discord_presence != old_discord_presence) { | 2686 | if (UISettings::values.enable_discord_presence.GetValue() != old_discord_presence) { |
| 2679 | SetDiscordEnabled(UISettings::values.enable_discord_presence); | 2687 | SetDiscordEnabled(UISettings::values.enable_discord_presence.GetValue()); |
| 2680 | } | 2688 | } |
| 2681 | emit UpdateThemedIcons(); | 2689 | emit UpdateThemedIcons(); |
| 2682 | 2690 | ||
| @@ -2832,7 +2840,8 @@ void GMainWindow::OnCaptureScreenshot() { | |||
| 2832 | } | 2840 | } |
| 2833 | } | 2841 | } |
| 2834 | #endif | 2842 | #endif |
| 2835 | render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor, filename); | 2843 | render_window->CaptureScreenshot(UISettings::values.screenshot_resolution_factor.GetValue(), |
| 2844 | filename); | ||
| 2836 | OnStartGame(); | 2845 | OnStartGame(); |
| 2837 | } | 2846 | } |
| 2838 | 2847 | ||
| @@ -2907,7 +2916,12 @@ void GMainWindow::UpdateStatusBar() { | |||
| 2907 | } else { | 2916 | } else { |
| 2908 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); | 2917 | emu_speed_label->setText(tr("Speed: %1%").arg(results.emulation_speed * 100.0, 0, 'f', 0)); |
| 2909 | } | 2918 | } |
| 2910 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); | 2919 | if (Settings::values.disable_fps_limit) { |
| 2920 | game_fps_label->setText( | ||
| 2921 | tr("Game: %1 FPS (Limit off)").arg(results.average_game_fps, 0, 'f', 0)); | ||
| 2922 | } else { | ||
| 2923 | game_fps_label->setText(tr("Game: %1 FPS").arg(results.average_game_fps, 0, 'f', 0)); | ||
| 2924 | } | ||
| 2911 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); | 2925 | emu_frametime_label->setText(tr("Frame: %1 ms").arg(results.frametime * 1000.0, 0, 'f', 2)); |
| 2912 | 2926 | ||
| 2913 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); | 2927 | emu_speed_label->setVisible(!Settings::values.use_multi_core.GetValue()); |
diff --git a/src/yuzu/uisettings.h b/src/yuzu/uisettings.h index cdcb83f9f..7b9d2dd53 100644 --- a/src/yuzu/uisettings.h +++ b/src/yuzu/uisettings.h | |||
| @@ -13,6 +13,7 @@ | |||
| 13 | #include <QStringList> | 13 | #include <QStringList> |
| 14 | #include <QVector> | 14 | #include <QVector> |
| 15 | #include "common/common_types.h" | 15 | #include "common/common_types.h" |
| 16 | #include "common/settings.h" | ||
| 16 | 17 | ||
| 17 | namespace UISettings { | 18 | namespace UISettings { |
| 18 | 19 | ||
| @@ -48,26 +49,26 @@ struct Values { | |||
| 48 | QByteArray gamelist_header_state; | 49 | QByteArray gamelist_header_state; |
| 49 | 50 | ||
| 50 | QByteArray microprofile_geometry; | 51 | QByteArray microprofile_geometry; |
| 51 | bool microprofile_visible; | 52 | Settings::BasicSetting<bool> microprofile_visible{false, "microProfileDialogVisible"}; |
| 52 | 53 | ||
| 53 | bool single_window_mode; | 54 | Settings::BasicSetting<bool> single_window_mode{true, "singleWindowMode"}; |
| 54 | bool fullscreen; | 55 | Settings::BasicSetting<bool> fullscreen{false, "fullscreen"}; |
| 55 | bool display_titlebar; | 56 | Settings::BasicSetting<bool> display_titlebar{true, "displayTitleBars"}; |
| 56 | bool show_filter_bar; | 57 | Settings::BasicSetting<bool> show_filter_bar{true, "showFilterBar"}; |
| 57 | bool show_status_bar; | 58 | Settings::BasicSetting<bool> show_status_bar{true, "showStatusBar"}; |
| 58 | 59 | ||
| 59 | bool confirm_before_closing; | 60 | Settings::BasicSetting<bool> confirm_before_closing{true, "confirmClose"}; |
| 60 | bool first_start; | 61 | Settings::BasicSetting<bool> first_start{true, "firstStart"}; |
| 61 | bool pause_when_in_background; | 62 | Settings::BasicSetting<bool> pause_when_in_background{false, "pauseWhenInBackground"}; |
| 62 | bool hide_mouse; | 63 | Settings::BasicSetting<bool> hide_mouse{false, "hideInactiveMouse"}; |
| 63 | 64 | ||
| 64 | bool select_user_on_boot; | 65 | Settings::BasicSetting<bool> select_user_on_boot{false, "select_user_on_boot"}; |
| 65 | 66 | ||
| 66 | // Discord RPC | 67 | // Discord RPC |
| 67 | bool enable_discord_presence; | 68 | Settings::BasicSetting<bool> enable_discord_presence{true, "enable_discord_presence"}; |
| 68 | 69 | ||
| 69 | bool enable_screenshot_save_as; | 70 | Settings::BasicSetting<bool> enable_screenshot_save_as{true, "enable_screenshot_save_as"}; |
| 70 | u16 screenshot_resolution_factor; | 71 | Settings::BasicSetting<u16> screenshot_resolution_factor{0, "screenshot_resolution_factor"}; |
| 71 | 72 | ||
| 72 | QString roms_path; | 73 | QString roms_path; |
| 73 | QString symbols_path; | 74 | QString symbols_path; |
| @@ -83,18 +84,18 @@ struct Values { | |||
| 83 | // Shortcut name <Shortcut, context> | 84 | // Shortcut name <Shortcut, context> |
| 84 | std::vector<Shortcut> shortcuts; | 85 | std::vector<Shortcut> shortcuts; |
| 85 | 86 | ||
| 86 | uint32_t callout_flags; | 87 | Settings::BasicSetting<uint32_t> callout_flags{0, "calloutFlags"}; |
| 87 | 88 | ||
| 88 | // logging | 89 | // logging |
| 89 | bool show_console; | 90 | Settings::BasicSetting<bool> show_console{false, "showConsole"}; |
| 90 | 91 | ||
| 91 | // Game List | 92 | // Game List |
| 92 | bool show_add_ons; | 93 | Settings::BasicSetting<bool> show_add_ons{true, "show_add_ons"}; |
| 93 | uint32_t icon_size; | 94 | Settings::BasicSetting<uint32_t> icon_size{64, "icon_size"}; |
| 94 | uint8_t row_1_text_id; | 95 | Settings::BasicSetting<uint8_t> row_1_text_id{3, "row_1_text_id"}; |
| 95 | uint8_t row_2_text_id; | 96 | Settings::BasicSetting<uint8_t> row_2_text_id{2, "row_2_text_id"}; |
| 96 | std::atomic_bool is_game_list_reload_pending{false}; | 97 | std::atomic_bool is_game_list_reload_pending{false}; |
| 97 | bool cache_game_list; | 98 | Settings::BasicSetting<bool> cache_game_list{true, "cache_game_list"}; |
| 98 | 99 | ||
| 99 | bool configuration_applied; | 100 | bool configuration_applied; |
| 100 | bool reset_to_defaults; | 101 | bool reset_to_defaults; |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 60bf66ec0..325584a1a 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -241,6 +241,24 @@ static const std::array<int, 8> keyboard_mods{ | |||
| 241 | SDL_SCANCODE_RCTRL, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_RALT, SDL_SCANCODE_RGUI, | 241 | SDL_SCANCODE_RCTRL, SDL_SCANCODE_RSHIFT, SDL_SCANCODE_RALT, SDL_SCANCODE_RGUI, |
| 242 | }; | 242 | }; |
| 243 | 243 | ||
| 244 | template <> | ||
| 245 | void Config::ReadSetting(const std::string& group, Settings::BasicSetting<float>& setting) { | ||
| 246 | setting = sdl2_config->GetReal(group, setting.GetLabel(), setting.GetDefault()); | ||
| 247 | } | ||
| 248 | template <> | ||
| 249 | void Config::ReadSetting(const std::string& group, Settings::BasicSetting<std::string>& setting) { | ||
| 250 | setting = sdl2_config->Get(group, setting.GetLabel(), setting.GetDefault()); | ||
| 251 | } | ||
| 252 | template <> | ||
| 253 | void Config::ReadSetting(const std::string& group, Settings::BasicSetting<bool>& setting) { | ||
| 254 | setting = sdl2_config->GetBoolean(group, setting.GetLabel(), setting.GetDefault()); | ||
| 255 | } | ||
| 256 | template <typename Type> | ||
| 257 | void Config::ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting) { | ||
| 258 | setting = static_cast<Type>(sdl2_config->GetInteger(group, setting.GetLabel(), | ||
| 259 | static_cast<long>(setting.GetDefault()))); | ||
| 260 | } | ||
| 261 | |||
| 244 | void Config::ReadValues() { | 262 | void Config::ReadValues() { |
| 245 | // Controls | 263 | // Controls |
| 246 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { | 264 | for (std::size_t p = 0; p < Settings::values.players.GetValue().size(); ++p) { |
| @@ -264,8 +282,7 @@ void Config::ReadValues() { | |||
| 264 | } | 282 | } |
| 265 | } | 283 | } |
| 266 | 284 | ||
| 267 | Settings::values.mouse_enabled = | 285 | ReadSetting("ControlsGeneral", Settings::values.mouse_enabled); |
| 268 | sdl2_config->GetBoolean("ControlsGeneral", "mouse_enabled", false); | ||
| 269 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { | 286 | for (int i = 0; i < Settings::NativeMouseButton::NumMouseButtons; ++i) { |
| 270 | std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); | 287 | std::string default_param = InputCommon::GenerateKeyboardParam(default_mouse_buttons[i]); |
| 271 | Settings::values.mouse_buttons[i] = sdl2_config->Get( | 288 | Settings::values.mouse_buttons[i] = sdl2_config->Get( |
| @@ -275,14 +292,11 @@ void Config::ReadValues() { | |||
| 275 | Settings::values.mouse_buttons[i] = default_param; | 292 | Settings::values.mouse_buttons[i] = default_param; |
| 276 | } | 293 | } |
| 277 | 294 | ||
| 278 | Settings::values.motion_device = sdl2_config->Get( | 295 | ReadSetting("ControlsGeneral", Settings::values.motion_device); |
| 279 | "ControlsGeneral", "motion_device", "engine:motion_emu,update_period:100,sensitivity:0.01"); | ||
| 280 | 296 | ||
| 281 | Settings::values.keyboard_enabled = | 297 | ReadSetting("ControlsGeneral", Settings::values.keyboard_enabled); |
| 282 | sdl2_config->GetBoolean("ControlsGeneral", "keyboard_enabled", false); | ||
| 283 | 298 | ||
| 284 | Settings::values.debug_pad_enabled = | 299 | ReadSetting("ControlsGeneral", Settings::values.debug_pad_enabled); |
| 285 | sdl2_config->GetBoolean("ControlsGeneral", "debug_pad_enabled", false); | ||
| 286 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { | 300 | for (int i = 0; i < Settings::NativeButton::NumButtons; ++i) { |
| 287 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); | 301 | std::string default_param = InputCommon::GenerateKeyboardParam(default_buttons[i]); |
| 288 | Settings::values.debug_pad_buttons[i] = sdl2_config->Get( | 302 | Settings::values.debug_pad_buttons[i] = sdl2_config->Get( |
| @@ -303,12 +317,9 @@ void Config::ReadValues() { | |||
| 303 | Settings::values.debug_pad_analogs[i] = default_param; | 317 | Settings::values.debug_pad_analogs[i] = default_param; |
| 304 | } | 318 | } |
| 305 | 319 | ||
| 306 | Settings::values.vibration_enabled.SetValue( | 320 | ReadSetting("ControlsGeneral", Settings::values.vibration_enabled); |
| 307 | sdl2_config->GetBoolean("ControlsGeneral", "vibration_enabled", true)); | 321 | ReadSetting("ControlsGeneral", Settings::values.enable_accurate_vibrations); |
| 308 | Settings::values.enable_accurate_vibrations.SetValue( | 322 | ReadSetting("ControlsGeneral", Settings::values.motion_enabled); |
| 309 | sdl2_config->GetBoolean("ControlsGeneral", "enable_accurate_vibrations", false)); | ||
| 310 | Settings::values.motion_enabled.SetValue( | ||
| 311 | sdl2_config->GetBoolean("ControlsGeneral", "motion_enabled", true)); | ||
| 312 | Settings::values.touchscreen.enabled = | 323 | Settings::values.touchscreen.enabled = |
| 313 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); | 324 | sdl2_config->GetBoolean("ControlsGeneral", "touch_enabled", true); |
| 314 | Settings::values.touchscreen.rotation_angle = | 325 | Settings::values.touchscreen.rotation_angle = |
| @@ -349,13 +360,11 @@ void Config::ReadValues() { | |||
| 349 | Settings::TouchFromButtonMap{"default", {}}); | 360 | Settings::TouchFromButtonMap{"default", {}}); |
| 350 | num_touch_from_button_maps = 1; | 361 | num_touch_from_button_maps = 1; |
| 351 | } | 362 | } |
| 352 | Settings::values.use_touch_from_button = | 363 | ReadSetting("ControlsGeneral", Settings::values.use_touch_from_button); |
| 353 | sdl2_config->GetBoolean("ControlsGeneral", "use_touch_from_button", false); | 364 | Settings::values.touch_from_button_map_index = std::clamp( |
| 354 | Settings::values.touch_from_button_map_index = | 365 | Settings::values.touch_from_button_map_index.GetValue(), 0, num_touch_from_button_maps - 1); |
| 355 | std::clamp(Settings::values.touch_from_button_map_index, 0, num_touch_from_button_maps - 1); | ||
| 356 | 366 | ||
| 357 | Settings::values.udp_input_servers = | 367 | ReadSetting("ControlsGeneral", Settings::values.udp_input_servers); |
| 358 | sdl2_config->Get("Controls", "udp_input_address", InputCommon::CemuhookUDP::DEFAULT_SRV); | ||
| 359 | 368 | ||
| 360 | std::transform(keyboard_keys.begin(), keyboard_keys.end(), | 369 | std::transform(keyboard_keys.begin(), keyboard_keys.end(), |
| 361 | Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); | 370 | Settings::values.keyboard_keys.begin(), InputCommon::GenerateKeyboardParam); |
| @@ -367,8 +376,7 @@ void Config::ReadValues() { | |||
| 367 | Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); | 376 | Settings::values.keyboard_mods.begin(), InputCommon::GenerateKeyboardParam); |
| 368 | 377 | ||
| 369 | // Data Storage | 378 | // Data Storage |
| 370 | Settings::values.use_virtual_sd = | 379 | ReadSetting("Data Storage", Settings::values.use_virtual_sd); |
| 371 | sdl2_config->GetBoolean("Data Storage", "use_virtual_sd", true); | ||
| 372 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, | 380 | FS::SetYuzuPath(FS::YuzuPath::NANDDir, |
| 373 | sdl2_config->Get("Data Storage", "nand_directory", | 381 | sdl2_config->Get("Data Storage", "nand_directory", |
| 374 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); | 382 | FS::GetYuzuPathString(FS::YuzuPath::NANDDir))); |
| @@ -381,18 +389,16 @@ void Config::ReadValues() { | |||
| 381 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, | 389 | FS::SetYuzuPath(FS::YuzuPath::DumpDir, |
| 382 | sdl2_config->Get("Data Storage", "dump_directory", | 390 | sdl2_config->Get("Data Storage", "dump_directory", |
| 383 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); | 391 | FS::GetYuzuPathString(FS::YuzuPath::DumpDir))); |
| 384 | Settings::values.gamecard_inserted = | 392 | ReadSetting("Data Storage", Settings::values.gamecard_inserted); |
| 385 | sdl2_config->GetBoolean("Data Storage", "gamecard_inserted", false); | 393 | ReadSetting("Data Storage", Settings::values.gamecard_current_game); |
| 386 | Settings::values.gamecard_current_game = | 394 | ReadSetting("Data Storage", Settings::values.gamecard_path); |
| 387 | sdl2_config->GetBoolean("Data Storage", "gamecard_current_game", false); | ||
| 388 | Settings::values.gamecard_path = sdl2_config->Get("Data Storage", "gamecard_path", ""); | ||
| 389 | 395 | ||
| 390 | // System | 396 | // System |
| 391 | Settings::values.use_docked_mode.SetValue( | 397 | ReadSetting("System", Settings::values.use_docked_mode); |
| 392 | sdl2_config->GetBoolean("System", "use_docked_mode", true)); | ||
| 393 | 398 | ||
| 394 | Settings::values.current_user = std::clamp<int>( | 399 | ReadSetting("System", Settings::values.current_user); |
| 395 | sdl2_config->GetInteger("System", "current_user", 0), 0, Service::Account::MAX_USERS - 1); | 400 | Settings::values.current_user = std::clamp<int>(Settings::values.current_user.GetValue(), 0, |
| 401 | Service::Account::MAX_USERS - 1); | ||
| 396 | 402 | ||
| 397 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); | 403 | const auto rng_seed_enabled = sdl2_config->GetBoolean("System", "rng_seed_enabled", false); |
| 398 | if (rng_seed_enabled) { | 404 | if (rng_seed_enabled) { |
| @@ -409,89 +415,60 @@ void Config::ReadValues() { | |||
| 409 | Settings::values.custom_rtc = std::nullopt; | 415 | Settings::values.custom_rtc = std::nullopt; |
| 410 | } | 416 | } |
| 411 | 417 | ||
| 412 | Settings::values.language_index.SetValue( | 418 | ReadSetting("System", Settings::values.language_index); |
| 413 | sdl2_config->GetInteger("System", "language_index", 1)); | 419 | ReadSetting("System", Settings::values.time_zone_index); |
| 414 | Settings::values.time_zone_index.SetValue( | ||
| 415 | sdl2_config->GetInteger("System", "time_zone_index", 0)); | ||
| 416 | 420 | ||
| 417 | // Core | 421 | // Core |
| 418 | Settings::values.use_multi_core.SetValue( | 422 | ReadSetting("Core", Settings::values.use_multi_core); |
| 419 | sdl2_config->GetBoolean("Core", "use_multi_core", true)); | ||
| 420 | 423 | ||
| 421 | // Renderer | 424 | // Renderer |
| 422 | const int renderer_backend = sdl2_config->GetInteger( | 425 | ReadSetting("Renderer", Settings::values.renderer_backend); |
| 423 | "Renderer", "backend", static_cast<int>(Settings::RendererBackend::OpenGL)); | 426 | ReadSetting("Renderer", Settings::values.renderer_debug); |
| 424 | Settings::values.renderer_backend.SetValue( | 427 | ReadSetting("Renderer", Settings::values.vulkan_device); |
| 425 | static_cast<Settings::RendererBackend>(renderer_backend)); | 428 | |
| 426 | Settings::values.renderer_debug = sdl2_config->GetBoolean("Renderer", "debug", false); | 429 | ReadSetting("Renderer", Settings::values.aspect_ratio); |
| 427 | Settings::values.vulkan_device.SetValue( | 430 | ReadSetting("Renderer", Settings::values.max_anisotropy); |
| 428 | sdl2_config->GetInteger("Renderer", "vulkan_device", 0)); | 431 | ReadSetting("Renderer", Settings::values.use_frame_limit); |
| 429 | 432 | ReadSetting("Renderer", Settings::values.frame_limit); | |
| 430 | Settings::values.aspect_ratio.SetValue( | 433 | ReadSetting("Renderer", Settings::values.use_disk_shader_cache); |
| 431 | static_cast<int>(sdl2_config->GetInteger("Renderer", "aspect_ratio", 0))); | 434 | ReadSetting("Renderer", Settings::values.gpu_accuracy); |
| 432 | Settings::values.max_anisotropy.SetValue( | 435 | ReadSetting("Renderer", Settings::values.use_asynchronous_gpu_emulation); |
| 433 | static_cast<int>(sdl2_config->GetInteger("Renderer", "max_anisotropy", 0))); | 436 | ReadSetting("Renderer", Settings::values.use_vsync); |
| 434 | Settings::values.use_frame_limit.SetValue( | 437 | ReadSetting("Renderer", Settings::values.disable_fps_limit); |
| 435 | sdl2_config->GetBoolean("Renderer", "use_frame_limit", true)); | 438 | ReadSetting("Renderer", Settings::values.use_assembly_shaders); |
| 436 | Settings::values.frame_limit.SetValue( | 439 | ReadSetting("Renderer", Settings::values.use_asynchronous_shaders); |
| 437 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "frame_limit", 100))); | 440 | ReadSetting("Renderer", Settings::values.use_nvdec_emulation); |
| 438 | Settings::values.use_disk_shader_cache.SetValue( | 441 | ReadSetting("Renderer", Settings::values.accelerate_astc); |
| 439 | sdl2_config->GetBoolean("Renderer", "use_disk_shader_cache", false)); | 442 | ReadSetting("Renderer", Settings::values.use_fast_gpu_time); |
| 440 | const int gpu_accuracy_level = sdl2_config->GetInteger("Renderer", "gpu_accuracy", 1); | 443 | |
| 441 | Settings::values.gpu_accuracy.SetValue(static_cast<Settings::GPUAccuracy>(gpu_accuracy_level)); | 444 | ReadSetting("Renderer", Settings::values.bg_red); |
| 442 | Settings::values.use_asynchronous_gpu_emulation.SetValue( | 445 | ReadSetting("Renderer", Settings::values.bg_green); |
| 443 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_gpu_emulation", true)); | 446 | ReadSetting("Renderer", Settings::values.bg_blue); |
| 444 | Settings::values.use_vsync.SetValue( | ||
| 445 | static_cast<u16>(sdl2_config->GetInteger("Renderer", "use_vsync", 1))); | ||
| 446 | Settings::values.disable_fps_limit.SetValue( | ||
| 447 | sdl2_config->GetBoolean("Renderer", "disable_fps_limit", false)); | ||
| 448 | Settings::values.use_assembly_shaders.SetValue( | ||
| 449 | sdl2_config->GetBoolean("Renderer", "use_assembly_shaders", true)); | ||
| 450 | Settings::values.use_asynchronous_shaders.SetValue( | ||
| 451 | sdl2_config->GetBoolean("Renderer", "use_asynchronous_shaders", false)); | ||
| 452 | Settings::values.use_nvdec_emulation.SetValue( | ||
| 453 | sdl2_config->GetBoolean("Renderer", "use_nvdec_emulation", true)); | ||
| 454 | Settings::values.accelerate_astc.SetValue( | ||
| 455 | sdl2_config->GetBoolean("Renderer", "accelerate_astc", true)); | ||
| 456 | Settings::values.use_fast_gpu_time.SetValue( | ||
| 457 | sdl2_config->GetBoolean("Renderer", "use_fast_gpu_time", true)); | ||
| 458 | |||
| 459 | Settings::values.bg_red.SetValue( | ||
| 460 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_red", 0.0))); | ||
| 461 | Settings::values.bg_green.SetValue( | ||
| 462 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_green", 0.0))); | ||
| 463 | Settings::values.bg_blue.SetValue( | ||
| 464 | static_cast<float>(sdl2_config->GetReal("Renderer", "bg_blue", 0.0))); | ||
| 465 | 447 | ||
| 466 | // Audio | 448 | // Audio |
| 467 | Settings::values.sink_id = sdl2_config->Get("Audio", "output_engine", "auto"); | 449 | ReadSetting("Audio", Settings::values.sink_id); |
| 468 | Settings::values.enable_audio_stretching.SetValue( | 450 | ReadSetting("Audio", Settings::values.enable_audio_stretching); |
| 469 | sdl2_config->GetBoolean("Audio", "enable_audio_stretching", true)); | 451 | ReadSetting("Audio", Settings::values.audio_device_id); |
| 470 | Settings::values.audio_device_id = sdl2_config->Get("Audio", "output_device", "auto"); | 452 | ReadSetting("Audio", Settings::values.volume); |
| 471 | Settings::values.volume.SetValue( | ||
| 472 | static_cast<float>(sdl2_config->GetReal("Audio", "volume", 1))); | ||
| 473 | 453 | ||
| 474 | // Miscellaneous | 454 | // Miscellaneous |
| 475 | Settings::values.log_filter = sdl2_config->Get("Miscellaneous", "log_filter", "*:Trace"); | 455 | // log_filter has a different default here than from common |
| 476 | Settings::values.use_dev_keys = sdl2_config->GetBoolean("Miscellaneous", "use_dev_keys", false); | 456 | Settings::values.log_filter = |
| 457 | sdl2_config->Get("Miscellaneous", Settings::values.log_filter.GetLabel(), "*:Trace"); | ||
| 458 | ReadSetting("Miscellaneous", Settings::values.use_dev_keys); | ||
| 477 | 459 | ||
| 478 | // Debugging | 460 | // Debugging |
| 479 | Settings::values.record_frame_times = | 461 | Settings::values.record_frame_times = |
| 480 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); | 462 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); |
| 481 | Settings::values.program_args = sdl2_config->Get("Debugging", "program_args", ""); | 463 | ReadSetting("Debugging", Settings::values.program_args); |
| 482 | Settings::values.dump_exefs = sdl2_config->GetBoolean("Debugging", "dump_exefs", false); | 464 | ReadSetting("Debugging", Settings::values.dump_exefs); |
| 483 | Settings::values.dump_nso = sdl2_config->GetBoolean("Debugging", "dump_nso", false); | 465 | ReadSetting("Debugging", Settings::values.dump_nso); |
| 484 | Settings::values.enable_fs_access_log = | 466 | ReadSetting("Debugging", Settings::values.enable_fs_access_log); |
| 485 | sdl2_config->GetBoolean("Debugging", "enable_fs_access_log", false); | 467 | ReadSetting("Debugging", Settings::values.reporting_services); |
| 486 | Settings::values.reporting_services = | 468 | ReadSetting("Debugging", Settings::values.quest_flag); |
| 487 | sdl2_config->GetBoolean("Debugging", "reporting_services", false); | 469 | ReadSetting("Debugging", Settings::values.use_debug_asserts); |
| 488 | Settings::values.quest_flag = sdl2_config->GetBoolean("Debugging", "quest_flag", false); | 470 | ReadSetting("Debugging", Settings::values.use_auto_stub); |
| 489 | Settings::values.use_debug_asserts = | 471 | ReadSetting("Debugging", Settings::values.disable_macro_jit); |
| 490 | sdl2_config->GetBoolean("Debugging", "use_debug_asserts", false); | ||
| 491 | Settings::values.use_auto_stub = sdl2_config->GetBoolean("Debugging", "use_auto_stub", false); | ||
| 492 | |||
| 493 | Settings::values.disable_macro_jit = | ||
| 494 | sdl2_config->GetBoolean("Debugging", "disable_macro_jit", false); | ||
| 495 | 472 | ||
| 496 | const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); | 473 | const auto title_list = sdl2_config->Get("AddOns", "title_ids", ""); |
| 497 | std::stringstream ss(title_list); | 474 | std::stringstream ss(title_list); |
| @@ -511,17 +488,14 @@ void Config::ReadValues() { | |||
| 511 | } | 488 | } |
| 512 | 489 | ||
| 513 | // Web Service | 490 | // Web Service |
| 514 | Settings::values.enable_telemetry = | 491 | ReadSetting("WebService", Settings::values.enable_telemetry); |
| 515 | sdl2_config->GetBoolean("WebService", "enable_telemetry", true); | 492 | ReadSetting("WebService", Settings::values.web_api_url); |
| 516 | Settings::values.web_api_url = | 493 | ReadSetting("WebService", Settings::values.yuzu_username); |
| 517 | sdl2_config->Get("WebService", "web_api_url", "https://api.yuzu-emu.org"); | 494 | ReadSetting("WebService", Settings::values.yuzu_token); |
| 518 | Settings::values.yuzu_username = sdl2_config->Get("WebService", "yuzu_username", ""); | ||
| 519 | Settings::values.yuzu_token = sdl2_config->Get("WebService", "yuzu_token", ""); | ||
| 520 | 495 | ||
| 521 | // Services | 496 | // Services |
| 522 | Settings::values.bcat_backend = sdl2_config->Get("Services", "bcat_backend", "none"); | 497 | ReadSetting("Services", Settings::values.bcat_backend); |
| 523 | Settings::values.bcat_boxcat_local = | 498 | ReadSetting("Services", Settings::values.bcat_boxcat_local); |
| 524 | sdl2_config->GetBoolean("Services", "bcat_boxcat_local", false); | ||
| 525 | } | 499 | } |
| 526 | 500 | ||
| 527 | void Config::Reload() { | 501 | void Config::Reload() { |
diff --git a/src/yuzu_cmd/config.h b/src/yuzu_cmd/config.h index 807199278..1ee932be2 100644 --- a/src/yuzu_cmd/config.h +++ b/src/yuzu_cmd/config.h | |||
| @@ -8,6 +8,8 @@ | |||
| 8 | #include <memory> | 8 | #include <memory> |
| 9 | #include <string> | 9 | #include <string> |
| 10 | 10 | ||
| 11 | #include "common/settings.h" | ||
| 12 | |||
| 11 | class INIReader; | 13 | class INIReader; |
| 12 | 14 | ||
| 13 | class Config { | 15 | class Config { |
| @@ -22,4 +24,14 @@ public: | |||
| 22 | ~Config(); | 24 | ~Config(); |
| 23 | 25 | ||
| 24 | void Reload(); | 26 | void Reload(); |
| 27 | |||
| 28 | private: | ||
| 29 | /** | ||
| 30 | * Applies a value read from the sdl2_config to a BasicSetting. | ||
| 31 | * | ||
| 32 | * @param group The name of the INI group | ||
| 33 | * @param setting The yuzu setting to modify | ||
| 34 | */ | ||
| 35 | template <typename Type> | ||
| 36 | void ReadSetting(const std::string& group, Settings::BasicSetting<Type>& setting); | ||
| 25 | }; | 37 | }; |
diff --git a/src/yuzu_cmd/yuzu.cpp b/src/yuzu_cmd/yuzu.cpp index 50e388312..9607cdcb1 100644 --- a/src/yuzu_cmd/yuzu.cpp +++ b/src/yuzu_cmd/yuzu.cpp | |||
| @@ -78,7 +78,7 @@ static void InitializeLogging() { | |||
| 78 | using namespace Common; | 78 | using namespace Common; |
| 79 | 79 | ||
| 80 | Log::Filter log_filter(Log::Level::Debug); | 80 | Log::Filter log_filter(Log::Level::Debug); |
| 81 | log_filter.ParseFilterString(Settings::values.log_filter); | 81 | log_filter.ParseFilterString(static_cast<std::string>(Settings::values.log_filter)); |
| 82 | Log::SetGlobalFilter(log_filter); | 82 | Log::SetGlobalFilter(log_filter); |
| 83 | 83 | ||
| 84 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); | 84 | Log::AddBackend(std::make_unique<Log::ColorConsoleBackend>()); |