Download single-use renders right away.

Should prevent issues with the memory being reused soon after, hopefully.
See also #8781 and #7695.
This commit is contained in:
Unknown W. Brackets 2016-06-04 19:36:30 -07:00
parent 6bbcf74926
commit c12f835364
5 changed files with 30 additions and 30 deletions

View file

@ -544,6 +544,20 @@ void FramebufferManagerCommon::UpdateFromMemory(u32 addr, int size, bool safe) {
} }
} }
void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb) {
if (vfb && vfb->safeWidth > 0 && vfb->safeHeight > 0 && !vfb->firstFrameSaved) {
// Some games will draw to some memory once, and use it as a render-to-texture later.
// To support this, we save the first frame to memory when we have a save w/h.
// Saving each frame would be slow.
if (!g_Config.bDisableSlowFramebufEffects) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
vfb->firstFrameSaved = true;
vfb->safeWidth = 0;
vfb->safeHeight = 0;
}
}
}
bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) { bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) {
if (updateVRAM_ || size == 0) { if (updateVRAM_ || size == 0) {
return false; return false;

View file

@ -62,6 +62,7 @@ struct VirtualFramebuffer {
u32 clutUpdatedBytes; u32 clutUpdatedBytes;
bool memoryUpdated; bool memoryUpdated;
bool depthUpdated; bool depthUpdated;
bool firstFrameSaved;
u32 fb_address; u32 fb_address;
u32 z_address; u32 z_address;
@ -252,6 +253,7 @@ protected:
void ShowScreenResolution(); void ShowScreenResolution();
bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const; bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const;
void DownloadFramebufferOnSwitch(VirtualFramebuffer *vfb);
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; 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;
VirtualFramebuffer *FindDownloadTempBuffer(VirtualFramebuffer *vfb); VirtualFramebuffer *FindDownloadTempBuffer(VirtualFramebuffer *vfb);
virtual bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0; virtual bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) = 0;

View file

@ -401,6 +401,8 @@ namespace DX9 {
void FramebufferManagerDX9::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { void FramebufferManagerDX9::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height); ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
} }
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
@ -704,6 +706,8 @@ namespace DX9 {
} }
void FramebufferManagerDX9::CopyDisplayToOutput() { void FramebufferManagerDX9::CopyDisplayToOutput() {
DownloadFramebufferOnSwitch(currentRenderVfb_);
fbo_unbind(); fbo_unbind();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
@ -1218,9 +1222,6 @@ namespace DX9 {
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) { if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--); vfbs_.erase(vfbs_.begin() + i--);
} }
@ -1269,12 +1270,6 @@ namespace DX9 {
for (size_t i = 0; i < vfbs_.size(); ++i) { for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i]; VirtualFramebuffer *vfb = vfbs_[i];
INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format);
if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
// But also let's check if Memory is shut down already.
if (Memory::IsActive()) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
} }
vfbs_.clear(); vfbs_.clear();

View file

@ -654,6 +654,8 @@ void FramebufferManager::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb)
void FramebufferManager::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { void FramebufferManager::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height); ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
} }
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
@ -911,9 +913,10 @@ struct CardboardSettings * FramebufferManager::GetCardboardSettings(struct Cardb
} }
void FramebufferManager::CopyDisplayToOutput() { void FramebufferManager::CopyDisplayToOutput() {
fbo_unbind(); DownloadFramebufferOnSwitch(currentRenderVfb_);
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_);
fbo_unbind();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
if (displayFramebufPtr_ == 0) { if (displayFramebufPtr_ == 0) {
@ -1895,9 +1898,6 @@ void FramebufferManager::DecimateFBOs() {
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) { if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--); vfbs_.erase(vfbs_.begin() + i--);
} }
@ -1936,12 +1936,6 @@ void FramebufferManager::DestroyAllFBOs(bool forceDelete) {
for (size_t i = 0; i < vfbs_.size(); ++i) { for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i]; VirtualFramebuffer *vfb = vfbs_[i];
INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format);
if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
// But also let's check if Memory is shut down already.
if (Memory::IsActive()) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
} }
vfbs_.clear(); vfbs_.clear();

View file

@ -628,6 +628,8 @@ void FramebufferManagerVulkan::NotifyRenderFramebufferCreated(VirtualFramebuffer
void FramebufferManagerVulkan::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) { void FramebufferManagerVulkan::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) { if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height); ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
} else {
DownloadFramebufferOnSwitch(prevVfb);
} }
textureCache_->ForgetLastTexture(); textureCache_->ForgetLastTexture();
@ -819,8 +821,10 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() {
// then in theory, we can even avoid starting up a render pass at all for the backbuffer (!). not sure if that // then in theory, we can even avoid starting up a render pass at all for the backbuffer (!). not sure if that
// is worth the needed refactoring trouble though. // is worth the needed refactoring trouble though.
// fbo_unbind();
DownloadFramebufferOnSwitch(currentRenderVfb_);
// fbo_unbind();
currentRenderVfb_ = 0; currentRenderVfb_ = 0;
if (useBufferedRendering_) { if (useBufferedRendering_) {
@ -1551,9 +1555,6 @@ void FramebufferManagerVulkan::DecimateFBOs() {
if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) {
if (age > FBO_OLD_AGE) { if (age > FBO_OLD_AGE) {
INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age); INFO_LOG(SCEGE, "Decimating FBO for %08x (%i x %i x %i), age %i", vfb->fb_address, vfb->width, vfb->height, vfb->format, age);
if (!g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
vfbs_.erase(vfbs_.begin() + i--); vfbs_.erase(vfbs_.begin() + i--);
} }
@ -1570,12 +1571,6 @@ void FramebufferManagerVulkan::DestroyAllFBOs(bool forceDelete) {
for (size_t i = 0; i < vfbs_.size(); ++i) { for (size_t i = 0; i < vfbs_.size(); ++i) {
VirtualFramebuffer *vfb = vfbs_[i]; VirtualFramebuffer *vfb = vfbs_[i];
INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format); INFO_LOG(SCEGE, "Destroying FBO for %08x : %i x %i x %i", vfb->fb_address, vfb->width, vfb->height, vfb->format);
if (!forceDelete && !g_Config.bDisableSlowFramebufEffects && vfb->safeWidth > 0 && vfb->safeHeight > 0) {
// But also let's check if Memory is shut down already.
if (Memory::IsActive()) {
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->safeWidth, vfb->safeHeight);
}
}
DestroyFramebuf(vfb); DestroyFramebuf(vfb);
} }
vfbs_.clear(); vfbs_.clear();