GpuSceneArray.inl.h 4.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161
  1. // Copyright (C) 2009-2023, 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/Scene/GpuSceneArray.h>
  6. #include <AnKi/Scene/SceneGraph.h>
  7. #include <AnKi/Gr/GrManager.h>
  8. namespace anki {
  9. template<typename TGpuSceneObject, U32 kId>
  10. GpuSceneArray<TGpuSceneObject, kId>::GpuSceneArray(U32 maxArraySize)
  11. {
  12. maxArraySize = getAlignedRoundUp(sizeof(SubMask), maxArraySize);
  13. const U32 alignment = GrManager::getSingleton().getDeviceCapabilities().m_uavBufferBindOffsetAlignment;
  14. m_gpuSceneAllocation = GpuSceneBuffer::getSingleton().allocate(sizeof(TGpuSceneObject) * maxArraySize, alignment);
  15. m_inUseIndicesMask.resize(maxArraySize / sizeof(SubMask), false);
  16. ANKI_ASSERT(m_inUseIndicesCount == 0);
  17. m_maxInUseIndex = 0;
  18. }
  19. template<typename TGpuSceneObject, U32 kId>
  20. GpuSceneArray<TGpuSceneObject, kId>::~GpuSceneArray()
  21. {
  22. flushInternal(false);
  23. validate();
  24. ANKI_ASSERT(m_inUseIndicesCount == 0 && "Forgot to free");
  25. }
  26. template<typename TGpuSceneObject, U32 kId>
  27. GpuSceneArrayAllocation<TGpuSceneObject, kId> GpuSceneArray<TGpuSceneObject, kId>::allocate()
  28. {
  29. LockGuard lock(m_mtx);
  30. U32 idx = kMaxU32;
  31. if(m_freedAllocations.getSize())
  32. {
  33. // There are freed indices this frame, use one
  34. idx = m_freedAllocations[0];
  35. m_freedAllocations.erase(m_freedAllocations.getBegin());
  36. }
  37. else
  38. {
  39. // No freed indices this frame, get a new one
  40. for(U32 maskGroup = 0; maskGroup < m_inUseIndicesMask.getSize(); ++maskGroup)
  41. {
  42. SubMask submask = m_inUseIndicesMask[maskGroup];
  43. submask = ~submask;
  44. const U32 bit = submask.getLeastSignificantBit();
  45. if(bit != kMaxU32)
  46. {
  47. // Found an index
  48. idx = maskGroup * 64 + bit;
  49. break;
  50. }
  51. }
  52. }
  53. if(idx == kMaxU32)
  54. {
  55. ANKI_SCENE_LOGF("Reached the limit of GPU scene objects");
  56. }
  57. ANKI_ASSERT(idx < m_inUseIndicesMask.getSize() * 64);
  58. ANKI_ASSERT(m_inUseIndicesMask[idx / 64].get(idx % 64) == false);
  59. m_inUseIndicesMask[idx / 64].set(idx % 64);
  60. m_maxInUseIndex = max(m_maxInUseIndex, idx);
  61. ++m_inUseIndicesCount;
  62. Allocation out;
  63. out.m_index = idx;
  64. return out;
  65. }
  66. template<typename TGpuSceneObject, U32 kId>
  67. void GpuSceneArray<TGpuSceneObject, kId>::free(Allocation& alloc)
  68. {
  69. if(!alloc.isValid()) [[unlikely]]
  70. {
  71. return;
  72. }
  73. const U32 idx = alloc.m_index;
  74. alloc.invalidate();
  75. LockGuard lock(m_mtx);
  76. m_freedAllocations.emplaceBack(idx);
  77. ANKI_ASSERT(m_inUseIndicesMask[idx / 64].get(idx % 64) == true);
  78. m_inUseIndicesMask[idx / 64].unset(idx % 64);
  79. ANKI_ASSERT(m_inUseIndicesCount > 0);
  80. --m_inUseIndicesCount;
  81. // Sort because allocations later on should preferably grab the lowest index possible
  82. std::sort(m_freedAllocations.getBegin(), m_freedAllocations.getEnd());
  83. }
  84. template<typename TGpuSceneObject, U32 kId>
  85. void GpuSceneArray<TGpuSceneObject, kId>::flushInternal(Bool nullifyElements)
  86. {
  87. LockGuard lock(m_mtx);
  88. if(m_freedAllocations.getSize())
  89. {
  90. // Nullify the deleted elements
  91. if(nullifyElements)
  92. {
  93. TGpuSceneObject nullObj = {};
  94. for(U32 idx : m_freedAllocations)
  95. {
  96. const PtrSize offset = idx * sizeof(TGpuSceneObject) + m_gpuSceneAllocation.getOffset();
  97. GpuSceneMicroPatcher::getSingleton().newCopy(SceneGraph::getSingleton().getFrameMemoryPool(), offset, nullObj);
  98. }
  99. }
  100. // Update the the last index
  101. U32 maskGroup = m_maxInUseIndex / 64 + 1;
  102. m_maxInUseIndex = 0;
  103. while(maskGroup--)
  104. {
  105. const U32 bit = m_inUseIndicesMask[maskGroup].getMostSignificantBit();
  106. if(bit != kMaxU32)
  107. {
  108. m_maxInUseIndex = maskGroup * 64 + bit;
  109. break;
  110. }
  111. }
  112. m_freedAllocations.destroy();
  113. }
  114. validate();
  115. }
  116. template<typename TGpuSceneObject, U32 kId>
  117. void GpuSceneArray<TGpuSceneObject, kId>::validate() const
  118. {
  119. #if ANKI_ASSERTIONS_ENABLED
  120. U32 count = 0;
  121. U32 maxIdx = 0;
  122. U32 maskGroupCount = 0;
  123. for(const SubMask& mask : m_inUseIndicesMask)
  124. {
  125. count += mask.getSetBitCount();
  126. maxIdx = max(maxIdx, (mask.getMostSignificantBit() != kMaxU32) ? (mask.getMostSignificantBit() + maskGroupCount * 64) : 0);
  127. ++maskGroupCount;
  128. }
  129. ANKI_ASSERT(count == m_inUseIndicesCount);
  130. ANKI_ASSERT(maxIdx == m_maxInUseIndex);
  131. #endif
  132. }
  133. } // end namespace anki