MTGS: Convert to namespace

This commit is contained in:
Stenzek 2023-06-24 17:46:36 +10:00 committed by Connor McLaughlin
parent 6f9164b986
commit 55e73bb4b9
31 changed files with 605 additions and 642 deletions

View File

@ -100,6 +100,7 @@ target_sources(common PRIVATE
TraceLog.h
WAVWriter.h
WindowInfo.h
WrappedMemCopy.h
emitter/implement/dwshift.h
emitter/implement/group1.h
emitter/implement/group2.h

50
common/WrappedMemCopy.h Normal file
View File

@ -0,0 +1,50 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "common/Pcsx2Defs.h"
__ri static void MemCopy_WrappedDest(const u128* src, u128* destBase, uint& destStart, uint destSize, uint len)
{
uint endpos = destStart + len;
if (endpos < destSize)
{
memcpy(&destBase[destStart], src, len * 16);
destStart += len;
}
else
{
uint firstcopylen = destSize - destStart;
memcpy(&destBase[destStart], src, firstcopylen * 16);
destStart = endpos % destSize;
memcpy(destBase, src + firstcopylen, destStart * 16);
}
}
__ri static void MemCopy_WrappedSrc(const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len)
{
uint endpos = srcStart + len;
if (endpos < srcSize)
{
memcpy(dest, &srcBase[srcStart], len * 16);
srcStart += len;
}
else
{
uint firstcopylen = srcSize - srcStart;
memcpy(dest, &srcBase[srcStart], firstcopylen * 16);
srcStart = endpos % srcSize;
memcpy(dest + firstcopylen, srcBase, srcStart * 16);
}
}

View File

@ -169,6 +169,7 @@
<ClInclude Include="emitter\implement\simd_helpers.h" />
<ClInclude Include="emitter\implement\simd_moremovs.h" />
<ClInclude Include="emitter\implement\simd_shufflepack.h" />
<ClInclude Include="WrappedMemCopy.h" />
<ClInclude Include="ZipHelpers.h" />
</ItemGroup>
<ItemGroup>

View File

@ -348,6 +348,9 @@
<ClInclude Include="ByteSwap.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="WrappedMemCopy.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<Filter Include="Source Files">

View File

@ -40,13 +40,13 @@
#include "pcsx2/Achievements.h"
#include "pcsx2/CDVD/CDVD.h"
#include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/GSDumpReplayer.h"
#include "pcsx2/Host.h"
#include "pcsx2/INISettingsInterface.h"
#include "pcsx2/ImGui/ImGuiManager.h"
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/VMManager.h"
@ -69,7 +69,6 @@ static constexpr u32 WINDOW_WIDTH = 640;
static constexpr u32 WINDOW_HEIGHT = 480;
static MemorySettingsInterface s_settings_interface;
alignas(16) static SysMtgsThread s_mtgs_thread;
static std::string s_output_prefix;
static s32 s_loop_count = 1;
@ -362,15 +361,6 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
return std::nullopt;
}
SysMtgsThread& GetMTGS()
{
return s_mtgs_thread;
}
//////////////////////////////////////////////////////////////////////////
// Interface Stuff
//////////////////////////////////////////////////////////////////////////
BEGIN_HOTKEY_LIST(g_host_hotkeys)
END_HOTKEY_LIST()
@ -651,8 +641,8 @@ int main(int argc, char* argv[])
void Host::VSyncOnCPUThread()
{
// update GS thread copy of frame number
GetMTGS().RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });
GetMTGS().RunOnGSThread([loop_number = GSDumpReplayer::GetLoopCount()]() { s_loop_number = loop_number; });
MTGS::RunOnGSThread([frame_number = GSDumpReplayer::GetFrameNumber()]() { s_dump_frame_number = frame_number; });
MTGS::RunOnGSThread([loop_number = GSDumpReplayer::GetLoopCount()]() { s_loop_number = loop_number; });
// process any window messages (but we shouldn't really have any)
GSRunner::PumpPlatformMessages();

View File

@ -41,6 +41,7 @@
#include "pcsx2/GameList.h"
#include "pcsx2/Host.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/Recording/InputRecording.h"
#include "pcsx2/Recording/InputRecordingControls.h"
@ -709,7 +710,7 @@ void MainWindow::updateEmulationActions(bool starting, bool running, bool stoppi
void MainWindow::updateDisplayRelatedActions(bool has_surface, bool render_to_main, bool fullscreen)
{
// rendering to main, or switched to gamelist/grid
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && GetMTGS().IsOpen()));
m_ui.actionViewSystemDisplay->setEnabled((has_surface && render_to_main) || (!has_surface && MTGS::IsOpen()));
m_ui.menuWindowSize->setEnabled(has_surface && !fullscreen);
m_ui.actionFullscreen->setEnabled(has_surface);
@ -821,7 +822,7 @@ bool MainWindow::isShowingGameList() const
bool MainWindow::isRenderingFullscreen() const
{
if (!GetMTGS().IsOpen() || !m_display_widget)
if (!MTGS::IsOpen() || !m_display_widget)
return false;
return getDisplayContainer()->isFullScreen();

View File

@ -39,6 +39,7 @@
#include "pcsx2/ImGui/ImGuiManager.h"
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/LogSink.h"
#include "pcsx2/MTGS.h"
#include "pcsx2/PAD/Host/PAD.h"
#include "pcsx2/PerformanceMetrics.h"
#include "pcsx2/VMManager.h"
@ -190,7 +191,7 @@ void EmuThread::startFullscreenUI(bool fullscreen)
return;
}
if (VMManager::HasValidVM() || GetMTGS().IsOpen())
if (VMManager::HasValidVM() || MTGS::IsOpen())
return;
// this should just set the flag so it gets automatically started
@ -199,7 +200,7 @@ void EmuThread::startFullscreenUI(bool fullscreen)
m_is_rendering_to_main = shouldRenderToMain();
m_is_fullscreen = fullscreen;
if (!GetMTGS().WaitForOpen())
if (!MTGS::WaitForOpen())
{
m_run_fullscreen_ui = false;
return;
@ -217,18 +218,18 @@ void EmuThread::stopFullscreenUI()
QMetaObject::invokeMethod(this, &EmuThread::stopFullscreenUI, Qt::QueuedConnection);
// wait until the host display is gone
while (GetMTGS().IsOpen())
while (MTGS::IsOpen())
QApplication::processEvents(QEventLoop::ExcludeUserInputEvents, 1);
return;
}
if (!GetMTGS().IsOpen())
if (!MTGS::IsOpen())
return;
pxAssertRel(!VMManager::HasValidVM(), "VM is not valid at FSUI shutdown time");
m_run_fullscreen_ui = false;
GetMTGS().WaitForClose();
MTGS::WaitForClose();
}
void EmuThread::startVM(std::shared_ptr<VMBootParameters> boot_params)
@ -509,14 +510,14 @@ void EmuThread::setFullscreen(bool fullscreen, bool allow_render_to_main)
return;
}
if (!GetMTGS().IsOpen() || m_is_fullscreen == fullscreen)
if (!MTGS::IsOpen() || m_is_fullscreen == fullscreen)
return;
// This will call back to us on the MTGS thread.
m_is_fullscreen = fullscreen;
m_is_rendering_to_main = allow_render_to_main && shouldRenderToMain();
GetMTGS().UpdateDisplayWindow();
GetMTGS().WaitGS();
MTGS::UpdateDisplayWindow();
MTGS::WaitGS();
// If we're using exclusive fullscreen, the refresh rate may have changed.
UpdateVSyncRate(true);
@ -530,17 +531,17 @@ void EmuThread::setSurfaceless(bool surfaceless)
return;
}
if (!GetMTGS().IsOpen() || m_is_surfaceless == surfaceless)
if (!MTGS::IsOpen() || m_is_surfaceless == surfaceless)
return;
// If we went surfaceless and were running the fullscreen UI, stop MTGS running idle.
// Otherwise, we'll keep trying to present to nothing.
GetMTGS().SetRunIdle(!surfaceless && m_run_fullscreen_ui);
MTGS::SetRunIdle(!surfaceless && m_run_fullscreen_ui);
// This will call back to us on the MTGS thread.
m_is_surfaceless = surfaceless;
GetMTGS().UpdateDisplayWindow();
GetMTGS().WaitGS();
MTGS::UpdateDisplayWindow();
MTGS::WaitGS();
}
void EmuThread::applySettings()
@ -601,14 +602,14 @@ void EmuThread::checkForSettingChanges(const Pcsx2Config& old_config)
updatePerformanceMetrics(true);
}
if (GetMTGS().IsOpen())
if (MTGS::IsOpen())
{
const bool render_to_main = shouldRenderToMain();
if (!m_is_fullscreen && m_is_rendering_to_main != render_to_main)
{
m_is_rendering_to_main = render_to_main;
GetMTGS().UpdateDisplayWindow();
GetMTGS().WaitGS();
MTGS::UpdateDisplayWindow();
MTGS::WaitGS();
}
}
}
@ -634,7 +635,7 @@ void EmuThread::toggleSoftwareRendering()
if (!VMManager::HasValidVM())
return;
GetMTGS().ToggleSoftwareRendering();
MTGS::ToggleSoftwareRendering();
}
void EmuThread::switchRenderer(GSRendererType renderer)
@ -648,7 +649,7 @@ void EmuThread::switchRenderer(GSRendererType renderer)
if (!VMManager::HasValidVM())
return;
GetMTGS().SwitchRenderer(renderer);
MTGS::SwitchRenderer(renderer);
}
void EmuThread::changeDisc(CDVD_SourceType source, const QString& path)
@ -792,10 +793,10 @@ void EmuThread::connectDisplaySignals(DisplayWidget* widget)
void EmuThread::onDisplayWindowResized(int width, int height, float scale)
{
if (!GetMTGS().IsOpen())
if (!MTGS::IsOpen())
return;
GetMTGS().ResizeDisplayWindow(width, height, scale);
MTGS::ResizeDisplayWindow(width, height, scale);
}
void EmuThread::onApplicationStateChanged(Qt::ApplicationState state)
@ -841,7 +842,7 @@ void EmuThread::redrawDisplayWindow()
if (!VMManager::HasValidVM() || VMManager::GetState() == VMState::Running)
return;
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
void EmuThread::runOnCPUThread(const std::function<void()>& func)
@ -860,7 +861,7 @@ void EmuThread::queueSnapshot(quint32 gsdump_frames)
if (!VMManager::HasValidVM())
return;
GetMTGS().RunOnGSThread([gsdump_frames]() { GSQueueSnapshot(std::string(), gsdump_frames); });
MTGS::RunOnGSThread([gsdump_frames]() { GSQueueSnapshot(std::string(), gsdump_frames); });
}
void EmuThread::beginCapture(const QString& path)
@ -874,13 +875,13 @@ void EmuThread::beginCapture(const QString& path)
if (!VMManager::HasValidVM())
return;
GetMTGS().RunOnGSThread([path = path.toStdString()]() {
MTGS::RunOnGSThread([path = path.toStdString()]() {
GSBeginCapture(std::move(path));
});
// Sync GS thread. We want to start adding audio at the same time as video.
// TODO: This could be up to 64 frames behind... use the pts to adjust it.
GetMTGS().WaitGS(false, false, false);
MTGS::WaitGS(false, false, false);
}
void EmuThread::endCapture()
@ -894,7 +895,7 @@ void EmuThread::endCapture()
if (!VMManager::HasValidVM())
return;
GetMTGS().RunOnGSThread(&GSEndCapture);
MTGS::RunOnGSThread(&GSEndCapture);
}
std::optional<WindowInfo> EmuThread::acquireRenderWindow(bool recreate_window)
@ -1185,13 +1186,6 @@ void Host::SetFullscreen(bool enabled)
g_emu_thread->setFullscreen(enabled, true);
}
alignas(16) static SysMtgsThread s_mtgs_thread;
SysMtgsThread& GetMTGS()
{
return s_mtgs_thread;
}
bool QtHost::InitializeConfig()
{
if (!EmuFolders::InitializeCriticalFolders())

View File

@ -21,13 +21,13 @@
#include "CDVD/IsoFS/IsoFS.h"
#include "CDVD/IsoFS/IsoFSCDVD.h"
#include "Elfheader.h"
#include "GS.h"
#include "Host.h"
#include "ImGui/FullscreenUI.h"
#include "ImGui/ImGuiFullscreen.h"
#include "ImGui/ImGuiManager.h"
#include "IopMem.h"
#include "Memory.h"
#include "MTGS.h"
#include "VMManager.h"
#include "svnrev.h"
#include "vtlb.h"
@ -426,7 +426,7 @@ std::string Achievements::GetUserAgent()
void Achievements::BeginLoadingScreen(const char* text, bool* was_running_idle)
{
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
MTGS::RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
ImGuiFullscreen::OpenBackgroundProgressDialog("achievements_loading", text, 0, 0, 0);
}
@ -1041,7 +1041,7 @@ void Achievements::DownloadImage(std::string url, std::string cache_filename)
return;
}
GetMTGS().RunOnGSThread([cache_filename]() { ImGuiFullscreen::InvalidateCachedTexture(cache_filename); });
MTGS::RunOnGSThread([cache_filename]() { ImGuiFullscreen::InvalidateCachedTexture(cache_filename); });
};
s_http_downloader->CreateRequest(std::move(url), std::move(callback));
@ -1072,7 +1072,7 @@ void Achievements::DisplayAchievementSummary()
summary.append(TRANSLATE_SV("Achievements", "Leaderboard submission is enabled."));
}
GetMTGS().RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() {
MTGS::RunOnGSThread([title = std::move(title), summary = std::move(summary), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
});
@ -1092,7 +1092,7 @@ void Achievements::DisplayMasteredNotification()
std::string message(fmt::format(
"{} achievements, {} points{}", GetAchievementCount(), GetCurrentPointsForGame(), s_challenge_mode ? " (Hardcore Mode)" : ""));
GetMTGS().RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
MTGS::RunOnGSThread([title = std::move(title), message = std::move(message), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
ImGuiFullscreen::AddNotification(20.0f, std::move(title), std::move(message), std::move(icon));
});
@ -1157,7 +1157,7 @@ void Achievements::GetPatchesCallback(s32 status_code, const std::string& conten
return;
// ensure fullscreen UI is ready
GetMTGS().RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
MTGS::RunOnGSThread(&ImGuiManager::InitializeFullscreenUI);
s_game_id = response.id;
s_game_title = response.title;
@ -1847,7 +1847,7 @@ void Achievements::SubmitLeaderboardCallback(s32 status_code, const std::string&
std::string summary = fmt::format(
"Your Score: {} (Best: {})\nLeaderboard Position: {} of {}", submitted_score, best_score, response.new_rank, response.num_entries);
GetMTGS().RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() {
MTGS::RunOnGSThread([title = lb->title, summary = std::move(summary), icon = s_game_icon]() {
if (FullscreenUI::IsInitialized())
ImGuiFullscreen::AddNotification(10.0f, std::move(title), std::move(summary), std::move(icon));
});
@ -1890,7 +1890,7 @@ void Achievements::UnlockAchievement(u32 achievement_id, bool add_notification /
break;
}
GetMTGS().RunOnGSThread(
MTGS::RunOnGSThread(
[title = std::move(title), description = achievement->description, icon = GetAchievementBadgePath(*achievement)]() {
ImGuiFullscreen::AddNotification(15.0f, std::move(title), std::move(description), std::move(icon));
});

View File

@ -202,6 +202,7 @@ set(pcsx2Headers
LogSink.h
PINE.h
Mdec.h
MTGS.h
MTVU.h
Memory.h
MemoryCardFile.h

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -26,16 +26,16 @@
#include "GS.h"
#include "GS/GS.h"
#include "VUmicro.h"
#include "MTGS.h"
#include "PerformanceMetrics.h"
#include "Patch.h"
#include "ps2/HwInternal.h"
#include "Sio.h"
#include "SPU2/spu2.h"
#include "PAD/Host/PAD.h"
#include "Recording/InputRecording.h"
#include "VMManager.h"
#include "VUmicro.h"
using namespace Threading;
@ -538,7 +538,7 @@ static __fi void DoFMVSwitch()
RendererSwitched = GSConfig.UseHardwareRenderer();
// we don't use the sw toggle here, because it'll change back to auto if set to sw
GetMTGS().SwitchRenderer(new_fmv_state ? GSRendererType::SW : EmuConfig.GS.Renderer, false);
MTGS::SwitchRenderer(new_fmv_state ? GSRendererType::SW : EmuConfig.GS.Renderer, false);
}
else
RendererSwitched = false;

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -19,6 +19,7 @@
#include "Gif.h"
#include "Gif_Unit.h"
#include "MTGS.h"
#include "Vif.h"
#include "Vif_Dma.h"
@ -51,7 +52,7 @@ void ReadFIFO_VIF1(mem128_t* out)
}
if (vif1Regs.stat.FQC > 0)
{
GetMTGS().InitAndReadFIFO(reinterpret_cast<u8*>(out), 1);
MTGS::InitAndReadFIFO(reinterpret_cast<u8*>(out), 1);
vif1.GSLastDownloadSize--;
GUNIT_LOG("ReadFIFO_VIF1");
if (vif1.GSLastDownloadSize <= 16)

View File

@ -14,17 +14,15 @@
*/
#include "PrecompiledHeader.h"
#include "Common.h"
#include <list>
#include "Gif_Unit.h"
#include "Counters.h"
#include "Common.h"
#include "Config.h"
#include "Gif_Unit.h"
#include "MTGS.h"
#include "VMManager.h"
using namespace Threading;
using namespace R5900;
#include <list>
alignas(16) u8 g_RealGSMem[Ps2MemSize::GSregs];
static bool s_GSRegistersWritten = false;
@ -38,7 +36,7 @@ void gsSetVideoMode(GS_VideoMode mode)
// Make sure framelimiter options are in sync with GS capabilities.
void gsReset()
{
GetMTGS().ResetGS(true);
MTGS::ResetGS(true);
gsVideoMode = GS_VideoMode::Uninitialized;
std::memset(g_RealGSMem, 0, sizeof(g_RealGSMem));
UpdateVSyncRate(true);
@ -72,7 +70,7 @@ void gsUpdateFrequency(Pcsx2Config& config)
config.GS.LimitScalar = 0.0f;
}
GetMTGS().UpdateVSyncMode();
MTGS::UpdateVSyncMode();
UpdateVSyncRate(true);
}
@ -88,7 +86,7 @@ static __fi void gsCSRwrite( const tGS_CSR& csr )
std::memset(g_RealGSMem, 0, sizeof(g_RealGSMem));
GSIMR.reset();
CSRreg.Reset();
GetMTGS().SendSimplePacket(GS_RINGTYPE_RESET, 0, 0, 0);
MTGS::SendSimplePacket(MTGS::Command::Reset, 0, 0, 0);
}
if(csr.FLUSH)
@ -371,7 +369,7 @@ void gsPostVsyncStart()
const bool registers_written = s_GSRegistersWritten;
s_GSRegistersWritten = false;
GetMTGS().PostVsyncStart(registers_written);
MTGS::PostVsyncStart(registers_written);
}
void SaveStateBase::gsFreeze()

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -19,10 +19,6 @@
#include "Gif.h"
#include "GS/GS.h"
#include "SingleRegisterTypes.h"
#include <atomic>
#include <functional>
#include <mutex>
#include <thread>
extern double GetVerticalFrequency();
alignas(16) extern u8 g_RealGSMem[Ps2MemSize::GSregs];
@ -281,165 +277,6 @@ enum class GS_VideoMode : int
extern GS_VideoMode gsVideoMode;
extern bool gsIsInterlaced;
/////////////////////////////////////////////////////////////////////////////
// MTGS Threaded Class Declaration
// Uncomment this to enable the MTGS debug stack, which tracks to ensure reads
// and writes stay synchronized. Warning: the debug stack is VERY slow.
//#define RINGBUF_DEBUG_STACK
enum MTGS_RingCommand
{
GS_RINGTYPE_P1,
GS_RINGTYPE_P2,
GS_RINGTYPE_P3,
GS_RINGTYPE_VSYNC,
GS_RINGTYPE_FREEZE,
GS_RINGTYPE_RESET, // issues a GSreset() command.
GS_RINGTYPE_SOFTRESET, // issues a soft reset for the GIF
GS_RINGTYPE_CRC,
GS_RINGTYPE_GSPACKET,
GS_RINGTYPE_MTVU_GSPACKET,
GS_RINGTYPE_INIT_AND_READ_FIFO,
GS_RINGTYPE_ASYNC_CALL,
};
struct MTGS_FreezeData
{
freezeData* fdata;
s32 retval; // value returned from the call, valid only after an mtgsWaitGS()
};
struct MTGS_MemoryScreenshotData
{
u32 width = 0;
u32 height = 0;
std::vector<u32> pixels; // width * height
bool success = false;
};
// --------------------------------------------------------------------------------------
// SysMtgsThread
// --------------------------------------------------------------------------------------
class SysMtgsThread
{
public:
using AsyncCallType = std::function<void()>;
// note: when m_ReadPos == m_WritePos, the fifo is empty
// Threading info: m_ReadPos is updated by the MTGS thread. m_WritePos is updated by the EE thread
std::atomic<unsigned int> m_ReadPos; // cur pos gs is reading from
std::atomic<unsigned int> m_WritePos; // cur pos ee thread is writing to
std::atomic<bool> m_SignalRingEnable;
std::atomic<int> m_SignalRingPosition;
std::atomic<int> m_QueuedFrameCount;
std::atomic<bool> m_VsyncSignalListener;
std::mutex m_mtx_RingBufferBusy2; // Gets released on semaXGkick waiting...
Threading::WorkSema m_sem_event;
Threading::UserspaceSemaphore m_sem_OnRingReset;
Threading::UserspaceSemaphore m_sem_Vsync;
// used to keep multiple threads from sending packets to the ringbuffer concurrently.
// (currently not used or implemented -- is a planned feature for a future threaded VU1)
//MutexLockRecursive m_PacketLocker;
// Used to delay the sending of events. Performance is better if the ringbuffer
// has more than one command in it when the thread is kicked.
int m_CopyDataTally;
// These vars maintain instance data for sending Data Packets.
// Only one data packet can be constructed and uploaded at a time.
uint m_packet_startpos; // size of the packet (data only, ie. not including the 16 byte command!)
uint m_packet_size; // size of the packet (data only, ie. not including the 16 byte command!)
uint m_packet_writepos; // index of the data location in the ringbuffer.
#ifdef RINGBUF_DEBUG_STACK
std::mutex m_lock_Stack;
#endif
std::thread m_thread;
Threading::ThreadHandle m_thread_handle;
std::atomic_bool m_open_flag{false};
std::atomic_bool m_shutdown_flag{false};
std::atomic_bool m_run_idle_flag{false};
Threading::UserspaceSemaphore m_open_or_close_done;
public:
SysMtgsThread();
virtual ~SysMtgsThread();
__fi const Threading::ThreadHandle& GetThreadHandle() const { return m_thread_handle; }
__fi bool IsOpen() const { return m_open_flag.load(std::memory_order_acquire); }
/// Starts the thread, if it hasn't already been started.
void StartThread();
/// Fully stops the thread, closing in the process if needed.
void ShutdownThread();
/// Re-presents the current frame. Call when things like window resizes happen to re-display
/// the current frame with the correct proportions. Should only be called from the CPU thread.
void PresentCurrentFrame();
// Waits for the GS to empty out the entire ring buffer contents.
void WaitGS(bool syncRegs=true, bool weakWait=false, bool isMTVU=false);
void ResetGS(bool hardware_reset);
void PrepDataPacket(MTGS_RingCommand cmd, u32 size);
void PrepDataPacket(GIF_PATH pathidx, u32 size);
void SendDataPacket();
void SendGameCRC(u32 crc);
bool WaitForOpen();
void WaitForClose();
void Freeze(FreezeAction mode, MTGS_FreezeData& data);
void SendSimpleGSPacket(MTGS_RingCommand type, u32 offset, u32 size, GIF_PATH path);
void SendSimplePacket(MTGS_RingCommand type, int data0, int data1, int data2);
void SendPointerPacket(MTGS_RingCommand type, u32 data0, void* data1);
u8* GetDataPacketPtr() const;
void SetEvent();
void PostVsyncStart(bool registers_written);
void InitAndReadFIFO(u8* mem, u32 qwc);
void RunOnGSThread(AsyncCallType func);
void ApplySettings();
void ResizeDisplayWindow(int width, int height, float scale);
void UpdateDisplayWindow();
void SetVSyncMode(VsyncMode mode);
void UpdateVSyncMode();
void SwitchRenderer(GSRendererType renderer, bool display_message = true);
void SetSoftwareRendering(bool software, bool display_message = true);
void ToggleSoftwareRendering();
bool SaveMemorySnapshot(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
u32* width, u32* height, std::vector<u32>* pixels);
void SetRunIdle(bool enabled);
protected:
bool TryOpenGS();
void CloseGS();
void ThreadEntryPoint();
void MainLoop();
void GenericStall(uint size);
// Used internally by SendSimplePacket type functions
void _FinishSimplePacket();
};
// GetMTGS() is a required external implementation. This function is *NOT* provided
// by the PCSX2 core library. It provides an interface for the linking User Interface
// apps or DLLs to reference their own instance of SysMtgsThread (also allowing them
// to extend the class and override virtual methods).
//
extern SysMtgsThread& GetMTGS();
/////////////////////////////////////////////////////////////////////////////
// Generalized GS Functions and Stuff
@ -469,68 +306,3 @@ extern u128 gsNonMirroredRead(u32 mem);
void gsIrq();
extern tGS_CSR CSRr;
// Size of the ringbuffer as a power of 2 -- size is a multiple of simd128s.
// (actual size is 1<<m_RingBufferSizeFactor simd vectors [128-bit values])
// A value of 19 is a 8meg ring buffer. 18 would be 4 megs, and 20 would be 16 megs.
// Default was 2mb, but some games with lots of MTGS activity want 8mb to run fast (rama)
static const uint RingBufferSizeFactor = 19;
// size of the ringbuffer in simd128's.
static const uint RingBufferSize = 1 << RingBufferSizeFactor;
// Mask to apply to ring buffer indices to wrap the pointer from end to
// start (the wrapping is what makes it a ringbuffer, yo!)
static const uint RingBufferMask = RingBufferSize - 1;
struct MTGS_BufferedData
{
u128 m_Ring[RingBufferSize];
u8 Regs[Ps2MemSize::GSregs];
MTGS_BufferedData() {}
u128& operator[](uint idx)
{
pxAssert(idx < RingBufferSize);
return m_Ring[idx];
}
};
alignas(32) extern MTGS_BufferedData RingBuffer;
// FIXME: These belong in common with other memcpy tools. Will move them there later if no one
// else beats me to it. --air
inline void MemCopy_WrappedDest(const u128* src, u128* destBase, uint& destStart, uint destSize, uint len)
{
uint endpos = destStart + len;
if (endpos < destSize)
{
memcpy(&destBase[destStart], src, len * 16);
destStart += len;
}
else
{
uint firstcopylen = destSize - destStart;
memcpy(&destBase[destStart], src, firstcopylen * 16);
destStart = endpos % destSize;
memcpy(destBase, src + firstcopylen, destStart * 16);
}
}
inline void MemCopy_WrappedSrc(const u128* srcBase, uint& srcStart, uint srcSize, u128* dest, uint len)
{
uint endpos = srcStart + len;
if (endpos < srcSize)
{
memcpy(dest, &srcBase[srcStart], len * 16);
srcStart += len;
}
else
{
uint firstcopylen = srcSize - srcStart;
memcpy(dest, &srcBase[srcStart], firstcopylen * 16);
srcStart = endpos % srcSize;
memcpy(dest + firstcopylen, srcBase, srcStart * 16);
}
}

View File

@ -28,6 +28,7 @@
#include "Host.h"
#include "Input/InputManager.h"
#include "MultiISA.h"
#include "MTGS.h"
#include "pcsx2/GS.h"
#include "GS/Renderers/Null/GSRendererNull.h"
#include "GS/Renderers/HW/GSRendererHW.h"
@ -972,7 +973,7 @@ static void HotkeyAdjustUpscaleMultiplier(s32 delta)
// this is pretty slow. we only really need to flush the TC and recompile shaders.
// TODO(Stenzek): Make it faster at some point in the future.
GetMTGS().ApplySettings();
MTGS::ApplySettings();
}
BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphics"),
@ -980,7 +981,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
[](s32 pressed) {
if (!pressed)
{
GetMTGS().RunOnGSThread([]() { GSQueueSnapshot(std::string(), 0); });
MTGS::RunOnGSThread([]() { GSQueueSnapshot(std::string(), 0); });
}
}},
{"ToggleVideoCapture", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_NOOP("Hotkeys", "Toggle Video Capture"),
@ -989,30 +990,30 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
{
if (GSCapture::IsCapturing())
{
GetMTGS().RunOnGSThread([]() { g_gs_renderer->EndCapture(); });
GetMTGS().WaitGS(false, false, false);
MTGS::RunOnGSThread([]() { g_gs_renderer->EndCapture(); });
MTGS::WaitGS(false, false, false);
return;
}
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
std::string filename(fmt::format("{}.{}", GSGetBaseVideoFilename(), GSConfig.CaptureContainer));
g_gs_renderer->BeginCapture(std::move(filename));
});
// Sync GS thread. We want to start adding audio at the same time as video.
GetMTGS().WaitGS(false, false, false);
MTGS::WaitGS(false, false, false);
}
}},
{"GSDumpSingleFrame", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_NOOP("Hotkeys", "Save Single Frame GS Dump"),
[](s32 pressed) {
if (!pressed)
{
GetMTGS().RunOnGSThread([]() { GSQueueSnapshot(std::string(), 1); });
MTGS::RunOnGSThread([]() { GSQueueSnapshot(std::string(), 1); });
}
}},
{"GSDumpMultiFrame", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_NOOP("Hotkeys", "Save Multi Frame GS Dump"),
[](s32 pressed) {
GetMTGS().RunOnGSThread([pressed]() {
MTGS::RunOnGSThread([pressed]() {
if (pressed > 0)
GSQueueSnapshot(std::string(), std::numeric_limits<u32>::max());
else
@ -1023,7 +1024,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
TRANSLATE_NOOP("Hotkeys", "Toggle Software Rendering"),
[](s32 pressed) {
if (!pressed)
GetMTGS().ToggleSoftwareRendering();
MTGS::ToggleSoftwareRendering();
}},
{"IncreaseUpscaleMultiplier", TRANSLATE_NOOP("Hotkeys", "Graphics"),
TRANSLATE_NOOP("Hotkeys", "Increase Upscale Multiplier"),
@ -1067,7 +1068,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
Host::OSD_QUICK_DURATION);
EmuConfig.GS.HWMipmap = new_level;
GetMTGS().RunOnGSThread([new_level]() {
MTGS::RunOnGSThread([new_level]() {
GSConfig.HWMipmap = new_level;
g_gs_renderer->PurgeTextureCache();
g_gs_renderer->PurgePool();
@ -1099,7 +1100,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
Host::OSD_QUICK_DURATION);
EmuConfig.GS.InterlaceMode = new_mode;
GetMTGS().RunOnGSThread([new_mode]() { GSConfig.InterlaceMode = new_mode; });
MTGS::RunOnGSThread([new_mode]() { GSConfig.InterlaceMode = new_mode; });
}},
{"ToggleTextureDumping", TRANSLATE_NOOP("Hotkeys", "Graphics"), TRANSLATE_NOOP("Hotkeys", "Toggle Texture Dumping"),
[](s32 pressed) {
@ -1110,7 +1111,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
EmuConfig.GS.DumpReplaceableTextures ? TRANSLATE_STR("Hotkeys", "Texture dumping is now enabled.") :
TRANSLATE_STR("Hotkeys", "Texture dumping is now disabled."),
Host::OSD_INFO_DURATION);
GetMTGS().ApplySettings();
MTGS::ApplySettings();
}
}},
{"ToggleTextureReplacements", TRANSLATE_NOOP("Hotkeys", "Graphics"),
@ -1124,7 +1125,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
TRANSLATE_STR("Hotkeys", "Texture replacements are now enabled.") :
TRANSLATE_STR("Hotkeys", "Texture replacements are now disabled."),
Host::OSD_INFO_DURATION);
GetMTGS().ApplySettings();
MTGS::ApplySettings();
}
}},
{"ReloadTextureReplacements", TRANSLATE_NOOP("Hotkeys", "Graphics"),
@ -1141,7 +1142,7 @@ BEGIN_HOTKEY_LIST(g_gs_hotkeys){"Screenshot", TRANSLATE_NOOP("Hotkeys", "Graphic
{
Host::AddKeyedOSDMessage("ReloadTextureReplacements",
TRANSLATE_STR("Hotkeys", "Reloading texture replacements..."), Host::OSD_INFO_DURATION);
GetMTGS().RunOnGSThread([]() { GSTextureReplacements::ReloadReplacementMap(); });
MTGS::RunOnGSThread([]() { GSTextureReplacements::ReloadReplacementMap(); });
}
}
}},

View File

@ -213,8 +213,8 @@ static void GSDumpReplayerLoadInitialState()
// load GS state
freezeData fd = {static_cast<int>(s_dump_file->GetStateData().size()),
const_cast<u8*>(s_dump_file->GetStateData().data())};
MTGS_FreezeData mfd = {&fd, 0};
GetMTGS().Freeze(FreezeAction::Load, mfd);
MTGS::FreezeData mfd = {&fd, 0};
MTGS::Freeze(FreezeAction::Load, mfd);
if (mfd.retval != 0)
Host::ReportFormattedErrorAsync("GSDumpReplayer", "Failed to load GS state.");
}
@ -317,7 +317,7 @@ void GSDumpReplayerCpuStep()
s_dump_frame_number++;
GSDumpReplayerUpdateFrameLimit();
GSDumpReplayerFrameLimit();
GetMTGS().PostVsyncStart(false);
MTGS::PostVsyncStart(false);
VMManager::Internal::VSyncOnCPUThread();
if (VMManager::Internal::IsExecutionInterrupted())
GSDumpReplayerExitExecution();
@ -331,7 +331,7 @@ void GSDumpReplayerCpuStep()
// Allocate an extra quadword, some transfers write too much (e.g. Lego Racers 2 with Z24 downloads).
std::unique_ptr<u8[]> arr(new u8[(size + 1) * 16]);
GetMTGS().InitAndReadFIFO(arr.get(), size);
MTGS::InitAndReadFIFO(arr.get(), size);
}
break;

View File

@ -195,42 +195,6 @@ void Gif_FinishIRQ()
}
}
// Used in MTVU mode... MTVU will later complete a real packet
void Gif_AddGSPacketMTVU(GS_Packet& gsPack, GIF_PATH path)
{
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_MTVU_GSPACKET, 0, 0, path);
}
void Gif_AddCompletedGSPacket(GS_Packet& gsPack, GIF_PATH path)
{
//DevCon.WriteLn("Adding Completed Gif Packet [size=%x]", gsPack.size);
if (COPY_GS_PACKET_TO_MTGS)
{
GetMTGS().PrepDataPacket(path, gsPack.size / 16);
MemCopy_WrappedDest((u128*)&gifUnit.gifPath[path].buffer[gsPack.offset], RingBuffer.m_Ring,
GetMTGS().m_packet_writepos, RingBufferSize, gsPack.size / 16);
GetMTGS().SendDataPacket();
}
else
{
pxAssertDev(!gsPack.readAmount, "Gif Unit - gsPack.readAmount only valid for MTVU path 1!");
gifUnit.gifPath[path].readAmount.fetch_add(gsPack.size);
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, gsPack.offset, gsPack.size, path);
}
}
void Gif_AddBlankGSPacket(u32 size, GIF_PATH path)
{
//DevCon.WriteLn("Adding Blank Gif Packet [size=%x]", size);
gifUnit.gifPath[path].readAmount.fetch_add(size);
GetMTGS().SendSimpleGSPacket(GS_RINGTYPE_GSPACKET, ~0u, size, path);
}
void Gif_MTGS_Wait(bool isMTVU)
{
GetMTGS().WaitGS(false, true, isMTVU);
}
void SaveStateBase::gifPathFreeze(u32 path)
{
@ -262,7 +226,7 @@ void SaveStateBase::gifFreeze()
{
bool mtvuMode = THREAD_VU1;
pxAssert(vu1Thread.IsDone());
GetMTGS().WaitGS();
MTGS::WaitGS();
FreezeTag("Gif Unit");
Freeze(mtvuMode);
Freeze(gifUnit.stat);

View File

@ -19,6 +19,7 @@
#include "Vif.h"
#include "GS.h"
#include "GS/GSRegs.h"
#include "MTGS.h"
// FIXME common path ?
#include "common/boost_spsc_queue.hpp"
@ -193,7 +194,7 @@ struct Gif_Path_MTVU
// Set a size based on MTGS but keep a factor 2 to avoid too waste to much
// memory overhead. Note the struct is instantied 3 times (for each gif
// path)
ringbuffer_base<GS_Packet, RingBufferSize / 2> gsPackQueue;
ringbuffer_base<GS_Packet, MTGS::RingBufferSize / 2> gsPackQueue;
Gif_Path_MTVU() { Reset(); }
void Reset()
{

View File

@ -22,6 +22,8 @@
#include "USB/USB.h"
#include "x86/newVif.h"
#include "common/WrappedMemCopy.h"
#include "fmt/core.h"
using namespace R5900;

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -22,7 +22,6 @@
#include "GS/Renderers/Common/GSTexture.h"
#include "Achievements.h"
#include "CDVD/CDVDdiscReader.h"
#include "GS.h"
#include "GameList.h"
#include "Host.h"
#include "INISettingsInterface.h"
@ -31,6 +30,7 @@
#include "ImGui/ImGuiManager.h"
#include "Input/InputManager.h"
#include "MemoryCardFile.h"
#include "MTGS.h"
#include "PAD/Host/PAD.h"
#include "Sio.h"
#include "USB/USB.h"
@ -584,7 +584,7 @@ bool FullscreenUI::Initialize()
s_initialized = true;
s_hotkey_list_cache = InputManager::GetHotkeyList();
GetMTGS().SetRunIdle(true);
MTGS::SetRunIdle(true);
if (VMManager::HasValidVM())
{
@ -623,13 +623,13 @@ void FullscreenUI::CheckForConfigChanges(const Pcsx2Config& old_config)
if (old_config.Achievements.Enabled && !EmuConfig.Achievements.Enabled)
{
// So, wait just in case.
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (s_current_main_window == MainWindowType::Achievements || s_current_main_window == MainWindowType::Leaderboards)
{
ReturnToMainWindow();
}
});
GetMTGS().WaitGS(false, false, false);
MTGS::WaitGS(false, false, false);
}
#endif
}
@ -639,7 +639,7 @@ void FullscreenUI::OnVMStarted()
if (!IsInitialized())
return;
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (!IsInitialized())
return;
@ -653,7 +653,7 @@ void FullscreenUI::OnVMDestroyed()
if (!IsInitialized())
return;
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (!IsInitialized())
return;
@ -667,7 +667,7 @@ void FullscreenUI::GameChanged(std::string path, std::string serial, std::string
if (!IsInitialized())
return;
GetMTGS().RunOnGSThread(
MTGS::RunOnGSThread(
[path = std::move(path), serial = std::move(serial), title = std::move(title), disc_crc, crc]() {
if (!IsInitialized())
return;
@ -711,7 +711,7 @@ void FullscreenUI::OpenPauseMenu()
if (!VMManager::HasValidVM())
return;
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (!ImGuiManager::InitializeFullscreenUI() || s_current_main_window != MainWindowType::None)
return;
@ -866,7 +866,7 @@ void FullscreenUI::InvalidateCoverCache()
if (!IsInitialized())
return;
GetMTGS().RunOnGSThread([]() { s_cover_image_map.clear(); });
MTGS::RunOnGSThread([]() { s_cover_image_map.clear(); });
}
void FullscreenUI::ReturnToMainWindow()
@ -1030,7 +1030,7 @@ void FullscreenUI::DoToggleSoftwareRenderer()
if (!VMManager::HasValidVM())
return;
GetMTGS().ToggleSoftwareRendering();
MTGS::ToggleSoftwareRendering();
});
}
@ -2244,7 +2244,7 @@ void FullscreenUI::StartAutomaticBinding(u32 port)
// messy because the enumeration has to happen on the input thread
Host::RunOnCPUThread([port]() {
std::vector<std::pair<std::string, std::string>> devices(InputManager::EnumerateDevices());
GetMTGS().RunOnGSThread([port, devices = std::move(devices)]() {
MTGS::RunOnGSThread([port, devices = std::move(devices)]() {
if (devices.empty())
{
ShowToast({}, "Automatic binding failed, no devices are available.");
@ -2274,7 +2274,7 @@ void FullscreenUI::StartAutomaticBinding(u32 port)
// and the toast needs to happen on the UI thread.
GetMTGS().RunOnGSThread([result, name = std::move(name)]() {
MTGS::RunOnGSThread([result, name = std::move(name)]() {
ShowToast({}, result ? fmt::format("Automatic mapping completed for {}.", name) :
fmt::format("Automatic mapping failed for {}.", name));
});
@ -5890,7 +5890,7 @@ void FullscreenUI::DrawCoverDownloaderWindow()
GameList::DownloadCovers(urls, use_serial_names, progress, [](const GameList::Entry* entry, std::string save_path) {
// cache the cover path on our side once it's saved
Host::RunOnCPUThread([path = entry->path, save_path = std::move(save_path)]() {
GetMTGS().RunOnGSThread([path = std::move(path), save_path = std::move(save_path)]() {
MTGS::RunOnGSThread([path = std::move(path), save_path = std::move(save_path)]() {
s_cover_image_map[std::move(path)] = std::move(save_path);
});
});
@ -6167,7 +6167,7 @@ void FullscreenUI::OpenAchievementsWindow()
if (!VMManager::HasValidVM() || !Achievements::IsActive())
return;
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (!ImGuiManager::InitializeFullscreenUI())
return;
@ -6557,7 +6557,7 @@ void FullscreenUI::OpenLeaderboardsWindow()
if (!VMManager::HasValidVM() || !Achievements::IsActive())
return;
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (!ImGuiManager::InitializeFullscreenUI())
return;

View File

@ -18,7 +18,6 @@
#include "GS/Renderers/Common/GSDevice.h"
#include "Config.h"
#include "Counters.h"
#include "GS.h"
#include "GS/GS.h"
#include "Host.h"
#include "IconsFontAwesome5.h"
@ -27,6 +26,7 @@
#include "ImGui/ImGuiManager.h"
#include "ImGui/ImGuiOverlays.h"
#include "Input/InputManager.h"
#include "MTGS.h"
#include "PerformanceMetrics.h"
#include "Recording/InputRecording.h"
#include "VMManager.h"
@ -713,7 +713,7 @@ void ImGuiManager::AddTextInput(std::string str)
// Has to go through the CPU -> GS thread :(
Host::RunOnCPUThread([str = std::move(str)]() {
GetMTGS().RunOnGSThread([str = std::move(str)]() {
MTGS::RunOnGSThread([str = std::move(str)]() {
if (!ImGui::GetCurrentContext())
return;
@ -737,7 +737,7 @@ bool ImGuiManager::ProcessPointerButtonEvent(InputBindingKey key, float value)
return false;
// still update state anyway
GetMTGS().RunOnGSThread([button = key.data, down = (value != 0.0f)]() { ImGui::GetIO().AddMouseButtonEvent(button, down); });
MTGS::RunOnGSThread([button = key.data, down = (value != 0.0f)]() { ImGui::GetIO().AddMouseButtonEvent(button, down); });
return s_imgui_wants_mouse.load(std::memory_order_acquire);
}
@ -749,7 +749,7 @@ bool ImGuiManager::ProcessPointerAxisEvent(InputBindingKey key, float value)
// still update state anyway
const bool horizontal = (key.data == static_cast<u32>(InputPointerAxis::WheelX));
GetMTGS().RunOnGSThread([wheel_x = horizontal ? value : 0.0f, wheel_y = horizontal ? 0.0f : value]() {
MTGS::RunOnGSThread([wheel_x = horizontal ? value : 0.0f, wheel_y = horizontal ? 0.0f : value]() {
ImGui::GetIO().AddMouseWheelEvent(wheel_x, wheel_y);
});
@ -763,7 +763,7 @@ bool ImGuiManager::ProcessHostKeyEvent(InputBindingKey key, float value)
return false;
// still update state anyway
GetMTGS().RunOnGSThread([imkey = iter->second, down = (value != 0.0f)]() { ImGui::GetIO().AddKeyEvent(imkey, down); });
MTGS::RunOnGSThread([imkey = iter->second, down = (value != 0.0f)]() { ImGui::GetIO().AddKeyEvent(imkey, down); });
return s_imgui_wants_keyboard.load(std::memory_order_acquire);
}
@ -805,7 +805,7 @@ bool ImGuiManager::ProcessGenericInputEvent(GenericInputBinding key, float value
if (static_cast<u32>(key) >= std::size(key_map) || key_map[static_cast<u32>(key)] == ImGuiKey_None)
return false;
GetMTGS().RunOnGSThread(
MTGS::RunOnGSThread(
[key = key_map[static_cast<u32>(key)], value]() { ImGui::GetIO().AddKeyAnalogEvent(key, (value > 0.0f), value); });
return true;

File diff suppressed because it is too large Load Diff

107
pcsx2/MTGS.h Normal file
View File

@ -0,0 +1,107 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* PCSX2 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 for more details.
*
* You should have received a copy of the GNU General Public License along with PCSX2.
* If not, see <http://www.gnu.org/licenses/>.
*/
#pragma once
#include "GS.h"
#include <functional>
/////////////////////////////////////////////////////////////////////////////
// MTGS Threaded Class Declaration
// Uncomment this to enable the MTGS debug stack, which tracks to ensure reads
// and writes stay synchronized. Warning: the debug stack is VERY slow.
//#define RINGBUF_DEBUG_STACK
namespace MTGS
{
using AsyncCallType = std::function<void()>;
enum class Command : u32
{
GIFPath1,
GIFPath2,
GIFPath3,
VSync,
Freeze,
Reset, // issues a GSreset() command.
SoftReset, // issues a soft reset for the GIF
CRC,
GSPacket,
MTVUGSPacket,
InitAndReadFIFO,
AsyncCall,
};
struct FreezeData
{
freezeData* fdata;
s32 retval; // value returned from the call, valid only after an mtgsWaitGS()
};
const Threading::ThreadHandle& GetThreadHandle();
bool IsOpen();
/// Starts the thread, if it hasn't already been started.
void StartThread();
/// Fully stops the thread, closing in the process if needed.
void ShutdownThread();
/// Re-presents the current frame. Call when things like window resizes happen to re-display
/// the current frame with the correct proportions. Should only be called from the CPU thread.
void PresentCurrentFrame();
// Waits for the GS to empty out the entire ring buffer contents.
void WaitGS(bool syncRegs = true, bool weakWait = false, bool isMTVU = false);
void ResetGS(bool hardware_reset);
void SendGameCRC(u32 crc);
bool WaitForOpen();
void WaitForClose();
void Freeze(FreezeAction mode, FreezeData& data);
void SendSimplePacket(Command type, int data0, int data1, int data2);
void PostVsyncStart(bool registers_written);
void InitAndReadFIFO(u8* mem, u32 qwc);
void RunOnGSThread(AsyncCallType func);
void ApplySettings();
void ResizeDisplayWindow(int width, int height, float scale);
void UpdateDisplayWindow();
void SetVSyncMode(VsyncMode mode);
void UpdateVSyncMode();
void SwitchRenderer(GSRendererType renderer, bool display_message = true);
void SetSoftwareRendering(bool software, bool display_message = true);
void ToggleSoftwareRendering();
bool SaveMemorySnapshot(u32 window_width, u32 window_height, bool apply_aspect, bool crop_borders,
u32* width, u32* height, std::vector<u32>* pixels);
void SetRunIdle(bool enabled);
// Size of the ringbuffer as a power of 2 -- size is a multiple of simd128s.
// (actual size is 1<<m_RingBufferSizeFactor simd vectors [128-bit values])
// A value of 19 is a 8meg ring buffer. 18 would be 4 megs, and 20 would be 16 megs.
// Default was 2mb, but some games with lots of MTGS activity want 8mb to run fast (rama)
static const uint RingBufferSizeFactor = 19;
// size of the ringbuffer in simd128's.
static const uint RingBufferSize = 1 << RingBufferSizeFactor;
// Mask to apply to ring buffer indices to wrap the pointer from end to
// start (the wrapping is what makes it a ringbuffer, yo!)
static const uint RingBufferMask = RingBufferSize - 1;
}

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -26,6 +26,7 @@
#include "GS.h"
#include "GS/GSCapture.h"
#include "MTGS.h"
#include "MTVU.h"
#include "VMManager.h"
@ -132,7 +133,7 @@ void PerformanceMetrics::Reset()
s_last_frame_time.Reset();
s_last_cpu_time = s_cpu_thread_handle.GetCPUTime();
s_last_gs_time = GetMTGS().GetThreadHandle().GetCPUTime();
s_last_gs_time = MTGS::GetThreadHandle().GetCPUTime();
s_last_vu_time = THREAD_VU1 ? vu1Thread.GetThreadHandle().GetCPUTime() : 0;
s_last_ticks = GetCPUTicks();
s_last_capture_time = GSCapture::IsCapturing() ? GSCapture::GetEncoderThreadHandle().GetCPUTime() : 0;
@ -205,7 +206,7 @@ void PerformanceMetrics::Update(bool gs_register_write, bool fb_blit, bool is_sk
(1.0 / static_cast<double>(s_frames_since_last_update));
const u64 cpu_time = s_cpu_thread_handle.GetCPUTime();
const u64 gs_time = GetMTGS().GetThreadHandle().GetCPUTime();
const u64 gs_time = MTGS::GetThreadHandle().GetCPUTime();
const u64 vu_time = THREAD_VU1 ? vu1Thread.GetThreadHandle().GetCPUTime() : 0;
const u64 capture_time = GSCapture::IsCapturing() ? GSCapture::GetEncoderThreadHandle().GetCPUTime() : 0;

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -70,11 +70,6 @@ extern SysMainMemory& GetVmMemory();
void cpuReset()
{
vu1Thread.WaitVU();
vu1Thread.Reset();
if (GetMTGS().IsOpen())
GetMTGS().WaitGS(); // GS better be done processing before we reset the EE, just in case.
GetVmMemory().Reset();
std::memset(&cpuRegs, 0, sizeof(cpuRegs));

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2022 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -15,8 +15,9 @@
#include "PrecompiledHeader.h"
#include "SaveState.h"
#include "Counters.h"
#include "MTGS.h"
#include "SaveState.h"
void SaveStateBase::InputRecordingFreeze()
{
@ -146,7 +147,7 @@ void InputRecording::closeActiveFile()
{
m_is_active = false;
InputRec::log("Input recording stopped");
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
else
{

View File

@ -22,7 +22,7 @@
#include "InputRecordingControls.h"
#include "Utilities/InputRecordingLogger.h"
#include "GS.h"
#include "MTGS.h"
#include "VMManager.h"
void InputRecordingControls::toggleRecordMode()
@ -43,7 +43,7 @@ void InputRecordingControls::setRecordMode(bool waitForFrameToEnd)
{
m_state = Mode::Recording;
InputRec::log("Record mode ON");
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
else
{
@ -60,7 +60,7 @@ void InputRecordingControls::setReplayMode(bool waitForFrameToEnd)
{
m_state = Mode::Replaying;
InputRec::log("Replay mode ON");
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
else
{
@ -86,7 +86,7 @@ void InputRecordingControls::processControlQueue()
m_controlQueue.front()();
m_controlQueue.pop();
}
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
}

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2023 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -18,8 +18,8 @@
#include "SPU2/Debug.h"
#include "SPU2/spu2.h"
#include "SPU2/Dma.h"
#include "GS.h"
#include "GS/GSCapture.h"
#include "MTGS.h"
#include "R3000A.h"
namespace SPU2
@ -134,8 +134,8 @@ void SPU2::UpdateSampleRate()
// Can't be capturing when the sample rate changes.
if (IsAudioCaptureActive())
{
GetMTGS().RunOnGSThread(&GSEndCapture);
GetMTGS().WaitGS(false, false, false);
MTGS::RunOnGSThread(&GSEndCapture);
MTGS::WaitGS(false, false, false);
}
}

View File

@ -26,6 +26,7 @@
#include "GS.h"
#include "GS/GS.h"
#include "Host.h"
#include "MTGS.h"
#include "MTVU.h"
#include "PAD/Host/PAD.h"
#include "Patch.h"
@ -59,7 +60,7 @@ static void PreLoadPrep()
// ensure everything is in sync before we start overwriting stuff.
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
MTGS::WaitGS(false);
// backup current TLBs, since we're going to overwrite them all
std::memcpy(s_tlb_backup, tlb, sizeof(s_tlb_backup));
@ -322,8 +323,8 @@ struct SysState_Component
static int SysState_MTGSFreeze(FreezeAction mode, freezeData* fP)
{
MTGS_FreezeData sstate = { fP, 0 };
GetMTGS().Freeze(mode, sstate);
MTGS::FreezeData sstate = { fP, 0 };
MTGS::Freeze(mode, sstate);
return sstate.retval;
}
@ -709,7 +710,7 @@ std::unique_ptr<SaveStateScreenshotData> SaveState_SaveScreenshot()
u32 width, height;
std::vector<u32> pixels;
if (!GetMTGS().SaveMemorySnapshot(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT, true, false, &width, &height, &pixels))
if (!MTGS::SaveMemorySnapshot(SCREENSHOT_WIDTH, SCREENSHOT_HEIGHT, true, false, &width, &height, &pixels))
{
// saving failed for some reason, device lost?
return nullptr;

View File

@ -34,6 +34,7 @@
#include "Input/InputManager.h"
#include "IopBios.h"
#include "LogSink.h"
#include "MTGS.h"
#include "MTVU.h"
#include "MemoryCardFile.h"
#include "PAD/Host/PAD.h"
@ -236,7 +237,7 @@ void VMManager::SetState(VMState state)
{
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
MTGS::WaitGS(false);
InputManager::PauseVibration();
}
else
@ -384,6 +385,8 @@ void VMManager::Internal::CPUThreadShutdown()
USBshutdown();
GSshutdown();
MTGS::ShutdownThread();
#ifdef _WIN32
CoUninitialize();
#endif
@ -521,7 +524,7 @@ void VMManager::ApplySettings()
{
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
MTGS::WaitGS(false);
}
// Reset to a clean Pcsx2Config. Otherwise things which are optional (e.g. gamefixes)
@ -544,7 +547,7 @@ void VMManager::ApplyCoreSettings()
{
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS(false);
MTGS::WaitGS(false);
}
// Reset to a clean Pcsx2Config. Otherwise things which are optional (e.g. gamefixes)
@ -631,7 +634,7 @@ void VMManager::Internal::UpdateEmuFolders()
if (EmuFolders::Textures != old_textures_directory)
{
GetMTGS().RunOnGSThread([]() {
MTGS::RunOnGSThread([]() {
if (VMManager::HasValidVM())
GSTextureReplacements::ReloadReplacementMap();
});
@ -640,7 +643,7 @@ void VMManager::Internal::UpdateEmuFolders()
if (EmuFolders::Videos != old_videos_directory)
{
if (VMManager::HasValidVM())
GetMTGS().RunOnGSThread(&GSEndCapture);
MTGS::RunOnGSThread(&GSEndCapture);
}
}
}
@ -1189,8 +1192,8 @@ bool VMManager::Initialize(VMBootParameters boot_params)
EmuConfig.LimiterMode = GetInitialLimiterMode();
Console.WriteLn("Opening GS...");
s_gs_open_on_initialize = GetMTGS().IsOpen();
if (!s_gs_open_on_initialize && !GetMTGS().WaitForOpen())
s_gs_open_on_initialize = MTGS::IsOpen();
if (!s_gs_open_on_initialize && !MTGS::WaitForOpen())
{
// we assume GS is going to report its own error
Console.WriteLn("Failed to open GS.");
@ -1199,7 +1202,7 @@ bool VMManager::Initialize(VMBootParameters boot_params)
ScopedGuard close_gs = []() {
if (!s_gs_open_on_initialize)
GetMTGS().WaitForClose();
MTGS::WaitForClose();
};
Console.WriteLn("Opening SPU2...");
@ -1310,7 +1313,7 @@ void VMManager::Shutdown(bool save_resume_state)
// sync everything
if (THREAD_VU1)
vu1Thread.WaitVU();
GetMTGS().WaitGS();
MTGS::WaitGS();
if (!GSDumpReplayer::IsReplayingDump() && save_resume_state)
{
@ -1359,12 +1362,12 @@ void VMManager::Shutdown(bool save_resume_state)
// so that the texture cache and targets are all cleared.
if (s_gs_open_on_initialize)
{
GetMTGS().WaitGS(false, false, false);
GetMTGS().ResetGS(true);
MTGS::WaitGS(false, false, false);
MTGS::ResetGS(true);
}
else
{
GetMTGS().WaitForClose();
MTGS::WaitForClose();
}
PADshutdown();
@ -1402,6 +1405,10 @@ void VMManager::Reset()
return;
#endif
vu1Thread.WaitVU();
vu1Thread.Reset();
MTGS::WaitGS();
const bool elf_was_changed = (s_current_crc != 0);
ClearELFInfo();
if (elf_was_changed)
@ -1416,7 +1423,7 @@ void VMManager::Reset()
if (g_InputRecording.isActive())
{
g_InputRecording.handleReset();
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
// If we were paused, state won't be resetting, so don't flip back to running.
@ -1511,7 +1518,7 @@ bool VMManager::DoLoadState(const char* filename)
if (g_InputRecording.isActive())
{
g_InputRecording.handleLoadingSavestate();
GetMTGS().PresentCurrentFrame();
MTGS::PresentCurrentFrame();
}
return true;
}
@ -2044,7 +2051,7 @@ void VMManager::CheckForGSConfigChanges(const Pcsx2Config& old_config)
EmuConfig.LimiterMode = GetInitialLimiterMode();
ResetFrameLimiterState();
GetMTGS().ApplySettings();
MTGS::ApplySettings();
}
void VMManager::CheckForFramerateConfigChanges(const Pcsx2Config& old_config)
@ -2073,7 +2080,7 @@ void VMManager::CheckForPatchConfigChanges(const Pcsx2Config& old_config)
// This is a bit messy, because the patch config update happens after the settings are loaded,
// if we disable widescreen patches, we have to reload the original settings again.
if (Patch::ReloadPatchAffectingOptions())
GetMTGS().ApplySettings();
MTGS::ApplySettings();
}
void VMManager::CheckForDEV9ConfigChanges(const Pcsx2Config& old_config)
@ -2171,7 +2178,7 @@ void VMManager::CheckForConfigChanges(const Pcsx2Config& old_config)
// For the big picture UI, we still need to update GS settings, since it's running,
// and we don't update its config when we start the VM.
if (HasValidVM() || GetMTGS().IsOpen())
if (HasValidVM() || MTGS::IsOpen())
CheckForGSConfigChanges(old_config);
if (EmuConfig.Achievements != old_config.Achievements)
@ -2705,7 +2712,7 @@ void VMManager::SetEmuThreadAffinities()
if (EmuConfig.Cpu.AffinityControlMode != 0)
Console.Error("Insufficient processors for affinity control.");
GetMTGS().GetThreadHandle().SetAffinity(0);
MTGS::GetThreadHandle().SetAffinity(0);
vu1Thread.GetThreadHandle().SetAffinity(0);
s_vm_thread_handle.SetAffinity(0);
return;
@ -2748,7 +2755,7 @@ void VMManager::SetEmuThreadAffinities()
const u64 gs_affinity = static_cast<u64>(1) << gs_index;
Console.WriteLn(Color_StrongGreen, "GS thread is on processor %u (0x%llx)", gs_index, gs_affinity);
GetMTGS().GetThreadHandle().SetAffinity(gs_affinity);
MTGS::GetThreadHandle().SetAffinity(gs_affinity);
}
void VMManager::SetHardwareDependentDefaultSettings(SettingsInterface& si)

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2010 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -72,7 +72,7 @@ void vif1TransferToMemory()
pxAssert(p3.isDone() || !p3.gifTag.isValid);
}
GetMTGS().InitAndReadFIFO(reinterpret_cast<u8*>(pMem), size);
MTGS::InitAndReadFIFO(reinterpret_cast<u8*>(pMem), size);
// pMem += size;
//Some games such as Alex Ferguson's Player Manager 2001 reads less than GSLastDownloadSize by VIF then reads the remainder by FIFO

View File

@ -1,5 +1,5 @@
/* PCSX2 - PS2 Emulator for PCs
* Copyright (C) 2002-2021 PCSX2 Dev Team
* Copyright (C) 2002-2023 PCSX2 Dev Team
*
* PCSX2 is free software: you can redistribute it and/or modify it under the terms
* of the GNU Lesser General Public License as published by the Free Software Found-
@ -13,13 +13,12 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "pcsx2/Achievements.h"
#include "pcsx2/GS.h"
#include "pcsx2/Host.h"
#include "pcsx2/ImGui/ImGuiManager.h"
#include "pcsx2/Input/InputManager.h"
#include "pcsx2/GS.h"
#include "pcsx2/GS/GS.h"
#include "pcsx2/Host.h"
#include "pcsx2/VMManager.h"
#include "pcsx2/Achievements.h"
void Host::CommitBaseSettingChanges()
{
@ -219,15 +218,5 @@ std::optional<std::string> InputManager::ConvertHostKeyboardCodeToString(u32 cod
return std::nullopt;
}
SysMtgsThread& GetMTGS()
{
throw std::exception();
}
//////////////////////////////////////////////////////////////////////////
// Interface Stuff
//////////////////////////////////////////////////////////////////////////
const IConsoleWriter* PatchesCon = &Console;
BEGIN_HOTKEY_LIST(g_host_hotkeys)
END_HOTKEY_LIST()