diff options
| -rw-r--r-- | src/core/core.cpp | 25 | ||||
| -rw-r--r-- | src/core/file_sys/submission_package.cpp | 26 | ||||
| -rw-r--r-- | src/core/loader/nsp.cpp | 27 | ||||
| -rw-r--r-- | src/core/memory.cpp | 9 | ||||
| -rw-r--r-- | src/core/perf_stats.cpp | 47 | ||||
| -rw-r--r-- | src/core/perf_stats.h | 21 | ||||
| -rw-r--r-- | src/core/settings.h | 1 | ||||
| -rw-r--r-- | src/video_core/renderer_opengl/maxwell_to_gl.h | 4 | ||||
| -rw-r--r-- | src/yuzu/configuration/config.cpp | 5 | ||||
| -rw-r--r-- | src/yuzu/configuration/configure_input.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu_cmd/config.cpp | 2 | ||||
| -rw-r--r-- | src/yuzu_cmd/default_ini.h | 2 |
12 files changed, 143 insertions, 28 deletions
diff --git a/src/core/core.cpp b/src/core/core.cpp index 3d0978cbf..9ab174de2 100644 --- a/src/core/core.cpp +++ b/src/core/core.cpp | |||
| @@ -160,10 +160,6 @@ struct System::Impl { | |||
| 160 | 160 | ||
| 161 | LOG_DEBUG(Core, "Initialized OK"); | 161 | LOG_DEBUG(Core, "Initialized OK"); |
| 162 | 162 | ||
| 163 | // Reset counters and set time origin to current frame | ||
| 164 | GetAndResetPerfStats(); | ||
| 165 | perf_stats.BeginSystemFrame(); | ||
| 166 | |||
| 167 | return ResultStatus::Success; | 163 | return ResultStatus::Success; |
| 168 | } | 164 | } |
| 169 | 165 | ||
| @@ -206,6 +202,16 @@ struct System::Impl { | |||
| 206 | main_process->Run(load_parameters->main_thread_priority, | 202 | main_process->Run(load_parameters->main_thread_priority, |
| 207 | load_parameters->main_thread_stack_size); | 203 | load_parameters->main_thread_stack_size); |
| 208 | 204 | ||
| 205 | u64 title_id{0}; | ||
| 206 | if (app_loader->ReadProgramId(title_id) != Loader::ResultStatus::Success) { | ||
| 207 | LOG_ERROR(Core, "Failed to find title id for ROM (Error {})", | ||
| 208 | static_cast<u32>(load_result)); | ||
| 209 | } | ||
| 210 | perf_stats = std::make_unique<PerfStats>(title_id); | ||
| 211 | // Reset counters and set time origin to current frame | ||
| 212 | GetAndResetPerfStats(); | ||
| 213 | perf_stats->BeginSystemFrame(); | ||
| 214 | |||
| 209 | status = ResultStatus::Success; | 215 | status = ResultStatus::Success; |
| 210 | return status; | 216 | return status; |
| 211 | } | 217 | } |
| @@ -219,6 +225,8 @@ struct System::Impl { | |||
| 219 | perf_results.game_fps); | 225 | perf_results.game_fps); |
| 220 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", | 226 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Shutdown_Frametime", |
| 221 | perf_results.frametime * 1000.0); | 227 | perf_results.frametime * 1000.0); |
| 228 | telemetry_session->AddField(Telemetry::FieldType::Performance, "Mean_Frametime_MS", | ||
| 229 | perf_stats->GetMeanFrametime()); | ||
| 222 | 230 | ||
| 223 | is_powered_on = false; | 231 | is_powered_on = false; |
| 224 | 232 | ||
| @@ -229,6 +237,7 @@ struct System::Impl { | |||
| 229 | service_manager.reset(); | 237 | service_manager.reset(); |
| 230 | cheat_engine.reset(); | 238 | cheat_engine.reset(); |
| 231 | telemetry_session.reset(); | 239 | telemetry_session.reset(); |
| 240 | perf_stats.reset(); | ||
| 232 | gpu_core.reset(); | 241 | gpu_core.reset(); |
| 233 | 242 | ||
| 234 | // Close all CPU/threading state | 243 | // Close all CPU/threading state |
| @@ -286,7 +295,7 @@ struct System::Impl { | |||
| 286 | } | 295 | } |
| 287 | 296 | ||
| 288 | PerfStatsResults GetAndResetPerfStats() { | 297 | PerfStatsResults GetAndResetPerfStats() { |
| 289 | return perf_stats.GetAndResetStats(core_timing.GetGlobalTimeUs()); | 298 | return perf_stats->GetAndResetStats(core_timing.GetGlobalTimeUs()); |
| 290 | } | 299 | } |
| 291 | 300 | ||
| 292 | Timing::CoreTiming core_timing; | 301 | Timing::CoreTiming core_timing; |
| @@ -327,7 +336,7 @@ struct System::Impl { | |||
| 327 | ResultStatus status = ResultStatus::Success; | 336 | ResultStatus status = ResultStatus::Success; |
| 328 | std::string status_details = ""; | 337 | std::string status_details = ""; |
| 329 | 338 | ||
| 330 | Core::PerfStats perf_stats; | 339 | std::unique_ptr<Core::PerfStats> perf_stats; |
| 331 | Core::FrameLimiter frame_limiter; | 340 | Core::FrameLimiter frame_limiter; |
| 332 | }; | 341 | }; |
| 333 | 342 | ||
| @@ -480,11 +489,11 @@ const Timing::CoreTiming& System::CoreTiming() const { | |||
| 480 | } | 489 | } |
| 481 | 490 | ||
| 482 | Core::PerfStats& System::GetPerfStats() { | 491 | Core::PerfStats& System::GetPerfStats() { |
| 483 | return impl->perf_stats; | 492 | return *impl->perf_stats; |
| 484 | } | 493 | } |
| 485 | 494 | ||
| 486 | const Core::PerfStats& System::GetPerfStats() const { | 495 | const Core::PerfStats& System::GetPerfStats() const { |
| 487 | return impl->perf_stats; | 496 | return *impl->perf_stats; |
| 488 | } | 497 | } |
| 489 | 498 | ||
| 490 | Core::FrameLimiter& System::FrameLimiter() { | 499 | Core::FrameLimiter& System::FrameLimiter() { |
diff --git a/src/core/file_sys/submission_package.cpp b/src/core/file_sys/submission_package.cpp index 8b3b14e25..730221fd6 100644 --- a/src/core/file_sys/submission_package.cpp +++ b/src/core/file_sys/submission_package.cpp | |||
| @@ -14,6 +14,7 @@ | |||
| 14 | #include "core/file_sys/content_archive.h" | 14 | #include "core/file_sys/content_archive.h" |
| 15 | #include "core/file_sys/nca_metadata.h" | 15 | #include "core/file_sys/nca_metadata.h" |
| 16 | #include "core/file_sys/partition_filesystem.h" | 16 | #include "core/file_sys/partition_filesystem.h" |
| 17 | #include "core/file_sys/program_metadata.h" | ||
| 17 | #include "core/file_sys/submission_package.h" | 18 | #include "core/file_sys/submission_package.h" |
| 18 | #include "core/loader/loader.h" | 19 | #include "core/loader/loader.h" |
| 19 | 20 | ||
| @@ -78,6 +79,10 @@ Loader::ResultStatus NSP::GetStatus() const { | |||
| 78 | } | 79 | } |
| 79 | 80 | ||
| 80 | Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const { | 81 | Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const { |
| 82 | if (IsExtractedType() && GetExeFS() != nullptr && FileSys::IsDirectoryExeFS(GetExeFS())) { | ||
| 83 | return Loader::ResultStatus::Success; | ||
| 84 | } | ||
| 85 | |||
| 81 | const auto iter = program_status.find(title_id); | 86 | const auto iter = program_status.find(title_id); |
| 82 | if (iter == program_status.end()) | 87 | if (iter == program_status.end()) |
| 83 | return Loader::ResultStatus::ErrorNSPMissingProgramNCA; | 88 | return Loader::ResultStatus::ErrorNSPMissingProgramNCA; |
| @@ -85,12 +90,29 @@ Loader::ResultStatus NSP::GetProgramStatus(u64 title_id) const { | |||
| 85 | } | 90 | } |
| 86 | 91 | ||
| 87 | u64 NSP::GetFirstTitleID() const { | 92 | u64 NSP::GetFirstTitleID() const { |
| 93 | if (IsExtractedType()) { | ||
| 94 | return GetProgramTitleID(); | ||
| 95 | } | ||
| 96 | |||
| 88 | if (program_status.empty()) | 97 | if (program_status.empty()) |
| 89 | return 0; | 98 | return 0; |
| 90 | return program_status.begin()->first; | 99 | return program_status.begin()->first; |
| 91 | } | 100 | } |
| 92 | 101 | ||
| 93 | u64 NSP::GetProgramTitleID() const { | 102 | u64 NSP::GetProgramTitleID() const { |
| 103 | if (IsExtractedType()) { | ||
| 104 | if (GetExeFS() == nullptr || !IsDirectoryExeFS(GetExeFS())) { | ||
| 105 | return 0; | ||
| 106 | } | ||
| 107 | |||
| 108 | ProgramMetadata meta; | ||
| 109 | if (meta.Load(GetExeFS()->GetFile("main.npdm")) == Loader::ResultStatus::Success) { | ||
| 110 | return meta.GetTitleID(); | ||
| 111 | } else { | ||
| 112 | return 0; | ||
| 113 | } | ||
| 114 | } | ||
| 115 | |||
| 94 | const auto out = GetFirstTitleID(); | 116 | const auto out = GetFirstTitleID(); |
| 95 | if ((out & 0x800) == 0) | 117 | if ((out & 0x800) == 0) |
| 96 | return out; | 118 | return out; |
| @@ -102,6 +124,10 @@ u64 NSP::GetProgramTitleID() const { | |||
| 102 | } | 124 | } |
| 103 | 125 | ||
| 104 | std::vector<u64> NSP::GetTitleIDs() const { | 126 | std::vector<u64> NSP::GetTitleIDs() const { |
| 127 | if (IsExtractedType()) { | ||
| 128 | return {GetProgramTitleID()}; | ||
| 129 | } | ||
| 130 | |||
| 105 | std::vector<u64> out; | 131 | std::vector<u64> out; |
| 106 | out.reserve(ncas.size()); | 132 | out.reserve(ncas.size()); |
| 107 | for (const auto& kv : ncas) | 133 | for (const auto& kv : ncas) |
diff --git a/src/core/loader/nsp.cpp b/src/core/loader/nsp.cpp index b1171ce65..35c82c99d 100644 --- a/src/core/loader/nsp.cpp +++ b/src/core/loader/nsp.cpp | |||
| @@ -26,20 +26,18 @@ AppLoader_NSP::AppLoader_NSP(FileSys::VirtualFile file) | |||
| 26 | 26 | ||
| 27 | if (nsp->GetStatus() != ResultStatus::Success) | 27 | if (nsp->GetStatus() != ResultStatus::Success) |
| 28 | return; | 28 | return; |
| 29 | if (nsp->IsExtractedType()) | ||
| 30 | return; | ||
| 31 | |||
| 32 | const auto control_nca = | ||
| 33 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); | ||
| 34 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) | ||
| 35 | return; | ||
| 36 | |||
| 37 | std::tie(nacp_file, icon_file) = | ||
| 38 | FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca); | ||
| 39 | 29 | ||
| 40 | if (nsp->IsExtractedType()) { | 30 | if (nsp->IsExtractedType()) { |
| 41 | secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); | 31 | secondary_loader = std::make_unique<AppLoader_DeconstructedRomDirectory>(nsp->GetExeFS()); |
| 42 | } else { | 32 | } else { |
| 33 | const auto control_nca = | ||
| 34 | nsp->GetNCA(nsp->GetProgramTitleID(), FileSys::ContentRecordType::Control); | ||
| 35 | if (control_nca == nullptr || control_nca->GetStatus() != ResultStatus::Success) | ||
| 36 | return; | ||
| 37 | |||
| 38 | std::tie(nacp_file, icon_file) = | ||
| 39 | FileSys::PatchManager(nsp->GetProgramTitleID()).ParseControlNCA(*control_nca); | ||
| 40 | |||
| 43 | if (title_id == 0) | 41 | if (title_id == 0) |
| 44 | return; | 42 | return; |
| 45 | 43 | ||
| @@ -56,11 +54,11 @@ FileType AppLoader_NSP::IdentifyType(const FileSys::VirtualFile& file) { | |||
| 56 | if (nsp.GetStatus() == ResultStatus::Success) { | 54 | if (nsp.GetStatus() == ResultStatus::Success) { |
| 57 | // Extracted Type case | 55 | // Extracted Type case |
| 58 | if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr && | 56 | if (nsp.IsExtractedType() && nsp.GetExeFS() != nullptr && |
| 59 | FileSys::IsDirectoryExeFS(nsp.GetExeFS()) && nsp.GetRomFS() != nullptr) { | 57 | FileSys::IsDirectoryExeFS(nsp.GetExeFS())) { |
| 60 | return FileType::NSP; | 58 | return FileType::NSP; |
| 61 | } | 59 | } |
| 62 | 60 | ||
| 63 | // Non-Ectracted Type case | 61 | // Non-Extracted Type case |
| 64 | if (!nsp.IsExtractedType() && | 62 | if (!nsp.IsExtractedType() && |
| 65 | nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && | 63 | nsp.GetNCA(nsp.GetFirstTitleID(), FileSys::ContentRecordType::Program) != nullptr && |
| 66 | AppLoader_NCA::IdentifyType(nsp.GetNCAFile( | 64 | AppLoader_NCA::IdentifyType(nsp.GetNCAFile( |
| @@ -77,7 +75,7 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) { | |||
| 77 | return {ResultStatus::ErrorAlreadyLoaded, {}}; | 75 | return {ResultStatus::ErrorAlreadyLoaded, {}}; |
| 78 | } | 76 | } |
| 79 | 77 | ||
| 80 | if (title_id == 0) { | 78 | if (!nsp->IsExtractedType() && title_id == 0) { |
| 81 | return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; | 79 | return {ResultStatus::ErrorNSPMissingProgramNCA, {}}; |
| 82 | } | 80 | } |
| 83 | 81 | ||
| @@ -91,7 +89,8 @@ AppLoader_NSP::LoadResult AppLoader_NSP::Load(Kernel::Process& process) { | |||
| 91 | return {nsp_program_status, {}}; | 89 | return {nsp_program_status, {}}; |
| 92 | } | 90 | } |
| 93 | 91 | ||
| 94 | if (nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { | 92 | if (!nsp->IsExtractedType() && |
| 93 | nsp->GetNCA(title_id, FileSys::ContentRecordType::Program) == nullptr) { | ||
| 95 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) { | 94 | if (!Core::Crypto::KeyManager::KeyFileExists(false)) { |
| 96 | return {ResultStatus::ErrorMissingProductionKeyFile, {}}; | 95 | return {ResultStatus::ErrorMissingProductionKeyFile, {}}; |
| 97 | } | 96 | } |
diff --git a/src/core/memory.cpp b/src/core/memory.cpp index 8555691c0..9e030789d 100644 --- a/src/core/memory.cpp +++ b/src/core/memory.cpp | |||
| @@ -43,8 +43,13 @@ static void MapPages(Common::PageTable& page_table, VAddr base, u64 size, u8* me | |||
| 43 | 43 | ||
| 44 | // During boot, current_page_table might not be set yet, in which case we need not flush | 44 | // During boot, current_page_table might not be set yet, in which case we need not flush |
| 45 | if (Core::System::GetInstance().IsPoweredOn()) { | 45 | if (Core::System::GetInstance().IsPoweredOn()) { |
| 46 | Core::System::GetInstance().GPU().FlushAndInvalidateRegion(base << PAGE_BITS, | 46 | auto& gpu = Core::System::GetInstance().GPU(); |
| 47 | size * PAGE_SIZE); | 47 | for (u64 i = 0; i < size; i++) { |
| 48 | const auto page = base + i; | ||
| 49 | if (page_table.attributes[page] == Common::PageType::RasterizerCachedMemory) { | ||
| 50 | gpu.FlushAndInvalidateRegion(page << PAGE_BITS, PAGE_SIZE); | ||
| 51 | } | ||
| 52 | } | ||
| 48 | } | 53 | } |
| 49 | 54 | ||
| 50 | VAddr end = base + size; | 55 | VAddr end = base + size; |
diff --git a/src/core/perf_stats.cpp b/src/core/perf_stats.cpp index 4afd6c8a3..d2c69d1a0 100644 --- a/src/core/perf_stats.cpp +++ b/src/core/perf_stats.cpp | |||
| @@ -4,8 +4,14 @@ | |||
| 4 | 4 | ||
| 5 | #include <algorithm> | 5 | #include <algorithm> |
| 6 | #include <chrono> | 6 | #include <chrono> |
| 7 | #include <iterator> | ||
| 7 | #include <mutex> | 8 | #include <mutex> |
| 9 | #include <numeric> | ||
| 10 | #include <sstream> | ||
| 8 | #include <thread> | 11 | #include <thread> |
| 12 | #include <fmt/chrono.h> | ||
| 13 | #include <fmt/format.h> | ||
| 14 | #include "common/file_util.h" | ||
| 9 | #include "common/math_util.h" | 15 | #include "common/math_util.h" |
| 10 | #include "core/perf_stats.h" | 16 | #include "core/perf_stats.h" |
| 11 | #include "core/settings.h" | 17 | #include "core/settings.h" |
| @@ -15,8 +21,31 @@ using DoubleSecs = std::chrono::duration<double, std::chrono::seconds::period>; | |||
| 15 | using std::chrono::duration_cast; | 21 | using std::chrono::duration_cast; |
| 16 | using std::chrono::microseconds; | 22 | using std::chrono::microseconds; |
| 17 | 23 | ||
| 24 | // Purposefully ignore the first five frames, as there's a significant amount of overhead in | ||
| 25 | // booting that we shouldn't account for | ||
| 26 | constexpr std::size_t IgnoreFrames = 5; | ||
| 27 | |||
| 18 | namespace Core { | 28 | namespace Core { |
| 19 | 29 | ||
| 30 | PerfStats::PerfStats(u64 title_id) : title_id(title_id) {} | ||
| 31 | |||
| 32 | PerfStats::~PerfStats() { | ||
| 33 | if (!Settings::values.record_frame_times || title_id == 0) { | ||
| 34 | return; | ||
| 35 | } | ||
| 36 | |||
| 37 | const std::time_t t = std::time(nullptr); | ||
| 38 | std::ostringstream stream; | ||
| 39 | std::copy(perf_history.begin() + IgnoreFrames, perf_history.begin() + current_index, | ||
| 40 | std::ostream_iterator<double>(stream, "\n")); | ||
| 41 | const std::string& path = FileUtil::GetUserPath(FileUtil::UserPath::LogDir); | ||
| 42 | // %F Date format expanded is "%Y-%m-%d" | ||
| 43 | const std::string filename = | ||
| 44 | fmt::format("{}/{:%F-%H-%M}_{:016X}.csv", path, *std::localtime(&t), title_id); | ||
| 45 | FileUtil::IOFile file(filename, "w"); | ||
| 46 | file.WriteString(stream.str()); | ||
| 47 | } | ||
| 48 | |||
| 20 | void PerfStats::BeginSystemFrame() { | 49 | void PerfStats::BeginSystemFrame() { |
| 21 | std::lock_guard lock{object_mutex}; | 50 | std::lock_guard lock{object_mutex}; |
| 22 | 51 | ||
| @@ -27,7 +56,12 @@ void PerfStats::EndSystemFrame() { | |||
| 27 | std::lock_guard lock{object_mutex}; | 56 | std::lock_guard lock{object_mutex}; |
| 28 | 57 | ||
| 29 | auto frame_end = Clock::now(); | 58 | auto frame_end = Clock::now(); |
| 30 | accumulated_frametime += frame_end - frame_begin; | 59 | const auto frame_time = frame_end - frame_begin; |
| 60 | if (current_index < perf_history.size()) { | ||
| 61 | perf_history[current_index++] = | ||
| 62 | std::chrono::duration<double, std::milli>(frame_time).count(); | ||
| 63 | } | ||
| 64 | accumulated_frametime += frame_time; | ||
| 31 | system_frames += 1; | 65 | system_frames += 1; |
| 32 | 66 | ||
| 33 | previous_frame_length = frame_end - previous_frame_end; | 67 | previous_frame_length = frame_end - previous_frame_end; |
| @@ -40,6 +74,17 @@ void PerfStats::EndGameFrame() { | |||
| 40 | game_frames += 1; | 74 | game_frames += 1; |
| 41 | } | 75 | } |
| 42 | 76 | ||
| 77 | double PerfStats::GetMeanFrametime() { | ||
| 78 | std::lock_guard lock{object_mutex}; | ||
| 79 | |||
| 80 | if (current_index <= IgnoreFrames) { | ||
| 81 | return 0; | ||
| 82 | } | ||
| 83 | const double sum = std::accumulate(perf_history.begin() + IgnoreFrames, | ||
| 84 | perf_history.begin() + current_index, 0); | ||
| 85 | return sum / (current_index - IgnoreFrames); | ||
| 86 | } | ||
| 87 | |||
| 43 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { | 88 | PerfStatsResults PerfStats::GetAndResetStats(microseconds current_system_time_us) { |
| 44 | std::lock_guard lock{object_mutex}; | 89 | std::lock_guard lock{object_mutex}; |
| 45 | 90 | ||
diff --git a/src/core/perf_stats.h b/src/core/perf_stats.h index 222ac1a63..d9a64f072 100644 --- a/src/core/perf_stats.h +++ b/src/core/perf_stats.h | |||
| @@ -4,7 +4,9 @@ | |||
| 4 | 4 | ||
| 5 | #pragma once | 5 | #pragma once |
| 6 | 6 | ||
| 7 | #include <array> | ||
| 7 | #include <chrono> | 8 | #include <chrono> |
| 9 | #include <cstddef> | ||
| 8 | #include <mutex> | 10 | #include <mutex> |
| 9 | #include "common/common_types.h" | 11 | #include "common/common_types.h" |
| 10 | 12 | ||
| @@ -27,6 +29,10 @@ struct PerfStatsResults { | |||
| 27 | */ | 29 | */ |
| 28 | class PerfStats { | 30 | class PerfStats { |
| 29 | public: | 31 | public: |
| 32 | explicit PerfStats(u64 title_id); | ||
| 33 | |||
| 34 | ~PerfStats(); | ||
| 35 | |||
| 30 | using Clock = std::chrono::high_resolution_clock; | 36 | using Clock = std::chrono::high_resolution_clock; |
| 31 | 37 | ||
| 32 | void BeginSystemFrame(); | 38 | void BeginSystemFrame(); |
| @@ -36,13 +42,26 @@ public: | |||
| 36 | PerfStatsResults GetAndResetStats(std::chrono::microseconds current_system_time_us); | 42 | PerfStatsResults GetAndResetStats(std::chrono::microseconds current_system_time_us); |
| 37 | 43 | ||
| 38 | /** | 44 | /** |
| 45 | * Returns the Arthimetic Mean of all frametime values stored in the performance history. | ||
| 46 | */ | ||
| 47 | double GetMeanFrametime(); | ||
| 48 | |||
| 49 | /** | ||
| 39 | * Gets the ratio between walltime and the emulated time of the previous system frame. This is | 50 | * Gets the ratio between walltime and the emulated time of the previous system frame. This is |
| 40 | * useful for scaling inputs or outputs moving between the two time domains. | 51 | * useful for scaling inputs or outputs moving between the two time domains. |
| 41 | */ | 52 | */ |
| 42 | double GetLastFrameTimeScale(); | 53 | double GetLastFrameTimeScale(); |
| 43 | 54 | ||
| 44 | private: | 55 | private: |
| 45 | std::mutex object_mutex; | 56 | std::mutex object_mutex{}; |
| 57 | |||
| 58 | /// Title ID for the game that is running. 0 if there is no game running yet | ||
| 59 | u64 title_id{0}; | ||
| 60 | /// Current index for writing to the perf_history array | ||
| 61 | std::size_t current_index{0}; | ||
| 62 | /// Stores an hour of historical frametime data useful for processing and tracking performance | ||
| 63 | /// regressions with code changes. | ||
| 64 | std::array<double, 216000> perf_history = {}; | ||
| 46 | 65 | ||
| 47 | /// Point when the cumulative counters were reset | 66 | /// Point when the cumulative counters were reset |
| 48 | Clock::time_point reset_point = Clock::now(); | 67 | Clock::time_point reset_point = Clock::now(); |
diff --git a/src/core/settings.h b/src/core/settings.h index 6638ce8f9..d4b70ec4c 100644 --- a/src/core/settings.h +++ b/src/core/settings.h | |||
| @@ -409,6 +409,7 @@ struct Values { | |||
| 409 | float volume; | 409 | float volume; |
| 410 | 410 | ||
| 411 | // Debugging | 411 | // Debugging |
| 412 | bool record_frame_times; | ||
| 412 | bool use_gdbstub; | 413 | bool use_gdbstub; |
| 413 | u16 gdbstub_port; | 414 | u16 gdbstub_port; |
| 414 | std::string program_args; | 415 | std::string program_args; |
diff --git a/src/video_core/renderer_opengl/maxwell_to_gl.h b/src/video_core/renderer_opengl/maxwell_to_gl.h index ea77dd211..9ed738171 100644 --- a/src/video_core/renderer_opengl/maxwell_to_gl.h +++ b/src/video_core/renderer_opengl/maxwell_to_gl.h | |||
| @@ -145,7 +145,7 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode, | |||
| 145 | case Tegra::Texture::TextureMipmapFilter::None: | 145 | case Tegra::Texture::TextureMipmapFilter::None: |
| 146 | return GL_LINEAR; | 146 | return GL_LINEAR; |
| 147 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 147 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 148 | return GL_NEAREST_MIPMAP_LINEAR; | 148 | return GL_LINEAR_MIPMAP_NEAREST; |
| 149 | case Tegra::Texture::TextureMipmapFilter::Linear: | 149 | case Tegra::Texture::TextureMipmapFilter::Linear: |
| 150 | return GL_LINEAR_MIPMAP_LINEAR; | 150 | return GL_LINEAR_MIPMAP_LINEAR; |
| 151 | } | 151 | } |
| @@ -157,7 +157,7 @@ inline GLenum TextureFilterMode(Tegra::Texture::TextureFilter filter_mode, | |||
| 157 | case Tegra::Texture::TextureMipmapFilter::Nearest: | 157 | case Tegra::Texture::TextureMipmapFilter::Nearest: |
| 158 | return GL_NEAREST_MIPMAP_NEAREST; | 158 | return GL_NEAREST_MIPMAP_NEAREST; |
| 159 | case Tegra::Texture::TextureMipmapFilter::Linear: | 159 | case Tegra::Texture::TextureMipmapFilter::Linear: |
| 160 | return GL_LINEAR_MIPMAP_NEAREST; | 160 | return GL_NEAREST_MIPMAP_LINEAR; |
| 161 | } | 161 | } |
| 162 | } | 162 | } |
| 163 | } | 163 | } |
diff --git a/src/yuzu/configuration/config.cpp b/src/yuzu/configuration/config.cpp index f594106bf..3f54f54fb 100644 --- a/src/yuzu/configuration/config.cpp +++ b/src/yuzu/configuration/config.cpp | |||
| @@ -466,6 +466,9 @@ void Config::ReadDataStorageValues() { | |||
| 466 | void Config::ReadDebuggingValues() { | 466 | void Config::ReadDebuggingValues() { |
| 467 | qt_config->beginGroup(QStringLiteral("Debugging")); | 467 | qt_config->beginGroup(QStringLiteral("Debugging")); |
| 468 | 468 | ||
| 469 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 470 | Settings::values.record_frame_times = | ||
| 471 | qt_config->value(QStringLiteral("record_frame_times"), false).toBool(); | ||
| 469 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); | 472 | Settings::values.use_gdbstub = ReadSetting(QStringLiteral("use_gdbstub"), false).toBool(); |
| 470 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); | 473 | Settings::values.gdbstub_port = ReadSetting(QStringLiteral("gdbstub_port"), 24689).toInt(); |
| 471 | Settings::values.program_args = | 474 | Settings::values.program_args = |
| @@ -879,6 +882,8 @@ void Config::SaveDataStorageValues() { | |||
| 879 | void Config::SaveDebuggingValues() { | 882 | void Config::SaveDebuggingValues() { |
| 880 | qt_config->beginGroup(QStringLiteral("Debugging")); | 883 | qt_config->beginGroup(QStringLiteral("Debugging")); |
| 881 | 884 | ||
| 885 | // Intentionally not using the QT default setting as this is intended to be changed in the ini | ||
| 886 | qt_config->setValue(QStringLiteral("record_frame_times"), Settings::values.record_frame_times); | ||
| 882 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); | 887 | WriteSetting(QStringLiteral("use_gdbstub"), Settings::values.use_gdbstub, false); |
| 883 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); | 888 | WriteSetting(QStringLiteral("gdbstub_port"), Settings::values.gdbstub_port, 24689); |
| 884 | WriteSetting(QStringLiteral("program_args"), | 889 | WriteSetting(QStringLiteral("program_args"), |
diff --git a/src/yuzu/configuration/configure_input.cpp b/src/yuzu/configuration/configure_input.cpp index 7613197f2..f2977719c 100644 --- a/src/yuzu/configuration/configure_input.cpp +++ b/src/yuzu/configuration/configure_input.cpp | |||
| @@ -182,6 +182,8 @@ void ConfigureInput::UpdateUIEnabled() { | |||
| 182 | players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0); | 182 | players_configure[i]->setEnabled(players_controller[i]->currentIndex() != 0); |
| 183 | } | 183 | } |
| 184 | 184 | ||
| 185 | ui->handheld_connected->setChecked(ui->handheld_connected->isChecked() && | ||
| 186 | !ui->use_docked_mode->isChecked()); | ||
| 185 | ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); | 187 | ui->handheld_connected->setEnabled(!ui->use_docked_mode->isChecked()); |
| 186 | ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() && | 188 | ui->handheld_configure->setEnabled(ui->handheld_connected->isChecked() && |
| 187 | !ui->use_docked_mode->isChecked()); | 189 | !ui->use_docked_mode->isChecked()); |
diff --git a/src/yuzu_cmd/config.cpp b/src/yuzu_cmd/config.cpp index 067d58d80..5cadfd191 100644 --- a/src/yuzu_cmd/config.cpp +++ b/src/yuzu_cmd/config.cpp | |||
| @@ -374,6 +374,8 @@ void Config::ReadValues() { | |||
| 374 | Settings::values.use_dev_keys = sdl2_config->GetBoolean("Miscellaneous", "use_dev_keys", false); | 374 | Settings::values.use_dev_keys = sdl2_config->GetBoolean("Miscellaneous", "use_dev_keys", false); |
| 375 | 375 | ||
| 376 | // Debugging | 376 | // Debugging |
| 377 | Settings::values.record_frame_times = | ||
| 378 | sdl2_config->GetBoolean("Debugging", "record_frame_times", false); | ||
| 377 | Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); | 379 | Settings::values.use_gdbstub = sdl2_config->GetBoolean("Debugging", "use_gdbstub", false); |
| 378 | Settings::values.gdbstub_port = | 380 | Settings::values.gdbstub_port = |
| 379 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); | 381 | static_cast<u16>(sdl2_config->GetInteger("Debugging", "gdbstub_port", 24689)); |
diff --git a/src/yuzu_cmd/default_ini.h b/src/yuzu_cmd/default_ini.h index 0cfc111a6..f9f244522 100644 --- a/src/yuzu_cmd/default_ini.h +++ b/src/yuzu_cmd/default_ini.h | |||
| @@ -213,6 +213,8 @@ region_value = | |||
| 213 | log_filter = *:Trace | 213 | log_filter = *:Trace |
| 214 | 214 | ||
| 215 | [Debugging] | 215 | [Debugging] |
| 216 | # Record frame time data, can be found in the log directory. Boolean value | ||
| 217 | record_frame_times = | ||
| 216 | # Port for listening to GDB connections. | 218 | # Port for listening to GDB connections. |
| 217 | use_gdbstub=false | 219 | use_gdbstub=false |
| 218 | gdbstub_port=24689 | 220 | gdbstub_port=24689 |