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_PLATFORM_HPP
12 #define BOOST_COMPUTE_PLATFORM_HPP
13 
14 #include <algorithm>
15 #include <string>
16 #include <vector>
17 
18 #include <boost/algorithm/string/split.hpp>
19 #include <boost/algorithm/string/classification.hpp>
20 
21 #include <boost/compute/cl.hpp>
22 #include <boost/compute/device.hpp>
23 #include <boost/compute/detail/get_object_info.hpp>
24 
25 namespace boost {
26 namespace compute {
27 
28 /// \class platform
29 /// \brief A compute platform.
30 ///
31 /// The platform class provides an interface to an OpenCL platform.
32 ///
33 /// To obtain a list of all platforms on the system use the
34 /// system::platforms() method.
35 ///
36 /// \see device, context
37 class platform
38 {
39 public:
40     /// Creates a new platform object for \p id.
platform(cl_platform_id id)41     explicit platform(cl_platform_id id)
42         : m_platform(id)
43     {
44     }
45 
46     /// Creates a new platform as a copy of \p other.
platform(const platform & other)47     platform(const platform &other)
48         : m_platform(other.m_platform)
49     {
50     }
51 
52     /// Copies the platform id from \p other.
operator =(const platform & other)53     platform& operator=(const platform &other)
54     {
55         if(this != &other){
56             m_platform = other.m_platform;
57         }
58 
59         return *this;
60     }
61 
62     /// Destroys the platform object.
~platform()63     ~platform()
64     {
65     }
66 
67     /// Returns the ID of the platform.
id() const68     cl_platform_id id() const
69     {
70         return m_platform;
71     }
72 
73     /// Returns the name of the platform.
name() const74     std::string name() const
75     {
76         return get_info<std::string>(CL_PLATFORM_NAME);
77     }
78 
79     /// Returns the name of the vendor for the platform.
vendor() const80     std::string vendor() const
81     {
82         return get_info<std::string>(CL_PLATFORM_VENDOR);
83     }
84 
85     /// Returns the profile string for the platform.
profile() const86     std::string profile() const
87     {
88         return get_info<std::string>(CL_PLATFORM_PROFILE);
89     }
90 
91     /// Returns the version string for the platform.
version() const92     std::string version() const
93     {
94         return get_info<std::string>(CL_PLATFORM_VERSION);
95     }
96 
97     /// Returns a list of extensions supported by the platform.
extensions() const98     std::vector<std::string> extensions() const
99     {
100         std::string extensions_string =
101             get_info<std::string>(CL_PLATFORM_EXTENSIONS);
102         std::vector<std::string> extensions_vector;
103         boost::split(extensions_vector,
104                      extensions_string,
105                      boost::is_any_of("\t "),
106                      boost::token_compress_on);
107         return extensions_vector;
108     }
109 
110     /// Returns \c true if the platform supports the extension with
111     /// \p name.
supports_extension(const std::string & name) const112     bool supports_extension(const std::string &name) const
113     {
114         const std::vector<std::string> extensions = this->extensions();
115 
116         return std::find(
117             extensions.begin(), extensions.end(), name) != extensions.end();
118     }
119 
120     /// Returns a list of devices on the platform.
devices(cl_device_type type=CL_DEVICE_TYPE_ALL) const121     std::vector<device> devices(cl_device_type type = CL_DEVICE_TYPE_ALL) const
122     {
123         size_t count = device_count(type);
124         if(count == 0){
125             // no devices for this platform
126             return std::vector<device>();
127         }
128 
129         std::vector<cl_device_id> device_ids(count);
130         cl_int ret = clGetDeviceIDs(m_platform,
131                                     type,
132                                     static_cast<cl_uint>(count),
133                                     &device_ids[0],
134                                     0);
135         if(ret != CL_SUCCESS){
136             BOOST_THROW_EXCEPTION(opencl_error(ret));
137         }
138 
139         std::vector<device> devices;
140         for(cl_uint i = 0; i < count; i++){
141             devices.push_back(device(device_ids[i]));
142         }
143 
144         return devices;
145     }
146 
147     /// Returns the number of devices on the platform.
device_count(cl_device_type type=CL_DEVICE_TYPE_ALL) const148     size_t device_count(cl_device_type type = CL_DEVICE_TYPE_ALL) const
149     {
150         cl_uint count = 0;
151         cl_int ret = clGetDeviceIDs(m_platform, type, 0, 0, &count);
152         if(ret != CL_SUCCESS){
153             if(ret == CL_DEVICE_NOT_FOUND){
154                 // no devices for this platform
155                 return 0;
156             }
157             else {
158                 // something else went wrong
159                 BOOST_THROW_EXCEPTION(opencl_error(ret));
160             }
161         }
162 
163         return count;
164     }
165 
166     /// Returns information about the platform.
167     ///
168     /// \see_opencl_ref{clGetPlatformInfo}
169     template<class T>
get_info(cl_platform_info info) const170     T get_info(cl_platform_info info) const
171     {
172         return detail::get_object_info<T>(clGetPlatformInfo, m_platform, info);
173     }
174 
175     /// \overload
176     template<int Enum>
177     typename detail::get_object_info_type<platform, Enum>::type
178     get_info() const;
179 
180     /// Returns the address of the \p function_name extension
181     /// function. Returns \c 0 if \p function_name is invalid.
get_extension_function_address(const char * function_name) const182     void* get_extension_function_address(const char *function_name) const
183     {
184         #ifdef CL_VERSION_1_2
185         return clGetExtensionFunctionAddressForPlatform(m_platform,
186                                                         function_name);
187         #else
188         return clGetExtensionFunctionAddress(function_name);
189         #endif
190     }
191 
192     /// Requests that the platform unload any compiler resources.
unload_compiler()193     void unload_compiler()
194     {
195         #ifdef CL_VERSION_1_2
196         clUnloadPlatformCompiler(m_platform);
197         #else
198         clUnloadCompiler();
199         #endif
200     }
201 
202     /// Returns \c true if the platform is the same at \p other.
operator ==(const platform & other) const203     bool operator==(const platform &other) const
204     {
205         return m_platform == other.m_platform;
206     }
207 
208     /// Returns \c true if the platform is different from \p other.
operator !=(const platform & other) const209     bool operator!=(const platform &other) const
210     {
211         return m_platform != other.m_platform;
212     }
213 
214 private:
215     cl_platform_id m_platform;
216 };
217 
218 /// \internal_ define get_info() specializations for platform
219 BOOST_COMPUTE_DETAIL_DEFINE_GET_INFO_SPECIALIZATIONS(platform,
220     ((std::string, CL_PLATFORM_PROFILE))
221     ((std::string, CL_PLATFORM_VERSION))
222     ((std::string, CL_PLATFORM_NAME))
223     ((std::string, CL_PLATFORM_VENDOR))
224     ((std::string, CL_PLATFORM_EXTENSIONS))
225 )
226 
platform() const227 inline boost::compute::platform device::platform() const
228 {
229     return boost::compute::platform(get_info<CL_DEVICE_PLATFORM>());
230 }
231 
232 } // end compute namespace
233 } // end boost namespace
234 
235 #endif // BOOST_COMPUTE_PLATFORM_HPP
236