Avoid useless buffer data modification checks

This commit is contained in:
Gabriel A 2024-03-25 13:32:15 -03:00
parent c8a19501ee
commit 70a6b7ea65

View file

@ -176,6 +176,7 @@ namespace Ryujinx.Graphics.Gpu.Image
private int[] _cachedSamplerBuffer; private int[] _cachedSamplerBuffer;
private int _lastBinding; private int _lastBinding;
private int _lastSequenceNumber;
/// <summary> /// <summary>
/// Creates a new array cache entry. /// Creates a new array cache entry.
@ -192,6 +193,9 @@ namespace Ryujinx.Graphics.Gpu.Image
_texturePool = texturePool; _texturePool = texturePool;
_samplerPool = samplerPool; _samplerPool = samplerPool;
_lastBinding = -1;
_lastSequenceNumber = -1;
} }
/// <summary> /// <summary>
@ -218,6 +222,23 @@ namespace Ryujinx.Graphics.Gpu.Image
ImageArray = array; ImageArray = array;
} }
/// <summary>
/// Synchronizes memory for all textures in the array.
/// </summary>
/// <param name="isStore">Indicates if the texture may be modified by the access</param>
public void SynchronizeMemory(bool isStore)
{
foreach (Texture texture in Textures.Keys)
{
texture.SynchronizeMemory();
if (isStore)
{
texture.SignalModified();
}
}
}
/// <summary> /// <summary>
/// Clears all cached texture instances. /// Clears all cached texture instances.
/// </summary> /// </summary>
@ -336,6 +357,23 @@ namespace Ryujinx.Graphics.Gpu.Image
return false; return false;
} }
/// <summary>
/// Checks if the sequence number matches the one used on the last call to this method.
/// </summary>
/// <param name="currentSequenceNumber">Current sequence number</param>
/// <returns>True if the sequence numbers match, false otherwise</returns>
public bool MatchesSequenceNumber(int currentSequenceNumber)
{
if (_lastSequenceNumber == currentSequenceNumber)
{
return true;
}
_lastSequenceNumber = currentSequenceNumber;
return false;
}
/// <summary> /// <summary>
/// Checks if the buffer data matches the cached data. /// Checks if the buffer data matches the cached data.
/// </summary> /// </summary>
@ -455,9 +493,6 @@ namespace Ryujinx.Graphics.Gpu.Image
SamplerIndex samplerIndex, SamplerIndex samplerIndex,
TextureBindingInfo bindingInfo) TextureBindingInfo bindingInfo)
{ {
ReadOnlySpan<int> cachedTextureBuffer;
ReadOnlySpan<int> cachedSamplerBuffer;
(textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, textureBufferIndex); (textureBufferIndex, int samplerBufferIndex) = TextureHandle.UnpackSlots(bindingInfo.CbufSlot, textureBufferIndex);
bool separateSamplerBuffer = textureBufferIndex != samplerBufferIndex; bool separateSamplerBuffer = textureBufferIndex != samplerBufferIndex;
@ -465,6 +500,34 @@ namespace Ryujinx.Graphics.Gpu.Image
ref BufferBounds textureBufferBounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, textureBufferIndex); ref BufferBounds textureBufferBounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, textureBufferIndex);
ref BufferBounds samplerBufferBounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, samplerBufferIndex); ref BufferBounds samplerBufferBounds = ref _channel.BufferManager.GetUniformBufferBounds(_isCompute, stageIndex, samplerBufferIndex);
CacheEntry entry = GetOrAddEntry(
texturePool,
samplerPool,
bindingInfo,
isImage,
ref textureBufferBounds,
out bool isNewEnry);
bool poolsModified = entry.PoolsModified();
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
ReadOnlySpan<int> cachedTextureBuffer;
ReadOnlySpan<int> cachedSamplerBuffer;
if (!poolsModified && !isNewEnry && entry.ValidateTextures())
{
if (entry.MatchesSequenceNumber(_context.SequenceNumber))
{
entry.SynchronizeMemory(isStore);
if (entry.BindingChanged(this, bindingInfo.Binding))
{
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
}
return;
}
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(textureBufferBounds.Range)); cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(textureBufferBounds.Range));
if (separateSamplerBuffer) if (separateSamplerBuffer)
@ -478,31 +541,9 @@ namespace Ryujinx.Graphics.Gpu.Image
(_, int samplerWordOffset, _) = TextureHandle.UnpackOffsets(bindingInfo.Handle); (_, int samplerWordOffset, _) = TextureHandle.UnpackOffsets(bindingInfo.Handle);
CacheEntry entry = GetOrAddEntry( if (entry.MatchesBufferData(cachedTextureBuffer, cachedSamplerBuffer, separateSamplerBuffer, samplerWordOffset))
texturePool,
samplerPool,
bindingInfo,
isImage,
ref textureBufferBounds,
out bool isNewEnry);
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
bool poolsModified = entry.PoolsModified();
if (!poolsModified &&
!isNewEnry &&
entry.MatchesBufferData(cachedTextureBuffer, cachedSamplerBuffer, separateSamplerBuffer, samplerWordOffset) &&
entry.ValidateTextures())
{ {
foreach (Texture texture in entry.Textures.Keys) entry.SynchronizeMemory(isStore);
{
texture.SynchronizeMemory();
if (isStore)
{
texture.SignalModified();
}
}
if (entry.BindingChanged(this, bindingInfo.Binding)) if (entry.BindingChanged(this, bindingInfo.Binding))
{ {
@ -511,6 +552,20 @@ namespace Ryujinx.Graphics.Gpu.Image
return; return;
} }
}
else
{
cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(textureBufferBounds.Range));
if (separateSamplerBuffer)
{
cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(samplerBufferBounds.Range));
}
else
{
cachedSamplerBuffer = cachedTextureBuffer;
}
}
if (!isNewEnry) if (!isNewEnry)
{ {