Skip to content

Commit

Permalink
Initial implementation of buffer mirrors
Browse files Browse the repository at this point in the history
Generally slower right now, goal is to reduce render passes in games that do inline updates

Fix support buffer mirrors

Reintroduce vertex buffer mirror

Add storage buffer support

Optimisation part 1

More optimisation

Avoid useless data copies.

Remove unused cbIndex stuff

Properly set write flag for storage buffers.

Fix minor issues

Not sure why this was here.

Fix BufferRangeList

Fix some big issues

Align storage buffers rather than getting full buffer as a range

Improves mirrorability of read-only storage buffers

Increase staging buffer size, as it now contains mirrors

Fix some issues with buffers not updating

Fix buffer SetDataUnchecked offset for one of the paths when using mirrors

Fix buffer mirrors interaction with buffer textures

Fix mirror rebinding

Move GetBuffer calls on indirect draws before BeginRenderPass to avoid draws without render pass

Fix mirrors rebase

Fix rebase 2023
  • Loading branch information
riperiperi committed May 22, 2023
1 parent 2725e40 commit 5974e86
Show file tree
Hide file tree
Showing 20 changed files with 1,265 additions and 127 deletions.
4 changes: 3 additions & 1 deletion src/Ryujinx.Graphics.GAL/BufferRange.cs
Expand Up @@ -10,12 +10,14 @@ namespace Ryujinx.Graphics.GAL

public int Offset { get; }
public int Size { get; }
public bool Write { get; }

public BufferRange(BufferHandle handle, int offset, int size)
public BufferRange(BufferHandle handle, int offset, int size, bool write = false)
{
Handle = handle;
Offset = offset;
Size = size;
Write = write;
}
}
}
8 changes: 4 additions & 4 deletions src/Ryujinx.Graphics.GAL/Multithreading/BufferMap.cs
Expand Up @@ -116,7 +116,7 @@ internal BufferHandle MapBufferBlocking(BufferHandle handle)

internal BufferRange MapBufferRange(BufferRange range)
{
return new BufferRange(MapBuffer(range.Handle), range.Offset, range.Size);
return new BufferRange(MapBuffer(range.Handle), range.Offset, range.Size, range.Write);
}

internal Span<BufferRange> MapBufferRanges(Span<BufferRange> ranges)
Expand All @@ -135,7 +135,7 @@ internal Span<BufferRange> MapBufferRanges(Span<BufferRange> ranges)
result = BufferHandle.Null;
}

range = new BufferRange(result, range.Offset, range.Size);
range = new BufferRange(result, range.Offset, range.Size, range.Write);
}
}

Expand All @@ -159,7 +159,7 @@ internal Span<BufferAssignment> MapBufferRanges(Span<BufferAssignment> ranges)
result = BufferHandle.Null;
}

assignment = new BufferAssignment(ranges[i].Binding, new BufferRange(result, range.Offset, range.Size));
assignment = new BufferAssignment(ranges[i].Binding, new BufferRange(result, range.Offset, range.Size, range.Write));
}
}

Expand All @@ -182,7 +182,7 @@ internal Span<VertexBufferDescriptor> MapBufferRanges(Span<VertexBufferDescripto
result = BufferHandle.Null;
}

range = new BufferRange(result, range.Offset, range.Size);
range = new BufferRange(result, range.Offset, range.Size, range.Write);

ranges[i] = new VertexBufferDescriptor(range, ranges[i].Stride, ranges[i].Divisor);
}
Expand Down
14 changes: 9 additions & 5 deletions src/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
Expand Up @@ -140,18 +140,21 @@ public Buffer(GpuContext context, PhysicalMemory physicalMemory, ulong address,
}

/// <summary>
/// Gets a sub-range from the buffer, from a start address till the end of the buffer.
/// Gets a sub-range from the buffer, from a start address til a page boundary after the given size.
/// </summary>
/// <remarks>
/// This can be used to bind and use sub-ranges of the buffer on the host API.
/// </remarks>
/// <param name="address">Start address of the sub-range, must be greater than or equal to the buffer address</param>
/// <param name="size">Size in bytes of the sub-range, must be less than or equal to the buffer size</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer sub-range</returns>
public BufferRange GetRange(ulong address)
public BufferRange GetRangeAligned(ulong address, ulong size, bool write)
{
ulong end = ((address + size + MemoryManager.PageMask) & ~MemoryManager.PageMask) - Address;
ulong offset = address - Address;

return new BufferRange(Handle, (int)offset, (int)(Size - offset));
return new BufferRange(Handle, (int)offset, (int)(end - offset), write);
}

/// <summary>
Expand All @@ -162,12 +165,13 @@ public BufferRange GetRange(ulong address)
/// </remarks>
/// <param name="address">Start address of the sub-range, must be greater than or equal to the buffer address</param>
/// <param name="size">Size in bytes of the sub-range, must be less than or equal to the buffer size</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer sub-range</returns>
public BufferRange GetRange(ulong address, ulong size)
public BufferRange GetRange(ulong address, ulong size, bool write)
{
int offset = (int)(address - Address);

return new BufferRange(Handle, offset, (int)size);
return new BufferRange(Handle, offset, (int)size, write);
}

/// <summary>
Expand Down
20 changes: 16 additions & 4 deletions src/Ryujinx.Graphics.Gpu/Memory/BufferCache.cs
Expand Up @@ -372,15 +372,27 @@ public void ClearBuffer(MemoryManager memoryManager, ulong gpuVa, ulong size, ui
}

/// <summary>
/// Gets a buffer sub-range starting at a given memory address.
/// Gets a buffer sub-range for a given GPU memory range.
/// </summary>
/// <param name="memoryManager">GPU memory manager where the buffer is mapped</param>
/// <param name="gpuVa">Start GPU virtual address of the buffer</param>
/// <param name="size">Size in bytes of the buffer</param>
/// <returns>The buffer sub-range for the given range</returns>
public BufferRange GetGpuBufferRange(MemoryManager memoryManager, ulong gpuVa, ulong size)
{
return GetBufferRange(TranslateAndCreateBuffer(memoryManager, gpuVa, size), size);
}

/// <summary>
/// Gets a buffer sub-range from a start address til a page boundary after the given size.
/// </summary>
/// <param name="address">Start address of the memory range</param>
/// <param name="size">Size in bytes of the memory range</param>
/// <param name="write">Whether the buffer will be written to by this use</param>
/// <returns>The buffer sub-range starting at the given memory address</returns>
public BufferRange GetBufferRangeTillEnd(ulong address, ulong size, bool write = false)
public BufferRange GetBufferRangeAligned(ulong address, ulong size, bool write = false)
{
return GetBuffer(address, size, write).GetRange(address);
return GetBuffer(address, size, write).GetRangeAligned(address, size, write);
}

/// <summary>
Expand All @@ -392,7 +404,7 @@ public BufferRange GetBufferRangeTillEnd(ulong address, ulong size, bool write =
/// <returns>The buffer sub-range for the given range</returns>
public BufferRange GetBufferRange(ulong address, ulong size, bool write = false)
{
return GetBuffer(address, size, write).GetRange(address, size);
return GetBuffer(address, size, write).GetRange(address, size, write);
}

/// <summary>
Expand Down
4 changes: 2 additions & 2 deletions src/Ryujinx.Graphics.Gpu/Memory/BufferManager.cs
Expand Up @@ -623,7 +623,7 @@ private void BindBuffers(BufferCache bufferCache, BuffersPerStage[] bindings, bo
{
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
var range = isStorage
? bufferCache.GetBufferRangeTillEnd(bounds.Address, bounds.Size, isWrite)
? bufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
: bufferCache.GetBufferRange(bounds.Address, bounds.Size);

ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
Expand Down Expand Up @@ -660,7 +660,7 @@ private void BindBuffers(BufferCache bufferCache, BuffersPerStage buffers, bool
{
var isWrite = bounds.Flags.HasFlag(BufferUsageFlags.Write);
var range = isStorage
? bufferCache.GetBufferRangeTillEnd(bounds.Address, bounds.Size, isWrite)
? bufferCache.GetBufferRangeAligned(bounds.Address, bounds.Size, isWrite)
: bufferCache.GetBufferRange(bounds.Address, bounds.Size);

ranges[rangesCount++] = new BufferAssignment(bindingInfo.Binding, range);
Expand Down
25 changes: 23 additions & 2 deletions src/Ryujinx.Graphics.Vulkan/Auto.cs
Expand Up @@ -18,6 +18,12 @@ interface IAutoPrivate : IAuto
void AddCommandBufferDependencies(CommandBufferScoped cbs);
}

interface IMirrorable<T> where T : IDisposable
{
Auto<T> GetMirrorable(CommandBufferScoped cbs, ref int offset, int size, out bool mirrored);
void ClearMirrors(CommandBufferScoped cbs, int offset, int size);
}

class Auto<T> : IAutoPrivate, IDisposable where T : IDisposable
{
private int _referenceCount;
Expand All @@ -26,6 +32,7 @@ class Auto<T> : IAutoPrivate, IDisposable where T : IDisposable
private readonly BitMap _cbOwnership;
private readonly MultiFenceHolder _waitable;
private readonly IAutoPrivate[] _referencedObjs;
private readonly IMirrorable<T> _mirrorable;

private bool _disposed;
private bool _destroyed;
Expand All @@ -37,6 +44,11 @@ public Auto(T value)
_cbOwnership = new BitMap(CommandBufferPool.MaxCommandBuffers);
}

public Auto(T value, IMirrorable<T> mirrorable, MultiFenceHolder waitable, params IAutoPrivate[] referencedObjs) : this(value, waitable, referencedObjs)
{
_mirrorable = mirrorable;
}

public Auto(T value, MultiFenceHolder waitable, params IAutoPrivate[] referencedObjs) : this(value)
{
_waitable = waitable;
Expand All @@ -48,9 +60,18 @@ public Auto(T value, MultiFenceHolder waitable, params IAutoPrivate[] referenced
}
}

public T Get(CommandBufferScoped cbs, int offset, int size)
public T GetMirrorable(CommandBufferScoped cbs, ref int offset, int size, out bool mirrored)
{
mirrored = false;
var mirror = _mirrorable?.GetMirrorable(cbs, ref offset, size, out mirrored);
mirror._waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size, false);
return mirror.Get(cbs);
}

public T Get(CommandBufferScoped cbs, int offset, int size, bool write = false)
{
_waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size);
_mirrorable?.ClearMirrors(cbs, offset, size);
_waitable?.AddBufferUse(cbs.CommandBufferIndex, offset, size, write);
return Get(cbs);
}

Expand Down

0 comments on commit 5974e86

Please sign in to comment.