From d7f4c47c2296ad952b0625be1fbf16b7384849c2 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Wed, 5 Aug 2015 12:13:14 +0200 Subject: [PATCH] Refactor: Even more getting rid of gstate access in the framebuffer manager. --- GPU/Common/FramebufferCommon.cpp | 28 +++++++++--------- GPU/Common/FramebufferCommon.h | 10 +++---- GPU/Directx9/GPU_DX9.cpp | 14 ++++----- GPU/Directx9/GPU_DX9.h | 2 +- GPU/Directx9/StateMappingDX9.cpp | 2 +- GPU/GLES/Framebuffer.cpp | 51 ++++++++++++-------------------- GPU/GLES/Framebuffer.h | 8 ++--- GPU/GLES/GLES_GPU.cpp | 30 +++++++++++++------ GPU/GLES/GLES_GPU.h | 2 +- GPU/GLES/StateMapping.cpp | 4 +-- GPU/GLES/TextureCache.cpp | 4 +-- GPU/GPUState.h | 3 +- 12 files changed, 79 insertions(+), 79 deletions(-) diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index fd0d09509..e9c555109 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -248,7 +248,7 @@ void GetFramebufferHeuristicInputs(FramebufferHeuristicParams *params, const GPU params->scissorHeight = gstate.getScissorY2() + 1; } -VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms) { +VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms, u32 skipDrawReason) { gstate_c.framebufChanged = false; // Collect all parameters. This whole function has really become a cesspool of heuristics... @@ -259,7 +259,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame int drawing_width, drawing_height; EstimateDrawingSize(params.fb_address, params.fmt, params.viewportWidth, params.viewportHeight, params.regionWidth, params.regionHeight, params.scissorWidth, params.scissorHeight, std::max(params.fb_stride, 4), drawing_width, drawing_height); - gstate_c.cutRTOffsetX = 0; + gstate_c.curRTOffsetX = 0; bool vfbFormatChanged = false; // Find a matching framebuffer @@ -290,7 +290,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame if (v->format == params.fmt && v->fb_stride == params.fb_stride && x_offset < params.fb_stride && v->height >= drawing_height) { WARN_LOG_REPORT_ONCE(renderoffset, HLE, "Rendering to framebuffer offset: %08x +%dx%d", v->fb_address, x_offset, 0); vfb = v; - gstate_c.cutRTOffsetX = x_offset; + gstate_c.curRTOffsetX = x_offset; vfb->width = std::max((int)vfb->width, x_offset + drawing_width); // To prevent the newSize code from being confused. drawing_width += x_offset; @@ -355,7 +355,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->drawnHeight = 0; vfb->drawnFormat = params.fmt; vfb->usageFlags = FB_USAGE_RENDERTARGET; - SetColorUpdated(vfb, gstate_c.skipDrawReason); + SetColorUpdated(vfb, skipDrawReason); vfb->depthUpdated = false; u32 byteSize = FramebufferByteSize(vfb); @@ -417,7 +417,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->last_frame_render = gpuStats.numFlips; frameLastFramebufUsed_ = gpuStats.numFlips; vfb->dirtyAfterDisplay = true; - if ((gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) + if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) vfb->reallyDirtyAfterDisplay = true; VirtualFramebuffer *prev = currentRenderVfb_; @@ -427,7 +427,7 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame vfb->last_frame_render = gpuStats.numFlips; frameLastFramebufUsed_ = gpuStats.numFlips; vfb->dirtyAfterDisplay = true; - if ((gstate_c.skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) + if ((skipDrawReason & SKIPDRAW_SKIPFRAME) == 0) vfb->reallyDirtyAfterDisplay = true; NotifyRenderFramebufferUpdated(vfb, vfbFormatChanged); @@ -476,7 +476,7 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) { } } -bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset) { +bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) { if (updateVRAM_ || size == 0) { return false; } @@ -552,7 +552,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, // Just do the blit! if (g_Config.bBlockTransferGPU) { BlitFramebuffer(dstBuffer, 0, dstY, srcBuffer, 0, srcY, srcBuffer->width, srcH, 0); - SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); + SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer(); } } @@ -563,7 +563,7 @@ bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, FlushBeforeCopy(); const u8 *srcBase = Memory::GetPointerUnchecked(src); DrawPixels(dstBuffer, 0, dstY, srcBase, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->width, dstH); - SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); + SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer(); // This is a memcpy, let's still copy just in case. return false; @@ -666,7 +666,7 @@ void FramebufferManagerCommon::FindTransferFramebuffers(VirtualFramebuffer *&dst } } -bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp) { +bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp, u32 skipDrawReason) { if (!useBufferedRendering_ || updateVRAM_) { return false; } @@ -692,7 +692,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst FlushBeforeCopy(); BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp); RebindFramebuffer(); - SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); + SetColorUpdated(dstBuffer, skipDrawReason); return true; } } else { @@ -708,7 +708,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst FlushBeforeCopy(); BlitFramebuffer(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp); RebindFramebuffer(); - SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); + SetColorUpdated(dstBuffer, skipDrawReason); return true; // No need to actually do the memory copy behind, probably. } } @@ -737,7 +737,7 @@ bool FramebufferManagerCommon::NotifyBlockTransferBefore(u32 dstBasePtr, int dst } } -void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp) { +void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp, u32 skipDrawReason) { // A few games use this INSTEAD of actually drawing the video image to the screen, they just blast it to // the backbuffer. Detect this and have the framebuffermanager draw the pixels. @@ -773,7 +773,7 @@ void FramebufferManagerCommon::NotifyBlockTransferAfter(u32 dstBasePtr, int dstS int dstBpp = dstBuffer->format == GE_FORMAT_8888 ? 4 : 2; float dstXFactor = (float)bpp / dstBpp; DrawPixels(dstBuffer, static_cast(dstX * dstXFactor), dstY, srcBase, dstBuffer->format, static_cast(srcStride * dstXFactor), static_cast(dstWidth * dstXFactor), dstHeight); - SetColorUpdated(dstBuffer, gstate_c.skipDrawReason); + SetColorUpdated(dstBuffer, skipDrawReason); RebindFramebuffer(); } } diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 0762fe530..e01ea005f 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -124,7 +124,7 @@ public: void BeginFrame(); void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format); - VirtualFramebuffer *DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms); + VirtualFramebuffer *DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms, u32 skipDrawReason); VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) { // Inlining this part since it's so frequent. if (!framebufChanged && currentRenderVfb_) { @@ -138,19 +138,19 @@ public: // that come from elsewhere than gstate. FramebufferHeuristicParams inputs; GetFramebufferHeuristicInputs(&inputs, gstate); - return DoSetRenderFrameBuffer(inputs); + return DoSetRenderFrameBuffer(inputs, skipDrawReason); } } virtual void RebindFramebuffer() = 0; - bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset = false); + bool NotifyFramebufferCopy(u32 src, u32 dest, int size, bool isMemset, u32 skipDrawReason); void UpdateFromMemory(u32 addr, int size, bool safe); virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) = 0; // Returns true if it's sure this is a direct FBO->FBO transfer and it has already handle it. // In that case we hardly need to actually copy the bytes in VRAM, they will be wrong anyway (unless // read framebuffers is on, in which case this should always return false). - bool NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp); - void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp); + bool NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); + void NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int w, int h, int bpp, u32 skipDrawReason); virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) = 0; virtual void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) = 0; diff --git a/GPU/Directx9/GPU_DX9.cpp b/GPU/Directx9/GPU_DX9.cpp index 9ecef98f7..42502240f 100644 --- a/GPU/Directx9/GPU_DX9.cpp +++ b/GPU/Directx9/GPU_DX9.cpp @@ -1481,8 +1481,8 @@ void DIRECTX9_GPU::Execute_Generic(u32 op, u32 diff) { { // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. - // Can we skip this on SkipDraw? - DoBlockTransfer(); + // Can we skip this entirely on SkipDraw? It skips some things internally. + DoBlockTransfer(gstate_c.skipDrawReason); // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. gstate_c.textureChanged = TEXCHANGE_UPDATED; @@ -1820,7 +1820,7 @@ void DIRECTX9_GPU::UpdateStats() { gpuStats.numFBOs = (int)framebufferManager_.NumVFBs(); } -void DIRECTX9_GPU::DoBlockTransfer() { +void DIRECTX9_GPU::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. @@ -1874,7 +1874,7 @@ void DIRECTX9_GPU::DoBlockTransfer() { } // 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)) { + 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... @@ -1897,7 +1897,7 @@ void DIRECTX9_GPU::DoBlockTransfer() { } 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); + 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); @@ -1931,7 +1931,7 @@ void DIRECTX9_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationTy } void DIRECTX9_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(src, dest, 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) { @@ -1942,7 +1942,7 @@ void DIRECTX9_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { } void DIRECTX9_GPU::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true)) { + if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } } diff --git a/GPU/Directx9/GPU_DX9.h b/GPU/Directx9/GPU_DX9.h index 8b324feaa..6673212ad 100644 --- a/GPU/Directx9/GPU_DX9.h +++ b/GPU/Directx9/GPU_DX9.h @@ -154,7 +154,7 @@ private: void Flush() { transformDraw_.Flush(); } - void DoBlockTransfer(); + void DoBlockTransfer(u32 skipDrawReason); void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); diff --git a/GPU/Directx9/StateMappingDX9.cpp b/GPU/Directx9/StateMappingDX9.cpp index 397251a8e..a98013de0 100644 --- a/GPU/Directx9/StateMappingDX9.cpp +++ b/GPU/Directx9/StateMappingDX9.cpp @@ -671,7 +671,7 @@ void TransformDrawEngineDX9::ApplyDrawState(int prim) { renderHeightFactor = renderHeight / 272.0f; } - renderX += gstate_c.cutRTOffsetX * renderWidthFactor; + renderX += gstate_c.curRTOffsetX * renderWidthFactor; bool throughmode = gstate.isModeThrough(); diff --git a/GPU/GLES/Framebuffer.cpp b/GPU/GLES/Framebuffer.cpp index c9f8defb2..de82f196b 100644 --- a/GPU/GLES/Framebuffer.cpp +++ b/GPU/GLES/Framebuffer.cpp @@ -247,7 +247,7 @@ void FramebufferManager::CompileDraw2DProgram() { usePostShader_ = true; } } else { - postShaderProgram_ = 0; + postShaderProgram_ = nullptr; usePostShader_ = false; } @@ -258,36 +258,36 @@ void FramebufferManager::CompileDraw2DProgram() { void FramebufferManager::DestroyDraw2DProgram() { if (draw2dprogram_) { glsl_destroy(draw2dprogram_); - draw2dprogram_ = 0; + draw2dprogram_ = nullptr; } if (plainColorProgram_) { glsl_destroy(plainColorProgram_); - plainColorProgram_ = 0; + plainColorProgram_ = nullptr; } if (postShaderProgram_) { glsl_destroy(postShaderProgram_); - postShaderProgram_ = 0; + postShaderProgram_ = nullptr; } } FramebufferManager::FramebufferManager() : drawPixelsTex_(0), drawPixelsTexFormat_(GE_FORMAT_INVALID), - convBuf_(0), - draw2dprogram_(0), - postShaderProgram_(0), - stencilUploadProgram_(0), + convBuf_(nullptr), + draw2dprogram_(nullptr), + postShaderProgram_(nullptr), + stencilUploadProgram_(nullptr), plainColorLoc_(-1), timeLoc_(-1), - textureCache_(0), - shaderManager_(0), + textureCache_(nullptr), + shaderManager_(nullptr), usePostShader_(false), postShaderAtOutputResolution_(false), resized_(false), gameUsesSequentialCopies_(false) #ifndef USING_GLES2 , - pixelBufObj_(0), + pixelBufObj_(nullptr), currentPBO_(0) #endif { @@ -703,7 +703,7 @@ void FramebufferManager::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) ClearBuffer(); // ugly... - if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) { + if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height && shaderManager_) { shaderManager_->DirtyUniform(DIRTY_PROJTHROUGHMATRIX); } } @@ -764,7 +764,7 @@ void FramebufferManager::NotifyRenderFramebufferSwitched(VirtualFramebuffer *pre } // ugly... - if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) { + if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height && shaderManager_) { shaderManager_->DirtyUniform(DIRTY_PROJTHROUGHMATRIX); } } @@ -778,7 +778,7 @@ void FramebufferManager::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, } // ugly... - if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) { + if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height && shaderManager_) { shaderManager_->DirtyUniform(DIRTY_PROJTHROUGHMATRIX); } } @@ -875,7 +875,7 @@ FBO *FramebufferManager::GetTempFBO(u16 w, u16 h, FBOColorDepth depth) { return fbo; } -void FramebufferManager::BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, bool skipCopy) { +void FramebufferManager::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, bool skipCopy) { if (framebuffer == NULL) { framebuffer = currentRenderVfb_; } @@ -896,7 +896,7 @@ void FramebufferManager::BindFramebufferColor(int stage, VirtualFramebuffer *fra if (GPUStepping::IsStepping() || g_Config.bDisableSlowFramebufEffects) { skipCopy = true; } - if (!skipCopy && currentRenderVfb_ && framebuffer->fb_address == gstate.getFrameBufRawAddress()) { + if (!skipCopy && currentRenderVfb_ && framebuffer->fb_address == fbRawAddress) { // TODO: Maybe merge with bvfbs_? Not sure if those could be packing, and they're created at a different size. FBO *renderCopy = GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, (FBOColorDepth)framebuffer->colorDepth); if (renderCopy) { @@ -1862,11 +1862,7 @@ void FramebufferManager::Resized() { resized_ = true; } -bool FramebufferManager::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - GEBufferFormat format = gstate.FrameBufFormat(); - +bool FramebufferManager::GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1898,13 +1894,7 @@ bool FramebufferManager::GetDisplayFramebuffer(GPUDebugBuffer &buffer) { return true; } -bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - - u32 z_address = gstate.getDepthBufRawAddress(); - int z_stride = gstate.DepthBufStride(); - +bool FramebufferManager::GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); @@ -1930,10 +1920,7 @@ bool FramebufferManager::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { #endif } -bool FramebufferManager::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - u32 fb_address = gstate.getFrameBufRawAddress(); - int fb_stride = gstate.FrameBufStride(); - +bool FramebufferManager::GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer) { VirtualFramebuffer *vfb = currentRenderVfb_; if (!vfb) { vfb = GetVFBAt(fb_address); diff --git a/GPU/GLES/Framebuffer.h b/GPU/GLES/Framebuffer.h index a0af393a7..27b784807 100644 --- a/GPU/GLES/Framebuffer.h +++ b/GPU/GLES/Framebuffer.h @@ -101,7 +101,7 @@ public: void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst); // For use when texturing from a framebuffer. May create a duplicate if target. - void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, bool skipCopy = false); + void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, bool skipCopy = false); // Reads a rectangular subregion of a framebuffer to the right position in its backing memory. virtual void ReadFramebufferToMemory(VirtualFramebuffer *vfb, bool sync, int x, int y, int w, int h) override; @@ -113,9 +113,9 @@ public: void DestroyFramebuf(VirtualFramebuffer *vfb); void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false); - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer); - bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); - bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); + bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer); + bool GetDepthbuffer(u32 fb_address, int fb_stride, u32 z_address, int z_stride, GPUDebugBuffer &buffer); + bool GetStencilbuffer(u32 fb_address, int fb_stride, GPUDebugBuffer &buffer); static bool GetDisplayFramebuffer(GPUDebugBuffer &buffer); virtual void RebindFramebuffer() override; diff --git a/GPU/GLES/GLES_GPU.cpp b/GPU/GLES/GLES_GPU.cpp index 8d2edb8d4..8cc3be391 100644 --- a/GPU/GLES/GLES_GPU.cpp +++ b/GPU/GLES/GLES_GPU.cpp @@ -1396,7 +1396,7 @@ void GLES_GPU::Execute_BlockTransferStart(u32 op, u32 diff) { // TODO: Here we should check if the transfer overlaps a framebuffer or any textures, // and take appropriate action. This is a block transfer between RAM and VRAM, or vice versa. // Can we skip this on SkipDraw? - DoBlockTransfer(); + DoBlockTransfer(gstate_c.skipDrawReason); // Fixes Gran Turismo's funky text issue, since it overwrites the current texture. gstate_c.textureChanged = TEXCHANGE_UPDATED; @@ -1959,7 +1959,7 @@ void GLES_GPU::UpdateStats() { gpuStats.numFBOs = (int)framebufferManager_.NumVFBs(); } -void GLES_GPU::DoBlockTransfer() { +void GLES_GPU::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. @@ -2013,7 +2013,7 @@ void GLES_GPU::DoBlockTransfer() { } // 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)) { + 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... @@ -2036,7 +2036,7 @@ void GLES_GPU::DoBlockTransfer() { } 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); + framebufferManager_.NotifyBlockTransferAfter(dstBasePtr, dstStride, dstX, dstY, srcBasePtr, srcStride, srcX, srcY, width, height, bpp, skipDrawReason); } #ifndef MOBILE_DEVICE @@ -2072,7 +2072,7 @@ void GLES_GPU::InvalidateCacheInternal(u32 addr, int size, GPUInvalidationType t } void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(src, dest, 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) { @@ -2083,7 +2083,7 @@ void GLES_GPU::PerformMemoryCopyInternal(u32 dest, u32 src, int size) { } void GLES_GPU::PerformMemorySetInternal(u32 dest, u8 v, int size) { - if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true)) { + if (!framebufferManager_.NotifyFramebufferCopy(dest, dest, size, true, gstate_c.skipDrawReason)) { InvalidateCache(dest, size, GPU_INVALIDATE_HINT); } } @@ -2213,15 +2213,27 @@ void GLES_GPU::DoState(PointerWrap &p) { } bool GLES_GPU::GetCurrentFramebuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentFramebuffer(buffer); + u32 fb_address = gstate.getFrameBufRawAddress(); + int fb_stride = gstate.FrameBufStride(); + GEBufferFormat format = gstate.FrameBufFormat(); + return framebufferManager_.GetFramebuffer(fb_address, fb_stride, format, buffer); } bool GLES_GPU::GetCurrentDepthbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentDepthbuffer(buffer); + u32 fb_address = gstate.getFrameBufRawAddress(); + int fb_stride = gstate.FrameBufStride(); + + u32 z_address = gstate.getDepthBufRawAddress(); + int z_stride = gstate.DepthBufStride(); + + return framebufferManager_.GetDepthbuffer(fb_address, fb_stride, z_address, z_stride, buffer); } bool GLES_GPU::GetCurrentStencilbuffer(GPUDebugBuffer &buffer) { - return framebufferManager_.GetCurrentStencilbuffer(buffer); + u32 fb_address = gstate.getFrameBufRawAddress(); + int fb_stride = gstate.FrameBufStride(); + + return framebufferManager_.GetStencilbuffer(fb_address, fb_stride, buffer); } bool GLES_GPU::GetCurrentTexture(GPUDebugBuffer &buffer, int level) { diff --git a/GPU/GLES/GLES_GPU.h b/GPU/GLES/GLES_GPU.h index bbbc98d08..711f34c72 100644 --- a/GPU/GLES/GLES_GPU.h +++ b/GPU/GLES/GLES_GPU.h @@ -155,7 +155,7 @@ private: void Flush() { transformDraw_.Flush(); } - void DoBlockTransfer(); + void DoBlockTransfer(u32 skipDrawReason); void ApplyDrawState(int prim); void CheckFlushOp(int cmd, u32 diff); void BuildReportingInfo(); diff --git a/GPU/GLES/StateMapping.cpp b/GPU/GLES/StateMapping.cpp index 4484b6ff8..f9f77dc97 100644 --- a/GPU/GLES/StateMapping.cpp +++ b/GPU/GLES/StateMapping.cpp @@ -190,7 +190,7 @@ bool TransformDrawEngine::ApplyShaderBlending() { return false; } - framebufferManager_->BindFramebufferColor(GL_TEXTURE1, NULL); + framebufferManager_->BindFramebufferColor(GL_TEXTURE1, gstate.getFrameBufRawAddress(), nullptr); glActiveTexture(GL_TEXTURE1); // If we are rendering at a higher resolution, linear is probably best for the dest color. glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); @@ -743,7 +743,7 @@ void TransformDrawEngine::ApplyDrawState(int prim) { renderHeightFactor = renderHeight / 272.0f; } - renderX += gstate_c.cutRTOffsetX * renderWidthFactor; + renderX += gstate_c.curRTOffsetX * renderWidthFactor; // Scissor int scissorX1 = gstate.getScissorX1(); diff --git a/GPU/GLES/TextureCache.cpp b/GPU/GLES/TextureCache.cpp index 7d4bb7613..d953087a8 100644 --- a/GPU/GLES/TextureCache.cpp +++ b/GPU/GLES/TextureCache.cpp @@ -1016,7 +1016,7 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe glBindTexture(GL_TEXTURE_2D, clutTexture); glActiveTexture(GL_TEXTURE0); - framebufferManager_->BindFramebufferColor(GL_TEXTURE0, framebuffer, true); + framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer, true); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); @@ -1049,7 +1049,7 @@ void TextureCache::SetTextureFramebuffer(TexCacheEntry *entry, VirtualFramebuffe gstate_c.textureSimpleAlpha = alphaStatus == TexCacheEntry::STATUS_ALPHA_SIMPLE; } else { entry->status &= ~TexCacheEntry::STATUS_DEPALETTIZE; - framebufferManager_->BindFramebufferColor(GL_TEXTURE0, framebuffer); + framebufferManager_->BindFramebufferColor(GL_TEXTURE0, gstate.getFrameBufRawAddress(), framebuffer); gstate_c.textureFullAlpha = gstate.getTextureFormat() == GE_TFMT_5650; gstate_c.textureSimpleAlpha = gstate_c.textureFullAlpha; diff --git a/GPU/GPUState.h b/GPU/GPUState.h index cc8e3d339..2b808fc16 100644 --- a/GPU/GPUState.h +++ b/GPU/GPUState.h @@ -482,11 +482,12 @@ struct GPUStateCache { float vpWidthScale; float vpHeightScale; + // TODO: These should be accessed from the current VFB object directly. u32 curRTWidth; u32 curRTHeight; u32 curRTRenderWidth; u32 curRTRenderHeight; - u32 cutRTOffsetX; + u32 curRTOffsetX; u32 getRelativeAddress(u32 data) const; void DoState(PointerWrap &p);