• 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>() = dev.has_halves() ? 8 : 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>() = 8 * dev.mem_base_addr_align();
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_HALF_FP_CONFIG:
216       // This is the "mandated minimum half precision floating-point
217       // capability" for OpenCL 1.x.
218       buf.as_scalar<cl_device_fp_config>() =
219          CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
220       break;
221 
222    case CL_DEVICE_SINGLE_FP_CONFIG:
223       // This is the "mandated minimum single precision floating-point
224       // capability" for OpenCL 1.1.  In OpenCL 1.2, nothing is required for
225       // custom devices.
226       buf.as_scalar<cl_device_fp_config>() =
227          CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
228       break;
229 
230    case CL_DEVICE_DOUBLE_FP_CONFIG:
231       if (dev.has_doubles())
232          // This is the "mandated minimum double precision floating-point
233          // capability"
234          buf.as_scalar<cl_device_fp_config>() =
235                CL_FP_FMA
236              | CL_FP_ROUND_TO_NEAREST
237              | CL_FP_ROUND_TO_ZERO
238              | CL_FP_ROUND_TO_INF
239              | CL_FP_INF_NAN
240              | CL_FP_DENORM;
241       else
242          buf.as_scalar<cl_device_fp_config>() = 0;
243       break;
244 
245    case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
246       buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE;
247       break;
248 
249    case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
250       buf.as_scalar<cl_uint>() = 0;
251       break;
252 
253    case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
254       buf.as_scalar<cl_ulong>() = 0;
255       break;
256 
257    case CL_DEVICE_GLOBAL_MEM_SIZE:
258       buf.as_scalar<cl_ulong>() = dev.max_mem_global();
259       break;
260 
261    case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
262       buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size();
263       break;
264 
265    case CL_DEVICE_MAX_CONSTANT_ARGS:
266       buf.as_scalar<cl_uint>() = dev.max_const_buffers();
267       break;
268 
269    case CL_DEVICE_LOCAL_MEM_TYPE:
270       buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL;
271       break;
272 
273    case CL_DEVICE_LOCAL_MEM_SIZE:
274       buf.as_scalar<cl_ulong>() = dev.max_mem_local();
275       break;
276 
277    case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
278       buf.as_scalar<cl_bool>() = CL_FALSE;
279       break;
280 
281    case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
282       buf.as_scalar<size_t>() = 0;
283       break;
284 
285    case CL_DEVICE_ENDIAN_LITTLE:
286       buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE);
287       break;
288 
289    case CL_DEVICE_AVAILABLE:
290    case CL_DEVICE_COMPILER_AVAILABLE:
291    case CL_DEVICE_LINKER_AVAILABLE:
292       buf.as_scalar<cl_bool>() = CL_TRUE;
293       break;
294 
295    case CL_DEVICE_EXECUTION_CAPABILITIES:
296       buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL;
297       break;
298 
299    case CL_DEVICE_QUEUE_PROPERTIES:
300       buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE;
301       break;
302 
303    case CL_DEVICE_BUILT_IN_KERNELS:
304       buf.as_string() = "";
305       break;
306 
307    case CL_DEVICE_NAME:
308       buf.as_string() = dev.device_name();
309       break;
310 
311    case CL_DEVICE_VENDOR:
312       buf.as_string() = dev.vendor_name();
313       break;
314 
315    case CL_DRIVER_VERSION:
316       buf.as_string() = PACKAGE_VERSION;
317       break;
318 
319    case CL_DEVICE_PROFILE:
320       buf.as_string() = "FULL_PROFILE";
321       break;
322 
323    case CL_DEVICE_VERSION:
324       buf.as_string() = "OpenCL " + dev.device_version() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1;
325       break;
326 
327    case CL_DEVICE_EXTENSIONS:
328       buf.as_string() = dev.supported_extensions();
329       break;
330 
331    case CL_DEVICE_PLATFORM:
332       buf.as_scalar<cl_platform_id>() = desc(dev.platform);
333       break;
334 
335    case CL_DEVICE_HOST_UNIFIED_MEMORY:
336       buf.as_scalar<cl_bool>() = dev.has_unified_memory();
337       break;
338 
339    case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
340       buf.as_scalar<cl_uint>() = 16;
341       break;
342 
343    case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
344       buf.as_scalar<cl_uint>() = 8;
345       break;
346 
347    case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
348       buf.as_scalar<cl_uint>() = 4;
349       break;
350 
351    case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
352       buf.as_scalar<cl_uint>() = 2;
353       break;
354 
355    case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
356       buf.as_scalar<cl_uint>() = 4;
357       break;
358 
359    case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
360       buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0;
361       break;
362 
363    case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
364       buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0;
365       break;
366 
367    case CL_DEVICE_OPENCL_C_VERSION:
368       buf.as_string() = "OpenCL C " + dev.device_clc_version() + " ";
369       break;
370 
371    case CL_DEVICE_PRINTF_BUFFER_SIZE:
372       // Per the spec, the minimum value for the FULL profile is 1 MB.
373       // However, clover is not ready yet to support it
374       buf.as_scalar<size_t>() = 0 /* 1024 */;
375       break;
376 
377    case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC:
378       buf.as_scalar<cl_bool>() = CL_TRUE;
379       break;
380 
381    case CL_DEVICE_PARENT_DEVICE:
382       buf.as_scalar<cl_device_id>() = NULL;
383       break;
384 
385    case CL_DEVICE_PARTITION_MAX_SUB_DEVICES:
386       buf.as_scalar<cl_uint>() = 0;
387       break;
388 
389    case CL_DEVICE_PARTITION_PROPERTIES:
390       buf.as_vector<cl_device_partition_property>() =
391          desc(property_list<cl_device_partition_property>());
392       break;
393 
394    case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
395       buf.as_scalar<cl_device_affinity_domain>() = 0;
396       break;
397 
398    case CL_DEVICE_PARTITION_TYPE:
399       buf.as_vector<cl_device_partition_property>() =
400          desc(property_list<cl_device_partition_property>());
401       break;
402 
403    case CL_DEVICE_REFERENCE_COUNT:
404       buf.as_scalar<cl_uint>() = 1;
405       break;
406 
407    case CL_DEVICE_SVM_CAPABILITIES:
408    case CL_DEVICE_SVM_CAPABILITIES_ARM:
409       buf.as_scalar<cl_device_svm_capabilities>() = dev.svm_support();
410       break;
411 
412    default:
413       throw error(CL_INVALID_VALUE);
414    }
415 
416    return CL_SUCCESS;
417 
418 } catch (error &e) {
419    return e.get();
420 }
421