AutoFlushCounter.cs 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112
  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 MinConsecutiveQueryForFlush = 10;
  12. private const int InitialQueryCountForFlush = 32;
  13. private long _lastFlush;
  14. private ulong _lastDrawCount;
  15. private bool _hasPendingQuery;
  16. private int _consecutiveQueries;
  17. private int _queryCount;
  18. private int[] _queryCountHistory = new int[3];
  19. private int _queryCountHistoryIndex;
  20. private int _remainingQueries;
  21. public void RegisterFlush(ulong drawCount)
  22. {
  23. _lastFlush = Stopwatch.GetTimestamp();
  24. _lastDrawCount = drawCount;
  25. _hasPendingQuery = false;
  26. _consecutiveQueries = 0;
  27. }
  28. public bool RegisterPendingQuery()
  29. {
  30. _hasPendingQuery = true;
  31. _consecutiveQueries++;
  32. _remainingQueries--;
  33. _queryCountHistory[_queryCountHistoryIndex]++;
  34. // Interrupt render passes to flush queries, so that early results arrive sooner.
  35. if (++_queryCount == InitialQueryCountForFlush)
  36. {
  37. return true;
  38. }
  39. return false;
  40. }
  41. public int GetRemainingQueries()
  42. {
  43. if (_remainingQueries <= 0)
  44. {
  45. _remainingQueries = 16;
  46. }
  47. if (_queryCount < InitialQueryCountForFlush)
  48. {
  49. return Math.Min(InitialQueryCountForFlush - _queryCount, _remainingQueries);
  50. }
  51. return _remainingQueries;
  52. }
  53. public bool ShouldFlushQuery()
  54. {
  55. return _hasPendingQuery;
  56. }
  57. public bool ShouldFlushAttachmentChange(ulong drawCount)
  58. {
  59. _queryCount = 0;
  60. // Flush when there's an attachment change out of a large block of queries.
  61. if (_consecutiveQueries > MinConsecutiveQueryForFlush)
  62. {
  63. return true;
  64. }
  65. _consecutiveQueries = 0;
  66. long draws = (long)(drawCount - _lastDrawCount);
  67. if (draws < MinDrawCountForFlush)
  68. {
  69. if (draws == 0)
  70. {
  71. _lastFlush = Stopwatch.GetTimestamp();
  72. }
  73. return false;
  74. }
  75. long flushTimeout = FramebufferFlushTimer;
  76. long now = Stopwatch.GetTimestamp();
  77. return now > _lastFlush + flushTimeout;
  78. }
  79. public void Present()
  80. {
  81. _queryCountHistoryIndex = (_queryCountHistoryIndex + 1) % 3;
  82. _remainingQueries = _queryCountHistory.Max() + 10;
  83. _queryCountHistory[_queryCountHistoryIndex] = 0;
  84. }
  85. }
  86. }