buffer.hpp 6.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227
  1. //---------------------------------------------------------------------------//
  2. // Copyright (c) 2013 Kyle Lutz <kyle.r.lutz@gmail.com>
  3. //
  4. // Distributed under the Boost Software License, Version 1.0
  5. // See accompanying file LICENSE_1_0.txt or copy at
  6. // http://www.boost.org/LICENSE_1_0.txt
  7. //
  8. // See http://boostorg.github.com/compute for more information.
  9. //---------------------------------------------------------------------------//
  10. #ifndef BOOST_COMPUTE_BUFFER_HPP
  11. #define BOOST_COMPUTE_BUFFER_HPP
  12. #include <boost/compute/config.hpp>
  13. #include <boost/compute/context.hpp>
  14. #include <boost/compute/exception.hpp>
  15. #include <boost/compute/memory_object.hpp>
  16. #include <boost/compute/detail/get_object_info.hpp>
  17. namespace boost {
  18. namespace compute {
  19. // forward declarations
  20. class command_queue;
  21. /// \class buffer
  22. /// \brief A memory buffer on a compute device.
  23. ///
  24. /// The buffer class represents a memory buffer on a compute device.
  25. ///
  26. /// Buffers are allocated within a compute context. For example, to allocate
  27. /// a memory buffer for 32 float's:
  28. ///
  29. /// \snippet test/test_buffer.cpp constructor
  30. ///
  31. /// Once created, data can be copied to and from the buffer using the
  32. /// \c enqueue_*_buffer() methods in the command_queue class. For example, to
  33. /// copy a set of \c int values from the host to the device:
  34. /// \code
  35. /// int data[] = { 1, 2, 3, 4 };
  36. ///
  37. /// queue.enqueue_write_buffer(buf, 0, 4 * sizeof(int), data);
  38. /// \endcode
  39. ///
  40. /// Also see the copy() algorithm for a higher-level interface to copying data
  41. /// between the host and the device. For a higher-level, dynamically-resizable,
  42. /// type-safe container for data on a compute device, use the vector<T> class.
  43. ///
  44. /// Buffer objects have reference semantics. Creating a copy of a buffer
  45. /// object simply creates another reference to the underlying OpenCL memory
  46. /// object. To create an actual copy use the buffer::clone() method.
  47. ///
  48. /// \see context, command_queue
  49. class buffer : public memory_object
  50. {
  51. public:
  52. /// Creates a null buffer object.
  53. buffer()
  54. : memory_object()
  55. {
  56. }
  57. /// Creates a buffer object for \p mem. If \p retain is \c true, the
  58. /// reference count for \p mem will be incremented.
  59. explicit buffer(cl_mem mem, bool retain = true)
  60. : memory_object(mem, retain)
  61. {
  62. }
  63. /// Create a new memory buffer in of \p size with \p flags in
  64. /// \p context.
  65. ///
  66. /// \see_opencl_ref{clCreateBuffer}
  67. buffer(const context &context,
  68. size_t size,
  69. cl_mem_flags flags = read_write,
  70. void *host_ptr = 0)
  71. {
  72. cl_int error = 0;
  73. m_mem = clCreateBuffer(context,
  74. flags,
  75. (std::max)(size, size_t(1)),
  76. host_ptr,
  77. &error);
  78. if(!m_mem){
  79. BOOST_THROW_EXCEPTION(opencl_error(error));
  80. }
  81. }
  82. /// Creates a new buffer object as a copy of \p other.
  83. buffer(const buffer &other)
  84. : memory_object(other)
  85. {
  86. }
  87. /// Copies the buffer object from \p other to \c *this.
  88. buffer& operator=(const buffer &other)
  89. {
  90. if(this != &other){
  91. memory_object::operator=(other);
  92. }
  93. return *this;
  94. }
  95. #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
  96. /// Move-constructs a new buffer object from \p other.
  97. buffer(buffer&& other) BOOST_NOEXCEPT
  98. : memory_object(std::move(other))
  99. {
  100. }
  101. /// Move-assigns the buffer from \p other to \c *this.
  102. buffer& operator=(buffer&& other) BOOST_NOEXCEPT
  103. {
  104. memory_object::operator=(std::move(other));
  105. return *this;
  106. }
  107. #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
  108. /// Destroys the buffer object.
  109. ~buffer()
  110. {
  111. }
  112. /// Returns the size of the buffer in bytes.
  113. size_t size() const
  114. {
  115. return get_memory_size();
  116. }
  117. /// \internal_
  118. size_t max_size() const
  119. {
  120. return get_context().get_device().max_memory_alloc_size();
  121. }
  122. /// Returns information about the buffer.
  123. ///
  124. /// \see_opencl_ref{clGetMemObjectInfo}
  125. template<class T>
  126. T get_info(cl_mem_info info) const
  127. {
  128. return get_memory_info<T>(info);
  129. }
  130. /// \overload
  131. template<int Enum>
  132. typename detail::get_object_info_type<buffer, Enum>::type
  133. get_info() const;
  134. /// Creates a new buffer with a copy of the data in \c *this. Uses
  135. /// \p queue to perform the copy.
  136. buffer clone(command_queue &queue) const;
  137. #if defined(BOOST_COMPUTE_CL_VERSION_1_1) || defined(BOOST_COMPUTE_DOXYGEN_INVOKED)
  138. /// Creates a new buffer out of this buffer.
  139. /// The new buffer is a sub region of this buffer.
  140. /// \p flags The mem_flags which should be used to create the new buffer
  141. /// \p origin The start index in this buffer
  142. /// \p size The size of the new sub buffer
  143. ///
  144. /// \see_opencl_ref{clCreateSubBuffer}
  145. ///
  146. /// \opencl_version_warning{1,1}
  147. buffer create_subbuffer(cl_mem_flags flags, size_t origin,
  148. size_t size)
  149. {
  150. BOOST_ASSERT(origin + size <= this->size());
  151. BOOST_ASSERT(origin % (get_context().
  152. get_device().
  153. get_info<CL_DEVICE_MEM_BASE_ADDR_ALIGN>() / 8) == 0);
  154. cl_int error = 0;
  155. cl_buffer_region region = { origin, size };
  156. cl_mem mem = clCreateSubBuffer(m_mem,
  157. flags,
  158. CL_BUFFER_CREATE_TYPE_REGION,
  159. &region,
  160. &error);
  161. if(!mem){
  162. BOOST_THROW_EXCEPTION(opencl_error(error));
  163. }
  164. return buffer(mem, false);
  165. }
  166. #endif // BOOST_COMPUTE_CL_VERSION_1_1
  167. };
  168. /// \internal_ define get_info() specializations for buffer
  169. BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
  170. ((cl_mem_object_type, CL_MEM_TYPE))
  171. ((cl_mem_flags, CL_MEM_FLAGS))
  172. ((size_t, CL_MEM_SIZE))
  173. ((void *, CL_MEM_HOST_PTR))
  174. ((cl_uint, CL_MEM_MAP_COUNT))
  175. ((cl_uint, CL_MEM_REFERENCE_COUNT))
  176. ((cl_context, CL_MEM_CONTEXT))
  177. )
  178. #ifdef BOOST_COMPUTE_CL_VERSION_1_1
  179. BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(buffer,
  180. ((cl_mem, CL_MEM_ASSOCIATED_MEMOBJECT))
  181. ((size_t, CL_MEM_OFFSET))
  182. )
  183. #endif // BOOST_COMPUTE_CL_VERSION_1_1
  184. namespace detail {
  185. // set_kernel_arg specialization for buffer
  186. template<>
  187. struct set_kernel_arg<buffer>
  188. {
  189. void operator()(kernel &kernel_, size_t index, const buffer &buffer_)
  190. {
  191. kernel_.set_arg(index, buffer_.get());
  192. }
  193. };
  194. } // end detail namespace
  195. } // end compute namespace
  196. } // end boost namespace
  197. #endif // BOOST_COMPUTE_BUFFER_HPP