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