diff --git a/GPU/Common/FramebufferCommon.cpp b/GPU/Common/FramebufferCommon.cpp index ec1fd7bb70..9a985234de 100644 --- a/GPU/Common/FramebufferCommon.cpp +++ b/GPU/Common/FramebufferCommon.cpp @@ -134,10 +134,6 @@ FramebufferManagerCommon::~FramebufferManagerCommon() { void FramebufferManagerCommon::Init() { const std::string gameId = g_paramSFO.GetValueString("DISC_ID"); - // And an initial clear. We don't clear per frame as the games are supposed to handle that - // by themselves. - ClearBuffer(); - BeginFrame(); } @@ -206,7 +202,7 @@ void FramebufferManagerCommon::SetNumExtraFBOs(int num) { extraFBOs_.push_back(fbo); } currentRenderVfb_ = 0; - draw_->BindFramebufferAsRenderTarget(nullptr); + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } // Heuristics to figure out the size of FBO to create. @@ -534,6 +530,7 @@ void FramebufferManagerCommon::NotifyRenderFramebufferCreated(VirtualFramebuffer textureCache_->NotifyFramebuffer(vfb->fb_address, vfb, NOTIFY_FB_CREATED); + // TODO: Is this necessary? ClearBuffer(); // ugly... @@ -575,7 +572,19 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe if (useBufferedRendering_) { if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); + 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) { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + } else { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); + } + } else { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); + } } else { // This should only happen very briefly when toggling useBufferedRendering_. ResizeFramebufFBO(vfb, vfb->width, vfb->height, true); @@ -587,7 +596,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe delete vfb->fbo; vfb->fbo = nullptr; } - draw_->BindFramebufferAsRenderTarget(nullptr); // Let's ignore rendering to targets that have not (yet) been displayed. if (vfb->usageFlags & FB_USAGE_DISPLAYED_FRAMEBUFFER) { @@ -598,16 +606,6 @@ void FramebufferManagerCommon::NotifyRenderFramebufferSwitched(VirtualFramebuffe } 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) { @@ -704,7 +702,7 @@ void FramebufferManagerCommon::DrawPixels(VirtualFramebuffer *vfb, int dstX, int MakePixelTexture(srcPixels, srcPixelFormat, srcStride, width, height, u1, v1); if (useBufferedRendering_ && vfb && vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); SetViewport2D(0, 0, vfb->renderWidth, vfb->renderHeight); } else { // We are drawing to the back buffer so need to flip. @@ -827,8 +825,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { if (displayFramebufPtr_ == 0) { DEBUG_LOG(FRAMEBUF, "Display disabled, displaying only black"); // No framebuffer to display! Clear to black. - draw_->BindFramebufferAsRenderTarget(nullptr); - ClearBuffer(); + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); return; } @@ -878,11 +875,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } } - draw_->BindFramebufferAsRenderTarget(nullptr); - if (useBufferedRendering_) { - draw_->Clear(Draw::FB_COLOR_BIT | Draw::FB_STENCIL_BIT | Draw::FB_DEPTH_BIT, 0, 0, 0); - } - if (!vfb) { if (Memory::IsValidAddress(displayFramebufPtr_)) { // The game is displaying something directly from RAM. In GTA, it's decoded video. @@ -895,6 +887,10 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } if (!vfb) { + if (useBufferedRendering_) { + // Bind and clear the backbuffer. This should be the first time during the frame that it's bound. + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + } // Just a pointer to plain memory to draw. We should create a framebuffer, then draw to it. DrawFramebufferToOutput(Memory::GetPointer(displayFramebufPtr_), displayFormat_, displayStride_, true); return; @@ -902,7 +898,10 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } else { DEBUG_LOG(FRAMEBUF, "Found no FBO to display! displayFBPtr = %08x", displayFramebufPtr_); // No framebuffer to display! Clear to black. - ClearBuffer(); + if (useBufferedRendering_) { + // Bind and clear the backbuffer. This should be the first time during the frame that it's bound. + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + } return; } } @@ -924,8 +923,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { DEBUG_LOG(FRAMEBUF, "Displaying FBO %08x", vfb->fb_address); DisableState(); - draw_->BindFramebufferAsTexture(vfb->fbo, 0, Draw::FB_COLOR_BIT, 0); - int uvRotation = useBufferedRendering_ ? g_Config.iInternalScreenRotation : ROTATION_LOCKED_HORIZONTAL; // Output coordinates @@ -940,6 +937,8 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { float v1 = (272.0f + offsetY) / (float)vfb->bufferHeight; if (!usePostShader_) { + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + draw_->BindFramebufferAsTexture(vfb->fbo, 0, Draw::FB_COLOR_BIT, 0); bool linearFilter = g_Config.iBufFilter == SCALE_LINEAR; // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must // flip V. @@ -961,7 +960,7 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } } else if (usePostShader_ && extraFBOs_.size() == 1 && !postShaderAtOutputResolution_) { // An additional pass, post-processing shader to the extra FBO. - draw_->BindFramebufferAsRenderTarget(extraFBOs_[0]); + draw_->BindFramebufferAsRenderTarget(extraFBOs_[0], { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); int fbo_w, fbo_h; draw_->GetFramebufferDimensions(extraFBOs_[0], &fbo_w, &fbo_h); SetViewport2D(0, 0, fbo_w, fbo_h); @@ -972,7 +971,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_->BindFramebufferAsRenderTarget(nullptr); + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); // Use the extra FBO, with applied post-processing shader, as a texture. // fbo_bind_as_texture(extraFBOs_[0], FB_COLOR_BIT, 0); @@ -1004,11 +1003,12 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { /* if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { - draw_->BindFramebufferAsRenderTarget(extraFBOs_[0]); + draw_->BindFramebufferAsRenderTarget(extraFBOs_[0], { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_DEPTH_ATTACHMENT, GL_STENCIL_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); }*/ } else { + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); // We are doing the DrawActiveTexture call directly to the backbuffer here. Hence, we must // flip V. if (needBackBufferYSwap_) @@ -1040,9 +1040,6 @@ void FramebufferManagerCommon::CopyDisplayToOutput() { } void FramebufferManagerCommon::DecimateFBOs() { - if (useBufferedRendering_) { - draw_->BindFramebufferAsRenderTarget(nullptr); - } currentRenderVfb_ = 0; for (size_t i = 0; i < vfbs_.size(); ++i) { @@ -1133,7 +1130,6 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, } textureCache_->ForgetLastTexture(); - draw_->BindFramebufferAsRenderTarget(nullptr); if (!useBufferedRendering_) { if (vfb->fbo) { @@ -1151,16 +1147,14 @@ void FramebufferManagerCommon::ResizeFramebufFBO(VirtualFramebuffer *vfb, u16 w, if (old.fbo) { INFO_LOG(FRAMEBUF, "Resizing FBO for %08x : %i x %i x %i", vfb->fb_address, w, h, vfb->format); if (vfb->fbo) { - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - ClearBuffer(); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); 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); - } + delete old.fbo; + } else { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); } if (!vfb->fbo) { @@ -1796,8 +1790,9 @@ Draw::Framebuffer *FramebufferManagerCommon::GetTempFBO(u16 w, u16 h, Draw::FBCo Draw::Framebuffer *fbo = draw_->CreateFramebuffer({ w, h, 1, 1, false, depth }); if (!fbo) return fbo; - draw_->BindFramebufferAsRenderTarget(fbo); - ClearBuffer(true); + + // TODO: Move binding out of here! + draw_->BindFramebufferAsRenderTarget(fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); const TempFBO info = { fbo, gpuStats.numFlips }; tempFBOs_[key] = info; return fbo; diff --git a/GPU/Common/FramebufferCommon.h b/GPU/Common/FramebufferCommon.h index 835e7b66cb..11f339073c 100644 --- a/GPU/Common/FramebufferCommon.h +++ b/GPU/Common/FramebufferCommon.h @@ -267,7 +267,7 @@ public: virtual void Resized(); - Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth depth = Draw::FBO_8888); + Draw::Framebuffer *GetTempFBO(u16 w, u16 h, Draw::FBColorDepth colorDepth = Draw::FBO_8888); // Debug features virtual bool GetFramebuffer(u32 fb_address, int fb_stride, GEBufferFormat format, GPUDebugBuffer &buffer, int maxRes) = 0; diff --git a/GPU/D3D11/FramebufferManagerD3D11.cpp b/GPU/D3D11/FramebufferManagerD3D11.cpp index 0532a7b356..3d2cdf774f 100644 --- a/GPU/D3D11/FramebufferManagerD3D11.cpp +++ b/GPU/D3D11/FramebufferManagerD3D11.cpp @@ -218,8 +218,6 @@ void FramebufferManagerD3D11::DisableState() { } void FramebufferManagerD3D11::CompilePostShader() { - SetNumExtraFBOs(0); - std::string vsSource; std::string psSource; @@ -472,9 +470,10 @@ void FramebufferManagerD3D11::BindPostShader(const PostShaderUniforms &uniforms) void FramebufferManagerD3D11::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } else { - draw_->BindFramebufferAsRenderTarget(nullptr); + // Should this even happen? + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } } @@ -483,8 +482,6 @@ void FramebufferManagerD3D11::ReformatFramebufferFrom(VirtualFramebuffer *vfb, G return; } - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - // Technically, we should at this point re-interpret the bytes of the old format to the new. // That might get tricky, and could cause unnecessary slowness in some games. // For now, we just clear alpha/stencil from 565, which fixes shadow issues in Kingdom Hearts. @@ -494,7 +491,10 @@ void FramebufferManagerD3D11::ReformatFramebufferFrom(VirtualFramebuffer *vfb, G // and blit with a shader to that, then replace the FBO on vfb. Stencil would still be complex // to exactly reproduce in 4444 and 8888 formats. + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP }); + if (old == GE_FORMAT_565) { + // TODO: There's no way this does anything useful :( context_->OMSetDepthStencilState(stockD3D11.depthDisabledStencilWrite, 0xFF); context_->OMSetBlendState(stockD3D11.blendStateDisabledWithColorMask[0], nullptr, 0xFFFFFFFF); context_->RSSetState(stockD3D11.rasterStateNoCull); @@ -571,7 +571,6 @@ void FramebufferManagerD3D11::BindFramebufferAsColorTexture(int stage, VirtualFr if (renderCopy) { VirtualFramebuffer copyInfo = *framebuffer; copyInfo.fbo = renderCopy; - CopyFramebufferForColorTexture(©Info, framebuffer, flags); RebindFramebuffer(); draw_->BindFramebufferAsTexture(renderCopy, stage, Draw::FB_COLOR_BIT, 0); @@ -653,8 +652,7 @@ bool FramebufferManagerD3D11::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) return false; } - draw_->BindFramebufferAsRenderTarget(nvfb->fbo); - ClearBuffer(); + draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); return true; } @@ -697,7 +695,7 @@ void FramebufferManagerD3D11::SimpleBlit( // Unbind the texture first to avoid the D3D11 hazard check (can't set render target to things bound as textures and vice versa, not even temporarily). draw_->BindTexture(0, nullptr); - draw_->BindFramebufferAsRenderTarget(dest); + draw_->BindFramebufferAsRenderTarget(dest, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); draw_->BindFramebufferAsTexture(src, 0, Draw::FB_COLOR_BIT, 0); Bind2DShader(); @@ -717,7 +715,9 @@ 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_->BindFramebufferAsRenderTarget(nullptr); + if (useBufferedRendering_) { + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); + } return; } @@ -812,7 +812,6 @@ 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_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -884,7 +883,6 @@ std::vector FramebufferManagerD3D11::GetFramebufferList() { } void FramebufferManagerD3D11::DestroyAllFBOs() { - draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; diff --git a/GPU/D3D11/StencilBufferD3D11.cpp b/GPU/D3D11/StencilBufferD3D11.cpp index aa117bcca7..9f18eff386 100644 --- a/GPU/D3D11/StencilBufferD3D11.cpp +++ b/GPU/D3D11/StencilBufferD3D11.cpp @@ -194,16 +194,13 @@ bool FramebufferManagerD3D11::NotifyStencilUpload(u32 addr, int size, bool skipZ float v1 = 1.0f; MakePixelTexture(src, dstBuffer->format, dstBuffer->fb_stride, dstBuffer->bufferWidth, dstBuffer->bufferHeight, u1, v1); if (dstBuffer->fbo) { - draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo); + draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } else { // something is wrong... } D3D11_VIEWPORT vp{ 0.0f, 0.0f, (float)w, (float)h, 0.0f, 1.0f }; context_->RSSetViewports(1, &vp); - // Zero stencil - draw_->Clear(Draw::FBChannel::FB_STENCIL_BIT, 0, 0, 0); - float fw = dstBuffer->width; float fh = dstBuffer->height; diff --git a/GPU/D3D11/TextureCacheD3D11.cpp b/GPU/D3D11/TextureCacheD3D11.cpp index edb91563af..8ceec37249 100644 --- a/GPU/D3D11/TextureCacheD3D11.cpp +++ b/GPU/D3D11/TextureCacheD3D11.cpp @@ -434,7 +434,7 @@ void TextureCacheD3D11::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFra context_->PSSetShaderResources(1, 1, &clutTexture); framebufferManagerD3D11_->BindFramebufferAsColorTexture(0, framebuffer, BINDFBCOLOR_SKIP_COPY); context_->PSSetSamplers(0, 1, &stockD3D11.samplerPoint2DWrap); - draw_->BindFramebufferAsRenderTarget(depalFBO); + draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE }); shaderApply.Shade(); framebufferManagerD3D11_->RebindFramebuffer(); diff --git a/GPU/Directx9/FramebufferDX9.cpp b/GPU/Directx9/FramebufferDX9.cpp index 185b55342e..e639ddaa3f 100644 --- a/GPU/Directx9/FramebufferDX9.cpp +++ b/GPU/Directx9/FramebufferDX9.cpp @@ -324,9 +324,10 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { void FramebufferManagerDX9::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } else { - draw_->BindFramebufferAsRenderTarget(nullptr); + // Should this even happen? + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } } @@ -345,7 +346,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { return; } - draw_->BindFramebufferAsRenderTarget(vfb->fbo); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::KEEP }); // Technically, we should at this point re-interpret the bytes of the old format to the new. // That might get tricky, and could cause unnecessary slowness in some games. @@ -552,8 +553,7 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { return false; } - draw_->BindFramebufferAsRenderTarget(nvfb->fbo); - ClearBuffer(); + draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); return true; } @@ -564,7 +564,8 @@ 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_->BindFramebufferAsRenderTarget(nullptr); + if (useBufferedRendering_) + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); return; } @@ -664,7 +665,6 @@ 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_->BindFramebufferAsRenderTarget(nullptr); return; } @@ -792,7 +792,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } void FramebufferManagerDX9::DestroyAllFBOs() { - draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -882,8 +881,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } bool FramebufferManagerDX9::GetOutputFramebuffer(GPUDebugBuffer &buffer) { - draw_->BindFramebufferAsRenderTarget(nullptr); - LPDIRECT3DSURFACE9 renderTarget = nullptr; HRESULT hr = device_->GetRenderTarget(0, &renderTarget); bool success = false; @@ -899,7 +896,6 @@ static const D3DVERTEXELEMENT9 g_FramebufferVertexElements[] = { } renderTarget->Release(); } - return success; } diff --git a/GPU/Directx9/StencilBufferDX9.cpp b/GPU/Directx9/StencilBufferDX9.cpp index 4ad4cc7ecf..5195c0b428 100644 --- a/GPU/Directx9/StencilBufferDX9.cpp +++ b/GPU/Directx9/StencilBufferDX9.cpp @@ -221,7 +221,7 @@ bool FramebufferManagerDX9::NotifyStencilUpload(u32 addr, int size, bool skipZer u16 h = dstBuffer->renderHeight; if (dstBuffer->fbo) { - draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo); + draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::CLEAR }); } D3DVIEWPORT9 vp{ 0, 0, w, h, 0.0f, 1.0f }; device_->SetViewport(&vp); diff --git a/GPU/Directx9/TextureCacheDX9.cpp b/GPU/Directx9/TextureCacheDX9.cpp index 2a2f532686..0fffa606ea 100644 --- a/GPU/Directx9/TextureCacheDX9.cpp +++ b/GPU/Directx9/TextureCacheDX9.cpp @@ -421,7 +421,7 @@ void TextureCacheDX9::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFrame LPDIRECT3DTEXTURE9 clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); Draw::Framebuffer *depalFBO = framebufferManagerDX9_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, Draw::FBO_8888); - draw_->BindFramebufferAsRenderTarget(depalFBO); + draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderManager_->DirtyLastShader(); float xoff = -0.5f / framebuffer->renderWidth; diff --git a/GPU/GLES/FramebufferManagerGLES.cpp b/GPU/GLES/FramebufferManagerGLES.cpp index c14b93dc24..5fcd307b93 100644 --- a/GPU/GLES/FramebufferManagerGLES.cpp +++ b/GPU/GLES/FramebufferManagerGLES.cpp @@ -93,6 +93,11 @@ void FramebufferManagerGLES::ClearBuffer(bool keepState) { #endif glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); if (keepState) { + glstate.scissorTest.force(false); + glstate.depthWrite.force(GL_TRUE); + glstate.colorMask.force(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + glstate.stencilFunc.force(GL_ALWAYS, 0, 0); + glstate.stencilMask.force(0xFF); glstate.scissorTest.restore(); glstate.depthWrite.restore(); glstate.colorMask.restore(); @@ -450,9 +455,10 @@ void FramebufferManagerGLES::DrawActiveTexture(float x, float y, float w, float void FramebufferManagerGLES::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } else { - draw_->BindFramebufferAsRenderTarget(nullptr); + // Should this even happen? + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } if (g_Config.iRenderingMode == FB_NON_BUFFERED_MODE) glstate.viewport.restore(); @@ -475,8 +481,6 @@ void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GE return; } - draw_->BindFramebufferAsRenderTarget(vfb->fbo); - // Technically, we should at this point re-interpret the bytes of the old format to the new. // That might get tricky, and could cause unnecessary slowness in some games. // For now, we just clear alpha/stencil from 565, which fixes shadow issues in Kingdom Hearts. @@ -487,14 +491,9 @@ void FramebufferManagerGLES::ReformatFramebufferFrom(VirtualFramebuffer *vfb, GE // to exactly reproduce in 4444 and 8888 formats. if (old == GE_FORMAT_565) { - glstate.scissorTest.disable(); - glstate.depthWrite.set(GL_FALSE); - glstate.colorMask.set(false, false, false, true); - glstate.stencilFunc.set(GL_ALWAYS, 0, 0); - glstate.stencilMask.set(0xFF); - glClearColor(0.0f, 0.0f, 0.0f, 0.0f); - glClearStencil(0); - glClear(GL_COLOR_BUFFER_BIT | GL_STENCIL_BUFFER_BIT); + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::CLEAR, Draw::RPAction::CLEAR }); + } else { + draw_->BindFramebufferAsRenderTarget(vfb->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } RebindFramebuffer(); @@ -655,10 +654,6 @@ bool FramebufferManagerGLES::CreateDownloadTempBuffer(VirtualFramebuffer *nvfb) ERROR_LOG(FRAMEBUF, "Error creating GL FBO! %i x %i", nvfb->renderWidth, nvfb->renderHeight); return false; } - - draw_->BindFramebufferAsRenderTarget(nvfb->fbo); - ClearBuffer(); - glDisable(GL_DITHER); // Weird place to do this return true; } @@ -667,11 +662,11 @@ void FramebufferManagerGLES::UpdateDownloadTempBuffer(VirtualFramebuffer *nvfb) // Discard the previous contents of this buffer where possible. if (gl_extensions.GLES3 && glInvalidateFramebuffer != nullptr) { - draw_->BindFramebufferAsRenderTarget(nvfb->fbo); + draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); } else if (gl_extensions.IsGLES) { - draw_->BindFramebufferAsRenderTarget(nvfb->fbo); + draw_->BindFramebufferAsRenderTarget(nvfb->fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); ClearBuffer(); } CHECK_GL_ERROR_IF_DEBUG(); @@ -680,7 +675,8 @@ 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_->BindFramebufferAsRenderTarget(nullptr); + if (useBufferedRendering_) + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); return; } @@ -735,7 +731,7 @@ void FramebufferManagerGLES::BlitFramebuffer(VirtualFramebuffer *dst, int dstX, if (useBlit) { draw_->BlitFramebuffer(src->fbo, srcX1, srcY1, srcX2, srcY2, dst->fbo, dstX1, dstY1, dstX2, dstY2, Draw::FB_COLOR_BIT, Draw::FB_BLIT_NEAREST); } else { - draw_->BindFramebufferAsRenderTarget(dst->fbo); + draw_->BindFramebufferAsRenderTarget(dst->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); draw_->BindFramebufferAsTexture(src->fbo, 0, Draw::FB_COLOR_BIT, 0); // Make sure our 2D drawing program is ready. Compiles only if not already compiled. @@ -1161,11 +1157,11 @@ void FramebufferManagerGLES::EndFrame() { continue; } - draw_->BindFramebufferAsRenderTarget(temp.second.fbo); + draw_->BindFramebufferAsRenderTarget(temp.second.fbo, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); GLenum attachments[3] = { GL_COLOR_ATTACHMENT0, GL_STENCIL_ATTACHMENT, GL_DEPTH_ATTACHMENT }; glInvalidateFramebuffer(GL_FRAMEBUFFER, 3, attachments); } - draw_->BindFramebufferAsRenderTarget(nullptr); + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP , Draw::RPAction::KEEP }); } CHECK_GL_ERROR_IF_DEBUG(); } @@ -1196,7 +1192,6 @@ std::vector FramebufferManagerGLES::GetFramebufferList() { void FramebufferManagerGLES::DestroyAllFBOs() { CHECK_GL_ERROR_IF_DEBUG(); - draw_->BindFramebufferAsRenderTarget(nullptr); currentRenderVfb_ = 0; displayFramebuf_ = 0; prevDisplayFramebuf_ = 0; @@ -1220,7 +1215,6 @@ void FramebufferManagerGLES::DestroyAllFBOs() { } tempFBOs_.clear(); - draw_->BindFramebufferAsRenderTarget(nullptr); DisableState(); CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/GPU/GLES/StencilBufferGLES.cpp b/GPU/GLES/StencilBufferGLES.cpp index cdd1b6c79f..a595bb19bc 100644 --- a/GPU/GLES/StencilBufferGLES.cpp +++ b/GPU/GLES/StencilBufferGLES.cpp @@ -183,9 +183,9 @@ bool FramebufferManagerGLES::NotifyStencilUpload(u32 addr, int size, bool skipZe Draw::Framebuffer *blitFBO = nullptr; if (useBlit) { blitFBO = GetTempFBO(w, h, Draw::FBO_8888); - draw_->BindFramebufferAsRenderTarget(blitFBO); + draw_->BindFramebufferAsRenderTarget(blitFBO, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE }); } else if (dstBuffer->fbo) { - draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo); + draw_->BindFramebufferAsRenderTarget(dstBuffer->fbo, { Draw::RPAction::KEEP, Draw::RPAction::DONT_CARE }); } glViewport(0, 0, w, h); diff --git a/GPU/GLES/TextureCacheGLES.cpp b/GPU/GLES/TextureCacheGLES.cpp index 732f6e61de..2950324c88 100644 --- a/GPU/GLES/TextureCacheGLES.cpp +++ b/GPU/GLES/TextureCacheGLES.cpp @@ -483,7 +483,7 @@ void TextureCacheGLES::ApplyTextureFramebuffer(TexCacheEntry *entry, VirtualFram const GEPaletteFormat clutFormat = gstate.getClutPaletteFormat(); GLuint clutTexture = depalShaderCache_->GetClutTexture(clutFormat, clutHash_, clutBuf_); Draw::Framebuffer *depalFBO = framebufferManagerGL_->GetTempFBO(framebuffer->renderWidth, framebuffer->renderHeight, Draw::FBO_8888); - draw_->BindFramebufferAsRenderTarget(depalFBO); + draw_->BindFramebufferAsRenderTarget(depalFBO, { Draw::RPAction::DONT_CARE, Draw::RPAction::DONT_CARE }); shaderManager_->DirtyLastShader(); TextureShaderApplier shaderApply(depal, framebuffer->bufferWidth, framebuffer->bufferHeight, framebuffer->renderWidth, framebuffer->renderHeight); diff --git a/GPU/Software/SoftGpu.cpp b/GPU/Software/SoftGpu.cpp index 10d7ab7370..91fc88fb10 100644 --- a/GPU/Software/SoftGpu.cpp +++ b/GPU/Software/SoftGpu.cpp @@ -236,8 +236,7 @@ void SoftGPU::CopyToCurrentFboFromDisplayRam(int srcwidth, int srcheight) { if (GetGPUBackend() == GPUBackend::VULKAN) { std::swap(v0, v1); } - draw_->BindFramebufferAsRenderTarget(nullptr); - draw_->Clear(Draw::FB_COLOR_BIT, 0, 0, 0); + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::CLEAR, Draw::RPAction::DONT_CARE }); Draw::SamplerState *sampler; if (g_Config.iBufFilter == SCALE_NEAREST) { diff --git a/GPU/Vulkan/FramebufferVulkan.cpp b/GPU/Vulkan/FramebufferVulkan.cpp index 26b7ee598a..307aa03179 100644 --- a/GPU/Vulkan/FramebufferVulkan.cpp +++ b/GPU/Vulkan/FramebufferVulkan.cpp @@ -480,9 +480,10 @@ void FramebufferManagerVulkan::BindPostShader(const PostShaderUniforms &uniforms void FramebufferManagerVulkan::RebindFramebuffer() { if (currentRenderVfb_ && currentRenderVfb_->fbo) { - draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo); + draw_->BindFramebufferAsRenderTarget(currentRenderVfb_->fbo, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } else { - draw_->BindFramebufferAsRenderTarget(nullptr); + // Should this even happen? + draw_->BindFramebufferAsRenderTarget(nullptr, { Draw::RPAction::KEEP, Draw::RPAction::KEEP }); } } diff --git a/UI/EmuScreen.cpp b/UI/EmuScreen.cpp index 7e810c418a..16b992a71e 100644 --- a/UI/EmuScreen.cpp +++ b/UI/EmuScreen.cpp @@ -973,8 +973,7 @@ void EmuScreen::preRender() { if (!useBufferedRendering) { // We need to clear here already so that drawing during the frame is done on a clean slate. DrawContext *draw = screenManager()->getDrawContext(); - draw->BindFramebufferAsRenderTarget(nullptr); - draw->Clear(FBChannel::FB_COLOR_BIT | FBChannel::FB_DEPTH_BIT | FBChannel::FB_STENCIL_BIT, 0xFF000000, 0.0f, 0); + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }); Viewport viewport; viewport.TopLeftX = 0; diff --git a/ext/native/thin3d/thin3d.h b/ext/native/thin3d/thin3d.h index 2635e1296c..1e2c9d0ca0 100644 --- a/ext/native/thin3d/thin3d.h +++ b/ext/native/thin3d/thin3d.h @@ -562,6 +562,20 @@ struct TextureDesc { std::vector initData; }; +enum class RPAction { + DONT_CARE, + CLEAR, + KEEP, +}; + +struct RenderPassInfo { + RPAction color; + RPAction depth; + uint32_t clearColor; + float clearDepth; + uint8_t clearStencil; +}; + class DrawContext { public: virtual ~DrawContext(); @@ -601,7 +615,7 @@ public: // These functions should be self explanatory. // Binding a zero render target means binding the backbuffer. - virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo) = 0; + virtual void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) = 0; // color must be 0, for now. virtual void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) = 0; @@ -611,6 +625,9 @@ public: virtual void GetFramebufferDimensions(Framebuffer *fbo, int *w, int *h) = 0; + // Useful in OpenGL ES to give hints about framebuffers on tiler GPUs. + virtual void InvalidateFramebuffer(Framebuffer *fbo) {} + // Dynamic state virtual void SetScissorRect(int left, int top, int width, int height) = 0; virtual void SetViewports(int count, Viewport *viewports) = 0; diff --git a/ext/native/thin3d/thin3d_d3d11.cpp b/ext/native/thin3d/thin3d_d3d11.cpp index d4e0add435..85e44c9035 100644 --- a/ext/native/thin3d/thin3d_d3d11.cpp +++ b/ext/native/thin3d/thin3d_d3d11.cpp @@ -58,7 +58,7 @@ public: 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) override; // These functions should be self explanatory. - void BindFramebufferAsRenderTarget(Framebuffer *fbo) override; + void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) override; // color must be 0, for now. void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; @@ -1286,7 +1286,7 @@ bool D3D11DrawContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, return false; } -void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { +void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { // TODO: deviceContext1 can actually discard. Useful on Windows Mobile. if (fbo) { D3D11Framebuffer *fb = (D3D11Framebuffer *)fbo; @@ -1307,6 +1307,15 @@ void D3D11DrawContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { curRTWidth_ = bbWidth_; curRTHeight_ = bbHeight_; } + if (rp.color == RPAction::CLEAR && curRenderTargetView_) { + float cv[4]{}; + if (rp.clearColor) + Uint8x4ToFloat4(cv, rp.clearColor); + context_->ClearRenderTargetView(curRenderTargetView_, cv); + } + if (rp.depth == RPAction::CLEAR && curDepthStencilView_) { + context_->ClearDepthStencilView(curDepthStencilView_, D3D11_CLEAR_DEPTH | D3D11_CLEAR_STENCIL, rp.clearDepth, rp.clearStencil); + } } // color must be 0, for now. diff --git a/ext/native/thin3d/thin3d_d3d9.cpp b/ext/native/thin3d/thin3d_d3d9.cpp index 06c1fa6bc0..0a4e1938e4 100644 --- a/ext/native/thin3d/thin3d_d3d9.cpp +++ b/ext/native/thin3d/thin3d_d3d9.cpp @@ -487,7 +487,7 @@ public: 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) override; // These functions should be self explanatory. - void BindFramebufferAsRenderTarget(Framebuffer *fbo) override; + void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) override; // color must be 0, for now. void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override {} @@ -1043,9 +1043,8 @@ D3D9Framebuffer::~D3D9Framebuffer() { } } -void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo) { +void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { using namespace DX9; - if (fbo) { D3D9Framebuffer *fb = (D3D9Framebuffer *)fbo; device_->SetRenderTarget(0, fb->surf); @@ -1054,6 +1053,20 @@ void D3D9Context::BindFramebufferAsRenderTarget(Framebuffer *fbo) { device_->SetRenderTarget(0, deviceRTsurf); device_->SetDepthStencilSurface(deviceDSsurf); } + + int clearFlags = 0; + if (rp.color == RPAction::CLEAR) { + clearFlags |= D3DCLEAR_TARGET; + } + if (rp.depth == RPAction::CLEAR) { + clearFlags |= D3DCLEAR_ZBUFFER | D3DCLEAR_STENCIL; + } + if (clearFlags) { + dxstate.scissorTest.force(false); + device_->Clear(0, nullptr, clearFlags, (D3DCOLOR)SwapRB(rp.clearColor), rp.clearDepth, rp.clearStencil); + dxstate.scissorRect.restore(); + } + dxstate.scissorRect.restore(); dxstate.viewport.restore(); } diff --git a/ext/native/thin3d/thin3d_gl.cpp b/ext/native/thin3d/thin3d_gl.cpp index 62c857846e..4c9164ab6b 100644 --- a/ext/native/thin3d/thin3d_gl.cpp +++ b/ext/native/thin3d/thin3d_gl.cpp @@ -465,7 +465,7 @@ public: 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) override; // These functions should be self explanatory. - void BindFramebufferAsRenderTarget(Framebuffer *fbo) override; + void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) override; // color must be 0, for now. void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; @@ -1468,6 +1468,7 @@ Framebuffer *OpenGLContext::CreateFramebuffer(const FramebufferDesc &desc) { FLOG("Other framebuffer error: %i", status); break; } + // Unbind state we don't need glBindRenderbuffer(GL_RENDERBUFFER, 0); glBindTexture(GL_TEXTURE_2D, 0); @@ -1533,7 +1534,7 @@ void OpenGLContext::fbo_unbind() { currentReadHandle_ = 0; } -void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { +void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { CHECK_GL_ERROR_IF_DEBUG(); if (fbo) { OpenGLFramebuffer *fb = (OpenGLFramebuffer *)fbo; @@ -1545,6 +1546,37 @@ void OpenGLContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { } else { fbo_unbind(); } + int clearFlags = 0; + if (rp.color == RPAction::CLEAR) { + float fc[4]{}; + if (rp.clearColor) { + Uint8x4ToFloat4(fc, rp.clearColor); + } + glClearColor(fc[0], fc[1], fc[2], fc[3]); + clearFlags |= GL_COLOR_BUFFER_BIT; + glstate.colorMask.force(GL_TRUE, GL_TRUE, GL_TRUE, GL_TRUE); + } + if (rp.depth == RPAction::CLEAR) { + glClearDepth(rp.clearDepth); + glClearStencil(rp.clearStencil); + clearFlags |= GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT; + glstate.depthWrite.force(GL_TRUE); + glstate.stencilFunc.force(GL_ALWAYS, 0, 0); + glstate.stencilMask.force(0xFF); + } + if (clearFlags) { + glstate.scissorTest.force(false); + glClear(clearFlags); + glstate.scissorTest.restore(); + } + if (rp.color == RPAction::CLEAR) { + glstate.colorMask.restore(); + } + if (rp.depth == RPAction::CLEAR) { + glstate.depthWrite.restore(); + glstate.stencilFunc.restore(); + glstate.stencilMask.restore(); + } CHECK_GL_ERROR_IF_DEBUG(); } diff --git a/ext/native/thin3d/thin3d_vulkan.cpp b/ext/native/thin3d/thin3d_vulkan.cpp index b2103485a8..6c7beea45a 100644 --- a/ext/native/thin3d/thin3d_vulkan.cpp +++ b/ext/native/thin3d/thin3d_vulkan.cpp @@ -346,7 +346,7 @@ public: 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) override; // These functions should be self explanatory. - void BindFramebufferAsRenderTarget(Framebuffer *fbo) override; + void BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) override; // color must be 0, for now. void BindFramebufferAsTexture(Framebuffer *fbo, int binding, FBChannel channelBit, int attachment) override; void BindFramebufferForRead(Framebuffer *fbo) override; @@ -1304,7 +1304,7 @@ bool VKContext::BlitFramebuffer(Framebuffer *srcfb, int srcX1, int srcY1, int sr } // These functions should be self explanatory. -void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo) { +void VKContext::BindFramebufferAsRenderTarget(Framebuffer *fbo, const RenderPassInfo &rp) { if (fbo) { VKFramebuffer *fb = (VKFramebuffer *)fbo; } else { diff --git a/ext/native/ui/ui_screen.cpp b/ext/native/ui/ui_screen.cpp index 65633292b4..fd7fcf6783 100644 --- a/ext/native/ui/ui_screen.cpp +++ b/ext/native/ui/ui_screen.cpp @@ -61,14 +61,14 @@ void UIScreen::update() { } void UIScreen::preRender() { + using namespace Draw; Draw::DrawContext *draw = screenManager()->getDrawContext(); if (!draw) { return; } draw->BeginFrame(); - // Bind the back buffer - draw->BindFramebufferAsRenderTarget(nullptr); - draw->Clear(0xF, 0xFF000000, 0.0f, 0); + // Bind and clear the back buffer + draw->BindFramebufferAsRenderTarget(nullptr, { RPAction::CLEAR, RPAction::CLEAR, 0xFF000000 }); Draw::Viewport viewport; viewport.TopLeftX = 0;