MicroFenceFactory.inl.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166
  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. #include <AnKi/Gr/BackendCommon/MicroFenceFactory.h>
  6. #include <AnKi/Core/StatsSet.h>
  7. namespace anki {
  8. ANKI_SVAR(FenceCount, StatCategory::kGr, "Fence count", StatFlag::kNone)
  9. template<typename TImplementation>
  10. MicroFenceFactory<TImplementation>::~MicroFenceFactory()
  11. {
  12. GrDynamicArray<U32> fenceIdxToDelete;
  13. for(U32 idx = m_markedForDeletionMask.getLeastSignificantBit(); idx < kMaxU32; idx = m_markedForDeletionMask.getLeastSignificantBit())
  14. {
  15. fenceIdxToDelete.emplaceBack(idx);
  16. m_markedForDeletionMask.unset(idx);
  17. }
  18. for(U32 idx : fenceIdxToDelete)
  19. {
  20. MyMicroFence& fence = m_fences[idx];
  21. if(fence.m_impl)
  22. {
  23. fence.m_impl.destroy();
  24. ANKI_ASSERT(m_aliveFenceCount > 0);
  25. --m_aliveFenceCount;
  26. g_svarFenceCount.decrement(1_U64);
  27. }
  28. m_fences.erase(idx);
  29. }
  30. ANKI_ASSERT(!m_markedForDeletionMask.getAnySet());
  31. ANKI_ASSERT(m_fences.getSize() == 0);
  32. ANKI_ASSERT(m_aliveFenceCount == 0);
  33. }
  34. template<typename TImplementation>
  35. MicroFenceFactory<TImplementation>::MyMicroFence* MicroFenceFactory<TImplementation>::newFence(CString name)
  36. {
  37. MyMicroFence* out = nullptr;
  38. LockGuard<Mutex> lock(m_mtx);
  39. // Trim fences if needed
  40. if(m_aliveFenceCount > kMaxAliveFences * 80 / 100)
  41. {
  42. GrDynamicArray<U32> toDelete;
  43. for(auto it = m_fences.getBegin(); it != m_fences.getEnd(); ++it)
  44. {
  45. LockGuard lock(it->m_lock);
  46. const Bool markedForDeletion = m_markedForDeletionMask.get(it.getArrayIndex());
  47. if(markedForDeletion)
  48. {
  49. toDelete.emplaceBack(it.getArrayIndex());
  50. }
  51. if(!it->m_impl)
  52. {
  53. continue;
  54. }
  55. // Marked for deletion or signaled will loose their fence
  56. Bool destroyFence = it->m_state == MyMicroFence::kSignaled;
  57. if(!destroyFence)
  58. {
  59. const Bool signaled = it->m_impl.signaled();
  60. destroyFence = signaled;
  61. if(signaled)
  62. {
  63. it->m_state = MyMicroFence::kSignaled;
  64. }
  65. }
  66. if(destroyFence)
  67. {
  68. if(it->m_impl)
  69. {
  70. it->m_impl.destroy();
  71. ANKI_ASSERT(m_aliveFenceCount > 0);
  72. --m_aliveFenceCount;
  73. g_svarFenceCount.decrement(1_U64);
  74. }
  75. }
  76. }
  77. for(U32 i = 0; i < toDelete.getSize(); ++i)
  78. {
  79. m_fences.erase(toDelete[i]);
  80. ANKI_ASSERT(m_markedForDeletionMask.get(toDelete[i]));
  81. m_markedForDeletionMask.unset(toDelete[i]);
  82. }
  83. }
  84. // Find to recycle
  85. const U32 idx = m_markedForDeletionMask.getLeastSignificantBit();
  86. if(idx != kMaxU32)
  87. {
  88. m_markedForDeletionMask.unset(idx);
  89. out = &m_fences[idx];
  90. }
  91. if(!out)
  92. {
  93. // Create new
  94. auto it = m_fences.emplace();
  95. out = &(*it);
  96. out->m_arrayIdx = U16(it.getArrayIndex());
  97. }
  98. if(!out->m_impl)
  99. {
  100. // Create new
  101. out->m_impl.create();
  102. g_svarFenceCount.increment(1_U64);
  103. ++m_aliveFenceCount;
  104. if(m_aliveFenceCount > kMaxAliveFences)
  105. {
  106. ANKI_GR_LOGW("Too many alive fences (%u). You may run out of file descriptors", m_aliveFenceCount);
  107. }
  108. }
  109. else
  110. {
  111. // Recycle
  112. if(!out->signaled())
  113. {
  114. ANKI_GR_LOGW("Fence marked for deletion but it's not signaled: %s", out->m_name.cstr());
  115. }
  116. out->m_impl.reset();
  117. }
  118. out->m_state = MyMicroFence::kUnsignaled;
  119. out->m_impl.setName(name);
  120. out->m_name = name;
  121. ANKI_ASSERT(out->m_refcount.getNonAtomically() == 0);
  122. return out;
  123. }
  124. template<typename TImplementation>
  125. void MicroFenceFactory<TImplementation>::releaseFence(MyMicroFence* fence)
  126. {
  127. LockGuard lock(m_mtx);
  128. ANKI_ASSERT(!m_markedForDeletionMask.get(fence->m_arrayIdx));
  129. m_markedForDeletionMask.set(fence->m_arrayIdx);
  130. if(!fence->signaled())
  131. {
  132. ANKI_GR_LOGW("Fence marked for deletion but it's not signaled: %s", fence->m_name.cstr());
  133. }
  134. }
  135. } // end namespace anki