• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 //
2 // Copyright 2012 Francisco Jerez
3 //
4 // Permission is hereby granted, free of charge, to any person obtaining a
5 // copy of this software and associated documentation files (the "Software"),
6 // to deal in the Software without restriction, including without limitation
7 // the rights to use, copy, modify, merge, publish, distribute, sublicense,
8 // and/or sell copies of the Software, and to permit persons to whom the
9 // Software is furnished to do so, subject to the following conditions:
10 //
11 // The above copyright notice and this permission notice shall be included in
12 // all copies or substantial portions of the Software.
13 //
14 // THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
15 // IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
16 // FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.  IN NO EVENT SHALL
17 // THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR
18 // OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE,
19 // ARISING FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
20 // OTHER DEALINGS IN THE SOFTWARE.
21 //
22 
23 #include "api/util.hpp"
24 #include "core/platform.hpp"
25 #include "core/device.hpp"
26 #include "git_sha1.h"
27 
28 using namespace clover;
29 
30 CLOVER_API cl_int
clGetDeviceIDs(cl_platform_id d_platform,cl_device_type device_type,cl_uint num_entries,cl_device_id * rd_devices,cl_uint * rnum_devices)31 clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type,
32                cl_uint num_entries, cl_device_id *rd_devices,
33                cl_uint *rnum_devices) try {
34    auto &platform = obj(d_platform);
35    std::vector<cl_device_id> d_devs;
36 
37    if ((!num_entries && rd_devices) ||
38        (!rnum_devices && !rd_devices))
39       throw error(CL_INVALID_VALUE);
40 
41    // Collect matching devices
42    for (device &dev : platform) {
43       if (((device_type & CL_DEVICE_TYPE_DEFAULT) &&
44            dev == platform.front()) ||
45           (device_type & dev.type()))
46          d_devs.push_back(desc(dev));
47    }
48 
49    if (d_devs.empty())
50       throw error(CL_DEVICE_NOT_FOUND);
51 
52    // ...and return the requested data.
53    if (rnum_devices)
54       *rnum_devices = d_devs.size();
55    if (rd_devices)
56       copy(range(d_devs.begin(),
57                  std::min((unsigned)d_devs.size(), num_entries)),
58            rd_devices);
59 
60    return CL_SUCCESS;
61 
62 } catch (error &e) {
63    return e.get();
64 }
65 
66 CLOVER_API cl_int
clCreateSubDevices(cl_device_id d_dev,const cl_device_partition_property * props,cl_uint num_devs,cl_device_id * rd_devs,cl_uint * rnum_devs)67 clCreateSubDevices(cl_device_id d_dev,
68                    const cl_device_partition_property *props,
69                    cl_uint num_devs, cl_device_id *rd_devs,
70                    cl_uint *rnum_devs) {
71    // There are no currently supported partitioning schemes.
72    return CL_INVALID_VALUE;
73 }
74 
75 CLOVER_API cl_int
clRetainDevice(cl_device_id d_dev)76 clRetainDevice(cl_device_id d_dev) try {
77    obj(d_dev);
78 
79    // The reference count doesn't change for root devices.
80    return CL_SUCCESS;
81 
82 } catch (error &e) {
83    return e.get();
84 }
85 
86 CLOVER_API cl_int
clReleaseDevice(cl_device_id d_dev)87 clReleaseDevice(cl_device_id d_dev) try {
88    obj(d_dev);
89 
90    // The reference count doesn't change for root devices.
91    return CL_SUCCESS;
92 
93 } catch (error &e) {
94    return e.get();
95 }
96 
97 CLOVER_API cl_int
clGetDeviceInfo(cl_device_id d_dev,cl_device_info param,size_t size,void * r_buf,size_t * r_size)98 clGetDeviceInfo(cl_device_id d_dev, cl_device_info param,
99                 size_t size, void *r_buf, size_t *r_size) try {
100    property_buffer buf { r_buf, size, r_size };
101    auto &dev = obj(d_dev);
102 
103    switch (param) {
104    case CL_DEVICE_TYPE:
105       buf.as_scalar<cl_device_type>() = dev.type();
106       break;
107 
108    case CL_DEVICE_VENDOR_ID:
109       buf.as_scalar<cl_uint>() = dev.vendor_id();
110       break;
111 
112    case CL_DEVICE_MAX_COMPUTE_UNITS:
113       buf.as_scalar<cl_uint>() = dev.max_compute_units();
114       break;
115 
116    case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
117       buf.as_scalar<cl_uint>() = dev.max_block_size().size();
118       break;
119 
120    case CL_DEVICE_MAX_WORK_ITEM_SIZES:
121       buf.as_vector<size_t>() = dev.max_block_size();
122       break;
123 
124    case CL_DEVICE_MAX_WORK_GROUP_SIZE:
125       buf.as_scalar<size_t>() = dev.max_threads_per_block();
126       break;
127 
128    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
129       buf.as_scalar<cl_uint>() = 16;
130       break;
131 
132    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
133       buf.as_scalar<cl_uint>() = 8;
134       break;
135 
136    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
137       buf.as_scalar<cl_uint>() = 4;
138       break;
139 
140    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
141       buf.as_scalar<cl_uint>() = 2;
142       break;
143 
144    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
145       buf.as_scalar<cl_uint>() = 4;
146       break;
147 
148    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
149       buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0;
150       break;
151 
152    case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
153       buf.as_scalar<cl_uint>() = 0;
154       break;
155 
156    case CL_DEVICE_MAX_CLOCK_FREQUENCY:
157       buf.as_scalar<cl_uint>() = dev.max_clock_frequency();
158       break;
159 
160    case CL_DEVICE_ADDRESS_BITS:
161       buf.as_scalar<cl_uint>() = dev.address_bits();
162       break;
163 
164    case CL_DEVICE_MAX_READ_IMAGE_ARGS:
165       buf.as_scalar<cl_uint>() = dev.max_images_read();
166       break;
167 
168    case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
169       buf.as_scalar<cl_uint>() = dev.max_images_write();
170       break;
171 
172    case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
173       buf.as_scalar<cl_ulong>() = dev.max_mem_alloc_size();
174       break;
175 
176    case CL_DEVICE_IMAGE2D_MAX_WIDTH:
177    case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
178       buf.as_scalar<size_t>() = 1 << dev.max_image_levels_2d();
179       break;
180 
181    case CL_DEVICE_IMAGE3D_MAX_WIDTH:
182    case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
183    case CL_DEVICE_IMAGE3D_MAX_DEPTH:
184       buf.as_scalar<size_t>() = 1 << dev.max_image_levels_3d();
185       break;
186 
187    case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE:
188       buf.as_scalar<size_t>() = dev.max_image_buffer_size();
189       break;
190 
191    case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE:
192       buf.as_scalar<size_t>() = dev.max_image_array_number();
193       break;
194 
195    case CL_DEVICE_IMAGE_SUPPORT:
196       buf.as_scalar<cl_bool>() = dev.image_support();
197       break;
198 
199    case CL_DEVICE_MAX_PARAMETER_SIZE:
200       buf.as_scalar<size_t>() = dev.max_mem_input();
201       break;
202 
203    case CL_DEVICE_MAX_SAMPLERS:
204       buf.as_scalar<cl_uint>() = dev.max_samplers();
205       break;
206 
207    case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
208       buf.as_scalar<cl_uint>() = 128 * 8;
209       break;
210 
211    case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
212       buf.as_scalar<cl_uint>() = 128;
213       break;
214 
215    case CL_DEVICE_SINGLE_FP_CONFIG:
216       // This is the "mandated minimum single precision floating-point
217       // capability" for OpenCL 1.1.  In OpenCL 1.2, nothing is required for
218       // custom devices.
219       buf.as_scalar<cl_device_fp_config>() =
220          CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
221       break;
222 
223    case CL_DEVICE_DOUBLE_FP_CONFIG:
224       if (dev.has_doubles())
225          // This is the "mandated minimum double precision floating-point
226          // capability"
227          buf.as_scalar<cl_device_fp_config>() =
228                CL_FP_FMA
229              | CL_FP_ROUND_TO_NEAREST
230              | CL_FP_ROUND_TO_ZERO
231              | CL_FP_ROUND_TO_INF
232              | CL_FP_INF_NAN
233              | CL_FP_DENORM;
234       else
235          buf.as_scalar<cl_device_fp_config>() = 0;
236       break;
237 
238    case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
239       buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE;
240       break;
241 
242    case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
243       buf.as_scalar<cl_uint>() = 0;
244       break;
245 
246    case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
247       buf.as_scalar<cl_ulong>() = 0;
248       break;
249 
250    case CL_DEVICE_GLOBAL_MEM_SIZE:
251       buf.as_scalar<cl_ulong>() = dev.max_mem_global();
252       break;
253 
254    case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
255       buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size();
256       break;
257 
258    case CL_DEVICE_MAX_CONSTANT_ARGS:
259       buf.as_scalar<cl_uint>() = dev.max_const_buffers();
260       break;
261 
262    case CL_DEVICE_LOCAL_MEM_TYPE:
263       buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL;
264       break;
265 
266    case CL_DEVICE_LOCAL_MEM_SIZE:
267       buf.as_scalar<cl_ulong>() = dev.max_mem_local();
268       break;
269 
270    case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
271       buf.as_scalar<cl_bool>() = CL_FALSE;
272       break;
273 
274    case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
275       buf.as_scalar<size_t>() = 0;
276       break;
277 
278    case CL_DEVICE_ENDIAN_LITTLE:
279       buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE);
280       break;
281 
282    case CL_DEVICE_AVAILABLE:
283    case CL_DEVICE_COMPILER_AVAILABLE:
284    case CL_DEVICE_LINKER_AVAILABLE:
285       buf.as_scalar<cl_bool>() = CL_TRUE;
286       break;
287 
288    case CL_DEVICE_EXECUTION_CAPABILITIES:
289       buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL;
290       break;
291 
292    case CL_DEVICE_QUEUE_PROPERTIES:
293       buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE;
294       break;
295 
296    case CL_DEVICE_BUILT_IN_KERNELS:
297       buf.as_string() = "";
298       break;
299 
300    case CL_DEVICE_NAME:
301       buf.as_string() = dev.device_name();
302       break;
303 
304    case CL_DEVICE_VENDOR:
305       buf.as_string() = dev.vendor_name();
306       break;
307 
308    case CL_DRIVER_VERSION:
309       buf.as_string() = PACKAGE_VERSION;
310       break;
311 
312    case CL_DEVICE_PROFILE:
313       buf.as_string() = "FULL_PROFILE";
314       break;
315 
316    case CL_DEVICE_VERSION:
317       buf.as_string() = "OpenCL 1.1 Mesa " PACKAGE_VERSION
318 #ifdef MESA_GIT_SHA1
319                         " (" MESA_GIT_SHA1 ")"
320 #endif
321 			;
322       break;
323 
324    case CL_DEVICE_EXTENSIONS:
325       buf.as_string() =
326          "cl_khr_global_int32_base_atomics"
327          " cl_khr_global_int32_extended_atomics"
328          " cl_khr_local_int32_base_atomics"
329          " cl_khr_local_int32_extended_atomics"
330          " cl_khr_byte_addressable_store"
331          + std::string(dev.has_doubles() ? " cl_khr_fp64" : "");
332       break;
333 
334    case CL_DEVICE_PLATFORM:
335       buf.as_scalar<cl_platform_id>() = desc(dev.platform);
336       break;
337 
338    case CL_DEVICE_HOST_UNIFIED_MEMORY:
339       buf.as_scalar<cl_bool>() = CL_TRUE;
340       break;
341 
342    case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
343       buf.as_scalar<cl_uint>() = 16;
344       break;
345 
346    case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
347       buf.as_scalar<cl_uint>() = 8;
348       break;
349 
350    case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
351       buf.as_scalar<cl_uint>() = 4;
352       break;
353 
354    case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
355       buf.as_scalar<cl_uint>() = 2;
356       break;
357 
358    case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
359       buf.as_scalar<cl_uint>() = 4;
360       break;
361 
362    case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
363       buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0;
364       break;
365 
366    case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
367       buf.as_scalar<cl_uint>() = 0;
368       break;
369 
370    case CL_DEVICE_OPENCL_C_VERSION:
371       buf.as_string() = "OpenCL C 1.1 ";
372       break;
373 
374    case CL_DEVICE_PRINTF_BUFFER_SIZE:
375       // Per the spec, the minimum value for the FULL profile is 1 MB.
376       // However, clover is not ready yet to support it
377       buf.as_scalar<size_t>() = 0 /* 1024 */;
378       break;
379 
380    case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC:
381       buf.as_scalar<cl_bool>() = CL_TRUE;
382       break;
383 
384    case CL_DEVICE_PARENT_DEVICE:
385       buf.as_scalar<cl_device_id>() = NULL;
386       break;
387 
388    case CL_DEVICE_PARTITION_MAX_SUB_DEVICES:
389       buf.as_scalar<cl_uint>() = 0;
390       break;
391 
392    case CL_DEVICE_PARTITION_PROPERTIES:
393       buf.as_vector<cl_device_partition_property>() =
394          desc(property_list<cl_device_partition_property>());
395       break;
396 
397    case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
398       buf.as_scalar<cl_device_affinity_domain>() = 0;
399       break;
400 
401    case CL_DEVICE_PARTITION_TYPE:
402       buf.as_vector<cl_device_partition_property>() =
403          desc(property_list<cl_device_partition_property>());
404       break;
405 
406    case CL_DEVICE_REFERENCE_COUNT:
407       buf.as_scalar<cl_uint>() = 1;
408       break;
409 
410    default:
411       throw error(CL_INVALID_VALUE);
412    }
413 
414    return CL_SUCCESS;
415 
416 } catch (error &e) {
417    return e.get();
418 }
419