aboutsummaryrefslogtreecommitdiff
path: root/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
diff options
context:
space:
mode:
Diffstat (limited to 'Ryujinx.Graphics.Gpu/Memory/Buffer.cs')
-rw-r--r--Ryujinx.Graphics.Gpu/Memory/Buffer.cs99
1 files changed, 99 insertions, 0 deletions
diff --git a/Ryujinx.Graphics.Gpu/Memory/Buffer.cs b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
new file mode 100644
index 00000000..30bd1ac0
--- /dev/null
+++ b/Ryujinx.Graphics.Gpu/Memory/Buffer.cs
@@ -0,0 +1,99 @@
+using Ryujinx.Graphics.GAL;
+using System;
+
+namespace Ryujinx.Graphics.Gpu.Memory
+{
+ class Buffer : IRange<Buffer>, IDisposable
+ {
+ private GpuContext _context;
+
+ private IBuffer _buffer;
+
+ public ulong Address { get; }
+ public ulong Size { get; }
+
+ public ulong EndAddress => Address + Size;
+
+ private int[] _sequenceNumbers;
+
+ public Buffer(GpuContext context, ulong address, ulong size)
+ {
+ _context = context;
+ Address = address;
+ Size = size;
+
+ _buffer = context.Renderer.CreateBuffer((int)size);
+
+ _sequenceNumbers = new int[size / MemoryManager.PageSize];
+
+ Invalidate();
+ }
+
+ public BufferRange GetRange(ulong address, ulong size)
+ {
+ int offset = (int)(address - Address);
+
+ return new BufferRange(_buffer, offset, (int)size);
+ }
+
+ public bool OverlapsWith(ulong address, ulong size)
+ {
+ return Address < address + size && address < EndAddress;
+ }
+
+ public void SynchronizeMemory(ulong address, ulong size)
+ {
+ int currentSequenceNumber = _context.SequenceNumber;
+
+ bool needsSync = false;
+
+ ulong buffOffset = address - Address;
+
+ ulong buffEndOffset = (buffOffset + size + MemoryManager.PageMask) & ~MemoryManager.PageMask;
+
+ int startIndex = (int)(buffOffset / MemoryManager.PageSize);
+ int endIndex = (int)(buffEndOffset / MemoryManager.PageSize);
+
+ for (int index = startIndex; index < endIndex; index++)
+ {
+ if (_sequenceNumbers[index] != currentSequenceNumber)
+ {
+ _sequenceNumbers[index] = currentSequenceNumber;
+
+ needsSync = true;
+ }
+ }
+
+ if (!needsSync)
+ {
+ return;
+ }
+
+ (ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size);
+
+ for (int index = 0; index < modifiedRanges.Length; index++)
+ {
+ (ulong mAddress, ulong mSize) = modifiedRanges[index];
+
+ int offset = (int)(mAddress - Address);
+
+ _buffer.SetData(offset, _context.PhysicalMemory.Read(mAddress, mSize));
+ }
+ }
+
+ public void CopyTo(Buffer destination, int dstOffset)
+ {
+ _buffer.CopyTo(destination._buffer, 0, dstOffset, (int)Size);
+ }
+
+ public void Invalidate()
+ {
+ _buffer.SetData(0, _context.PhysicalMemory.Read(Address, Size));
+ }
+
+ public void Dispose()
+ {
+ _buffer.Dispose();
+ }
+ }
+} \ No newline at end of file