diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index b7d89316be..3f3716e248 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -211,7 +211,7 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) { } currentRenderVfb_ = 0; - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } // Heuristics to figure out the size of FBO to create. @@ -533,7 +533,7 @@ void FramebufferManagerCommon::DestroyFramebuf(VirtualFramebuffer *v) { void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer *vfb) { if (!useBufferedRendering_) { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); // Let's ignore rendering to targets that have not (yet) been displayed. gstate_c.skipDrawReason |= SKIPDRAW_NON_DISPLAYED_FB; } @@ -593,7 +593,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe delete vfb->fbo; vfb->fbo = nullptr; } - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); // Let's ignore rendering to targets that have not (yet) been displayed. if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { @@ -833,7 +833,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { if (displayFramebufPtr_ == 0) { DEBUG_LOG(FRAMEBUF, "Display disabled, displaying only black"); // No framebuffer to display! Clear to black. - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); ClearBuffer(); return; } @@ -884,7 +884,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } } - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); if (useBufferedRendering_) { draw_->Clear(Draw::FB_COLOR_BIT | Draw::FB_STENCIL_BIT | Draw::FB_DEPTH_BIT, 0, 0, 0); } @@ -978,7 +978,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { 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, ROTATION_LOCKED_HORIZONTAL, linearFilter); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); // Use the extra FBO, with applied post-processing shader, as a texture. // fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); @@ -1047,7 +1047,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { void FramebufferManagerCommon::DecimateFBOs() { if (useBufferedRendering_) { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } currentRenderVfb_ = 0; @@ -1139,7 +1139,7 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, } textureCache_->ForgetLastTexture(); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); if (!useBufferedRendering_) { if (vfb->fbo) { diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 5a19704a05..0532a7b356 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -474,7 +474,7 @@ void FramebufferManagerD3D11::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); } else { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } } @@ -717,7 +717,7 @@ void FramebufferManagerD3D11::SimpleBlit( void FramebufferManagerD3D11::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if they recently switched from non-buffered. - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -812,7 +812,7 @@ void ConvertFromRGBA8888(u8 *dst, u8 *src, u32 dstStride, u32 srcStride, u32 wid void FramebufferManagerD3D11::PackFramebufferD3D11_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferD3D11_: vfb->fbo == 0"); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -884,7 +884,7 @@ std::vector FramebufferManagerD3D11::GetFramebufferList() { } void FramebufferManagerD3D11::DestroyAllFBOs() { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 6a9a03cb75..185b55342e 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -326,7 +326,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { if (currentRenderVfb_ && currentRenderVfb_->fbo) { draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); } else { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } } @@ -564,7 +564,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { void FramebufferManagerDX9::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if we recently switched from non-buffered. - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -664,7 +664,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { void FramebufferManagerDX9::PackFramebufferDirectx9_(VirtualFramebuffer *vfb, int x, int y, int w, int h) { if (!vfb->fbo) { ERROR_LOG_REPORT_ONCE(vfbfbozero, SCEGE, "PackFramebufferDirectx9_: vfb->fbo == 0"); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -792,7 +792,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } void FramebufferManagerDX9::DestroyAllFBOs() { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -882,7 +882,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } bool FramebufferManagerDX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); LPDIRECT3DSURFACE9 renderTarget = nullptr; HRESULT hr = device_->GetRenderTarget(0, &renderTarget); diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index 26ce3f48d2..c14b93dc24 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -452,7 +452,7 @@ void FramebufferManagerGLES::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); } else { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) glstate.viewport.restore(); @@ -680,7 +680,7 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, int dstY, VirtualFramebuffer *src, int srcX, int srcY, int w, int h, int bpp) { if (!dst->fbo || !src->fbo || !useBufferedRendering_) { // This can happen if they recently switched from non-buffered. - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -1165,7 +1165,7 @@ void FramebufferManagerGLES::EndFrame() { GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); } - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } CHECK_GL_ERROR_IF_DEBUG(); } @@ -1196,7 +1196,7 @@ std::vector FramebufferManagerGLES::GetFramebufferList() { void FramebufferManagerGLES::DestroyAllFBOs() { CHECK_GL_ERROR_IF_DEBUG(); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1220,7 +1220,7 @@ void FramebufferManagerGLES::DestroyAllFBOs() { } tempFBOs_.clear(); - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); DisableState(); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index dfef1d3386..10d7ab7370 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -236,7 +236,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { if (GetGPUBackend() == GPUBackend::VULKAN) { std::swap(v0, v1); } - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); draw_->Clear(Draw::FB_COLOR_BIT, 0, 0, 0); Draw::SamplerState *sampler; diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index eed60df430..26b7ee598a 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -482,7 +482,7 @@ void FramebufferManagerVulkan::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); } else { - draw_->BindBackbufferAsRenderTarget(); + draw_->BindFramebufferAsRenderTarget(nullptr); } } diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 75175c431e..2635e1296c 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -600,12 +600,13 @@ public: virtual bool BlitFramebuffer(Framebuffer *src, int srcX1, int srcY1, int srcX2, int srcY2, Framebuffer *dst, int dstX1, int dstY1, int dstX2, int dstY2, int channelBits, FBBlitFilter filter) = 0; // These functions should be self explanatory. + // Binding a zero render target means binding the backbuffer. virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo) = 0; + // color must be 0, for now. virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0; virtual void BindFramebufferForRead(Framebuffer *fbo) = 0; - virtual void BindBackbufferAsRenderTarget() = 0; virtual uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) = 0; virtual void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) = 0; @@ -640,8 +641,10 @@ public: virtual void BeginFrame() {} virtual void EndFrame() {} + // This should be avoided as much as possible, in favor of clearing when binding a render target, which is native + // on Vulkan. virtual void Clear(int mask, uint32_t colorval, float depthVal, int stencilVal) = 0; - + // Necessary to correctly flip scissor rectangles etc for OpenGL. void SetTargetSize(int w, int h) { targetWidth_ = w; diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index 2d40ad00ed..d4e0add435 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -63,7 +63,6 @@ public: void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; - void BindBackbufferAsRenderTarget() override; uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; @@ -1287,18 +1286,27 @@ bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, return false; } -// These functions should be self explanatory. void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { // TODO: deviceContext1 can actually discard. Useful on Windows Mobile. - D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; - if (curRenderTargetView_ == fb->colorRTView && curDepthStencilView_ == fb->depthStencilRTView) { - return; + if (fbo) { + D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; + if (curRenderTargetView_ == fb->colorRTView && curDepthStencilView_ == fb->depthStencilRTView) { + return; + } + context_->OMSetRenderTargets(1, &fb->colorRTView, fb->depthStencilRTView); + curRenderTargetView_ = fb->colorRTView; + curDepthStencilView_ = fb->depthStencilRTView; + curRTWidth_ = fb->width; + curRTHeight_ = fb->height; + } else { + if (curRenderTargetView_ == bbRenderTargetView_ && curDepthStencilView_ == bbDepthStencilView_) + return; + context_->OMSetRenderTargets(1, &bbRenderTargetView_, bbDepthStencilView_); + curRenderTargetView_ = bbRenderTargetView_; + curDepthStencilView_ = bbDepthStencilView_; + curRTWidth_ = bbWidth_; + curRTHeight_ = bbHeight_; } - context_->OMSetRenderTargets(1, &fb->colorRTView, fb->depthStencilRTView); - curRenderTargetView_ = fb->colorRTView; - curDepthStencilView_ = fb->depthStencilRTView; - curRTWidth_ = fb->width; - curRTHeight_ = fb->height; } // color must be 0, for now. @@ -1311,16 +1319,6 @@ void D3D11DrawContext::BindFramebufferForRead(Framebuffer *fbo) { // This is meaningless in D3D11 } -void D3D11DrawContext::BindBackbufferAsRenderTarget() { - if (curRenderTargetView_ == bbRenderTargetView_ && curDepthStencilView_ == bbDepthStencilView_) - return; - context_->OMSetRenderTargets(1, &bbRenderTargetView_, bbDepthStencilView_); - curRenderTargetView_ = bbRenderTargetView_; - curDepthStencilView_ = bbDepthStencilView_; - curRTWidth_ = bbWidth_; - curRTHeight_ = bbHeight_; -} - uintptr_t D3D11DrawContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; switch (channelBit) { diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index 09998a2149..06c1fa6bc0 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -492,7 +492,6 @@ public: void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override {} - void BindBackbufferAsRenderTarget() override; uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) override; void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; @@ -1044,21 +1043,17 @@ D3D9Framebuffer::~D3D9Framebuffer() { } } -void D3D9Context::BindBackbufferAsRenderTarget() { - using namespace DX9; - - device_->SetRenderTarget(0, deviceRTsurf); - device_->SetDepthStencilSurface(deviceDSsurf); - dxstate.scissorRect.restore(); - dxstate.viewport.restore(); -} - void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo) { using namespace DX9; - D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo; - device_->SetRenderTarget(0, fb->surf); - device_->SetDepthStencilSurface(fb->depthstencil); + if (fbo) { + D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo; + device_->SetRenderTarget(0, fb->surf); + device_->SetDepthStencilSurface(fb->depthstencil); + } else { + device_->SetRenderTarget(0, deviceRTsurf); + device_->SetDepthStencilSurface(deviceDSsurf); + } dxstate.scissorRect.restore(); dxstate.viewport.restore(); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 63d9b235c7..7388cb34e5 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -470,7 +470,6 @@ public: void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; - void BindBackbufferAsRenderTarget() override; uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBits, int attachment) override; void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; @@ -1535,19 +1534,17 @@ void OpenGLContext::fbo_unbind() { } void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { - OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; - // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing - // in ES 2.0 that actually separate them anyway of course, so doesn't matter. - fbo_bind_fb_target(false, fb->handle); - // Always restore viewport after render target binding - // TODO: Should we set viewports this way too? - glstate.viewport.restore(); CHECK_GL_ERROR_IF_DEBUG(); -} - -void OpenGLContext::BindBackbufferAsRenderTarget() { - CHECK_GL_ERROR_IF_DEBUG(); - fbo_unbind(); + if (fbo) { + OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; + // Without FBO_ARB / GLES3, this will collide with bind_for_read, but there's nothing + // in ES 2.0 that actually separate them anyway of course, so doesn't matter. + fbo_bind_fb_target(false, fb->handle); + // Always restore viewport after render target binding. Works around driver bugs. + glstate.viewport.restore(); + } else { + fbo_unbind(); + } CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index ca0e90e3cd..b2103485a8 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -351,7 +351,6 @@ public: void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; - void BindBackbufferAsRenderTarget() override; uintptr_t GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) override; void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) override; @@ -1303,10 +1302,16 @@ bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int sr VKFramebuffer *dst = (VKFramebuffer *)dstfb; return true; } + // These functions should be self explanatory. void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { - VKFramebuffer *fb = (VKFramebuffer *)fbo; + if (fbo) { + VKFramebuffer *fb = (VKFramebuffer *)fbo; + } else { + + } } + // color must be 0, for now. void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) { VKFramebuffer *fb = (VKFramebuffer *)fbo; @@ -1314,10 +1319,6 @@ void VKContext::BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChanne } void VKContext::BindFramebufferForRead(Framebuffer *fbo) { /* noop */ } -void VKContext::BindBackbufferAsRenderTarget() { - -} - uintptr_t VKContext::GetFramebufferAPITexture(Framebuffer *fbo, int channelBit, int attachment) { return 0; }