Flush draws before doing any block transfers.

Otherwise, we might flush on top, or we might download the wrong thing.
This commit is contained in:
Unknown W. Brackets 2014-06-11 00:28:28 -07:00
parent dd4b191003
commit c49ba888b5
3 changed files with 28 additions and 4 deletions

View File

@ -39,6 +39,7 @@
#include "GPU/Common/TextureDecoder.h"
#include "GPU/GLES/Framebuffer.h"
#include "GPU/GLES/TextureCache.h"
#include "GPU/GLES/TransformPipeline.h"
#include "GPU/GLES/ShaderManager.h"
#include "UI/OnScreenDisplay.h"
@ -1963,6 +1964,7 @@ void FramebufferManager::UpdateFromMemory(u32 addr, int size, bool safe) {
for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i];
if (MaskedEqual(vfb->fb_address, addr)) {
FlushBeforeCopy();
fbo_unbind();
currentRenderVfb_ = 0;
@ -2047,6 +2049,7 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool
} else if (dstBuffer) {
WARN_LOG_REPORT_ONCE(btucpy, G3D, "Memcpy fbo upload %08x -> %08x", src, dst);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(src);
if (useBufferedRendering_ && dstBuffer->fbo) {
fbo_bind_as_render_target(dstBuffer->fbo);
@ -2080,6 +2083,7 @@ bool FramebufferManager::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool
h = srcBuffer->height;
}
if (h > 0) {
FlushBeforeCopy();
ReadFramebufferToMemory(srcBuffer, true, 0, 0, srcBuffer->width, h);
}
}
@ -2176,6 +2180,13 @@ void FramebufferManager::FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer
}
}
void FramebufferManager::FlushBeforeCopy() {
// Flush anything not yet drawn before blitting, downloading, or uploading.
// This might be a stalled list, or unflushed before a block transfer, etc.
SetRenderFrameBuffer();
transformDraw_->Flush();
}
bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride, int dstX, int dstY, u32 srcBasePtr, int srcStride, int srcX, int srcY, int width, int height, int bpp) {
if (!useBufferedRendering_ || updateVRAM_) {
return false;
@ -2199,6 +2210,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride
if (srcX != dstX || srcY != dstY) {
WARN_LOG_ONCE(dstsrc, G3D, "Intra-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
FBO *tempFBO = GetTempFBO(dstBuffer->renderWidth, dstBuffer->renderHeight, dstBuffer->colorDepth);
VirtualFramebuffer tempBuffer = *dstBuffer;
tempBuffer.fbo = tempFBO;
@ -2217,6 +2229,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride
WARN_LOG_ONCE(dstnotsrc, G3D, "Inter-buffer block transfer %08x -> %08x", srcBasePtr, dstBasePtr);
// Just do the blit!
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
BlitFramebuffer_(dstBuffer, dstX, dstY, srcBuffer, srcX, srcY, dstWidth, dstHeight, bpp);
RebindFramebuffer();
return true; // No need to actually do the memory copy behind, probably.
@ -2231,6 +2244,7 @@ bool FramebufferManager::NotifyBlockTransferBefore(u32 dstBasePtr, int dstStride
if (g_Config.bBlockTransferGPU && (srcBuffer == currentRenderVfb_ || !srcBuffer->memoryUpdated)) {
int srcBpp = srcBuffer->format == GE_FORMAT_8888 ? 4 : 2;
float srcXFactor = (float)bpp / srcBpp;
FlushBeforeCopy();
ReadFramebufferToMemory(srcBuffer, true, srcX * srcXFactor, srcY, srcWidth * srcXFactor, srcHeight);
}
return false; // Let the bit copy happen
@ -2250,6 +2264,7 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride,
if (((backBuffer != 0 && dstBasePtr == backBuffer) ||
(displayBuffer != 0 && dstBasePtr == displayBuffer)) &&
dstStride == 512 && height == 272 && !useBufferedRendering_) {
FlushBeforeCopy();
DrawFramebuffer(Memory::GetPointerUnchecked(dstBasePtr), displayFormat_, 512, false);
}
@ -2269,6 +2284,7 @@ void FramebufferManager::NotifyBlockTransferAfter(u32 dstBasePtr, int dstStride,
if (dstBuffer && !srcBuffer) {
WARN_LOG_ONCE(btu, G3D, "Block transfer upload %08x -> %08x", srcBasePtr, dstBasePtr);
if (g_Config.bBlockTransferGPU) {
FlushBeforeCopy();
const u8 *srcBase = Memory::GetPointerUnchecked(srcBasePtr) + (srcX + srcY * srcStride) * bpp;
if (useBufferedRendering_ && dstBuffer->fbo) {
fbo_bind_as_render_target(dstBuffer->fbo);

View File

@ -33,6 +33,8 @@
struct GLSLProgram;
class TextureCache;
class TransformDrawEngine;
class ShaderManager;
enum {
FB_USAGE_DISPLAYED_FRAMEBUFFER = 1,
@ -110,8 +112,6 @@ struct AsyncPBO {
#endif
class ShaderManager;
class FramebufferManager {
public:
FramebufferManager();
@ -123,6 +123,9 @@ public:
void SetShaderManager(ShaderManager *sm) {
shaderManager_ = sm;
}
void SetTransformDrawEngine(TransformDrawEngine *td) {
transformDraw_ = td;
}
void MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height);
@ -232,6 +235,7 @@ public:
private:
void CompileDraw2DProgram();
void DestroyDraw2DProgram();
void FlushBeforeCopy();
void FindTransferFramebuffers(VirtualFramebuffer *&dstBuffer, VirtualFramebuffer *&srcBuffer, u32 dstBasePtr, int dstStride, int &dstX, int &dstY, u32 srcBasePtr, int srcStride, int &srcX, int &srcY, int &srcWidth, int &srcHeight, int &dstWidth, int &dstHeight, int bpp) const;
u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const;
@ -280,6 +284,7 @@ private:
TextureCache *textureCache_;
ShaderManager *shaderManager_;
TransformDrawEngine *transformDraw_;
bool usePostShader_;
bool postShaderAtOutputResolution_;

View File

@ -409,6 +409,7 @@ GLES_GPU::GLES_GPU()
transformDraw_.SetFramebufferManager(&framebufferManager_);
framebufferManager_.SetTextureCache(&textureCache_);
framebufferManager_.SetShaderManager(shaderManager_);
framebufferManager_.SetTransformDrawEngine(&transformDraw_);
textureCache_.SetFramebufferManager(&framebufferManager_);
textureCache_.SetDepalShaderCache(&depalShaderCache_);
textureCache_.SetShaderManager(shaderManager_);
@ -603,11 +604,13 @@ void GLES_GPU::CopyDisplayToOutput() {
}
void GLES_GPU::CopyDisplayToOutputInternal() {
// Flush anything left over.
framebufferManager_.SetRenderFrameBuffer();
transformDraw_.Flush();
glstate.depthWrite.set(GL_TRUE);
glstate.colorMask.set(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE);
transformDraw_.Flush();
framebufferManager_.CopyDisplayToOutput();
framebufferManager_.EndFrame();