cf4ocl (C Framework for OpenCL)  v2.1.0
Object-oriented framework for developing and benchmarking OpenCL projects in C/C++
 All Data Structures Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
ccl_device_query.c
Go to the documentation of this file.
1 /*
2  * This file is part of cf4ocl (C Framework for OpenCL).
3  *
4  * cf4ocl is free software: you can redistribute it and/or modify
5  * it under the terms of the GNU Lesser General Public License as
6  * published by the Free Software Foundation, either version 3 of the
7  * License, or (at your option) any later version.
8  *
9  * cf4ocl is distributed in the hope that it will be useful,
10  * but WITHOUT ANY WARRANTY; without even the implied warranty of
11  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
12  * GNU Lesser General Public License for more details.
13  *
14  * You should have received a copy of the GNU Lesser General Public
15  * License along with cf4ocl. If not, see
16  * <http://www.gnu.org/licenses/>.
17  * */
18 
29 #include "ccl_device_query.h"
30 #include "_ccl_abstract_wrapper.h"
31 
37 static char* ccl_devquery_format_uint(CCLWrapperInfo* info,
38  char* out, size_t size, const char* units) {
39 
40  g_snprintf(out, (gulong) size, "%u %s", *((cl_uint*) info->value), units);
41  return out;
42 
43 }
44 
50 static char* ccl_devquery_format_hex(CCLWrapperInfo* info,
51  char* out, size_t size, const char* units) {
52 
53  GString* str = g_string_new("0x");
54  gboolean start = FALSE;
55  gchar val;
56 
57  for (gint i = (gint) info->size - 1; i >= 0 ; i--) {
58  val = ((cl_char*) info->value)[i];
59  if (val) start = TRUE;
60  if (start)
61  g_string_append_printf(str, "%.2x", val);
62  }
63  if (units && units[0])
64  g_string_append_printf(str, " %s", units);
65 
66  g_snprintf(out, (gulong) size, "%s", str->str);
67  g_string_free(str, TRUE);
68  return out;
69 
70 }
71 
77 static char* ccl_devquery_format_sizet(CCLWrapperInfo* info,
78  char* out, size_t size, const char* units) {
79 
80  g_snprintf(out, (gulong) size, "%lu %s", (gulong) *((size_t*) info->value), units);
81  return out;
82 
83 }
84 
91 #define ccl_devquery_format_bytes(spec) \
92  if (bytes < 1024) \
93  g_snprintf(out, (gulong) size, "%" spec " bytes", bytes); \
94  else if (bytes < 1048576) \
95  g_snprintf(out, (gulong) size, "%.1lf KiB (%" spec " bytes)", \
96  bytes / 1024.0, bytes); \
97  else if (bytes < 1073741824) \
98  g_snprintf(out, (gulong) size, "%.1lf MiB (%" spec " bytes)", \
99  bytes / (1024.0 * 1024), bytes); \
100  else \
101  g_snprintf(out, (gulong) size, "%.1lf GiB (%" spec " bytes)", \
102  bytes / (1024.0 * 1024 * 1024), bytes);
103 
109 static char* ccl_devquery_format_ulongbytes(CCLWrapperInfo* info,
110  char* out, size_t size, const char* units) {
111 
112  CCL_UNUSED(units);
113  unsigned long bytes = (unsigned long) *((cl_ulong*) info->value);
114  ccl_devquery_format_bytes("lu");
115  return out;
116 
117 }
118 
124 static char* ccl_devquery_format_uintbytes(CCLWrapperInfo* info,
125  char* out, size_t size, const char* units) {
126 
127  CCL_UNUSED(units);
128  unsigned int bytes = (unsigned int) *((cl_uint*) info->value);
129  ccl_devquery_format_bytes("u");
130  return out;
131 
132 }
133 
139 static char* ccl_devquery_format_sizetbytes(CCLWrapperInfo* info,
140  char* out, size_t size, const char* units) {
141 
142  CCL_UNUSED(units);
143  unsigned long bytes = (unsigned long) *((size_t*) info->value);
144  ccl_devquery_format_bytes("lu");
145  return out;
146 
147 }
148 
154 static char* ccl_devquery_format_sizetvec(CCLWrapperInfo* info,
155  char* out, size_t size, const char* units) {
156 
157  CCL_UNUSED(units);
158  GString* str = g_string_new("(");
159  size_t* vec = (size_t*) info->value;
160  guint count = (guint) (info->size / sizeof(gsize));
161 
162  for (guint i = 0; i < count; i++) {
163  if (i > 0) g_string_append(str, ", ");
164  g_string_append_printf(str, "%lu", (gulong) vec[i]);
165  }
166 
167  g_string_append(str, ")");
168 
169  g_snprintf(out, (gulong) size, "%s", str->str);
170  g_string_free(str, TRUE);
171  return out;
172 }
173 
179 static char* ccl_devquery_format_yesno(CCLWrapperInfo* info,
180  char* out, size_t size, const char* units) {
181 
182  CCL_UNUSED(units);
183  g_snprintf(out,
184  (gulong) size, "%s", *((cl_bool*)info->value) ? "Yes" : "No");
185  return out;
186 
187 }
188 
194 static char* ccl_devquery_format_char(CCLWrapperInfo* info,
195  char* out, size_t size, const char* units) {
196 
197  g_snprintf(out, (gulong) size, "%s %s", (gchar*)info->value, units);
198  return out;
199 
200 }
201 
207 static char* ccl_devquery_format_ptr(CCLWrapperInfo* info,
208  char* out, size_t size, const char* units) {
209 
210  CCL_UNUSED(units);
211  g_snprintf(out, (gulong) size, "%p", *((void**)info->value));
212  return out;
213 
214 }
215 
221 static char* ccl_devquery_format_type(CCLWrapperInfo* info,
222  char* out, size_t size, const char* units) {
223 
224  CCL_UNUSED(units);
225  g_snprintf(out, (gulong) size, "%s",
226  ccl_devquery_type2str(*((cl_device_type*) info->value)));
227  return out;
228 
229 }
230 
236 static char* ccl_devquery_format_fpconfig(CCLWrapperInfo* info,
237  char* out, size_t size, const char* units) {
238 
239  CCL_UNUSED(units);
240  cl_device_fp_config fpc = *((cl_device_fp_config*) info->value);
241  g_snprintf(out, (gulong) size, "%s%s%s%s%s%s%s",
242  fpc & CL_FP_DENORM ? "DENORM " : "",
243  fpc & CL_FP_INF_NAN ? "INF_NAN " : "",
244  fpc & CL_FP_ROUND_TO_NEAREST ? "ROUND_TO_NEAREST " : "",
245  fpc & CL_FP_ROUND_TO_ZERO ? "ROUND_TO_ZERO " : "",
246  fpc & CL_FP_ROUND_TO_INF ? "ROUND_TO_INF " : "",
247  fpc & CL_FP_FMA ? "FMA " : "",
248  fpc & CL_FP_SOFT_FLOAT ? "SOFT_FLOAT" : "");
249  return out;
250 
251 }
252 
258 static char* ccl_devquery_format_execcap(CCLWrapperInfo* info,
259  char* out, size_t size, const char* units) {
260 
261  CCL_UNUSED(units);
262  cl_device_exec_capabilities exc =
263  *((cl_device_exec_capabilities*) info->value);
264  g_snprintf(out, (gulong) size, "%s%s",
265  exc & CL_EXEC_KERNEL ? "KERNEL " : "",
266  exc & CL_EXEC_NATIVE_KERNEL ? "NATIVE_KERNEL " : "");
267  return out;
268 }
269 
274 static char* ccl_devquery_format_locmemtype(CCLWrapperInfo* info,
275  char* out, size_t size, const char* units) {
276 
277  CCL_UNUSED(units);
278  cl_device_local_mem_type lmt =
279  *((cl_device_local_mem_type*) info->value);
280  g_snprintf(out, (gulong) size, "%s%s%s",
281  lmt & CL_LOCAL ? "LOCAL" : "",
282  lmt & CL_GLOBAL ? "GLOBAL" : "",
283  lmt & CL_NONE ? "NONE" : "");
284  return out;
285 }
286 
292 static char* ccl_devquery_format_partprop(CCLWrapperInfo* info,
293  char* out, size_t size, const char* units) {
294 
295  CCL_UNUSED(units);
296  cl_device_partition_property* pp =
297  (cl_device_partition_property*) info->value;
298  GString* str = g_string_new("");
299  guint count = (guint) (info->size / sizeof(cl_device_partition_property));
300  for (guint i = 0; i < count; i++) {
301  switch (pp[i]) {
302  case CL_DEVICE_PARTITION_EQUALLY:
303  g_string_append_printf(str, "EQUALLY ");
304  break;
305  case CL_DEVICE_PARTITION_BY_COUNTS:
306  g_string_append_printf(str, "BY_COUNTS ");
307  break;
308  case CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN:
309  g_string_append_printf(str, "BY_AFFINITY_DOMAIN ");
310  break;
311  case CL_DEVICE_PARTITION_EQUALLY_EXT:
312  g_string_append_printf(str, "EQUALLY_EXT ");
313  break;
314  case CL_DEVICE_PARTITION_BY_COUNTS_EXT:
315  g_string_append_printf(str, "BY_COUNTS_EXT ");
316  break;
317  case CL_DEVICE_PARTITION_BY_NAMES_EXT:
318  g_string_append_printf(str, "BY_NAMES_EXT ");
319  break;
320  case CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN_EXT:
321  g_string_append_printf(str, "BY_AFFINITY_DOMAIN_EXT ");
322  break;
323  default:
324  g_string_append_printf(str, "UNKNOWN(0x%lx) ",
325  (unsigned long) pp[i]);
326  }
327  }
328  g_snprintf(out, (gulong) size, "%s", str->str);
329  g_string_free(str, TRUE);
330  return out;
331 
332 }
333 
340 static char* ccl_devquery_format_affdom(CCLWrapperInfo* info,
341  char* out, size_t size, const char* units) {
342 
343  CCL_UNUSED(units);
344  cl_device_affinity_domain ad =
345  *((cl_device_affinity_domain*) info->value);
346  g_snprintf(out, (gulong) size, "%s%s%s%s%s%s",
347  ad & CL_DEVICE_AFFINITY_DOMAIN_NUMA ? "NUMA " : "",
348  ad & CL_DEVICE_AFFINITY_DOMAIN_L4_CACHE ? "L4_CACHE " : "",
349  ad & CL_DEVICE_AFFINITY_DOMAIN_L3_CACHE ? "L3_CACHE " : "",
350  ad & CL_DEVICE_AFFINITY_DOMAIN_L2_CACHE ? "L2_CACHE " : "",
351  ad & CL_DEVICE_AFFINITY_DOMAIN_L1_CACHE ? "L1_CACHE " : "",
352  ad & CL_DEVICE_AFFINITY_DOMAIN_NEXT_PARTITIONABLE ?
353  "NEXT_PARTITIONABLE " : "");
354  return out;
355 
356 }
357 
364 static char* ccl_devquery_format_affdom_ext(CCLWrapperInfo* info,
365  char* out, size_t size, const char* units) {
366 
367  CCL_UNUSED(units);
368  cl_device_partition_property_ext* ade =
369  (cl_device_partition_property_ext*) info->value;
370  GString* str = g_string_new("");
371  guint count = (guint) (info->size / sizeof(cl_device_partition_property_ext));
372  for (guint i = 0; i < count; i++) {
373  switch (ade[i]) {
374  case CL_AFFINITY_DOMAIN_L1_CACHE_EXT:
375  g_string_append_printf(str, "L1_CACHE_EXT ");
376  break;
377  case CL_AFFINITY_DOMAIN_L2_CACHE_EXT:
378  g_string_append_printf(str, "L2_CACHE_EXT ");
379  break;
380  case CL_AFFINITY_DOMAIN_L3_CACHE_EXT:
381  g_string_append_printf(str, "L3_CACHE_EXT ");
382  break;
383  case CL_AFFINITY_DOMAIN_L4_CACHE_EXT:
384  g_string_append_printf(str, "L4_CACHE_EXT ");
385  break;
386  case CL_AFFINITY_DOMAIN_NUMA_EXT:
387  g_string_append_printf(str, "NUMA_EXT ");
388  break;
389  case CL_AFFINITY_DOMAIN_NEXT_FISSIONABLE_EXT:
390  g_string_append_printf(str, "NEXT_FISSIONABLE_EXT ");
391  break;
392  case CL_PROPERTIES_LIST_END_EXT:
393  break;
394  default:
395  g_string_append_printf(str, "UNKNOWN(0x%lx) ",
396  (unsigned long) ade[i]);
397  }
398  }
399  g_snprintf(out, (gulong) size, "%s", str->str);
400  g_string_free(str, TRUE);
401  return out;
402 
403 }
404 
410 static char* ccl_devquery_format_cachetype(CCLWrapperInfo* info,
411  char* out, size_t size, const char* units) {
412 
413  CCL_UNUSED(units);
414  cl_device_mem_cache_type mct =
415  *((cl_device_mem_cache_type*) info->value);
416  g_snprintf(out, (gulong) size, "%s%s%s",
417  mct & CL_READ_ONLY_CACHE ? "READ_ONLY" : "",
418  mct & CL_READ_WRITE_CACHE ? "READ_WRITE" : "",
419  mct & CL_NONE ? "NONE" : "");
420  return out;
421 }
422 
428 static char* ccl_devquery_format_queueprop(CCLWrapperInfo* info,
429  char* out, size_t size, const char* units) {
430 
431  CCL_UNUSED(units);
432  cl_command_queue_properties qp =
433  *((cl_command_queue_properties*) info->value);
434  g_snprintf(out, (gulong) size, "%s%s",
435  qp & CL_QUEUE_OUT_OF_ORDER_EXEC_MODE_ENABLE
436  ? "OUT_OF_ORDER_EXEC_MODE_ENABLE " : "",
437  qp & CL_QUEUE_PROFILING_ENABLE ? "PROFILING_ENABLE " : "");
438  return out;
439 
440 }
441 
448 static char* ccl_devquery_format_svmc(CCLWrapperInfo* info,
449  char* out, size_t size, const char* units) {
450 
451  CCL_UNUSED(units);
452  cl_device_svm_capabilities svmc =
453  *((cl_device_svm_capabilities*) info->value);
454  g_snprintf(out, (gulong) size, "%s%s%s%s",
455  svmc & CL_DEVICE_SVM_COARSE_GRAIN_BUFFER ? "COARSE_GRAIN_BUFFER " : "",
456  svmc & CL_DEVICE_SVM_FINE_GRAIN_BUFFER ? "FINE_GRAIN_BUFFER " : "",
457  svmc & CL_DEVICE_SVM_FINE_GRAIN_SYSTEM ? "FINE_GRAIN_SYSTEM " : "",
458  svmc & CL_DEVICE_SVM_ATOMICS ? "ATOMICS" : "");
459  return out;
460 }
461 
462 //~ /**
463  //~ * @internal
464  //~ * Implementation of ccl_devquery_format() function for debugging
465  //~ * purposes.
466  //~ * */
467 //~ static char* ccl_devquery_format_testsize(CCLWrapperInfo* info,
468  //~ gchar* out, guint size, const gchar const* units) {
469  //~
470  //~ g_snprintf(out, size, "%ld %s", (gulong) info->size, units);
471  //~ return out;
472 //~
473 //~ }
474 
475 /* Size of parameter information map. */
476 CCL_EXPORT
478 
479 /* Map of parameter name strings to respective cl_device_info
480  * bitfields, long description string, format output function and a
481  * units suffix. */
482 CCL_EXPORT
484 
485  {"ADDRESS_BITS", CL_DEVICE_ADDRESS_BITS,
486  "Address space size in bits",
487  ccl_devquery_format_uint, "bits"},
488  {"AFFINITY_DOMAINS_EXT", CL_DEVICE_AFFINITY_DOMAINS_EXT,
489  "Ext.: List of supported affinity domains for partitioning the device",
490  ccl_devquery_format_affdom_ext, ""},
491  {"AVAILABLE", CL_DEVICE_AVAILABLE,
492  "Is device available",
493  ccl_devquery_format_yesno, ""},
494  {"BOARD_NAME_AMD", CL_DEVICE_BOARD_NAME_AMD,
495  "AMD ext.: Name of the GPU board and model of the specific device",
496  ccl_devquery_format_char, ""},
497  {"BUILT_IN_KERNELS", CL_DEVICE_BUILT_IN_KERNELS,
498  "Device built-in kernels",
499  ccl_devquery_format_char, ""},
500  {"COMPILER_AVAILABLE", CL_DEVICE_COMPILER_AVAILABLE,
501  "Is a compiler available for device",
502  ccl_devquery_format_yesno, ""},
503  {"COMPUTE_CAPABILITY_MAJOR_NV", CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV,
504  "NVidia ext.: Major revision number that defines the CUDA compute "
505  "capability of the device",
506  ccl_devquery_format_uint, ""},
507  {"COMPUTE_CAPABILITY_MINOR_NV", CL_DEVICE_COMPUTE_CAPABILITY_MINOR_NV,
508  "NVidia ext.: Minor revision number that defines the CUDA compute "
509  "capability of the device",
510  ccl_devquery_format_uint, ""},
511  {"DOUBLE_FP_CONFIG", CL_DEVICE_DOUBLE_FP_CONFIG,
512  "Floating-point device configuration (double)",
513  ccl_devquery_format_fpconfig, ""},
514  {"DRIVER_VERSION", CL_DRIVER_VERSION,
515  "Driver version",
516  ccl_devquery_format_char, ""},
517  {"ENDIAN_LITTLE", CL_DEVICE_ENDIAN_LITTLE,
518  "Is device little endian",
519  ccl_devquery_format_yesno, ""},
520  {"ERROR_CORRECTION_SUPPORT", CL_DEVICE_ERROR_CORRECTION_SUPPORT,
521  "Error correction support",
522  ccl_devquery_format_yesno, ""},
523  {"EXECUTION_CAPABILITIES", CL_DEVICE_EXECUTION_CAPABILITIES,
524  "Execution capabilities",
525  ccl_devquery_format_execcap, ""},
526  {"EXTENSIONS", CL_DEVICE_EXTENSIONS,
527  "Extensions",
528  ccl_devquery_format_char, ""},
529  {"EXT_MEM_PADDING_IN_BYTES_QCOM", CL_DEVICE_EXT_MEM_PADDING_IN_BYTES_QCOM,
530  "Qualcomm ext.: Amount of padding necessary at the end of the buffer",
531  ccl_devquery_format_sizetbytes, ""},
532  /* The parameter below has in fact a length of 16 bytes,
533  * but due to the lack of documentation, only the first half
534  * of it is shown for now. */
535  {"GLOBAL_FREE_MEMORY_AMD", CL_DEVICE_GLOBAL_FREE_MEMORY_AMD,
536  "AMD ext.: Free device memory",
537  ccl_devquery_format_ulongbytes, ""},
538  {"GLOBAL_MEM_CACHELINE_SIZE", CL_DEVICE_GLOBAL_MEM_CACHELINE_SIZE,
539  "Global mem. cache line size",
540  ccl_devquery_format_uintbytes, ""},
541  {"GLOBAL_MEM_CACHE_SIZE", CL_DEVICE_GLOBAL_MEM_CACHE_SIZE,
542  "Global mem. cache size",
543  ccl_devquery_format_ulongbytes, ""},
544  {"GLOBAL_MEM_CACHE_TYPE", CL_DEVICE_GLOBAL_MEM_CACHE_TYPE,
545  "Global mem. cache type",
546  ccl_devquery_format_cachetype, ""},
547  {"GLOBAL_MEM_CHANNELS_AMD", CL_DEVICE_GLOBAL_MEM_CHANNELS_AMD,
548  "AMD ext.: Global mem. channels",
549  ccl_devquery_format_uint, ""},
550  {"GLOBAL_MEM_CHANNEL_BANKS_AMD", CL_DEVICE_GLOBAL_MEM_CHANNEL_BANKS_AMD,
551  "AMD ext.: Global mem. channel banks",
552  ccl_devquery_format_uint, ""},
553  {"GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD",
554  CL_DEVICE_GLOBAL_MEM_CHANNEL_BANK_WIDTH_AMD,
555  "AMD ext.: Global mem. channel bank width",
556  ccl_devquery_format_uint, ""},
557  {"GLOBAL_MEM_SIZE", CL_DEVICE_GLOBAL_MEM_SIZE,
558  "Global mem. size",
559  ccl_devquery_format_ulongbytes, ""},
560  {"GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE",
561  CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE,
562  "Max. pref. total size of all program variables in the global address "
563  "space",
564  ccl_devquery_format_sizetbytes, ""},
565  {"GPU_OVERLAP_NV", CL_DEVICE_GPU_OVERLAP_NV,
566  "NVidia ext.: Can device concurrently copy memory between host and "
567  "device while executing a kernel",
568  ccl_devquery_format_yesno, ""},
569  {"HALF_FP_CONFIG", CL_DEVICE_HALF_FP_CONFIG,
570  "Floating-point device configuration (half)",
571  ccl_devquery_format_fpconfig, ""},
572  {"HOST_UNIFIED_MEMORY", CL_DEVICE_HOST_UNIFIED_MEMORY,
573  "Host unified memory subsystem",
574  ccl_devquery_format_yesno, ""},
575  {"IL_VERSION", CL_DEVICE_IL_VERSION,
576  "The intermediate languages supported by clCreateProgramWithIL",
577  ccl_devquery_format_char, ""},
578  {"IMAGE2D_MAX_HEIGHT", CL_DEVICE_IMAGE2D_MAX_HEIGHT,
579  "Max. height of 2D image (pixels)",
580  ccl_devquery_format_sizet, "px"},
581  {"IMAGE2D_MAX_WIDTH", CL_DEVICE_IMAGE2D_MAX_WIDTH,
582  "Max. width of 1D/2D image (pixels)",
583  ccl_devquery_format_sizet, "px"},
584  {"IMAGE3D_MAX_DEPTH", CL_DEVICE_IMAGE3D_MAX_DEPTH,
585  "Max. depth of 3D image (pixels)",
586  ccl_devquery_format_sizet, "px"},
587  {"IMAGE3D_MAX_HEIGHT", CL_DEVICE_IMAGE3D_MAX_HEIGHT,
588  "Max. height of 3D image (pixels)",
589  ccl_devquery_format_sizet, "px"},
590  {"IMAGE3D_MAX_WIDTH", CL_DEVICE_IMAGE3D_MAX_WIDTH,
591  "Max. width of 3D image (pixels)",
592  ccl_devquery_format_sizet, "px"},
593  {"IMAGE_BASE_ADDRESS_ALIGNMENT", CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT,
594  "Min. alignment of the host_ptr specified to clCreateBuffer (for 2D "
595  "images created from a buffer in turn created using "
596  "CL_MEM_USE_HOST_PTR)",
597  ccl_devquery_format_uint, "px"},
598  {"IMAGE_MAX_ARRAY_SIZE", CL_DEVICE_IMAGE_MAX_ARRAY_SIZE,
599  "Max. images in a 1D or 2D image array",
600  ccl_devquery_format_sizet, "images"},
601  {"IMAGE_MAX_BUFFER_SIZE", CL_DEVICE_IMAGE_MAX_BUFFER_SIZE,
602  "Max. pixels for 1D image from buffer object",
603  ccl_devquery_format_sizet, "px"},
604  {"IMAGE_PITCH_ALIGNMENT", CL_DEVICE_IMAGE_PITCH_ALIGNMENT,
605  "Row pitch alignment size in pixels for 2D images created from a "
606  "buffer",
607  ccl_devquery_format_uint, "px"},
608  {"IMAGE_SUPPORT", CL_DEVICE_IMAGE_SUPPORT,
609  "Image support",
610  ccl_devquery_format_yesno, ""},
611  {"INTEGRATED_MEMORY_NV", CL_DEVICE_INTEGRATED_MEMORY_NV,
612  "NVidia ext.: Is device integrated with the memory subsystem?",
613  ccl_devquery_format_yesno, ""},
614  {"KERNEL_EXEC_TIMEOUT_NV", CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV,
615  "Nvidia ext.: Is there a limit for kernels executed on device?",
616  ccl_devquery_format_yesno, ""},
617  {"LINKER_AVAILABLE", CL_DEVICE_LINKER_AVAILABLE,
618  "Linker available",
619  ccl_devquery_format_yesno, ""},
620  {"LOCAL_MEM_BANKS_AMD", CL_DEVICE_LOCAL_MEM_BANKS_AMD,
621  "AMD ext.: Local mem. banks",
622  ccl_devquery_format_uint, ""},
623  {"LOCAL_MEM_SIZE", CL_DEVICE_LOCAL_MEM_SIZE,
624  "Local mem. size",
625  ccl_devquery_format_ulongbytes, ""},
626  {"LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD",
627  CL_DEVICE_LOCAL_MEM_SIZE_PER_COMPUTE_UNIT_AMD,
628  "AMD ext.: Local mem. size per compute unit",
629  ccl_devquery_format_uintbytes, ""},
630  {"LOCAL_MEM_TYPE", CL_DEVICE_LOCAL_MEM_TYPE,
631  "Local mem. type",
632  ccl_devquery_format_locmemtype, ""},
633  {"MAX_ATOMIC_COUNTERS_EXT", CL_DEVICE_MAX_ATOMIC_COUNTERS_EXT,
634  "Ext.: Max. atomic counters",
635  ccl_devquery_format_uint, ""},
636  {"MAX_CLOCK_FREQUENCY", CL_DEVICE_MAX_CLOCK_FREQUENCY,
637  "Max. clock frequency (MHz)",
638  ccl_devquery_format_uint, "MHz"},
639  {"MAX_COMPUTE_UNITS", CL_DEVICE_MAX_COMPUTE_UNITS,
640  "Number of compute units in device",
641  ccl_devquery_format_uint, ""},
642  {"MAX_CONSTANT_ARGS", CL_DEVICE_MAX_CONSTANT_ARGS,
643  "Max. number of __constant args in kernel",
644  ccl_devquery_format_uint, ""},
645  {"MAX_CONSTANT_BUFFER_SIZE", CL_DEVICE_MAX_CONSTANT_BUFFER_SIZE,
646  "Max. size in bytes of a constant buffer allocation",
647  ccl_devquery_format_ulongbytes, ""},
648  {"MAX_GLOBAL_VARIABLE_SIZE", CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE,
649  "Max. storage that may be allocated for any single variable in program "
650  "scope or inside a function in OpenCL C declared in the global address "
651  "space",
652  ccl_devquery_format_sizetbytes, ""},
653  {"MAX_MEM_ALLOC_SIZE", CL_DEVICE_MAX_MEM_ALLOC_SIZE,
654  "Max. size of memory object allocation in bytes",
655  ccl_devquery_format_ulongbytes, ""},
656  {"MAX_NUM_SUB_GROUPS", CL_DEVICE_MAX_NUM_SUB_GROUPS,
657  "Max. sub-groups in work-group on a single compute unit for any given "
658  "kernel-instance",
659  ccl_devquery_format_uint, ""},
660  {"MAX_ON_DEVICE_EVENTS", CL_DEVICE_MAX_ON_DEVICE_EVENTS,
661  "The maximum number of events in use by a device queue",
662  ccl_devquery_format_uint, ""},
663  {"MAX_ON_DEVICE_QUEUES", CL_DEVICE_MAX_ON_DEVICE_QUEUES,
664  "Max. number of device queues that can be created per context",
665  ccl_devquery_format_uint, ""},
666  {"MAX_PARAMETER_SIZE", CL_DEVICE_MAX_PARAMETER_SIZE,
667  "Max. size in bytes of the arguments that can be passed to a kernel",
668  ccl_devquery_format_sizetbytes, ""},
669  {"MAX_PIPE_ARGS", CL_DEVICE_MAX_PIPE_ARGS,
670  "Max. pipe objects that can be passed as arguments to a kernel",
671  ccl_devquery_format_uint, ""},
672  {"MAX_READ_IMAGE_ARGS", CL_DEVICE_MAX_READ_IMAGE_ARGS,
673  "Max. number of simultaneous image objects that can be read by a "
674  "kernel",
675  ccl_devquery_format_uint, "images"},
676  {"MAX_READ_WRITE_IMAGE_ARGS", CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS,
677  "Max. image objects arguments of a kernel declared with the read_only "
678  "qualifier",
679  ccl_devquery_format_uint, ""},
680  {"MAX_SAMPLERS", CL_DEVICE_MAX_SAMPLERS,
681  "Max. samplers that can be used in kernel",
682  ccl_devquery_format_uint, "samplers"},
683  {"MAX_WORK_GROUP_SIZE", CL_DEVICE_MAX_WORK_GROUP_SIZE,
684  "Max. work-items in work-group executing a kernel on a single compute "
685  "unit, using the data parallel execution model",
686  ccl_devquery_format_sizet, "work-items"},
687  {"MAX_WORK_ITEM_DIMENSIONS", CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS,
688  "Max. dims that specify the global and local work-item IDs used by the "
689  "data parallel execution model",
690  ccl_devquery_format_uint, ""},
691  {"MAX_WORK_ITEM_SIZES", CL_DEVICE_MAX_WORK_ITEM_SIZES,
692  "Max. work-items in each dimension of work-group",
693  ccl_devquery_format_sizetvec, ""},
694  {"MAX_WRITE_IMAGE_ARGS", CL_DEVICE_MAX_WRITE_IMAGE_ARGS,
695  "Max. simultaneous image objects that can be written to by a kernel",
696  ccl_devquery_format_uint, "images"},
697  {"MEM_BASE_ADDR_ALIGN", CL_DEVICE_MEM_BASE_ADDR_ALIGN,
698  "Size in bits of the largest OpenCL built-in data type supported by "
699  "the device",
700  ccl_devquery_format_uint, "bits"},
701  {"MIN_DATA_TYPE_ALIGN_SIZE", CL_DEVICE_MIN_DATA_TYPE_ALIGN_SIZE,
702  "Smallest alignment which can be used for any data type (deprecated in "
703  "OpenCL 1.2)",
704  ccl_devquery_format_uintbytes, ""},
705  {"NAME", CL_DEVICE_NAME,
706  "Name of device",
707  ccl_devquery_format_char, ""},
708  {"NATIVE_VECTOR_WIDTH_CHAR", CL_DEVICE_NATIVE_VECTOR_WIDTH_CHAR,
709  "Native ISA char vector width (number of scalar elements that can be "
710  "stored in the vector)",
711  ccl_devquery_format_uint, ""},
712  {"NATIVE_VECTOR_WIDTH_DOUBLE", CL_DEVICE_NATIVE_VECTOR_WIDTH_DOUBLE,
713  "Native ISA double vector width (number of scalar elements that can be "
714  "stored in the vector)",
715  ccl_devquery_format_uint, ""},
716  {"NATIVE_VECTOR_WIDTH_FLOAT", CL_DEVICE_NATIVE_VECTOR_WIDTH_FLOAT,
717  "Native ISA float vector width (number of scalar elements that can be "
718  "stored in the vector)",
719  ccl_devquery_format_uint, ""},
720  {"NATIVE_VECTOR_WIDTH_HALF", CL_DEVICE_NATIVE_VECTOR_WIDTH_HALF,
721  "Native ISA half vector width (number of scalar elements that can be "
722  "stored in the vector)",
723  ccl_devquery_format_uint, ""},
724  {"NATIVE_VECTOR_WIDTH_INT", CL_DEVICE_NATIVE_VECTOR_WIDTH_INT,
725  "Native ISA int vector width (number of scalar elements that can be "
726  "stored in the vector)",
727  ccl_devquery_format_uint, ""},
728  {"NATIVE_VECTOR_WIDTH_LONG", CL_DEVICE_NATIVE_VECTOR_WIDTH_LONG,
729  "Native ISA long vector width (number of scalar elements that can be "
730  "stored in the vector)",
731  ccl_devquery_format_uint, ""},
732  {"NATIVE_VECTOR_WIDTH_SHORT", CL_DEVICE_NATIVE_VECTOR_WIDTH_SHORT,
733  "Native ISA short vector width (number of scalar elements that can be "
734  "stored in the vector)",
735  ccl_devquery_format_uint, ""},
736  {"OPENCL_C_VERSION", CL_DEVICE_OPENCL_C_VERSION,
737  "Highest OpenCL C version supported by the device compiler",
738  ccl_devquery_format_char, ""},
739  {"PAGE_SIZE_QCOM", CL_DEVICE_PAGE_SIZE_QCOM,
740  "Qualcomm ext.: Page size of device",
741  ccl_devquery_format_sizetbytes, ""},
742  {"PARENT_DEVICE", CL_DEVICE_PARENT_DEVICE,
743  "The cl_device_id of the parent device to which the sub-device belongs",
744  ccl_devquery_format_ptr, ""},
745  {"PARENT_DEVICE_EXT", CL_DEVICE_PARENT_DEVICE_EXT,
746  "Ext.: Get the parent device to which the sub-device belongs",
747  ccl_devquery_format_hex, ""},
748  {"PARTITION_AFFINITY_DOMAIN", CL_DEVICE_PARTITION_AFFINITY_DOMAIN,
749  "Supported affinity domains for partitioning the device using "
750  "CL_DEVICE_PARTITION_BY_AFFINITY_DOMAIN",
751  ccl_devquery_format_affdom, ""},
752  {"PARTITION_MAX_SUB_DEVICES", CL_DEVICE_PARTITION_MAX_SUB_DEVICES,
753  "Max. sub-devices that can be created when device is partitioned",
754  ccl_devquery_format_uint, "devices"},
755  {"PARTITION_PROPERTIES", CL_DEVICE_PARTITION_PROPERTIES,
756  "Partition types supported by device",
757  ccl_devquery_format_partprop, ""},
758  {"PARTITION_STYLE_EXT", CL_DEVICE_PARTITION_STYLE_EXT,
759  "Ext.: Partition properties used to create the sub-device",
760  ccl_devquery_format_affdom_ext, ""},
761  {"PARTITION_TYPE", CL_DEVICE_PARTITION_TYPE,
762  "Properties specified in clCreateSubDevices if device is a subdevice",
763  ccl_devquery_format_uint, ""},
764  {"PARTITION_TYPES_EXT", CL_DEVICE_PARTITION_TYPES_EXT,
765  "Ext.: List of supported partition types for partitioning a device",
766  ccl_devquery_format_partprop, ""},
767  {"PIPE_MAX_ACTIVE_RESERVATIONS", CL_DEVICE_PIPE_MAX_ACTIVE_RESERVATIONS,
768  "Max. reservations that can be active for a pipe per work-item in a "
769  "kernel",
770  ccl_devquery_format_uint, ""},
771  {"PIPE_MAX_PACKET_SIZE", CL_DEVICE_PIPE_MAX_PACKET_SIZE,
772  "Max. size of pipe packet",
773  ccl_devquery_format_uintbytes, ""},
774  {"PLATFORM", CL_DEVICE_PLATFORM,
775  "The platform associated with device",
776  ccl_devquery_format_ptr, ""},
777  {"PREFERRED_GLOBAL_ATOMIC_ALIGNMENT",
778  CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT,
779  "Preferred alignment for OpenCL 2.0 atomic types to global memory",
780  ccl_devquery_format_uintbytes, ""},
781  {"PREFERRED_INTEROP_USER_SYNC", CL_DEVICE_PREFERRED_INTEROP_USER_SYNC,
782  "'Yes' if device prefers user to be responsible for sync. when sharing "
783  "memory objects between OpenCL and other APIs, 'No' if device has a "
784  "performant path for performing such sync.",
785  ccl_devquery_format_yesno, ""},
786  {"PREFERRED_LOCAL_ATOMIC_ALIGNMENT",
787  CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT,
788  "Preferred alignment for OpenCL 2.0 atomic types to local memory",
789  ccl_devquery_format_uintbytes, ""},
790  {"PREFERRED_PLATFORM_ATOMIC_ALIGNMENT",
791  CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT,
792  "Preferred alignment for OpenCL 2.0 fine-grained SVM atomic types",
793  ccl_devquery_format_uintbytes, ""},
794  {"PREFERRED_VECTOR_WIDTH_CHAR", CL_DEVICE_PREFERRED_VECTOR_WIDTH_CHAR,
795  "Preferred ISA char vector width (number of scalar elements that can "
796  "be stored in the vector)",
797  ccl_devquery_format_uint, ""},
798  {"PREFERRED_VECTOR_WIDTH_DOUBLE", CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE,
799  "Preferred ISA double vector width (number of scalar elements that can "
800  "be stored in the vector)",
801  ccl_devquery_format_uint, ""},
802  {"PREFERRED_VECTOR_WIDTH_FLOAT", CL_DEVICE_PREFERRED_VECTOR_WIDTH_FLOAT,
803  "Preferred ISA float vector width (number of scalar elements that can "
804  "be stored in the vector)",
805  ccl_devquery_format_uint, ""},
806  {"PREFERRED_VECTOR_WIDTH_HALF", CL_DEVICE_PREFERRED_VECTOR_WIDTH_HALF,
807  "Preferred ISA half vector width (number of scalar elements that can "
808  "be stored in the vector)",
809  ccl_devquery_format_uint, ""},
810  {"PREFERRED_VECTOR_WIDTH_INT", CL_DEVICE_PREFERRED_VECTOR_WIDTH_INT,
811  "Preferred ISA int vector width (number of scalar elements that can be "
812  "stored in the vector)",
813  ccl_devquery_format_uint, ""},
814  {"PREFERRED_VECTOR_WIDTH_LONG", CL_DEVICE_PREFERRED_VECTOR_WIDTH_LONG,
815  "Preferred ISA long vector width (number of scalar elements that can "
816  "be stored in the vector)",
817  ccl_devquery_format_uint, ""},
818  {"PREFERRED_VECTOR_WIDTH_SHORT", CL_DEVICE_PREFERRED_VECTOR_WIDTH_SHORT,
819  "Preferred ISA short vector width (number of scalar elements that can "
820  "be stored in the vector)",
821  ccl_devquery_format_uint, ""},
822  {"PRINTF_BUFFER_SIZE", CL_DEVICE_PRINTF_BUFFER_SIZE,
823  "Max. size of internal buffer that holds the output of printf calls "
824  "from kernel",
825  ccl_devquery_format_sizetbytes, ""},
826  {"PROFILE", CL_DEVICE_PROFILE,
827  "Profile name supported by the device (FULL or EMBEDDED)",
828  ccl_devquery_format_char, ""},
829  {"PROFILING_TIMER_OFFSET_AMD", CL_DEVICE_PROFILING_TIMER_OFFSET_AMD,
830  "AMD ext.: Offset between event timestamps in nanoseconds",
831  ccl_devquery_format_sizet, "ns"},
832  {"PROFILING_TIMER_RESOLUTION", CL_DEVICE_PROFILING_TIMER_RESOLUTION,
833  "Resolution of device timer in nanoseconds",
834  ccl_devquery_format_sizet, "ns"},
835  {"QUEUE_ON_DEVICE_MAX_SIZE", CL_DEVICE_QUEUE_ON_DEVICE_MAX_SIZE,
836  "Max. size of the device queue",
837  ccl_devquery_format_uintbytes, ""},
838  {"QUEUE_ON_DEVICE_PREFERRED_SIZE", CL_DEVICE_QUEUE_ON_DEVICE_PREFERRED_SIZE,
839  "Size of the device queue preferred by the implementation",
840  ccl_devquery_format_uintbytes, ""},
841  {"QUEUE_ON_DEVICE_PROPERTIES", CL_DEVICE_QUEUE_ON_DEVICE_PROPERTIES,
842  "On-device command-queue properties supported by the device",
843  ccl_devquery_format_queueprop , ""},
844  {"QUEUE_ON_HOST_PROPERTIES", CL_DEVICE_QUEUE_ON_HOST_PROPERTIES,
845  "On-host command-queue properties supported by the device",
846  ccl_devquery_format_queueprop, ""},
847  {"QUEUE_PROPERTIES", CL_DEVICE_QUEUE_PROPERTIES,
848  "Command-queue properties supported by device",
849  ccl_devquery_format_queueprop, ""},
850  {"REFERENCE_COUNT", CL_DEVICE_REFERENCE_COUNT,
851  "Device reference count",
852  ccl_devquery_format_uint, ""},
853  {"REFERENCE_COUNT_EXT", CL_DEVICE_REFERENCE_COUNT_EXT,
854  "Ext.: Device reference count",
855  ccl_devquery_format_uint, ""},
856  {"REGISTERS_PER_BLOCK_NV", CL_DEVICE_REGISTERS_PER_BLOCK_NV,
857  "NVidia ext.: Maximum number of 32-bit registers available to a "
858  "work-group",
859  ccl_devquery_format_uint, ""},
860  {"SIMD_INSTRUCTION_WIDTH_AMD", CL_DEVICE_SIMD_INSTRUCTION_WIDTH_AMD,
861  "AMD ext.: SIMD instruction width",
862  ccl_devquery_format_uint, ""},
863  {"SIMD_PER_COMPUTE_UNIT_AMD", CL_DEVICE_SIMD_PER_COMPUTE_UNIT_AMD,
864  "AMD ext.: SIMD per compute unit",
865  ccl_devquery_format_uint, ""},
866  {"SIMD_WIDTH_AMD", CL_DEVICE_SIMD_WIDTH_AMD,
867  "AMD ext.: SIMD width",
868  ccl_devquery_format_uint, ""},
869  {"SINGLE_FP_CONFIG", CL_DEVICE_SINGLE_FP_CONFIG,
870  "Floating-point device configuration (single)",
871  ccl_devquery_format_fpconfig, ""},
872  {"SPIR_VERSIONS", CL_DEVICE_SPIR_VERSIONS,
873  "Space separated list of SPIR versions supported by the device",
874  ccl_devquery_format_char, ""},
875  {"SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS",
876  CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS,
877  "True if device supports independent forward progress of sub-groups, "
878  "false otherwise",
879  ccl_devquery_format_yesno, ""},
880  {"SVM_CAPABILITIES", CL_DEVICE_SVM_CAPABILITIES,
881  "Shared virtual memory (SVM) memory allocation types the device "
882  "supports",
883  ccl_devquery_format_svmc, ""},
884  {"TERMINATE_CAPABILITY_KHR", CL_DEVICE_TERMINATE_CAPABILITY_KHR,
885  "Termination capability of the OpenCL device",
886  ccl_devquery_format_hex, ""},
887  {"THREAD_TRACE_SUPPORTED_AMD", CL_DEVICE_THREAD_TRACE_SUPPORTED_AMD,
888  "AMD ext.: Is thread trace supported",
889  ccl_devquery_format_yesno, ""},
890  {"TOPOLOGY_AMD", CL_DEVICE_TOPOLOGY_AMD,
891  "AMD ext.: Description of the topology used to connect the device to "
892  "the host",
893  ccl_devquery_format_hex, ""},
894  {"TYPE", CL_DEVICE_TYPE,
895  "Type of OpenCL device",
896  ccl_devquery_format_type, ""},
897  {"VENDOR", CL_DEVICE_VENDOR,
898  "Vendor of OpenCL device",
899  ccl_devquery_format_char, ""},
900  {"VENDOR_ID", CL_DEVICE_VENDOR_ID,
901  "Unique device vendor identifier",
902  ccl_devquery_format_hex, ""},
903  {"VERSION", CL_DEVICE_VERSION,
904  "OpenCL software driver version",
905  ccl_devquery_format_char, ""},
906  {"WARP_SIZE_NV", CL_DEVICE_WARP_SIZE_NV,
907  "NVidia ext.: Warp size in work-items",
908  ccl_devquery_format_uint, ""},
909  {"WAVEFRONT_WIDTH_AMD", CL_DEVICE_WAVEFRONT_WIDTH_AMD,
910  "AMD ext.: Wavefront width",
911  ccl_devquery_format_uint, ""},
912  {NULL, 0, NULL, NULL, NULL}
913 
914 };
915 
933 static int ccl_devquery_get_index(const char* name) {
934 
935  /* Make sure name is not NULL. */
936  g_return_val_if_fail(name != NULL, -1);
937 
938  /* Search indexes. */
939  gint idx_middle;
940  guint idx_start, idx_end;
941 
942  /* String comparison result. */
943  gint cmp_res;
944 
945  /* Found info flag. */
946  gboolean found = FALSE;
947 
948  /* Binary search. */
949  idx_start = 0;
950  idx_end = ccl_devquery_info_map_size - 1;
951  while (idx_end >= idx_start) {
952  idx_middle = (idx_start + idx_end) / 2;
953  cmp_res = g_strcmp0(
954  name, ccl_devquery_info_map[idx_middle].param_name);
955  if (cmp_res == 0) {
956  found = TRUE;
957  break;
958  }
959  if (cmp_res > 0)
960  idx_start = idx_middle + 1;
961  else
962  idx_end = idx_middle - 1;
963  }
964 
965  /* Return result */
966  return found ? idx_middle : -1;
967 }
968 
983 CCL_EXPORT
984 gchar* ccl_devquery_get_prefix_final(const char* prefix) {
985 
986  /* Make sure prefix is not NULL. */
987  g_return_val_if_fail(prefix != NULL, NULL);
988 
989  /* Auxiliary string variables. */
990  gchar* str_upper;
991  gchar* str_aux;
992  gchar* str_final;
993 
994  /* Make string uppercase. */
995  str_upper = g_ascii_strup(prefix, -1);
996 
997  /* Remove possible cl_device or cl_ prefix */
998  if (g_str_has_prefix(str_upper, "CL_DEVICE_")) {
999  str_aux = str_upper + strlen("CL_DEVICE_");
1000  } else if (g_str_has_prefix(str_upper, "CL_")) {
1001  str_aux = str_upper + strlen("CL_");
1002  } else {
1003  str_aux = str_upper;
1004  }
1005 
1006  /* Create a new string for returning. */
1007  str_final = g_strdup(str_aux);
1008 
1009  /* Free lowercase string. */
1010  g_free(str_upper);
1011 
1012  /* Return result */
1013  return str_final;
1014 
1015 }
1016 
1029 CCL_EXPORT
1030 cl_device_info ccl_devquery_name(const char* name) {
1031 
1032  /* Make sure name is not NULL. */
1033  g_return_val_if_fail(name != NULL, 0);
1034 
1035  /* Final name */
1036  gchar* name_final;
1037 
1038  /* Index of device info. */
1039  gint idx;
1040 
1041  /* Get final name. */
1042  name_final = ccl_devquery_get_prefix_final(name);
1043 
1044  /* Get index of cl_device_info given its final name. */
1045  idx = ccl_devquery_get_index(name_final);
1046 
1047  /* Release memory holding the final name. */
1048  g_free(name_final);
1049 
1050  /* Return the cl_device_info object if found, or 0 otherwise. */
1051  if (idx >= 0)
1052  return ccl_devquery_info_map[idx].device_info;
1053  else
1054  return 0;
1055 
1056 }
1057 
1071 CCL_EXPORT
1073  const char* prefix, int* size) {
1074 
1075  /* Make sure prefix is not NULL. */
1076  g_return_val_if_fail(prefix != NULL, NULL);
1077 
1078  /* Final prefix to search for. */
1079  gchar* prefix_final;
1080 
1081  /* Size of final prefix. */
1082  gint len_prefix_final;
1083 
1084  /* Search index. */
1085  gint idx_middle, idx_start, idx_end;
1086 
1087  /* Found info. */
1088  const CCLDevQueryMap* found_ccl_devquery_info_map = NULL;
1089 
1090  /* Determine final prefix according to how parameter names are
1091  * stored in ccl_devquery_info_map. */
1092  prefix_final = ccl_devquery_get_prefix_final(prefix);
1093 
1094  /* Determine prefix size. */
1095  len_prefix_final = (gint) strlen(prefix_final);
1096 
1097  /* Binary search. */
1098  idx_middle = ccl_devquery_get_index(prefix_final);
1099 
1100  if (idx_middle >= 0) {
1101  /* Search for beginning. */
1102  idx_start = idx_middle;
1103  while (TRUE) {
1104  if (idx_start == 0)
1105  break;
1106  if (g_ascii_strncasecmp(prefix_final,
1107  ccl_devquery_info_map[idx_start - 1].param_name,
1108  len_prefix_final)
1109  == 0)
1110  idx_start--;
1111  else
1112  break;
1113  }
1114  /* Search for ending. */
1115  idx_end = idx_middle;
1116  while (TRUE) {
1117  if (idx_end == ccl_devquery_info_map_size - 1)
1118  break;
1119  if (g_ascii_strncasecmp(prefix_final,
1120  ccl_devquery_info_map[idx_end + 1].param_name,
1121  len_prefix_final)
1122  == 0)
1123  idx_end++;
1124  else
1125  break;
1126  }
1127 
1128  /* Set return values. */
1129  if (size != NULL)
1130  *size = idx_end - idx_start + 1;
1131  found_ccl_devquery_info_map = &ccl_devquery_info_map[idx_start];
1132 
1133  } else {
1134 
1135  /* Nothing found. */
1136  if (size != NULL)
1137  *size = -1;
1138 
1139  }
1140 
1141  /* Free final prefix. */
1142  g_free(prefix_final);
1143 
1144  /* Return result */
1145  return found_ccl_devquery_info_map;
1146 }
1147 
1159 CCL_EXPORT
1160 const CCLDevQueryMap* ccl_devquery_match(const char* substr, int* idx) {
1161 
1162  /* Make sure substr is not NULL. */
1163  g_return_val_if_fail(substr != NULL, NULL);
1164 
1165  /* Make sure idx is not NULL. */
1166  g_return_val_if_fail(idx != NULL, NULL);
1167 
1168  /* Found flag. */
1169  gboolean found = FALSE;
1170 
1171  /* Found result. */
1172  const CCLDevQueryMap* info_row = NULL;
1173 
1174  /* Linear search. */
1175  for ( ; *idx < ccl_devquery_info_map_size; (*idx)++) {
1176  if (g_strstr_len(
1177  ccl_devquery_info_map[*idx].param_name, -1, substr)) {
1178 
1179  found = TRUE;
1180  break;
1181  }
1182  }
1183 
1184  /* Set found result. */
1185  if (found)
1186  info_row = &ccl_devquery_info_map[*idx];
1187 
1188  /* Increment index (for next iteration). */
1189  (*idx)++;
1190 
1191  /* Return result. */
1192  return info_row;
1193 
1194 }
1195 
Maps a string to a cl_device_info bitfield.
const CCLDevQueryMap * ccl_devquery_prefix(const char *prefix, int *size)
Get a pointer to the first device information parameter which has the given prefix.
#define ccl_devquery_type2str(type)
Map an OpenCL cl_device_type object to a string identifying the device type.
#define CCL_UNUSED(x)
Macro to avoid warning in unused variables.
Definition: ccl_common.h:86
size_t size
Size in bytes of object information.
Functions for querying OpenCL devices.
const cl_device_info device_info
CL device information bitfield.
void * value
Object information.
Class which represents information about a wrapped OpenCL object.
const int ccl_devquery_info_map_size
Size of parameter information map.
cl_device_info ccl_devquery_name(const char *name)
Return a cl_device_info object given its name.
gchar * ccl_devquery_get_prefix_final(const char *prefix)
Get a final device info prefix in the same format as kept in the ccl_devquery_info_map.
const CCLDevQueryMap ccl_devquery_info_map[]
Map of parameter name strings to respective cl_device_info bitfields, long description string...
const CCLDevQueryMap * ccl_devquery_match(const char *substr, int *idx)
Search for a device information parameter by matching part of its name.