MethodUniformBufferUpdate.cs 3.2 KB

12345678910111213141516171819202122232425262728293031323334353637383940414243444546474849505152535455565758596061626364656667686970717273747576777879808182838485868788
  1. using Ryujinx.Graphics.Gpu.Memory;
  2. using Ryujinx.Graphics.Gpu.State;
  3. using System;
  4. using System.Runtime.InteropServices;
  5. namespace Ryujinx.Graphics.Gpu.Engine
  6. {
  7. partial class Methods
  8. {
  9. // State associated with direct uniform buffer updates.
  10. // This state is used to attempt to batch together consecutive updates.
  11. private ulong _ubBeginCpuAddress = 0;
  12. private ulong _ubFollowUpAddress = 0;
  13. private ulong _ubByteCount = 0;
  14. /// <summary>
  15. /// Flushes any queued ubo updates.
  16. /// </summary>
  17. /// <param name="memoryManager">GPU memory manager where the uniform buffer is mapped</param>
  18. private void FlushUboDirty(MemoryManager memoryManager)
  19. {
  20. if (_ubFollowUpAddress != 0)
  21. {
  22. memoryManager.Physical.BufferCache.ForceDirty(memoryManager, _ubFollowUpAddress - _ubByteCount, _ubByteCount);
  23. _ubFollowUpAddress = 0;
  24. }
  25. }
  26. /// <summary>
  27. /// Updates the uniform buffer data with inline data.
  28. /// </summary>
  29. /// <param name="state">Current GPU state</param>
  30. /// <param name="argument">New uniform buffer data word</param>
  31. private void UniformBufferUpdate(GpuState state, int argument)
  32. {
  33. var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
  34. ulong address = uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset;
  35. if (_ubFollowUpAddress != address)
  36. {
  37. FlushUboDirty(state.Channel.MemoryManager);
  38. _ubByteCount = 0;
  39. _ubBeginCpuAddress = state.Channel.MemoryManager.Translate(address);
  40. }
  41. var byteData = MemoryMarshal.Cast<int, byte>(MemoryMarshal.CreateSpan(ref argument, 1));
  42. state.Channel.MemoryManager.Physical.WriteUntracked(_ubBeginCpuAddress + _ubByteCount, byteData);
  43. _ubFollowUpAddress = address + 4;
  44. _ubByteCount += 4;
  45. state.SetUniformBufferOffset(uniformBuffer.Offset + 4);
  46. }
  47. /// <summary>
  48. /// Updates the uniform buffer data with inline data.
  49. /// </summary>
  50. /// <param name="state">Current GPU state</param>
  51. /// <param name="data">Data to be written to the uniform buffer</param>
  52. public void UniformBufferUpdate(GpuState state, ReadOnlySpan<int> data)
  53. {
  54. var uniformBuffer = state.Get<UniformBufferState>(MethodOffset.UniformBufferState);
  55. ulong address = uniformBuffer.Address.Pack() + (uint)uniformBuffer.Offset;
  56. ulong size = (ulong)data.Length * 4;
  57. if (_ubFollowUpAddress != address)
  58. {
  59. FlushUboDirty(state.Channel.MemoryManager);
  60. _ubByteCount = 0;
  61. _ubBeginCpuAddress = state.Channel.MemoryManager.Translate(address);
  62. }
  63. var byteData = MemoryMarshal.Cast<int, byte>(data);
  64. state.Channel.MemoryManager.Physical.WriteUntracked(_ubBeginCpuAddress + _ubByteCount, byteData);
  65. _ubFollowUpAddress = address + size;
  66. _ubByteCount += size;
  67. state.SetUniformBufferOffset(uniformBuffer.Offset + data.Length * 4);
  68. }
  69. }
  70. }