From 7e46a153c0ef15d18f9816e32691d6032c0ed0ba Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 18:07:17 +0100 Subject: [PATCH 1/6] Centralize DoBlockTransfer between the GPUs. Required adding a pointer to the framebuffer manager and texture cache in GPUCommon, which took a little bit of refactoring. --- GPU/Common/TextureCacheCommon.cpp | 4 - GPU/Common/TextureCacheCommon.h | 3 +- GPU/Directx9/GPU_DX9.cpp | 156 +++++----------------- GPU/Directx9/GPU_DX9.h | 3 +- GPU/GLES/GPU_GLES.cpp | 212 +++++++++--------------------- GPU/GLES/GPU_GLES.h | 7 +- GPU/GPUCommon.cpp | 97 +++++++++++++- GPU/GPUCommon.h | 8 ++ GPU/Vulkan/GPU_Vulkan.cpp | 165 ++++++----------------- GPU/Vulkan/GPU_Vulkan.h | 5 +- 10 files changed, 251 insertions(+), 409 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.cpp b/GPU/Common/TextureCacheCommon.cpp index 4e88b8d68c..e32c391a64 100644 --- a/GPU/Common/TextureCacheCommon.cpp +++ b/GPU/Common/TextureCacheCommon.cpp @@ -63,10 +63,6 @@ TextureCacheCommon::~TextureCacheCommon() { FreeAlignedMemory(clutBufRaw_); } -bool TextureCacheCommon::SetOffsetTexture(u32 offset) { - return false; -} - int TextureCacheCommon::AttachedDrawingHeight() { if (nextTexture_) { if (nextTexture_->framebuffer) { diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 462296d34b..82e0d0e7c4 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -50,7 +50,8 @@ public: void LoadClut(u32 clutAddr, u32 loadBytes); bool GetCurrentClutBuffer(GPUDebugBuffer &buffer); - virtual bool SetOffsetTexture(u32 offset); + virtual bool SetOffsetTexture(u32 offset) = 0; + virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0; // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index cf9e91f0a7..e275c9adf6 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -398,15 +398,18 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) lastVsync_ = g_Config.bVSync ? 1 : 0; dxstate.SetVSyncInterval(g_Config.bVSync); + framebufferManagerDX9_ = new FramebufferManagerDX9(); + framebufferManager_ = framebufferManagerDX9_; + shaderManager_ = new ShaderManagerDX9(); drawEngine_.SetShaderManager(shaderManager_); drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(&framebufferManager_); - framebufferManager_.Init(); - framebufferManager_.SetTextureCache(&textureCache_); - framebufferManager_.SetShaderManager(shaderManager_); - framebufferManager_.SetTransformDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(&framebufferManager_); + drawEngine_.SetFramebufferManager(framebufferManagerDX9_); + framebufferManagerDX9_->Init(); + framebufferManagerDX9_->SetTextureCache(&textureCache_); + framebufferManagerDX9_->SetShaderManager(shaderManager_); + framebufferManagerDX9_->SetTransformDrawEngine(&drawEngine_); + textureCache_.SetFramebufferManager(framebufferManagerDX9_); textureCache_.SetDepalShaderCache(&depalShaderCache_); textureCache_.SetShaderManager(shaderManager_); @@ -500,7 +503,7 @@ void GPU_DX9::CheckGPUFeatures() { } GPU_DX9::~GPU_DX9() { - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerDX9_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); delete shaderManager_; } @@ -520,7 +523,7 @@ void GPU_DX9::DeviceLost() { // FBOs appear to survive? Or no? shaderManager_->ClearCache(false); textureCache_.Clear(false); - framebufferManager_.DeviceLost(); + framebufferManagerDX9_->DeviceLost(); } void GPU_DX9::DeviceRestore() { @@ -584,12 +587,12 @@ void GPU_DX9::BeginFrameInternal() { } shaderManager_->DirtyShader(); - framebufferManager_.BeginFrame(); + framebufferManagerDX9_->BeginFrame(); } void GPU_DX9::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { host->GPUNotifyDisplay(framebuf, stride, format); - framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format); + framebufferManagerDX9_->SetDisplayFramebuffer(framebuf, stride, format); } bool GPU_DX9::FramebufferDirty() { @@ -600,7 +603,7 @@ bool GPU_DX9::FramebufferDirty() { // Allow it to process fully before deciding if it's dirty. SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; vfb->dirtyAfterDisplay = false; @@ -617,7 +620,7 @@ bool GPU_DX9::FramebufferReallyDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManager_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; vfb->reallyDirtyAfterDisplay = false; @@ -636,8 +639,8 @@ void GPU_DX9::CopyDisplayToOutputInternal() { drawEngine_.Flush(); - framebufferManager_.CopyDisplayToOutput(); - framebufferManager_.EndFrame(); + framebufferManagerDX9_->CopyDisplayToOutput(); + framebufferManagerDX9_->EndFrame(); // shaderManager_->EndFrame(); shaderManager_->DirtyLastShader(); @@ -787,7 +790,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) { } // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { drawEngine_.SetupVertexDecoder(gstate.vertType); // Rough estimate, not sure what's correct. @@ -835,7 +838,7 @@ void GPU_DX9::Execute_Prim(u32 op, u32 diff) { void GPU_DX9::Execute_Bezier(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -878,7 +881,7 @@ void GPU_DX9::Execute_Bezier(u32 op, u32 diff) { void GPU_DX9::Execute_Spline(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerDX9_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1876,7 +1879,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, - (int)framebufferManager_.NumVFBs(), + (int)framebufferManagerDX9_->NumVFBs(), (int)textureCache_.NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, @@ -1885,93 +1888,6 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_DX9::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((height - 1 + srcY) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((height - 1 + dstY) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - void GPU_DX9::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE); ev.invalidate_cache.addr = addr; @@ -1986,25 +1902,25 @@ void GPU_DX9::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType ty else textureCache_.InvalidateAll(type); - if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) { + if (type != GPU_INVALIDATE_ALL && framebufferManagerDX9_->MayIntersectFramebuffer(addr)) { // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. // Vempire invalidates (with writeback) after drawing, but before blitting. if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); + framebufferManagerDX9_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); } } } void GPU_DX9::NotifyVideoUpload(u32 addr, int size, int width, int format) { if (Memory::IsVRAMAddress(addr)) { - framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + framebufferManagerDX9_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); } textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } void GPU_DX9::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { + if (!framebufferManagerDX9_->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) { @@ -2015,18 +1931,18 @@ void GPU_DX9::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { } void GPU_DX9::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { + if (!framebufferManagerDX9_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } } void GPU_DX9::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_.NotifyStencilUpload(dest, size); + framebufferManagerDX9_->NotifyStencilUpload(dest, size); } bool GPU_DX9::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 (framebufferManagerDX9_->MayIntersectFramebuffer(src) || framebufferManagerDX9_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { GPUEvent ev(GPU_EVENT_FB_MEMCPY); ev.fb_memcpy.dst = dest; @@ -2048,7 +1964,7 @@ bool GPU_DX9::PerformMemoryCopy(u32 dest, u32 src, int size) { bool GPU_DX9::PerformMemorySet(u32 dest, u8 v, int size) { // This may indicate a memset, usually to 0, of a framebuffer. - if (framebufferManager_.MayIntersectFramebuffer(dest)) { + if (framebufferManagerDX9_->MayIntersectFramebuffer(dest)) { Memory::Memset(dest, v, size); if (IsOnSeparateCPUThread()) { @@ -2089,7 +2005,7 @@ bool GPU_DX9::PerformMemoryUpload(u32 dest, int size) { } bool GPU_DX9::PerformStencilUpload(u32 dest, int size) { - if (framebufferManager_.MayIntersectFramebuffer(dest)) { + if (framebufferManagerDX9_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD); ev.fb_stencil_upload.dst = dest; @@ -2109,7 +2025,7 @@ void GPU_DX9::ClearCacheNextFrame() { void GPU_DX9::Resized() { resized_ = true; - framebufferManager_.Resized(); + framebufferManagerDX9_->Resized(); } void GPU_DX9::ClearShaderCache() { @@ -2117,7 +2033,7 @@ void GPU_DX9::ClearShaderCache() { } std::vector GPU_DX9::GetFramebufferList() { - return framebufferManager_.GetFramebufferList(); + return framebufferManagerDX9_->GetFramebufferList(); } void GPU_DX9::DoState(PointerWrap &p) { @@ -2130,21 +2046,21 @@ void GPU_DX9::DoState(PointerWrap &p) { drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerDX9_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } bool GPU_DX9::GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes) { - return framebufferManager_.GetCurrentFramebuffer(buffer, type, maxRes); + return framebufferManagerDX9_->GetCurrentFramebuffer(buffer, type, maxRes); } bool GPU_DX9::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentDepthbuffer(buffer); + return framebufferManagerDX9_->GetCurrentDepthbuffer(buffer); } bool GPU_DX9::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentStencilbuffer(buffer); + return framebufferManagerDX9_->GetCurrentStencilbuffer(buffer); } bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index ce0003a34e..c97a6bff3b 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -163,7 +163,6 @@ private: void Flush() { drawEngine_.Flush(); } - void DoBlockTransfer(u32 skipDrawReason); void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); @@ -175,7 +174,7 @@ private: void PerformStencilUploadInternal(u32 dest, int size); void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); - FramebufferManagerDX9 framebufferManager_; + FramebufferManagerDX9 *framebufferManagerDX9_; TextureCacheDX9 textureCache_; DepalShaderCacheDX9 depalShaderCache_; DrawEngineDX9 drawEngine_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 4b9ad6582b..d2e62efc54 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -402,19 +402,24 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) CheckGPUFeatures(); shaderManager_ = new ShaderManager(); + framebufferManagerGL_ = new FramebufferManager(); + framebufferManager_ = framebufferManagerGL_; + textureCacheGL_ = new TextureCache(); + textureCache_ = textureCacheGL_; + drawEngine_.SetShaderManager(shaderManager_); - drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(&framebufferManager_); + drawEngine_.SetTextureCache(textureCacheGL_); + drawEngine_.SetFramebufferManager(framebufferManagerGL_); drawEngine_.SetFragmentTestCache(&fragmentTestCache_); - framebufferManager_.Init(); - framebufferManager_.SetTextureCache(&textureCache_); - framebufferManager_.SetShaderManager(shaderManager_); - framebufferManager_.SetTransformDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(&framebufferManager_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); - textureCache_.SetTransformDrawEngine(&drawEngine_); - fragmentTestCache_.SetTextureCache(&textureCache_); + framebufferManagerGL_->Init(); + framebufferManagerGL_->SetTextureCache(textureCacheGL_); + framebufferManagerGL_->SetShaderManager(shaderManager_); + framebufferManagerGL_->SetTransformDrawEngine(&drawEngine_); + textureCacheGL_->SetFramebufferManager(framebufferManagerGL_); + textureCacheGL_->SetDepalShaderCache(&depalShaderCache_); + textureCacheGL_->SetShaderManager(shaderManager_); + textureCacheGL_->SetTransformDrawEngine(&drawEngine_); + fragmentTestCache_.SetTextureCache(textureCacheGL_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -457,7 +462,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) // We restore each frame anyway, but here is convenient for tests. glstate.Restore(); drawEngine_.RestoreVAO(); - textureCache_.NotifyConfigChanged(); + textureCacheGL_->NotifyConfigChanged(); // Load shader cache. std::string discID = g_paramSFO.GetValueString("DISC_ID"); @@ -469,7 +474,7 @@ GPU_GLES::GPU_GLES(GraphicsContext *ctx) } GPU_GLES::~GPU_GLES() { - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerGL_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); depalShaderCache_.Clear(); fragmentTestCache_.Clear(); @@ -647,10 +652,10 @@ void GPU_GLES::DeviceLost() { // FBOs appear to survive? Or no? // TransformDraw has registered as a GfxResourceHolder. shaderManager_->ClearCache(false); - textureCache_.Clear(false); + textureCacheGL_->Clear(false); fragmentTestCache_.Clear(false); depalShaderCache_.Clear(); - framebufferManager_.DeviceLost(); + framebufferManagerGL_->DeviceLost(); } void GPU_GLES::DeviceRestore() { @@ -669,10 +674,10 @@ void GPU_GLES::Reinitialize() { } void GPU_GLES::ReinitializeInternal() { - textureCache_.Clear(true); + textureCacheGL_->Clear(true); depalShaderCache_.Clear(); - framebufferManager_.DestroyAllFBOs(true); - framebufferManager_.Resized(); + framebufferManagerGL_->DestroyAllFBOs(true); + framebufferManagerGL_->Resized(); } void GPU_GLES::InitClearInternal() { @@ -742,12 +747,12 @@ void GPU_GLES::BeginFrameInternal() { CheckGPUFeatures(); UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheGL_->NotifyConfigChanged(); } UpdateVsyncInterval(resized_); resized_ = false; - textureCache_.StartFrame(); + textureCacheGL_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); drawEngine_.DecimateBuffers(); depalShaderCache_.Decimate(); @@ -771,12 +776,12 @@ void GPU_GLES::BeginFrameInternal() { // Not sure if this is really needed. shaderManager_->DirtyUniform(DIRTY_ALL); - framebufferManager_.BeginFrame(); + framebufferManagerGL_->BeginFrame(); } void GPU_GLES::SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) { host->GPUNotifyDisplay(framebuf, stride, format); - framebufferManager_.SetDisplayFramebuffer(framebuf, stride, format); + framebufferManagerGL_->SetDisplayFramebuffer(framebuf, stride, format); } bool GPU_GLES::FramebufferDirty() { @@ -785,7 +790,7 @@ bool GPU_GLES::FramebufferDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->dirtyAfterDisplay; vfb->dirtyAfterDisplay = false; @@ -800,7 +805,7 @@ bool GPU_GLES::FramebufferReallyDirty() { SyncThread(); } - VirtualFramebuffer *vfb = framebufferManager_.GetDisplayVFB(); + VirtualFramebuffer *vfb = framebufferManagerGL_->GetDisplayVFB(); if (vfb) { bool dirty = vfb->reallyDirtyAfterDisplay; vfb->reallyDirtyAfterDisplay = false; @@ -815,7 +820,7 @@ void GPU_GLES::CopyDisplayToOutput() { void GPU_GLES::CopyDisplayToOutputInternal() { // Flush anything left over. - framebufferManager_.RebindFramebuffer(); + framebufferManagerGL_->RebindFramebuffer(); drawEngine_.Flush(); shaderManager_->DirtyLastShader(); @@ -823,8 +828,8 @@ void GPU_GLES::CopyDisplayToOutputInternal() { glstate.depthWrite.set(GL_TRUE); glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); - framebufferManager_.CopyDisplayToOutput(); - framebufferManager_.EndFrame(); + framebufferManagerGL_->CopyDisplayToOutput(); + framebufferManagerGL_->EndFrame(); // If buffered, discard the depth buffer of the backbuffer. Don't even know if we need one. #if 0 @@ -965,7 +970,7 @@ void GPU_GLES::Execute_Prim(u32 op, u32 diff) { } // This also makes skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { drawEngine_.SetupVertexDecoder(gstate.vertType); // Rough estimate, not sure what's correct. @@ -1034,7 +1039,7 @@ void GPU_GLES::Execute_VertexTypeSkinning(u32 op, u32 diff) { void GPU_GLES::Execute_Bezier(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1077,7 +1082,7 @@ void GPU_GLES::Execute_Bezier(u32 op, u32 diff) { void GPU_GLES::Execute_Spline(u32 op, u32 diff) { // This also make skipping drawing very effective. - framebufferManager_.SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); + framebufferManagerGL_->SetRenderFrameBuffer(gstate_c.framebufChanged, gstate_c.skipDrawReason); if (gstate_c.skipDrawReason & (SKIPDRAW_SKIPFRAME | SKIPDRAW_NON_DISPLAYED_FB)) { // TODO: Should this eat some cycles? Probably yes. Not sure if important. return; @@ -1257,7 +1262,7 @@ void GPU_GLES::Execute_TexLevel(u32 op, u32 diff) { void GPU_GLES::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheGL_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -2135,8 +2140,8 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { gpuStats.numVertsSubmitted, gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, - (int)framebufferManager_.NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)framebufferManagerGL_->NumVFBs(), + (int)textureCacheGL_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->NumVertexShaders(), @@ -2144,95 +2149,6 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { shaderManager_->NumPrograms()); } -void GPU_GLES::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_.NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - -#ifndef MOBILE_DEVICE - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); -#endif - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - void GPU_GLES::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE); ev.invalidate_cache.addr = addr; @@ -2243,29 +2159,29 @@ void GPU_GLES::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { void GPU_GLES::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { if (size > 0) - textureCache_.Invalidate(addr, size, type); + textureCacheGL_->Invalidate(addr, size, type); else - textureCache_.InvalidateAll(type); + textureCacheGL_->InvalidateAll(type); - if (type != GPU_INVALIDATE_ALL && framebufferManager_.MayIntersectFramebuffer(addr)) { + if (type != GPU_INVALIDATE_ALL && framebufferManagerGL_->MayIntersectFramebuffer(addr)) { // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. // Vempire invalidates (with writeback) after drawing, but before blitting. if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_.UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); + framebufferManagerGL_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); } } } void GPU_GLES::NotifyVideoUpload(u32 addr, int size, int width, int format) { if (Memory::IsVRAMAddress(addr)) { - framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + framebufferManagerGL_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + textureCacheGL_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } void GPU_GLES::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(src, dest, size, false, gstate_c.skipDrawReason)) { + if (!framebufferManagerGL_->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) { @@ -2276,18 +2192,18 @@ void GPU_GLES::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { } void GPU_GLES::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { + if (!framebufferManagerGL_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } } void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_.NotifyStencilUpload(dest, size); + framebufferManagerGL_->NotifyStencilUpload(dest, size); } bool GPU_GLES::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 (framebufferManagerGL_->MayIntersectFramebuffer(src) || framebufferManagerGL_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { GPUEvent ev(GPU_EVENT_FB_MEMCPY); ev.fb_memcpy.dst = dest; @@ -2309,7 +2225,7 @@ bool GPU_GLES::PerformMemoryCopy(u32 dest, u32 src, int size) { bool GPU_GLES::PerformMemorySet(u32 dest, u8 v, int size) { // This may indicate a memset, usually to 0, of a framebuffer. - if (framebufferManager_.MayIntersectFramebuffer(dest)) { + if (framebufferManagerGL_->MayIntersectFramebuffer(dest)) { Memory::Memset(dest, v, size); if (IsOnSeparateCPUThread()) { @@ -2350,7 +2266,7 @@ bool GPU_GLES::PerformMemoryUpload(u32 dest, int size) { } bool GPU_GLES::PerformStencilUpload(u32 dest, int size) { - if (framebufferManager_.MayIntersectFramebuffer(dest)) { + if (framebufferManagerGL_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { GPUEvent ev(GPU_EVENT_FB_STENCIL_UPLOAD); ev.fb_stencil_upload.dst = dest; @@ -2365,12 +2281,12 @@ bool GPU_GLES::PerformStencilUpload(u32 dest, int size) { } void GPU_GLES::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); + textureCacheGL_->ClearNextFrame(); } void GPU_GLES::Resized() { resized_ = true; - framebufferManager_.Resized(); + framebufferManagerGL_->Resized(); } void GPU_GLES::ClearShaderCache() { @@ -2385,7 +2301,7 @@ void GPU_GLES::CleanupBeforeUI() { } std::vector GPU_GLES::GetFramebufferList() { - return framebufferManager_.GetFramebufferList(); + return framebufferManagerGL_->GetFramebufferList(); } void GPU_GLES::DoState(PointerWrap &p) { @@ -2395,21 +2311,21 @@ void GPU_GLES::DoState(PointerWrap &p) { // None of these are necessary when saving. // In Freeze-Frame mode, we don't want to do any of this. if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_.Clear(true); + textureCacheGL_->Clear(true); depalShaderCache_.Clear(); drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_.DestroyAllFBOs(true); + framebufferManagerGL_->DestroyAllFBOs(true); shaderManager_->ClearCache(true); } } bool GPU_GLES::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(); - GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManager_.DisplayFramebufFormat(); - return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); + u32 fb_address = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.getFrameBufRawAddress() : framebufferManagerGL_->DisplayFramebufAddr(); + int fb_stride = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufStride() : framebufferManagerGL_->DisplayFramebufStride(); + GEBufferFormat format = type == GPU_DBG_FRAMEBUF_RENDER ? gstate.FrameBufFormat() : framebufferManagerGL_->DisplayFramebufFormat(); + return framebufferManagerGL_->GetFramebuffer(fb_address, fb_stride, format, buffer, maxRes); } bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { @@ -2419,14 +2335,14 @@ bool GPU_GLES::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { u32 z_address = gstate.getDepthBufRawAddress(); int z_stride = gstate.DepthBufStride(); - return framebufferManager_.GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); + return framebufferManagerGL_->GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); } bool GPU_GLES::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { u32 fb_address = gstate.getFrameBufRawAddress(); int fb_stride = gstate.FrameBufStride(); - return framebufferManager_.GetStencilbuffer(fb_address, fb_stride, buffer); + return framebufferManagerGL_->GetStencilbuffer(fb_address, fb_stride, buffer); } bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { @@ -2445,8 +2361,8 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { gstate.texbufwidth[0] = gstate.texbufwidth[level]; } - textureCache_.SetTexture(true); - textureCache_.ApplyTexture(); + textureCacheGL_->SetTexture(true); + textureCacheGL_->ApplyTexture(); int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); glGetTexLevelParameteriv(GL_TEXTURE_2D, 0, GL_TEXTURE_WIDTH, &w); @@ -2467,7 +2383,7 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { } bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { - return textureCache_.GetCurrentClutBuffer(buffer); + return textureCacheGL_->GetCurrentClutBuffer(buffer); } bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 63f33b57b3..4daadf7298 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -70,7 +70,7 @@ public: void ClearShaderCache() override; void CleanupBeforeUI() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCache_.DecodeTexture(dest, state); + return textureCacheGL_->DecodeTexture(dest, state); } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; @@ -168,7 +168,6 @@ private: void Flush() { drawEngine_.Flush(); } - void DoBlockTransfer(u32 skipDrawReason); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); void InitClearInternal(); @@ -184,8 +183,8 @@ private: static CommandInfo cmdInfo_[256]; - FramebufferManager framebufferManager_; - TextureCache textureCache_; + FramebufferManager *framebufferManagerGL_; + TextureCache *textureCacheGL_; DepalShaderCache depalShaderCache_; DrawEngineGLES drawEngine_; FragmentTestCache fragmentTestCache_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 9436393efe..cd3c9229e1 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -19,10 +19,14 @@ #include "Core/HLE/sceKernelInterrupt.h" #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceGe.h" +#include "Core/Debugger/Breakpoints.h" +#include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/TextureCacheCommon.h" GPUCommon::GPUCommon() : dumpNextFrame_(false), - dumpThisFrame_(false) + dumpThisFrame_(false), + framebufferManager_(nullptr) { // This assert failed on GCC x86 32-bit (but not MSVC 32-bit!) before adding the // "padding" field at the end. This is important for save state compatibility. @@ -39,6 +43,7 @@ GPUCommon::GPUCommon() : } GPUCommon::~GPUCommon() { + delete framebufferManager_; } void GPUCommon::BeginHostFrame() { @@ -1312,3 +1317,93 @@ void GPUCommon::AdvanceVerts(u32 vertType, int count, int bytesRead) { gstate_c.vertexAddr += bytesRead; } } + + +void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { + // TODO: This is used a lot to copy data around between render targets and textures, + // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: + // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. + // + // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so + // either copy between rt and texture or reassign the texture to point to the render target + // + // etc.... + + u32 srcBasePtr = gstate.getTransferSrcAddress(); + u32 srcStride = gstate.getTransferSrcStride(); + + u32 dstBasePtr = gstate.getTransferDstAddress(); + u32 dstStride = gstate.getTransferDstStride(); + + int srcX = gstate.getTransferSrcX(); + int srcY = gstate.getTransferSrcY(); + + int dstX = gstate.getTransferDstX(); + int dstY = gstate.getTransferDstY(); + + int width = gstate.getTransferWidth(); + int height = gstate.getTransferHeight(); + + int bpp = gstate.getTransferBpp(); + + DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); + + if (!Memory::IsValidAddress(srcBasePtr)) { + ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); + return; + } + + if (!Memory::IsValidAddress(dstBasePtr)) { + ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); + return; + } + + // Check that the last address of both source and dest are valid addresses + + u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; + u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; + + if (!Memory::IsValidAddress(srcLastAddr)) { + ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); + return; + } + if (!Memory::IsValidAddress(dstLastAddr)) { + ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); + return; + } + + // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. + if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { + // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) + // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them + // entirely by walking a couple of pointers... + if (srcStride == dstStride && (u32)width == srcStride) { + // Common case in God of War, let's do it all in one chunk. + u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; + const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); + u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); + memcpy(dst, src, width * height * bpp); + } else { + for (int y = 0; y < height; y++) { + u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; + u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; + + const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); + u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); + memcpy(dst, src, width * bpp); + } + } + + textureCache_->Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); + framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); + } + +#ifndef MOBILE_DEVICE + CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); + CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); +#endif + + // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. + cyclesExecuted += ((height * width * bpp) * 16) / 10; +} \ No newline at end of file diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 94519e2a0a..2b69994ab5 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -14,6 +14,9 @@ typedef ThreadEventQueue GPUThreadEventQueue; +class FramebufferManagerCommon; +class TextureCacheCommon; + class GPUCommon : public GPUThreadEventQueue, public GPUDebugInterface { public: GPUCommon(); @@ -156,6 +159,8 @@ protected: virtual void FinishDeferred() { } + void DoBlockTransfer(u32 skipDrawReason); + void AdvanceVerts(u32 vertType, int count, int bytesRead); // Allows early unlocking with a guard. Do not double unlock. @@ -170,6 +175,9 @@ protected: bool locked_; }; + FramebufferManagerCommon *framebufferManager_; + TextureCacheCommon *textureCache_; + typedef std::list DisplayListQueue; int nextListID; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 0405b3fc9c..721f8aa24e 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -393,7 +393,6 @@ static const CommandTableEntry commandTable[] = { GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) : vulkan_((VulkanContext *)ctx->GetAPIContext()), drawEngine_(vulkan_), - textureCache_(vulkan_), resized_(false), gfxCtx_(ctx) { UpdateVsyncInterval(true); @@ -401,18 +400,22 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) shaderManager_ = new ShaderManagerVulkan(vulkan_); pipelineManager_ = new PipelineManagerVulkan(vulkan_); - framebufferManager_ = new FramebufferManagerVulkan(vulkan_); - drawEngine_.SetTextureCache(&textureCache_); - drawEngine_.SetFramebufferManager(framebufferManager_); + framebufferManagerVulkan_ = new FramebufferManagerVulkan(vulkan_); + framebufferManager_ = framebufferManagerVulkan_; + textureCacheVulkan_ = new TextureCacheVulkan(vulkan_); + textureCache_ = textureCacheVulkan_; + + drawEngine_.SetTextureCache(textureCacheVulkan_); + drawEngine_.SetFramebufferManager(framebufferManagerVulkan_); drawEngine_.SetShaderManager(shaderManager_); drawEngine_.SetPipelineManager(pipelineManager_); - framebufferManager_->Init(); - framebufferManager_->SetTextureCache(&textureCache_); - framebufferManager_->SetDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(framebufferManager_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); - textureCache_.SetTransformDrawEngine(&drawEngine_); + framebufferManagerVulkan_->Init(); + framebufferManagerVulkan_->SetTextureCache(textureCacheVulkan_); + framebufferManagerVulkan_->SetDrawEngine(&drawEngine_); + textureCacheVulkan_->SetFramebufferManager(framebufferManagerVulkan_); + textureCacheVulkan_->SetDepalShaderCache(&depalShaderCache_); + textureCacheVulkan_->SetShaderManager(shaderManager_); + textureCacheVulkan_->SetTransformDrawEngine(&drawEngine_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -448,13 +451,12 @@ GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) // Update again after init to be sure of any silly driver problems. UpdateVsyncInterval(true); - textureCache_.NotifyConfigChanged(); + textureCacheVulkan_->NotifyConfigChanged(); } GPU_Vulkan::~GPU_Vulkan() { - framebufferManager_->DestroyAllFBOs(true); + framebufferManagerVulkan_->DestroyAllFBOs(true); depalShaderCache_.Clear(); - delete framebufferManager_; delete pipelineManager_; delete shaderManager_; } @@ -495,14 +497,14 @@ void GPU_Vulkan::BeginHostFrame() { BuildReportingInfo(); UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheVulkan_->NotifyConfigChanged(); } resized_ = false; - textureCache_.StartFrame(); + textureCacheVulkan_->StartFrame(); depalShaderCache_.Decimate(); - framebufferManager_->BeginFrameVulkan(); + framebufferManagerVulkan_->BeginFrameVulkan(); shaderManager_->DirtyShader(); shaderManager_->DirtyUniform(DIRTY_ALL); @@ -518,8 +520,8 @@ void GPU_Vulkan::BeginHostFrame() { void GPU_Vulkan::EndHostFrame() { drawEngine_.EndFrame(); - framebufferManager_->EndFrame(); - textureCache_.EndFrame(); + framebufferManagerVulkan_->EndFrame(); + textureCacheVulkan_->EndFrame(); } // Needs to be called on GPU thread, not reporting thread. @@ -610,10 +612,10 @@ void GPU_Vulkan::Reinitialize() { } void GPU_Vulkan::ReinitializeInternal() { - textureCache_.Clear(true); + textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); - framebufferManager_->DestroyAllFBOs(true); - framebufferManager_->Resized(); + framebufferManagerVulkan_->DestroyAllFBOs(true); + framebufferManagerVulkan_->Resized(); } void GPU_Vulkan::InitClearInternal() { @@ -703,7 +705,7 @@ void GPU_Vulkan::CopyDisplayToOutputInternal() { shaderManager_->DirtyLastShader(); - framebufferManager_->CopyDisplayToOutput(); + framebufferManagerVulkan_->CopyDisplayToOutput(); gstate_c.textureChanged = TEXCHANGE_UPDATED; } @@ -1107,7 +1109,7 @@ void GPU_Vulkan::Execute_TexLevel(u32 op, u32 diff) { void GPU_Vulkan::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheVulkan_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -1936,10 +1938,10 @@ void GPU_Vulkan::FastLoadBoneMatrix(u32 target) { } void GPU_Vulkan::DeviceLost() { - framebufferManager_->DeviceLost(); + framebufferManagerVulkan_->DeviceLost(); drawEngine_.DeviceLost(); pipelineManager_->DeviceLost(); - textureCache_.DeviceLost(); + textureCacheVulkan_->DeviceLost(); depalShaderCache_.Clear(); shaderManager_->ClearShaders(); } @@ -1950,10 +1952,10 @@ void GPU_Vulkan::DeviceRestore() { BuildReportingInfo(); UpdateCmdInfo(); - framebufferManager_->DeviceRestore(vulkan_); + framebufferManagerVulkan_->DeviceRestore(vulkan_); drawEngine_.DeviceRestore(vulkan_); pipelineManager_->DeviceRestore(vulkan_); - textureCache_.DeviceRestore(vulkan_); + textureCacheVulkan_->DeviceRestore(vulkan_); shaderManager_->DeviceRestore(vulkan_); } @@ -1985,7 +1987,7 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, (int)framebufferManager_->NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)textureCacheVulkan_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->GetNumVertexShaders(), @@ -1997,95 +1999,6 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_Vulkan::DoBlockTransfer(u32 skipDrawReason) { - // TODO: This is used a lot to copy data around between render targets and textures, - // and also to quickly load textures from RAM to VRAM. So we should do checks like the following: - // * Does dstBasePtr point to an existing texture? If so maybe reload it immediately. - // - // * Does srcBasePtr point to a render target, and dstBasePtr to a texture? If so - // either copy between rt and texture or reassign the texture to point to the render target - // - // etc.... - - u32 srcBasePtr = gstate.getTransferSrcAddress(); - u32 srcStride = gstate.getTransferSrcStride(); - - u32 dstBasePtr = gstate.getTransferDstAddress(); - u32 dstStride = gstate.getTransferDstStride(); - - int srcX = gstate.getTransferSrcX(); - int srcY = gstate.getTransferSrcY(); - - int dstX = gstate.getTransferDstX(); - int dstY = gstate.getTransferDstY(); - - int width = gstate.getTransferWidth(); - int height = gstate.getTransferHeight(); - - int bpp = gstate.getTransferBpp(); - - DEBUG_LOG(G3D, "Block transfer: %08x/%x -> %08x/%x, %ix%ix%i (%i,%i)->(%i,%i)", srcBasePtr, srcStride, dstBasePtr, dstStride, width, height, bpp, srcX, srcY, dstX, dstY); - - if (!Memory::IsValidAddress(srcBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad source transfer address %08x!", srcBasePtr); - return; - } - - if (!Memory::IsValidAddress(dstBasePtr)) { - ERROR_LOG_REPORT(G3D, "BlockTransfer: Bad destination transfer address %08x!", dstBasePtr); - return; - } - - // Check that the last address of both source and dest are valid addresses - - u32 srcLastAddr = srcBasePtr + ((srcY + height - 1) * srcStride + (srcX + width - 1)) * bpp; - u32 dstLastAddr = dstBasePtr + ((dstY + height - 1) * dstStride + (dstX + width - 1)) * bpp; - - if (!Memory::IsValidAddress(srcLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of source of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - if (!Memory::IsValidAddress(dstLastAddr)) { - ERROR_LOG_REPORT(G3D, "Bottom-right corner of destination of block transfer is at an invalid address: %08x", srcLastAddr); - return; - } - - // Tell the framebuffer manager to take action if possible. If it does the entire thing, let's just return. - if (!framebufferManager_->NotifyBlockTransferBefore(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason)) { - // Do the copy! (Hm, if we detect a drawn video frame (see below) then we could maybe skip this?) - // Can use GetPointerUnchecked because we checked the addresses above. We could also avoid them - // entirely by walking a couple of pointers... - if (srcStride == dstStride && (u32)width == srcStride) { - // Common case in God of War, let's do it all in one chunk. - u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp; - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * height * bpp); - } else { - for (int y = 0; y < height; y++) { - u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp; - u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp; - - const u8 *src = Memory::GetPointerUnchecked(srcLineStartAddr); - u8 *dst = Memory::GetPointerUnchecked(dstLineStartAddr); - memcpy(dst, src, width * bpp); - } - } - - textureCache_.Invalidate(dstBasePtr + (dstY * dstStride + dstX) * bpp, height * dstStride * bpp, GPU_INVALIDATE_HINT); - framebufferManager_->NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); - } - -#ifndef MOBILE_DEVICE - CBreakPoints::ExecMemCheck(srcBasePtr + (srcY * srcStride + srcX) * bpp, false, height * srcStride * bpp, currentMIPS->pc); - CBreakPoints::ExecMemCheck(dstBasePtr + (srcY * dstStride + srcX) * bpp, true, height * dstStride * bpp, currentMIPS->pc); -#endif - - // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. - cyclesExecuted += ((height * width * bpp) * 16) / 10; -} - void GPU_Vulkan::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { GPUEvent ev(GPU_EVENT_INVALIDATE_CACHE); ev.invalidate_cache.addr = addr; @@ -2096,9 +2009,9 @@ void GPU_Vulkan::InvalidateCache(u32 addr, int size, GPUInvalidationType type) { void GPU_Vulkan::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { if (size > 0) - textureCache_.Invalidate(addr, size, type); + textureCacheVulkan_->Invalidate(addr, size, type); else - textureCache_.InvalidateAll(type); + textureCacheVulkan_->InvalidateAll(type); if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. @@ -2181,7 +2094,7 @@ void GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) { // TODO //framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + textureCacheVulkan_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } @@ -2219,12 +2132,12 @@ bool GPU_Vulkan::PerformStencilUpload(u32 dest, int size) { } void GPU_Vulkan::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); + textureCacheVulkan_->ClearNextFrame(); } void GPU_Vulkan::Resized() { resized_ = true; - framebufferManager_->Resized(); + framebufferManagerVulkan_->Resized(); } void GPU_Vulkan::ClearShaderCache() { @@ -2232,7 +2145,7 @@ void GPU_Vulkan::ClearShaderCache() { } std::vector GPU_Vulkan::GetFramebufferList() { - return framebufferManager_->GetFramebufferList(); + return framebufferManagerVulkan_->GetFramebufferList(); } void GPU_Vulkan::DoState(PointerWrap &p) { @@ -2242,11 +2155,11 @@ void GPU_Vulkan::DoState(PointerWrap &p) { // None of these are necessary when saving. // In Freeze-Frame mode, we don't want to do any of this. if (p.mode == p.MODE_READ && !PSP_CoreParameter().frozen) { - textureCache_.Clear(true); + textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); gstate_c.textureChanged = TEXCHANGE_UPDATED; - framebufferManager_->DestroyAllFBOs(true); + framebufferManagerVulkan_->DestroyAllFBOs(true); shaderManager_->ClearShaders(); pipelineManager_->Clear(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 7aa67b18fa..865144f7fc 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -161,7 +161,6 @@ private: void Flush() { drawEngine_.Flush(nullptr); } - void DoBlockTransfer(u32 skipDrawReason); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); void InitClearInternal(); @@ -178,8 +177,8 @@ private: GraphicsContext *gfxCtx_; VulkanContext *vulkan_; - FramebufferManagerVulkan *framebufferManager_; - TextureCacheVulkan textureCache_; + FramebufferManagerVulkan *framebufferManagerVulkan_; + TextureCacheVulkan *textureCacheVulkan_; DepalShaderCacheVulkan depalShaderCache_; DrawEngineVulkan drawEngine_; From e15cba0e1b485861887f2d663f2ce83771dab44c Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 18:13:58 +0100 Subject: [PATCH 2/6] Centralize "Resized()" --- GPU/Common/FramebufferCommon.h | 2 ++ GPU/Directx9/GPU_DX9.cpp | 7 +------ GPU/Directx9/GPU_DX9.h | 4 +--- GPU/GLES/GPU_GLES.cpp | 7 +------ GPU/GLES/GPU_GLES.h | 3 --- GPU/GPUCommon.cpp | 8 +++++++- GPU/GPUCommon.h | 3 +++ GPU/Vulkan/GPU_Vulkan.cpp | 6 ------ GPU/Vulkan/GPU_Vulkan.h | 3 --- 9 files changed, 15 insertions(+), 28 deletions(-) diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index c3c5069dfa..97fd9204cb 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -236,6 +236,8 @@ public: void SetRenderSize(VirtualFramebuffer *vfb); void SetSafeSize(u16 w, u16 h); + virtual void Resized() = 0; + protected: void UpdateSize(); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index e275c9adf6..826bcc6750 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -394,7 +394,7 @@ static const CommandTableEntry commandTable[] = { GPU_DX9::CommandInfo GPU_DX9::cmdInfo_[256]; GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) -: resized_(false), gfxCtx_(gfxCtx) { +: gfxCtx_(gfxCtx) { lastVsync_ = g_Config.bVSync ? 1 : 0; dxstate.SetVSyncInterval(g_Config.bVSync); @@ -2023,11 +2023,6 @@ void GPU_DX9::ClearCacheNextFrame() { textureCache_.ClearNextFrame(); } -void GPU_DX9::Resized() { - resized_ = true; - framebufferManagerDX9_->Resized(); -} - void GPU_DX9::ClearShaderCache() { shaderManager_->ClearCache(true); } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index c97a6bff3b..c5de8cd987 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -37,6 +37,7 @@ class GPU_DX9 : public GPUCommon { public: GPU_DX9(GraphicsContext *gfxCtx); ~GPU_DX9(); + void CheckGPUFeatures(); void InitClear() override; void PreExecuteOp(u32 op, u32 diff) override; @@ -61,8 +62,6 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { return textureCache_.DecodeTexture(dest, state); @@ -182,7 +181,6 @@ private: static CommandInfo cmdInfo_[256]; - bool resized_; int lastVsync_; std::string reportingPrimaryInfo_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index d2e62efc54..b9d521534b 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -397,7 +397,7 @@ static const CommandTableEntry commandTable[] = { GPU_GLES::CommandInfo GPU_GLES::cmdInfo_[256]; GPU_GLES::GPU_GLES(GraphicsContext *ctx) -: resized_(false), gfxCtx_(ctx) { +: gfxCtx_(ctx) { UpdateVsyncInterval(true); CheckGPUFeatures(); @@ -2284,11 +2284,6 @@ void GPU_GLES::ClearCacheNextFrame() { textureCacheGL_->ClearNextFrame(); } -void GPU_GLES::Resized() { - resized_ = true; - framebufferManagerGL_->Resized(); -} - void GPU_GLES::ClearShaderCache() { shaderManager_->ClearCache(true); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 4daadf7298..97e19feab7 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -65,8 +65,6 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; void CleanupBeforeUI() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { @@ -190,7 +188,6 @@ private: FragmentTestCache fragmentTestCache_; ShaderManager *shaderManager_; - bool resized_; int lastVsync_; std::string reportingPrimaryInfo_; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index cd3c9229e1..bfc3a18ba9 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -26,7 +26,8 @@ GPUCommon::GPUCommon() : dumpNextFrame_(false), dumpThisFrame_(false), - framebufferManager_(nullptr) + framebufferManager_(nullptr), + resized_(false) { // This assert failed on GCC x86 32-bit (but not MSVC 32-bit!) before adding the // "padding" field at the end. This is important for save state compatibility. @@ -98,6 +99,11 @@ bool GPUCommon::BusyDrawing() { return false; } +void GPUCommon::Resized() { + resized_ = true; + framebufferManager_->Resized(); +} + u32 GPUCommon::DrawSync(int mode) { if (ThreadEnabled()) { // Sync first, because the CPU is usually faster than the emulated GPU. diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 2b69994ab5..439bab20c5 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -34,6 +34,8 @@ public: interruptsEnabled_ = enable; } + void Resized() override; + void ExecuteOp(u32 op, u32 diff) override; void PreExecuteOp(u32 op, u32 diff) override; bool InterpretList(DisplayList &list) override; @@ -200,6 +202,7 @@ protected: bool dumpNextFrame_; bool dumpThisFrame_; bool interruptsEnabled_; + bool resized_; private: // For CPU/GPU sync. diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 721f8aa24e..63a110d0a7 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -393,7 +393,6 @@ static const CommandTableEntry commandTable[] = { GPU_Vulkan::GPU_Vulkan(GraphicsContext *ctx) : vulkan_((VulkanContext *)ctx->GetAPIContext()), drawEngine_(vulkan_), - resized_(false), gfxCtx_(ctx) { UpdateVsyncInterval(true); CheckGPUFeatures(); @@ -2135,11 +2134,6 @@ void GPU_Vulkan::ClearCacheNextFrame() { textureCacheVulkan_->ClearNextFrame(); } -void GPU_Vulkan::Resized() { - resized_ = true; - framebufferManagerVulkan_->Resized(); -} - void GPU_Vulkan::ClearShaderCache() { // TODO } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 865144f7fc..091f8f9624 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -67,8 +67,6 @@ public: void DumpNextFrame() override; void DoState(PointerWrap &p) override; - // Called by the window system if the window size changed. This will be reflected in PSPCoreParam.pixel*. - void Resized() override; void ClearShaderCache() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { return false; @@ -188,7 +186,6 @@ private: // Manages state and pipeline objects PipelineManagerVulkan *pipelineManager_; - bool resized_; int lastVsync_; VkCommandBuffer curCmd_; From 866d4a645f349dc9844878ab7f5c6bd17add1cb8 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 18:26:06 +0100 Subject: [PATCH 3/6] Centralize "PerformMemory*" functions --- GPU/Directx9/GPU_DX9.cpp | 81 ----------------------------------- GPU/Directx9/GPU_DX9.h | 6 --- GPU/GLES/GPU_GLES.cpp | 89 ++------------------------------------- GPU/GLES/GPU_GLES.h | 6 --- GPU/GPUCommon.cpp | 84 +++++++++++++++++++++++++++++++++++- GPU/GPUCommon.h | 8 ++++ GPU/Vulkan/GPU_Vulkan.cpp | 81 ----------------------------------- GPU/Vulkan/GPU_Vulkan.h | 6 --- 8 files changed, 95 insertions(+), 266 deletions(-) diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 826bcc6750..14fe75daf2 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1919,91 +1919,10 @@ void GPU_DX9::NotifyVideoUpload(u32 addr, int size, int width, int format) { InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } -void GPU_DX9::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManagerDX9_->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 GPU_DX9::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManagerDX9_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - void GPU_DX9::PerformStencilUploadInternal(u32 dest, int size) { framebufferManagerDX9_->NotifyStencilUpload(dest, size); } -bool GPU_DX9::PerformMemoryCopy(u32 dest, u32 src, int size) { - // Track stray copies of a framebuffer in RAM. MotoGP does this. - if (framebufferManagerDX9_->MayIntersectFramebuffer(src) || framebufferManagerDX9_->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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_DX9::PerformMemorySet(u32 dest, u8 v, int size) { - // This may indicate a memset, usually to 0, of a framebuffer. - if (framebufferManagerDX9_->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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_DX9::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_DX9::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - bool GPU_DX9::PerformStencilUpload(u32 dest, int size) { if (framebufferManagerDX9_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index c5de8cd987..7a96369c29 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -50,10 +50,6 @@ public: void GetStats(char *buffer, size_t bufsize) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - 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; - bool PerformMemoryUpload(u32 dest, int size) override; bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. @@ -168,8 +164,6 @@ private: void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - 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); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index b9d521534b..fd7b8e7053 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -2180,91 +2180,6 @@ void GPU_GLES::NotifyVideoUpload(u32 addr, int size, int width, int format) { InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } -void GPU_GLES::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManagerGL_->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 GPU_GLES::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManagerGL_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - -void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManagerGL_->NotifyStencilUpload(dest, size); -} - -bool GPU_GLES::PerformMemoryCopy(u32 dest, u32 src, int size) { - // Track stray copies of a framebuffer in RAM. MotoGP does this. - if (framebufferManagerGL_->MayIntersectFramebuffer(src) || framebufferManagerGL_->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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_GLES::PerformMemorySet(u32 dest, u8 v, int size) { - // This may indicate a memset, usually to 0, of a framebuffer. - if (framebufferManagerGL_->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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_GLES::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_GLES::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - bool GPU_GLES::PerformStencilUpload(u32 dest, int size) { if (framebufferManagerGL_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { @@ -2377,6 +2292,10 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { #endif } +void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) { + framebufferManager_->NotifyStencilUpload(dest, size); +} + bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCacheGL_->GetCurrentClutBuffer(buffer); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 97e19feab7..12744d9109 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -53,10 +53,6 @@ public: void GetStats(char *buffer, size_t bufsize) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - 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; - bool PerformMemoryUpload(u32 dest, int size) override; bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. @@ -171,8 +167,6 @@ private: void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - 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); void ReinitializeInternal(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index bfc3a18ba9..862c11ae7e 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -20,6 +20,7 @@ #include "Core/HLE/sceKernelThread.h" #include "Core/HLE/sceGe.h" #include "Core/Debugger/Breakpoints.h" +#include "Core/MemMapHelpers.h" #include "GPU/Common/FramebufferCommon.h" #include "GPU/Common/TextureCacheCommon.h" @@ -1412,4 +1413,85 @@ void GPUCommon::DoBlockTransfer(u32 skipDrawReason) { // TODO: Correct timing appears to be 1.9, but erring a bit low since some of our other timing is inaccurate. cyclesExecuted += ((height * width * bpp) * 16) / 10; -} \ No newline at end of file +} + +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); + } + return true; + } + + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + +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); + } + return true; + } + + // Or perhaps a texture, let's invalidate. + InvalidateCache(dest, size, GPU_INVALIDATE_HINT); + return false; +} + +bool GPUCommon::PerformMemoryDownload(u32 dest, int size) { + // Cheat a bit to force a download of the framebuffer. + // VRAM + 0x00400000 is simply a VRAM mirror. + if (Memory::IsVRAMAddress(dest)) { + return PerformMemoryCopy(dest ^ 0x00400000, dest, size); + } + return false; +} + +bool GPUCommon::PerformMemoryUpload(u32 dest, int size) { + // Cheat a bit to force an upload of the framebuffer. + // VRAM + 0x00400000 is simply a VRAM mirror. + if (Memory::IsVRAMAddress(dest)) { + return PerformMemoryCopy(dest, dest ^ 0x00400000, size); + } + return false; +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 439bab20c5..28c766984f 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -60,6 +60,11 @@ public: u32 Break(int mode) override; void ReapplyGfxState() override; + 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; + bool PerformMemoryUpload(u32 dest, int size) override; + void Execute_OffsetAddr(u32 op, u32 diff); void Execute_Origin(u32 op, u32 diff); void Execute_Jump(u32 op, u32 diff); @@ -140,6 +145,9 @@ public: } protected: + void PerformMemoryCopyInternal(u32 dest, u32 src, int size); + void PerformMemorySetInternal(u32 dest, u8 v, int size); + // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 63a110d0a7..85eb8feee4 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -2021,73 +2021,10 @@ void GPU_Vulkan::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType } } -void GPU_Vulkan::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 GPU_Vulkan::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_->NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - } -} - void GPU_Vulkan::PerformStencilUploadInternal(u32 dest, int size) { framebufferManager_->NotifyStencilUpload(dest, size); } -bool GPU_Vulkan::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); - } - return true; - } - - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - -bool GPU_Vulkan::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); - } - return true; - } - - // Or perhaps a texture, let's invalidate. - InvalidateCache(dest, size, GPU_INVALIDATE_HINT); - return false; -} - void GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) { if (Memory::IsVRAMAddress(addr)) { // TODO @@ -2097,24 +2034,6 @@ void GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) { InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); } -bool GPU_Vulkan::PerformMemoryDownload(u32 dest, int size) { - // Cheat a bit to force a download of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest ^ 0x00400000, dest, size); - } - return false; -} - -bool GPU_Vulkan::PerformMemoryUpload(u32 dest, int size) { - // Cheat a bit to force an upload of the framebuffer. - // VRAM + 0x00400000 is simply a VRAM mirror. - if (Memory::IsVRAMAddress(dest)) { - return PerformMemoryCopy(dest, dest ^ 0x00400000, size); - } - return false; -} - bool GPU_Vulkan::PerformStencilUpload(u32 dest, int size) { if (framebufferManager_->MayIntersectFramebuffer(dest)) { if (IsOnSeparateCPUThread()) { diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 091f8f9624..5cbc42497a 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -55,10 +55,6 @@ public: void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - 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; - bool PerformMemoryUpload(u32 dest, int size) override; bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. @@ -164,8 +160,6 @@ private: void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - 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); void ReinitializeInternal(); From 98ebf9ed6fdfe1795ae1c2381ed0656a66217bf1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 18:33:08 +0100 Subject: [PATCH 4/6] Centralize PerformStencil* and Invalidate* functions --- GPU/Common/TextureCacheCommon.h | 1 + GPU/Directx9/GPU_DX9.cpp | 50 -------------------------------- GPU/Directx9/GPU_DX9.h | 7 +---- GPU/GLES/GPU_GLES.cpp | 50 -------------------------------- GPU/GLES/GPU_GLES.h | 6 +--- GPU/GPUCommon.cpp | 50 ++++++++++++++++++++++++++++++++ GPU/GPUCommon.h | 13 +++++++-- GPU/Vulkan/GPU_Vulkan.cpp | 51 --------------------------------- GPU/Vulkan/GPU_Vulkan.h | 5 ---- GPU/Vulkan/TextureCacheVulkan.h | 4 +-- 10 files changed, 65 insertions(+), 172 deletions(-) diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 82e0d0e7c4..4c2be709d6 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -52,6 +52,7 @@ public: virtual bool SetOffsetTexture(u32 offset) = 0; virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0; + virtual void InvalidateAll(GPUInvalidationType type) = 0; // FramebufferManager keeps TextureCache updated about what regions of memory are being rendered to. void NotifyFramebuffer(u32 address, VirtualFramebuffer *framebuffer, FramebufferNotification msg); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 14fe75daf2..f832869d62 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1888,56 +1888,6 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_DX9::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 GPU_DX9::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCache_.Invalidate(addr, size, type); - else - textureCache_.InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManagerDX9_->MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManagerDX9_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_DX9::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - framebufferManagerDX9_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCache_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -void GPU_DX9::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManagerDX9_->NotifyStencilUpload(dest, size); -} - -bool GPU_DX9::PerformStencilUpload(u32 dest, int size) { - if (framebufferManagerDX9_->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); - } - return true; - } - return false; -} - void GPU_DX9::ClearCacheNextFrame() { textureCache_.ClearNextFrame(); } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 7a96369c29..ac158e9948 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -48,9 +48,6 @@ public: void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -158,14 +155,12 @@ private: void Flush() { drawEngine_.Flush(); } - void ApplyDrawState(int prim); + // void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - void PerformStencilUploadInternal(u32 dest, int size); - void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); FramebufferManagerDX9 *framebufferManagerDX9_; TextureCacheDX9 textureCache_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index fd7b8e7053..ecdc37c284 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -2149,52 +2149,6 @@ void GPU_GLES::GetStats(char *buffer, size_t bufsize) { shaderManager_->NumPrograms()); } -void GPU_GLES::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 GPU_GLES::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCacheGL_->Invalidate(addr, size, type); - else - textureCacheGL_->InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManagerGL_->MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManagerGL_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_GLES::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - framebufferManagerGL_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCacheGL_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -bool GPU_GLES::PerformStencilUpload(u32 dest, int size) { - if (framebufferManagerGL_->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); - } - return true; - } - return false; -} - void GPU_GLES::ClearCacheNextFrame() { textureCacheGL_->ClearNextFrame(); } @@ -2292,10 +2246,6 @@ bool GPU_GLES::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { #endif } -void GPU_GLES::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_->NotifyStencilUpload(dest, size); -} - bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { return textureCacheGL_->GetCurrentClutBuffer(buffer); } diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 12744d9109..fdd672808e 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -51,9 +51,7 @@ public: void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; - bool PerformStencilUpload(u32 dest, int size) override; + void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -167,8 +165,6 @@ private: void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - void PerformStencilUploadInternal(u32 dest, int size); - void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); void ReinitializeInternal(); inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index 862c11ae7e..eb24c8a644 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -1495,3 +1495,53 @@ bool GPUCommon::PerformMemoryUpload(u32 dest, int size) { } return false; } + +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 + textureCache_->InvalidateAll(type); + + if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { + // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. + // Vempire invalidates (with writeback) after drawing, but before blitting. + if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { + framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); + } + } +} + +void GPUCommon::NotifyVideoUpload(u32 addr, int size, int width, int format) { + if (Memory::IsVRAMAddress(addr)) { + framebufferManager_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + } + textureCache_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); + InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); +} + +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); + } + return true; + } + return false; +} + +void GPUCommon::PerformStencilUploadInternal(u32 dest, int size) { + framebufferManager_->NotifyStencilUpload(dest, size); +} diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 28c766984f..97853c3b36 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -65,6 +65,10 @@ public: bool PerformMemoryDownload(u32 dest, int size) override; bool PerformMemoryUpload(u32 dest, int size) override; + void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; + void NotifyVideoUpload(u32 addr, int size, int width, int format) override; + bool PerformStencilUpload(u32 dest, int size) override; + void Execute_OffsetAddr(u32 op, u32 diff); void Execute_Origin(u32 op, u32 diff); void Execute_Jump(u32 op, u32 diff); @@ -145,9 +149,6 @@ public: } protected: - void PerformMemoryCopyInternal(u32 dest, u32 src, int size); - void PerformMemorySetInternal(u32 dest, u8 v, int size); - // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); @@ -173,6 +174,11 @@ protected: void AdvanceVerts(u32 vertType, int count, int bytesRead); + 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); + // Allows early unlocking with a guard. Do not double unlock. class easy_guard { public: @@ -213,6 +219,7 @@ protected: bool resized_; private: + // For CPU/GPU sync. #ifdef __ANDROID__ alignas(16) std::atomic curTickEst_; diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 85eb8feee4..88df36e77c 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -1998,57 +1998,6 @@ void GPU_Vulkan::GetStats(char *buffer, size_t bufsize) { ); } -void GPU_Vulkan::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 GPU_Vulkan::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type) { - if (size > 0) - textureCacheVulkan_->Invalidate(addr, size, type); - else - textureCacheVulkan_->InvalidateAll(type); - - if (type != GPU_INVALIDATE_ALL && framebufferManager_->MayIntersectFramebuffer(addr)) { - // If we're doing block transfers, we shouldn't need this, and it'll only confuse us. - // Vempire invalidates (with writeback) after drawing, but before blitting. - if (!g_Config.bBlockTransferGPU || type == GPU_INVALIDATE_SAFE) { - framebufferManager_->UpdateFromMemory(addr, size, type == GPU_INVALIDATE_SAFE); - } - } -} - -void GPU_Vulkan::PerformStencilUploadInternal(u32 dest, int size) { - framebufferManager_->NotifyStencilUpload(dest, size); -} - -void GPU_Vulkan::NotifyVideoUpload(u32 addr, int size, int width, int format) { - if (Memory::IsVRAMAddress(addr)) { - // TODO - //framebufferManager_.NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - } - textureCacheVulkan_->NotifyVideoUpload(addr, size, width, (GEBufferFormat)format); - InvalidateCache(addr, size, GPU_INVALIDATE_SAFE); -} - -bool GPU_Vulkan::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); - } - return true; - } - return false; -} - void GPU_Vulkan::ClearCacheNextFrame() { textureCacheVulkan_->ClearNextFrame(); } diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index 5cbc42497a..f178501f63 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -51,11 +51,8 @@ public: void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; void CopyDisplayToOutput() override; - void NotifyVideoUpload(u32 addr, int size, int width, int format) override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; - void InvalidateCache(u32 addr, int size, GPUInvalidationType type) override; - bool PerformStencilUpload(u32 dest, int size) override; void ClearCacheNextFrame() override; void DeviceLost() override; // Only happens on Android. Drop all textures and shaders. void DeviceRestore() override; @@ -160,8 +157,6 @@ private: void InitClearInternal(); void BeginFrameInternal(); void CopyDisplayToOutputInternal(); - void PerformStencilUploadInternal(u32 dest, int size); - void InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType type); void ReinitializeInternal(); inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index b0fe471449..213c43e491 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -95,8 +95,8 @@ public: void Clear(bool delete_them); void StartFrame(); void EndFrame(); - void Invalidate(u32 addr, int size, GPUInvalidationType type); - void InvalidateAll(GPUInvalidationType type); + void Invalidate(u32 addr, int size, GPUInvalidationType type) override; + void InvalidateAll(GPUInvalidationType type) override; void ClearNextFrame(); void DeviceLost(); From 7634ff7f0932507b305bc9f3807444f97148a397 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 18:51:19 +0100 Subject: [PATCH 5/6] Centralize a few more functions, fix DX9 --- GPU/Directx9/FramebufferDX9.h | 2 +- GPU/Directx9/GPU_DX9.cpp | 42 +++++++++++++++------------------- GPU/Directx9/GPU_DX9.h | 6 ++--- GPU/GLES/Framebuffer.h | 2 +- GPU/GLES/GPU_GLES.cpp | 13 ----------- GPU/GLES/GPU_GLES.h | 3 --- GPU/GPUCommon.cpp | 9 ++++++++ GPU/GPUCommon.h | 2 ++ GPU/Vulkan/FramebufferVulkan.h | 2 +- GPU/Vulkan/GPU_Vulkan.cpp | 17 -------------- GPU/Vulkan/GPU_Vulkan.h | 4 ---- 11 files changed, 34 insertions(+), 68 deletions(-) diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index f11bb5d3ee..e3b6cb844e 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -63,7 +63,7 @@ public: void DestroyAllFBOs(bool forceDelete); void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void CopyDisplayToOutput(); void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index f832869d62..cec624d44e 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -400,18 +400,20 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) framebufferManagerDX9_ = new FramebufferManagerDX9(); framebufferManager_ = framebufferManagerDX9_; + textureCacheDX9_ = new TextureCacheDX9(); + textureCache_ = textureCacheDX9_; shaderManager_ = new ShaderManagerDX9(); drawEngine_.SetShaderManager(shaderManager_); - drawEngine_.SetTextureCache(&textureCache_); + drawEngine_.SetTextureCache(textureCacheDX9_); drawEngine_.SetFramebufferManager(framebufferManagerDX9_); framebufferManagerDX9_->Init(); - framebufferManagerDX9_->SetTextureCache(&textureCache_); + framebufferManagerDX9_->SetTextureCache(textureCacheDX9_); framebufferManagerDX9_->SetShaderManager(shaderManager_); framebufferManagerDX9_->SetTransformDrawEngine(&drawEngine_); - textureCache_.SetFramebufferManager(framebufferManagerDX9_); - textureCache_.SetDepalShaderCache(&depalShaderCache_); - textureCache_.SetShaderManager(shaderManager_); + textureCacheDX9_->SetFramebufferManager(framebufferManagerDX9_); + textureCacheDX9_->SetDepalShaderCache(&depalShaderCache_); + textureCacheDX9_->SetShaderManager(shaderManager_); // Sanity check gstate if ((int *)&gstate.transferstart - (int *)&gstate != 0xEA) { @@ -450,7 +452,7 @@ GPU_DX9::GPU_DX9(GraphicsContext *gfxCtx) // Some of our defaults are different from hw defaults, let's assert them. // We restore each frame anyway, but here is convenient for tests. dxstate.Restore(); - textureCache_.NotifyConfigChanged(); + textureCache_->NotifyConfigChanged(); } void GPU_DX9::UpdateCmdInfo() { @@ -522,7 +524,7 @@ void GPU_DX9::DeviceLost() { // Simply drop all caches and textures. // FBOs appear to survive? Or no? shaderManager_->ClearCache(false); - textureCache_.Clear(false); + textureCacheDX9_->Clear(false); framebufferManagerDX9_->DeviceLost(); } @@ -530,10 +532,6 @@ void GPU_DX9::DeviceRestore() { // Nothing needed. } -void GPU_DX9::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - void GPU_DX9::InitClearInternal() { bool useNonBufferedRendering = g_Config.iRenderingMode == FB_NON_BUFFERED_MODE; if (useNonBufferedRendering) { @@ -560,7 +558,7 @@ void GPU_DX9::BeginFrameInternal() { if (resized_) { UpdateCmdInfo(); drawEngine_.Resized(); - textureCache_.NotifyConfigChanged(); + textureCacheDX9_->NotifyConfigChanged(); resized_ = false; } @@ -573,7 +571,7 @@ void GPU_DX9::BeginFrameInternal() { lastVsync_ = desiredVSyncInterval; } - textureCache_.StartFrame(); + textureCacheDX9_->StartFrame(); drawEngine_.DecimateTrackedVertexArrays(); depalShaderCache_.Decimate(); // fragmentTestCache_.Decimate(); @@ -629,10 +627,6 @@ bool GPU_DX9::FramebufferReallyDirty() { return true; } -void GPU_DX9::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_DX9::CopyDisplayToOutputInternal() { dxstate.depthWrite.set(true); dxstate.colorMask.set(true, true, true, true); @@ -1063,7 +1057,7 @@ void GPU_DX9::Execute_TexLevel(u32 op, u32 diff) { void GPU_DX9::Execute_LoadClut(u32 op, u32 diff) { gstate_c.textureChanged |= TEXCHANGE_PARAMSONLY; - textureCache_.LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); + textureCacheDX9_->LoadClut(gstate.getClutAddress(), gstate.getClutLoadBytes()); // This could be used to "dirty" textures with clut. } @@ -1880,7 +1874,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { gpuStats.numCachedVertsDrawn, gpuStats.numUncachedVertsDrawn, (int)framebufferManagerDX9_->NumVFBs(), - (int)textureCache_.NumLoadedTextures(), + (int)textureCacheDX9_->NumLoadedTextures(), gpuStats.numTexturesDecoded, gpuStats.numTextureInvalidations, shaderManager_->NumVertexShaders(), @@ -1889,7 +1883,7 @@ void GPU_DX9::GetStats(char *buffer, size_t bufsize) { } void GPU_DX9::ClearCacheNextFrame() { - textureCache_.ClearNextFrame(); + textureCacheDX9_->ClearNextFrame(); } void GPU_DX9::ClearShaderCache() { @@ -1906,7 +1900,7 @@ void GPU_DX9::DoState(PointerWrap &p) { // TODO: Some of these things may not be necessary. // None of these are necessary when saving. if (p.mode == p.MODE_READ) { - textureCache_.Clear(true); + textureCacheDX9_->Clear(true); drawEngine_.ClearTrackedVertexArrays(); gstate_c.textureChanged = TEXCHANGE_UPDATED; @@ -1932,8 +1926,8 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { return false; } - textureCache_.SetTexture(true); - textureCache_.ApplyTexture(); + textureCacheDX9_->SetTexture(true); + textureCacheDX9_->ApplyTexture(); int w = gstate.getTextureWidth(level); int h = gstate.getTextureHeight(level); @@ -2017,7 +2011,7 @@ bool GPU_DX9::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { } bool GPU_DX9::GetCurrentClut(GPUDebugBuffer &buffer) { - return textureCache_.GetCurrentClutBuffer(buffer); + return textureCacheDX9_->GetCurrentClutBuffer(buffer); } bool GPU_DX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index ac158e9948..8b8e4f7c15 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -39,13 +39,11 @@ public: ~GPU_DX9(); void CheckGPUFeatures(); - void InitClear() override; void PreExecuteOp(u32 op, u32 diff) override; void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; void ClearCacheNextFrame() override; @@ -57,7 +55,7 @@ public: void ClearShaderCache() override; bool DecodeTexture(u8 *dest, const GPUgstate &state) override { - return textureCache_.DecodeTexture(dest, state); + return textureCacheDX9_->DecodeTexture(dest, state); } bool FramebufferDirty() override; bool FramebufferReallyDirty() override; @@ -163,7 +161,7 @@ private: void CopyDisplayToOutputInternal(); FramebufferManagerDX9 *framebufferManagerDX9_; - TextureCacheDX9 textureCache_; + TextureCacheDX9 *textureCacheDX9_; DepalShaderCacheDX9 depalShaderCache_; DrawEngineDX9 drawEngine_; ShaderManagerDX9 *shaderManager_; diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index ee80abbbf7..5ad05fc819 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -86,7 +86,7 @@ public: virtual void Init() override; void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void CopyDisplayToOutput(); void SetLineWidth(); diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index ecdc37c284..bcc594d5b4 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -664,15 +664,6 @@ void GPU_GLES::DeviceRestore() { UpdateVsyncInterval(true); } -void GPU_GLES::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - -void GPU_GLES::Reinitialize() { - GPUCommon::Reinitialize(); - ScheduleEvent(GPU_EVENT_REINITIALIZE); -} - void GPU_GLES::ReinitializeInternal() { textureCacheGL_->Clear(true); depalShaderCache_.Clear(); @@ -814,10 +805,6 @@ bool GPU_GLES::FramebufferReallyDirty() { return true; } -void GPU_GLES::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_GLES::CopyDisplayToOutputInternal() { // Flush anything left over. framebufferManagerGL_->RebindFramebuffer(); diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index fdd672808e..9abedb937e 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -40,15 +40,12 @@ public: // This gets called on startup and when we get back from settings. void CheckGPUFeatures(); - void InitClear() override; - void Reinitialize() override; void PreExecuteOp(u32 op, u32 diff) override; void Execute_Generic(u32 op, u32 diff); void ExecuteOp(u32 op, u32 diff) override; void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index eb24c8a644..e7368add32 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -56,6 +56,14 @@ 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)); @@ -72,6 +80,7 @@ void GPUCommon::Reinitialize() { timeSpentStepping_ = 0.0; interruptsEnabled_ = true; UpdateTickEstimate(0); + ScheduleEvent(GPU_EVENT_REINITIALIZE); } void GPUCommon::PopDLQueue() { diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index 97853c3b36..bb9871031b 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -60,6 +60,8 @@ public: u32 Break(int mode) override; void ReapplyGfxState() override; + void CopyDisplayToOutput() override; + void InitClear() override; 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; diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index d1742b8c1d..b72f2405e1 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -102,7 +102,7 @@ public: void BeginFrameVulkan(); // there's a BeginFrame in the base class, which this calls void EndFrame(); - void Resized(); + void Resized() override; void DeviceLost(); void DeviceRestore(VulkanContext *vulkan); void CopyDisplayToOutput(); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 88df36e77c..691e32f254 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -601,15 +601,6 @@ void GPU_Vulkan::BuildReportingInfo() { Reporting::UpdateConfig(); } -void GPU_Vulkan::InitClear() { - ScheduleEvent(GPU_EVENT_INIT_CLEAR); -} - -void GPU_Vulkan::Reinitialize() { - GPUCommon::Reinitialize(); - ScheduleEvent(GPU_EVENT_REINITIALIZE); -} - void GPU_Vulkan::ReinitializeInternal() { textureCacheVulkan_->Clear(true); depalShaderCache_.Clear(); @@ -652,10 +643,6 @@ void GPU_Vulkan::UpdateCmdInfo() { // } } -void GPU_Vulkan::ReapplyGfxStateInternal() { - GPUCommon::ReapplyGfxStateInternal(); -} - void GPU_Vulkan::BeginFrameInternal() { } @@ -694,10 +681,6 @@ bool GPU_Vulkan::FramebufferReallyDirty() { return true; } -void GPU_Vulkan::CopyDisplayToOutput() { - ScheduleEvent(GPU_EVENT_COPY_DISPLAY_TO_OUTPUT); -} - void GPU_Vulkan::CopyDisplayToOutputInternal() { // Flush anything left over. drawEngine_.Flush(curCmd_); diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index f178501f63..e7842dd1cf 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -42,15 +42,11 @@ public: void BeginHostFrame() override; void EndHostFrame() override; - void InitClear() override; - void Reinitialize() override; void PreExecuteOp(u32 op, u32 diff) override; void Execute_Generic(u32 op, u32 diff); void ExecuteOp(u32 op, u32 diff) override; - void ReapplyGfxStateInternal() override; void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format) override; - void CopyDisplayToOutput() override; void BeginFrame() override; void GetStats(char *buffer, size_t bufsize) override; void ClearCacheNextFrame() override; From dc5c0c0d2da5d3368fd55a4765be13a29e1a76c1 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 21 Dec 2016 19:58:10 +0100 Subject: [PATCH 6/6] Centralize ProcessEvent --- GPU/Directx9/GPU_DX9.cpp | 35 ----------------------------------- GPU/Directx9/GPU_DX9.h | 8 ++++---- GPU/GLES/GPU_GLES.cpp | 39 --------------------------------------- GPU/GLES/GPU_GLES.h | 11 ++++++----- GPU/GPUCommon.cpp | 29 +++++++++++++++++++++++++++++ GPU/GPUCommon.h | 5 +++++ GPU/Vulkan/GPU_Vulkan.cpp | 39 --------------------------------------- GPU/Vulkan/GPU_Vulkan.h | 10 ++++------ 8 files changed, 48 insertions(+), 128 deletions(-) diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index cec624d44e..cbec9370e3 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -670,41 +670,6 @@ void GPU_DX9::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_DX9::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_DX9::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 8b8e4f7c15..a1bf7ac22a 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -143,7 +143,6 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -156,9 +155,10 @@ private: // void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); + + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; FramebufferManagerDX9 *framebufferManagerDX9_; TextureCacheDX9 *textureCacheDX9_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index bcc594d5b4..5a1215a7bc 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -863,45 +863,6 @@ void GPU_GLES::FinishDeferred() { drawEngine_.FinishDeferred(); } -void GPU_GLES::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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: - ReinitializeInternal(); - break; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_GLES::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { diff --git a/GPU/GLES/GPU_GLES.h b/GPU/GLES/GPU_GLES.h index 9abedb937e..774f6ba208 100644 --- a/GPU/GLES/GPU_GLES.h +++ b/GPU/GLES/GPU_GLES.h @@ -149,7 +149,6 @@ public: protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -159,10 +158,12 @@ private: } void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); - void ReinitializeInternal(); + + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; + void ReinitializeInternal() override; + inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index e7368add32..7e8bb73202 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -698,8 +698,37 @@ void GPUCommon::ProcessEvent(GPUEvent ev) { 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; + default: ERROR_LOG_REPORT(G3D, "Unexpected GPU event type: %d", (int)ev); + break; } } diff --git a/GPU/GPUCommon.h b/GPU/GPUCommon.h index bb9871031b..271373f5a9 100644 --- a/GPU/GPUCommon.h +++ b/GPU/GPUCommon.h @@ -151,6 +151,11 @@ public: } protected: + virtual void InitClearInternal() {} + virtual void BeginFrameInternal() {} + virtual void CopyDisplayToOutputInternal() {} + virtual void ReinitializeInternal() {} + // To avoid virtual calls to PreExecuteOp(). virtual void FastRunLoop(DisplayList &list) = 0; void SlowRunLoop(DisplayList &list); diff --git a/GPU/Vulkan/GPU_Vulkan.cpp b/GPU/Vulkan/GPU_Vulkan.cpp index 691e32f254..f26cacb090 100644 --- a/GPU/Vulkan/GPU_Vulkan.cpp +++ b/GPU/Vulkan/GPU_Vulkan.cpp @@ -722,45 +722,6 @@ void GPU_Vulkan::FastRunLoop(DisplayList &list) { void GPU_Vulkan::FinishDeferred() { } -void GPU_Vulkan::ProcessEvent(GPUEvent ev) { - switch (ev.type) { - 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: - ReinitializeInternal(); - break; - - default: - GPUCommon::ProcessEvent(ev); - } -} - inline void GPU_Vulkan::CheckFlushOp(int cmd, u32 diff) { const u8 cmdFlags = cmdInfo_[cmd].flags; if ((cmdFlags & FLAG_FLUSHBEFORE) || (diff && (cmdFlags & FLAG_FLUSHBEFOREONCHANGE))) { diff --git a/GPU/Vulkan/GPU_Vulkan.h b/GPU/Vulkan/GPU_Vulkan.h index e7842dd1cf..837b066f90 100644 --- a/GPU/Vulkan/GPU_Vulkan.h +++ b/GPU/Vulkan/GPU_Vulkan.h @@ -137,10 +137,8 @@ public: bool GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) override; bool DescribeCodePtr(const u8 *ptr, std::string &name) override; - protected: void FastRunLoop(DisplayList &list) override; - void ProcessEvent(GPUEvent ev) override; void FastLoadBoneMatrix(u32 target) override; void FinishDeferred() override; @@ -150,10 +148,10 @@ private: } void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); - void InitClearInternal(); - void BeginFrameInternal(); - void CopyDisplayToOutputInternal(); - void ReinitializeInternal(); + void InitClearInternal() override; + void BeginFrameInternal() override; + void CopyDisplayToOutputInternal() override; + void ReinitializeInternal() override; inline void UpdateVsyncInterval(bool force); void UpdateCmdInfo(); static CommandInfo cmdInfo_[256];