mirror of
https://github.com/hrydgard/ppsspp.git
synced 2026-11-15 02:29:51 +01:00
Unify NotifyRenderFramebufferSwitched
This commit is contained in:
1 parent
19868b5df7
commit
27d5c5a2d4
8 files changed
+73
-177
No files matched your search
@@ -19,6 +19,7 @@
|
||||
#include <sstream>
|
||||
|
||||
#include "ext/native/thin3d/thin3d.h"
|
||||
#include "gfx_es2/gpu_features.h"
|
||||
|
||||
#include "i18n/i18n.h"
|
||||
#include "Common/Common.h"
|
||||
@@ -557,6 +558,73 @@ void FramebufferManagerCommon::NotifyRenderFramebufferUpdated(VirtualFramebuffer
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
|
||||
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
|
||||
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
|
||||
} else {
|
||||
DownloadFramebufferOnSwitch(prevVfb);
|
||||
}
|
||||
textureCache_->ForgetLastTexture();
|
||||
|
||||
if (useBufferedRendering_) {
|
||||
if (vfb->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
|
||||
} else {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
}
|
||||
} else {
|
||||
if (vfb->fbo) {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
|
||||
delete vfb->fbo;
|
||||
vfb->fbo = nullptr;
|
||||
}
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
|
||||
// Let's ignore rendering to targets that have not (yet) been displayed.
|
||||
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
|
||||
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
|
||||
} else {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
|
||||
}
|
||||
}
|
||||
textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
|
||||
// to it. This broke stuff before, so now it only clears on the first use of an
|
||||
// FBO in a frame. This means that some games won't be able to avoid the on-some-GPUs
|
||||
// performance-crushing framebuffer reloads from RAM, but we'll have to live with that.
|
||||
if (vfb->last_frame_render != gpuStats.numFlips) {
|
||||
ClearBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
// Copy depth pixel value from the read framebuffer to the draw framebuffer
|
||||
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
|
||||
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
|
||||
// If depth wasn't updated, then we're at least "two degrees" away from the data.
|
||||
// This is an optimization: it probably doesn't need to be copied in this case.
|
||||
} else {
|
||||
BlitFramebufferDepth(prevVfb, vfb);
|
||||
}
|
||||
}
|
||||
if (vfb->drawnFormat != vfb->format) {
|
||||
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
|
||||
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
|
||||
}
|
||||
|
||||
// ugly...
|
||||
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
|
||||
gstate_c.Dirty(DIRTY_PROJMATRIX);
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerCommon::NotifyVideoUpload(u32 addr, int size, int width, GEBufferFormat fmt) {
|
||||
// Note: UpdateFromMemory() is still called later.
|
||||
// This is a special case where we have extra information prior to the invalidation.
|
||||
|
||||
@@ -273,10 +273,11 @@ protected:
|
||||
|
||||
void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb);
|
||||
void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged);
|
||||
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth);
|
||||
|
||||
virtual void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) = 0;
|
||||
virtual void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) = 0;
|
||||
virtual void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) = 0;
|
||||
virtual void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) = 0;
|
||||
|
||||
void ShowScreenResolution();
|
||||
|
||||
|
||||
@@ -433,63 +433,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
|
||||
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
|
||||
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
|
||||
} else {
|
||||
DownloadFramebufferOnSwitch(prevVfb);
|
||||
}
|
||||
textureCacheDX9_->ForgetLastTexture();
|
||||
|
||||
if (useBufferedRendering_) {
|
||||
if (vfb->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
|
||||
} else {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
}
|
||||
} else {
|
||||
if (vfb->fbo) {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
textureCacheDX9_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
|
||||
delete vfb->fbo;
|
||||
vfb->fbo = nullptr;
|
||||
}
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
|
||||
// Let's ignore rendering to targets that have not (yet) been displayed.
|
||||
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
|
||||
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
|
||||
} else {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
|
||||
}
|
||||
}
|
||||
textureCacheDX9_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
|
||||
|
||||
// Copy depth pixel value from the read framebuffer to the draw framebuffer
|
||||
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
|
||||
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
|
||||
// If depth wasn't updated, then we're at least "two degrees" away from the data.
|
||||
// This is an optimization: it probably doesn't need to be copied in this case.
|
||||
} else {
|
||||
BlitFramebufferDepth(prevVfb, vfb);
|
||||
}
|
||||
}
|
||||
if (vfb->drawnFormat != vfb->format) {
|
||||
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
|
||||
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
|
||||
}
|
||||
|
||||
// ugly...
|
||||
if (gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) {
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
if (gstate_c.curRTRenderWidth != vfb->renderWidth || gstate_c.curRTRenderHeight != vfb->renderHeight) {
|
||||
gstate_c.Dirty(DIRTY_PROJMATRIX);
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerDX9::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) {
|
||||
if (!useBufferedRendering_ || !vfb->fbo) {
|
||||
return;
|
||||
|
||||
@@ -66,7 +66,7 @@ public:
|
||||
void CopyDisplayToOutput();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
|
||||
|
||||
void BindFramebufferColor(int stage, VirtualFramebuffer *framebuffer, int flags);
|
||||
|
||||
@@ -98,7 +98,6 @@ protected:
|
||||
// Used by ReadFramebufferToMemory and later framebuffer block copies
|
||||
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
|
||||
|
||||
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
|
||||
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
|
||||
|
||||
@@ -583,69 +583,6 @@ void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
|
||||
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
|
||||
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
|
||||
} else {
|
||||
DownloadFramebufferOnSwitch(prevVfb);
|
||||
}
|
||||
textureCacheGL_->ForgetLastTexture();
|
||||
|
||||
if (useBufferedRendering_) {
|
||||
if (vfb->fbo) {
|
||||
draw_->BindFramebufferAsRenderTarget(vfb->fbo);
|
||||
} else {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
}
|
||||
} else {
|
||||
if (vfb->fbo) {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
textureCacheGL_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
|
||||
delete vfb->fbo;
|
||||
vfb->fbo = nullptr;
|
||||
}
|
||||
draw_->BindBackbufferAsRenderTarget();
|
||||
|
||||
// Let's ignore rendering to targets that have not (yet) been displayed.
|
||||
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
|
||||
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
|
||||
} else {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
|
||||
}
|
||||
}
|
||||
textureCacheGL_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
|
||||
|
||||
if (gl_extensions.IsGLES) {
|
||||
// Some tiled mobile GPUs benefit IMMENSELY from clearing an FBO before rendering
|
||||
// to it. This broke stuff before, so now it only clears on the first use of an
|
||||
// FBO in a frame. This means that some games won't be able to avoid the on-some-GPUs
|
||||
// performance-crushing framebuffer reloads from RAM, but we'll have to live with that.
|
||||
if (vfb->last_frame_render != gpuStats.numFlips) {
|
||||
ClearBuffer();
|
||||
}
|
||||
}
|
||||
|
||||
// Copy depth pixel value from the read framebuffer to the draw framebuffer
|
||||
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
|
||||
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
|
||||
// If depth wasn't updated, then we're at least "two degrees" away from the data.
|
||||
// This is an optimization: it probably doesn't need to be copied in this case.
|
||||
} else {
|
||||
BlitFramebufferDepth(prevVfb, vfb);
|
||||
}
|
||||
}
|
||||
if (vfb->drawnFormat != vfb->format) {
|
||||
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
|
||||
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
|
||||
}
|
||||
|
||||
// ugly...
|
||||
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
|
||||
gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
void FramebufferManagerGLES::SetLineWidth() {
|
||||
#ifndef USING_GLES2
|
||||
if (g_Config.iInternalResolution == 0) {
|
||||
|
||||
@@ -80,7 +80,7 @@ public:
|
||||
void SetLineWidth();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
|
||||
|
||||
// For use when texturing from a framebuffer. May create a duplicate if target.
|
||||
void BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
|
||||
@@ -111,7 +111,6 @@ protected:
|
||||
// Used by ReadFramebufferToMemory and later framebuffer block copies
|
||||
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
|
||||
|
||||
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
|
||||
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
|
||||
|
||||
@@ -624,55 +624,6 @@ void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w,
|
||||
*/
|
||||
}
|
||||
|
||||
void FramebufferManagerVulkan::NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) {
|
||||
if (ShouldDownloadFramebuffer(vfb) && !vfb->memoryUpdated) {
|
||||
ReadFramebufferToMemory(vfb, true, 0, 0, vfb->width, vfb->height);
|
||||
} else {
|
||||
DownloadFramebufferOnSwitch(prevVfb);
|
||||
}
|
||||
textureCacheVulkan_->ForgetLastTexture();
|
||||
|
||||
if (useBufferedRendering_) {
|
||||
if (vfb->fbo) {
|
||||
// vfb->fbo->GetColorImageView();
|
||||
}
|
||||
} else {
|
||||
if (vfb->fbo) {
|
||||
// wtf? This should only happen very briefly when toggling bBufferedRendering
|
||||
textureCacheVulkan_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_DESTROYED);
|
||||
delete vfb->fbo;
|
||||
vfb->fbo = nullptr;
|
||||
}
|
||||
|
||||
// Let's ignore rendering to targets that have not (yet) been displayed.
|
||||
if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) {
|
||||
gstate_c.skipDrawReason &= ~SKIPDRAW_NON_DISPLAYED_FB;
|
||||
} else {
|
||||
gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB;
|
||||
}
|
||||
}
|
||||
textureCacheVulkan_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED);
|
||||
|
||||
// Copy depth pixel value from the read framebuffer to the draw framebuffer
|
||||
if (prevVfb && !g_Config.bDisableSlowFramebufEffects) {
|
||||
if (!prevVfb->fbo || !vfb->fbo || !useBufferedRendering_ || !prevVfb->depthUpdated || isClearingDepth) {
|
||||
// If depth wasn't updated, then we're at least "two degrees" away from the data.
|
||||
// This is an optimization: it probably doesn't need to be copied in this case.
|
||||
} else {
|
||||
BlitFramebufferDepth(prevVfb, vfb);
|
||||
}
|
||||
}
|
||||
if (vfb->drawnFormat != vfb->format) {
|
||||
// TODO: Might ultimately combine this with the resize step in DoSetRenderFrameBuffer().
|
||||
ReformatFramebufferFrom(vfb, vfb->drawnFormat);
|
||||
}
|
||||
|
||||
// ugly...
|
||||
if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) {
|
||||
gstate_c.Dirty(DIRTY_PROJMATRIX);
|
||||
}
|
||||
}
|
||||
|
||||
bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skipZero) {
|
||||
// In Vulkan we should be able to simply copy the stencil data directly to a stencil buffer without
|
||||
// messing about with bitplane textures and the like.
|
||||
|
||||
@@ -98,7 +98,7 @@ public:
|
||||
int GetLineWidth();
|
||||
void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) override;
|
||||
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst);
|
||||
void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) override;
|
||||
|
||||
// For use when texturing from a framebuffer. May create a duplicate if target.
|
||||
VulkanTexture *GetFramebufferColor(u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags);
|
||||
@@ -140,8 +140,6 @@ protected:
|
||||
|
||||
// Used by ReadFramebufferToMemory and later framebuffer block copies
|
||||
void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) override;
|
||||
|
||||
void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override;
|
||||
bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override;
|
||||
|
||||
|
||||
Reference in new issue
Block a user