GpuSceneArray.inl.h 4.0 KB

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