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,19 +500,6 @@ 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);
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;
}
(_, int samplerWordOffset, _) = TextureHandle.UnpackOffsets(bindingInfo.Handle);
CacheEntry entry = GetOrAddEntry( CacheEntry entry = GetOrAddEntry(
texturePool, texturePool,
samplerPool, samplerPool,
@ -486,30 +508,63 @@ namespace Ryujinx.Graphics.Gpu.Image
ref textureBufferBounds, ref textureBufferBounds,
out bool isNewEnry); out bool isNewEnry);
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
bool poolsModified = entry.PoolsModified(); bool poolsModified = entry.PoolsModified();
bool isStore = bindingInfo.Flags.HasFlag(TextureUsageFlags.ImageStore);
if (!poolsModified && ReadOnlySpan<int> cachedTextureBuffer;
!isNewEnry && ReadOnlySpan<int> cachedSamplerBuffer;
entry.MatchesBufferData(cachedTextureBuffer, cachedSamplerBuffer, separateSamplerBuffer, samplerWordOffset) &&
entry.ValidateTextures()) if (!poolsModified && !isNewEnry && entry.ValidateTextures())
{ {
foreach (Texture texture in entry.Textures.Keys) if (entry.MatchesSequenceNumber(_context.SequenceNumber))
{ {
texture.SynchronizeMemory(); entry.SynchronizeMemory(isStore);
if (isStore) if (entry.BindingChanged(this, bindingInfo.Binding))
{ {
texture.SignalModified(); _context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
} }
return;
} }
if (entry.BindingChanged(this, bindingInfo.Binding)) cachedTextureBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(textureBufferBounds.Range));
if (separateSamplerBuffer)
{ {
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray); cachedSamplerBuffer = MemoryMarshal.Cast<byte, int>(_channel.MemoryManager.Physical.GetSpan(samplerBufferBounds.Range));
}
else
{
cachedSamplerBuffer = cachedTextureBuffer;
} }
return; (_, int samplerWordOffset, _) = TextureHandle.UnpackOffsets(bindingInfo.Handle);
if (entry.MatchesBufferData(cachedTextureBuffer, cachedSamplerBuffer, separateSamplerBuffer, samplerWordOffset))
{
entry.SynchronizeMemory(isStore);
if (entry.BindingChanged(this, bindingInfo.Binding))
{
_context.Renderer.Pipeline.SetTextureArray(stage, bindingInfo.Binding, entry.TextureArray);
}
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)