From be2ba4ffb365a6361a722190971fee796f716dc0 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 19:34:48 +0100 Subject: [PATCH 01/10] Remove the setting to run the display list interpreter on a separate thread. --- Core/Config.cpp | 1 - Core/Config.h | 2 -- Core/System.cpp | 26 +++++++++++++++----------- GPU/GPUCommon.cpp | 4 ++-- GPU/Software/SoftGpu.cpp | 5 ----- UI/GameSettingsScreen.cpp | 7 ------- 6 files changed, 17 insertions(+), 28 deletions(-) diff --git a/Core/Config.cpp b/Core/Config.cpp index e4adbd12ff..9ddda1a9e9 100644 --- a/Core/Config.cpp +++ b/Core/Config.cpp @@ -406,7 +406,6 @@ static bool DefaultSasThread() { static ConfigSetting cpuSettings[] = { ReportedConfigSetting("CPUCore", &g_Config.iCpuCore, &DefaultCpuCore, true, true), - ReportedConfigSetting("SeparateCPUThread", &g_Config.bSeparateCPUThread, false, true, true), ReportedConfigSetting("SeparateSASThread", &g_Config.bSeparateSASThread, &DefaultSasThread, true, true), ReportedConfigSetting("SeparateIOThread", &g_Config.bSeparateIOThread, true, true, true), ReportedConfigSetting("IOTimingMethod", &g_Config.iIOTimingMethod, IOTIMING_FAST, true, true), diff --git a/Core/Config.h b/Core/Config.h index 37dd1373fe..6a1d4c2134 100644 --- a/Core/Config.h +++ b/Core/Config.h @@ -132,8 +132,6 @@ public: bool bFuncReplacements; bool bHideSlowWarnings; - // Definitely cannot be changed while game is running. - bool bSeparateCPUThread; bool bSeparateSASThread; bool bSeparateIOThread; int iIOTimingMethod; diff --git a/Core/System.cpp b/Core/System.cpp index 04c93deeb1..6f7069f1f2 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -392,10 +392,10 @@ void System_Wake() { // Ugly! static bool pspIsInited = false; static bool pspIsIniting = false; -static bool pspIsQuiting = false; +static bool pspIsQuitting = false; bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { - if (pspIsIniting || pspIsQuiting) { + if (pspIsIniting || pspIsQuitting) { return false; } @@ -415,7 +415,9 @@ bool PSP_InitStart(const CoreParameter &coreParam, std::string *error_string) { coreParameter.errorString = ""; pspIsIniting = true; - if (g_Config.bSeparateCPUThread) { + // Keeping this around because we might need it in the future. + const bool separateCPUThread = false; + if (separateCPUThread) { Core_ListenShutdown(System_Wake); CPU_SetState(CPU_THREAD_PENDING); cpuThread = new std::thread(&CPU_RunLoop); @@ -438,7 +440,7 @@ bool PSP_InitUpdate(std::string *error_string) { return true; } - if (g_Config.bSeparateCPUThread && !CPU_IsReady()) { + if (!CPU_IsReady()) { return false; } @@ -459,7 +461,8 @@ bool PSP_InitUpdate(std::string *error_string) { bool PSP_Init(const CoreParameter &coreParam, std::string *error_string) { PSP_InitStart(coreParam, error_string); - if (g_Config.bSeparateCPUThread) { + // For a potential resurrection of separate CPU thread later. + if (false) { CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); } @@ -472,12 +475,12 @@ bool PSP_IsIniting() { } bool PSP_IsInited() { - return pspIsInited && !pspIsQuiting; + return pspIsInited && !pspIsQuitting; } void PSP_Shutdown() { // Do nothing if we never inited. - if (!pspIsInited && !pspIsIniting && !pspIsQuiting) { + if (!pspIsInited && !pspIsIniting && !pspIsQuitting) { return; } @@ -488,7 +491,7 @@ void PSP_Shutdown() { #endif // Make sure things know right away that PSP memory, etc. is going away. - pspIsQuiting = true; + pspIsQuitting = true; if (coreState == CORE_RUNNING) Core_UpdateState(CORE_ERROR); Core_NotifyShutdown(); @@ -507,7 +510,7 @@ void PSP_Shutdown() { currentMIPS = 0; pspIsInited = false; pspIsIniting = false; - pspIsQuiting = false; + pspIsQuitting = false; g_Config.unloadGameConfig(); } @@ -532,8 +535,9 @@ void PSP_RunLoopUntil(u64 globalticks) { return; } - // Switch the CPU thread on or off, as the case may be. - bool useCPUThread = g_Config.bSeparateCPUThread; + // We no longer allow a separate CPU thread but if we add a render queue + // to GL we're gonna need it. + bool useCPUThread = false; if (useCPUThread && cpuThread == nullptr) { // Need to start the cpu thread. Core_ListenShutdown(System_Wake); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 53b39e6d32..84873b5133 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -359,11 +359,11 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : // The compiler was not rounding the struct size up to an 8 byte boundary, which // you'd expect due to the int64 field, but the Linux ABI apparently does not require that. static_assert(sizeof(DisplayList) == 456, "Bad DisplayList size"); - listLock.set_enabled(g_Config.bSeparateCPUThread); + listLock.set_enabled(false); Reinitialize(); SetupColorConv(); - SetThreadEnabled(g_Config.bSeparateCPUThread); + SetThreadEnabled(false); gstate.Reset(); gstate_c.Reset(); gpuStats.Reset(); diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 812c164cb2..89b8383fb0 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -913,11 +913,6 @@ bool SoftGPU::PerformStencilUpload(u32 dest, int size) } bool SoftGPU::FramebufferDirty() { - if (g_Config.bSeparateCPUThread) { - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } - if (g_Config.iFrameSkip != 0) { bool dirty = framebufferDirty_; framebufferDirty_ = false; diff --git a/UI/GameSettingsScreen.cpp b/UI/GameSettingsScreen.cpp index 5baed5463e..7579c65aaa 100644 --- a/UI/GameSettingsScreen.cpp +++ b/UI/GameSettingsScreen.cpp @@ -661,13 +661,6 @@ void GameSettingsScreen::CreateViews() { systemSettings->Add(new CheckBox(&g_Config.bFastMemory, sy->T("Fast Memory", "Fast Memory (Unstable)")))->OnClick.Handle(this, &GameSettingsScreen::OnJitAffectingSetting); - auto separateCPUThread = new CheckBox(&g_Config.bSeparateCPUThread, sy->T("Multithreaded (experimental)")); - systemSettings->Add(separateCPUThread); - separateCPUThread->OnClick.Add([=](EventParams &e) { - if (g_Config.bSeparateCPUThread) - settingInfo_->Show(sy->T("Multithreaded Tip", "Not always faster, causes glitches/crashing"), e.v); - return UI::EVENT_CONTINUE; - }); systemSettings->Add(new CheckBox(&g_Config.bSeparateIOThread, sy->T("I/O on thread (experimental)")))->SetEnabled(!PSP_IsInited()); static const char *ioTimingMethods[] = { "Fast (lag on slow storage)", "Host (bugs, less lag)", "Simulate UMD delays" }; View *ioTimingMethod = systemSettings->Add(new PopupMultiChoice(&g_Config.iIOTimingMethod, sy->T("IO timing method"), ioTimingMethods, 0, ARRAY_SIZE(ioTimingMethods), sy->GetName(), screenManager())); From 4d9c571bf449b0aa94e02876cfb7f13192700a09 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 19:44:07 +0100 Subject: [PATCH 02/10] Delete the mutex in GPUCommon. --- GPU/GPUCommon.cpp | 52 +++-------------------------------------------- GPU/GPUCommon.h | 43 --------------------------------------- 2 files changed, 3 insertions(+), 92 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 84873b5133..a90c119a6d 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -359,7 +359,6 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : // The compiler was not rounding the struct size up to an 8 byte boundary, which // you'd expect due to the int64 field, but the Linux ABI apparently does not require that. static_assert(sizeof(DisplayList) == 456, "Bad DisplayList size"); - listLock.set_enabled(false); Reinitialize(); SetupColorConv(); @@ -392,7 +391,6 @@ void GPUCommon::CopyDisplayToOutput() { } void GPUCommon::Reinitialize() { - easy_guard guard(listLock); memset(dls, 0, sizeof(dls)); for (int i = 0; i < DisplayListMaxCount; ++i) { dls[i].state = PSP_GE_DL_STATE_NONE; @@ -400,7 +398,7 @@ void GPUCommon::Reinitialize() { } nextListID = 0; - currentList = NULL; + currentList = nullptr; isbreak = false; drawCompleteTicks = 0; busyTicks = 0; @@ -440,7 +438,6 @@ int GPUCommon::EstimatePerVertexCost() { } void GPUCommon::PopDLQueue() { - easy_guard guard(listLock); if(!dlQueue.empty()) { dlQueue.pop_front(); if(!dlQueue.empty()) { @@ -457,7 +454,6 @@ void GPUCommon::PopDLQueue() { bool GPUCommon::BusyDrawing() { u32 state = DrawSync(1); if (state == PSP_GE_LIST_DRAWING || state == PSP_GE_LIST_STALLING) { - easy_guard guard(listLock); if (currentList && currentList->state != PSP_GE_DL_STATE_PAUSED) { return true; } @@ -479,7 +475,6 @@ u32 GPUCommon::DrawSync(int mode) { SyncThread(); } - easy_guard guard(listLock); if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; @@ -521,7 +516,6 @@ u32 GPUCommon::DrawSync(int mode) { } void GPUCommon::CheckDrawSync() { - easy_guard guard(listLock); if (dlQueue.empty()) { for (int i = 0; i < DisplayListMaxCount; ++i) dls[i].state = PSP_GE_DL_STATE_NONE; @@ -534,7 +528,6 @@ int GPUCommon::ListSync(int listid, int mode) { SyncThread(); } - easy_guard guard(listLock); if (listid < 0 || listid >= DisplayListMaxCount) return SCE_KERNEL_ERROR_INVALID_ID; @@ -579,8 +572,7 @@ int GPUCommon::ListSync(int listid, int mode) { } int GPUCommon::GetStack(int index, u32 stackPtr) { - easy_guard guard(listLock); - if (currentList == NULL) { + if (!currentList) { // Seems like it doesn't return an error code? return 0; } @@ -605,7 +597,6 @@ int GPUCommon::GetStack(int index, u32 stackPtr) { } u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) { - easy_guard guard(listLock); // TODO Check the stack values in missing arg and ajust the stack depth // Check alignment @@ -704,7 +695,6 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE) return SCE_KERNEL_ERROR_INVALID_ID; @@ -736,7 +725,6 @@ u32 GPUCommon::DequeueList(int listid) { } u32 GPUCommon::UpdateStall(int listid, u32 newstall) { - easy_guard guard(listLock); if (listid < 0 || listid >= DisplayListMaxCount || dls[listid].state == PSP_GE_DL_STATE_NONE) return SCE_KERNEL_ERROR_INVALID_ID; auto &dl = dls[listid]; @@ -745,14 +733,12 @@ u32 GPUCommon::UpdateStall(int listid, u32 newstall) { dl.stall = newstall & 0x0FFFFFFF; - guard.unlock(); ProcessDLQueue(); return 0; } u32 GPUCommon::Continue() { - easy_guard guard(listLock); if (!currentList) return 0; @@ -788,13 +774,11 @@ u32 GPUCommon::Continue() { return -1; } - guard.unlock(); ProcessDLQueue(); return 0; } u32 GPUCommon::Break(int mode) { - easy_guard guard(listLock); if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; @@ -883,8 +867,6 @@ bool GPUCommon::InterpretList(DisplayList &list) { start = time_now_d(); } - easy_guard guard(listLock); - if (list.state == PSP_GE_DL_STATE_PAUSED) return false; currentList = &list; @@ -908,14 +890,12 @@ bool GPUCommon::InterpretList(DisplayList &list) { list.interrupted = false; gpuState = list.pc == list.stall ? GPUSTATE_STALL : GPUSTATE_RUNNING; - guard.unlock(); debugRecording_ = GPURecord::IsActive(); const bool useDebugger = host->GPUDebuggingActive() || debugRecording_; const bool useFastRunLoop = !dumpThisFrame_ && !useDebugger; while (gpuState == GPUSTATE_RUNNING) { { - easy_guard innerGuard(listLock); if (list.pc == list.stall) { gpuState = GPUSTATE_STALL; downcount = 0; @@ -929,7 +909,6 @@ bool GPUCommon::InterpretList(DisplayList &list) { } { - easy_guard innerGuard(listLock); downcount = list.stall == 0 ? 0x0FFFFFFF : (list.stall - list.pc) / 4; if (gpuState == GPUSTATE_STALL && list.stall != list.pc) { @@ -1112,7 +1091,6 @@ void GPUCommon::ProcessEvent(GPUEvent ev) { } int GPUCommon::GetNextListIndex() { - easy_guard guard(listLock); auto iter = dlQueue.begin(); if (iter != dlQueue.end()) { return *iter; @@ -1143,8 +1121,6 @@ void GPUCommon::ProcessDLQueueInternal() { if (!InterpretList(l)) { return; } else { - easy_guard guard(listLock); - // Some other list could've taken the spot while we dilly-dallied around. if (l.state != PSP_GE_DL_STATE_QUEUED) { // At the end, we can remove it from the queue and continue. @@ -1154,8 +1130,7 @@ void GPUCommon::ProcessDLQueueInternal() { } } - easy_guard guard(listLock); - currentList = NULL; + currentList = nullptr; drawCompleteTicks = startingTicks + cyclesExecuted; busyTicks = std::max(busyTicks, drawCompleteTicks); @@ -1181,12 +1156,10 @@ void GPUCommon::Execute_Iaddr(u32 op, u32 diff) { } void GPUCommon::Execute_Origin(u32 op, u32 diff) { - easy_guard guard(listLock); gstate_c.offsetAddr = currentList->pc; } void GPUCommon::Execute_Jump(u32 op, u32 diff) { - easy_guard guard(listLock); const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); #ifdef _DEBUG if (!Memory::IsValidAddress(target)) { @@ -1201,7 +1174,6 @@ void GPUCommon::Execute_Jump(u32 op, u32 diff) { void GPUCommon::Execute_BJump(u32 op, u32 diff) { if (!currentList->bboxResult) { // bounding box jump. - easy_guard guard(listLock); const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); if (Memory::IsValidAddress(target)) { UpdatePC(currentList->pc, target - 4); @@ -1214,7 +1186,6 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) { void GPUCommon::Execute_Call(u32 op, u32 diff) { PROFILE_THIS_SCOPE("gpu_call"); - easy_guard guard(listLock); // Saint Seiya needs correct support for relative calls. const u32 retval = currentList->pc + 4; @@ -1253,7 +1224,6 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) { } void GPUCommon::Execute_Ret(u32 op, u32 diff) { - easy_guard guard(listLock); if (currentList->stackptr == 0) { DEBUG_LOG_REPORT(G3D, "RET: Stack empty!"); } else { @@ -1275,7 +1245,6 @@ void GPUCommon::Execute_Ret(u32 op, u32 diff) { void GPUCommon::Execute_End(u32 op, u32 diff) { Flush(); - easy_guard guard(listLock); const u32 prev = Memory::ReadUnchecked_U32(currentList->pc - 4); UpdatePC(currentList->pc, currentList->pc); // Count in a few extra cycles on END. @@ -1600,7 +1569,6 @@ void GPUCommon::Execute_WorldMtxNum(u32 op, u32 diff) { gstate.worldmtxnum = (GE_CMD_WORLDMATRIXNUMBER << 24) | ((op + count) & 0xF); // Skip over the loaded data, it's done now. - easy_guard innerGuard(listLock); UpdatePC(currentList->pc, currentList->pc + count * 4); currentList->pc += count * 4; } @@ -1648,7 +1616,6 @@ void GPUCommon::Execute_ViewMtxNum(u32 op, u32 diff) { gstate.viewmtxnum = (GE_CMD_VIEWMATRIXNUMBER << 24) | ((op + count) & 0xF); // Skip over the loaded data, it's done now. - easy_guard innerGuard(listLock); UpdatePC(currentList->pc, currentList->pc + count * 4); currentList->pc += count * 4; } @@ -1696,7 +1663,6 @@ void GPUCommon::Execute_ProjMtxNum(u32 op, u32 diff) { gstate.projmtxnum = (GE_CMD_PROJMATRIXNUMBER << 24) | ((op + count) & 0x1F); // Skip over the loaded data, it's done now. - easy_guard innerGuard(listLock); UpdatePC(currentList->pc, currentList->pc + count * 4); currentList->pc += count * 4; } @@ -1745,7 +1711,6 @@ void GPUCommon::Execute_TgenMtxNum(u32 op, u32 diff) { gstate.texmtxnum = (GE_CMD_TGENMATRIXNUMBER << 24) | ((op + count) & 0xF); // Skip over the loaded data, it's done now. - easy_guard innerGuard(listLock); UpdatePC(currentList->pc, currentList->pc + count * 4); currentList->pc += count * 4; } @@ -1812,7 +1777,6 @@ void GPUCommon::Execute_BoneMtxNum(u32 op, u32 diff) { gstate.boneMatrixNumber = (GE_CMD_BONEMATRIXNUMBER << 24) | ((op + count) & 0x7F); // Skip over the loaded data, it's done now. - easy_guard innerGuard(listLock); UpdatePC(currentList->pc, currentList->pc + count * 4); currentList->pc += count * 4; } @@ -2028,8 +1992,6 @@ struct DisplayList_v2 { }; void GPUCommon::DoState(PointerWrap &p) { - easy_guard guard(listLock); - auto s = p.Section("GPUCommon", 1, 4); if (!s) return; @@ -2108,7 +2070,6 @@ void GPUCommon::InterruptStart(int listid) { interruptRunning = true; } void GPUCommon::InterruptEnd(int listid) { - easy_guard guard(listLock); interruptRunning = false; isbreak = false; @@ -2124,13 +2085,11 @@ void GPUCommon::InterruptEnd(int listid) { __GeTriggerWait(GPU_SYNC_LIST, listid); } - guard.unlock(); ProcessDLQueue(); } // TODO: Maybe cleaner to keep this in GE and trigger the clear directly? void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) { - easy_guard guard(listLock); if (waitType == GPU_SYNC_DRAW && wokeThreads) { for (int i = 0; i < DisplayListMaxCount; ++i) { @@ -2142,7 +2101,6 @@ void GPUCommon::SyncEnd(GPUSyncType waitType, int listid, bool wokeThreads) { } bool GPUCommon::GetCurrentDisplayList(DisplayList &list) { - easy_guard guard(listLock); if (!currentList) { return false; } @@ -2153,7 +2111,6 @@ bool GPUCommon::GetCurrentDisplayList(DisplayList &list) { std::vector GPUCommon::ActiveDisplayLists() { std::vector result; - easy_guard guard(listLock); for (auto it = dlQueue.begin(), end = dlQueue.end(); it != end; ++it) { result.push_back(dls[*it]); } @@ -2167,7 +2124,6 @@ void GPUCommon::ResetListPC(int listID, u32 pc) { return; } - easy_guard guard(listLock); dls[listID].pc = pc; } @@ -2177,7 +2133,6 @@ void GPUCommon::ResetListStall(int listID, u32 stall) { return; } - easy_guard guard(listLock); dls[listID].stall = stall; } @@ -2187,7 +2142,6 @@ void GPUCommon::ResetListState(int listID, DisplayListState state) { return; } - easy_guard guard(listLock); dls[listID].state = state; } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 3d2430125d..752264b714 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -294,48 +294,6 @@ protected: void PerformStencilUploadInternal(u32 dest, int size); void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); - // This mutex can be disabled, which is useful for single core mode. - class optional_mutex { - public: - optional_mutex() : enabled_(true) {} - void set_enabled(bool enabled) { - enabled_ = enabled; - } - void lock() { - if (enabled_) - mutex_.lock(); - } - void unlock() { - if (enabled_) - mutex_.unlock(); - } - private: - std::mutex mutex_; - bool enabled_; - }; - - - // Allows early unlocking with a guard. Do not double unlock. - class easy_guard { - public: - easy_guard(optional_mutex &mtx) : mtx_(mtx), locked_(true) { mtx_.lock(); } - ~easy_guard() { - if (locked_) - mtx_.unlock(); - } - void unlock() { - if (locked_) - mtx_.unlock(); - else - Crash(); - locked_ = false; - } - - private: - optional_mutex &mtx_; - bool locked_; - }; - FramebufferManagerCommon *framebufferManager_; TextureCacheCommon *textureCache_; DrawEngineCommon *drawEngineCommon_; @@ -350,7 +308,6 @@ protected: DisplayList dls[DisplayListMaxCount]; DisplayList *currentList; DisplayListQueue dlQueue; - optional_mutex listLock; bool interruptRunning; GPURunState gpuState; From 5e63f0700ec087dab67797cf67298e91bbe3b8c4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 19:46:42 +0100 Subject: [PATCH 03/10] Get rid of the sync around curTickEst --- GPU/GPUCommon.cpp | 8 ++++---- GPU/GPUCommon.h | 32 +------------------------------- 2 files changed, 5 insertions(+), 35 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a90c119a6d..dff49ed0bb 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -404,7 +404,7 @@ void GPUCommon::Reinitialize() { busyTicks = 0; timeSpentStepping_ = 0.0; interruptsEnabled_ = true; - UpdateTickEstimate(0); + curTickEst_ = 0; ScheduleEvent(GPU_EVENT_REINITIALIZE); } @@ -1107,7 +1107,7 @@ bool GPUCommon::ProcessDLQueue() { void GPUCommon::ProcessDLQueueInternal() { startingTicks = CoreTiming::GetTicks(); cyclesExecuted = 0; - UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted)); + curTickEst_ = std::max(busyTicks, startingTicks + cyclesExecuted); // Seems to be correct behaviour to process the list anyway? if (startingTicks < busyTicks) { @@ -1126,7 +1126,7 @@ void GPUCommon::ProcessDLQueueInternal() { // At the end, we can remove it from the queue and continue. dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end()); } - UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted)); + curTickEst_ = std::max(busyTicks, startingTicks + cyclesExecuted); } } @@ -1136,7 +1136,7 @@ void GPUCommon::ProcessDLQueueInternal() { busyTicks = std::max(busyTicks, drawCompleteTicks); __GeTriggerSync(GPU_SYNC_DRAW, 1, drawCompleteTicks); // Since the event is in CoreTiming, we're in sync. Just set 0 now. - UpdateTickEstimate(0); + curTickEst_ = 0; } void GPUCommon::PreExecuteOp(u32 op, u32 diff) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 752264b714..2123a3eea7 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -143,17 +143,7 @@ public: inline void Flush(); u64 GetTickEstimate() override { -#if defined(_M_X64) || defined(__ANDROID__) return curTickEst_; -#elif defined(_M_SSE) - __m64 result = *(__m64 *)&curTickEst_; - u64 safeResult = *(u64 *)&result; - _mm_empty(); - return safeResult; -#else - std::lock_guard guard(curTickEstLock_); - return curTickEst_; -#endif } #ifdef USE_CRT_DBG @@ -329,27 +319,7 @@ protected: GEPrimitiveType lastPrim_; private: - - // For CPU/GPU sync. -#ifdef __ANDROID__ - alignas(16) std::atomic curTickEst_; -#else - alignas(16) volatile u64 curTickEst_; - std::mutex curTickEstLock_; -#endif - - inline void UpdateTickEstimate(u64 value) { -#if defined(_M_X64) || defined(__ANDROID__) - curTickEst_ = value; -#elif defined(_M_SSE) - __m64 result = *(__m64 *)&value; - *(__m64 *)&curTickEst_ = result; - _mm_empty(); -#else - std::lock_guard guard(curTickEstLock_); - curTickEst_ = value; -#endif - } + u64 curTickEst_; // Debug stats. double timeSteppingStarted_; From 26e52ca5e823d3930c4fb9e31c2c36fec3d7a840 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 20:10:05 +0100 Subject: [PATCH 04/10] Get rid of a bunch of sync stuff that's no longer needed. --- Core/HLE/sceGe.cpp | 5 +---- Core/System.cpp | 23 +++-------------------- GPU/D3D11/DrawEngineD3D11.h | 4 +++- GPU/D3D11/GPU_D3D11.cpp | 16 +--------------- GPU/Directx9/GPU_DX9.cpp | 16 +--------------- GPU/GLES/GPU_GLES.cpp | 10 ---------- GPU/GPUCommon.cpp | 19 +++++-------------- GPU/GPUCommon.h | 25 +++++++------------------ GPU/GPUInterface.h | 7 ------- GPU/Null/NullGpu.h | 1 + GPU/Software/SoftGpu.cpp | 1 + GPU/Software/SoftGpu.h | 3 ++- GPU/Vulkan/GPU_Vulkan.cpp | 10 ---------- 13 files changed, 25 insertions(+), 115 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 25aaa6848a..d72ebe4a26 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -193,13 +193,12 @@ static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) { __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_GE_INTR, PSP_INTR_SUB_NONE); } +// Should we still do this? static void __GeCheckCycles(u64 userdata, int cyclesLate) { u64 geTicks = gpu->GetTickEstimate(); if (geTicks != 0) { if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) { u64 diff = CoreTiming::GetTicks() - geTicks; - // Let the GPU thread catch up. - gpu->SyncThread(); CoreTiming::Advance(); } } @@ -504,7 +503,6 @@ static int sceGeUnsetCallback(u32 cbID) { // unless some insane game pokes it and relies on it... u32 sceGeSaveContext(u32 ctxAddr) { DEBUG_LOG(SCEGE, "sceGeSaveContext(%08x)", ctxAddr); - gpu->SyncThread(); if (gpu->BusyDrawing()) { WARN_LOG(SCEGE, "sceGeSaveContext(%08x): lists in process, aborting", ctxAddr); @@ -524,7 +522,6 @@ u32 sceGeSaveContext(u32 ctxAddr) { u32 sceGeRestoreContext(u32 ctxAddr) { DEBUG_LOG(SCEGE, "sceGeRestoreContext(%08x)", ctxAddr); - gpu->SyncThread(); if (gpu->BusyDrawing()) { WARN_LOG(SCEGE, "sceGeRestoreContext(%08x): lists in process, aborting", ctxAddr); diff --git a/Core/System.cpp b/Core/System.cpp index 6f7069f1f2..1ec7ae54aa 100644 --- a/Core/System.cpp +++ b/Core/System.cpp @@ -328,7 +328,6 @@ void CPU_RunLoop() { switch (cpuThreadState) { case CPU_THREAD_EXECUTE: mipsr4k.RunLoopUntil(cpuThreadUntil); - gpu->FinishEventLoop(); CPU_NextState(CPU_THREAD_EXECUTE, CPU_THREAD_RUNNING); break; @@ -354,12 +353,6 @@ void CPU_RunLoop() { coreState = CORE_POWERDOWN; } - // Let's make sure the gpu has already cleaned up before we start freeing memory. - if (gpu) { - gpu->FinishEventLoop(); - gpu->SyncThread(true); - } - CPU_Shutdown(); CPU_SetState(CPU_THREAD_NOT_RUNNING); } @@ -384,9 +377,6 @@ static void Core_UpdateDebugStats(bool flag) { void System_Wake() { // Ping the threads so they check coreState. CPU_NextStateNot(CPU_THREAD_NOT_RUNNING, CPU_THREAD_SHUTDOWN); - if (gpu) { - gpu->FinishEventLoop(); - } } // Ugly! @@ -545,9 +535,8 @@ void PSP_RunLoopUntil(u64 globalticks) { cpuThread = new std::thread(&CPU_RunLoop); cpuThreadID = cpuThread->get_id(); cpuThread->detach(); - if (gpu) { - gpu->SetThreadEnabled(true); - } + // Probably needs to tell the gpu that it will need to queue up its output + // on another thread. CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); } else if (!useCPUThread && cpuThread != nullptr) { CPU_SetState(CPU_THREAD_QUIT); @@ -555,21 +544,15 @@ void PSP_RunLoopUntil(u64 globalticks) { delete cpuThread; cpuThread = nullptr; cpuThreadID = std::thread::id(); - if (gpu) { - gpu->SetThreadEnabled(false); - } } if (cpuThread != nullptr) { - // Tell the gpu a new frame is about to begin, before we start the CPU. - gpu->SyncBeginFrame(); - cpuThreadUntil = globalticks; if (CPU_NextState(CPU_THREAD_RUNNING, CPU_THREAD_EXECUTE)) { // The CPU doesn't actually respect cpuThreadUntil well, especially when skipping frames. // TODO: Something smarter? Or force CPU to bail periodically? while (!CPU_IsReady()) { - gpu->RunEventsUntil(CoreTiming::GetTicks() + msToCycles(1000)); + // Have the GPU do stuff here. if (coreState != CORE_RUNNING) { CPU_WaitStatus(cpuThreadReplyCond, &CPU_IsReady); } diff --git a/GPU/D3D11/DrawEngineD3D11.h b/GPU/D3D11/DrawEngineD3D11.h index 7175a78e61..48b52063bf 100644 --- a/GPU/D3D11/DrawEngineD3D11.h +++ b/GPU/D3D11/DrawEngineD3D11.h @@ -17,6 +17,7 @@ #pragma once +#include #include #include @@ -190,7 +191,8 @@ private: PushBufferD3D11 *pushVerts_; PushBufferD3D11 *pushInds_; - // D3D11 state object caches + // D3D11 state object caches. + // TODO: Change them to DenseHashMaps. std::map blendCache_; std::map blendCache1_; std::map depthStencilCache_; diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index cc3f06f16e..aa281e3b67 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -338,13 +338,6 @@ void GPU_D3D11::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat f } bool GPU_D3D11::FramebufferDirty() { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - if (ThreadEnabled()) { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; @@ -353,15 +346,8 @@ bool GPU_D3D11::FramebufferDirty() { } return true; } -bool GPU_D3D11::FramebufferReallyDirty() { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - if (ThreadEnabled()) { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } +bool GPU_D3D11::FramebufferReallyDirty() { VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 0dd93e7137..e9af77b1d1 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -304,13 +304,6 @@ void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat for } bool GPU_DX9::FramebufferDirty() { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - if (ThreadEnabled()) { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; @@ -319,15 +312,8 @@ bool GPU_DX9::FramebufferDirty() { } return true; } -bool GPU_DX9::FramebufferReallyDirty() { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - if (ThreadEnabled()) { - // FIXME: Workaround for displaylists sometimes hanging unprocessed. Not yet sure of the cause. - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } +bool GPU_DX9::FramebufferReallyDirty() { VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b7d25debd3..d8b3829305 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -504,11 +504,6 @@ void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat fo } bool GPU_GLES::FramebufferDirty() { - if (ThreadEnabled()) { - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } - VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; @@ -519,11 +514,6 @@ bool GPU_GLES::FramebufferDirty() { } bool GPU_GLES::FramebufferReallyDirty() { - if (ThreadEnabled()) { - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } - VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index dff49ed0bb..a7270edf2f 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -362,7 +362,6 @@ GPUCommon::GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw) : Reinitialize(); SetupColorConv(); - SetThreadEnabled(false); gstate.Reset(); gstate_c.Reset(); gpuStats.Reset(); @@ -408,6 +407,11 @@ void GPUCommon::Reinitialize() { ScheduleEvent(GPU_EVENT_REINITIALIZE); } +void GPUCommon::ScheduleEvent(GPUEventType event) { + // Queue is gone, we now process events immediately. + ProcessEvent(event); +} + int GPUCommon::EstimatePerVertexCost() { // TODO: This is transform cost, also account for rasterization cost somehow... although it probably // runs in parallel with transform. @@ -470,11 +474,6 @@ void GPUCommon::DumpNextFrame() { } u32 GPUCommon::DrawSync(int mode) { - if (ThreadEnabled()) { - // Sync first, because the CPU is usually faster than the emulated GPU. - SyncThread(); - } - if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; @@ -523,11 +522,6 @@ void GPUCommon::CheckDrawSync() { } int GPUCommon::ListSync(int listid, int mode) { - if (ThreadEnabled()) { - // Sync first, because the CPU is usually faster than the emulated GPU. - SyncThread(); - } - if (listid < 0 || listid >= DisplayListMaxCount) return SCE_KERNEL_ERROR_INVALID_ID; @@ -2319,9 +2313,6 @@ bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { ev.fb_memcpy.src = src; ev.fb_memcpy.size = size; ScheduleEvent(ev); - - // This is a memcpy, so we need to wait for it to complete. - SyncThread(); } else { PerformMemoryCopyInternal(dest, src, size); } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 2123a3eea7..434fbeda3d 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -2,7 +2,6 @@ #include "Common/Common.h" #include "Common/MemoryUtil.h" -#include "Core/ThreadEventQueue.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" #include "GPU/Common/GPUDebugInterface.h" @@ -15,8 +14,6 @@ #include #endif -typedef ThreadEventQueue GPUThreadEventQueue; - class FramebufferManagerCommon; class TextureCacheCommon; class DrawEngineCommon; @@ -42,7 +39,7 @@ enum { FLAG_DIRTYONCHANGE = 64, // NOTE: Either this or FLAG_EXECUTE*, not both! }; -class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface { +class GPUCommon : public GPUInterface, public GPUDebugInterface { public: GPUCommon(GraphicsContext *gfxCtx, Draw::DrawContext *draw); virtual ~GPUCommon(); @@ -77,14 +74,6 @@ public: u32 DrawSync(int mode) override; int GetStack(int index, u32 stackPtr) override; void DoState(PointerWrap &p) override; - bool FramebufferDirty() override { - SyncThread(); - return true; - } - bool FramebufferReallyDirty() override { - SyncThread(); - return true; - } bool BusyDrawing() override; u32 Continue() override; u32 Break(int mode) override; @@ -261,12 +250,12 @@ protected: void ProcessDLQueueInternal(); virtual void ReapplyGfxStateInternal(); virtual void FastLoadBoneMatrix(u32 target); - void ProcessEvent(GPUEvent ev) override; - bool ShouldExitEventLoop() override { - return coreState != CORE_RUNNING; - } - virtual void FinishDeferred() { - } + + void ScheduleEvent(GPUEventType event); + void ProcessEvent(GPUEvent ev); + + // TODO: Unify this. + virtual void FinishDeferred() {} void DoBlockTransfer(u32 skipDrawReason); diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 5faf3540bb..3c21e45298 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -225,10 +225,6 @@ public: virtual void BeginHostFrame() = 0; virtual void EndHostFrame() = 0; - // Events - virtual void RunEventsUntil(u64 globalticks) = 0; - virtual void FinishEventLoop() = 0; - // Draw queue management virtual DisplayList* getList(int listid) = 0; // TODO: Much of this should probably be shared between the different GPU implementations. @@ -277,8 +273,6 @@ public: virtual void DeviceLost() = 0; virtual void DeviceRestore() = 0; virtual void ReapplyGfxState() = 0; - virtual void SyncThread(bool force = false) = 0; - virtual void SyncBeginFrame() = 0; virtual u64 GetTickEstimate() = 0; virtual void DoState(PointerWrap &p) = 0; @@ -289,7 +283,6 @@ public: virtual bool FramebufferDirty() = 0; virtual bool FramebufferReallyDirty() = 0; virtual bool BusyDrawing() = 0; - virtual void SetThreadEnabled(bool threadEnabled) = 0; // If any jit is being used inside the GPU. virtual bool DescribeCodePtr(const u8 *ptr, std::string &name) = 0; diff --git a/GPU/Null/NullGpu.h b/GPU/Null/NullGpu.h index ae31ce3024..59b920723c 100644 --- a/GPU/Null/NullGpu.h +++ b/GPU/Null/NullGpu.h @@ -40,6 +40,7 @@ public: bool PerformMemoryUpload(u32 dest, int size) override; bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override {} + bool FramebufferDirty() override { return true; } void DeviceLost() override {} void DeviceRestore() override {} diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 89b8383fb0..9d84af6385 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -28,6 +28,7 @@ #include "Core/HLE/sceGe.h" #include "Core/MIPS/MIPS.h" #include "Core/Reporting.h" +#include "Core/Core.h" #include "profiler/profiler.h" #include "thin3d/thin3d.h" diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 25c21da0ec..664e3d74f7 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -94,7 +94,8 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; + void ScheduleEvent(GPUEvent ev) { ProcessEvent(ev); } + void ProcessEvent(GPUEvent ev); void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight); private: diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index cfaae884f3..3513f5d755 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -370,11 +370,6 @@ void GPU_Vulkan::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat } bool GPU_Vulkan::FramebufferDirty() { - if (ThreadEnabled()) { - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; @@ -385,11 +380,6 @@ bool GPU_Vulkan::FramebufferDirty() { } bool GPU_Vulkan::FramebufferReallyDirty() { - if (ThreadEnabled()) { - // Allow it to process fully before deciding if it's dirty. - SyncThread(); - } - VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; From 6680e787dea0cbce1fed734464b4fb4a09a051ed Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 20:15:57 +0100 Subject: [PATCH 05/10] Delete GPUCommon::ScheduleEvent --- GPU/GPUCommon.cpp | 61 +++++++++-------------------------------------- GPU/GPUCommon.h | 1 - 2 files changed, 11 insertions(+), 51 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index a7270edf2f..3953b33e0a 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -382,11 +382,11 @@ void GPUCommon::EndHostFrame() { } void GPUCommon::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); + InitClearInternal(); } void GPUCommon::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); + CopyDisplayToOutputInternal(); } void GPUCommon::Reinitialize() { @@ -404,12 +404,7 @@ void GPUCommon::Reinitialize() { timeSpentStepping_ = 0.0; interruptsEnabled_ = true; curTickEst_ = 0; - ScheduleEvent(GPU_EVENT_REINITIALIZE); -} - -void GPUCommon::ScheduleEvent(GPUEventType event) { - // Queue is gone, we now process events immediately. - ProcessEvent(event); + ReinitializeInternal(); } int GPUCommon::EstimatePerVertexCost() { @@ -450,7 +445,7 @@ void GPUCommon::PopDLQueue() { if (running) currentList->state = PSP_GE_DL_STATE_RUNNING; } else { - currentList = NULL; + currentList = nullptr; } } } @@ -932,7 +927,7 @@ bool GPUCommon::InterpretList(DisplayList &list) { } void GPUCommon::BeginFrame() { - ScheduleEvent(GPU_EVENT_BEGIN_FRAME); + BeginFrameInternal(); } void GPUCommon::BeginFrameInternal() { @@ -999,11 +994,7 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) { } void GPUCommon::ReapplyGfxState() { - if (IsOnSeparateCPUThread()) { - ScheduleEvent(GPU_EVENT_REAPPLY_GFX_STATE); - } else { - ReapplyGfxStateInternal(); - } + ReapplyGfxStateInternal(); } void GPUCommon::ReapplyGfxStateInternal() { @@ -1094,7 +1085,7 @@ int GPUCommon::GetNextListIndex() { } bool GPUCommon::ProcessDLQueue() { - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); + ProcessDLQueueInternal(); return true; } @@ -2307,15 +2298,7 @@ void GPUCommon::PerformMemorySetInternal(u32 dest, u8 v, int size) { bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { // Track stray copies of a framebuffer in RAM. MotoGP does this. if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) { - if (IsOnSeparateCPUThread()) { - GPUEvent ev(GPU_EVENT_FB_MEMCPY); - ev.fb_memcpy.dst = dest; - ev.fb_memcpy.src = src; - ev.fb_memcpy.size = size; - ScheduleEvent(ev); - } else { - PerformMemoryCopyInternal(dest, src, size); - } + PerformMemoryCopyInternal(dest, src, size); return true; } @@ -2328,18 +2311,7 @@ bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) { // This may indicate a memset, usually to 0, of a framebuffer. if (framebufferManager_->MayIntersectFramebuffer(dest)) { Memory::Memset(dest, v, size); - - if (IsOnSeparateCPUThread()) { - GPUEvent ev(GPU_EVENT_FB_MEMSET); - ev.fb_memset.dst = dest; - ev.fb_memset.v = v; - ev.fb_memset.size = size; - ScheduleEvent(ev); - - // We don't need to wait for the framebuffer to be updated. - } else { - PerformMemorySetInternal(dest, v, size); - } + PerformMemorySetInternal(dest, v, size); return true; } @@ -2369,11 +2341,7 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) { } void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { - GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE); - ev.invalidate_cache.addr = addr; - ev.invalidate_cache.size = size; - ev.invalidate_cache.type = type; - ScheduleEvent(ev); + InvalidateCacheInternal(addr, size, type); } void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { @@ -2401,14 +2369,7 @@ void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) { bool GPUCommon::PerformStencilUpload(u32 dest, int size) { if (framebufferManager_->MayIntersectFramebuffer(dest)) { - if (IsOnSeparateCPUThread()) { - GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD); - ev.fb_stencil_upload.dst = dest; - ev.fb_stencil_upload.size = size; - ScheduleEvent(ev); - } else { - PerformStencilUploadInternal(dest, size); - } + PerformStencilUploadInternal(dest, size); return true; } return false; diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 434fbeda3d..2a8a9c7742 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -251,7 +251,6 @@ protected: virtual void ReapplyGfxStateInternal(); virtual void FastLoadBoneMatrix(u32 target); - void ScheduleEvent(GPUEventType event); void ProcessEvent(GPUEvent ev); // TODO: Unify this. From bb68906d884b7c30dd5d34bd6ec93881c0767e4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 20:19:42 +0100 Subject: [PATCH 06/10] Delete ProcessEvent and the GPUEvent enum --- GPU/GPUCommon.cpp | 47 ------------------------------------- GPU/GPUCommon.h | 2 -- GPU/GPUInterface.h | 50 ---------------------------------------- GPU/Software/SoftGpu.cpp | 13 +---------- GPU/Software/SoftGpu.h | 2 -- 5 files changed, 1 insertion(+), 113 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 3953b33e0a..fea82012f5 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1028,53 +1028,6 @@ inline void GPUCommon::UpdateState(GPURunState state) { downcount = 0; } -void GPUCommon::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - case GPU_EVENT_PROCESS_QUEUE: - ProcessDLQueueInternal(); - break; - - case GPU_EVENT_REAPPLY_GFX_STATE: - ReapplyGfxStateInternal(); - break; - - case GPU_EVENT_INIT_CLEAR: - InitClearInternal(); - break; - - case GPU_EVENT_BEGIN_FRAME: - BeginFrameInternal(); - break; - - case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT: - CopyDisplayToOutputInternal(); - break; - - case GPU_EVENT_INVALIDATE_CACHE: - InvalidateCacheInternal(ev.invalidate_cache.addr, ev.invalidate_cache.size, ev.invalidate_cache.type); - break; - - case GPU_EVENT_FB_MEMCPY: - PerformMemoryCopyInternal(ev.fb_memcpy.dst, ev.fb_memcpy.src, ev.fb_memcpy.size); - break; - - case GPU_EVENT_FB_MEMSET: - PerformMemorySetInternal(ev.fb_memset.dst, ev.fb_memset.v, ev.fb_memset.size); - break; - - case GPU_EVENT_FB_STENCIL_UPLOAD: - PerformStencilUploadInternal(ev.fb_stencil_upload.dst, ev.fb_stencil_upload.size); - break; - - case GPU_EVENT_REINITIALIZE: - break; - - default: - ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev); - break; - } -} - int GPUCommon::GetNextListIndex() { auto iter = dlQueue.begin(); if (iter != dlQueue.end()) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 2a8a9c7742..0737171a90 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -251,8 +251,6 @@ protected: virtual void ReapplyGfxStateInternal(); virtual void FastLoadBoneMatrix(u32 target); - void ProcessEvent(GPUEvent ev); - // TODO: Unify this. virtual void FinishDeferred() {} diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 3c21e45298..a8dfc780c3 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -155,56 +155,6 @@ enum GPUInvalidationType { GPU_INVALIDATE_SAFE, }; -enum GPUEventType { - GPU_EVENT_INVALID, - GPU_EVENT_PROCESS_QUEUE, - GPU_EVENT_INIT_CLEAR, - GPU_EVENT_BEGIN_FRAME, - GPU_EVENT_COPY_DISPLAY_TO_OUTPUT, - GPU_EVENT_REAPPLY_GFX_STATE, - GPU_EVENT_INVALIDATE_CACHE, - GPU_EVENT_FINISH_EVENT_LOOP, - GPU_EVENT_SYNC_THREAD, - GPU_EVENT_FB_MEMCPY, - GPU_EVENT_FB_MEMSET, - GPU_EVENT_FB_STENCIL_UPLOAD, - GPU_EVENT_REINITIALIZE, -}; - -struct GPUEvent { - GPUEvent(GPUEventType t) : type(t) {} - GPUEventType type; - union { - // GPU_EVENT_INVALIDATE_CACHE - struct { - u32 addr; - int size; - GPUInvalidationType type; - } invalidate_cache; - // GPU_EVENT_FB_MEMCPY - struct { - u32 dst; - u32 src; - int size; - } fb_memcpy; - // GPU_EVENT_FB_MEMSET - struct { - u32 dst; - u8 v; - int size; - } fb_memset; - // GPU_EVENT_FB_STENCIL_UPLOAD - struct { - u32 dst; - int size; - } fb_stencil_upload; - }; - - operator GPUEventType() const { - return type; - } -}; - namespace Draw { class DrawContext; } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 9d84af6385..588df982da 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -283,7 +283,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { void SoftGPU::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); + CopyDisplayToOutputInternal(); } void SoftGPU::CopyDisplayToOutputInternal() @@ -302,17 +302,6 @@ void SoftGPU::CopyDisplayToOutputInternal() } } -void SoftGPU::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - case GPU_EVENT_COPY_DISPLAY_TO_OUTPUT: - CopyDisplayToOutputInternal(); - break; - - default: - GPUCommon::ProcessEvent(ev); - } -} - void SoftGPU::FastRunLoop(DisplayList &list) { PROFILE_THIS_SCOPE("soft_runloop"); for (; downcount > 0; --downcount) { diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 664e3d74f7..627b2acd52 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -94,8 +94,6 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ScheduleEvent(GPUEvent ev) { ProcessEvent(ev); } - void ProcessEvent(GPUEvent ev); void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight); private: From 8c69be9bfa98c7c12418e7e5d40231630a764c47 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 20:33:28 +0100 Subject: [PATCH 07/10] Get rid of GPUCommon's "Internal" functions. --- GPU/D3D11/GPU_D3D11.cpp | 12 +++---- GPU/D3D11/GPU_D3D11.h | 8 ++--- GPU/Directx9/GPU_DX9.cpp | 12 +++---- GPU/Directx9/GPU_DX9.h | 8 ++--- GPU/GLES/GPU_GLES.cpp | 15 ++++----- GPU/GLES/GPU_GLES.h | 10 +++--- GPU/GPUCommon.cpp | 66 +++++++++------------------------------ GPU/GPUCommon.h | 21 ++----------- GPU/Software/SoftGpu.cpp | 8 +---- GPU/Software/SoftGpu.h | 2 -- GPU/Vulkan/GPU_Vulkan.cpp | 14 +++------ GPU/Vulkan/GPU_Vulkan.h | 6 ++-- 12 files changed, 59 insertions(+), 123 deletions(-) diff --git a/GPU/D3D11/GPU_D3D11.cpp b/GPU/D3D11/GPU_D3D11.cpp index aa281e3b67..847fbf09c1 100644 --- a/GPU/D3D11/GPU_D3D11.cpp +++ b/GPU/D3D11/GPU_D3D11.cpp @@ -286,7 +286,7 @@ void GPU_D3D11::DeviceRestore() { // Nothing needed. } -void GPU_D3D11::InitClearInternal() { +void GPU_D3D11::InitClear() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { // device_->Clear(0, NULL, D3DCLEAR_STENCIL | D3DCLEAR_TARGET | D3DCLEAR_ZBUFFER, D3DCOLOR_XRGB(0, 0, 0), 1.f, 0); @@ -305,8 +305,8 @@ void GPU_D3D11::BeginHostFrame() { } } -void GPU_D3D11::ReapplyGfxStateInternal() { - GPUCommon::ReapplyGfxStateInternal(); +void GPU_D3D11::ReapplyGfxState() { + GPUCommon::ReapplyGfxState(); // TODO: Dirty our caches for depth states etc } @@ -316,8 +316,8 @@ void GPU_D3D11::EndHostFrame() { draw_->BindPipeline(nullptr); } -void GPU_D3D11::BeginFrameInternal() { - GPUCommon::BeginFrameInternal(); +void GPU_D3D11::BeginFrame() { + GPUCommon::BeginFrame(); textureCacheD3D11_->StartFrame(); drawEngine_.BeginFrame(); @@ -357,7 +357,7 @@ bool GPU_D3D11::FramebufferReallyDirty() { return true; } -void GPU_D3D11::CopyDisplayToOutputInternal() { +void GPU_D3D11::CopyDisplayToOutput() { float blendColor[4]{}; context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0xF], blendColor, 0xFFFFFFFF); diff --git a/GPU/D3D11/GPU_D3D11.h b/GPU/D3D11/GPU_D3D11.h index c83bc35534..a528d41169 100644 --- a/GPU/D3D11/GPU_D3D11.h +++ b/GPU/D3D11/GPU_D3D11.h @@ -40,7 +40,7 @@ public: void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxStateInternal() override; + void ReapplyGfxState() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void GetStats(char *buffer, size_t bufsize) override; void ClearCacheNextFrame() override; @@ -96,9 +96,9 @@ private: void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal() override; - void BeginFrameInternal() override; - void CopyDisplayToOutputInternal() override; + void InitClear() override; + void BeginFrame() override; + void CopyDisplayToOutput() override; ID3D11Device *device_; ID3D11DeviceContext *context_; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index e9af77b1d1..df33d8e41b 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -251,7 +251,7 @@ void GPU_DX9::DeviceRestore() { // Nothing needed. } -void GPU_DX9::InitClearInternal() { +void GPU_DX9::InitClear() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { dxstate.depthWrite.set(true); @@ -272,12 +272,12 @@ void GPU_DX9::BeginHostFrame() { } } -void GPU_DX9::ReapplyGfxStateInternal() { +void GPU_DX9::ReapplyGfxState() { dxstate.Restore(); - GPUCommon::ReapplyGfxStateInternal(); + GPUCommon::ReapplyGfxState(); } -void GPU_DX9::BeginFrameInternal() { +void GPU_DX9::BeginFrame() { // Turn off vsync when unthrottled int desiredVSyncInterval = g_Config.bVSync ? 1 : 0; if ((PSP_CoreParameter().unthrottle) || (PSP_CoreParameter().fpsLimit == 1)) @@ -292,7 +292,7 @@ void GPU_DX9::BeginFrameInternal() { depalShaderCache_.Decimate(); // fragmentTestCache_.Decimate(); - GPUCommon::BeginFrameInternal(); + GPUCommon::BeginFrame(); shaderManagerDX9_->DirtyShader(); framebufferManager_->BeginFrame(); @@ -323,7 +323,7 @@ bool GPU_DX9::FramebufferReallyDirty() { return true; } -void GPU_DX9::CopyDisplayToOutputInternal() { +void GPU_DX9::CopyDisplayToOutput() { dxstate.depthWrite.set(true); dxstate.colorMask.set(true, true, true, true); diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 72e76267ff..2f15d48197 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -41,7 +41,7 @@ public: void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxStateInternal() override; + void ReapplyGfxState() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void GetStats(char *buffer, size_t bufsize) override; void ClearCacheNextFrame() override; @@ -96,9 +96,9 @@ private: void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal() override; - void BeginFrameInternal() override; - void CopyDisplayToOutputInternal() override; + void InitClear() override; + void BeginFrame() override; + void CopyDisplayToOutput() override; LPDIRECT3DDEVICE9 device_; LPDIRECT3DDEVICE9EX deviceEx_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index d8b3829305..f12245778c 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -401,13 +401,14 @@ void GPU_GLES::DeviceRestore() { UpdateVsyncInterval(true); } -void GPU_GLES::ReinitializeInternal() { +void GPU_GLES::Reinitialize() { + GPUCommon::Reinitialize(); textureCacheGL_->Clear(true); depalShaderCache_.Clear(); framebufferManagerGL_->DestroyAllFBOs(); } -void GPU_GLES::InitClearInternal() { +void GPU_GLES::InitClear() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { glstate.depthWrite.set(GL_TRUE); @@ -467,13 +468,13 @@ void GPU_GLES::UpdateCmdInfo() { } } -void GPU_GLES::ReapplyGfxStateInternal() { +void GPU_GLES::ReapplyGfxState() { drawEngine_.RestoreVAO(); glstate.Restore(); - GPUCommon::ReapplyGfxStateInternal(); + GPUCommon::ReapplyGfxState(); } -void GPU_GLES::BeginFrameInternal() { +void GPU_GLES::BeginFrame() { UpdateVsyncInterval(resized_); resized_ = false; @@ -483,7 +484,7 @@ void GPU_GLES::BeginFrameInternal() { depalShaderCache_.Decimate(); fragmentTestCache_.Decimate(); - GPUCommon::BeginFrameInternal(); + GPUCommon::BeginFrame(); // Save the cache from time to time. TODO: How often? if (!shaderCachePath_.empty() && (gpuStats.numFlips & 1023) == 0) { @@ -523,7 +524,7 @@ bool GPU_GLES::FramebufferReallyDirty() { return true; } -void GPU_GLES::CopyDisplayToOutputInternal() { +void GPU_GLES::CopyDisplayToOutput() { // Flush anything left over. framebufferManagerGL_->RebindFramebuffer(); drawEngine_.Flush(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index e15a26c4d8..a9662cf271 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -41,7 +41,7 @@ public: void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxStateInternal() override; + void ReapplyGfxState() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void GetStats(char *buffer, size_t bufsize) override; @@ -95,10 +95,10 @@ private: void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal() override; - void BeginFrameInternal() override; - void CopyDisplayToOutputInternal() override; - void ReinitializeInternal() override; + void InitClear() override; + void BeginFrame() override; + void CopyDisplayToOutput() override; + void Reinitialize() override; inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index fea82012f5..8ecf357fa3 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -381,14 +381,6 @@ void GPUCommon::EndHostFrame() { } -void GPUCommon::InitClear() { - InitClearInternal(); -} - -void GPUCommon::CopyDisplayToOutput() { - CopyDisplayToOutputInternal(); -} - void GPUCommon::Reinitialize() { memset(dls, 0, sizeof(dls)); for (int i = 0; i < DisplayListMaxCount; ++i) { @@ -404,7 +396,6 @@ void GPUCommon::Reinitialize() { timeSpentStepping_ = 0.0; interruptsEnabled_ = true; curTickEst_ = 0; - ReinitializeInternal(); } int GPUCommon::EstimatePerVertexCost() { @@ -927,10 +918,6 @@ bool GPUCommon::InterpretList(DisplayList &list) { } void GPUCommon::BeginFrame() { - BeginFrameInternal(); -} - -void GPUCommon::BeginFrameInternal() { if (dumpNextFrame_) { NOTICE_LOG(G3D, "DUMPING THIS FRAME"); dumpThisFrame_ = true; @@ -994,10 +981,6 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) { } void GPUCommon::ReapplyGfxState() { - ReapplyGfxStateInternal(); -} - -void GPUCommon::ReapplyGfxStateInternal() { // The commands are embedded in the command memory so we can just reexecute the words. Convenient. // To be safe we pass 0xFFFFFFFF as the diff. @@ -1037,12 +1020,7 @@ int GPUCommon::GetNextListIndex() { } } -bool GPUCommon::ProcessDLQueue() { - ProcessDLQueueInternal(); - return true; -} - -void GPUCommon::ProcessDLQueueInternal() { +void GPUCommon::ProcessDLQueue() { startingTicks = CoreTiming::GetTicks(); cyclesExecuted = 0; curTickEst_ = std::max(busyTicks, startingTicks + cyclesExecuted); @@ -1326,7 +1304,7 @@ void GPUCommon::Execute_End(u32 op, u32 diff) { __GeTriggerSync(GPU_SYNC_LIST, currentList->id, currentList->waitTicks); if (currentList->started && currentList->context.IsValid()) { gstate.Restore(currentList->context); - ReapplyGfxStateInternal(); + ReapplyGfxState(); } } break; @@ -2231,27 +2209,17 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { cyclesExecuted += ((height * width * bpp) * 16) / 10; } -void GPUCommon::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { - // We use a little hack for Download/Upload using a VRAM mirror. - // Since they're identical we don't need to copy. - if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) { - Memory::Memcpy(dest, src, size); - } - } - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); -} - -void GPUCommon::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - bool GPUCommon::PerformMemoryCopy(u32 dest, u32 src, int size) { // Track stray copies of a framebuffer in RAM. MotoGP does this. if (framebufferManager_->MayIntersectFramebuffer(src) || framebufferManager_->MayIntersectFramebuffer(dest)) { - PerformMemoryCopyInternal(dest, src, size); + if (!framebufferManager_->NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { + // We use a little hack for Download/Upload using a VRAM mirror. + // Since they're identical we don't need to copy. + if (!Memory::IsVRAMAddress(dest) || (dest ^ 0x00400000) != src) { + Memory::Memcpy(dest, src, size); + } + } + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); return true; } @@ -2264,7 +2232,9 @@ bool GPUCommon::PerformMemorySet(u32 dest, u8 v, int size) { // This may indicate a memset, usually to 0, of a framebuffer. if (framebufferManager_->MayIntersectFramebuffer(dest)) { Memory::Memset(dest, v, size); - PerformMemorySetInternal(dest, v, size); + if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + } return true; } @@ -2294,10 +2264,6 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) { } void GPUCommon::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { - InvalidateCacheInternal(addr, size, type); -} - -void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { if (size > 0) textureCache_->Invalidate(addr, size, type); else @@ -2322,16 +2288,12 @@ void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) { bool GPUCommon::PerformStencilUpload(u32 dest, int size) { if (framebufferManager_->MayIntersectFramebuffer(dest)) { - PerformStencilUploadInternal(dest, size); + framebufferManager_->NotifyStencilUpload(dest, size); return true; } return false; } -void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_->NotifyStencilUpload(dest, size); -} - bool GPUCommon::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManager_->DisplayFramebufAddr(); int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManager_->DisplayFramebufStride(); diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 0737171a90..c1310ae8fc 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -66,7 +66,7 @@ public: void PreExecuteOp(u32 op, u32 diff) override; bool InterpretList(DisplayList &list) override; - virtual bool ProcessDLQueue(); + void ProcessDLQueue(); u32 UpdateStall(int listid, u32 newstall) override; u32 EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer args, bool head) override; u32 DequeueList(int listid) override; @@ -79,8 +79,8 @@ public: u32 Break(int mode) override; void ReapplyGfxState() override; - void CopyDisplayToOutput() override; - void InitClear() override; + void CopyDisplayToOutput() override = 0; + void InitClear() override = 0; bool PerformMemoryCopy(u32 dest, u32 src, int size) override; bool PerformMemorySet(u32 dest, u8 v, int size) override; bool PerformMemoryDownload(u32 dest, int size) override; @@ -105,10 +105,6 @@ public: void Execute_BoundingBox(u32 op, u32 diff); void Execute_BlockTransferStart(u32 op, u32 diff); - void Execute_TexScaleU(u32 op, u32 diff); - void Execute_TexScaleV(u32 op, u32 diff); - void Execute_TexOffsetU(u32 op, u32 diff); - void Execute_TexOffsetV(u32 op, u32 diff); void Execute_TexLevel(u32 op, u32 diff); void Execute_WorldMtxNum(u32 op, u32 diff); @@ -233,11 +229,7 @@ protected: } } - virtual void InitClearInternal() {} void BeginFrame() override; - virtual void BeginFrameInternal(); - virtual void CopyDisplayToOutputInternal() {} - virtual void ReinitializeInternal() {} // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; @@ -247,8 +239,6 @@ protected: void PopDLQueue(); void CheckDrawSync(); int GetNextListIndex(); - void ProcessDLQueueInternal(); - virtual void ReapplyGfxStateInternal(); virtual void FastLoadBoneMatrix(u32 target); // TODO: Unify this. @@ -265,11 +255,6 @@ protected: } } - void PerformMemoryCopyInternal(u32 dest, u32 src, int size); - void PerformMemorySetInternal(u32 dest, u8 v, int size); - void PerformStencilUploadInternal(u32 dest, int size); - void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); - FramebufferManagerCommon *framebufferManager_; TextureCacheCommon *textureCache_; DrawEngineCommon *drawEngineCommon_; diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 588df982da..0b7a40012f 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -281,13 +281,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { draw_->BindIndexBuffer(nullptr, 0); } -void SoftGPU::CopyDisplayToOutput() -{ - CopyDisplayToOutputInternal(); -} - -void SoftGPU::CopyDisplayToOutputInternal() -{ +void SoftGPU::CopyDisplayToOutput() { // The display always shows 480x272. CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT); framebufferDirty_ = false; diff --git a/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 627b2acd52..7d5750b043 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -97,8 +97,6 @@ protected: void CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight); private: - void CopyDisplayToOutputInternal() override; - bool framebufferDirty_; u32 displayFramebuf_; u32 displayStride_; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 3513f5d755..2e276056aa 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -332,21 +332,17 @@ void GPU_Vulkan::BuildReportingInfo() { Reporting::UpdateConfig(); } -void GPU_Vulkan::ReinitializeInternal() { +void GPU_Vulkan::Reinitialize() { + GPUCommon::Reinitialize(); textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); framebufferManagerVulkan_->DestroyAllFBOs(); } -void GPU_Vulkan::InitClearInternal() { +void GPU_Vulkan::InitClear() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { - /* - glstate.depthWrite.set(GL_TRUE); - glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - glClearColor(0, 0, 0, 1); - glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); - */ + // TODO? } } @@ -389,7 +385,7 @@ bool GPU_Vulkan::FramebufferReallyDirty() { return true; } -void GPU_Vulkan::CopyDisplayToOutputInternal() { +void GPU_Vulkan::CopyDisplayToOutput() { // Flush anything left over. drawEngine_.Flush(); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 4c1d49a470..289a8463f1 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -96,9 +96,9 @@ private: } void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal() override; - void CopyDisplayToOutputInternal() override; - void ReinitializeInternal() override; + void InitClear() override; + void CopyDisplayToOutput() override; + void Reinitialize() override; inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); From 9e35144b96fe2331650a3fb0d2be4062cf860150 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 23:07:37 +0100 Subject: [PATCH 08/10] Remove/deprecate GPU tick sync --- Core/HLE/sceGe.cpp | 24 +++--------------------- GPU/Common/SoftwareTransformCommon.cpp | 1 + GPU/GPUCommon.cpp | 4 ---- GPU/GPUCommon.h | 6 ------ GPU/GPUInterface.h | 1 - 5 files changed, 4 insertions(+), 32 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index d72ebe4a26..bcc5a467fe 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -57,10 +57,6 @@ static int geSyncEvent; static int geInterruptEvent; static int geCycleEvent; -// Let's try updating 10 times per vblank - this is the interval for geCycleEvent. -const int geIntervalUs = 1000000 / (60 * 10); -const int geBehindThresholdUs = 1000000 / (60 * 10); - class GeIntrHandler : public IntrHandler { public: GeIntrHandler() : IntrHandler(PSP_GE_INTR) {} @@ -193,19 +189,8 @@ static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) { __TriggerInterrupt(PSP_INTR_IMMEDIATE, PSP_GE_INTR, PSP_INTR_SUB_NONE); } -// Should we still do this? static void __GeCheckCycles(u64 userdata, int cyclesLate) { - u64 geTicks = gpu->GetTickEstimate(); - if (geTicks != 0) { - if (CoreTiming::GetTicks() > geTicks + usToCycles(geBehindThresholdUs)) { - u64 diff = CoreTiming::GetTicks() - geTicks; - CoreTiming::Advance(); - } - } - - // This may get out of step if we synced (because we don't correct for cyclesLate), - // but that's okay - __GeCheckCycles is a very rough way to synchronize anyway. - CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0); + // Deprecated } void __GeInit() { @@ -216,15 +201,12 @@ void __GeInit() { geSyncEvent = CoreTiming::RegisterEvent("GeSyncEvent", &__GeExecuteSync); geInterruptEvent = CoreTiming::RegisterEvent("GeInterruptEvent", &__GeExecuteInterrupt); + + // Deprecated geCycleEvent = CoreTiming::RegisterEvent("GeCycleEvent", &__GeCheckCycles); listWaitingThreads.clear(); drawWaitingThreads.clear(); - - // When we're using separate CPU/GPU threads, we need to keep them in sync. - if (IsOnSeparateCPUThread()) { - CoreTiming::ScheduleEvent(usToCycles(geIntervalUs), geCycleEvent, 0); - } } struct GeInterruptData_v1 { diff --git a/GPU/Common/SoftwareTransformCommon.cpp b/GPU/Common/SoftwareTransformCommon.cpp index bab715e13f..f55c793c47 100644 --- a/GPU/Common/SoftwareTransformCommon.cpp +++ b/GPU/Common/SoftwareTransformCommon.cpp @@ -400,6 +400,7 @@ void SoftwareTransform( // rectangle out of many. Quite a small optimization though. // Experiment: Disable on PowerVR (see issue #6290) // TODO: This bleeds outside the play area in non-buffered mode. Big deal? Probably not. + // TODO: Allow creating a depth clear and a color draw. bool reallyAClear = false; if (maxIndex > 1 && prim == GE_PRIM_RECTANGLES && gstate.isModeClear()) { int scissorX2 = gstate.getScissorX2() + 1; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 8ecf357fa3..347b331244 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -395,7 +395,6 @@ void GPUCommon::Reinitialize() { busyTicks = 0; timeSpentStepping_ = 0.0; interruptsEnabled_ = true; - curTickEst_ = 0; } int GPUCommon::EstimatePerVertexCost() { @@ -1023,7 +1022,6 @@ int GPUCommon::GetNextListIndex() { void GPUCommon::ProcessDLQueue() { startingTicks = CoreTiming::GetTicks(); cyclesExecuted = 0; - curTickEst_ = std::max(busyTicks, startingTicks + cyclesExecuted); // Seems to be correct behaviour to process the list anyway? if (startingTicks < busyTicks) { @@ -1042,7 +1040,6 @@ void GPUCommon::ProcessDLQueue() { // At the end, we can remove it from the queue and continue. dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end()); } - curTickEst_ = std::max(busyTicks, startingTicks + cyclesExecuted); } } @@ -1052,7 +1049,6 @@ void GPUCommon::ProcessDLQueue() { busyTicks = std::max(busyTicks, drawCompleteTicks); __GeTriggerSync(GPU_SYNC_DRAW, 1, drawCompleteTicks); // Since the event is in CoreTiming, we're in sync. Just set 0 now. - curTickEst_ = 0; } void GPUCommon::PreExecuteOp(u32 op, u32 diff) { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index c1310ae8fc..d3b53ad514 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -127,10 +127,6 @@ public: // Note: Not virtual! inline void Flush(); - u64 GetTickEstimate() override { - return curTickEst_; - } - #ifdef USE_CRT_DBG #undef new #endif @@ -290,8 +286,6 @@ protected: GEPrimitiveType lastPrim_; private: - u64 curTickEst_; - // Debug stats. double timeSteppingStarted_; double timeSpentStepping_; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index a8dfc780c3..af5c1a36df 100644 --- a/GPU/GPUInterface.h +++ b/GPU/GPUInterface.h @@ -223,7 +223,6 @@ public: virtual void DeviceLost() = 0; virtual void DeviceRestore() = 0; virtual void ReapplyGfxState() = 0; - virtual u64 GetTickEstimate() = 0; virtual void DoState(PointerWrap &p) = 0; // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. From f16d11a43bcc006618566911dbc9a48587499729 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Sun, 5 Nov 2017 21:22:29 +0100 Subject: [PATCH 09/10] Turn on multithreaded vulkan --- ext/native/thin3d/VulkanRenderManager.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index b87f9a6d63..308b04c2d0 100644 --- a/ext/native/thin3d/VulkanRenderManager.cpp +++ b/ext/native/thin3d/VulkanRenderManager.cpp @@ -12,7 +12,7 @@ #endif // TODO: Using a thread here is unfinished and does not work correctly. -const bool useThread = false; +const bool useThread = true; #ifndef UINT64_MAX #define UINT64_MAX 0xFFFFFFFFFFFFFFFFULL From a827ad23ae6d090042b63042a415aef4931b5e66 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Henrik=20Rydg=C3=A5rd?= Date: Mon, 6 Nov 2017 00:27:51 +0100 Subject: [PATCH 10/10] Don't use "threadsafe events" for Ge stuff. --- Core/HLE/sceGe.cpp | 8 +++----- 1 file changed, 3 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index bcc5a467fe..fad468bfa8 100644 --- a/Core/HLE/sceGe.cpp +++ b/Core/HLE/sceGe.cpp @@ -251,20 +251,18 @@ void __GeDoState(PointerWrap &p) { void __GeShutdown() { } -// Warning: may be called from the GPU thread, if there is a separate one (multithread mode). bool __GeTriggerSync(GPUSyncType type, int id, u64 atTicks) { u64 userdata = (u64)id << 32 | (u64)type; s64 future = atTicks - CoreTiming::GetTicks(); if (type == GPU_SYNC_DRAW) { - s64 left = CoreTiming::UnscheduleThreadsafeEvent(geSyncEvent, userdata); + s64 left = CoreTiming::UnscheduleEvent(geSyncEvent, userdata); if (left > future) future = left; } - CoreTiming::ScheduleEvent_Threadsafe(future, geSyncEvent, userdata); + CoreTiming::ScheduleEvent(future, geSyncEvent, userdata); return true; } -// Warning: may be called from the GPU thread, if there is a separate one (multithread mode). bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) { GeInterruptData intrdata; intrdata.listid = listid; @@ -274,7 +272,7 @@ bool __GeTriggerInterrupt(int listid, u32 pc, u64 atTicks) { ge_pending_cb.push_back(intrdata); u64 userdata = (u64)listid << 32 | (u64) pc; - CoreTiming::ScheduleEvent_Threadsafe(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata); + CoreTiming::ScheduleEvent(atTicks - CoreTiming::GetTicks(), geInterruptEvent, userdata); return true; }