Better depth range detection (#2754)

* Better depth range detection

* PR feedback

* Move depth mode set out of the loop and to a separate method
This commit is contained in:
gdkchan 2021-11-21 10:25:03 -03:00 committed by GitHub
parent 02d786a086
commit 30b7aaefca
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23

View File

@ -485,6 +485,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
var face = _state.State.FaceState; var face = _state.State.FaceState;
UpdateFrontFace(yControl, face.FrontFace); UpdateFrontFace(yControl, face.FrontFace);
UpdateDepthMode();
bool flipY = yControl.HasFlag(YControl.NegateY); bool flipY = yControl.HasFlag(YControl.NegateY);
@ -492,8 +493,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
for (int index = 0; index < Constants.TotalViewports; index++) for (int index = 0; index < Constants.TotalViewports; index++)
{ {
var transform = _state.State.ViewportTransform[index]; ref var transform = ref _state.State.ViewportTransform[index];
var extents = _state.State.ViewportExtents[index]; ref var extents = ref _state.State.ViewportExtents[index];
float scaleX = MathF.Abs(transform.ScaleX); float scaleX = MathF.Abs(transform.ScaleX);
float scaleY = transform.ScaleY; float scaleY = transform.ScaleY;
@ -508,24 +509,6 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
scaleY = -scaleY; scaleY = -scaleY;
} }
if (index == 0)
{
// Try to guess the depth mode being used on the high level API
// based on current transform.
// It is setup like so by said APIs:
// If depth mode is ZeroToOne:
// TranslateZ = Near
// ScaleZ = Far - Near
// If depth mode is MinusOneToOne:
// TranslateZ = (Near + Far) / 2
// ScaleZ = (Far - Near) / 2
// DepthNear/Far are sorted such as that Near is always less than Far.
DepthMode depthMode = extents.DepthNear != transform.TranslateZ &&
extents.DepthFar != transform.TranslateZ ? DepthMode.MinusOneToOne : DepthMode.ZeroToOne;
_context.Renderer.Pipeline.SetDepthMode(depthMode);
}
float x = transform.TranslateX - scaleX; float x = transform.TranslateX - scaleX;
float y = transform.TranslateY - scaleY; float y = transform.TranslateY - scaleY;
@ -564,6 +547,44 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
_context.Renderer.Pipeline.SetViewports(0, viewports); _context.Renderer.Pipeline.SetViewports(0, viewports);
} }
/// <summary>
/// Updates the depth mode (0 to 1 or -1 to 1) based on the current viewport and depth mode register state.
/// </summary>
private void UpdateDepthMode()
{
ref var transform = ref _state.State.ViewportTransform[0];
ref var extents = ref _state.State.ViewportExtents[0];
DepthMode depthMode;
if (!float.IsInfinity(extents.DepthNear) &&
!float.IsInfinity(extents.DepthFar) &&
(extents.DepthFar - extents.DepthNear) != 0)
{
// Try to guess the depth mode being used on the high level API
// based on current transform.
// It is setup like so by said APIs:
// If depth mode is ZeroToOne:
// TranslateZ = Near
// ScaleZ = Far - Near
// If depth mode is MinusOneToOne:
// TranslateZ = (Near + Far) / 2
// ScaleZ = (Far - Near) / 2
// DepthNear/Far are sorted such as that Near is always less than Far.
depthMode = extents.DepthNear != transform.TranslateZ &&
extents.DepthFar != transform.TranslateZ
? DepthMode.MinusOneToOne
: DepthMode.ZeroToOne;
}
else
{
// If we can't guess from the viewport transform, then just use the depth mode register.
depthMode = (DepthMode)(_state.State.DepthMode & 1);
}
_context.Renderer.Pipeline.SetDepthMode(depthMode);
}
/// <summary> /// <summary>
/// Updates polygon mode state based on current GPU state. /// Updates polygon mode state based on current GPU state.
/// </summary> /// </summary>