diff --git a/CMakeLists.txt b/CMakeLists.txt index a7b642a3ec..3f7b1ff615 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -645,6 +645,7 @@ add_library(Common STATIC Common/Data/Collections/Hashmaps.h Common/Data/Collections/TinySet.h Common/Data/Collections/FastVec.h + Common/Data/Collections/CyclicBuffer.h Common/Data/Collections/ThreadSafeList.h Common/Data/Color/RGBAUtil.cpp Common/Data/Color/RGBAUtil.h diff --git a/Common/Common.vcxproj b/Common/Common.vcxproj index 0b65c4e83c..68bd679caf 100644 --- a/Common/Common.vcxproj +++ b/Common/Common.vcxproj @@ -882,6 +882,7 @@ + diff --git a/Common/Common.vcxproj.filters b/Common/Common.vcxproj.filters index 6541f4776e..10010e8c16 100644 --- a/Common/Common.vcxproj.filters +++ b/Common/Common.vcxproj.filters @@ -994,6 +994,9 @@ Data\Collections + + Data\Collections + GPU diff --git a/Common/Data/Collections/CyclicBuffer.h b/Common/Data/Collections/CyclicBuffer.h new file mode 100644 index 0000000000..7eaa042198 --- /dev/null +++ b/Common/Data/Collections/CyclicBuffer.h @@ -0,0 +1,87 @@ +// Copyright (c) 2024- PPSSPP Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0 or later versions. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official git repository and contact information can be found at +// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. + +#pragma once + +#include + +#include "Common/CommonTypes.h" + + +template +struct CyclicBuffer { + std::vector buffer; + u32 current_index; + bool overflow; + + explicit CyclicBuffer(u32 capacity) : buffer(capacity, T()), current_index(0), overflow(false) {} + + CyclicBuffer(): buffer(), current_index(0), overflow(false) {} + + void push_back(const T& value); + void push_back(T&& value); + + void clear(); + void resize(u32 new_capacity); + + std::vector get_content() const; +}; + +template +std::vector CyclicBuffer::get_content() const { + if (!overflow) { + return std::vector(buffer.begin(), buffer.begin() + current_index); + } + + std::vector ans; + ans.reserve(buffer.size()); + std::copy(buffer.begin() + current_index, buffer.end(), std::back_inserter(ans)); + std::copy(buffer.begin(), buffer.begin() + current_index, std::back_inserter(ans)); + return ans; +} + +template +void CyclicBuffer::push_back(const T& value) { + buffer[current_index] = value; + ++current_index; + if (current_index == buffer.size()) { + current_index = 0; + overflow = true; + } +} + +template +void CyclicBuffer::push_back(T&& value) { + buffer[current_index] = std::move(value); + ++current_index; + if (current_index == buffer.size()) { + current_index = 0; + overflow = true; + } +} + +template +void CyclicBuffer::clear() { + buffer.clear(); + current_index = 0; + overflow = false; +} + +template +void CyclicBuffer::resize(u32 new_capacity) { + buffer.resize(new_capacity); +} diff --git a/Core/MIPS/MIPSTracer.cpp b/Core/MIPS/MIPSTracer.cpp index 20289a5d92..628f58adeb 100644 --- a/Core/MIPS/MIPSTracer.cpp +++ b/Core/MIPS/MIPSTracer.cpp @@ -100,6 +100,11 @@ void MIPSTracer::prepare_block(const MIPSComp::IRBlock* block, MIPSComp::IRBlock } bool MIPSTracer::flush_to_file() { + if (logging_path.empty()) { + WARN_LOG(Log::JIT, "The path is empty, cannot flush the trace!"); + return false; + } + INFO_LOG(Log::JIT, "Flushing the trace to a file..."); output = File::OpenCFile(logging_path, "w"); diff --git a/Core/MIPS/MIPSTracer.h b/Core/MIPS/MIPSTracer.h index 8ba1bef6e8..d9c873323d 100644 --- a/Core/MIPS/MIPSTracer.h +++ b/Core/MIPS/MIPSTracer.h @@ -26,6 +26,7 @@ #include "Core/MIPS/IR/IRJit.h" #include "Common/Log.h" #include "Common/File/Path.h" +#include "Common/Data/Collections/CyclicBuffer.h" struct TraceBlockInfo { @@ -60,70 +61,6 @@ struct TraceBlockStorage { }; -template -struct CyclicBuffer { - std::vector buffer; - u32 current_index; - bool overflow; - - explicit CyclicBuffer(u32 capacity) : buffer(capacity, T()), current_index(0), overflow(false) {} - - CyclicBuffer(): buffer(), current_index(0), overflow(false) {} - - void push_back(const T& value); - void push_back(T&& value); - - void clear(); - void resize(u32 new_capacity); - - std::vector get_content() const; -}; - -template -std::vector CyclicBuffer::get_content() const { - if (!overflow) { - return std::vector(buffer.begin(), buffer.begin() + current_index); - } - - std::vector ans; - ans.reserve(buffer.size()); - std::copy(buffer.begin() + current_index, buffer.end(), std::back_inserter(ans)); - std::copy(buffer.begin(), buffer.begin() + current_index, std::back_inserter(ans)); - return ans; -} - -template -void CyclicBuffer::push_back(const T& value) { - buffer[current_index] = value; - ++current_index; - if (current_index == buffer.size()) { - current_index = 0; - overflow = true; - } -} - -template -void CyclicBuffer::push_back(T&& value) { - buffer[current_index] = std::move(value); - ++current_index; - if (current_index == buffer.size()) { - current_index = 0; - overflow = true; - } -} - -template -void CyclicBuffer::clear() { - buffer.clear(); - current_index = 0; - overflow = false; -} - -template -void CyclicBuffer::resize(u32 new_capacity) { - buffer.resize(new_capacity); -} - // This system is meant for trace recording. // A trace here stands for a sequence of instructions and their respective addresses in RAM. diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 2545438e71..0199a7d2d7 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -1894,16 +1894,16 @@ void DeveloperToolsScreen::CreateViews() { list->Add(new ItemHeader(dev->T("MIPSTracer"))); MIPSTracerEnabled_ = mipsTracer.tracing_enabled; - CheckBox *MIPSLoggerEnabled = new CheckBox(&MIPSTracerEnabled_, dev->T("MIPSTracer enabled")); - list->Add(MIPSLoggerEnabled)->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerEnabled); - MIPSLoggerEnabled->SetEnabledFunc([]() { + CheckBox *MIPSTracerEnabled = new CheckBox(&MIPSTracerEnabled_, dev->T("MIPSTracer enabled")); + list->Add(MIPSTracerEnabled)->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerEnabled); + MIPSTracerEnabled->SetEnabledFunc([]() { bool temp = g_Config.iCpuCore == static_cast(CPUCore::IR_INTERPRETER) && PSP_IsInited(); return temp && Core_IsStepping() && coreState != CORE_POWERDOWN; }); - Choice *MIPSlogging_path = list->Add(new Choice(dev->T("Select the output logging file"))); - MIPSlogging_path->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerPathChanged); - MIPSlogging_path->SetEnabledFunc([]() { + Choice *TraceDumpPath = list->Add(new Choice(dev->T("Select the file path for the trace"))); + TraceDumpPath->OnClick.Handle(this, &DeveloperToolsScreen::OnMIPSTracerPathChanged); + TraceDumpPath->SetEnabledFunc([]() { if (!PSP_IsInited()) return false; return true; @@ -2159,10 +2159,9 @@ UI::EventReturn DeveloperToolsScreen::OnMIPSTracerPathChanged(UI::EventParams &e } UI::EventReturn DeveloperToolsScreen::OnMIPSTracerFlushTrace(UI::EventParams &e) { - bool success = mipsTracer.flush_to_file(); - if (!success) { - WARN_LOG(Log::JIT, "Error: cannot flush the trace to the specified file!"); - } + mipsTracer.flush_to_file(); + // The error logs are emitted inside the tracer + return UI::EVENT_DONE; } diff --git a/UWP/CommonUWP/CommonUWP.vcxproj b/UWP/CommonUWP/CommonUWP.vcxproj index 195b61c8b4..17feea19a7 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj +++ b/UWP/CommonUWP/CommonUWP.vcxproj @@ -115,6 +115,7 @@ + diff --git a/UWP/CommonUWP/CommonUWP.vcxproj.filters b/UWP/CommonUWP/CommonUWP.vcxproj.filters index f38724008a..eaf244e0cb 100644 --- a/UWP/CommonUWP/CommonUWP.vcxproj.filters +++ b/UWP/CommonUWP/CommonUWP.vcxproj.filters @@ -597,6 +597,9 @@ Data\Collections + + Data\Collections + Data\Random