buffer.h 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280
  1. // ======================================================================== //
  2. // Copyright 2009-2017 Intel Corporation //
  3. // //
  4. // Licensed under the Apache License, Version 2.0 (the "License"); //
  5. // you may not use this file except in compliance with the License. //
  6. // You may obtain a copy of the License at //
  7. // //
  8. // http://www.apache.org/licenses/LICENSE-2.0 //
  9. // //
  10. // Unless required by applicable law or agreed to in writing, software //
  11. // distributed under the License is distributed on an "AS IS" BASIS, //
  12. // WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. //
  13. // See the License for the specific language governing permissions and //
  14. // limitations under the License. //
  15. // ======================================================================== //
  16. #pragma once
  17. #include "default.h"
  18. namespace embree
  19. {
  20. /*! Implements a reference to a data buffer, this class does not own the buffer content. */
  21. class BufferRef
  22. {
  23. public:
  24. /*! Buffer construction */
  25. BufferRef (size_t num = 0, size_t stride = 0)
  26. : ptr_ofs(nullptr), stride(stride), num(num) {}
  27. public:
  28. /*! sets shared buffer */
  29. void set(char* ptr_ofs_in, size_t stride_in) {
  30. ptr_ofs = ptr_ofs_in;
  31. stride = stride_in;
  32. }
  33. /*! returns pointer to first element */
  34. __forceinline const char* getPtr( size_t i = 0 ) const {
  35. assert(i<num);
  36. return ptr_ofs + i*stride;
  37. }
  38. /*! returns the number of elements of the buffer */
  39. __forceinline size_t size() const {
  40. return num;
  41. }
  42. /*! returns the number of bytes of the buffer */
  43. __forceinline size_t bytes() const {
  44. return num*stride;
  45. }
  46. /*! returns buffer stride */
  47. __forceinline size_t getStride() const {
  48. return stride;
  49. }
  50. protected:
  51. char* ptr_ofs; //!< base pointer plus offset
  52. size_t stride; //!< stride of the stream in bytes
  53. size_t num; //!< number of elements in the stream
  54. };
  55. /*! Implements a typed data stream from a data buffer reference. */
  56. template<typename T>
  57. class BufferRefT : public BufferRef
  58. {
  59. public:
  60. typedef T value_type;
  61. BufferRefT (size_t num = 0, size_t stride = 0)
  62. : BufferRef(num,stride) {}
  63. /*! access to the ith element of the buffer stream */
  64. __forceinline T& operator[](size_t i) { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
  65. __forceinline const T& operator[](size_t i) const { assert(i<num); return *(T*)(ptr_ofs + i*stride); }
  66. };
  67. /*! Implements a typed data stream from a data buffer reference. */
  68. template<>
  69. class BufferRefT<Vec3fa> : public BufferRef
  70. {
  71. public:
  72. typedef Vec3fa value_type;
  73. BufferRefT (size_t num = 0, size_t stride = 0)
  74. : BufferRef(num,stride) {}
  75. /*! access to the ith element of the buffer stream */
  76. __forceinline const Vec3fa operator[](size_t i) const
  77. {
  78. assert(i<num);
  79. return Vec3fa(vfloat4::loadu((float*)(ptr_ofs + i*stride)));
  80. }
  81. /*! writes the i'th element */
  82. __forceinline void store(size_t i, const Vec3fa& v)
  83. {
  84. assert(i<num);
  85. vfloat4::storeu((float*)(ptr_ofs + i*stride),(vfloat4)v);
  86. }
  87. };
  88. /*! Implements an API data buffer object. This class may or may not own the data. */
  89. template<typename T>
  90. class APIBuffer : public BufferRefT<T>
  91. {
  92. public:
  93. /*! Buffer construction */
  94. APIBuffer ()
  95. : device(nullptr), ptr(nullptr), allocated(false), shared(false), mapped(false), modified(true), userdata(0) {}
  96. APIBuffer (const BufferRefT<T>& other)
  97. : BufferRefT<T>(other), device(nullptr), ptr(nullptr), allocated(false), shared(true), mapped(false), modified(true), userdata(0) {}
  98. /*! Buffer construction */
  99. APIBuffer (MemoryMonitorInterface* device, size_t num_in, size_t stride_in, bool allocate = false)
  100. : BufferRefT<T>(num_in,stride_in), device(device), ptr(nullptr), allocated(false), shared(false), mapped(false), modified(true), userdata(0)
  101. {
  102. if (allocate) alloc();
  103. }
  104. /*! Buffer destruction */
  105. ~APIBuffer () {
  106. free();
  107. }
  108. /*! this class is not copyable */
  109. private:
  110. APIBuffer (const APIBuffer& other) DELETED; // do not implement
  111. APIBuffer& operator= (const APIBuffer& other) DELETED; // do not implement
  112. /*! make the class movable */
  113. public:
  114. APIBuffer (APIBuffer&& other) : BufferRefT<T>(std::move(other))
  115. {
  116. device = other.device; other.device = nullptr;
  117. ptr = other.ptr; other.ptr = nullptr;
  118. allocated = other.allocated; other.allocated = false;
  119. shared = other.shared; other.shared = false;
  120. mapped = other.mapped; other.mapped = false;
  121. modified = other.modified; other.modified = false;
  122. userdata = other.userdata; other.userdata = 0;
  123. }
  124. APIBuffer& operator= (APIBuffer&& other)
  125. {
  126. device = other.device; other.device = nullptr;
  127. ptr = other.ptr; other.ptr = nullptr;
  128. allocated = other.allocated; other.allocated = false;
  129. shared = other.shared; other.shared = false;
  130. mapped = other.mapped; other.mapped = false;
  131. modified = other.modified; other.modified = false;
  132. userdata = other.userdata; other.userdata = 0;
  133. BufferRefT<T>::operator=(std::move(other));
  134. return *this;
  135. }
  136. public:
  137. /* inits the buffer */
  138. void init(MemoryMonitorInterface* device_in, size_t num_in, size_t stride_in)
  139. {
  140. device = device_in;
  141. ptr = nullptr;
  142. this->ptr_ofs = nullptr;
  143. this->num = num_in;
  144. this->stride = stride_in;
  145. shared = false;
  146. mapped = false;
  147. modified = true;
  148. }
  149. /*! sets shared buffer */
  150. void set(void* ptr_in, size_t ofs_in, size_t stride_in, size_t num_in)
  151. {
  152. /* report error if buffer is not existing */
  153. if (!device)
  154. throw_RTCError(RTC_INVALID_ARGUMENT,"invalid buffer specified");
  155. ptr = (char*) ptr_in;
  156. if (num_in != (size_t)-1) this->num = num_in;
  157. shared = true;
  158. BufferRefT<T>::set(ptr+ofs_in,stride_in);
  159. }
  160. /*! allocated buffer */
  161. void alloc() {
  162. if (device) device->memoryMonitor(this->bytes(),false);
  163. ptr = this->ptr_ofs = (char*) alignedMalloc(this->bytes());
  164. allocated = true; // this flag is sticky, such that we do never allocated a buffer again after it was freed
  165. }
  166. /*! frees the buffer */
  167. void free()
  168. {
  169. if (shared || !ptr) return;
  170. alignedFree(ptr);
  171. if (device) device->memoryMonitor(-ssize_t(this->bytes()),true);
  172. ptr = nullptr; this->ptr_ofs = nullptr;
  173. }
  174. /*! maps the buffer */
  175. void* map(std::atomic<size_t>& cntr)
  176. {
  177. /* report error if buffer is not existing */
  178. if (!device)
  179. throw_RTCError(RTC_INVALID_ARGUMENT,"invalid buffer specified");
  180. /* report error if buffer is already mapped */
  181. if (mapped)
  182. throw_RTCError(RTC_INVALID_OPERATION,"buffer is already mapped");
  183. /* allocate buffer */
  184. if (!ptr && !shared && !allocated)
  185. alloc();
  186. /* return mapped buffer */
  187. cntr++;
  188. mapped = true;
  189. return ptr;
  190. }
  191. /*! unmaps the buffer */
  192. void unmap(std::atomic<size_t>& cntr)
  193. {
  194. /* report error if buffer not mapped */
  195. if (!mapped)
  196. throw_RTCError(RTC_INVALID_OPERATION,"buffer is not mapped");
  197. /* unmap buffer */
  198. cntr--;
  199. mapped = false;
  200. }
  201. /*! checks if the buffer is mapped */
  202. __forceinline bool isMapped() const {
  203. return mapped;
  204. }
  205. /*! mark buffer as modified or unmodified */
  206. __forceinline void setModified(bool b) {
  207. modified = b;
  208. }
  209. /*! mark buffer as modified or unmodified */
  210. __forceinline bool isModified() const {
  211. return modified;
  212. }
  213. /*! returns true of the buffer is not empty */
  214. __forceinline operator bool() const {
  215. return ptr;
  216. }
  217. /*! checks padding to 16 byte check, fails hard */
  218. __forceinline void checkPadding16() const
  219. {
  220. if (BufferRef::size())
  221. volatile int MAYBE_UNUSED w = *((int*)BufferRef::getPtr(BufferRef::size()-1)+3); // FIXME: is failing hard avoidable?
  222. }
  223. protected:
  224. MemoryMonitorInterface* device; //!< device to report memory usage to
  225. char* ptr; //!< pointer to buffer data
  226. bool allocated; //!< set if buffer got allocated by us
  227. bool shared; //!< set if memory is shared with application
  228. bool mapped; //!< set if buffer is mapped
  229. bool modified; //!< true if the buffer got modified
  230. public:
  231. int userdata; //!< special data
  232. };
  233. }