FrameGarbageCollector.cpp 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156
  1. // Copyright (C) 2009-2022, 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/Vulkan/FrameGarbageCollector.h>
  6. #include <AnKi/Gr/Vulkan/GrManagerImpl.h>
  7. #include <AnKi/Gr/Fence.h>
  8. namespace anki {
  9. FrameGarbageCollector::~FrameGarbageCollector()
  10. {
  11. destroy();
  12. }
  13. void FrameGarbageCollector::collectGarbage()
  14. {
  15. if(ANKI_LIKELY(m_frames.isEmpty()))
  16. {
  17. return;
  18. }
  19. const VkDevice dev = m_gr->getDevice();
  20. GrAllocator<U8> alloc = m_gr->getAllocator();
  21. IntrusiveList<FrameGarbage> newFrames;
  22. while(!m_frames.isEmpty())
  23. {
  24. FrameGarbage& frame = *m_frames.popFront();
  25. if(frame.m_fence.isCreated() && !frame.m_fence->done())
  26. {
  27. ANKI_ASSERT(!frame.m_textureGarbage.isEmpty() || !frame.m_bufferGarbage.isEmpty());
  28. newFrames.pushBack(&frame);
  29. continue;
  30. }
  31. // Frame is done, dispose garbage and destroy it
  32. // Dispose texture garbage
  33. while(!frame.m_textureGarbage.isEmpty())
  34. {
  35. TextureGarbage* textureGarbage = frame.m_textureGarbage.popBack();
  36. for(VkImageView viewHandle : textureGarbage->m_viewHandles)
  37. {
  38. vkDestroyImageView(dev, viewHandle, nullptr);
  39. }
  40. textureGarbage->m_viewHandles.destroy(alloc);
  41. for(U32 bindlessIndex : textureGarbage->m_bindlessIndices)
  42. {
  43. m_gr->getDescriptorSetFactory().unbindBindlessTexture(bindlessIndex);
  44. }
  45. textureGarbage->m_bindlessIndices.destroy(alloc);
  46. if(textureGarbage->m_imageHandle)
  47. {
  48. vkDestroyImage(dev, textureGarbage->m_imageHandle, nullptr);
  49. }
  50. if(textureGarbage->m_memoryHandle)
  51. {
  52. m_gr->getGpuMemoryManager().freeMemory(textureGarbage->m_memoryHandle);
  53. }
  54. alloc.deleteInstance(textureGarbage);
  55. }
  56. // Dispose buffer garbage
  57. while(!frame.m_bufferGarbage.isEmpty())
  58. {
  59. BufferGarbage* bufferGarbage = frame.m_bufferGarbage.popBack();
  60. if(bufferGarbage->m_bufferHandle)
  61. {
  62. vkDestroyBuffer(dev, bufferGarbage->m_bufferHandle, nullptr);
  63. }
  64. if(bufferGarbage->m_memoryHandle)
  65. {
  66. m_gr->getGpuMemoryManager().freeMemory(bufferGarbage->m_memoryHandle);
  67. }
  68. alloc.deleteInstance(bufferGarbage);
  69. }
  70. alloc.deleteInstance(&frame);
  71. }
  72. m_frames = std::move(newFrames);
  73. }
  74. FrameGarbageCollector::FrameGarbage& FrameGarbageCollector::getFrame()
  75. {
  76. if(!m_frames.isEmpty() && !m_frames.getBack().m_fence.isCreated())
  77. {
  78. // Do nothing
  79. }
  80. else
  81. {
  82. FrameGarbage* newGarbage = m_gr->getAllocator().newInstance<FrameGarbage>();
  83. m_frames.pushBack(newGarbage);
  84. }
  85. return m_frames.getBack();
  86. }
  87. void FrameGarbageCollector::setNewFrame(MicroFencePtr frameFence)
  88. {
  89. ANKI_ASSERT(frameFence.isCreated());
  90. LockGuard<Mutex> lock(m_mtx);
  91. ANKI_ASSERT(m_initialized);
  92. if(!m_frames.isEmpty() && !m_frames.getBack().m_fence.isCreated())
  93. {
  94. // Last frame is without a fence, asign the fence to not not have it garbage collected
  95. m_frames.getBack().m_fence = frameFence;
  96. }
  97. collectGarbage();
  98. }
  99. void FrameGarbageCollector::newTextureGarbage(TextureGarbage* textureGarbage)
  100. {
  101. ANKI_ASSERT(textureGarbage);
  102. LockGuard<Mutex> lock(m_mtx);
  103. ANKI_ASSERT(m_initialized);
  104. FrameGarbage& frame = getFrame();
  105. frame.m_textureGarbage.pushBack(textureGarbage);
  106. }
  107. void FrameGarbageCollector::newBufferGarbage(BufferGarbage* bufferGarbage)
  108. {
  109. ANKI_ASSERT(bufferGarbage);
  110. LockGuard<Mutex> lock(m_mtx);
  111. ANKI_ASSERT(m_initialized);
  112. FrameGarbage& frame = getFrame();
  113. frame.m_bufferGarbage.pushBack(bufferGarbage);
  114. }
  115. void FrameGarbageCollector::destroy()
  116. {
  117. LockGuard<Mutex> lock(m_mtx);
  118. collectGarbage();
  119. ANKI_ASSERT(m_frames.isEmpty());
  120. #if ANKI_EXTRA_CHECKS
  121. m_initialized = false;
  122. #endif
  123. }
  124. } // end namespace anki