Buffer.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110
  1. using Ryujinx.Graphics.GAL;
  2. using System;
  3. namespace Ryujinx.Graphics.Gpu.Memory
  4. {
  5. class Buffer : IRange<Buffer>, IDisposable
  6. {
  7. private GpuContext _context;
  8. private IBuffer _buffer;
  9. public IBuffer HostBuffer => _buffer;
  10. public ulong Address { get; }
  11. public ulong Size { get; }
  12. public ulong EndAddress => Address + Size;
  13. private int[] _sequenceNumbers;
  14. public Buffer(GpuContext context, ulong address, ulong size)
  15. {
  16. _context = context;
  17. Address = address;
  18. Size = size;
  19. _buffer = context.Renderer.CreateBuffer((int)size);
  20. _sequenceNumbers = new int[size / MemoryManager.PageSize];
  21. Invalidate();
  22. }
  23. public BufferRange GetRange(ulong address, ulong size)
  24. {
  25. int offset = (int)(address - Address);
  26. return new BufferRange(_buffer, offset, (int)size);
  27. }
  28. public bool OverlapsWith(ulong address, ulong size)
  29. {
  30. return Address < address + size && address < EndAddress;
  31. }
  32. public void SynchronizeMemory(ulong address, ulong size)
  33. {
  34. int currentSequenceNumber = _context.SequenceNumber;
  35. bool needsSync = false;
  36. ulong buffOffset = address - Address;
  37. ulong buffEndOffset = (buffOffset + size + MemoryManager.PageMask) & ~MemoryManager.PageMask;
  38. int startIndex = (int)(buffOffset / MemoryManager.PageSize);
  39. int endIndex = (int)(buffEndOffset / MemoryManager.PageSize);
  40. for (int index = startIndex; index < endIndex; index++)
  41. {
  42. if (_sequenceNumbers[index] != currentSequenceNumber)
  43. {
  44. _sequenceNumbers[index] = currentSequenceNumber;
  45. needsSync = true;
  46. }
  47. }
  48. if (!needsSync)
  49. {
  50. return;
  51. }
  52. (ulong, ulong)[] modifiedRanges = _context.PhysicalMemory.GetModifiedRanges(address, size, ResourceName.Buffer);
  53. for (int index = 0; index < modifiedRanges.Length; index++)
  54. {
  55. (ulong mAddress, ulong mSize) = modifiedRanges[index];
  56. int offset = (int)(mAddress - Address);
  57. _buffer.SetData(offset, _context.PhysicalMemory.Read(mAddress, mSize));
  58. }
  59. }
  60. public void CopyTo(Buffer destination, int dstOffset)
  61. {
  62. _buffer.CopyTo(destination._buffer, 0, dstOffset, (int)Size);
  63. }
  64. public void Flush(ulong address, ulong size)
  65. {
  66. int offset = (int)(address - Address);
  67. byte[] data = _buffer.GetData(offset, (int)size);
  68. _context.PhysicalMemory.Write(address, data);
  69. }
  70. public void Invalidate()
  71. {
  72. _buffer.SetData(0, _context.PhysicalMemory.Read(Address, Size));
  73. }
  74. public void Dispose()
  75. {
  76. _buffer.Dispose();
  77. }
  78. }
  79. }