AutoFlushCounter.cs 2.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105
  1. using System;
  2. using System.Diagnostics;
  3. using System.Linq;
  4. namespace Ryujinx.Graphics.Vulkan
  5. {
  6. internal class AutoFlushCounter
  7. {
  8. // How often to flush on framebuffer change.
  9. private readonly static long FramebufferFlushTimer = Stopwatch.Frequency / 1000;
  10. private const int MinDrawCountForFlush = 10;
  11. private const int InitialQueryCountForFlush = 32;
  12. private long _lastFlush;
  13. private ulong _lastDrawCount;
  14. private bool _hasPendingQuery;
  15. private int _queryCount;
  16. private int[] _queryCountHistory = new int[3];
  17. private int _queryCountHistoryIndex;
  18. private int _remainingQueries;
  19. public void RegisterFlush(ulong drawCount)
  20. {
  21. _lastFlush = Stopwatch.GetTimestamp();
  22. _lastDrawCount = drawCount;
  23. _hasPendingQuery = false;
  24. }
  25. public bool RegisterPendingQuery()
  26. {
  27. _hasPendingQuery = true;
  28. _remainingQueries--;
  29. _queryCountHistory[_queryCountHistoryIndex]++;
  30. // Interrupt render passes to flush queries, so that early results arrive sooner.
  31. if (++_queryCount == InitialQueryCountForFlush)
  32. {
  33. return true;
  34. }
  35. return false;
  36. }
  37. public int GetRemainingQueries()
  38. {
  39. if (_remainingQueries <= 0)
  40. {
  41. _remainingQueries = 16;
  42. }
  43. if (_queryCount < InitialQueryCountForFlush)
  44. {
  45. return Math.Min(InitialQueryCountForFlush - _queryCount, _remainingQueries);
  46. }
  47. return _remainingQueries;
  48. }
  49. public bool ShouldFlushQuery()
  50. {
  51. return _hasPendingQuery;
  52. }
  53. public bool ShouldFlush(ulong drawCount)
  54. {
  55. _queryCount = 0;
  56. if (_hasPendingQuery)
  57. {
  58. return true;
  59. }
  60. long draws = (long)(drawCount - _lastDrawCount);
  61. if (draws < MinDrawCountForFlush)
  62. {
  63. if (draws == 0)
  64. {
  65. _lastFlush = Stopwatch.GetTimestamp();
  66. }
  67. return false;
  68. }
  69. long flushTimeout = FramebufferFlushTimer;
  70. long now = Stopwatch.GetTimestamp();
  71. return now > _lastFlush + flushTimeout;
  72. }
  73. public void Present()
  74. {
  75. _queryCountHistoryIndex = (_queryCountHistoryIndex + 1) % 3;
  76. _remainingQueries = _queryCountHistory.Max() + 10;
  77. _queryCountHistory[_queryCountHistoryIndex] = 0;
  78. }
  79. }
  80. }