context.hpp 6.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247
  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_CONTEXT_HPP
  11. #define BOOST_COMPUTE_CONTEXT_HPP
  12. #include <vector>
  13. #include <boost/throw_exception.hpp>
  14. #include <boost/compute/config.hpp>
  15. #include <boost/compute/device.hpp>
  16. #include <boost/compute/exception/opencl_error.hpp>
  17. #include <boost/compute/exception/set_default_queue_error.hpp>
  18. #include <boost/compute/detail/assert_cl_success.hpp>
  19. namespace boost {
  20. namespace compute {
  21. /// \class context
  22. /// \brief A compute context.
  23. ///
  24. /// The context class represents a compute context.
  25. ///
  26. /// A context object manages a set of OpenCL resources including memory
  27. /// buffers and program objects. Before allocating memory on the device or
  28. /// executing kernels you must set up a context object.
  29. ///
  30. /// To create a context for the default device on the system:
  31. /// \code
  32. /// // get the default compute device
  33. /// boost::compute::device gpu = boost::compute::system::default_device();
  34. ///
  35. /// // create a context for the device
  36. /// boost::compute::context context(gpu);
  37. /// \endcode
  38. ///
  39. /// Once a context is created, memory can be allocated using the buffer class
  40. /// and kernels can be executed using the command_queue class.
  41. ///
  42. /// \see device, command_queue
  43. class context
  44. {
  45. public:
  46. /// Create a null context object.
  47. context()
  48. : m_context(0)
  49. {
  50. }
  51. /// Creates a new context for \p device with \p properties.
  52. ///
  53. /// \see_opencl_ref{clCreateContext}
  54. explicit context(const device &device,
  55. const cl_context_properties *properties = 0)
  56. {
  57. BOOST_ASSERT(device.id() != 0);
  58. cl_device_id device_id = device.id();
  59. cl_int error = 0;
  60. m_context = clCreateContext(properties, 1, &device_id, 0, 0, &error);
  61. if(!m_context){
  62. BOOST_THROW_EXCEPTION(opencl_error(error));
  63. }
  64. }
  65. /// Creates a new context for \p devices with \p properties.
  66. ///
  67. /// \see_opencl_ref{clCreateContext}
  68. explicit context(const std::vector<device> &devices,
  69. const cl_context_properties *properties = 0)
  70. {
  71. BOOST_ASSERT(!devices.empty());
  72. cl_int error = 0;
  73. m_context = clCreateContext(
  74. properties,
  75. static_cast<cl_uint>(devices.size()),
  76. reinterpret_cast<const cl_device_id *>(&devices[0]),
  77. 0,
  78. 0,
  79. &error
  80. );
  81. if(!m_context){
  82. BOOST_THROW_EXCEPTION(opencl_error(error));
  83. }
  84. }
  85. /// Creates a new context object for \p context. If \p retain is
  86. /// \c true, the reference count for \p context will be incremented.
  87. explicit context(cl_context context, bool retain = true)
  88. : m_context(context)
  89. {
  90. if(m_context && retain){
  91. clRetainContext(m_context);
  92. }
  93. }
  94. /// Creates a new context object as a copy of \p other.
  95. context(const context &other)
  96. : m_context(other.m_context)
  97. {
  98. if(m_context){
  99. clRetainContext(m_context);
  100. }
  101. }
  102. /// Copies the context object from \p other to \c *this.
  103. context& operator=(const context &other)
  104. {
  105. if(this != &other){
  106. if(m_context){
  107. clReleaseContext(m_context);
  108. }
  109. m_context = other.m_context;
  110. if(m_context){
  111. clRetainContext(m_context);
  112. }
  113. }
  114. return *this;
  115. }
  116. #ifndef BOOST_COMPUTE_NO_RVALUE_REFERENCES
  117. /// Move-constructs a new context object from \p other.
  118. context(context&& other) BOOST_NOEXCEPT
  119. : m_context(other.m_context)
  120. {
  121. other.m_context = 0;
  122. }
  123. /// Move-assigns the context from \p other to \c *this.
  124. context& operator=(context&& other) BOOST_NOEXCEPT
  125. {
  126. if(m_context){
  127. clReleaseContext(m_context);
  128. }
  129. m_context = other.m_context;
  130. other.m_context = 0;
  131. return *this;
  132. }
  133. #endif // BOOST_COMPUTE_NO_RVALUE_REFERENCES
  134. /// Destroys the context object.
  135. ~context()
  136. {
  137. if(m_context){
  138. BOOST_COMPUTE_ASSERT_CL_SUCCESS(
  139. clReleaseContext(m_context)
  140. );
  141. }
  142. }
  143. /// Returns the underlying OpenCL context.
  144. cl_context& get() const
  145. {
  146. return const_cast<cl_context &>(m_context);
  147. }
  148. /// Returns the device for the context. If the context contains multiple
  149. /// devices, the first is returned.
  150. device get_device() const
  151. {
  152. std::vector<device> devices = get_devices();
  153. if(devices.empty()) {
  154. return device();
  155. }
  156. return devices.front();
  157. }
  158. /// Returns a vector of devices for the context.
  159. std::vector<device> get_devices() const
  160. {
  161. return get_info<std::vector<device> >(CL_CONTEXT_DEVICES);
  162. }
  163. /// Returns information about the context.
  164. ///
  165. /// \see_opencl_ref{clGetContextInfo}
  166. template<class T>
  167. T get_info(cl_context_info info) const
  168. {
  169. return detail::get_object_info<T>(clGetContextInfo, m_context, info);
  170. }
  171. /// \overload
  172. template<int Enum>
  173. typename detail::get_object_info_type<context, Enum>::type
  174. get_info() const;
  175. /// Returns \c true if the context is the same as \p other.
  176. bool operator==(const context &other) const
  177. {
  178. return m_context == other.m_context;
  179. }
  180. /// Returns \c true if the context is different from \p other.
  181. bool operator!=(const context &other) const
  182. {
  183. return m_context != other.m_context;
  184. }
  185. /// \internal_
  186. operator cl_context() const
  187. {
  188. return m_context;
  189. }
  190. private:
  191. cl_context m_context;
  192. };
  193. /// \internal_ define get_info() specializations for context
  194. BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
  195. ((cl_uint, CL_CONTEXT_REFERENCE_COUNT))
  196. ((std::vector<cl_device_id>, CL_CONTEXT_DEVICES))
  197. ((std::vector<cl_context_properties>, CL_CONTEXT_PROPERTIES))
  198. )
  199. #ifdef BOOST_COMPUTE_CL_VERSION_1_1
  200. BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(context,
  201. ((cl_uint, CL_CONTEXT_NUM_DEVICES))
  202. )
  203. #endif // BOOST_COMPUTE_CL_VERSION_1_1
  204. } // end compute namespace
  205. } // end boost namespace
  206. #endif // BOOST_COMPUTE_CONTEXT_HPP