Buffer.h 5.1 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256
  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/Gr/GrObject.h>
  7. #include <AnKi/Util/WeakArray.h>
  8. namespace anki {
  9. /// @addtogroup graphics
  10. /// @{
  11. /// Buffer init info.
  12. /// @memberof Buffer
  13. class BufferInitInfo : public GrBaseInitInfo
  14. {
  15. public:
  16. PtrSize m_size = 0;
  17. BufferUsageBit m_usage = BufferUsageBit::kNone;
  18. BufferMapAccessBit m_mapAccess = BufferMapAccessBit::kNone;
  19. BufferInitInfo(CString name = {})
  20. : GrBaseInitInfo(name)
  21. {
  22. }
  23. BufferInitInfo(PtrSize size, BufferUsageBit usage, BufferMapAccessBit mapAccess, CString name = {})
  24. : GrBaseInitInfo(name)
  25. , m_size(size)
  26. , m_usage(usage)
  27. , m_mapAccess(mapAccess)
  28. {
  29. }
  30. Bool isValid() const
  31. {
  32. return m_size && !!m_usage;
  33. }
  34. };
  35. /// GPU buffer.
  36. class Buffer : public GrObject
  37. {
  38. ANKI_GR_OBJECT
  39. public:
  40. static constexpr GrObjectType kClassType = GrObjectType::kBuffer;
  41. /// Return the size of the buffer.
  42. PtrSize getSize() const
  43. {
  44. ANKI_ASSERT(m_size > 0);
  45. return m_size;
  46. }
  47. /// Return the BufferUsageBit of the Buffer.
  48. BufferUsageBit getBufferUsage() const
  49. {
  50. ANKI_ASSERT(!!m_usage);
  51. return m_usage;
  52. }
  53. /// Return the BufferMapAccessBit of the Buffer.
  54. BufferMapAccessBit getMapAccess() const
  55. {
  56. return m_access;
  57. }
  58. /// Map the buffer.
  59. /// @param offset The starting offset.
  60. /// @param range The range to map or kMaxPtrSize to map until the end.
  61. /// @param access The access to the buffer.
  62. void* map(PtrSize offset, PtrSize range, BufferMapAccessBit access);
  63. /// Flush the buffer from the CPU caches. Call it to make the buffer memory available to the GPU.
  64. /// @param offset The starting offset.
  65. /// @param range The range to map or kMaxPtrSize to map until the end.
  66. void flush(PtrSize offset, PtrSize range) const;
  67. /// Invalidate the buffer from the CPU caches. Call it to ready the buffer to see GPU updates.
  68. /// @param offset The starting offset.
  69. /// @param range The range to map or kMaxPtrSize to map until the end.
  70. void invalidate(PtrSize offset, PtrSize range) const;
  71. /// Convenience map method.
  72. /// @param offset The starting offset.
  73. /// @param elementCount The number of T element sto map.
  74. /// @param access The access to the buffer.
  75. /// @return The array that was mapped.
  76. template<typename T>
  77. WeakArray<T, PtrSize> map(PtrSize offset, PtrSize elementCount, BufferMapAccessBit access)
  78. {
  79. return WeakArray<T, PtrSize>(static_cast<T*>(map(offset, sizeof(T) * elementCount, access)), elementCount);
  80. }
  81. /// Unmap the buffer.
  82. void unmap();
  83. /// Get the GPU adress of the buffer.
  84. U64 getGpuAddress() const
  85. {
  86. ANKI_ASSERT(m_gpuAddress);
  87. return m_gpuAddress;
  88. }
  89. protected:
  90. PtrSize m_size = 0;
  91. BufferUsageBit m_usage = BufferUsageBit::kNone;
  92. BufferMapAccessBit m_access = BufferMapAccessBit::kNone;
  93. U64 m_gpuAddress = 0;
  94. /// Construct.
  95. Buffer(CString name)
  96. : GrObject(kClassType, name)
  97. {
  98. }
  99. /// Destroy.
  100. ~Buffer()
  101. {
  102. }
  103. private:
  104. /// Allocate and initialize a new instance.
  105. [[nodiscard]] static Buffer* newInstance(const BufferInitInfo& init);
  106. };
  107. /// A part of a buffer.
  108. class BufferView
  109. {
  110. public:
  111. BufferView() = default;
  112. BufferView(const BufferView&) = default;
  113. explicit BufferView(Buffer* buffer)
  114. : m_buffer(buffer)
  115. , m_offset(0)
  116. , m_range(buffer->getSize())
  117. {
  118. validate();
  119. }
  120. BufferView(Buffer* buffer, PtrSize offset, PtrSize range)
  121. : m_buffer(buffer)
  122. , m_offset(offset)
  123. , m_range(range)
  124. {
  125. validate();
  126. }
  127. BufferView& operator=(const BufferView&) = default;
  128. explicit operator Bool() const
  129. {
  130. return isValid();
  131. }
  132. [[nodiscard]] Buffer& getBuffer() const
  133. {
  134. validate();
  135. return *m_buffer;
  136. }
  137. [[nodiscard]] const PtrSize& getOffset() const
  138. {
  139. validate();
  140. return m_offset;
  141. }
  142. BufferView& setOffset(PtrSize offset)
  143. {
  144. validate();
  145. m_offset = offset;
  146. validate();
  147. return *this;
  148. }
  149. BufferView& incrementOffset(PtrSize bytes)
  150. {
  151. validate();
  152. ANKI_ASSERT(m_range >= bytes);
  153. m_range -= bytes;
  154. m_offset += bytes;
  155. if(m_range == 0)
  156. {
  157. *this = {};
  158. }
  159. else
  160. {
  161. validate();
  162. }
  163. return *this;
  164. }
  165. [[nodiscard]] const PtrSize& getRange() const
  166. {
  167. validate();
  168. return m_range;
  169. }
  170. BufferView& setRange(PtrSize range)
  171. {
  172. validate();
  173. if(range != 0)
  174. {
  175. m_range = range;
  176. validate();
  177. }
  178. else
  179. {
  180. *this = {};
  181. }
  182. return *this;
  183. }
  184. [[nodiscard]] Bool isValid() const
  185. {
  186. return m_buffer != nullptr;
  187. }
  188. [[nodiscard]] Bool overlaps(const BufferView& b) const
  189. {
  190. validate();
  191. b.validate();
  192. Bool overlaps = m_buffer == b.m_buffer;
  193. if(m_offset <= b.m_offset)
  194. {
  195. overlaps = overlaps && (m_offset + m_range > b.m_offset);
  196. }
  197. else
  198. {
  199. overlaps = overlaps && (b.m_offset + b.m_range > m_offset);
  200. }
  201. return overlaps;
  202. }
  203. private:
  204. Buffer* m_buffer = nullptr;
  205. PtrSize m_offset = kMaxPtrSize;
  206. PtrSize m_range = 0;
  207. void validate() const
  208. {
  209. ANKI_ASSERT(m_buffer && m_range > 0);
  210. ANKI_ASSERT(m_range <= m_buffer->getSize() && m_offset < m_buffer->getSize()); // Do that to ensure the next line won't overflow
  211. ANKI_ASSERT(m_offset + m_range <= m_buffer->getSize());
  212. }
  213. };
  214. /// @}
  215. } // end namespace anki