MicroFenceFactory.h 2.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153
  1. // Copyright (C) 2009-present, Panagiotis Christopoulos Charitos and contributors.
  2. // All rights reserved.
  3. // Code licensed under the BSD License.
  4. // http://www.anki3d.org/LICENSE
  5. #pragma once
  6. #include <AnKi/Gr/BackendCommon/Common.h>
  7. #include <AnKi/Util/BlockArray.h>
  8. namespace anki {
  9. /// @addtogroup graphics
  10. /// @{
  11. template<typename TImplementation>
  12. class MicroFence
  13. {
  14. public:
  15. template<typename>
  16. friend class MicroFenceFactory;
  17. public:
  18. MicroFence() = default;
  19. MicroFence(const MicroFence&) = delete; // Non-copyable
  20. MicroFence& operator=(const MicroFence&) = delete; // Non-copyable
  21. const TImplementation& getImplementation() const
  22. {
  23. LockGuard lock(m_lock);
  24. ANKI_ASSERT(m_state == kUnsignaled);
  25. return m_impl;
  26. }
  27. TImplementation& getImplementation()
  28. {
  29. LockGuard lock(m_lock);
  30. ANKI_ASSERT(m_state == kUnsignaled);
  31. return m_impl;
  32. }
  33. void retain() const
  34. {
  35. m_refcount.fetchAdd(1);
  36. }
  37. I32 release() const
  38. {
  39. return m_refcount.fetchSub(1);
  40. }
  41. Bool clientWait(Second seconds)
  42. {
  43. LockGuard lock(m_lock);
  44. Bool bSignaled;
  45. if(m_state == kSignaled)
  46. {
  47. bSignaled = true;
  48. }
  49. else if(seconds == 0.0)
  50. {
  51. bSignaled = m_impl.signaled();
  52. }
  53. else
  54. {
  55. // Not signaled and has handle
  56. seconds = min<Second>(seconds, g_cvarGrGpuTimeout);
  57. bSignaled = m_impl.clientWait(seconds);
  58. }
  59. if(bSignaled)
  60. {
  61. m_state = kSignaled;
  62. }
  63. return bSignaled;
  64. }
  65. Bool signaled()
  66. {
  67. LockGuard lock(m_lock);
  68. Bool bSignaled;
  69. if(m_state == kSignaled)
  70. {
  71. bSignaled = true;
  72. }
  73. else
  74. {
  75. bSignaled = m_impl.signaled();
  76. if(bSignaled)
  77. {
  78. m_state = kSignaled;
  79. }
  80. }
  81. return bSignaled;
  82. }
  83. CString getName() const
  84. {
  85. return m_name;
  86. }
  87. private:
  88. enum State : U8
  89. {
  90. kUnsignaled,
  91. kSignaled
  92. };
  93. TImplementation m_impl;
  94. mutable Atomic<I32> m_refcount = {0};
  95. mutable SpinLock m_lock;
  96. U16 m_arrayIdx = kMaxU16;
  97. State m_state = kUnsignaled;
  98. GrString m_name;
  99. };
  100. /// A factory of fences. It's designed to minimize the number of alive GFX API fences. If creating many VkFences on Linux the application may run out
  101. /// of file descriptors.
  102. template<typename TImplementation>
  103. class MicroFenceFactory
  104. {
  105. public:
  106. using MyMicroFence = MicroFence<TImplementation>;
  107. /// Limit the alive fences to avoid having too many file descriptors used in Linux.
  108. static constexpr U32 kMaxAliveFences = 32;
  109. MicroFenceFactory() = default;
  110. ~MicroFenceFactory();
  111. /// Create a new fence pointer.
  112. MyMicroFence* newFence(CString name = "unnamed");
  113. void releaseFence(MyMicroFence* fence);
  114. private:
  115. GrBlockArray<MyMicroFence> m_fences;
  116. U32 m_aliveFenceCount = 0;
  117. Mutex m_mtx;
  118. BitSet<1024, U64> m_markedForDeletionMask = {false}; // Always last for better caching
  119. };
  120. /// @}
  121. } // end namespace anki
  122. #include <AnKi/Gr/BackendCommon/MicroFenceFactory.inl.h>