RenderStateBucket.cpp 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135
  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/RenderStateBucket.h>
  6. namespace anki {
  7. RenderStateBucketContainer::~RenderStateBucketContainer()
  8. {
  9. for(RenderingTechnique t : EnumIterable<RenderingTechnique>())
  10. {
  11. for([[maybe_unused]] ExtendedBucket& b : m_buckets[t])
  12. {
  13. ANKI_ASSERT(!b.m_program.isCreated() && b.m_userCount == 0 && b.m_meshletGroupCount == 0);
  14. }
  15. ANKI_ASSERT(m_bucketUserCount[t] == 0);
  16. ANKI_ASSERT(m_activeBucketCount[t] == 0);
  17. ANKI_ASSERT(m_meshletGroupCount[t] == 0);
  18. }
  19. }
  20. RenderStateBucketIndex RenderStateBucketContainer::addUser(const RenderStateInfo& state, RenderingTechnique technique, U32 lod0MeshletCount)
  21. {
  22. if(!!(state.m_program->getShaderTypes() & ShaderTypeBit::kAllModernGeometry))
  23. {
  24. ANKI_ASSERT(lod0MeshletCount > 0);
  25. }
  26. else
  27. {
  28. ANKI_ASSERT(lod0MeshletCount == 0);
  29. }
  30. // Compute state gash
  31. Array<U64, 3> toHash;
  32. toHash[0] = state.m_program->getUuid();
  33. toHash[1] = U64(state.m_primitiveTopology);
  34. toHash[2] = state.m_indexedDrawcall;
  35. const U64 hash = computeHash(toHash.getBegin(), toHash.getSizeInBytes());
  36. const U32 meshletGroupCount = lod0MeshletCount + (kMaxMeshletsPerTaskShaderPayload - 1) / kMaxMeshletsPerTaskShaderPayload;
  37. SceneDynamicArray<ExtendedBucket>& buckets = m_buckets[technique];
  38. RenderStateBucketIndex out;
  39. out.m_technique = technique;
  40. LockGuard lock(m_mtx);
  41. ++m_bucketUserCount[technique];
  42. m_meshletGroupCount[technique] += meshletGroupCount;
  43. // Search bucket
  44. for(U32 i = 0; i < buckets.getSize(); ++i)
  45. {
  46. if(buckets[i].m_hash == hash)
  47. {
  48. ++buckets[i].m_userCount;
  49. buckets[i].m_meshletGroupCount += meshletGroupCount;
  50. if(buckets[i].m_userCount == 1)
  51. {
  52. ANKI_ASSERT(!buckets[i].m_program.isCreated());
  53. ANKI_ASSERT(buckets[i].m_meshletGroupCount == meshletGroupCount);
  54. buckets[i].m_program = state.m_program;
  55. ++m_activeBucketCount[technique];
  56. }
  57. else
  58. {
  59. ANKI_ASSERT(buckets[i].m_program.isCreated());
  60. }
  61. out.m_index = i;
  62. out.m_lod0MeshletCount = lod0MeshletCount;
  63. return out;
  64. }
  65. }
  66. // Bucket not found, create one
  67. ExtendedBucket& newBucket = *buckets.emplaceBack();
  68. newBucket.m_hash = hash;
  69. newBucket.m_indexedDrawcall = state.m_indexedDrawcall;
  70. newBucket.m_primitiveTopology = state.m_primitiveTopology;
  71. newBucket.m_program = state.m_program;
  72. newBucket.m_userCount = 1;
  73. newBucket.m_meshletGroupCount = meshletGroupCount;
  74. ++m_activeBucketCount[technique];
  75. out.m_index = buckets.getSize() - 1;
  76. out.m_lod0MeshletCount = lod0MeshletCount;
  77. return out;
  78. }
  79. void RenderStateBucketContainer::removeUser(RenderStateBucketIndex& bucketIndex)
  80. {
  81. if(!bucketIndex.isValid())
  82. {
  83. return;
  84. }
  85. const RenderingTechnique technique = bucketIndex.m_technique;
  86. const U32 idx = bucketIndex.m_index;
  87. const U32 meshletGroupCount = bucketIndex.m_lod0MeshletCount + (kMaxMeshletsPerTaskShaderPayload - 1) / kMaxMeshletsPerTaskShaderPayload;
  88. bucketIndex.invalidate();
  89. LockGuard lock(m_mtx);
  90. ANKI_ASSERT(idx < m_buckets[technique].getSize());
  91. ANKI_ASSERT(m_bucketUserCount[technique] > 0);
  92. --m_bucketUserCount[technique];
  93. ANKI_ASSERT(m_meshletGroupCount[technique] >= meshletGroupCount);
  94. m_meshletGroupCount[technique] -= meshletGroupCount;
  95. ExtendedBucket& bucket = m_buckets[technique][idx];
  96. ANKI_ASSERT(bucket.m_userCount > 0 && bucket.m_program.isCreated() && bucket.m_meshletGroupCount >= meshletGroupCount);
  97. --bucket.m_userCount;
  98. bucket.m_meshletGroupCount -= meshletGroupCount;
  99. if(bucket.m_userCount == 0)
  100. {
  101. // No more users, make sure you release any references
  102. bucket.m_program.reset(nullptr);
  103. ANKI_ASSERT(m_activeBucketCount[technique] > 0);
  104. --m_activeBucketCount[technique];
  105. }
  106. }
  107. } // end namespace anki