RenderStateBucket.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182
  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. #pragma once
  6. #include <AnKi/Scene/Common.h>
  7. #include <AnKi/Resource/RenderingKey.h>
  8. #include <AnKi/Gr/ShaderProgram.h>
  9. namespace anki {
  10. /// @addtogroup scene
  11. /// @{
  12. /// This is the unique render state of a renderable object in the scene.
  13. class RenderStateInfo
  14. {
  15. public:
  16. ShaderProgramPtr m_program;
  17. PrimitiveTopology m_primitiveTopology = PrimitiveTopology::kTriangles;
  18. };
  19. class RenderStateBucketIndex
  20. {
  21. friend class RenderStateBucketContainer;
  22. public:
  23. RenderStateBucketIndex() = default;
  24. RenderStateBucketIndex(const RenderStateBucketIndex&) = delete;
  25. RenderStateBucketIndex(RenderStateBucketIndex&& b)
  26. {
  27. *this = std::move(b);
  28. }
  29. ~RenderStateBucketIndex();
  30. RenderStateBucketIndex& operator=(const RenderStateBucketIndex&) = delete;
  31. RenderStateBucketIndex& operator=(RenderStateBucketIndex&& b)
  32. {
  33. ANKI_ASSERT(!isValid() && "Forgot to delete");
  34. m_index = b.m_index;
  35. m_technique = b.m_technique;
  36. m_lod0MeshletCount = b.m_lod0MeshletCount;
  37. b.invalidate();
  38. return *this;
  39. }
  40. U32 get() const
  41. {
  42. ANKI_ASSERT(m_index != kMaxU32);
  43. return m_index;
  44. }
  45. Bool isValid() const
  46. {
  47. return m_index != kMaxU32;
  48. }
  49. private:
  50. U32 m_index = kMaxU32;
  51. U32 m_lod0MeshletCount = kMaxU32;
  52. RenderingTechnique m_technique = RenderingTechnique::kCount;
  53. void invalidate()
  54. {
  55. m_index = kMaxU32;
  56. m_lod0MeshletCount = kMaxU32;
  57. m_technique = RenderingTechnique::kCount;
  58. }
  59. };
  60. /// Holds an array of all render state buckets.
  61. /// It creates buckets at will. If a bucket looses all its users then it becomes inactive but still be part of the bucket list.
  62. class RenderStateBucketContainer : public MakeSingleton<RenderStateBucketContainer>
  63. {
  64. template<typename>
  65. friend class MakeSingleton;
  66. public:
  67. /// Add a new user for a specific render state and rendering technique.
  68. /// @note It's thread-safe against addUser and removeUser
  69. RenderStateBucketIndex addUser(const RenderStateInfo& state, RenderingTechnique technique, U32 lod0MeshletCount);
  70. /// Remove the user.
  71. /// @note It's thread-safe against addUser and removeUser
  72. void removeUser(RenderStateBucketIndex& bucketIndex);
  73. /// Iterate empty and non-empty buckets.
  74. template<typename TFunc>
  75. void iterateBuckets(RenderingTechnique technique, TFunc func) const
  76. {
  77. for(const ExtendedBucket& b : m_buckets[technique])
  78. {
  79. func(static_cast<const RenderStateInfo&>(b), b.m_userCount, b.m_lod0MeshletCount);
  80. }
  81. }
  82. /// Iterate empty and non-empty buckets from the bucket that has the least heavy shader program to the one with the heavy.
  83. template<typename TFunc>
  84. void iterateBucketsPerformanceOrder(RenderingTechnique technique, TFunc func) const
  85. {
  86. for(U32 i : m_bucketPerfOrder[technique])
  87. {
  88. const ExtendedBucket& b = m_buckets[technique][i];
  89. func(static_cast<const RenderStateInfo&>(b), i, b.m_userCount, b.m_lod0MeshletCount);
  90. }
  91. }
  92. /// Get the number of renderables of all the buckets of a specific rendering technique.
  93. U32 getBucketsActiveUserCount(RenderingTechnique technique) const
  94. {
  95. return m_bucketActiveUserCount[technique];
  96. }
  97. /// Get the number of renderables of all the buckets that support meshlets.
  98. U32 getBucketsActiveUserCountWithMeshletSupport(RenderingTechnique technique) const
  99. {
  100. return m_bucketActiveUserCountWithMeshlets[technique];
  101. }
  102. /// Get the number of renderables of all the buckets that support meshlets.
  103. U32 getBucketsActiveUserCountWithNoMeshletSupport(RenderingTechnique technique) const
  104. {
  105. ANKI_ASSERT(m_bucketActiveUserCount[technique] >= m_bucketActiveUserCountWithMeshlets[technique]);
  106. return m_bucketActiveUserCount[technique] - m_bucketActiveUserCountWithMeshlets[technique];
  107. }
  108. /// Get the number of meshlets of a technique of LOD 0.
  109. U32 getBucketsLod0MeshletCount(RenderingTechnique technique) const
  110. {
  111. return m_lod0MeshletCount[technique];
  112. }
  113. /// Get number of empty and non-empty buckets.
  114. U32 getBucketCount(RenderingTechnique technique) const
  115. {
  116. return m_buckets[technique].getSize();
  117. }
  118. /// Get number of non-empty buckets.
  119. U32 getActiveBucketCount(RenderingTechnique technique) const
  120. {
  121. return m_activeBucketCount[technique];
  122. }
  123. private:
  124. class ExtendedBucket : public RenderStateInfo
  125. {
  126. public:
  127. U64 m_hash = 0;
  128. U32 m_userCount = 0;
  129. U32 m_lod0MeshletCount = 0;
  130. };
  131. Array<SceneDynamicArray<ExtendedBucket>, U32(RenderingTechnique::kCount)> m_buckets;
  132. Array<U32, U32(RenderingTechnique::kCount)> m_bucketActiveUserCount = {};
  133. Array<U32, U32(RenderingTechnique::kCount)> m_bucketActiveUserCountWithMeshlets = {};
  134. Array<U32, U32(RenderingTechnique::kCount)> m_lod0MeshletCount = {};
  135. Array<U32, U32(RenderingTechnique::kCount)> m_activeBucketCount = {};
  136. Array<SceneDynamicArray<U32>, U32(RenderingTechnique::kCount)> m_bucketPerfOrder; ///< Orders the buckets from the least heavy to the most.
  137. Mutex m_mtx;
  138. RenderStateBucketContainer() = default;
  139. ~RenderStateBucketContainer();
  140. void createPerfOrder(RenderingTechnique t);
  141. };
  142. inline RenderStateBucketIndex::~RenderStateBucketIndex()
  143. {
  144. RenderStateBucketContainer::getSingleton().removeUser(*this);
  145. }
  146. /// @}
  147. } // end namespace anki