Merge 9af84d9261
into e65effcb05
This commit is contained in:
commit
175f81351a
12 changed files with 199 additions and 55 deletions
|
@ -466,6 +466,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
|
||||
engine.UpdateState(ulong.MaxValue & ~(1UL << StateUpdater.ShaderStateIndex));
|
||||
|
||||
_channel.TextureManager.SignalRenderTargetsModifiable();
|
||||
_channel.TextureManager.UpdateRenderTargets();
|
||||
|
||||
int textureId = _state.State.DrawTextureTextureId;
|
||||
|
@ -803,7 +804,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
int index = (argument >> 6) & 0xf;
|
||||
int layer = (argument >> 10) & 0x3ff;
|
||||
|
||||
RenderTargetUpdateFlags updateFlags = RenderTargetUpdateFlags.SingleColor;
|
||||
RenderTargetUpdateFlags updateFlags = RenderTargetUpdateFlags.SingleColor | RenderTargetUpdateFlags.ForClear;
|
||||
|
||||
if (layer != 0 || layerCount > 1)
|
||||
{
|
||||
|
|
|
@ -38,6 +38,11 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
/// </summary>
|
||||
DiscardClip = 1 << 4,
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the render target will be used for a clear operation.
|
||||
/// </summary>
|
||||
ForClear = 1 << 5,
|
||||
|
||||
/// <summary>
|
||||
/// Default update flags for draw.
|
||||
/// </summary>
|
||||
|
|
|
@ -44,6 +44,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
private ProgramPipelineState _pipeline;
|
||||
|
||||
private bool _fsReadsFragCoord;
|
||||
private bool _fsAlwaysDiscards;
|
||||
private bool _vsUsesDrawParameters;
|
||||
private bool _vtgWritesRtLayer;
|
||||
private byte _vsClipDistancesWritten;
|
||||
|
@ -487,6 +488,8 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
bool changedScale = false;
|
||||
uint rtNoAlphaMask = 0;
|
||||
|
||||
bool rtModifiable = updateFlags.HasFlag(RenderTargetUpdateFlags.ForClear) || !_fsAlwaysDiscards;
|
||||
|
||||
for (int index = 0; index < Constants.TotalRenderTargets; index++)
|
||||
{
|
||||
int rtIndex = useControl ? rtControl.UnpackPermutationIndex(index) : index;
|
||||
|
@ -495,7 +498,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
|
||||
if (index >= count || !IsRtEnabled(colorState) || (singleColor && index != singleUse))
|
||||
{
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, null);
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, null, rtModifiable);
|
||||
|
||||
continue;
|
||||
}
|
||||
|
@ -514,7 +517,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
samplesInY,
|
||||
sizeHint);
|
||||
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, color);
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetColor(index, color, rtModifiable);
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
|
@ -568,7 +571,7 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
}
|
||||
}
|
||||
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetDepthStencil(depthStencil);
|
||||
changedScale |= _channel.TextureManager.SetRenderTargetDepthStencil(depthStencil, rtModifiable);
|
||||
|
||||
if (changedScale)
|
||||
{
|
||||
|
@ -1488,20 +1491,38 @@ namespace Ryujinx.Graphics.Gpu.Engine.Threed
|
|||
_currentProgramInfo[stageIndex] = info;
|
||||
}
|
||||
|
||||
if (gs.Shaders[5]?.Info.UsesFragCoord == true)
|
||||
{
|
||||
// Make sure we update the viewport size on the support buffer if it will be consumed on the new shader.
|
||||
_fsReadsFragCoord = false;
|
||||
|
||||
if (!_fsReadsFragCoord && _state.State.YControl.HasFlag(YControl.NegateY))
|
||||
ShaderProgramInfo fragmentShaderInfo = gs.Shaders[5]?.Info;
|
||||
|
||||
if (fragmentShaderInfo != null)
|
||||
{
|
||||
if (fragmentShaderInfo.UsesFragCoord)
|
||||
{
|
||||
UpdateSupportBufferViewportSize();
|
||||
// Make sure we update the viewport size on the support buffer if it will be consumed on the new shader.
|
||||
|
||||
if (!_fsReadsFragCoord && _state.State.YControl.HasFlag(YControl.NegateY))
|
||||
{
|
||||
UpdateSupportBufferViewportSize();
|
||||
}
|
||||
|
||||
_fsReadsFragCoord = true;
|
||||
}
|
||||
|
||||
_fsReadsFragCoord = true;
|
||||
if (_fsAlwaysDiscards != fragmentShaderInfo.HasUnconditionalDiscard)
|
||||
{
|
||||
_fsAlwaysDiscards = fragmentShaderInfo.HasUnconditionalDiscard;
|
||||
|
||||
if (!_fsAlwaysDiscards)
|
||||
{
|
||||
_channel.TextureManager.RefreshModifiedTextures();
|
||||
_channel.TextureManager.SignalRenderTargetsModifiable();
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
_fsReadsFragCoord = false;
|
||||
_fsAlwaysDiscards = false;
|
||||
}
|
||||
|
||||
if (gs.VertexAsCompute != null)
|
||||
|
|
|
@ -1479,11 +1479,6 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
/// <param name="bound">True if the texture has been bound, false if it has been unbound</param>
|
||||
public void SignalModifying(bool bound)
|
||||
{
|
||||
if (bound)
|
||||
{
|
||||
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
||||
}
|
||||
|
||||
if (_modifiedStale || Group.HasCopyDependencies || Group.HasFlushBuffer)
|
||||
{
|
||||
_modifiedStale = false;
|
||||
|
@ -1491,9 +1486,18 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
}
|
||||
|
||||
_physicalMemory.TextureCache.Lift(this);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Signals that a render target texture has been either bound or unbound.
|
||||
/// </summary>
|
||||
/// <param name="bound">True if the texture has been bound, false if it has been unbound</param>
|
||||
public void SignalBindingChange(bool bound)
|
||||
{
|
||||
if (bound)
|
||||
{
|
||||
_scaledSetScore = Math.Max(0, _scaledSetScore - 1);
|
||||
|
||||
IncrementReferenceCount();
|
||||
}
|
||||
else
|
||||
|
|
|
@ -187,7 +187,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
(TexturePool texturePool, SamplerPool samplerPool) = GetPools();
|
||||
|
||||
return (texturePool.Get(textureId), samplerPool.Get(samplerId));
|
||||
return (texturePool?.Get(textureId), samplerPool?.Get(samplerId));
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
|
|
@ -19,12 +19,39 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
private readonly TexturePoolCache _texturePoolCache;
|
||||
private readonly SamplerPoolCache _samplerPoolCache;
|
||||
|
||||
/// <summary>
|
||||
/// Bound render target texture modification report state.
|
||||
/// </summary>
|
||||
[Flags]
|
||||
private enum BindState : byte
|
||||
{
|
||||
/// <summary>
|
||||
/// Render target texture has not been signalled for modification, and can't be modified on the next render operations.
|
||||
/// </summary>
|
||||
None = 0,
|
||||
|
||||
/// <summary>
|
||||
/// Render target texture has been signalled for modification.
|
||||
/// </summary>
|
||||
Bound = 1 << 0,
|
||||
|
||||
/// <summary>
|
||||
/// Render target texture might be modified on the next render operations.
|
||||
/// </summary>
|
||||
Modified = 1 << 1,
|
||||
|
||||
/// <summary>
|
||||
/// Render target texture has been signalled for modification and might be modified on the next render operations.
|
||||
/// </summary>
|
||||
BoundModified = Bound | Modified,
|
||||
}
|
||||
|
||||
private readonly Texture[] _rtColors;
|
||||
private readonly ITexture[] _rtHostColors;
|
||||
private readonly bool[] _rtColorsBound;
|
||||
private readonly BindState[] _rtColorsBound;
|
||||
private Texture _rtDepthStencil;
|
||||
private ITexture _rtHostDs;
|
||||
private bool _rtDsBound;
|
||||
private BindState _rtDsBound;
|
||||
|
||||
public int ClipRegionWidth { get; private set; }
|
||||
public int ClipRegionHeight { get; private set; }
|
||||
|
@ -55,7 +82,7 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
_rtColors = new Texture[Constants.TotalRenderTargets];
|
||||
_rtHostColors = new ITexture[Constants.TotalRenderTargets];
|
||||
_rtColorsBound = new bool[Constants.TotalRenderTargets];
|
||||
_rtColorsBound = new BindState[Constants.TotalRenderTargets];
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
|
@ -151,27 +178,39 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
/// </summary>
|
||||
/// <param name="index">The index of the color buffer to set (up to 8)</param>
|
||||
/// <param name="color">The color buffer texture</param>
|
||||
/// <param name="modified">Indicates if the following render operations will modidify <paramref name="color"/> contents</param>
|
||||
/// <returns>True if render target scale must be updated.</returns>
|
||||
public bool SetRenderTargetColor(int index, Texture color)
|
||||
public bool SetRenderTargetColor(int index, Texture color, bool modified)
|
||||
{
|
||||
bool hasValue = color != null;
|
||||
bool changesScale = (hasValue != (_rtColors[index] != null)) || (hasValue && RenderTargetScale != color.ScaleFactor);
|
||||
|
||||
if (_rtColors[index] != color)
|
||||
{
|
||||
if (_rtColorsBound[index])
|
||||
Texture oldColor = _rtColors[index];
|
||||
|
||||
if (oldColor != null)
|
||||
{
|
||||
_rtColors[index]?.SignalModifying(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rtColorsBound[index] = true;
|
||||
if (_rtColorsBound[index].HasFlag(BindState.Bound))
|
||||
{
|
||||
oldColor.SignalModifying(false);
|
||||
}
|
||||
|
||||
oldColor.SignalBindingChange(false);
|
||||
}
|
||||
|
||||
_rtColorsBound[index] = modified ? BindState.BoundModified : BindState.None;
|
||||
|
||||
if (color != null)
|
||||
{
|
||||
color.SynchronizeMemory();
|
||||
color.SignalModifying(true);
|
||||
|
||||
if (modified)
|
||||
{
|
||||
color.SignalModifying(true);
|
||||
}
|
||||
|
||||
color.SignalBindingChange(true);
|
||||
}
|
||||
|
||||
_rtColors[index] = color;
|
||||
|
@ -184,27 +223,39 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
/// Sets the render target depth-stencil buffer.
|
||||
/// </summary>
|
||||
/// <param name="depthStencil">The depth-stencil buffer texture</param>
|
||||
/// <param name="modified">Indicates if the following render operations will modidify <paramref name="depthStencil"/> contents</param>
|
||||
/// <returns>True if render target scale must be updated.</returns>
|
||||
public bool SetRenderTargetDepthStencil(Texture depthStencil)
|
||||
public bool SetRenderTargetDepthStencil(Texture depthStencil, bool modified)
|
||||
{
|
||||
bool hasValue = depthStencil != null;
|
||||
bool changesScale = (hasValue != (_rtDepthStencil != null)) || (hasValue && RenderTargetScale != depthStencil.ScaleFactor);
|
||||
|
||||
if (_rtDepthStencil != depthStencil)
|
||||
{
|
||||
if (_rtDsBound)
|
||||
Texture oldDepthStencil = _rtDepthStencil;
|
||||
|
||||
if (oldDepthStencil != null)
|
||||
{
|
||||
_rtDepthStencil?.SignalModifying(false);
|
||||
}
|
||||
else
|
||||
{
|
||||
_rtDsBound = true;
|
||||
if (_rtDsBound.HasFlag(BindState.Bound))
|
||||
{
|
||||
oldDepthStencil.SignalModifying(false);
|
||||
}
|
||||
|
||||
oldDepthStencil.SignalBindingChange(false);
|
||||
}
|
||||
|
||||
_rtDsBound = modified ? BindState.BoundModified : BindState.None;
|
||||
|
||||
if (depthStencil != null)
|
||||
{
|
||||
depthStencil.SynchronizeMemory();
|
||||
depthStencil.SignalModifying(true);
|
||||
|
||||
if (modified)
|
||||
{
|
||||
depthStencil.SignalModifying(true);
|
||||
}
|
||||
|
||||
depthStencil.SignalBindingChange(true);
|
||||
}
|
||||
|
||||
_rtDepthStencil = depthStencil;
|
||||
|
@ -443,10 +494,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
hostDsTexture = dsTexture.HostTexture;
|
||||
|
||||
if (!_rtDsBound)
|
||||
if (_rtDsBound == BindState.Modified)
|
||||
{
|
||||
dsTexture.SignalModifying(true);
|
||||
_rtDsBound = true;
|
||||
_rtDsBound |= BindState.Bound;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -470,10 +521,10 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
hostTexture = texture.HostTexture;
|
||||
|
||||
if (!_rtColorsBound[index])
|
||||
if (_rtColorsBound[index] == BindState.Modified)
|
||||
{
|
||||
texture.SignalModifying(true);
|
||||
_rtColorsBound[index] = true;
|
||||
_rtColorsBound[index] |= BindState.Bound;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -518,24 +569,37 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
{
|
||||
Texture dsTexture = _rtDepthStencil;
|
||||
|
||||
if (dsTexture != null && _rtDsBound)
|
||||
if (dsTexture != null && _rtDsBound.HasFlag(BindState.Bound))
|
||||
{
|
||||
dsTexture.SignalModifying(false);
|
||||
_rtDsBound = false;
|
||||
_rtDsBound &= ~BindState.Bound;
|
||||
}
|
||||
|
||||
for (int index = 0; index < _rtColors.Length; index++)
|
||||
{
|
||||
Texture texture = _rtColors[index];
|
||||
|
||||
if (texture != null && _rtColorsBound[index])
|
||||
if (texture != null && _rtColorsBound[index].HasFlag(BindState.Bound))
|
||||
{
|
||||
texture.SignalModifying(false);
|
||||
_rtColorsBound[index] = false;
|
||||
_rtColorsBound[index] &= ~BindState.Bound;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the currently bound render targets might be modified, if they are used on the next render operation.
|
||||
/// </summary>
|
||||
public void SignalRenderTargetsModifiable()
|
||||
{
|
||||
_rtDsBound |= BindState.Modified;
|
||||
|
||||
for (int index = 0; index < _rtColorsBound.Length; index++)
|
||||
{
|
||||
_rtColorsBound[index] |= BindState.Modified;
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Forces the texture and sampler pools to be re-loaded from the cache on next use.
|
||||
/// </summary>
|
||||
|
@ -572,19 +636,11 @@ namespace Ryujinx.Graphics.Gpu.Image
|
|||
|
||||
for (int i = 0; i < _rtColors.Length; i++)
|
||||
{
|
||||
if (_rtColorsBound[i])
|
||||
{
|
||||
_rtColors[i]?.DecrementReferenceCount();
|
||||
}
|
||||
|
||||
_rtColors[i]?.DecrementReferenceCount();
|
||||
_rtColors[i] = null;
|
||||
}
|
||||
|
||||
if (_rtDsBound)
|
||||
{
|
||||
_rtDepthStencil?.DecrementReferenceCount();
|
||||
}
|
||||
|
||||
_rtDepthStencil?.DecrementReferenceCount();
|
||||
_rtDepthStencil = null;
|
||||
}
|
||||
}
|
||||
|
|
|
@ -22,7 +22,8 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
private const ushort FileFormatVersionMajor = 1;
|
||||
private const ushort FileFormatVersionMinor = 2;
|
||||
private const uint FileFormatVersionPacked = ((uint)FileFormatVersionMajor << 16) | FileFormatVersionMinor;
|
||||
private const uint CodeGenVersion = 5936;
|
||||
|
||||
private const uint CodeGenVersion = 6371;
|
||||
|
||||
private const string SharedTocFileName = "shared.toc";
|
||||
private const string SharedDataFileName = "shared.data";
|
||||
|
@ -170,6 +171,11 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
/// </summary>
|
||||
public bool UsesRtLayer;
|
||||
|
||||
/// <summary>
|
||||
/// Indicates that the fragment shader always discards the fragment, not producing any output for the bound render targets.
|
||||
/// </summary>
|
||||
public bool HasUnconditionalDiscard;
|
||||
|
||||
/// <summary>
|
||||
/// Bit mask with the clip distances written on the vertex stage.
|
||||
/// </summary>
|
||||
|
@ -806,6 +812,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
dataInfo.UsesInstanceId,
|
||||
dataInfo.UsesDrawParameters,
|
||||
dataInfo.UsesRtLayer,
|
||||
dataInfo.HasUnconditionalDiscard,
|
||||
dataInfo.ClipDistancesWritten,
|
||||
dataInfo.FragmentOutputMap);
|
||||
}
|
||||
|
@ -836,6 +843,7 @@ namespace Ryujinx.Graphics.Gpu.Shader.DiskCache
|
|||
UsesInstanceId = info.UsesInstanceId,
|
||||
UsesDrawParameters = info.UsesDrawParameters,
|
||||
UsesRtLayer = info.UsesRtLayer,
|
||||
HasUnconditionalDiscard = info.HasUnconditionalDiscard,
|
||||
ClipDistancesWritten = info.ClipDistancesWritten,
|
||||
FragmentOutputMap = info.FragmentOutputMap,
|
||||
};
|
||||
|
|
|
@ -23,6 +23,7 @@ namespace Ryujinx.Graphics.Shader.IntermediateRepresentation
|
|||
set => _branch = AddSuccessor(_branch, value);
|
||||
}
|
||||
|
||||
public bool HasSuccessor => _branch != null || _next != null;
|
||||
public bool HasBranch => _branch != null;
|
||||
public bool Reachable => Index == 0 || Predecessors.Count != 0;
|
||||
|
||||
|
|
|
@ -18,6 +18,7 @@ namespace Ryujinx.Graphics.Shader
|
|||
public bool UsesInstanceId { get; }
|
||||
public bool UsesDrawParameters { get; }
|
||||
public bool UsesRtLayer { get; }
|
||||
public bool HasUnconditionalDiscard { get; }
|
||||
public byte ClipDistancesWritten { get; }
|
||||
public int FragmentOutputMap { get; }
|
||||
|
||||
|
@ -34,6 +35,7 @@ namespace Ryujinx.Graphics.Shader
|
|||
bool usesInstanceId,
|
||||
bool usesDrawParameters,
|
||||
bool usesRtLayer,
|
||||
bool hasUnconditionalDiscard,
|
||||
byte clipDistancesWritten,
|
||||
int fragmentOutputMap)
|
||||
{
|
||||
|
@ -50,6 +52,7 @@ namespace Ryujinx.Graphics.Shader
|
|||
UsesInstanceId = usesInstanceId;
|
||||
UsesDrawParameters = usesDrawParameters;
|
||||
UsesRtLayer = usesRtLayer;
|
||||
HasUnconditionalDiscard = hasUnconditionalDiscard;
|
||||
ClipDistancesWritten = clipDistancesWritten;
|
||||
FragmentOutputMap = fragmentOutputMap;
|
||||
}
|
||||
|
|
|
@ -26,5 +26,6 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
SharedMemory = 1 << 11,
|
||||
Store = 1 << 12,
|
||||
VtgAsCompute = 1 << 13,
|
||||
UnconditionalDiscard = 1 << 14,
|
||||
}
|
||||
}
|
||||
|
|
|
@ -0,0 +1,38 @@
|
|||
using Ryujinx.Graphics.Shader.IntermediateRepresentation;
|
||||
|
||||
namespace Ryujinx.Graphics.Shader.Translation
|
||||
{
|
||||
static class FeatureIdentification
|
||||
{
|
||||
public static void RunPass(BasicBlock[] blocks, ShaderStage stage, ref FeatureFlags usedFeatures)
|
||||
{
|
||||
if (stage == ShaderStage.Fragment)
|
||||
{
|
||||
bool endsWithDiscardOnly = true;
|
||||
|
||||
for (int blockIndex = 0; blockIndex < blocks.Length; blockIndex++)
|
||||
{
|
||||
BasicBlock block = blocks[blockIndex];
|
||||
|
||||
if (block.HasSuccessor)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (block.Operations.Count == 0 ||
|
||||
block.Operations.Last.Value is not Operation operation ||
|
||||
operation.Inst != Instruction.Discard)
|
||||
{
|
||||
endsWithDiscardOnly = false;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (endsWithDiscardOnly)
|
||||
{
|
||||
usedFeatures |= FeatureFlags.UnconditionalDiscard;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
|
@ -301,6 +301,11 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
|
||||
Optimizer.RunPass(context);
|
||||
TransformPasses.RunPass(context);
|
||||
|
||||
if (i == 0)
|
||||
{
|
||||
FeatureIdentification.RunPass(cfg.Blocks, Definitions.Stage, ref usedFeatures);
|
||||
}
|
||||
}
|
||||
|
||||
funcs[i] = new Function(cfg.Blocks, $"fun{i}", false, inArgumentsCount, outArgumentsCount);
|
||||
|
@ -353,6 +358,7 @@ namespace Ryujinx.Graphics.Shader.Translation
|
|||
usedFeatures.HasFlag(FeatureFlags.InstanceId),
|
||||
usedFeatures.HasFlag(FeatureFlags.DrawParameters),
|
||||
usedFeatures.HasFlag(FeatureFlags.RtLayer),
|
||||
usedFeatures.HasFlag(FeatureFlags.UnconditionalDiscard),
|
||||
clipDistancesWritten,
|
||||
originalDefinitions.OmapTargets);
|
||||
|
||||
|
|
Loading…
Add table
Reference in a new issue