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 namespace {
31 std::string
supported_il_versions_as_string(const device & dev)32 supported_il_versions_as_string(const device &dev) {
33 std::string il_versions_string;
34
35 for (const auto &il_version : dev.supported_il_versions()) {
36 if (!il_versions_string.empty())
37 il_versions_string += " ";
38
39 il_versions_string += std::string(il_version.name) + "_" +
40 std::to_string(CL_VERSION_MAJOR(il_version.version)) + "." +
41 std::to_string(CL_VERSION_MINOR(il_version.version));
42 }
43 return il_versions_string;
44 }
45 }
46
47 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)48 clGetDeviceIDs(cl_platform_id d_platform, cl_device_type device_type,
49 cl_uint num_entries, cl_device_id *rd_devices,
50 cl_uint *rnum_devices) try {
51 auto &platform = obj(d_platform);
52 std::vector<cl_device_id> d_devs;
53
54 if ((!num_entries && rd_devices) ||
55 (!rnum_devices && !rd_devices))
56 throw error(CL_INVALID_VALUE);
57
58 // Collect matching devices
59 for (device &dev : platform) {
60 if (((device_type & CL_DEVICE_TYPE_DEFAULT) &&
61 dev == platform.front()) ||
62 (device_type & dev.type()))
63 d_devs.push_back(desc(dev));
64 }
65
66 if (d_devs.empty())
67 throw error(CL_DEVICE_NOT_FOUND);
68
69 // ...and return the requested data.
70 if (rnum_devices)
71 *rnum_devices = d_devs.size();
72 if (rd_devices)
73 copy(range(d_devs.begin(),
74 std::min((unsigned)d_devs.size(), num_entries)),
75 rd_devices);
76
77 return CL_SUCCESS;
78
79 } catch (error &e) {
80 return e.get();
81 }
82
83 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)84 clCreateSubDevices(cl_device_id d_dev,
85 const cl_device_partition_property *props,
86 cl_uint num_devs, cl_device_id *rd_devs,
87 cl_uint *rnum_devs) {
88 // There are no currently supported partitioning schemes.
89 return CL_INVALID_VALUE;
90 }
91
92 CLOVER_API cl_int
clRetainDevice(cl_device_id d_dev)93 clRetainDevice(cl_device_id d_dev) try {
94 obj(d_dev);
95
96 // The reference count doesn't change for root devices.
97 return CL_SUCCESS;
98
99 } catch (error &e) {
100 return e.get();
101 }
102
103 CLOVER_API cl_int
clReleaseDevice(cl_device_id d_dev)104 clReleaseDevice(cl_device_id d_dev) try {
105 obj(d_dev);
106
107 // The reference count doesn't change for root devices.
108 return CL_SUCCESS;
109
110 } catch (error &e) {
111 return e.get();
112 }
113
114 CLOVER_API cl_int
clGetDeviceInfo(cl_device_id d_dev,cl_device_info param,size_t size,void * r_buf,size_t * r_size)115 clGetDeviceInfo(cl_device_id d_dev, cl_device_info param,
116 size_t size, void *r_buf, size_t *r_size) try {
117 property_buffer buf { r_buf, size, r_size };
118 auto &dev = obj(d_dev);
119
120 switch (param) {
121 case CL_DEVICE_TYPE:
122 buf.as_scalar<cl_device_type>() = dev.type();
123 break;
124
125 case CL_DEVICE_VENDOR_ID:
126 buf.as_scalar<cl_uint>() = dev.vendor_id();
127 break;
128
129 case CL_DEVICE_MAX_COMPUTE_UNITS:
130 buf.as_scalar<cl_uint>() = dev.max_compute_units();
131 break;
132
133 case CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS:
134 buf.as_scalar<cl_uint>() = dev.max_block_size().size();
135 break;
136
137 case CL_DEVICE_MAX_WORK_ITEM_SIZES:
138 buf.as_vector<size_t>() = dev.max_block_size();
139 break;
140
141 case CL_DEVICE_MAX_WORK_GROUP_SIZE:
142 buf.as_scalar<size_t>() = dev.max_threads_per_block();
143 break;
144
145 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR:
146 buf.as_scalar<cl_uint>() = 16;
147 break;
148
149 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT:
150 buf.as_scalar<cl_uint>() = 8;
151 break;
152
153 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT:
154 buf.as_scalar<cl_uint>() = 4;
155 break;
156
157 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG:
158 buf.as_scalar<cl_uint>() = 2;
159 break;
160
161 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT:
162 buf.as_scalar<cl_uint>() = 4;
163 break;
164
165 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE:
166 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0;
167 break;
168
169 case CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF:
170 buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0;
171 break;
172
173 case CL_DEVICE_MAX_CLOCK_FREQUENCY:
174 buf.as_scalar<cl_uint>() = dev.max_clock_frequency();
175 break;
176
177 case CL_DEVICE_ADDRESS_BITS:
178 buf.as_scalar<cl_uint>() = dev.address_bits();
179 break;
180
181 case CL_DEVICE_MAX_READ_IMAGE_ARGS:
182 buf.as_scalar<cl_uint>() = dev.max_images_read();
183 break;
184
185 case CL_DEVICE_MAX_WRITE_IMAGE_ARGS:
186 buf.as_scalar<cl_uint>() = dev.max_images_write();
187 break;
188
189 case CL_DEVICE_MAX_MEM_ALLOC_SIZE:
190 buf.as_scalar<cl_ulong>() = dev.max_mem_alloc_size();
191 break;
192
193 case CL_DEVICE_IMAGE2D_MAX_WIDTH:
194 case CL_DEVICE_IMAGE2D_MAX_HEIGHT:
195 buf.as_scalar<size_t>() = dev.max_image_size();
196 break;
197
198 case CL_DEVICE_IMAGE3D_MAX_WIDTH:
199 case CL_DEVICE_IMAGE3D_MAX_HEIGHT:
200 case CL_DEVICE_IMAGE3D_MAX_DEPTH:
201 buf.as_scalar<size_t>() = dev.max_image_size_3d();
202 break;
203
204 case CL_DEVICE_IMAGE_MAX_BUFFER_SIZE:
205 buf.as_scalar<size_t>() = dev.max_image_buffer_size();
206 break;
207
208 case CL_DEVICE_IMAGE_MAX_ARRAY_SIZE:
209 buf.as_scalar<size_t>() = dev.max_image_array_number();
210 break;
211
212 case CL_DEVICE_IMAGE_SUPPORT:
213 buf.as_scalar<cl_bool>() = dev.image_support();
214 break;
215
216 case CL_DEVICE_MAX_PARAMETER_SIZE:
217 buf.as_scalar<size_t>() = dev.max_mem_input();
218 break;
219
220 case CL_DEVICE_MAX_SAMPLERS:
221 buf.as_scalar<cl_uint>() = dev.max_samplers();
222 break;
223
224 case CL_DEVICE_MEM_BASE_ADDR_ALIGN:
225 buf.as_scalar<cl_uint>() = 8 * dev.mem_base_addr_align();
226 break;
227
228 case CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE:
229 buf.as_scalar<cl_uint>() = 128;
230 break;
231
232 case CL_DEVICE_HALF_FP_CONFIG:
233 // This is the "mandated minimum half precision floating-point
234 // capability" for OpenCL 1.x.
235 buf.as_scalar<cl_device_fp_config>() =
236 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
237 break;
238
239 case CL_DEVICE_SINGLE_FP_CONFIG:
240 // This is the "mandated minimum single precision floating-point
241 // capability" for OpenCL 1.1. In OpenCL 1.2, nothing is required for
242 // custom devices.
243 buf.as_scalar<cl_device_fp_config>() =
244 CL_FP_INF_NAN | CL_FP_ROUND_TO_NEAREST;
245 break;
246
247 case CL_DEVICE_DOUBLE_FP_CONFIG:
248 if (dev.has_doubles())
249 // This is the "mandated minimum double precision floating-point
250 // capability"
251 buf.as_scalar<cl_device_fp_config>() =
252 CL_FP_FMA
253 | CL_FP_ROUND_TO_NEAREST
254 | CL_FP_ROUND_TO_ZERO
255 | CL_FP_ROUND_TO_INF
256 | CL_FP_INF_NAN
257 | CL_FP_DENORM;
258 else
259 buf.as_scalar<cl_device_fp_config>() = 0;
260 break;
261
262 case CL_DEVICE_GLOBAL_MEM_CACHE_TYPE:
263 buf.as_scalar<cl_device_mem_cache_type>() = CL_NONE;
264 break;
265
266 case CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE:
267 buf.as_scalar<cl_uint>() = 0;
268 break;
269
270 case CL_DEVICE_GLOBAL_MEM_CACHE_SIZE:
271 buf.as_scalar<cl_ulong>() = 0;
272 break;
273
274 case CL_DEVICE_GLOBAL_MEM_SIZE:
275 buf.as_scalar<cl_ulong>() = dev.max_mem_global();
276 break;
277
278 case CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE:
279 buf.as_scalar<cl_ulong>() = dev.max_const_buffer_size();
280 break;
281
282 case CL_DEVICE_MAX_CONSTANT_ARGS:
283 buf.as_scalar<cl_uint>() = dev.max_const_buffers();
284 break;
285
286 case CL_DEVICE_LOCAL_MEM_TYPE:
287 buf.as_scalar<cl_device_local_mem_type>() = CL_LOCAL;
288 break;
289
290 case CL_DEVICE_LOCAL_MEM_SIZE:
291 buf.as_scalar<cl_ulong>() = dev.max_mem_local();
292 break;
293
294 case CL_DEVICE_ERROR_CORRECTION_SUPPORT:
295 buf.as_scalar<cl_bool>() = CL_FALSE;
296 break;
297
298 case CL_DEVICE_PROFILING_TIMER_RESOLUTION:
299 buf.as_scalar<size_t>() = 0;
300 break;
301
302 case CL_DEVICE_ENDIAN_LITTLE:
303 buf.as_scalar<cl_bool>() = (dev.endianness() == PIPE_ENDIAN_LITTLE);
304 break;
305
306 case CL_DEVICE_AVAILABLE:
307 case CL_DEVICE_COMPILER_AVAILABLE:
308 case CL_DEVICE_LINKER_AVAILABLE:
309 buf.as_scalar<cl_bool>() = CL_TRUE;
310 break;
311
312 case CL_DEVICE_EXECUTION_CAPABILITIES:
313 buf.as_scalar<cl_device_exec_capabilities>() = CL_EXEC_KERNEL;
314 break;
315
316 case CL_DEVICE_QUEUE_PROPERTIES:
317 buf.as_scalar<cl_command_queue_properties>() = CL_QUEUE_PROFILING_ENABLE;
318 break;
319
320 case CL_DEVICE_BUILT_IN_KERNELS:
321 buf.as_string() = "";
322 break;
323
324 case CL_DEVICE_NAME:
325 buf.as_string() = dev.device_name();
326 break;
327
328 case CL_DEVICE_VENDOR:
329 buf.as_string() = dev.vendor_name();
330 break;
331
332 case CL_DRIVER_VERSION:
333 buf.as_string() = PACKAGE_VERSION;
334 break;
335
336 case CL_DEVICE_PROFILE:
337 buf.as_string() = "FULL_PROFILE";
338 break;
339
340 case CL_DEVICE_VERSION:
341 buf.as_string() = "OpenCL " + dev.device_version_as_string() + " Mesa " PACKAGE_VERSION MESA_GIT_SHA1;
342 break;
343
344 case CL_DEVICE_EXTENSIONS:
345 buf.as_string() = dev.supported_extensions_as_string();
346 break;
347
348 case CL_DEVICE_PLATFORM:
349 buf.as_scalar<cl_platform_id>() = desc(dev.platform);
350 break;
351
352 case CL_DEVICE_HOST_UNIFIED_MEMORY:
353 buf.as_scalar<cl_bool>() = dev.has_unified_memory();
354 break;
355
356 case CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR:
357 buf.as_scalar<cl_uint>() = 16;
358 break;
359
360 case CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT:
361 buf.as_scalar<cl_uint>() = 8;
362 break;
363
364 case CL_DEVICE_NATIVE_VECTOR_WIDTH_INT:
365 buf.as_scalar<cl_uint>() = 4;
366 break;
367
368 case CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG:
369 buf.as_scalar<cl_uint>() = 2;
370 break;
371
372 case CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT:
373 buf.as_scalar<cl_uint>() = 4;
374 break;
375
376 case CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE:
377 buf.as_scalar<cl_uint>() = dev.has_doubles() ? 2 : 0;
378 break;
379
380 case CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF:
381 buf.as_scalar<cl_uint>() = dev.has_halves() ? 8 : 0;
382 break;
383
384 case CL_DEVICE_OPENCL_C_VERSION:
385 buf.as_string() = "OpenCL C " + dev.device_clc_version_as_string() + " ";
386 break;
387
388 case CL_DEVICE_PRINTF_BUFFER_SIZE:
389 buf.as_scalar<size_t>() = dev.max_printf_buffer_size();
390 break;
391
392 case CL_DEVICE_PREFERRED_INTEROP_USER_SYNC:
393 buf.as_scalar<cl_bool>() = CL_TRUE;
394 break;
395
396 case CL_DEVICE_PARENT_DEVICE:
397 buf.as_scalar<cl_device_id>() = NULL;
398 break;
399
400 case CL_DEVICE_PARTITION_MAX_SUB_DEVICES:
401 buf.as_scalar<cl_uint>() = 0;
402 break;
403
404 case CL_DEVICE_PARTITION_PROPERTIES:
405 buf.as_vector<cl_device_partition_property>() =
406 desc(property_list<cl_device_partition_property>());
407 break;
408
409 case CL_DEVICE_PARTITION_AFFINITY_DOMAIN:
410 buf.as_scalar<cl_device_affinity_domain>() = 0;
411 break;
412
413 case CL_DEVICE_PARTITION_TYPE:
414 buf.as_vector<cl_device_partition_property>() =
415 desc(property_list<cl_device_partition_property>());
416 break;
417
418 case CL_DEVICE_REFERENCE_COUNT:
419 buf.as_scalar<cl_uint>() = 1;
420 break;
421
422 case CL_DEVICE_SVM_CAPABILITIES:
423 case CL_DEVICE_SVM_CAPABILITIES_ARM:
424 buf.as_scalar<cl_device_svm_capabilities>() = dev.svm_support();
425 break;
426
427 case CL_DEVICE_NUMERIC_VERSION:
428 buf.as_scalar<cl_version>() = dev.device_version();
429 break;
430
431 case CL_DEVICE_OPENCL_C_NUMERIC_VERSION_KHR:
432 buf.as_scalar<cl_version>() = dev.device_clc_version(true);
433 break;
434
435 case CL_DEVICE_OPENCL_C_ALL_VERSIONS:
436 buf.as_vector<cl_name_version>() = dev.opencl_c_all_versions();
437 break;
438
439 case CL_DEVICE_EXTENSIONS_WITH_VERSION:
440 buf.as_vector<cl_name_version>() = dev.supported_extensions();
441 break;
442
443 case CL_DEVICE_OPENCL_C_FEATURES:
444 buf.as_vector<cl_name_version>() = dev.opencl_c_features();
445 break;
446
447 case CL_DEVICE_IL_VERSION:
448 if (dev.supported_extensions_as_string().find("cl_khr_il_program") == std::string::npos)
449 throw error(CL_INVALID_VALUE);
450 buf.as_string() = supported_il_versions_as_string(dev);
451 break;
452
453 case CL_DEVICE_ILS_WITH_VERSION:
454 buf.as_vector<cl_name_version>() = dev.supported_il_versions();
455 break;
456
457 case CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION:
458 buf.as_vector<cl_name_version>() = std::vector<cl_name_version>{};
459 break;
460
461 case CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS:
462 case CL_DEVICE_IMAGE_PITCH_ALIGNMENT:
463 case CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT:
464 case CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT:
465 case CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT:
466 case CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT:
467 case CL_DEVICE_MAX_NUM_SUB_GROUPS:
468 case CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE:
469 case CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE:
470 case CL_DEVICE_MAX_ON_DEVICE_QUEUES:
471 case CL_DEVICE_MAX_ON_DEVICE_EVENTS:
472 case CL_DEVICE_MAX_PIPE_ARGS:
473 case CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS:
474 case CL_DEVICE_PIPE_MAX_PACKET_SIZE:
475 buf.as_scalar<cl_uint>() = 0;
476 break;
477
478 case CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE:
479 case CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE:
480 buf.as_scalar<size_t>() = 0;
481 break;
482
483 case CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS:
484 case CL_DEVICE_NON_UNIFORM_WORK_GROUP_SUPPORT:
485 case CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT:
486 case CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT:
487 case CL_DEVICE_PIPE_SUPPORT:
488 buf.as_scalar<cl_bool>() = CL_FALSE;
489 break;
490
491 case CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES:
492 buf.as_scalar<cl_command_queue_properties>() = 0;
493 break;
494
495 case CL_DEVICE_ATOMIC_MEMORY_CAPABILITIES:
496 buf.as_scalar<cl_device_atomic_capabilities>() = (CL_DEVICE_ATOMIC_ORDER_RELAXED |
497 CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP);
498 break;
499 case CL_DEVICE_ATOMIC_FENCE_CAPABILITIES:
500 buf.as_scalar<cl_device_atomic_capabilities>() = (CL_DEVICE_ATOMIC_ORDER_RELAXED |
501 CL_DEVICE_ATOMIC_ORDER_ACQ_REL |
502 CL_DEVICE_ATOMIC_SCOPE_WORK_GROUP);
503 break;
504
505 case CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES:
506 buf.as_scalar<cl_device_device_enqueue_capabilities>() = 0;
507 break;
508
509 case CL_DEVICE_PREFERRED_WORK_GROUP_SIZE_MULTIPLE:
510 buf.as_scalar<size_t>() = 1;
511 break;
512
513 case CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED:
514 buf.as_string() = "";
515 break;
516
517 default:
518 throw error(CL_INVALID_VALUE);
519 }
520
521 return CL_SUCCESS;
522
523 } catch (error &e) {
524 return e.get();
525 }
526