diff options
| author | riperiperi <rhy3756547@hotmail.com> | 2023-09-25 22:07:03 +0100 |
|---|---|---|
| committer | GitHub <noreply@github.com> | 2023-09-25 23:07:03 +0200 |
| commit | f6c3f1cdfdb9145634be3bfc54400f0d408f36dd (patch) | |
| tree | aa3de1c788717cd76f5990550dad0f3ab3d397bf /src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs | |
| parent | 8026e1c804fae39561087f9e04bd5c4eefa640fa (diff) | |
GPU: Discard data when getting texture before full clear (#5719)
* GPU: Discard data when getting texture before full clear
* Fix rules and order of clear checks
* Fix formatting
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs')
| -rw-r--r-- | src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs | 55 |
1 files changed, 50 insertions, 5 deletions
diff --git a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs index 18e7ac00..1c31312c 100644 --- a/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs +++ b/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs @@ -1,6 +1,7 @@ using Ryujinx.Graphics.GAL; using Ryujinx.Graphics.Gpu.Engine.Threed.ComputeDraw; using Ryujinx.Graphics.Gpu.Engine.Types; +using Ryujinx.Graphics.Gpu.Image; using Ryujinx.Graphics.Gpu.Memory; using System; @@ -806,25 +807,69 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed updateFlags |= RenderTargetUpdateFlags.Layered; } - if (clearDepth || clearStencil) + bool clearDS = clearDepth || clearStencil; + + if (clearDS) { updateFlags |= RenderTargetUpdateFlags.UpdateDepthStencil; } - engine.UpdateRenderTargetState(updateFlags, singleUse: componentMask != 0 ? index : -1); - // If there is a mismatch on the host clip region and the one explicitly defined by the guest // on the screen scissor state, then we need to force only one texture to be bound to avoid // host clipping. var screenScissorState = _state.State.ScreenScissorState; + bool clearAffectedByStencilMask = (_state.State.ClearFlags & 1) != 0; + bool clearAffectedByScissor = (_state.State.ClearFlags & 0x100) != 0; + + if (clearDS || componentMask == 15) + { + // A full clear if scissor is disabled, or it matches the screen scissor state. + + bool fullClear = screenScissorState.X == 0 && screenScissorState.Y == 0; + + if (fullClear && clearAffectedByScissor && _state.State.ScissorState[0].Enable) + { + ref var scissorState = ref _state.State.ScissorState[0]; + + fullClear = scissorState.X1 == screenScissorState.X && + scissorState.Y1 == screenScissorState.Y && + scissorState.X2 >= screenScissorState.X + screenScissorState.Width && + scissorState.Y2 >= screenScissorState.Y + screenScissorState.Height; + } + + if (fullClear && clearDS) + { + // Must clear all aspects of the depth-stencil format. + + FormatInfo dsFormat = _state.State.RtDepthStencilState.Format.Convert(); + + bool hasDepth = dsFormat.Format.HasDepth(); + bool hasStencil = dsFormat.Format.HasStencil(); + + if (hasStencil && (!clearStencil || (clearAffectedByStencilMask && _state.State.StencilTestState.FrontMask != 0xff))) + { + fullClear = false; + } + else if (hasDepth && !clearDepth) + { + fullClear = false; + } + } + + if (fullClear) + { + updateFlags |= RenderTargetUpdateFlags.DiscardClip; + } + } + + engine.UpdateRenderTargetState(updateFlags, singleUse: componentMask != 0 ? index : -1); + // Must happen after UpdateRenderTargetState to have up-to-date clip region values. bool clipMismatch = (screenScissorState.X | screenScissorState.Y) != 0 || screenScissorState.Width != _channel.TextureManager.ClipRegionWidth || screenScissorState.Height != _channel.TextureManager.ClipRegionHeight; - bool clearAffectedByStencilMask = (_state.State.ClearFlags & 1) != 0; - bool clearAffectedByScissor = (_state.State.ClearFlags & 0x100) != 0; bool needsCustomScissor = !clearAffectedByScissor || clipMismatch; // Scissor and rasterizer discard also affect clears. |
