Implement Viewport Transform Disable (#3328)

* Initial implementation (no specialization)

* Use specialization

* Fix render scale, increase code gen version

* Revert accidental change

* Address Feedback
This commit is contained in:
riperiperi 2022-05-12 14:47:13 +01:00 committed by GitHub
parent 92ca1cb0cb
commit 43b4b34376
No known key found for this signature in database
GPG key ID: 4AEE18F83AFDEB23
24 changed files with 200 additions and 26 deletions

View file

@ -113,7 +113,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
nameof(ThreedClassState.DepthMode),
nameof(ThreedClassState.ViewportTransform),
nameof(ThreedClassState.ViewportExtents),
nameof(ThreedClassState.YControl)),
nameof(ThreedClassState.YControl),
nameof(ThreedClassState.ViewportTransformEnable)),
new StateUpdateCallbackEntry(UpdatePolygonMode,
nameof(ThreedClassState.PolygonModeFront),
@ -200,7 +201,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
// of the shader for the new state.
if (_shaderSpecState != null)
{
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState()))
if (!_shaderSpecState.MatchesGraphics(_channel, GetPoolState(), GetGraphicsState()))
{
ForceShaderUpdate();
}
@ -568,6 +569,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
var yControl = _state.State.YControl;
var face = _state.State.FaceState;
bool disableTransform = _state.State.ViewportTransformEnable == 0;
UpdateFrontFace(yControl, face.FrontFace);
UpdateDepthMode();
@ -577,6 +580,17 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
for (int index = 0; index < Constants.TotalViewports; index++)
{
if (disableTransform)
{
ref var scissor = ref _state.State.ScreenScissorState;
float rScale = _channel.TextureManager.RenderTargetScale;
var scissorRect = new RectangleF(0, 0, (scissor.X + scissor.Width) * rScale, (scissor.Y + scissor.Height) * rScale);
viewports[index] = new Viewport(scissorRect, ViewportSwizzle.PositiveX, ViewportSwizzle.PositiveY, ViewportSwizzle.PositiveZ, ViewportSwizzle.PositiveW, 0, 1);
continue;
}
ref var transform = ref _state.State.ViewportTransform[index];
ref var extents = ref _state.State.ViewportExtents[index];
@ -628,7 +642,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
viewports[index] = new Viewport(region, swizzleX, swizzleY, swizzleZ, swizzleW, depthNear, depthFar);
}
_context.Renderer.Pipeline.SetViewports(0, viewports);
_context.Renderer.Pipeline.SetViewports(0, viewports, disableTransform);
}
/// <summary>
@ -1194,7 +1208,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
return new GpuChannelGraphicsState(
_state.State.EarlyZForce,
_drawState.Topology,
_state.State.TessMode);
_state.State.TessMode,
_state.State.ViewportTransformEnable == 0);
}
/// <summary>

View file

@ -166,7 +166,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.Cache
GpuChannelGraphicsState graphicsState = new GpuChannelGraphicsState(
accessorHeader.StateFlags.HasFlag(GuestGpuStateFlags.EarlyZForce),
topology,
tessMode);
tessMode,
false);
TransformFeedbackDescriptor[] tfdNew = null;

View file

@ -185,6 +185,12 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
return _oldSpecState.GraphicsState.EarlyZForce;
}
/// <inheritdoc/>
public bool QueryViewportTransformDisable()
{
return _oldSpecState.GraphicsState.ViewportTransformDisable;
}
/// <inheritdoc/>
public void RegisterTexture(int handle, int cbufSlot)
{

View file

@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
private const ushort FileFormatVersionMajor = 1;
private const ushort FileFormatVersionMinor = 1;
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
private const uint CodeGenVersion = 0;
private const uint CodeGenVersion = 1;
private const string SharedTocFileName = "shared.toc";
private const string SharedDataFileName = "shared.data";

View file

@ -217,6 +217,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
return _state.GraphicsState.EarlyZForce;
}
/// <inheritdoc/>
public bool QueryViewportTransformDisable()
{
return _state.GraphicsState.ViewportTransformDisable;
}
/// <inheritdoc/>
public void RegisterTexture(int handle, int cbufSlot)
{

View file

@ -25,17 +25,24 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
public readonly TessMode TessellationMode;
/// <summary>
/// Indicates whenever the viewport transform is disabled.
/// </summary>
public readonly bool ViewportTransformDisable;
/// <summary>
/// Creates a new GPU graphics state.
/// </summary>
/// <param name="earlyZForce">Early Z force enable</param>
/// <param name="topology">Primitive topology</param>
/// <param name="tessellationMode">Tessellation mode</param>
public GpuChannelGraphicsState(bool earlyZForce, PrimitiveTopology topology, TessMode tessellationMode)
/// <param name="viewportTransformDisable">Indicates whenever the viewport transform is disabled</param>
public GpuChannelGraphicsState(bool earlyZForce, PrimitiveTopology topology, TessMode tessellationMode, bool viewportTransformDisable)
{
EarlyZForce = earlyZForce;
Topology = topology;
TessellationMode = tessellationMode;
ViewportTransformDisable = viewportTransformDisable;
}
}
}

View file

@ -249,12 +249,12 @@ namespace Ryujinx.Graphics.Gpu.Shader
GpuChannelGraphicsState graphicsState,
ShaderAddresses addresses)
{
if (_gpPrograms.TryGetValue(addresses, out var gpShaders) && IsShaderEqual(channel, poolState, gpShaders, addresses))
if (_gpPrograms.TryGetValue(addresses, out var gpShaders) && IsShaderEqual(channel, poolState, graphicsState, gpShaders, addresses))
{
return gpShaders;
}
if (_graphicsShaderCache.TryFind(channel, poolState, addresses, out gpShaders, out var cachedGuestCode))
if (_graphicsShaderCache.TryFind(channel, poolState, graphicsState, addresses, out gpShaders, out var cachedGuestCode))
{
_gpPrograms[addresses] = gpShaders;
return gpShaders;
@ -429,12 +429,14 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel using the shader</param>
/// <param name="poolState">GPU channel state to verify shader compatibility</param>
/// <param name="graphicsState">GPU channel graphics state to verify shader compatibility</param>
/// <param name="gpShaders">Cached graphics shaders</param>
/// <param name="addresses">GPU virtual addresses of all enabled shader stages</param>
/// <returns>True if the code is different, false otherwise</returns>
private static bool IsShaderEqual(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelGraphicsState graphicsState,
CachedShaderProgram gpShaders,
ShaderAddresses addresses)
{
@ -452,7 +454,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
}
}
return gpShaders.SpecializationState.MatchesGraphics(channel, poolState);
return gpShaders.SpecializationState.MatchesGraphics(channel, poolState, graphicsState);
}
/// <summary>

View file

@ -208,6 +208,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </remarks>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="graphicsState">Graphics state</param>
/// <param name="addresses">Guest addresses of the shaders to find</param>
/// <param name="program">Cached host program for the given state, if found</param>
/// <param name="guestCode">Cached guest code, if any found</param>
@ -215,6 +216,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
public bool TryFind(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelGraphicsState graphicsState,
ShaderAddresses addresses,
out CachedShaderProgram program,
out CachedGraphicsGuestCode guestCode)
@ -234,7 +236,7 @@ namespace Ryujinx.Graphics.Gpu.Shader
if (found && _shaderPrograms.TryGetValue(idTable, out ShaderSpecializationList specList))
{
return specList.TryFindForGraphics(channel, poolState, out program);
return specList.TryFindForGraphics(channel, poolState, graphicsState, out program);
}
return false;

View file

@ -24,13 +24,18 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="graphicsState">Graphics state</param>
/// <param name="program">Cached program, if found</param>
/// <returns>True if a compatible program is found, false otherwise</returns>
public bool TryFindForGraphics(GpuChannel channel, GpuChannelPoolState poolState, out CachedShaderProgram program)
public bool TryFindForGraphics(
GpuChannel channel,
GpuChannelPoolState poolState,
GpuChannelGraphicsState graphicsState,
out CachedShaderProgram program)
{
foreach (var entry in _entries)
{
if (entry.SpecializationState.MatchesGraphics(channel, poolState))
if (entry.SpecializationState.MatchesGraphics(channel, poolState, graphicsState))
{
program = entry;
return true;

View file

@ -395,9 +395,15 @@ namespace Ryujinx.Graphics.Gpu.Shader
/// </summary>
/// <param name="channel">GPU channel</param>
/// <param name="poolState">Texture pool state</param>
/// <param name="graphicsState">Graphics state</param>
/// <returns>True if the state matches, false otherwise</returns>
public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState)
public bool MatchesGraphics(GpuChannel channel, GpuChannelPoolState poolState, GpuChannelGraphicsState graphicsState)
{
if (graphicsState.ViewportTransformDisable != GraphicsState.ViewportTransformDisable)
{
return false;
}
return Matches(channel, poolState, isCompute: false);
}