aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorriperiperi <rhy3756547@hotmail.com>2022-10-08 15:28:27 +0100
committerGitHub <noreply@github.com>2022-10-08 11:28:27 -0300
commit1ca0517c99af1914b887d6197b816c84537a9145 (patch)
treeea0042b2bd1f178991142c8a7b0ad339488eb244
parent599d485bffc9080d1c54acce929bbda0c7077499 (diff)
Vulkan: Fix some issues with CacheByRange (#3743)1.1.296
* Fix some issues with CacheByRange - Cache now clears under more circumstances, the most important being the fast path write. - Cache supports partial clear which should help when more buffers join. - Fixed an issue with I8->I16 conversion where it wouldn't register the buffer for use on dispose. Should hopefully fix issues with https://github.com/Ryujinx/Ryujinx-Games-List/issues/4010 and maybe others. * Fix collection modified exception * Fix accidental use of parameterless constructor * Replay DynamicState when restoring from helper shader
-rw-r--r--Ryujinx.Graphics.Vulkan/BufferHolder.cs34
-rw-r--r--Ryujinx.Graphics.Vulkan/BufferManager.cs10
-rw-r--r--Ryujinx.Graphics.Vulkan/CacheByRange.cs48
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineBase.cs53
-rw-r--r--Ryujinx.Graphics.Vulkan/PipelineFull.cs2
-rw-r--r--Ryujinx.Graphics.Vulkan/StagingBuffer.cs2
6 files changed, 124 insertions, 25 deletions
diff --git a/Ryujinx.Graphics.Vulkan/BufferHolder.cs b/Ryujinx.Graphics.Vulkan/BufferHolder.cs
index f449c102..20571253 100644
--- a/Ryujinx.Graphics.Vulkan/BufferHolder.cs
+++ b/Ryujinx.Graphics.Vulkan/BufferHolder.cs
@@ -109,12 +109,34 @@ namespace Ryujinx.Graphics.Vulkan
{
if (isWrite)
{
- _cachedConvertedBuffers.Clear();
+ SignalWrite(0, Size);
+ }
+
+ return _buffer;
+ }
+
+ public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, int offset, int size, bool isWrite = false)
+ {
+ if (isWrite)
+ {
+ SignalWrite(offset, size);
}
return _buffer;
}
+ public void SignalWrite(int offset, int size)
+ {
+ if (offset == 0 && size == Size)
+ {
+ _cachedConvertedBuffers.Clear();
+ }
+ else
+ {
+ _cachedConvertedBuffers.ClearRange(offset, size);
+ }
+ }
+
public BufferHandle GetHandle()
{
var handle = _bufferHandle;
@@ -183,6 +205,8 @@ namespace Ryujinx.Graphics.Vulkan
data.Slice(0, dataSize).CopyTo(new Span<byte>((void*)(_map + offset), dataSize));
+ SignalWrite(offset, dataSize);
+
return;
}
}
@@ -240,7 +264,7 @@ namespace Ryujinx.Graphics.Vulkan
endRenderPass?.Invoke();
- var dstBuffer = GetBuffer(cbs.CommandBuffer, true).Get(cbs, dstOffset, data.Length).Value;
+ var dstBuffer = GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true).Get(cbs, dstOffset, data.Length).Value;
InsertBufferBarrier(
_gd,
@@ -364,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, int offset, int size)
{
- var key = new I8ToI16CacheKey();
+ var key = new I8ToI16CacheKey(_gd);
if (!_cachedConvertedBuffers.TryGetValue(offset, size, key, out var holder))
{
@@ -373,6 +397,8 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertI8ToI16(_gd, cbs, this, holder, offset, size);
+ key.SetBuffer(holder.GetBuffer());
+
_cachedConvertedBuffers.Add(offset, size, key, holder);
}
@@ -417,6 +443,8 @@ namespace Ryujinx.Graphics.Vulkan
_gd.PipelineInternal.EndRenderPass();
_gd.HelperShader.ConvertIndexBuffer(_gd, cbs, this, holder, pattern, indexSize, offset, indexCount);
+ key.SetBuffer(holder.GetBuffer());
+
_cachedConvertedBuffers.Add(offset, size, key, holder);
}
diff --git a/Ryujinx.Graphics.Vulkan/BufferManager.cs b/Ryujinx.Graphics.Vulkan/BufferManager.cs
index e4820a30..57d67242 100644
--- a/Ryujinx.Graphics.Vulkan/BufferManager.cs
+++ b/Ryujinx.Graphics.Vulkan/BufferManager.cs
@@ -124,6 +124,16 @@ namespace Ryujinx.Graphics.Vulkan
return null;
}
+ public Auto<DisposableBuffer> GetBuffer(CommandBuffer commandBuffer, BufferHandle handle, int offset, int size, bool isWrite)
+ {
+ if (TryGetBuffer(handle, out var holder))
+ {
+ return holder.GetBuffer(commandBuffer, offset, size, isWrite);
+ }
+
+ return null;
+ }
+
public Auto<DisposableBuffer> GetBufferI8ToI16(CommandBufferScoped cbs, BufferHandle handle, int offset, int size)
{
if (TryGetBuffer(handle, out var holder))
diff --git a/Ryujinx.Graphics.Vulkan/CacheByRange.cs b/Ryujinx.Graphics.Vulkan/CacheByRange.cs
index 4c47e1c1..c77e66ae 100644
--- a/Ryujinx.Graphics.Vulkan/CacheByRange.cs
+++ b/Ryujinx.Graphics.Vulkan/CacheByRange.cs
@@ -25,6 +25,11 @@ namespace Ryujinx.Graphics.Vulkan
return other is I8ToI16CacheKey;
}
+ public void SetBuffer(Auto<DisposableBuffer> buffer)
+ {
+ _buffer = buffer;
+ }
+
public void Dispose()
{
_gd.PipelineInternal.DirtyIndexBuffer(_buffer);
@@ -160,6 +165,44 @@ namespace Ryujinx.Graphics.Vulkan
}
}
+ public void ClearRange(int offset, int size)
+ {
+ if (_ranges != null && _ranges.Count > 0)
+ {
+ int end = offset + size;
+
+ List<ulong> toRemove = null;
+
+ foreach (KeyValuePair<ulong, List<Entry>> range in _ranges)
+ {
+ (int rOffset, int rSize) = UnpackRange(range.Key);
+
+ int rEnd = rOffset + rSize;
+
+ if (rEnd > offset && rOffset < end)
+ {
+ List<Entry> entries = range.Value;
+
+ foreach (Entry entry in entries)
+ {
+ entry.Key.Dispose();
+ entry.Value.Dispose();
+ }
+
+ (toRemove ??= new List<ulong>()).Add(range.Key);
+ }
+ }
+
+ if (toRemove != null)
+ {
+ foreach (ulong range in toRemove)
+ {
+ _ranges.Remove(range);
+ }
+ }
+ }
+ }
+
private List<Entry> GetEntries(int offset, int size)
{
if (_ranges == null)
@@ -184,6 +227,11 @@ namespace Ryujinx.Graphics.Vulkan
return (uint)offset | ((ulong)size << 32);
}
+ private static (int offset, int size) UnpackRange(ulong range)
+ {
+ return ((int)range, (int)(range >> 32));
+ }
+
public void Dispose()
{
Clear();
diff --git a/Ryujinx.Graphics.Vulkan/PipelineBase.cs b/Ryujinx.Graphics.Vulkan/PipelineBase.cs
index 1a284e20..0eb61123 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineBase.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineBase.cs
@@ -21,7 +21,7 @@ namespace Ryujinx.Graphics.Vulkan
protected readonly AutoFlushCounter AutoFlush;
- private PipelineDynamicState _dynamicState;
+ protected PipelineDynamicState DynamicState;
private PipelineState _newState;
private bool _stateDirty;
private GAL.PrimitiveTopology _topology;
@@ -150,7 +150,7 @@ namespace Ryujinx.Graphics.Vulkan
{
EndRenderPass();
- var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true).Get(Cbs, offset, size).Value;
+ var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, offset, size, true).Get(Cbs, offset, size).Value;
BufferHolder.InsertBufferBarrier(
Gd,
@@ -238,8 +238,8 @@ namespace Ryujinx.Graphics.Vulkan
{
EndRenderPass();
- var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, false);
- var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, true);
+ var src = Gd.BufferManager.GetBuffer(CommandBuffer, source, srcOffset, size, false);
+ var dst = Gd.BufferManager.GetBuffer(CommandBuffer, destination, dstOffset, size, true);
BufferHolder.Copy(Gd, Cbs, src, dst, srcOffset, dstOffset, size);
}
@@ -388,7 +388,7 @@ namespace Ryujinx.Graphics.Vulkan
var oldDepthTestEnable = _newState.DepthTestEnable;
var oldDepthWriteEnable = _newState.DepthWriteEnable;
var oldTopology = _newState.Topology;
- var oldViewports = _dynamicState.Viewports;
+ var oldViewports = DynamicState.Viewports;
var oldViewportsCount = _newState.ViewportsCount;
_newState.CullMode = CullModeFlags.CullModeNone;
@@ -411,9 +411,9 @@ namespace Ryujinx.Graphics.Vulkan
_newState.DepthWriteEnable = oldDepthWriteEnable;
_newState.Topology = oldTopology;
- _dynamicState.Viewports = oldViewports;
- _dynamicState.ViewportsCount = (int)oldViewportsCount;
- _dynamicState.SetViewportsDirty();
+ DynamicState.Viewports = oldViewports;
+ DynamicState.ViewportsCount = (int)oldViewportsCount;
+ DynamicState.SetViewportsDirty();
_newState.ViewportsCount = oldViewportsCount;
SignalStateChange();
@@ -448,8 +448,13 @@ namespace Ryujinx.Graphics.Vulkan
ResumeTransformFeedbackInternal();
DrawCount++;
- var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
- var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
+ var buffer = Gd.BufferManager
+ .GetBuffer(CommandBuffer, indirectBuffer.Handle, indirectBuffer.Offset, indirectBuffer.Size, true)
+ .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
+
+ var countBuffer = Gd.BufferManager
+ .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
+ .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
Gd.DrawIndirectCountApi.CmdDrawIndirectCount(
CommandBuffer,
@@ -478,8 +483,13 @@ namespace Ryujinx.Graphics.Vulkan
ResumeTransformFeedbackInternal();
DrawCount++;
- var buffer = Gd.BufferManager.GetBuffer(CommandBuffer, indirectBuffer.Handle, true).Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
- var countBuffer = Gd.BufferManager.GetBuffer(CommandBuffer, parameterBuffer.Handle, true).Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
+ var buffer = Gd.BufferManager
+ .GetBuffer(CommandBuffer, indirectBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
+ .Get(Cbs, indirectBuffer.Offset, indirectBuffer.Size).Value;
+
+ var countBuffer = Gd.BufferManager
+ .GetBuffer(CommandBuffer, parameterBuffer.Handle, parameterBuffer.Offset, parameterBuffer.Size, true)
+ .Get(Cbs, parameterBuffer.Offset, parameterBuffer.Size).Value;
Gd.DrawIndirectCountApi.CmdDrawIndexedIndirectCount(
CommandBuffer,
@@ -535,7 +545,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetDepthBias(PolygonModeMask enables, float factor, float units, float clamp)
{
- _dynamicState.SetDepthBias(factor, units, clamp);
+ DynamicState.SetDepthBias(factor, units, clamp);
_newState.DepthBiasEnable = enables != 0;
SignalStateChange();
@@ -753,10 +763,10 @@ namespace Ryujinx.Graphics.Vulkan
var offset = new Offset2D(region.X, region.Y);
var extent = new Extent2D((uint)region.Width, (uint)region.Height);
- _dynamicState.SetScissor(i, new Rect2D(offset, extent));
+ DynamicState.SetScissor(i, new Rect2D(offset, extent));
}
- _dynamicState.ScissorsCount = count;
+ DynamicState.ScissorsCount = count;
_newState.ScissorsCount = (uint)count;
SignalStateChange();
@@ -764,7 +774,7 @@ namespace Ryujinx.Graphics.Vulkan
public void SetStencilTest(StencilTestDescriptor stencilTest)
{
- _dynamicState.SetStencilMasks(
+ DynamicState.SetStencilMasks(
(uint)stencilTest.BackFuncMask,
(uint)stencilTest.BackMask,
(uint)stencilTest.BackFuncRef,
@@ -813,7 +823,8 @@ namespace Ryujinx.Graphics.Vulkan
if (range.Handle != BufferHandle.Null)
{
- _transformFeedbackBuffers[i] = new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, true), range.Offset, range.Size);
+ _transformFeedbackBuffers[i] =
+ new BufferState(Gd.BufferManager.GetBuffer(CommandBuffer, range.Handle, range.Offset, range.Size, true), range.Offset, range.Size);
_transformFeedbackBuffers[i].BindTransformFeedbackBuffer(Gd, Cbs, (uint)i);
}
else
@@ -975,7 +986,7 @@ namespace Ryujinx.Graphics.Vulkan
{
var viewport = viewports[i];
- _dynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport(
+ DynamicState.SetViewport(i, new Silk.NET.Vulkan.Viewport(
viewport.Region.X,
viewport.Region.Y,
viewport.Region.Width == 0f ? 1f : viewport.Region.Width,
@@ -984,7 +995,7 @@ namespace Ryujinx.Graphics.Vulkan
Clamp(viewport.DepthFar)));
}
- _dynamicState.ViewportsCount = count;
+ DynamicState.ViewportsCount = count;
float disableTransformF = disableTransform ? 1.0f : 0.0f;
if (SupportBufferUpdater.Data.ViewportInverse.W != disableTransformF || disableTransform)
@@ -1063,7 +1074,7 @@ namespace Ryujinx.Graphics.Vulkan
_vertexBuffersDirty = ulong.MaxValue >> (64 - _vertexBuffers.Length);
_descriptorSetUpdater.SignalCommandBufferChange();
- _dynamicState.ForceAllDirty();
+ DynamicState.ForceAllDirty();
_currentPipelineHandle = 0;
}
@@ -1201,7 +1212,7 @@ namespace Ryujinx.Graphics.Vulkan
private void RecreatePipelineIfNeeded(PipelineBindPoint pbp)
{
- _dynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
+ DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
// Commit changes to the support buffer before drawing.
SupportBufferUpdater.Commit();
diff --git a/Ryujinx.Graphics.Vulkan/PipelineFull.cs b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
index c8692993..1ad9f3e6 100644
--- a/Ryujinx.Graphics.Vulkan/PipelineFull.cs
+++ b/Ryujinx.Graphics.Vulkan/PipelineFull.cs
@@ -204,6 +204,8 @@ namespace Ryujinx.Graphics.Vulkan
}
SignalCommandBufferChange();
+
+ DynamicState.ReplayIfDirty(Gd.Api, CommandBuffer);
}
public void FlushCommandsImpl()
diff --git a/Ryujinx.Graphics.Vulkan/StagingBuffer.cs b/Ryujinx.Graphics.Vulkan/StagingBuffer.cs
index fe7a786b..df353453 100644
--- a/Ryujinx.Graphics.Vulkan/StagingBuffer.cs
+++ b/Ryujinx.Graphics.Vulkan/StagingBuffer.cs
@@ -87,7 +87,7 @@ namespace Ryujinx.Graphics.Vulkan
private void PushDataImpl(CommandBufferScoped cbs, BufferHolder dst, int dstOffset, ReadOnlySpan<byte> data)
{
var srcBuffer = _buffer.GetBuffer();
- var dstBuffer = dst.GetBuffer();
+ var dstBuffer = dst.GetBuffer(cbs.CommandBuffer, dstOffset, data.Length, true);
int offset = _freeOffset;
int capacity = BufferSize - offset;