RenderStateBucket.cpp 2.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104
  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);
  14. }
  15. ANKI_ASSERT(m_bucketItemCount[t] == 0);
  16. }
  17. }
  18. RenderStateBucketIndex RenderStateBucketContainer::addUser(const RenderStateInfo& state, RenderingTechnique technique)
  19. {
  20. // Compute state gash
  21. Array<U64, 3> toHash;
  22. toHash[0] = state.m_program->getUuid();
  23. toHash[1] = U64(state.m_primitiveTopology);
  24. toHash[2] = state.m_indexedDrawcall;
  25. const U64 hash = computeHash(toHash.getBegin(), toHash.getSizeInBytes());
  26. SceneDynamicArray<ExtendedBucket>& buckets = m_buckets[technique];
  27. RenderStateBucketIndex out;
  28. out.m_technique = technique;
  29. LockGuard lock(m_mtx);
  30. ++m_bucketItemCount[technique];
  31. // Search bucket
  32. for(U32 i = 0; i < buckets.getSize(); ++i)
  33. {
  34. if(buckets[i].m_hash == hash)
  35. {
  36. ++buckets[i].m_userCount;
  37. if(buckets[i].m_userCount == 1)
  38. {
  39. ANKI_ASSERT(!buckets[i].m_program.isCreated());
  40. buckets[i].m_program = state.m_program;
  41. }
  42. else
  43. {
  44. ANKI_ASSERT(buckets[i].m_program.isCreated());
  45. }
  46. out.m_index = i;
  47. return out;
  48. }
  49. }
  50. // Bucket not found, create one
  51. ExtendedBucket& newBucket = *buckets.emplaceBack();
  52. newBucket.m_hash = hash;
  53. newBucket.m_indexedDrawcall = state.m_indexedDrawcall;
  54. newBucket.m_primitiveTopology = state.m_primitiveTopology;
  55. newBucket.m_program = state.m_program;
  56. newBucket.m_userCount = 1;
  57. out.m_index = buckets.getSize() - 1;
  58. return out;
  59. }
  60. void RenderStateBucketContainer::removeUser(RenderStateBucketIndex& bucketIndex)
  61. {
  62. if(!bucketIndex.isValid())
  63. {
  64. return;
  65. }
  66. {
  67. LockGuard lock(m_mtx);
  68. ANKI_ASSERT(bucketIndex.m_index < m_buckets[bucketIndex.m_technique].getSize());
  69. --m_bucketItemCount[bucketIndex.m_technique];
  70. ExtendedBucket& bucket = m_buckets[bucketIndex.m_technique][bucketIndex.m_index];
  71. ANKI_ASSERT(bucket.m_userCount > 0 && bucket.m_program.isCreated());
  72. --bucket.m_userCount;
  73. if(bucket.m_userCount == 0)
  74. {
  75. // No more users, make sure you release any references
  76. bucket.m_program.reset(nullptr);
  77. }
  78. }
  79. bucketIndex.invalidate();
  80. }
  81. } // end namespace anki