GlObject.h 3.0 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174
  1. #ifndef ANKI_GL_GL_OBJECT_H
  2. #define ANKI_GL_GL_OBJECT_H
  3. #include "anki/gl/Ogl.h"
  4. #include "anki/gl/GlException.h"
  5. #include "anki/Config.h"
  6. #include "anki/util/NonCopyable.h"
  7. #include "anki/util/Assert.h"
  8. #include "anki/util/Array.h"
  9. #include "anki/util/StdTypes.h"
  10. #include "anki/core/Timestamp.h"
  11. #include <thread>
  12. #include <atomic>
  13. #include <cstring>
  14. namespace anki {
  15. /// @addtogroup OpenGL
  16. /// @{
  17. /// A compound GL object that supports buffering depending on the frame
  18. class GlObject: public NonCopyable
  19. {
  20. public:
  21. /// Buffering technique
  22. enum
  23. {
  24. SINGLE_OBJECT = 1,
  25. DOUBLE_OBJECT = 2,
  26. TRIPLE_OBJECT = 3,
  27. MAX_OBJECTS = 3
  28. };
  29. /// Default
  30. GlObject()
  31. {
  32. memset(&glIds[0], 0, sizeof(glIds));
  33. objectsCount = 1;
  34. #if ANKI_DEBUG
  35. refCount.store(0);
  36. #endif
  37. }
  38. /// Move
  39. GlObject(GlObject&& b)
  40. : GlObject()
  41. {
  42. *this = std::move(b);
  43. }
  44. ~GlObject()
  45. {
  46. // The destructor of the derived GL object should pass 0 name
  47. ANKI_ASSERT(!isCreated());
  48. }
  49. /// Move
  50. GlObject& operator=(GlObject&& b)
  51. {
  52. ANKI_ASSERT(!isCreated());
  53. for(U i = 0; i < MAX_OBJECTS; i++)
  54. {
  55. glIds[i] = b.glIds[i];
  56. b.glIds[i] = 0;
  57. }
  58. objectsCount = b.objectsCount;
  59. b.objectsCount = 1;
  60. #if ANKI_DEBUG
  61. refCount.store(b.refCount.load());
  62. b.refCount.store(0);
  63. #endif
  64. return *this;
  65. }
  66. /// Get the GL name for the current frame
  67. GLuint getGlId() const
  68. {
  69. ANKI_ASSERT(isCreated());
  70. return glIds[getGlobTimestamp() % objectsCount];
  71. }
  72. /// GL object is created
  73. Bool isCreated() const
  74. {
  75. ANKI_ASSERT(objectsCount > 0);
  76. #if ANKI_DEBUG
  77. U mask = 0;
  78. for(U i = 0; i < MAX_OBJECTS; i++)
  79. {
  80. mask <<= 1;
  81. mask |= (glIds[i] != 0);
  82. }
  83. // If the mask is not zero then make sure that objectsCount is sane
  84. ANKI_ASSERT(!(mask != 0 && __builtin_popcount(mask) != objectsCount));
  85. #endif
  86. return glId != 0;
  87. }
  88. protected:
  89. /// OpenGL names
  90. union
  91. {
  92. Array<GLuint, MAX_OBJECTS> glIds;
  93. GLuint glId;
  94. };
  95. /// The size of the glIds array
  96. U8 objectsCount;
  97. #if ANKI_DEBUG
  98. /// Textures and buffers can be attached so keep a refcount for sanity
  99. /// checks
  100. std::atomic<U32> refCount;
  101. #endif
  102. };
  103. /// Defines an non sharable GL object. Used to avoid idiotic mistakes and more
  104. /// specifically using the object from other than contexts
  105. class GlObjectContextNonSharable: protected GlObject
  106. {
  107. public:
  108. GlObjectContextNonSharable()
  109. {}
  110. GlObjectContextNonSharable(GlObjectContextNonSharable&& b)
  111. {
  112. *this = std::move(b);
  113. }
  114. ~GlObjectContextNonSharable()
  115. {
  116. checkNonSharable();
  117. }
  118. GlObjectContextNonSharable& operator=(GlObjectContextNonSharable&& b)
  119. {
  120. GlObject::operator=(std::forward<GlObject>(b));
  121. #if ANKI_DEBUG
  122. creationThreadId = b.creationThreadId;
  123. #endif
  124. return *this;
  125. }
  126. void crateNonSharable()
  127. {
  128. #if ANKI_DEBUG
  129. creationThreadId = std::this_thread::get_id();
  130. #endif
  131. }
  132. void checkNonSharable() const
  133. {
  134. #if ANKI_DEBUG
  135. ANKI_ASSERT((!isCreated()
  136. || creationThreadId == std::this_thread::get_id())
  137. && "Object is not context sharable");
  138. #endif
  139. }
  140. private:
  141. #if ANKI_DEBUG
  142. std::thread::id creationThreadId;
  143. #endif
  144. };
  145. /// @}
  146. } // end namespace anki
  147. #endif