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/HLE/sceGe.cpp b/Core/HLE/sceGe.cpp index 25aaa6848a..fad468bfa8 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) {} @@ -194,19 +190,7 @@ static void __GeExecuteInterrupt(u64 userdata, int cyclesLate) { } 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(); - } - } - - // 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() { @@ -217,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 { @@ -270,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; @@ -293,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; } @@ -504,7 +483,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 +502,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 04c93deeb1..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,18 +377,15 @@ 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! 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 +405,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 +430,7 @@ bool PSP_InitUpdate(std::string *error_string) { return true; } - if (g_Config.bSeparateCPUThread && !CPU_IsReady()) { + if (!CPU_IsReady()) { return false; } @@ -459,7 +451,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 +465,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 +481,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 +500,7 @@ void PSP_Shutdown() { currentMIPS = 0; pspIsInited = false; pspIsIniting = false; - pspIsQuiting = false; + pspIsQuitting = false; g_Config.unloadGameConfig(); } @@ -532,8 +525,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); @@ -541,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); @@ -551,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/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/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..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(); @@ -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; @@ -371,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 0dd93e7137..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(); @@ -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; @@ -337,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 b7d25debd3..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) { @@ -504,11 +505,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 +515,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; @@ -533,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 53b39e6d32..347b331244 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -359,11 +359,9 @@ 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); Reinitialize(); SetupColorConv(); - SetThreadEnabled(g_Config.bSeparateCPUThread); gstate.Reset(); gstate_c.Reset(); gpuStats.Reset(); @@ -383,16 +381,7 @@ void GPUCommon::EndHostFrame() { } -void GPUCommon::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - -void GPUCommon::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - 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,14 +389,12 @@ void GPUCommon::Reinitialize() { } nextListID = 0; - currentList = NULL; + currentList = nullptr; isbreak = false; drawCompleteTicks = 0; busyTicks = 0; timeSpentStepping_ = 0.0; interruptsEnabled_ = true; - UpdateTickEstimate(0); - ScheduleEvent(GPU_EVENT_REINITIALIZE); } int GPUCommon::EstimatePerVertexCost() { @@ -440,7 +427,6 @@ int GPUCommon::EstimatePerVertexCost() { } void GPUCommon::PopDLQueue() { - easy_guard guard(listLock); if(!dlQueue.empty()) { dlQueue.pop_front(); if(!dlQueue.empty()) { @@ -449,7 +435,7 @@ void GPUCommon::PopDLQueue() { if (running) currentList->state = PSP_GE_DL_STATE_RUNNING; } else { - currentList = NULL; + currentList = nullptr; } } } @@ -457,7 +443,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; } @@ -474,12 +459,6 @@ void GPUCommon::DumpNextFrame() { } u32 GPUCommon::DrawSync(int mode) { - if (ThreadEnabled()) { - // Sync first, because the CPU is usually faster than the emulated GPU. - SyncThread(); - } - - easy_guard guard(listLock); if (mode < 0 || mode > 1) return SCE_KERNEL_ERROR_INVALID_MODE; @@ -521,7 +500,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; @@ -529,12 +507,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(); - } - - easy_guard guard(listLock); if (listid < 0 || listid >= DisplayListMaxCount) return SCE_KERNEL_ERROR_INVALID_ID; @@ -579,8 +551,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 +576,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 +674,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 +704,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 +712,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 +753,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 +846,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 +869,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 +888,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) { @@ -959,10 +917,6 @@ bool GPUCommon::InterpretList(DisplayList &list) { } void GPUCommon::BeginFrame() { - ScheduleEvent(GPU_EVENT_BEGIN_FRAME); -} - -void GPUCommon::BeginFrameInternal() { if (dumpNextFrame_) { NOTICE_LOG(G3D, "DUMPING THIS FRAME"); dumpThisFrame_ = true; @@ -1026,14 +980,6 @@ void GPUCommon::UpdatePC(u32 currentPC, u32 newPC) { } void GPUCommon::ReapplyGfxState() { - if (IsOnSeparateCPUThread()) { - ScheduleEvent(GPU_EVENT_REAPPLY_GFX_STATE); - } else { - 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. @@ -1064,55 +1010,7 @@ 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() { - easy_guard guard(listLock); auto iter = dlQueue.begin(); if (iter != dlQueue.end()) { return *iter; @@ -1121,15 +1019,9 @@ int GPUCommon::GetNextListIndex() { } } -bool GPUCommon::ProcessDLQueue() { - ScheduleEvent(GPU_EVENT_PROCESS_QUEUE); - return true; -} - -void GPUCommon::ProcessDLQueueInternal() { +void GPUCommon::ProcessDLQueue() { startingTicks = CoreTiming::GetTicks(); cyclesExecuted = 0; - UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted)); // Seems to be correct behaviour to process the list anyway? if (startingTicks < busyTicks) { @@ -1143,25 +1035,20 @@ 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. dlQueue.erase(std::remove(dlQueue.begin(), dlQueue.end(), listIndex), dlQueue.end()); } - UpdateTickEstimate(std::max(busyTicks, startingTicks + cyclesExecuted)); } } - easy_guard guard(listLock); - currentList = NULL; + currentList = nullptr; drawCompleteTicks = startingTicks + cyclesExecuted; 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); } void GPUCommon::PreExecuteOp(u32 op, u32 diff) { @@ -1181,12 +1068,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 +1086,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 +1098,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 +1136,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 +1157,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. @@ -1419,7 +1300,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; @@ -1600,7 +1481,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 +1528,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 +1575,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 +1623,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 +1689,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 +1904,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 +1982,6 @@ void GPUCommon::InterruptStart(int listid) { interruptRunning = true; } void GPUCommon::InterruptEnd(int listid) { - easy_guard guard(listLock); interruptRunning = false; isbreak = false; @@ -2124,13 +1997,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 +2013,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 +2023,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 +2036,6 @@ void GPUCommon::ResetListPC(int listID, u32 pc) { return; } - easy_guard guard(listLock); dls[listID].pc = pc; } @@ -2177,7 +2045,6 @@ void GPUCommon::ResetListStall(int listID, u32 stall) { return; } - easy_guard guard(listLock); dls[listID].stall = stall; } @@ -2187,7 +2054,6 @@ void GPUCommon::ResetListState(int listID, DisplayListState state) { return; } - easy_guard guard(listLock); dls[listID].state = state; } @@ -2339,38 +2205,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)) { - 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); - - // This is a memcpy, so we need to wait for it to complete. - SyncThread(); - } else { - 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; } @@ -2383,17 +2228,8 @@ 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); + if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } return true; } @@ -2424,14 +2260,6 @@ 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); -} - -void GPUCommon::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { if (size > 0) textureCache_->Invalidate(addr, size, type); else @@ -2456,23 +2284,12 @@ 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); - } + 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 3d2430125d..d3b53ad514 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(); @@ -69,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; @@ -77,21 +74,13 @@ 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; 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; @@ -116,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); @@ -142,20 +127,6 @@ public: // Note: Not virtual! 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 #undef new #endif @@ -254,11 +225,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; @@ -268,15 +235,10 @@ protected: void PopDLQueue(); void CheckDrawSync(); int GetNextListIndex(); - 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() { - } + + // TODO: Unify this. + virtual void FinishDeferred() {} void DoBlockTransfer(u32 skipDrawReason); @@ -289,53 +251,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); - - // 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 +265,6 @@ protected: DisplayList dls[DisplayListMaxCount]; DisplayList *currentList; DisplayListQueue dlQueue; - optional_mutex listLock; bool interruptRunning; GPURunState gpuState; @@ -372,28 +286,6 @@ 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 - } - // Debug stats. double timeSteppingStarted_; double timeSpentStepping_; diff --git a/GPU/GPUInterface.h b/GPU/GPUInterface.h index 5faf3540bb..af5c1a36df 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; } @@ -225,10 +175,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,9 +223,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; // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. @@ -289,7 +232,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 812c164cb2..0b7a40012f 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" @@ -280,13 +281,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { draw_->BindIndexBuffer(nullptr, 0); } -void SoftGPU::CopyDisplayToOutput() -{ - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - -void SoftGPU::CopyDisplayToOutputInternal() -{ +void SoftGPU::CopyDisplayToOutput() { // The display always shows 480x272. CopyToCurrentFboFromDisplayRam(FB_WIDTH, FB_HEIGHT); framebufferDirty_ = false; @@ -301,17 +296,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) { @@ -913,11 +897,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/GPU/Software/SoftGpu.h b/GPU/Software/SoftGpu.h index 25c21da0ec..7d5750b043 100644 --- a/GPU/Software/SoftGpu.h +++ b/GPU/Software/SoftGpu.h @@ -94,12 +94,9 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; 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 cfaae884f3..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? } } @@ -370,11 +366,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 +376,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; @@ -399,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(); 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())); diff --git a/ext/native/thin3d/VulkanRenderManager.cpp b/ext/native/thin3d/VulkanRenderManager.cpp index 773a7fa59b..cc9f70d594 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