aboutsummaryrefslogtreecommitdiff
path: root/src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs
diff options
context:
space:
mode:
Diffstat (limited to 'src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs')
-rw-r--r--src/Ryujinx.Graphics.Gpu/Engine/Threed/DrawManager.cs55
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.