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