diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index 88ebcbac98..f6b7e5e17f 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -18,6 +18,9 @@ #include #include +#include "ext/native/thin3d/thin3d.h" +#include "gfx_es2/gpu_features.h" + #include "i18n/i18n.h" #include "Common/Common.h" #include "Core/Config.h" @@ -27,6 +30,7 @@ #include "Core/ELF/ParamSFO.h" #include "Core/System.h" #include "GPU/Common/FramebufferCommon.h" +#include "GPU/Common/TextureCacheCommon.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" @@ -179,6 +183,25 @@ bool FramebufferManagerCommon::ShouldDownloadFramebuffer(const VirtualFramebuffe return updateVRAM_ || (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000); } +void FramebufferManagerCommon::SetNumExtraFBOs(int num) { + for (size_t i = 0; i < extraFBOs_.size(); i++) { + delete extraFBOs_[i]; + } + extraFBOs_.clear(); + for (int i = 0; i < num; i++) { + // No depth/stencil for post processing + Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ (int)renderWidth_, (int)renderHeight_, 1, 1, false, Draw::FBO_8888 }); + extraFBOs_.push_back(fbo); + + // The new FBO is still bound after creation, but let's bind it anyway. + draw_->BindFramebufferAsRenderTarget(fbo); + ClearBuffer(); + } + + currentRenderVfb_ = 0; + draw_->BindBackbufferAsRenderTarget(); +} + // Heuristics to figure out the size of FBO to create. void FramebufferManagerCommon::EstimateDrawingSize(u32 fb_address, GEBufferFormat fb_format, int viewport_width, int viewport_height, int region_width, int region_height, int scissor_width, int scissor_height, int fb_stride, int &drawing_width, int &drawing_height) { static const int MAX_FRAMEBUF_HEIGHT = 512; @@ -476,6 +499,132 @@ VirtualFramebuffer *FramebufferManagerCommon::DoSetRenderFrameBuffer(const Frame return vfb; } +void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) { + textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED); + if (v->fbo) { + delete v->fbo; + v->fbo = nullptr; + } + + // Wipe some pointers + if (currentRenderVfb_ == v) + currentRenderVfb_ = 0; + if (displayFramebuf_ == v) + displayFramebuf_ = 0; + if (prevDisplayFramebuf_ == v) + prevDisplayFramebuf_ = 0; + if (prevPrevDisplayFramebuf_ == v) + prevPrevDisplayFramebuf_ = 0; + + delete v; +} + +void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { + if (!useBufferedRendering_) { + draw_->BindBackbufferAsRenderTarget(); + // Let's ignore rendering to targets that have not (yet) been displayed. + gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; + } + + textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); + + ClearBuffer(); + + // 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::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) { + if (vfbFormatChanged) { + textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED); + if (vfb->drawnFormat != vfb->format) { + 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::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. @@ -553,6 +702,130 @@ void FramebufferManagerCommon::DownloadFramebufferOnSwitch(VirtualFramebuffer *v } } +void FramebufferManagerCommon::DecimateFBOs() { + if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) { + draw_->BindBackbufferAsRenderTarget(); + } + currentRenderVfb_ = 0; + + for (size_t i = 0; i < vfbs_.size(); ++i) { + VirtualFramebuffer *vfb = vfbs_[i]; + int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); + + if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { + bool sync = gl_extensions.IsGLES; + ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height); + } + + // Let's also "decimate" the usageFlags. + UpdateFramebufUsage(vfb); + + if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { + 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); + DestroyFramebuf(vfb); + vfbs_.erase(vfbs_.begin() + i--); + } + } + } + + for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) { + int age = frameLastFramebufUsed_ - it->second.last_frame_used; + if (age > FBO_OLD_AGE) { + delete it->second.fbo; + tempFBOs_.erase(it++); + } else { + ++it; + } + } + + // Do the same for ReadFramebuffersToMemory's VFBs + for (size_t i = 0; i < bvfbs_.size(); ++i) { + VirtualFramebuffer *vfb = bvfbs_[i]; + int age = frameLastFramebufUsed_ - vfb->last_frame_render; + 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); + DestroyFramebuf(vfb); + bvfbs_.erase(bvfbs_.begin() + i--); + } + } +} + +void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { + VirtualFramebuffer old = *vfb; + + if (force) { + vfb->bufferWidth = w; + vfb->bufferHeight = h; + } else { + if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) { + return; + } + + // In case it gets thin and wide, don't resize down either side. + vfb->bufferWidth = std::max(vfb->bufferWidth, w); + vfb->bufferHeight = std::max(vfb->bufferHeight, h); + } + + SetRenderSize(vfb); + + bool trueColor = g_Config.bTrueColor; + if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) { + trueColor = true; + } + + if (trueColor) { + vfb->colorDepth = Draw::FBO_8888; + } else { + switch (vfb->format) { + case GE_FORMAT_4444: + vfb->colorDepth = Draw::FBO_4444; + break; + case GE_FORMAT_5551: + vfb->colorDepth = Draw::FBO_5551; + break; + case GE_FORMAT_565: + vfb->colorDepth = Draw::FBO_565; + break; + case GE_FORMAT_8888: + default: + vfb->colorDepth = Draw::FBO_8888; + break; + } + } + + textureCache_->ForgetLastTexture(); + draw_->BindBackbufferAsRenderTarget(); + + if (!useBufferedRendering_) { + if (vfb->fbo) { + delete vfb->fbo; + vfb->fbo = nullptr; + } + return; + } + + vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth }); + if (old.fbo) { + INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); + if (vfb->fbo) { + draw_->BindFramebufferAsRenderTarget(vfb->fbo); + ClearBuffer(); + if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { + BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); + } + } + delete old.fbo; + if (vfb->fbo) { + draw_->BindFramebufferAsRenderTarget(vfb->fbo); + } + } + + if (!vfb->fbo) { + ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); + } +} + bool FramebufferManagerCommon::NotifyFramebufferCopy(u32 src, u32 dst, int size, bool isMemset, u32 skipDrawReason) { if (updateVRAM_ || size == 0) { return false; @@ -998,6 +1271,46 @@ void FramebufferManagerCommon::SetSafeSize(u16 w, u16 h) { } } +void FramebufferManagerCommon::GetCardboardSettings(CardboardSettings *cardboardSettings) { + // Calculate Cardboard Settings + float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f; + float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale; + float cardboardScreenHeight = pixelHeight_ / 2.0f * cardboardScreenScale; + float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f; + float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift; + float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift; + float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift; + float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f; + float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift; + float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift; + + cardboardSettings->enabled = g_Config.bEnableCardboard; + cardboardSettings->leftEyeXPosition = cardboardLeftEyeX; + cardboardSettings->rightEyeXPosition = cardboardRightEyeX; + cardboardSettings->screenYPosition = cardboardScreenY; + cardboardSettings->screenWidth = cardboardScreenWidth; + cardboardSettings->screenHeight = cardboardScreenHeight; +} + +Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) { + u64 key = ((u64)depth << 32) | ((u32)w << 16) | h; + auto it = tempFBOs_.find(key); + if (it != tempFBOs_.end()) { + it->second.last_frame_used = gpuStats.numFlips; + return it->second.fbo; + } + + textureCache_->ForgetLastTexture(); + Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth }); + if (!fbo) + return fbo; + draw_->BindFramebufferAsRenderTarget(fbo); + ClearBuffer(true); + const TempFBO info = { fbo, gpuStats.numFlips }; + tempFBOs_[key] = info; + return fbo; +} + void FramebufferManagerCommon::UpdateFramebufUsage(VirtualFramebuffer *vfb) { auto checkFlag = [&](u16 flag, int last_frame) { if (vfb->usageFlags & flag) { diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index f54b070e95..cfbf2ad770 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -24,6 +24,7 @@ #include "Core/MemMap.h" #include "GPU/GPU.h" #include "GPU/ge_constants.h" +#include "thin3d/thin3d.h" enum { FB_USAGE_DISPLAYED_FRAMEBUFFER = 1, @@ -50,6 +51,15 @@ namespace Draw { class Framebuffer; } +struct CardboardSettings { + bool enabled; + float leftEyeXPosition; + float rightEyeXPosition; + float screenYPosition; + float screenWidth; + float screenHeight; +}; + class VulkanFBO; struct VirtualFramebuffer { @@ -137,6 +147,8 @@ namespace Draw { class DrawContext; } +class TextureCacheCommon; + class FramebufferManagerCommon { public: FramebufferManagerCommon(Draw::DrawContext *draw); @@ -145,6 +157,7 @@ public: virtual void Init(); void BeginFrame(); void SetDisplayFramebuffer(u32 framebuf, u32 stride, GEBufferFormat format); + void DestroyFramebuf(VirtualFramebuffer *v); VirtualFramebuffer *DoSetRenderFrameBuffer(const FramebufferHeuristicParams ¶ms, u32 skipDrawReason); VirtualFramebuffer *SetRenderFrameBuffer(bool framebufChanged, int skipDrawReason) { @@ -237,13 +250,19 @@ public: virtual void Resized() = 0; + Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888); + protected: + // Cardboard Settings Calculator + void GetCardboardSettings(CardboardSettings *cardboardSettings); + void UpdateSize(); + void SetNumExtraFBOs(int num); virtual void DisableState() = 0; virtual void ClearBuffer(bool keepState = false) = 0; virtual void FlushBeforeCopy() = 0; - virtual void DecimateFBOs() = 0; + virtual void DecimateFBOs(); // keeping it virtual to let D3D do a little extra // Used by ReadFramebufferToMemory and later framebuffer block copies virtual void BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) = 0; @@ -252,12 +271,14 @@ protected: u32 FramebufferByteSize(const VirtualFramebuffer *vfb) const; static bool MaskedEqual(u32 addr1, u32 addr2); - virtual void DestroyFramebuf(VirtualFramebuffer *vfb) = 0; - virtual void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) = 0; - virtual void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) = 0; - virtual void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) = 0; - virtual void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) = 0; + void NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb); + void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged); + void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth); + virtual void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old) = 0; + virtual void BlitFramebufferDepth(VirtualFramebuffer *src, VirtualFramebuffer *dst) = 0; + + void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false); void ShowScreenResolution(); bool ShouldDownloadFramebuffer(const VirtualFramebuffer *vfb) const; @@ -282,6 +303,7 @@ protected: } Draw::DrawContext *draw_; + TextureCacheCommon *textureCache_; u32 displayFramebufPtr_; u32 displayStride_; @@ -315,6 +337,17 @@ protected: int pixelWidth_; int pixelHeight_; + // Used by post-processing shaders + std::vector extraFBOs_; + + + struct TempFBO { + Draw::Framebuffer *fbo; + int last_frame_used; + }; + + std::map tempFBOs_; + // Aggressively delete unused FBOs to save gpu memory. enum { FBO_OLD_AGE = 5, diff --git a/GPU/Common/TextureCacheCommon.h b/GPU/Common/TextureCacheCommon.h index 9fd087a8e0..71eb7bfa8c 100644 --- a/GPU/Common/TextureCacheCommon.h +++ b/GPU/Common/TextureCacheCommon.h @@ -57,6 +57,7 @@ public: virtual bool SetOffsetTexture(u32 offset) = 0; virtual void Invalidate(u32 addr, int size, GPUInvalidationType type) = 0; virtual void InvalidateAll(GPUInvalidationType type) = 0; + virtual void ForgetLastTexture() = 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/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 756f269307..1b37e4ec13 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -178,6 +178,11 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } } + void FramebufferManagerDX9::SetTextureCache(TextureCacheDX9 *tc) { + textureCacheDX9_ = tc; + textureCache_ = tc; + } + void FramebufferManagerDX9::MakePixelTexture(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) { u8 *convBuf = NULL; D3DLOCKED_RECT rect; @@ -273,8 +278,9 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height); DisableState(); - DrawActiveTexture(drawPixelsTex_, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL); - textureCache_->ForgetLastTexture(); + device_->SetTexture(0, drawPixelsTex_); + DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, ROTATION_LOCKED_HORIZONTAL); + textureCacheDX9_->ForgetLastTexture(); dxstate.viewport.restore(); } @@ -289,10 +295,11 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float float x, y, w, h; int uvRotation = (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; CenterDisplayOutputRect(&x, &y, &w, &h, 480.0f, 272.0f, (float)pixelWidth_, (float)pixelHeight_, uvRotation); - DrawActiveTexture(drawPixelsTex_, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, 0.0f, 0.0f, 480.0f / 512.0f, 1.0f, uvRotation); + device_->SetTexture(0, drawPixelsTex_); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, 0.0f, 0.0f, 480.0f / 512.0f, 1.0f, uvRotation); } - void FramebufferManagerDX9::DrawActiveTexture(LPDIRECT3DTEXTURE9 tex, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation) { + void FramebufferManagerDX9::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation) { // TODO: StretchRect instead? float coord[20] = { x,y,0, u0,v0, @@ -337,35 +344,12 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float pD3Ddevice->SetPixelShader(pFramebufferPixelShader); pD3Ddevice->SetVertexShader(pFramebufferVertexShader); shaderManager_->DirtyLastShader(); - if (tex != NULL) { - pD3Ddevice->SetTexture(0, tex); - } HRESULT hr = pD3Ddevice->DrawPrimitiveUP(D3DPT_TRIANGLEFAN, 2, coord, 5 * sizeof(float)); if (FAILED(hr)) { ERROR_LOG_REPORT(G3D, "DrawActiveTexture() failed: %08x", hr); } } - void FramebufferManagerDX9::DestroyFramebuf(VirtualFramebuffer *v) { - textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED); - if (v->fbo) { - delete v->fbo; - v->fbo = nullptr; - } - - // Wipe some pointers - if (currentRenderVfb_ == v) - currentRenderVfb_ = 0; - if (displayFramebuf_ == v) - displayFramebuf_ = 0; - if (prevDisplayFramebuf_ == v) - prevDisplayFramebuf_ = 0; - if (prevPrevDisplayFramebuf_ == v) - prevPrevDisplayFramebuf_ = 0; - - delete v; - } - void FramebufferManagerDX9::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); @@ -374,177 +358,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } } - void FramebufferManagerDX9::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { - VirtualFramebuffer old = *vfb; - - if (force) { - vfb->bufferWidth = w; - vfb->bufferHeight = h; - } else { - if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) { - return; - } - - // In case it gets thin and wide, don't resize down either side. - vfb->bufferWidth = std::max(vfb->bufferWidth, w); - vfb->bufferHeight = std::max(vfb->bufferHeight, h); - } - - SetRenderSize(vfb); - - bool trueColor = g_Config.bTrueColor; - if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) { - trueColor = true; - } - - if (trueColor) { - vfb->colorDepth = Draw::FBO_8888; - } else { - switch (vfb->format) { - case GE_FORMAT_4444: - vfb->colorDepth = Draw::FBO_4444; - break; - case GE_FORMAT_5551: - vfb->colorDepth = Draw::FBO_5551; - break; - case GE_FORMAT_565: - vfb->colorDepth = Draw::FBO_565; - break; - case GE_FORMAT_8888: - default: - vfb->colorDepth = Draw::FBO_8888; - break; - } - } - - textureCache_->ForgetLastTexture(); - draw_->BindBackbufferAsRenderTarget(); - - if (!useBufferedRendering_) { - if (vfb->fbo) { - delete vfb->fbo; - vfb->fbo = nullptr; - } - return; - } - - vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth }); - if (old.fbo) { - INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); - if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - ClearBuffer(); - if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { - BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); - } - } - delete old.fbo; - if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - } - } - - if (!vfb->fbo) { - ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); - } - } - - void FramebufferManagerDX9::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { - if (!useBufferedRendering_) { - draw_->BindBackbufferAsRenderTarget(); - // Let's ignore rendering to targets that have not (yet) been displayed. - gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; - } - - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); - - ClearBuffer(); - - // 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::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); - - // 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::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) { - if (vfbFormatChanged) { - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED); - if (vfb->drawnFormat != vfb->format) { - 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; @@ -673,27 +486,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } } - Draw::Framebuffer *FramebufferManagerDX9::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) { - u64 key = ((u64)depth << 32) | ((u32)w << 16) | h; - auto it = tempFBOs_.find(key); - if (it != tempFBOs_.end()) { - it->second.last_frame_used = gpuStats.numFlips; - return it->second.fbo; - } - - textureCache_->ForgetLastTexture(); - Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth }); - if (!fbo) - return fbo; - draw_->BindFramebufferAsRenderTarget(fbo); - dxstate.viewport.force(0, 0, w, h); - ClearBuffer(true); - dxstate.viewport.restore(); - const TempFBO info = {fbo, gpuStats.numFlips}; - tempFBOs_[key] = info; - return fbo; - } - LPDIRECT3DSURFACE9 FramebufferManagerDX9::GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb) { D3DSURFACE_DESC desc = {}; HRESULT hr = similarSurface->GetDesc(&desc); @@ -713,7 +505,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float return it->second.surface; } - textureCache_->ForgetLastTexture(); + textureCacheDX9_->ForgetLastTexture(); LPDIRECT3DSURFACE9 offscreen = nullptr; HRESULT hr = pD3Ddevice->CreateOffscreenPlainSurface(w, h, fmt, D3DPOOL_SYSTEMMEM, &offscreen, NULL); if (FAILED(hr) || !offscreen) { @@ -918,7 +710,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } dxstate.texMipFilter.set(D3DTEXF_NONE); dxstate.texMipLodBias.set(0); - DrawActiveTexture(0, x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation); + DrawActiveTexture(x, y, w, h, (float)PSP_CoreParameter().pixelWidth, (float)PSP_CoreParameter().pixelHeight, u0, v0, u1, v1, uvRotation); } } /* @@ -963,7 +755,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float PackFramebufferDirectx9_(nvfb, x, y, w, h); - textureCache_->ForgetLastTexture(); + textureCacheDX9_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -997,7 +789,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float PackFramebufferDirectx9_(nvfb, x, y, w, h); - textureCache_->ForgetLastTexture(); + textureCacheDX9_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -1271,43 +1063,7 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float } void FramebufferManagerDX9::DecimateFBOs() { - if (g_Config.iRenderingMode != FB_NON_BUFFERED_MODE) { - draw_->BindBackbufferAsRenderTarget(); - } - currentRenderVfb_ = 0; - bool updateVram = !(g_Config.iRenderingMode == FB_NON_BUFFERED_MODE || g_Config.iRenderingMode == FB_BUFFERED_MODE); - - for (size_t i = 0; i < vfbs_.size(); ++i) { - VirtualFramebuffer *vfb = vfbs_[i]; - int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); - - if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { - ReadFramebufferToMemory(vfb, false, 0, 0, vfb->width, vfb->height); - } - - - // Let's also "decimate" the usageFlags. - UpdateFramebufUsage(vfb); - - if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { - 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); - DestroyFramebuf(vfb); - vfbs_.erase(vfbs_.begin() + i--); - } - } - } - - for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) { - int age = frameLastFramebufUsed_ - it->second.last_frame_used; - if (age > FBO_OLD_AGE) { - delete it->second.fbo; - tempFBOs_.erase(it++); - } else { - ++it; - } - } - + FramebufferManagerCommon::DecimateFBOs(); for (auto it = offscreenSurfaces_.begin(); it != offscreenSurfaces_.end(); ) { int age = frameLastFramebufUsed_ - it->second.last_frame_used; if (age > FBO_OLD_AGE) { @@ -1317,17 +1073,6 @@ static void DXSetViewport(float x, float y, float w, float h, float minZ, float ++it; } } - - // Do the same for ReadFramebuffersToMemory's VFBs - for (size_t i = 0; i < bvfbs_.size(); ++i) { - VirtualFramebuffer *vfb = bvfbs_[i]; - int age = frameLastFramebufUsed_ - vfb->last_frame_render; - 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); - DestroyFramebuf(vfb); - bvfbs_.erase(bvfbs_.begin() + i--); - } - } } void FramebufferManagerDX9::DestroyAllFBOs(bool forceDelete) { diff --git a/GPU/Directx9/FramebufferDX9.h b/GPU/Directx9/FramebufferDX9.h index 392fc1b2d7..cac1144940 100644 --- a/GPU/Directx9/FramebufferDX9.h +++ b/GPU/Directx9/FramebufferDX9.h @@ -45,9 +45,7 @@ public: FramebufferManagerDX9(Draw::DrawContext *draw); ~FramebufferManagerDX9(); - void SetTextureCache(TextureCacheDX9 *tc) { - textureCache_ = tc; - } + void SetTextureCache(TextureCacheDX9 *tc); void SetShaderManager(ShaderManagerDX9 *sm) { shaderManager_ = sm; } @@ -58,7 +56,7 @@ public: virtual void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; virtual void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override; - void DrawActiveTexture(LPDIRECT3DTEXTURE9 texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation); + void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, int uvRotation); void DestroyAllFBOs(bool forceDelete); @@ -66,9 +64,9 @@ public: void Resized() override; void DeviceLost(); void CopyDisplayToOutput(); - void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); + 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); @@ -79,9 +77,6 @@ public: virtual bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - void DestroyFramebuf(VirtualFramebuffer *vfb) override; - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; - bool GetCurrentFramebuffer(GPUDebugBuffer &buffer, GPUDebugFramebufferType type, int maxRes); bool GetCurrentDepthbuffer(GPUDebugBuffer &buffer); bool GetCurrentStencilbuffer(GPUDebugBuffer &buffer); @@ -89,7 +84,6 @@ public: virtual void RebindFramebuffer() override; - Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888); LPDIRECT3DSURFACE9 GetOffscreenSurface(LPDIRECT3DSURFACE9 similarSurface, VirtualFramebuffer *vfb); LPDIRECT3DSURFACE9 GetOffscreenSurface(D3DFORMAT fmt, u32 w, u32 h); @@ -102,9 +96,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 NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override; - void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override; - void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override; bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; @@ -113,8 +104,6 @@ private: void CompileDraw2DProgram(); void DestroyDraw2DProgram(); - void SetNumExtraFBOs(int num); - void PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h); void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); static bool GetRenderTargetFramebuffer(LPDIRECT3DSURFACE9 renderTarget, LPDIRECT3DSURFACE9 offscreen, int w, int h, GPUDebugBuffer &buffer); @@ -137,7 +126,7 @@ private: LPDIRECT3DVERTEXSHADER9 stencilUploadVS_; bool stencilUploadFailed_; - TextureCacheDX9 *textureCache_; + TextureCacheDX9 *textureCacheDX9_; ShaderManagerDX9 *shaderManager_; DrawEngineDX9 *drawEngine_; diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index da3f669197..5c51fde4b9 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -256,7 +256,7 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer pD3Ddevice->SetTexture(0, drawPixelsTex_); shaderManager_->DirtyLastShader(); - textureCache_->ForgetLastTexture(); + textureCacheDX9_->ForgetLastTexture(); for (int i = 1; i < values; i += i) { if (!(usedBits & i)) { diff --git a/GPU/Directx9/TextureCacheDX9.h b/GPU/Directx9/TextureCacheDX9.h index cbe3cd3b52..1767fe4610 100644 --- a/GPU/Directx9/TextureCacheDX9.h +++ b/GPU/Directx9/TextureCacheDX9.h @@ -65,7 +65,7 @@ public: // Only used by Qt UI? bool DecodeTexture(u8 *output, const GPUgstate &state); - void ForgetLastTexture(); + void ForgetLastTexture() override; void SetFramebufferSamplingParams(u16 bufferWidth, u16 bufferHeight); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 056c1bfc95..04b568b6f5 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -114,25 +114,6 @@ void FramebufferManagerGLES::DisableState() { glstate.stencilMask.set(0xFF); } -void FramebufferManagerGLES::SetNumExtraFBOs(int num) { - for (size_t i = 0; i < extraFBOs_.size(); i++) { - delete extraFBOs_[i]; - } - extraFBOs_.clear(); - for (int i = 0; i < num; i++) { - // No depth/stencil for post processing - Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ (int)renderWidth_, (int)renderHeight_, 1, 1, false, Draw::FBO_8888 }); - extraFBOs_.push_back(fbo); - - // The new FBO is still bound after creation, but let's bind it anyway. - draw_->BindFramebufferAsRenderTarget(fbo); - ClearBuffer(); - } - - currentRenderVfb_ = 0; - draw_->BindBackbufferAsRenderTarget(); -} - void FramebufferManagerGLES::CompileDraw2DProgram() { if (!draw2dprogram_) { std::string errorString; @@ -247,7 +228,7 @@ FramebufferManagerGLES::FramebufferManagerGLES(Draw::DrawContext *draw) : timeLoc_(-1), pixelDeltaLoc_(-1), deltaLoc_(-1), - textureCache_(nullptr), + textureCacheGL_(nullptr), shaderManager_(nullptr), resized_(false), pixelBufObj_(nullptr), @@ -263,6 +244,11 @@ void FramebufferManagerGLES::Init() { SetLineWidth(); } +void FramebufferManagerGLES::SetTextureCache(TextureCacheGLES *tc) { + textureCacheGL_ = tc; + textureCache_ = tc; +} + FramebufferManagerGLES::~FramebufferManagerGLES() { if (drawPixelsTex_) glDeleteTextures(1, &drawPixelsTex_); @@ -287,7 +273,7 @@ void FramebufferManagerGLES::MakePixelTexture(const u8 *srcPixels, GEBufferForma } if (!drawPixelsTex_) { - drawPixelsTex_ = textureCache_->AllocTextureName(); + drawPixelsTex_ = textureCacheGL_->AllocTextureName(); drawPixelsTexW_ = width; drawPixelsTexH_ = height; @@ -376,12 +362,12 @@ void FramebufferManagerGLES::DrawPixels(VirtualFramebuffer *vfb, int dstX, int d MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height); DisableState(); - DrawActiveTexture(0, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, v0, 1.0f, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); - textureCache_->ForgetLastTexture(); + bool linearFilter = vfb || g_Config.iBufFilter == SCALE_LINEAR; + DrawActiveTexture(dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, v0, 1.0f, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); + textureCacheGL_->ForgetLastTexture(); } void FramebufferManagerGLES::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) { - MakePixelTexture(srcPixels, srcPixelFormat, srcStride, 512, 272); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iTexFiltering == TEX_FILTER_NEAREST ? GL_NEAREST : GL_LINEAR); @@ -413,36 +399,39 @@ void FramebufferManagerGLES::DrawFramebufferToOutput(const u8 *srcPixels, GEBuff // We are drawing directly to the back buffer. std::swap(v0, v1); + bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR; + GLSLProgram *program = nullptr; + if (applyPostShader && usePostShader_ && useBufferedRendering_) + program = postShaderProgram_; if (cardboardSettings.enabled) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); - } else { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); - } - + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL, linearFilter); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); - } else { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); - } + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL, linearFilter); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); - } else { - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); - } + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, uvRotation, linearFilter); } } // x, y, w, h are relative coordinates against destW/destH, which is not very intuitive. // TODO: This could totally use fbo_blit. -void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation) { +void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation, bool linearFilter) { + if (!program) { + if (!draw2dprogram_) { + CompileDraw2DProgram(); + } + program = draw2dprogram_; + } + + if (program != postShaderProgram_) { + shaderManager_->DirtyLastShader(); // dirty lastShader_ + glsl_bind(program); + } + float texCoords[8] = { u0,v0, u1,v0, @@ -467,11 +456,6 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, memcpy(texCoords, temp, sizeof(temp)); } - if (texture) { - // Previously had NVDrawTexture fallback here but wasn't worth it. - glBindTexture(GL_TEXTURE_2D, texture); - } - float pos[12] = { x,y,0, x+w,y,0, @@ -486,26 +470,13 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, pos[i * 3 + 1] = pos[i * 3 + 1] * invDestH - 1.0f; } - if (!program) { - if (!draw2dprogram_) { - CompileDraw2DProgram(); - } - - program = draw2dprogram_; - } - // Upscaling postshaders doesn't look well with linear - if (postShaderIsUpscalingFilter_) { + if (linearFilter) { + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR); + glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR); + } else { glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_NEAREST); glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_NEAREST); - } else { - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR); - glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, g_Config.iBufFilter == SCALE_NEAREST ? GL_NEAREST : GL_LINEAR); - } - - if (program != postShaderProgram_) { - shaderManager_->DirtyLastShader(); // dirty lastShader_ - glsl_bind(program); } glEnableVertexAttribArray(program->a_position); @@ -525,28 +496,6 @@ void FramebufferManagerGLES::DrawActiveTexture(GLuint texture, float x, float y, } glDisableVertexAttribArray(program->a_position); glDisableVertexAttribArray(program->a_texcoord0); - - glsl_unbind(); -} - -void FramebufferManagerGLES::DestroyFramebuf(VirtualFramebuffer *v) { - textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED); - if (v->fbo) { - delete v->fbo; - v->fbo = nullptr; - } - - // Wipe some pointers - if (currentRenderVfb_ == v) - currentRenderVfb_ = 0; - if (displayFramebuf_ == v) - displayFramebuf_ = 0; - if (prevDisplayFramebuf_ == v) - prevDisplayFramebuf_ = 0; - if (prevPrevDisplayFramebuf_ == v) - prevPrevDisplayFramebuf_ = 0; - - delete v; } void FramebufferManagerGLES::RebindFramebuffer() { @@ -559,177 +508,6 @@ void FramebufferManagerGLES::RebindFramebuffer() { glstate.viewport.restore(); } -void FramebufferManagerGLES::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { - VirtualFramebuffer old = *vfb; - - if (force) { - vfb->bufferWidth = w; - vfb->bufferHeight = h; - } else { - if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) { - return; - } - - // In case it gets thin and wide, don't resize down either side. - vfb->bufferWidth = std::max(vfb->bufferWidth, w); - vfb->bufferHeight = std::max(vfb->bufferHeight, h); - } - - SetRenderSize(vfb); - - bool trueColor = g_Config.bTrueColor; - if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) { - trueColor = true; - } - - if (trueColor) { - vfb->colorDepth = Draw::FBO_8888; - } else { - switch (vfb->format) { - case GE_FORMAT_4444: - vfb->colorDepth = Draw::FBO_4444; - break; - case GE_FORMAT_5551: - vfb->colorDepth = Draw::FBO_5551; - break; - case GE_FORMAT_565: - vfb->colorDepth = Draw::FBO_565; - break; - case GE_FORMAT_8888: - default: - vfb->colorDepth = Draw::FBO_8888; - break; - } - } - - textureCache_->ForgetLastTexture(); - draw_->BindBackbufferAsRenderTarget(); - - if (!useBufferedRendering_) { - if (vfb->fbo) { - delete vfb->fbo; - vfb->fbo = nullptr; - } - return; - } - - vfb->fbo = draw_->CreateFramebuffer({ vfb->renderWidth, vfb->renderHeight, 1, 1, true, (Draw::FBColorDepth)vfb->colorDepth }); - if (old.fbo) { - INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); - if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - ClearBuffer(); - if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { - BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); - } - } - delete old.fbo; - if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - } - } - - if (!vfb->fbo) { - ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); - } -} - -void FramebufferManagerGLES::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { - if (!useBufferedRendering_) { - draw_->BindBackbufferAsRenderTarget(); - // Let's ignore rendering to targets that have not (yet) been displayed. - gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; - } - - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); - - // Some AMD drivers crash if we don't clear the buffer first? - glDisable(GL_DITHER); // why? - ClearBuffer(); - - // ugly... - if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) { - gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX); - } -} - -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); - } - 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) && shaderManager_) { - gstate_c.Dirty(DIRTY_PROJTHROUGHMATRIX); - } -} - -void FramebufferManagerGLES::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) { - if (vfbFormatChanged) { - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED); - if (vfb->drawnFormat != vfb->format) { - 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) { @@ -793,25 +571,6 @@ void FramebufferManagerGLES::BlitFramebufferDepth(VirtualFramebuffer *src, Virtu } } -Draw::Framebuffer *FramebufferManagerGLES::GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth) { - u64 key = ((u64)depth << 32) | ((u32)w << 16) | h; - auto it = tempFBOs_.find(key); - if (it != tempFBOs_.end()) { - it->second.last_frame_used = gpuStats.numFlips; - return it->second.fbo; - } - - textureCache_->ForgetLastTexture(); - Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth }); - if (!fbo) - return fbo; - draw_->BindFramebufferAsRenderTarget(fbo); - ClearBuffer(true); - const TempFBO info = {fbo, gpuStats.numFlips}; - tempFBOs_[key] = info; - return fbo; -} - void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, VirtualFramebuffer *framebuffer, int flags) { if (framebuffer == NULL) { framebuffer = currentRenderVfb_; @@ -876,32 +635,6 @@ void FramebufferManagerGLES::BindFramebufferColor(int stage, u32 fbRawAddress, V } } -struct CardboardSettings * FramebufferManagerGLES::GetCardboardSettings(struct CardboardSettings * cardboardSettings) { - if (cardboardSettings) { - // Calculate Cardboard Settings - float cardboardScreenScale = g_Config.iCardboardScreenSize / 100.0f; - float cardboardScreenWidth = pixelWidth_ / 2.0f * cardboardScreenScale; - float cardboardScreenHeight = pixelHeight_ / 2.0f * cardboardScreenScale; - float cardboardMaxXShift = (pixelWidth_ / 2.0f - cardboardScreenWidth) / 2.0f; - float cardboardUserXShift = g_Config.iCardboardXShift / 100.0f * cardboardMaxXShift; - float cardboardLeftEyeX = cardboardMaxXShift + cardboardUserXShift; - float cardboardRightEyeX = pixelWidth_ / 2.0f + cardboardMaxXShift - cardboardUserXShift; - float cardboardMaxYShift = pixelHeight_ / 2.0f - cardboardScreenHeight / 2.0f; - float cardboardUserYShift = g_Config.iCardboardYShift / 100.0f * cardboardMaxYShift; - float cardboardScreenY = cardboardMaxYShift + cardboardUserYShift; - - // Copy current Settings into Structure - cardboardSettings->enabled = g_Config.bEnableCardboard; - cardboardSettings->leftEyeXPosition = cardboardLeftEyeX; - cardboardSettings->rightEyeXPosition = cardboardRightEyeX; - cardboardSettings->screenYPosition = cardboardScreenY; - cardboardSettings->screenWidth = cardboardScreenWidth; - cardboardSettings->screenHeight = cardboardScreenHeight; - } - - return cardboardSettings; -} - void FramebufferManagerGLES::CopyDisplayToOutput() { DownloadFramebufferOnSwitch(currentRenderVfb_); @@ -931,7 +664,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { u32 offsetX = 0; u32 offsetY = 0; - struct CardboardSettings cardboardSettings; + CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); VirtualFramebuffer *vfb = GetVFBAt(displayFramebufPtr_); @@ -1031,21 +764,22 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { float v1 = (272.0f + offsetY) / (float)vfb->bufferHeight; if (!usePostShader_) { + bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR; // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must // flip V. std::swap(v0, v1); if (cardboardSettings.enabled) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation, linearFilter); } } else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. @@ -1056,7 +790,8 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { shaderManager_->DirtyLastShader(); // dirty lastShader_ glsl_bind(postShaderProgram_); UpdatePostShaderUniforms(vfb->bufferWidth, vfb->bufferHeight, renderWidth_, renderHeight_); - DrawActiveTexture(0, 0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); + bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR; + DrawActiveTexture(0, 0, fbo_w, fbo_h, fbo_w, fbo_h, 0.0f, 0.0f, 1.0f, 1.0f, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL, linearFilter); draw_->BindBackbufferAsRenderTarget(); @@ -1072,18 +807,19 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { // flip V. std::swap(v0, v1); + linearFilter = !postShaderIsUpscalingFilter_ && g_Config.iBufFilter == SCALE_LINEAR; if (g_Config.bEnableCardboard) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, uvRotation, linearFilter); } if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { @@ -1095,6 +831,7 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must // flip V. std::swap(v0, v1); + bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR; shaderManager_->DirtyLastShader(); // dirty lastShader_ glsl_bind(postShaderProgram_); @@ -1102,19 +839,17 @@ void FramebufferManagerGLES::CopyDisplayToOutput() { if (g_Config.bEnableCardboard) { // Left Eye Image glstate.viewport.set(cardboardSettings.leftEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); // Right Eye Image glstate.viewport.set(cardboardSettings.rightEyeXPosition, cardboardSettings.screenYPosition, cardboardSettings.screenWidth, cardboardSettings.screenHeight); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, nullptr, ROTATION_LOCKED_HORIZONTAL, linearFilter); } else { // Fullscreen Image glstate.viewport.set(0, 0, pixelWidth_, pixelHeight_); - DrawActiveTexture(0, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); + DrawActiveTexture(x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation, linearFilter); } } - - glBindTexture(GL_TEXTURE_2D, 0); } } @@ -1148,7 +883,7 @@ void FramebufferManagerGLES::ReadFramebufferToMemory(VirtualFramebuffer *vfb, bo } } - textureCache_->ForgetLastTexture(); + textureCacheGL_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -1186,7 +921,7 @@ void FramebufferManagerGLES::DownloadFramebufferForClut(u32 fb_address, u32 load PackFramebufferSync_(nvfb, x, y, w, h); - textureCache_->ForgetLastTexture(); + textureCacheGL_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -1220,7 +955,7 @@ bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) draw_->BindFramebufferAsRenderTarget(nvfb->fbo); ClearBuffer(); - glDisable(GL_DITHER); + glDisable(GL_DITHER); // Weird place to do this return true; } @@ -1316,9 +1051,9 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, // Should maybe revamp that interface. float srcW = src->bufferWidth; float srcH = src->bufferHeight; - DrawActiveTexture(0, dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(dstX1, dstY1, w * dstXFactor, h, dst->bufferWidth, dst->bufferHeight, srcX1 / srcW, srcY1 / srcH, srcX2 / srcW, srcY2 / srcH, draw2dprogram_, ROTATION_LOCKED_HORIZONTAL, false); glBindTexture(GL_TEXTURE_2D, 0); - textureCache_->ForgetLastTexture(); + textureCacheGL_->ForgetLastTexture(); glstate.viewport.restore(); glstate.blend.restore(); glstate.cullFace.restore(); @@ -1729,9 +1464,6 @@ void FramebufferManagerGLES::EndFrame() { // TODO: Only do this if the new size actually changed the renderwidth/height. DestroyAllFBOs(false); - // Probably not necessary - glstate.viewport.set(0, 0, PSP_CoreParameter().pixelWidth, PSP_CoreParameter().pixelHeight); - // Check if postprocessing shader is doing upscaling as it requires native resolution const ShaderInfo *shaderInfo = 0; if (g_Config.sPostShaderName != "Off") { @@ -1821,53 +1553,6 @@ std::vector FramebufferManagerGLES::GetFramebufferList() { return list; } -void FramebufferManagerGLES::DecimateFBOs() { - draw_->BindBackbufferAsRenderTarget(); - currentRenderVfb_ = 0; - - for (size_t i = 0; i < vfbs_.size(); ++i) { - VirtualFramebuffer *vfb = vfbs_[i]; - int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); - - if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { - bool sync = gl_extensions.IsGLES; - ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height); - } - - // Let's also "decimate" the usageFlags. - UpdateFramebufUsage(vfb); - - if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { - 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); - DestroyFramebuf(vfb); - vfbs_.erase(vfbs_.begin() + i--); - } - } - } - - for (auto it = tempFBOs_.begin(); it != tempFBOs_.end(); ) { - int age = frameLastFramebufUsed_ - it->second.last_frame_used; - if (age > FBO_OLD_AGE) { - delete it->second.fbo; - tempFBOs_.erase(it++); - } else { - ++it; - } - } - - // Do the same for ReadFramebuffersToMemory's VFBs - for (size_t i = 0; i < bvfbs_.size(); ++i) { - VirtualFramebuffer *vfb = bvfbs_[i]; - int age = frameLastFramebufUsed_ - vfb->last_frame_render; - 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); - DestroyFramebuf(vfb); - bvfbs_.erase(bvfbs_.begin() + i--); - } - } -} - void FramebufferManagerGLES::DestroyAllFBOs(bool forceDelete) { draw_->BindBackbufferAsRenderTarget(); currentRenderVfb_ = 0; @@ -1952,7 +1637,7 @@ bool FramebufferManagerGLES::GetFramebuffer(u32 fb_address, int fb_stride, GEBuf glPixelStorei(GL_PACK_ALIGNMENT, 4); SafeGLReadPixels(0, 0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, buffer.GetData()); - // We may have clitted to a temp FBO. + // We may have blitted to a temp FBO. RebindFramebuffer(); return true; } diff --git a/GPU/GLES/FramebufferManagerGLES.h b/GPU/GLES/FramebufferManagerGLES.h index 3f24be3f64..747a9d491b 100644 --- a/GPU/GLES/FramebufferManagerGLES.h +++ b/GPU/GLES/FramebufferManagerGLES.h @@ -51,23 +51,12 @@ struct AsyncPBO { bool reading; }; -struct CardboardSettings { - bool enabled; - float leftEyeXPosition; - float rightEyeXPosition; - float screenYPosition; - float screenWidth; - float screenHeight; -}; - class FramebufferManagerGLES : public FramebufferManagerCommon { public: FramebufferManagerGLES(Draw::DrawContext *draw); ~FramebufferManagerGLES(); - void SetTextureCache(TextureCacheGLES *tc) { - textureCache_ = tc; - } + void SetTextureCache(TextureCacheGLES *tc); void SetShaderManager(ShaderManagerGLES *sm) { shaderManager_ = sm; } @@ -78,9 +67,8 @@ public: void DrawPixels(VirtualFramebuffer *vfb, int dstX, int dstY, const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, int width, int height) override; void DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) override; - // If texture != 0, will bind it. // x,y,w,h are relative to destW, destH which fill out the target completely. - void DrawActiveTexture(GLuint texture, float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation); + void DrawActiveTexture(float x, float y, float w, float h, float destW, float destH, float u0, float v0, float u1, float v1, GLSLProgram *program, int uvRotation, bool linearFilter); void DestroyAllFBOs(bool forceDelete); @@ -90,9 +78,9 @@ public: void DeviceLost(); void CopyDisplayToOutput(); void SetLineWidth(); - void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); + 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); @@ -105,33 +93,21 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - void DestroyFramebuf(VirtualFramebuffer *vfb) override; - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; - bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes); 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 GetOutputFramebuffer(GPUDebugBuffer &buffer); + bool GetOutputFramebuffer(GPUDebugBuffer &buffer); virtual void RebindFramebuffer() override; - Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888); - - // Cardboard Settings Calculator - struct CardboardSettings * GetCardboardSettings(struct CardboardSettings * cardboardSettings); - protected: void DisableState() override; void ClearBuffer(bool keepState = false) override; void FlushBeforeCopy() override; - void DecimateFBOs() override; // 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 NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override; - void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override; - void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override; bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; @@ -141,8 +117,6 @@ private: void CompileDraw2DProgram(); void DestroyDraw2DProgram(); - void SetNumExtraFBOs(int num); - void PackFramebufferAsync_(VirtualFramebuffer *vfb); // Not used under ES currently void PackFramebufferSync_(VirtualFramebuffer *vfb, int x, int y, int w, int h); void PackDepthbuffer(VirtualFramebuffer *vfb, int x, int y, int w, int h); @@ -164,22 +138,12 @@ private: int pixelDeltaLoc_; int deltaLoc_; - TextureCacheGLES *textureCache_; + TextureCacheGLES *textureCacheGL_; ShaderManagerGLES *shaderManager_; DrawEngineGLES *drawEngine_; - // Used by post-processing shader - std::vector extraFBOs_; - bool resized_; - struct TempFBO { - Draw::Framebuffer *fbo; - int last_frame_used; - }; - - std::map tempFBOs_; - // Not used under ES currently. AsyncPBO *pixelBufObj_; //this isn't that large u8 currentPBO_; diff --git a/GPU/GLES/GPU_GLES.cpp b/GPU/GLES/GPU_GLES.cpp index 3b09aa171f..4942dbc9fd 100644 --- a/GPU/GLES/GPU_GLES.cpp +++ b/GPU/GLES/GPU_GLES.cpp @@ -1295,7 +1295,7 @@ bool GPU_GLES::GetCurrentClut(GPUDebugBuffer &buffer) { } bool GPU_GLES::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - return FramebufferManagerGLES::GetOutputFramebuffer(buffer); + return framebufferManagerGL_->GetOutputFramebuffer(buffer); } bool GPU_GLES::GetCurrentSimpleVertices(int count, std::vector &vertices, std::vector &indices) { diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index 1a959e267c..7fbedd23e9 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -190,7 +190,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe glViewport(0, 0, w, h); MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight); - textureCache_->ForgetLastTexture(); + textureCacheGL_->ForgetLastTexture(); glClearStencil(0); glClear(GL_STENCIL_BUFFER_BIT); @@ -215,7 +215,7 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe glstate.stencilMask.set(i); glUniform1f(u_stencilValue, i * (1.0f / 255.0f)); } - DrawActiveTexture(0, 0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, stencilUploadProgram_, ROTATION_LOCKED_HORIZONTAL); + DrawActiveTexture(0, 0, dstBuffer->width, dstBuffer->height, dstBuffer->bufferWidth, dstBuffer->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, stencilUploadProgram_, ROTATION_LOCKED_HORIZONTAL, false); } glstate.stencilMask.set(0xFF); diff --git a/GPU/GLES/TextureCacheGLES.h b/GPU/GLES/TextureCacheGLES.h index 55c9acde24..c031c65ff5 100644 --- a/GPU/GLES/TextureCacheGLES.h +++ b/GPU/GLES/TextureCacheGLES.h @@ -72,7 +72,7 @@ public: return cache.size(); } - void ForgetLastTexture() { + void ForgetLastTexture() override { lastBoundTexture = -1; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); } diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index ae6a427f0f..71fe336a45 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -86,7 +86,7 @@ FramebufferManagerVulkan::FramebufferManagerVulkan(Draw::DrawContext *draw, Vulk drawPixelsTexFormat_(GE_FORMAT_INVALID), convBuf_(nullptr), convBufSize_(0), - textureCache_(nullptr), + textureCacheVulkan_(nullptr), shaderManager_(nullptr), resized_(false), pixelBufObj_(nullptr), @@ -106,6 +106,11 @@ FramebufferManagerVulkan::~FramebufferManagerVulkan() { DestroyDeviceObjects(); } +void FramebufferManagerVulkan::SetTextureCache(TextureCacheVulkan *tc) { + textureCacheVulkan_ = tc; + textureCache_ = tc; +} + void FramebufferManagerVulkan::InitDeviceObjects() { // Create a bunch of render pass objects, for normal rendering with a depth buffer, // with and without pre-clearing of both depth/stencil and color, so 4 combos. @@ -416,7 +421,7 @@ void FramebufferManagerVulkan::DrawPixels(VirtualFramebuffer *vfb, int dstX, int VulkanTexture *pixelTex = MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height); DrawTexture(pixelTex, dstX, dstY, width, height, vfb->bufferWidth, vfb->bufferHeight, 0.0f, 0.0f, 1.0f, 1.0f, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL); - textureCache_->ForgetLastTexture(); + textureCacheVulkan_->ForgetLastTexture(); } void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBufferFormat srcPixelFormat, int srcStride, bool applyPostShader) { @@ -440,7 +445,12 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu VkPipeline postShaderProgram_ = VK_NULL_HANDLE; - struct CardboardSettings cardboardSettings; + VkPipeline program = pipelineBasicTex_; + if (applyPostShader && usePostShader_ && useBufferedRendering_) { + program = postShaderProgram_; + } + + CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); // TODO: Don't use the viewport mechanism for this. @@ -454,20 +464,13 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu vp.width = cardboardSettings.screenWidth; vp.height = cardboardSettings.screenHeight; vkCmdSetViewport(curCmd_, 0, 1, &vp); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); - } else { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL); - } + + DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL); // Right Eye Image vp.x = cardboardSettings.rightEyeXPosition; vkCmdSetViewport(curCmd_, 0, 1, &vp); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, ROTATION_LOCKED_HORIZONTAL); - } else { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, ROTATION_LOCKED_HORIZONTAL); - } + DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, ROTATION_LOCKED_HORIZONTAL); } else { // Fullscreen Image vp.x = 0.0f; @@ -475,11 +478,7 @@ void FramebufferManagerVulkan::DrawFramebufferToOutput(const u8 *srcPixels, GEBu vp.width = pixelWidth_; vp.height = pixelHeight_; vkCmdSetViewport(curCmd_, 0, 1, &vp); - if (applyPostShader && usePostShader_ && useBufferedRendering_) { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, postShaderProgram_, uvRotation); - } else { - DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, pipelineBasicTex_, uvRotation); - } + DrawTexture(pixelTex, x, y, w, h, (float)pixelWidth_, (float)pixelHeight_, u0, v0, u1, v1, program, uvRotation); } } @@ -536,182 +535,11 @@ void FramebufferManagerVulkan::DrawTexture(VulkanTexture *texture, float x, floa vkCmdDraw(cmd, 4, 1, 0, 0); } -void FramebufferManagerVulkan::DestroyFramebuf(VirtualFramebuffer *v) { - textureCache_->NotifyFramebuffer(v->fb_address, v, NOTIFY_FB_DESTROYED); - if (v->fbo) { - delete v->fbo; - v->fbo = 0; - } - - // Wipe some pointers - if (currentRenderVfb_ == v) - currentRenderVfb_ = 0; - if (displayFramebuf_ == v) - displayFramebuf_ = 0; - if (prevDisplayFramebuf_ == v) - prevDisplayFramebuf_ = 0; - if (prevPrevDisplayFramebuf_ == v) - prevPrevDisplayFramebuf_ = 0; - - delete v; -} - void FramebufferManagerVulkan::RebindFramebuffer() { - // Switch command buffer? -} - -void FramebufferManagerVulkan::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force, bool skipCopy) { - return; - - /* - VirtualFramebuffer old = *vfb; - - if (force) { - vfb->bufferWidth = w; - vfb->bufferHeight = h; + if (currentRenderVfb_ && currentRenderVfb_->fbo) { + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); } else { - if (vfb->bufferWidth >= w && vfb->bufferHeight >= h) { - return; - } - - // In case it gets thin and wide, don't resize down either side. - vfb->bufferWidth = std::max(vfb->bufferWidth, w); - vfb->bufferHeight = std::max(vfb->bufferHeight, h); - } - - SetRenderSize(vfb); - - bool trueColor = g_Config.bTrueColor; - if (PSP_CoreParameter().compat.flags().Force04154000Download && vfb->fb_address == 0x00154000) { - trueColor = true; - } - - if (trueColor) { - vfb->colorDepth = VK_FBO_8888; - } else { - switch (vfb->format) { - case GE_FORMAT_4444: - vfb->colorDepth = VK_FBO_4444; - break; - case GE_FORMAT_5551: - vfb->colorDepth = VK_FBO_5551; - break; - case GE_FORMAT_565: - vfb->colorDepth = VK_FBO_565; - break; - case GE_FORMAT_8888: - default: - vfb->colorDepth = VK_FBO_8888; - break; - } - } - - textureCache_->ForgetLastTexture(); - - if (!useBufferedRendering_) { - if (vfb->fbo) { - delete vfb->fbo; - vfb->fbo = 0; - } - return; - } - - vfb->fbo = new VulkanFBO(); - // bo_create(vfb->renderWidth, vfb->renderHeight, 1, true, (FBOColorDepth)vfb->colorDepth); - if (old.fbo) { - INFO_LOG(SCEGE, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); - if (vfb->fbo) { - /// BindFramebufferAsRenderTargetvfb->fbo); - ClearBuffer(); - if (!skipCopy && !g_Config.bDisableSlowFramebufEffects) { - BlitFramebuffer(vfb, 0, 0, &old, 0, 0, std::min(vfb->bufferWidth, vfb->width), std::min(vfb->height, vfb->bufferHeight), 0); - } - } - delete old.fbo; - if (vfb->fbo) { - // BindFramebufferAsRenderTargetvfb->fbo); - } - } - - if (!vfb->fbo) { - ERROR_LOG(SCEGE, "Error creating FBO! %i x %i", vfb->renderWidth, vfb->renderHeight); - } - */ -} - -void FramebufferManagerVulkan::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { - if (!useBufferedRendering_) { - // Let's ignore rendering to targets that have not (yet) been displayed. - gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; - } - - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); - // ugly... - if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) { - gstate_c.Dirty(DIRTY_PROJMATRIX); - } -} - -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); - } - textureCache_->ForgetLastTexture(); - - if (useBufferedRendering_) { - if (vfb->fbo) { - // vfb->fbo->GetColorImageView(); - } - } 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; - } - - // 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); - - // 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); - } -} - -void FramebufferManagerVulkan::NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) { - if (vfbFormatChanged) { - textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_UPDATED); - if (vfb->drawnFormat != vfb->format) { - ReformatFramebufferFrom(vfb, vfb->drawnFormat); - } - } - - // ugly... - if ((gstate_c.curRTWidth != vfb->width || gstate_c.curRTHeight != vfb->height) && shaderManager_) { - gstate_c.Dirty(DIRTY_PROJMATRIX); + draw_->BindBackbufferAsRenderTarget(); } } @@ -721,7 +549,6 @@ bool FramebufferManagerVulkan::NotifyStencilUpload(u32 addr, int size, bool skip return false; } - int FramebufferManagerVulkan::GetLineWidth() { if (g_Config.iInternalResolution == 0) { return std::max(1, (int)(renderWidth_ / 480)); @@ -833,11 +660,6 @@ VulkanTexture *FramebufferManagerVulkan::GetFramebufferColor(u32 fbRawAddress, V } } -struct CardboardSettings * FramebufferManagerVulkan::GetCardboardSettings(struct CardboardSettings * cardboardSettings) { - cardboardSettings->enabled = false; - return nullptr; -} - void FramebufferManagerVulkan::CopyDisplayToOutput() { // This is where we should collect all the renderpasses from this frame, // sort them in order according to texturing dependencies, and enqueue @@ -947,7 +769,7 @@ void FramebufferManagerVulkan::CopyDisplayToOutput() { displayFramebuf_ = vfb; if (vfb->fbo) { - struct CardboardSettings cardboardSettings; + CardboardSettings cardboardSettings; GetCardboardSettings(&cardboardSettings); DEBUG_LOG(SCEGE, "Displaying FBO %08x", vfb->fb_address); @@ -1075,7 +897,7 @@ void FramebufferManagerVulkan::ReadFramebufferToMemory(VirtualFramebuffer *vfb, PackFramebufferSync_(nvfb, x, y, w, h); } - textureCache_->ForgetLastTexture(); + textureCacheVulkan_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -1110,7 +932,7 @@ void FramebufferManagerVulkan::DownloadFramebufferForClut(u32 fb_address, u32 lo PackFramebufferSync_(nvfb, x, y, w, h); - textureCache_->ForgetLastTexture(); + textureCacheVulkan_->ForgetLastTexture(); RebindFramebuffer(); } } @@ -1578,31 +1400,6 @@ std::vector FramebufferManagerVulkan::GetFramebufferList() { return list; } -void FramebufferManagerVulkan::DecimateFBOs() { - currentRenderVfb_ = 0; - - for (size_t i = 0; i < vfbs_.size(); ++i) { - VirtualFramebuffer *vfb = vfbs_[i]; - int age = frameLastFramebufUsed_ - std::max(vfb->last_frame_render, vfb->last_frame_used); - - if (ShouldDownloadFramebuffer(vfb) && age == 0 && !vfb->memoryUpdated) { - bool sync = true; - ReadFramebufferToMemory(vfb, sync, 0, 0, vfb->width, vfb->height); - } - - // Let's also "decimate" the usageFlags. - UpdateFramebufUsage(vfb); - - if (vfb != displayFramebuf_ && vfb != prevDisplayFramebuf_ && vfb != prevPrevDisplayFramebuf_) { - 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); - DestroyFramebuf(vfb); - vfbs_.erase(vfbs_.begin() + i--); - } - } - } -} - void FramebufferManagerVulkan::DestroyAllFBOs(bool forceDelete) { currentRenderVfb_ = 0; displayFramebuf_ = 0; diff --git a/GPU/Vulkan/FramebufferVulkan.h b/GPU/Vulkan/FramebufferVulkan.h index 5ef6bccb54..e96ff88b0c 100644 --- a/GPU/Vulkan/FramebufferVulkan.h +++ b/GPU/Vulkan/FramebufferVulkan.h @@ -64,23 +64,12 @@ struct AsyncPBOVulkan { bool reading; }; -struct CardboardSettings { - bool enabled; - float leftEyeXPosition; - float rightEyeXPosition; - float screenYPosition; - float screenWidth; - float screenHeight; -}; - class FramebufferManagerVulkan : public FramebufferManagerCommon { public: FramebufferManagerVulkan(Draw::DrawContext *draw, VulkanContext *vulkan); ~FramebufferManagerVulkan(); - void SetTextureCache(TextureCacheVulkan *tc) { - textureCache_ = tc; - } + void SetTextureCache(TextureCacheVulkan *tc); void SetShaderManager(ShaderManagerVulkan *sm) { shaderManager_ = sm; } @@ -107,9 +96,9 @@ public: void DeviceRestore(VulkanContext *vulkan); void CopyDisplayToOutput(); int GetLineWidth(); - void ReformatFramebufferFrom(VirtualFramebuffer *vfb, GEBufferFormat old); + 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); @@ -122,9 +111,6 @@ public: bool NotifyStencilUpload(u32 addr, int size, bool skipZero = false) override; - void DestroyFramebuf(VirtualFramebuffer *vfb) override; - void ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, u16 h, bool force = false, bool skipCopy = false) override; - 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); @@ -134,9 +120,6 @@ public: // VulkanFBO *GetTempFBO(u16 w, u16 h, VulkanFBOColorDepth depth = VK_FBO_8888); - // Cardboard Settings Calculator - struct CardboardSettings * GetCardboardSettings(struct CardboardSettings * cardboardSettings); - // Pass management // void BeginPassClear() @@ -151,18 +134,12 @@ protected: void DisableState() override {} void ClearBuffer(bool keepState = false) override; void FlushBeforeCopy() override; - void DecimateFBOs() override; // 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 NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) override; - void NotifyRenderFramebufferSwitched(VirtualFramebuffer *prevVfb, VirtualFramebuffer *vfb, bool isClearingDepth) override; - void NotifyRenderFramebufferUpdated(VirtualFramebuffer *vfb, bool vfbFormatChanged) override; bool CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; void UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) override; - private: // The returned texture does not need to be free'd, might be returned from a pool (currently single entry) @@ -193,7 +170,7 @@ private: u8 *convBuf_; u32 convBufSize_; - TextureCacheVulkan *textureCache_; + TextureCacheVulkan *textureCacheVulkan_; ShaderManagerVulkan *shaderManager_; DrawEngineVulkan *drawEngine_; diff --git a/GPU/Vulkan/TextureCacheVulkan.h b/GPU/Vulkan/TextureCacheVulkan.h index 12c65d5345..69857cac4f 100644 --- a/GPU/Vulkan/TextureCacheVulkan.h +++ b/GPU/Vulkan/TextureCacheVulkan.h @@ -119,7 +119,7 @@ public: return cache.size(); } - void ForgetLastTexture() { + void ForgetLastTexture() override { lastBoundTexture = nullptr; gstate_c.Dirty(DIRTY_TEXTURE_PARAMS); }