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