RenderStateBucket.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136
  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. #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. Bool m_indexedDrawcall = true;
  19. };
  20. class RenderStateBucketIndex
  21. {
  22. friend class RenderStateBucketContainer;
  23. public:
  24. RenderStateBucketIndex() = default;
  25. RenderStateBucketIndex(const RenderStateBucketIndex&) = delete;
  26. RenderStateBucketIndex(RenderStateBucketIndex&& b)
  27. {
  28. *this = std::move(b);
  29. }
  30. ~RenderStateBucketIndex();
  31. RenderStateBucketIndex& operator=(const RenderStateBucketIndex&) = delete;
  32. RenderStateBucketIndex& operator=(RenderStateBucketIndex&& b)
  33. {
  34. ANKI_ASSERT(!isValid() && "Forgot to delete");
  35. m_index = b.m_index;
  36. m_technique = b.m_technique;
  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. RenderingTechnique m_technique = RenderingTechnique::kCount;
  52. void invalidate()
  53. {
  54. m_index = kMaxU32;
  55. m_technique = RenderingTechnique::kCount;
  56. }
  57. };
  58. /// Holds an array of all render state buckets.
  59. class RenderStateBucketContainer : public MakeSingleton<RenderStateBucketContainer>
  60. {
  61. template<typename>
  62. friend class MakeSingleton;
  63. public:
  64. /// Add a new user for a specific render state and rendering technique.
  65. /// @note It's thread-safe against addUser and removeUser
  66. RenderStateBucketIndex addUser(const RenderStateInfo& state, RenderingTechnique technique);
  67. /// Remove the user.
  68. /// @note It's thread-safe against addUser and removeUser
  69. void removeUser(RenderStateBucketIndex& bucketIndex);
  70. template<typename TFunc>
  71. void iterateBuckets(RenderingTechnique technique, TFunc func) const
  72. {
  73. for(const ExtendedBucket& b : m_buckets[technique])
  74. {
  75. if(b.m_userCount > 0)
  76. {
  77. func(static_cast<const RenderStateInfo&>(b));
  78. }
  79. }
  80. }
  81. /// Get the number of renderables of all the buckets of a specific rendering technique.
  82. U32 getBucketsItemCount(RenderingTechnique technique) const
  83. {
  84. return m_bucketItemCount[technique];
  85. }
  86. U32 getBucketCount(RenderingTechnique technique) const
  87. {
  88. return m_buckets[technique].getSize();
  89. }
  90. private:
  91. class ExtendedBucket : public RenderStateInfo
  92. {
  93. public:
  94. U64 m_hash = 0;
  95. U32 m_userCount = 0;
  96. };
  97. Array<SceneDynamicArray<ExtendedBucket>, U32(RenderingTechnique::kCount)> m_buckets;
  98. Array<U32, U32(RenderingTechnique::kCount)> m_bucketItemCount = {};
  99. Mutex m_mtx;
  100. RenderStateBucketContainer() = default;
  101. ~RenderStateBucketContainer();
  102. };
  103. inline RenderStateBucketIndex::~RenderStateBucketIndex()
  104. {
  105. RenderStateBucketContainer::getSingleton().removeUser(*this);
  106. }
  107. /// @}
  108. } // end namespace anki