1%%%---- BEGIN COPYRIGHT -------------------------------------------------------
2%%%
3%%% Copyright (C) 2007 - 2012, Rogvall Invest AB, <tony@rogvall.se>
4%%%
5%%% This software is licensed as described in the file COPYRIGHT, which
6%%% you should have received as part of this distribution. The terms
7%%% are also available at http://www.rogvall.se/docs/copyright.txt.
8%%%
9%%% You may opt to use, copy, modify, merge, publish, distribute and/or sell
10%%% copies of the Software, and permit persons to whom the Software is
11%%% furnished to do so, under the terms of the COPYRIGHT file.
12%%%
13%%% This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
14%%% KIND, either express or implied.
15%%%
16%%%---- END COPYRIGHT ---------------------------------------------------------
17%%% File    : cl.erl
18%%% Author  : Tony Rogvall <tony@rogvall.se>
19%%% Description : Erlang OpenCL  interface
20%%% Created : 25 Oct 2009 by Tony Rogvall <tony@rogvall.se>
21
22%% @doc The erlang api for <a href="http://www.khronos.org/opencl/">OpenCL</a>.
23%%
24%% OpenCL (Open Computing Language) is an open royalty-free standard
25%% for general purpose parallel programming across CPUs, GPUs and
26%% other processors, giving software developers portable and efficient
27%% access to the power of these heterogeneous processing platforms.
28%%
29%% OpenCL supports a wide range of applications, ranging from embedded
30%% and consumer software to HPC solutions, through a low-level,
31%% high-performance, portable abstraction. By creating an efficient,
32%% close-to-the-metal programming interface, OpenCL will form the
33%% foundation layer of a parallel computing ecosystem of
34%% platform-independent tools, middleware and applications.
35%%
36%% OpenCL consists of an API for coordinating parallel computation
37%% across heterogeneous processors; and a cross-platform programming
38%% language with a well-specified computation environment. The OpenCL
39%% standard:
40%%
41%% <li> Supports both data- and task-based parallel programming models</li>
42%% <li> Utilizes a subset of ISO C99 with extensions for parallelism </li>
43%% <li> Defines consistent numerical requirements based on IEEE 754</li>
44%% <li> Defines a configuration profile for handheld and embedded devices</li>
45%% <li> Efficiently interoperates with OpenGL, OpenGL ES, and other graphics APIs</li>
46%%
47%% The specification is divided into a core specification that any
48%% OpenCL compliant implementation must support; a handheld/embedded
49%% profile which relaxes the OpenCL compliance requirements for
50%% handheld and embedded devices; and a set of optional extensions
51%% that are likely to move into the core specification in later
52%% revisions of the OpenCL specification.
53%%
54%% The documentation is re-used with the following copyright:
55%%
56%% Copyright © 2007-2009 The Khronos Group Inc. Permission is hereby
57%% granted, free of charge, to any person obtaining a copy of this
58%% software and/or associated documentation files (the "Materials"),
59%% to deal in the Materials without restriction, including without
60%% limitation the rights to use, copy, modify, merge, publish,
61%% distribute, sublicense, and/or sell copies of the Materials, and to
62%% permit persons to whom the Materials are furnished to do so,
63%% subject to the condition that this copyright notice and permission
64%% notice shall be included in all copies or substantial portions of
65%% the Materials.
66%%
67%% @headerfile "../include/cl.hrl"
68%%
69-module(cl).
70
71-on_load(init/0).
72
73-export([start/0, start/1, stop/0]).
74-export([noop/0]).
75-export([versions/0]).
76%% Platform
77-export([get_platform_ids/0]).
78-export([platform_info/0]).
79-export([get_platform_info/1,get_platform_info/2]).
80%% Devices
81-export([get_device_ids/0, get_device_ids/2]).
82-export([create_sub_devices/2]).
83-export([release_device/1]).
84-export([retain_device/1]).
85-export([device_info/0]).
86-export([device_info_10/1]).
87-export([device_info_11/1]).
88-export([device_info_12/1]).
89-export([get_device_info/1,get_device_info/2]).
90%% Context
91-export([create_context/1]).
92-export([create_context_from_type/1]).
93-export([release_context/1]).
94-export([retain_context/1]).
95-export([context_info/0]).
96-export([get_context_info/1,get_context_info/2]).
97%% Command queue
98-export([create_queue/3]).
99-export([set_queue_property/3]).
100-export([release_queue/1]).
101-export([retain_queue/1]).
102-export([queue_info/0]).
103-export([get_queue_info/1,get_queue_info/2]).
104%% Memory object
105-export([create_buffer/3, create_buffer/4]).
106-export([create_sub_buffer/4]).
107-export([release_mem_object/1]).
108-export([retain_mem_object/1]).
109-export([mem_object_info/0]).
110-export([get_mem_object_info/1,get_mem_object_info/2]).
111-export([image_info/0]).
112-export([get_image_info/1,get_image_info/2]).
113-export([get_supported_image_formats/3]).
114-export([create_image/5]).
115-export([create_image2d/7]).
116-export([create_image3d/9]).
117
118%% Sampler
119-export([create_sampler/4]).
120-export([release_sampler/1]).
121-export([retain_sampler/1]).
122-export([sampler_info/0]).
123-export([get_sampler_info/1,get_sampler_info/2]).
124%% Program
125-export([create_program_with_source/2]).
126-export([create_program_with_binary/3]).
127-export([create_program_with_builtin_kernels/3]).
128-export([release_program/1]).
129-export([retain_program/1]).
130-export([build_program/3, async_build_program/3]).
131-export([unload_compiler/0]).
132-export([unload_platform_compiler/1]).
133-export([compile_program/5, async_compile_program/5]).
134-export([link_program/4, async_link_program/4]).
135-export([program_info/0]).
136-export([get_program_info/1,get_program_info/2]).
137-export([program_build_info/0]).
138-export([get_program_build_info/2,get_program_build_info/3]).
139%% Kernel
140-export([create_kernel/2]).
141-export([create_kernels_in_program/1]).
142-export([set_kernel_arg/3]).
143-export([set_kernel_arg_size/3]).
144-export([release_kernel/1]).
145-export([retain_kernel/1]).
146-export([kernel_info/0]).
147-export([get_kernel_info/1,get_kernel_info/2]).
148-export([kernel_workgroup_info/0]).
149-export([get_kernel_workgroup_info/2,get_kernel_workgroup_info/3]).
150-export([kernel_arg_info/0]).
151-export([get_kernel_arg_info/1, get_kernel_arg_info/2,get_kernel_arg_info/3]).
152%% Events
153-export([enqueue_task/3, enqueue_task/4]).
154-export([nowait_enqueue_task/3]).
155-export([enqueue_nd_range_kernel/5]).
156-export([enqueue_nd_range_kernel/6]).
157-export([nowait_enqueue_nd_range_kernel/5]).
158-export([enqueue_marker/1]).
159-export([enqueue_barrier/1]).
160-export([enqueue_marker_with_wait_list/2]).
161-export([enqueue_barrier_with_wait_list/2]).
162-export([enqueue_wait_for_events/2]).
163-export([enqueue_read_buffer/5]).
164-export([enqueue_read_buffer_rect/10]).
165-export([enqueue_write_buffer/6]).
166-export([enqueue_write_buffer/7]).
167-export([nowait_enqueue_write_buffer/6]).
168-export([enqueue_fill_buffer/6]).
169-export([enqueue_write_buffer_rect/11]).
170-export([enqueue_read_image/7]).
171-export([enqueue_write_image/8]).
172-export([enqueue_write_image/9]).
173-export([nowait_enqueue_write_image/8]).
174-export([enqueue_copy_buffer/7]).
175-export([enqueue_copy_buffer_rect/11]).
176-export([enqueue_copy_image/6]).
177-export([enqueue_fill_image/6]).
178-export([enqueue_copy_image_to_buffer/7]).
179-export([enqueue_copy_buffer_to_image/7]).
180-export([enqueue_map_buffer/6]).
181-export([enqueue_map_image/6]).
182-export([enqueue_unmap_mem_object/3]).
183-export([enqueue_migrate_mem_objects/4]).
184-export([release_event/1]).
185-export([retain_event/1]).
186-export([event_info/0]).
187-export([get_event_info/1, get_event_info/2]).
188-export([wait/1, wait/2]).
189-export([wait_for_events/1]).
190
191-export([async_flush/1, flush/1]).
192-export([async_finish/1, finish/1]).
193-export([async_wait_for_event/1, wait_for_event/1]).
194
195-import(lists, [map/2, reverse/1]).
196
197-include("../include/cl.hrl").
198
199-define(is_platform(X), element(1,X) =:= platform_t).
200-define(is_device(X), element(1,X) =:= device_t).
201-define(is_context(X), element(1,X) =:= context_t).
202-define(is_queue(X), element(1,X) =:= command_queue_t).
203-define(is_mem(X), element(1,X) =:= mem_t).
204-define(is_sampler(X), element(1,X) =:= sampler_t).
205-define(is_program(X), element(1,X) =:= program_t).
206-define(is_kernel(X), element(1,X) =:= kernel_t).
207-define(is_event(X), element(1,X) =:= event_t).
208
209-ifdef(debug).
210-define(DBG(F,A), io:format((F),(A))).
211-else.
212-define(DBG(F,A), ok).
213-endif.
214
215-define(nif_stub,nif_stub_error(?LINE)).
216nif_stub_error(Line) ->
217    erlang:nif_error({nif_not_loaded,module,?MODULE,line,Line}).
218
219init() ->
220    Nif = filename:join([code:priv_dir(cl), "cl_nif"]),
221    ?DBG("Loading: ~s\n", [Nif]),
222    erlang:load_nif(Nif, 0).
223
224%%
225%% @type start_arg() = { {'debug',boolean()} }
226%%
227-type start_arg() ::  {'debug',boolean()} .
228
229%%
230%% @spec start([start_arg()]) -> 'ok' | {'error', term()}
231%%
232%% @doc Start the OpenCL application
233%%
234-spec start(Args::[start_arg()]) -> 'ok' | {'error', term()}.
235
236start(_Args) ->
237    ok.
238
239%%
240%% @spec start() -> 'ok' | {'error', term()}
241%%
242%% @doc Start the OpenCL application
243%%
244%% @equiv start([])
245%%
246-spec start() -> 'ok' | {'error', term()}.
247
248start() ->
249    start([]).
250
251%%
252%% @spec stop() -> 'ok' | {'error', term()}
253%%
254%% @doc Stop the OpenCL application
255%%
256%% @equiv application:stop(cl)
257%%
258-spec stop() -> 'ok' | {'error', term()}.
259
260stop()  ->
261    ok.
262
263%%
264%% @spec noop() -> 'ok' | {'error', cl_error()}
265%%
266%% @doc Run a no operation towards the NIF object. This call can be used
267%% to messure the call overhead to the NIF objeect.
268%%
269-spec noop() -> 'ok' | {'error', cl_error()}.
270
271noop() ->
272    ?nif_stub.
273
274%%
275%% @spec versions() -> [{Major::integer(),Minor::integer()}]
276%%
277%% @doc Run a no operation towards the NIF object. This call can be used
278%% to messure the call overhead to the NIF objeect.
279%%
280-spec versions() -> [{Major::integer(),Minor::integer()}].
281
282versions() ->
283    ?nif_stub.
284
285%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
286%% Platform
287%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
288
289%%
290%% @type cl_platform_info_key() =
291%%    'profile' | 'name' | 'vendor' | 'extensions'.
292
293-type cl_platform_info_key() ::
294	'profile' | 'name' | 'vendor' | 'extensions'.
295%%
296%% @type cl_platform_info() =
297%%      {'profile',string()} |
298%%      {'version', string()} |
299%%      {'name',string()} |
300%%      {'vendor',string()} |
301%%      {'extensions',string()}.
302
303-type cl_platform_info() ::
304	{'profile',string()} |
305	{'version',string()} |
306	{'name',string()} |
307	{'vendor',string()} |
308	{'extensions',string()}.
309
310%%
311%% @spec get_platform_ids() ->
312%%    {'ok',[cl_platform_id()]} | {'error', cl_error()}
313%% @doc Obtain the list of platforms available.
314-spec get_platform_ids() ->
315    {'ok',[cl_platform_id()]} | {'error', cl_error()}.
316
317get_platform_ids() ->
318    ?nif_stub.
319%%
320%% @spec platform_info() ->
321%%    [cl_platform_info_keys()]
322%% @doc Returns a list of the possible platform info keys.
323-spec platform_info() ->
324    [cl_platform_info_key()].
325
326platform_info() ->
327    [profile,
328     version,
329     name,
330     vendor,
331     extensions].
332
333%%
334%% @spec get_platform_info(Platform :: cl_platform_id(),
335%%			Info :: cl_platform_info_key()) ->
336%%    {'ok',term()} | {'error', cl_error()}
337%% @doc Get specific information about the OpenCL platform.
338%% <dl>
339%%
340%% <dt>name</dt>     <dd>Platform name string.</dd>
341%%
342%% <dt>vendor</dt>   <dd>Platform vendor string.</dd>
343%%
344%% <dt>profile</dt>
345%%        <dd> OpenCL profile string. Returns the profile name
346%%        supported by the implementation. The profile name returned
347%%        can be one of the following strings:
348%%
349%%        FULL_PROFILE - if the implementation supports the OpenCL
350%%        specification (functionality defined as part of the core
351%%        specification and does not require any extensions to be supported).
352%%
353%%        EMBEDDED_PROFILE - if the implementation supports the OpenCL
354%%        embedded profile. The embedded profile is defined to be a subset for
355%%        each version of OpenCL.</dd>
356%%
357%% <dt>version</dt>
358%%       <dd>OpenCL version string. Returns the OpenCL version supported by the implementation.</dd>
359%%
360%% <dt>extensions</dt> <dd>Returns a space-separated list of extension
361%% names (the extension names themselves do not contain any spaces)
362%% supported by the platform. Extensions defined here must be
363%% supported by all devices associated with this platform. </dd>
364%%</dl>
365-spec get_platform_info(Platform :: cl_platform_id(),
366			Info :: cl_platform_info_key()) ->
367    {'ok',term()} | {'error', cl_error()}.
368
369get_platform_info(_Platform, _Info) ->
370    ?nif_stub.
371
372%%
373%% @spec get_platform_info(Platform::cl_platform_id()) ->
374%%     {'ok', [cl_platform_info()]} | {'error', cl_error()}
375%% @doc Get all information about the OpenCL platform.
376%% @see get_platform_info/2
377-spec get_platform_info(Platform::cl_platform_id()) ->
378    {'ok', [cl_platform_info()]} | {'error', cl_error()}.
379
380get_platform_info(Platform) when ?is_platform(Platform) ->
381    get_info_list(Platform, platform_info(), fun get_platform_info/2).
382
383%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
384%% Devices
385%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
386
387%%
388%% @type cl_device_type() =
389%%   {'gpu' | 'cpu' | 'accelerator' | 'all' | 'default' }
390%%
391-type cl_device_type() :: 'gpu' | 'cpu' | 'accelerator' | 'all' | 'default'.
392%%
393%%
394%% @type cl_device_types() = {cl_device_type() | [cl_device_type()]}
395%%
396-type cl_device_types() :: cl_device_type() | [cl_device_type()].
397
398%%
399%%
400%% @type cl_device_info_key() = { 'type' | 'vendor_id' | 'max_compute_units' |
401%%  'max_work_item_dimensions' | 'max_work_group_size' |
402%%  'max_work_item_sizes' |
403%%  'preferred_vector_width_char' | 'preferred_vector_width_short' |
404%%  'preferred_vector_width_int' | 'preferred_vector_width_long' |
405%%  'preferred_vector_width_float' | 'preferred_vector_width_double' |
406%%  'max_clock_frequency' | 'address_bits' | 'max_read_image_args' |
407%%  'max_write_image_args' | 'max_mem_alloc_size' |
408%%  'image2d_max_width' | 'image2d_max_height' | 'image3d_max_width' |
409%%  'image3d_max_height' | 'image3d_max_depth' |
410%%  'image_support' |
411%%  'max_parameter_size' | 'max_samplers' |
412%%  'mem_base_addr_align' | 'min_data_type_align_size' |
413%%  'single_fp_config' |  'global_mem_cache_type' |
414%%  'global_mem_cacheline_size' | 'global_mem_cache_size' | 'global_mem_size' |
415%%  'max_constant_buffer_size' | 'max_constant_args' |
416%%  'local_mem_type' | 'local_mem_size' | 'error_correction_support' |
417%%  'profiling_timer_resolution' | 'endian_little' | 'available' |
418%%  'compiler_available' | 'execution_capabilities' | 'queue_properties' |
419%%  'name' | 'vendor' | 'driver_version' | 'profile' | 'version' |
420%%  'extensions' | 'platform' }
421%%
422-type cl_device_info_key() :: 'type' | 'vendor_id' | 'max_compute_units' |
423 'max_work_item_dimensions' | 'max_work_group_size' |
424 'max_work_item_sizes' |
425 'preferred_vector_width_char' | 'preferred_vector_width_short' |
426 'preferred_vector_width_int' | 'preferred_vector_width_long' |
427 'preferred_vector_width_float' | 'preferred_vector_width_double' |
428 'max_clock_frequency' | 'address_bits' | 'max_read_image_args' |
429 'max_write_image_args' | 'max_mem_alloc_size' |
430 'image2d_max_width' | 'image2d_max_height' | 'image3d_max_width' |
431 'image3d_max_height' | 'image3d_max_depth' |
432 'image_support' |
433 'max_parameter_size' | 'max_samplers' |
434 'mem_base_addr_align' | 'min_data_type_align_size' |
435 'single_fp_config' |  'global_mem_cache_type' |
436 'global_mem_cacheline_size' | 'global_mem_cache_size' | 'global_mem_size' |
437 'max_constant_buffer_size' | 'max_constant_args' |
438 'local_mem_type' | 'local_mem_size' | 'error_correction_support' |
439 'profiling_timer_resolution' | 'endian_little' | 'available' |
440 'compiler_available' | 'execution_capabilities' | 'queue_properties' |
441 'name' | 'vendor' | 'driver_version' | 'profile' | 'version' |
442 'extensions' | 'platform'.
443
444%%
445%% @type cl_device_info() = {cl_device_info_key(), term()}
446%% @todo specifiy all info types
447-type cl_device_info() :: {cl_device_info_key(), term()}.
448
449%%
450%% @spec get_device_ids() -> {'ok',[cl_device_id()]} | {'error',cl_error()}
451%%
452%% @equiv get_devive_ids(0,all)
453%%
454-spec get_device_ids() -> {'ok',[cl_device_id()]} | {'error',cl_error()}.
455
456get_device_ids() ->
457    get_device_ids(undefined, all).
458
459%%
460%% @spec get_device_ids(Platform::cl_platform_id(),Type::cl_device_types()) ->
461%%     {'ok',[cl_device_id()]} | {'error',cl_error()}
462%% @doc Obtain the list of devices available on a platform.
463%% <dl> <dt>Platform</dt> <dd>
464%%
465%% Refers to the platform ID returned by <c>get_platform_ids</c> or can be
466%% NULL. If platform is NULL, the behavior is implementation-defined. </dd>
467%%
468%% <dt>Type</dt> <dd>
469%%
470%% A list that identifies the type of OpenCL device. The
471%% device_type can be used to query specific OpenCL devices or all
472%% OpenCL devices available. </dd>
473%%
474%% </dl>
475%%
476%%  get_device_ids/2 may return all or a subset of the actual
477%%  physical devices present in the platform and that match
478%%  device_type.
479%%
480%% The application can query specific capabilities of the OpenCL
481%% device(s) returned by get_device_ids/2. This can be used by the
482%% application to determine which device(s) to use.
483%%
484-spec get_device_ids(undefined|cl_platform_id(),Type::cl_device_types()) ->
485    {'ok',[cl_device_id()]} | {'error',cl_error()}.
486
487get_device_ids(_Platform, _Type) ->
488    ?nif_stub.
489
490-spec create_sub_devices(Device::cl_device_id(),
491			 Property::
492			   {equally|non_neg_integer()} |
493			   {by_counts,[non_neg_integer()]} |
494			   {by_affinity_domain,
495			    numa|l4_cache|l3_cache|l2_cache|l1_cache|
496			    next_partitionable}) ->
497    {'ok',[cl_device_id()]} | {'error',cl_error()}.
498
499create_sub_devices(_Device, _Properties) ->
500    ?nif_stub.
501
502-spec release_device(Device::cl_device_id()) ->
503			    'ok' | {'error', cl_error()}.
504release_device(_Device) ->
505    ok.
506
507-spec retain_device(Device::cl_device_id()) ->
508			   'ok' | {'error', cl_error()}.
509retain_device(_Device) ->
510    ok.
511
512%%
513%% @spec device_info() -> [cl_device_info_key()]
514%% @doc Return a list of possible device info queries.
515%% @see get_device_info/2
516-spec device_info() -> [cl_device_info_key()].
517
518device_info() ->
519    lists:foldl(
520      fun({1,2},Acc) -> device_info_12(Acc);
521	 ({1,1},Acc) -> device_info_11(Acc);
522	 ({1,0},Acc) -> device_info_10(Acc);
523	 (_, Acc) -> Acc
524      end, [], versions()).
525
526
527device_info_10(L) ->
528    [
529     type,
530     vendor_id,
531     max_compute_units,
532     max_work_item_dimensions,
533     max_work_group_size,
534     max_work_item_sizes,
535     preferred_vector_width_char,
536     preferred_vector_width_short,
537     preferred_vector_width_int,
538     preferred_vector_width_long,
539     preferred_vector_width_float,
540     preferred_vector_width_double,
541     max_clock_frequency,
542     address_bits,
543     max_read_image_args,
544     max_write_image_args,
545     max_mem_alloc_size,
546     image2d_max_width,
547     image2d_max_height,
548     image3d_max_width,
549     image3d_max_height,
550     image3d_max_depth,
551     image_support,
552     max_parameter_size,
553     max_samplers,
554     mem_base_addr_align,
555     min_data_type_align_size,
556     single_fp_config,
557     global_mem_cache_type,
558     global_mem_cacheline_size,
559     global_mem_cache_size,
560     global_mem_size,
561     max_constant_buffer_size,
562     max_constant_args,
563     local_mem_type,
564     local_mem_size,
565     error_correction_support,
566     profiling_timer_resolution,
567     endian_little,
568     available,
569     compiler_available,
570     execution_capabilities,
571     queue_properties,
572     name,
573     vendor,
574     driver_version,
575     profile,
576     version,
577     extensions,
578     platform | L
579    ].
580
581device_info_11(L) ->
582    [
583     preferred_vector_width_half,
584     host_unified_memory,
585     native_vector_width_char,
586     native_vector_width_short,
587     native_vector_width_int,
588     native_vector_width_long,
589     native_vector_width_float,
590     native_vector_width_double,
591     native_vector_width_half,
592     opencl_c_version | L
593    ].
594
595device_info_12(L) ->
596    [
597     double_fp_config,
598     linker_available,
599     built_in_kernels,
600     image_max_buffer_size,
601     image_max_array_size,
602     parent_device,
603     partition_max_sub_devices,
604     partition_properties,
605     partition_affinity_domain,
606     partition_type,
607     reference_count,
608     preferred_interop_user_sync,
609     printf_buffer_size | L
610%%     image_pitch_alignment,
611%%     image_base_address_alignment
612    ].
613
614%%
615%% @spec get_device_info(DevID::cl_device_id(), Info::cl_device_info_key()) ->
616%%   {'ok', term()} | {'error', cl_error()}
617%% @doc Get information about an OpenCL device.
618%%
619%% <dl> <dt>'type' </dt> <dd> <p>The OpenCL device type. Currently
620%% supported values are one of or a combination of: CL_DEVICE_TYPE_CPU,
621%% CL_DEVICE_TYPE_GPU, CL_DEVICE_TYPE_ACCELERATOR, or
622%% CL_DEVICE_TYPE_DEFAULT.</p></dd>
623%%
624%% <dt>'vendor_id'</dt> <dd> <p>A unique device vendor identifier. An
625%% example of a unique device identifier could be the PCIe ID.</p> </dd>
626%%
627%% <dt>'max_compute_units'</dt> <dd> <p>The number of parallel compute
628%% cores on the OpenCL device. The minimum value is 1.</p> </dd>
629%%
630%% <dt>'max_work_item_dimensions'</dt> <dd> <p>Maximum dimensions that
631%% specify the global and local work-item IDs used by the data parallel
632%% execution model. (@see enqueue_nd_range_kernel/5). The
633%% minimum value is 3.</p></dd>
634%%
635%% <dt>'max_work_group_size'</dt> <dd> <p>Maximum number of
636%% work-items in a work-group executing a kernel using the data parallel
637%% execution model. (@see enqueue_nd_range_kernel/5). The minimum value
638%% is 1.</p> </dd>
639%%
640%% <dt>'max_work_item_sizes'</dt> <dd> <p>Maximum number of work-items
641%% that can be specified in each dimension of the work-group to enqueue_nd_range_kernel/5.</p>
642%% <p>Returns <code class="varname">n</code> entries, where <code
643%% class="varname">n</code> is the value returned by the query for
644%% CL_DEVICE_MAX_WORK_ITEM_DIMENSIONS. The minimum value is (1, 1,
645%% 1).</p></dd>
646%%
647%% <dt>'preferred_vector_width_TYPE'</dt> <dd> <p>Preferred native vector
648%% width size for built-in scalar types that can be put into vectors. The
649%% vector width is defined as the number of scalar elements that can be
650%% stored in the vector.</p> <p>If the <c>cl_khr_fp64</c> extension is
651%% not supported, CL_DEVICE_PREFERRED_VECTOR_WIDTH_DOUBLE must return
652%% 0.</p></dd>
653%%
654%% <dt>'max_clock_frequency'</dt> <dd> <p>Maximum configured clock
655%% frequency of the device in MHz.</p>
656%%
657%% </dd> <dt>'address_bits'</dt> <dd> The default compute device address
658%% space size specified as an unsigned integer value in bits. Currently
659%% supported values are 32 or 64 bits. </dd>
660%%
661%% <dt>'max_read_image_args'</dt> <dd> <p>Max number of simultaneous
662%% image objects that can be read by a kernel. The minimum value is 128
663%% if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p></dd>
664%%
665%% <dt>'max_write_image_args'</dt> <dd> <p>Max number of
666%% simultaneous image objects that can be written to by a kernel. The
667%% minimum value is 8 if CL_DEVICE_IMAGE_SUPPORT is CL_TRUE.</p> </dd>
668%%
669%% <dt>'max_mem_alloc_size'</dt> <dd> <p>Max size of memory object
670%% allocation in bytes. The minimum value is max (1/4th of
671%% CL_DEVICE_GLOBAL_MEM_SIZE, 128*1024*1024)</p></dd>
672%%
673%% <dt>'image2d_max_width'</dt> <dd> <p>Max width of 2D image in
674%% pixels. The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is
675%% CL_TRUE.</p> </dd>
676%%
677%% <dt>'image2d_max_height'</dt> <dd> <p>Max height of 2D image in
678%% pixels. The minimum value is 8192 if CL_DEVICE_IMAGE_SUPPORT is
679%% CL_TRUE.</p> </dd>
680%%
681%% <dt>'image3d_max_width'</dt> <dd> <p>Max width of 3D image in
682%% pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is
683%% CL_TRUE.</p> </dd>
684%%
685%% <dt>'image3d_max_height'</dt> <dd> <p>Max height of 3D image in
686%% pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is
687%% CL_TRUE.</p> </dd>
688%%
689%% <dt>'image3d_max_depth'</dt> <dd> <p>Max depth of 3D image in
690%% pixels. The minimum value is 2048 if CL_DEVICE_IMAGE_SUPPORT is
691%% CL_TRUE.</p> </dd>
692%%
693%% <dt>'image_support'</dt> <dd> <p>Is CL_TRUE if images are supported by
694%% the OpenCL device and CL_FALSE otherwise.</p> </dd>
695%%
696%% <dt>'max_parameter_size'</dt> <dd> <p>Max size in bytes of the
697%% arguments that can be passed to a kernel. The minimum value is
698%% 256.</p> </dd>
699%%
700%% <dt>'max_samplers'</dt> <dd> <p>Maximum number of samplers that can be
701%% used in a kernel. The minimum value is 16 if CL_DEVICE_IMAGE_SUPPORT
702%% is CL_TRUE.</p> </dd>
703%%
704%% <dt>'mem_base_addr_align'</dt> <dd> <p>Describes the alignment in bits
705%% of the base address of any allocated memory object.</p> </dd>
706%%
707%% <dt>'min_data_type_align_size'</dt> <dd> <p>The smallest alignment in
708%% bytes which can be used for any data type.</p> </dd>
709%% <dt>'single_fp_config'</dt> <dd> <p>Describes single precision
710%% floating-point capability of the device. This is a bit-field that
711%% describes one or more of the following values:</p> <p>CL_FP_DENORM -
712%% denorms are supported</p> <p>CL_FP_INF_NAN - INF and quiet NaNs are
713%% supported</p> <p>CL_FP_ROUND_TO_NEAREST - round to nearest even
714%% rounding mode supported</p>
715%% <p>CL_FP_ROUND_TO_ZERO - round to zero rounding mode supported</p>
716%% <p>CL_FP_ROUND_TO_INF - round to +ve and -ve infinity rounding modes supported</p>
717%% <p>CL_FP_FMA - IEEE754-2008 fused multiply-add is supported</p>
718%% <p>The mandated minimum floating-point capability is CL_FP_ROUND_TO_NEAREST | CL_FP_INF_NAN.</p>
719%% </dd>
720%%
721%% <dt>'global_mem_cache_type'</dt> <dd> <p>Return type:
722%% cl_device_mem_cache_type</p> <p>Type of global memory cache
723%% supported. Valid values are: CL_NONE, CL_READ_ONLY_CACHE, and
724%% CL_READ_WRITE_CACHE.</p> </dd>
725%%
726%% <dt>'global_mem_cacheline_size'</dt> <dd>
727%% <p>Size of global memory cache line in bytes.</p>
728%% </dd>
729%%
730%% <dt>'global_mem_cache_size'</dt> <dd>
731%% <p>Size of global memory cache in bytes.</p>
732%% </dd>
733%%
734%% <dt>'global_mem_size'</dt> <dd>
735%% <p>Size of global device memory in bytes.</p>
736%% </dd>
737%%
738%% <dt>'max_constant_buffer_size'</dt> <dd>
739%% <p>Max size in bytes of a constant buffer allocation. The minimum value is 64 KB.</p></dd>
740%%
741%%  <dt>'max_constant_args'</dt> <dd> <p>Max number of arguments
742%% declared with the <c>__constant</c> qualifier in a kernel. The minimum
743%% value is 8.</p> </dd>
744%%
745%% <dt>'local_mem_type'</dt> <dd> <p>Type of local memory
746%% supported. This can be set to CL_LOCAL implying dedicated local memory
747%% storage such as SRAM, or CL_GLOBAL.</p> </dd>
748%%
749%% <dt>'local_mem_size'</dt> <dd> <p>Size of local memory arena in
750%% bytes. The minimum value is 16 KB.</p></dd>
751%%
752%% <dt>'error_correction_support'</dt> <dd> Is CL_TRUE if the device
753%% implements error correction for the memories, caches, registers
754%% etc. in the device. Is CL_FALSE if the device does not implement error
755%% correction. This can be a requirement for certain clients of
756%% OpenCL.</dd>
757%%
758%% <dt>'profiling_timer_resolution'</dt> <dd> <p>Describes the resolution
759%% of device timer. This is measured in nanoseconds.</p> </dd>
760%%
761%% <dt>'endian_little'</dt> <dd> Is CL_TRUE if the OpenCL device is a
762%% little endian device and CL_FALSE otherwise.  </dd>
763%%
764%% <dt>'available'</dt> <dd> Is CL_TRUE if the device is available and
765%% CL_FALSE if the device is not available.  </dd>
766%%
767%% <dt>'compiler_available'</dt> <dd> Is CL_FALSE if the implementation
768%% does not have a compiler available to compile the program source. Is
769%% CL_TRUE if the compiler is available. This can be CL_FALSE for the
770%% embededed platform profile only.  </dd>
771%%
772%% <dt>'execution_capabilities'</dt> <dd> <p>Return type:
773%% cl_device_exec_capabilities</p> <p>Describes the execution
774%% capabilities of the device. This is a bit-field that describes one or
775%% more of the following values:</p> <p>CL_EXEC_KERNEL - The OpenCL
776%% device can execute OpenCL kernels.</p> <p>CL_EXEC_NATIVE_KERNEL - The
777%% OpenCL device can execute native kernels.</p> <p>The mandated minimum
778%% capability is CL_EXEC_KERNEL.</p> </dd>
779%%
780%% <dt>'queue_properties'</dt> <dd> <p>Describes the command-queue
781%% properties supported by the device.  This is a bit-field that
782%% describes one or more of the following values:</p>
783%% <p>'out_of_order_exec_mode_enable'</p>
784%% <p>'profiling_enable'</p> <p>These properties are described in
785%% the table for create_queue/3 .  The mandated minimum capability is
786%% 'profiling_enable'.</p> </dd>
787%%
788%% <dt>'name'</dt> <dd> <p>Device name string.</p> </dd>
789%%
790%% <dt>'vendor'</dt> <dd><p>Vendor name string.</p></dd>
791%%
792%% <dt>'driver_version'</dt> <dd><p>OpenCL software driver version string</p> </dd>
793%%
794%% <dt>'profile'</dt> <dd> <p>OpenCL profile string. Returns the profile
795%% name supported by the device (see note). The profile name returned can
796%% be one of the following strings:</p>
797%% <p>FULL_PROFILE - if the device supports the OpenCL specification
798%% (functionality defined as part of the core
799%% specification and does not require any extensions
800%% to be supported).</p> <p>EMBEDDED_PROFILE - if
801%% the device supports the OpenCL embedded
802%% profile.</p></dd>
803%%
804%% <dt>'version'</dt> <dd> <p>OpenCL version string.</p> </dd>
805%%
806%% <dt>'extensions' </dt> <dd><p>Returns a space separated list of extension names (the extension
807%% names themselves do not contain any spaces). </p></dd>
808%%
809%% <dt>'platform' </dt> <dd> <p>The platform associated with this device.</p> </dd>
810%%
811%% </dl>
812%%
813%% <c>NOTE</c>: CL_DEVICE_PROFILE: The platform profile returns the profile that is
814%% implemented by the OpenCL framework. If the platform profile
815%% returned is FULL_PROFILE, the OpenCL framework will support devices
816%% that are FULL_PROFILE and may also support devices that are
817%% EMBEDDED_PROFILE. The compiler must be available for all devices
818%% i.e. CL_DEVICE_COMPILER_AVAILABLE is CL_TRUE. If the platform
819%% profile returned is EMBEDDED_PROFILE, then devices that are only
820%% EMBEDDED_PROFILE are supported.
821
822-spec get_device_info(Device::cl_device_id(), Info::cl_device_info_key()) ->
823    {'ok', term()} | {'error', cl_error()}.
824
825get_device_info(_Device, _Info) ->
826    ?nif_stub.
827
828%%
829%% @spec get_device_info(Device) ->
830%%    {'ok', [cl_device_info()]} | {'error', cl_error()}
831%% @doc Get all device info.
832%% @see get_device_info/2
833-spec get_device_info(Device::cl_device_id()) ->
834    {'ok', [cl_device_info()]} | {'error', cl_error()}.
835
836get_device_info(Device) ->
837    get_info_list(Device, device_info(), fun get_device_info/2).
838
839%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
840%% Context
841%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
842
843%% @type cl_context_info_key() = {'reference_count' | 'devices' | 'properties'}
844-type cl_context_info_key() :: 'reference_count' | 'devices' | 'properties'.
845
846%% @type cl_context_info() =
847%%  { {'reference_count', cl_uint()},
848%%    {'devices', [cl_device()]},
849%%    {'properties', [cl_int()]} }
850-type cl_context_info() ::
851	{'reference_count', cl_uint()} |
852	{'devices', [cl_device_id()]} |
853	{'properties', [cl_int()]}.
854
855%%
856%% @spec create_context(DeviceList::[cl_device_id()]) ->
857%%    {'ok', cl_context()} | {'error', cl_error()}
858%% @doc Creates an OpenCL context.
859%%
860%% An OpenCL context is created with one or more devices. Contexts are
861%% used by the OpenCL runtime for managing objects such as
862%% command-queues, memory, program and kernel objects and for
863%% executing kernels on one or more devices specified in the context.
864%%
865%% NOTE: create_context/1 and create_context_from_type/1 perform an
866%% implicit retain. This is very helpful for 3rd party libraries,
867%% which typically get a context passed to them by the
868%% application. However, it is possible that the application may
869%% delete the context without informing the library. Allowing
870%% functions to attach to (i.e. retain) and release a context solves
871%% the problem of a context being used by a library no longer being
872%% valid.
873
874-spec create_context(DeviceList::[cl_device_id()]) ->
875    {'ok', cl_context()} | {'error', cl_error()}.
876
877create_context(_DeviceList) ->
878    ?nif_stub.
879
880%%
881%% @spec create_context_from_type(Type::cl_device_types())->
882%%    {'ok', cl_context()} | {'error', cl_error()}
883%% @doc Create an OpenCL context from a device type that identifies the specific device(s) to use.
884%%
885%% NOTE:
886%% create_context_from_type/1 may return all or a subset of the
887%% actual physical devices present in the platform and that match
888%% device_type.
889%%
890%% create_context/1 and create_context_from_type/1 perform an
891%% implicit retain. This is very helpful for 3rd party libraries,
892%% which typically get a context passed to them by the
893%% application. However, it is possible that the application may
894%% delete the context without informing the library. Allowing
895%% functions to attach to (i.e. retain) and release a context solves
896%% the problem of a context being used by a library no longer being
897%% valid.
898-spec create_context_from_type(Type::cl_device_types())->
899    {'ok', cl_context()} | {'error', cl_error()}.
900
901create_context_from_type(Type) ->
902    case get_device_ids(undefined, Type) of
903	{ok,DeviceList} ->
904	    create_context(DeviceList);
905	Error ->
906	    Error
907    end.
908
909%%
910%% @spec release_context(Context::cl_context()) ->
911%%    'ok' | {'error', cl_error()}
912%% @doc Decrement the context reference count.
913%%
914%% After the context reference count becomes zero and all the objects
915%% attached to context (such as memory objects, command-queues) are
916%% released, the context is deleted.
917-spec release_context(Context::cl_context()) ->
918    'ok' | {'error', cl_error()}.
919
920release_context(Context) when ?is_context(Context) ->
921    ok.
922
923%%
924%% @spec retain_context(Context::cl_context()) ->
925%%     'ok' | {'error', cl_error()}
926%% @doc Increment the context reference count.
927%% @see create_context
928-spec retain_context(Context::cl_context()) ->
929    'ok' | {'error', cl_error()}.
930
931retain_context(Context) when ?is_context(Context) ->
932    ok.
933
934%%
935%% @spec context_info() -> [cl_context_info_key()]
936%% @doc List context info queries.
937-spec context_info() -> [cl_context_info_key()].
938
939context_info() ->
940    [
941     reference_count,
942     devices,
943     properties
944    ].
945%%
946%% @spec get_context_info(Context::cl_context(),Info::cl_context_info_key()) ->
947%%   {'ok', term()} | {'error', cl_error()}
948%% @doc  Query information about a context.
949%%
950%% <dl> <dt>reference_count</dt> <dd> Return the context reference
951%% count. The reference count returned should be considered
952%% immediately stale. It is unsuitable for general use in
953%% applications. This feature is provided for identifying memory
954%% leaks. </dd>
955%%
956%% <dt>devices</dt> <dd>Return the list of devices in context.</dd>
957%%
958%% <dt>properties</dt> <dd>Return the context properties.</dd>
959%% </dl>
960-spec get_context_info(Context::cl_context(), Info::cl_context_info_key()) ->
961    {'ok', term()} | {'error', cl_error()}.
962
963get_context_info(_Context, _Info) ->
964    ?nif_stub.
965
966
967%% @spec get_context_info(Context::cl_context()) ->
968%%    {'ok', [cl_context_info()]} | {'error', cl_error()}
969%% @doc Get all context info.
970%% @see get_context_info/2
971-spec get_context_info(Context::cl_context()) ->
972    {'ok', [cl_context_info()]} | {'error', cl_error()}.
973
974get_context_info(Context) when ?is_context(Context) ->
975    get_info_list(Context, context_info(), fun get_context_info/2).
976
977%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
978%% Command Queue (Queue)
979%% @type cl_queue_property() = { 'out_of_order_exec_mode_enable' |
980%%			         'profiling_enabled' }
981%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
982-type cl_queue_property() :: 'out_of_order_exec_mode_enable' | 'profiling_enabled'.
983%%
984%% @spec create_queue(Context::cl_context(),Device::cl_device_id(),
985%%                    Properties::[cl_queue_property()]) ->
986%%    {'ok', cl_queue()} | {'error', cl_error()}
987%% @doc Create a command-queue on a specific device.
988%%
989%% <dl>
990%% <dt>'out_of_order_exec_mode_enable'</dt> <dd> Determines
991%% whether the commands queued in the command-queue are executed
992%% in-order or out-of-order. If set, the commands in the command-queue
993%% are executed out-of-order. Otherwise, commands are executed
994%% in-order.</dd>
995%%
996%% <dt>'profiling_enabled'</dt> <dd> Enable or disable profiling of
997%% commands in the command-queue. If set, the profiling of commands is
998%% enabled. Otherwise profiling of commands is disabled. See
999%% clGetEventProfilingInfo for more information.
1000%% </dd>
1001%% </dl>
1002%%
1003%% The OpenCL functions that are submitted to a command-queue are
1004%% enqueued in the order the calls are made but can be configured to
1005%% execute in-order or out-of-order. The properties argument in
1006%% clCreateCommandQueue can be used to specify the execution order.
1007%%
1008%% If the 'out_of_order_exec_mode_enable' property of a
1009%% command-queue is not set, the commands enqueued to a command-queue
1010%% execute in order. For example, if an application calls
1011%% clEnqueueNDRangeKernel to execute kernel A followed by a
1012%% clEnqueueNDRangeKernel to execute kernel B, the application can
1013%% assume that kernel A finishes first and then kernel B is
1014%% executed. If the memory objects output by kernel A are inputs to
1015%% kernel B then kernel B will see the correct data in memory objects
1016%% produced by execution of kernel A. If the
1017%% 'out_of_order_exec_mode_enable' property of a commandqueue
1018%% is set, then there is no guarantee that kernel A will finish before
1019%% kernel B starts execution.
1020%%
1021%% Applications can configure the commands enqueued to a command-queue
1022%% to execute out-of-order by setting the
1023%% 'out_of_order_exec_mode_enable' property of the
1024%% command-queue. This can be specified when the command-queue is
1025%% created or can be changed dynamically using
1026%% clCreateCommandQueue. In out-of-order execution mode there is no
1027%% guarantee that the enqueued commands will finish execution in the
1028%% order they were queued. As there is no guarantee that kernels will
1029%% be executed in order, i.e. based on when the clEnqueueNDRangeKernel
1030%% calls are made within a command-queue, it is therefore possible
1031%% that an earlier clEnqueueNDRangeKernel call to execute kernel A
1032%% identified by event A may execute and/or finish later than a
1033%% clEnqueueNDRangeKernel call to execute kernel B which was called by
1034%% the application at a later point in time. To guarantee a specific
1035%% order of execution of kernels, a wait on a particular event (in
1036%% this case event A) can be used. The wait for event A can be
1037%% specified in the event_wait_list argument to clEnqueueNDRangeKernel
1038%% for kernel B.
1039%%
1040%% In addition, a wait for events or a barrier command can be enqueued
1041%% to the command-queue. The wait for events command ensures that
1042%% previously enqueued commands identified by the list of events to
1043%% wait for have finished before the next batch of commands is
1044%% executed. The barrier command ensures that all previously enqueued
1045%% commands in a command-queue have finished execution before the next
1046%% batch of commands is executed.
1047%%
1048%% Similarly, commands to read, write, copy or map memory objects that
1049%% are enqueued after clEnqueueNDRangeKernel, clEnqueueTask or
1050%% clEnqueueNativeKernel commands are not guaranteed to wait for
1051%% kernels scheduled for execution to have completed (if the
1052%% 'out_of_order_exec_mode_enable' property is set). To ensure
1053%% correct ordering of commands, the event object returned by
1054%% clEnqueueNDRangeKernel, clEnqueueTask or clEnqueueNativeKernel can
1055%% be used to enqueue a wait for event or a barrier command can be
1056%% enqueued that must complete before reads or writes to the memory
1057%% object(s) occur.
1058-spec create_queue(Context::cl_context(),Device::cl_device_id(),
1059		   Properties::[cl_queue_property()]) ->
1060    {'ok', cl_queue()} | {'error', cl_error()}.
1061
1062create_queue(_Context, _Device, _Properties) ->
1063    ?nif_stub.
1064
1065%%
1066%% @spec set_queue_property(Queue::cl_queue(),
1067%%                          Properties::[cl_queue_property()],
1068%%                          Enable::bool()) ->
1069%%    'ok' | {'error', cl_error()}
1070%% @doc Function is deprecated and have been removed.
1071-spec set_queue_property(_, _, _) -> no_return().
1072set_queue_property(_Queue, _Properties, _Enable) ->
1073    erlang:error(deprecated).
1074
1075%%
1076%% @spec release_queue(Queue::cl_queue()) ->
1077%%    'ok' | {'error', cl_error()}
1078%% @doc Decrements the command_queue reference count.
1079%%
1080%% After the command_queue reference count becomes zero and all
1081%% commands queued to command_queue have finished (e.g., kernel
1082%% executions, memory object updates, etc.), the command-queue is
1083%% deleted.
1084-spec release_queue(Queue::cl_queue()) ->
1085    'ok' | {'error', cl_error()}.
1086release_queue(Queue) when ?is_queue(Queue) ->
1087    ok.
1088
1089%%
1090%% @spec retain_queue(Queue::cl_queue()) ->
1091%%    'ok' | {'error', cl_error()}
1092%% @doc Increments the command_queue reference count.
1093%%
1094%%  create_queue/3 performs an implicit retain. This is very
1095%%  helpful for 3rd party libraries, which typically get a
1096%%  command-queue passed to them by the application. However, it is
1097%%  possible that the application may delete the command-queue without
1098%%  informing the library. Allowing functions to attach to
1099%%  (i.e. retain) and release a command-queue solves the problem of a
1100%%  command-queue being used by a library no longer being valid.
1101
1102-spec retain_queue(Queue::cl_queue()) ->
1103    'ok' | {'error', cl_error()}.
1104
1105retain_queue(Queue) when ?is_queue(Queue) ->
1106    ok.
1107
1108%% @spec queue_info() -> [queue_info_keys()]
1109%% @doc Returns the list of possible queue info items.
1110queue_info() ->
1111    [
1112     context,
1113     device,
1114     reference_count,
1115     properties
1116    ].
1117
1118%% @spec get_queue_info(Queue, Info) -> {ok, term()}
1119%% @doc Return the specified queue info
1120get_queue_info(_Queue, _Info) ->
1121    ?nif_stub.
1122
1123%% @spec get_queue_info(Queue) -> [queue_info_keys()]
1124%% @doc Returns all queue info.
1125get_queue_info(Queue) when ?is_queue(Queue) ->
1126    get_info_list(Queue, queue_info(), fun get_queue_info/2).
1127
1128
1129%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1130%% Mem
1131%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1132
1133%%
1134%% @type cl_mem_flag() = { 'read_write' | 'write_only' | 'read_only' |
1135%%                         'use_host_ptr' | 'alloc_host_ptr' |
1136%%                         'copy_host_ptr'}
1137%%
1138-type cl_mem_flag() :: 'read_write' | 'write_only' | 'read_only' |
1139		       'use_host_ptr' | 'alloc_host_ptr' |
1140		       'copy_host_ptr'.
1141
1142%%
1143%% @spec create_buffer(Context::cl_context(),Flags::cl_mem_flags(),
1144%%                      Size::non_neg_integer()) ->
1145%%    {'ok', cl_mem()} | {'error', cl_error()}
1146%%
1147%% @equiv create_buffer(Context,Flags,Size,<<>>)
1148%%
1149-spec create_buffer(Context::cl_context(),Flags::[cl_mem_flag()],
1150		    Size::non_neg_integer()) ->
1151    {'ok', cl_mem()} | {'error', cl_error()}.
1152
1153create_buffer(Context,Flags,Size) ->
1154    create_buffer(Context,Flags,Size,[]).
1155
1156%%
1157%% @spec create_buffer(Context::cl_context(),Flags::[cl_mem_flag()],
1158%%                      Size::non_neg_integer(), Data::iolist()) ->
1159%%    {'ok', cl_mem()} | {'error', cl_error()}
1160%% @doc  Creates a buffer object.
1161%%
1162-spec create_buffer(Context::cl_context(),Flags::[cl_mem_flag()],
1163		    Size::non_neg_integer(),Data::iodata()) ->
1164    {'ok', cl_mem()} | {'error', cl_error()}.
1165
1166create_buffer(_Context,_Flags,_Size,_Data) ->
1167    ?nif_stub.
1168
1169%%
1170%% @doc Creates a buffer object
1171%%
1172-spec create_sub_buffer(Buffer::cl_mem(),Flags::[cl_mem_flag()],
1173                         Type::'region', Info::[non_neg_integer()]) ->
1174    {'ok', cl_mem()} | {'error', cl_error()}.
1175
1176%%
1177create_sub_buffer(_Buffer, _Flags, _Type, _Info) ->
1178    ?nif_stub.
1179
1180%%
1181%% @spec release_mem_object(Mem::cl_mem()) ->
1182%%    'ok' | {'error', cl_error()}
1183%% @doc  Decrements the memory object reference count.
1184%%
1185%% After the memobj reference count becomes zero and commands queued
1186%% for execution on a command-queue(s) that use memobj have finished,
1187%% the memory object is deleted.
1188-spec release_mem_object(Mem::cl_mem()) ->
1189    'ok' | {'error', cl_error()}.
1190
1191release_mem_object(Mem) when ?is_mem(Mem) ->
1192    ok.
1193
1194%%
1195%% @spec retain_mem_object(Mem::cl_mem()) ->
1196%%    'ok' | {'error', cl_error()}
1197%% @doc Increments the memory object reference count.
1198-spec retain_mem_object(Mem::cl_mem()) ->
1199    'ok' | {'error', cl_error()}.
1200
1201retain_mem_object(Mem) when ?is_mem(Mem) ->
1202    ok.
1203
1204
1205-type cl_mem_info_key() ::
1206	'object_type' | 'flags' | 'size' | 'host_ptr' | 'map_count' |
1207	'reference_count' | 'context'.
1208
1209
1210%%
1211%% @spec mem_object_info() ->
1212%%    [cl_mem_info_keys()]
1213%% @doc Returns a list of the possible mem info keys.
1214-spec mem_object_info() ->
1215    [cl_mem_info_key()].
1216
1217mem_object_info() ->
1218    [
1219     object_type,
1220     flags,
1221     size,
1222     host_ptr,
1223     map_count,
1224     reference_count,
1225     context
1226    ].
1227
1228%%
1229%% @spec get_mem_object_info(Mem::cl_mem(), InfoType::cl_mem_info_key()) ->
1230%%    {'ok', term()} | {'error', cl_error()}
1231%%
1232%% @doc Used to get <c>InfoType</c> information that is common to all memory objects
1233%% (buffer and image objects).
1234-spec get_mem_object_info(Mem::cl_mem(), Info::cl_mem_info_key()) ->
1235    {'ok', term()} | {'error', cl_error()}.
1236
1237get_mem_object_info(_Mem, _Info) ->
1238    ?nif_stub.
1239
1240%%
1241%% @spec get_mem_object_info(Mem::cl_mem()) ->
1242%%    {'ok', term()} | {'error', cl_error()}
1243%%
1244%% @doc Used to get all information that is common to all memory objects
1245%% (buffer and image objects).
1246get_mem_object_info(Mem) when ?is_mem(Mem) ->
1247    get_info_list(Mem, mem_object_info(), fun get_mem_object_info/2).
1248
1249image_info() ->
1250    [
1251     format,
1252     element_size,
1253     row_pitch,
1254     slice_pitch,
1255     width,
1256     height,
1257     depth
1258    ].
1259
1260get_image_info(_Mem, _Info) ->
1261    ?nif_stub.
1262
1263get_image_info(Mem) when ?is_mem(Mem) ->
1264    get_info_list(Mem, image_info(), fun get_image_info/2).
1265
1266%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1267%% Sample
1268%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1269
1270%% @type cl_addressing_mode() = {'none'|'clamp_to_edge'|'clamp'|'repeat'}
1271%%
1272-type cl_addressing_mode() :: 'none'|'clamp_to_edge'|'clamp'|'repeat'.
1273
1274%% @type cl_filter_mode() = {'nearest' | 'linear' }
1275-type cl_filter_mode() :: 'nearest' | 'linear'.
1276
1277%%
1278%% @spec create_sampler(Context::cl_context(),Normalized::boolean(),
1279%%                      AddressingMode::cl_addressing_mode(),
1280%%                      FilterMode::cl_filter_mode()) ->
1281%%    {'ok', cl_sampler()} | {'error', cl_error()}
1282%% @doc Creates a sampler object.
1283%%
1284%%  A sampler object describes how to sample an image when the image
1285%%  is read in the kernel. The built-in functions to read from an
1286%%  image in a kernel take a sampler as an argument. The sampler
1287%%  arguments to the image read function can be sampler objects
1288%%  created using OpenCL functions and passed as argument values to
1289%%  the kernel or can be samplers declared inside a kernel. In this
1290%%  section we discuss how sampler objects are created using OpenCL
1291%%  functions.
1292-spec create_sampler(Context::cl_context(),Normalized::boolean(),
1293		     AddressingMode::cl_addressing_mode(),
1294		     FilterMode::cl_filter_mode()) ->
1295    {'ok', cl_sampler()} | {'error', cl_error()}.
1296
1297create_sampler(_Context, _Normalized, _AddressingMode, _FilterMode) ->
1298    ?nif_stub.
1299
1300%%
1301%% @spec release_sampler(Sampler::cl_sampler()) ->
1302%%    'ok' | {'error', cl_error()}
1303%% @doc Decrements the sampler reference count.
1304%%
1305%%  The sampler object is deleted after the reference count becomes
1306%%  zero and commands queued for execution on a command-queue(s) that
1307%%  use sampler have finished.
1308-spec release_sampler(Sampler::cl_sampler()) ->
1309    'ok' | {'error', cl_error()}.
1310
1311release_sampler(Sampler) when ?is_sampler(Sampler) ->
1312    ok.
1313
1314%%
1315%% @spec retain_sampler(Sampler::cl_sampler()) ->
1316%%    'ok' | {'error', cl_error()}
1317%% @doc Increments the sampler reference count.
1318-spec retain_sampler(Sampler::cl_sampler()) ->
1319    'ok' | {'error', cl_error()}.
1320
1321retain_sampler(Sampler) when ?is_sampler(Sampler) ->
1322    ok.
1323
1324sampler_info() ->
1325    [
1326     reference_count,
1327     context,
1328     normalized_coords,
1329     addressing_mode,
1330     filter_mode
1331    ].
1332
1333%% @spec get_sampler_info(Sampler::cl_sampler(), InfoType::cl_sampler_info_type()) ->
1334%%    {'ok', term()} | {'error', cl_error()}
1335%% @doc Returns <c>InfoType</c> information about the sampler object.
1336get_sampler_info(_Sampler, _Info) ->
1337    ?nif_stub.
1338
1339
1340%% @spec get_sampler_info(Sampler::cl_sampler()) -> {'ok', term()} | {'error', cl_error()}
1341%% @doc Returns all information about the sampler object.
1342%% @see get_sampler_info/2
1343get_sampler_info(Sampler) ->
1344    get_info_list(Sampler, sampler_info(), fun get_sampler_info/2).
1345
1346%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1347%% Program
1348%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1349
1350%%
1351%% @spec create_program_with_source(Context::cl_context(),
1352%%                                  Source::iodata()) ->
1353%%    {'ok', cl_program()} | {'error', cl_error()}
1354%%
1355%% @doc Creates a program object for a context,
1356%% and loads the source code specified by the text strings in the
1357%% strings array into the program object.
1358%%
1359%%  The devices associated with the program object are the devices associated with context.
1360
1361%% OpenCL allows applications to create a program object using the
1362%% program source or binary and build appropriate program
1363%% executables. This allows applications to determine whether they
1364%% want to use the pre-built offline binary or load and compile the
1365%% program source and use the executable compiled/linked online as the
1366%% program executable. This can be very useful as it allows
1367%% applications to load and build program executables online on its
1368%% first instance for appropriate OpenCL devices in the system. These
1369%% executables can now be queried and cached by the
1370%% application. Future instances of the application launching will no
1371%% longer need to compile and build the program executables. The
1372%% cached executables can be read and loaded by the application, which
1373%% can help significantly reduce the application initialization time.
1374
1375%% An OpenCL program consists of a set of kernels that are identified
1376%% as functions declared with the __kernel qualifier in the program
1377%% source. OpenCL programs may also contain auxiliary functions and
1378%% constant data that can be used by __kernel functions. The program
1379%% executable can be generated online or offline by the OpenCL
1380%% compiler for the appropriate target device(s).
1381%%
1382%% @todo allow iodata and handle multiple binaries in the driver
1383%%
1384-spec create_program_with_source(Context::cl_context(),
1385				 Source::iodata()) ->
1386    {'ok', cl_program()} | {'error', cl_error()}.
1387
1388create_program_with_source(_Context, _Source) ->
1389    ?nif_stub.
1390
1391%%
1392%% @spec create_program_with_binary(Context::cl_context(),
1393%%                                  DeviceList::[cl_device_id()],
1394%%                                  BinaryList::[binary()]) ->
1395%%    {'ok', cl_program()} | {'error', cl_error()}
1396%%
1397%% @doc  Creates a program object for a context, and loads specified binary data into the program object.
1398%%
1399%% OpenCL allows applications to create a program object using the
1400%% program source or binary and build appropriate program
1401%% executables. This allows applications to determine whether they
1402%% want to use the pre-built offline binary or load and compile the
1403%% program source and use the executable compiled/linked online as the
1404%% program executable. This can be very useful as it allows
1405%% applications to load and build program executables online on its
1406%% first instance for appropriate OpenCL devices in the system. These
1407%% executables can now be queried and cached by the
1408%% application. Future instances of the application launching will no
1409%% longer need to compile and build the program executables. The
1410%% cached executables can be read and loaded by the application, which
1411%% can help significantly reduce the application initialization time.
1412%%
1413%%  The binaries and device can be generated by calling:
1414%%  <code>
1415%%    {ok,P} = cl:create_program_with_source(Context,Source),
1416%%    ok = cl:build_program(P, DeviceList, Options),
1417%%    {ok,DeviceList} = cl:get_program_info(P, devices),
1418%%    {ok,BinaryList} = cl:get_program_info(P, binaries).
1419%%  </code>
1420%%
1421-spec create_program_with_binary(Context::cl_context(),
1422				 DeviceList::[cl_device_id()],
1423				 BinaryList::[binary()]) ->
1424    {'ok', cl_program()} | {'error', cl_error()}.
1425
1426create_program_with_binary(_Context, _DeviceList, _BinaryList) ->
1427    ?nif_stub.
1428
1429-spec create_program_with_builtin_kernels(Context::cl_context(),
1430					  DeviceList::[cl_device_id()],
1431					  KernelNames::string()) ->
1432    {'ok', cl_program()} | {'error', cl_error()}.
1433
1434create_program_with_builtin_kernels(_Context, _DeviceList, _KernelNames) ->
1435    ?nif_stub.
1436
1437%%
1438%% @spec retain_program(Program::cl_program()) ->
1439%%    'ok' | {'error', cl_error()}
1440%% @doc  Increments the program reference count.
1441retain_program(Program) when ?is_program(Program) ->
1442    ok.
1443
1444%%
1445%% @spec release_program(Program::cl_program()) ->
1446%%    'ok' | {'error', cl_error()}
1447%% @doc Decrements the program reference count.
1448%%
1449%% The program object is deleted after all kernel objects associated
1450%% with program have been deleted and the program reference count
1451%% becomes zero.
1452release_program(Program) when ?is_program(Program) ->
1453    ok.
1454
1455%%
1456%% @spec build_program(Program::cl_program(),
1457%%                     DeviceList::[cl_device_id()],
1458%%                     Options::string()) ->
1459%%  'ok' | {'error', cl_error()}
1460%%
1461%% @doc Builds (compiles and links) a program executable from the
1462%% program source or binary.
1463%%
1464%% OpenCL allows program executables to be built using the source or the binary.
1465%%
1466%% The build options are categorized as pre-processor options, options
1467%% for math intrinsics, options that control optimization and
1468%% miscellaneous options. This specification defines a standard set of
1469%% options that must be supported by an OpenCL compiler when building
1470%% program executables online or offline. These may be extended by a
1471%% set of vendor- or platform-specific options.
1472%%
1473%% <h4>Preprocessor Options</h4> These options
1474%% control the OpenCL preprocessor which is run on each program source
1475%% before actual compilation. -D options are processed in the order
1476%% they are given in the options argument to
1477%% <code>build_program/3</code>.
1478%%
1479%% <dl>
1480%% <dt><span>-D name</span></dt><dd>
1481%% <p> Predefine <code>name</code> as a macro, with definition 1.</p></dd>
1482%% <dt>-D name=definition</dt><dd><p> The contents of <code>definition</code>
1483%% are tokenized and processed as if they appeared during translation phase three in a `#define'
1484%% directive. In particular, the definition will be truncated by
1485%% embedded newline characters.  </p></dd>
1486%% <dt>-I dir</dt><dd> <p>Add the directory <code>dir</code> to the list of directories to be
1487%% searched for header files.</p> </dd></dl>
1488%% <br />
1489%%
1490%% <h4>Math Intrinsics Options</h4> These options control compiler
1491%% behavior regarding floating-point arithmetic. These options trade
1492%% off between speed and correctness.
1493%% <dl><dt>-cl-single-precision-constant</dt><dd><p> Treat double
1494%% precision floating-point constant as single precision constant.
1495%% </p></dd><dt>-cl-denorms-are-zero</dt><dd><p> This option controls
1496%% how single precision and double precision denormalized numbers are
1497%% handled. If specified as a build option, the single precision
1498%% denormalized numbers may be flushed to zero and if the optional
1499%% extension for double precision is supported, double precision
1500%% denormalized numbers may also be flushed to zero. This is intended
1501%% to be a performance hint and the OpenCL compiler can choose not to
1502%% flush denorms to zero if the device supports single precision (or
1503%% double precision) denormalized numbers.  </p><p> This option is
1504%% ignored for single precision numbers if the device does not support
1505%% single precision denormalized numbers i.e. CL_FP_DENORM bit is not
1506%% set in CL_DEVICE_SINGLE_FP_CONFIG.  </p><p> </p><p> This option is
1507%% ignored for double precision numbers if the device does not support
1508%% double precision or if it does support double precison but
1509%% CL_FP_DENORM bit is not set in CL_DEVICE_DOUBLE_FP_CONFIG.  </p><p>
1510%%
1511%% This flag only applies for scalar and vector single precision
1512%% floating-point variables and computations on these floating-point
1513%% variables inside a program. It does not apply to reading from or
1514%% writing to image objects.  </p><p> </p></dd></dl><p><br />
1515%% </p>
1516%%
1517%% <h4>Optimization Options</h4> These options control various
1518%% sorts of optimizations. Turning on optimization flags makes the
1519%% compiler attempt to improve the performance and/or code size at the
1520%% expense of compilation time and possibly the ability to debug the
1521%% program.  <dl><dt>-cl-opt-disable</dt><dd><p> This option
1522%% disables all optimizations. The default is optimizations are
1523%% enabled.  </p></dd><dt>-cl-strict-aliasing</dt><dd><p> This option
1524%% allows the compiler to assume the strictest aliasing rules.
1525%% </p></dd></dl>
1526%%<p> The following options control compiler
1527%% behavior regarding floating-point arithmetic. These options trade
1528%% off between performance and correctness and must be specifically
1529%% enabled. These options are not turned on by default since it can
1530%% result in incorrect output for programs which depend on an exact
1531%% implementation of IEEE 754 rules/specifications for math functions.
1532%% </p><dl><dt>-cl-mad-enable</dt><dd><p> Allow <code>a * b + c</code>
1533%% to be replaced by a <code>mad</code>. The <code>mad</code> computes
1534%% <code>a * b + c</code> with reduced accuracy. For example, some
1535%% OpenCL devices implement <code>mad</code> as truncate
1536%% the result of <code>a * b</code> before adding it to
1537%% <code>c</code>.  </p></dd>
1538%% <dt>-cl-no-signed-zeros</dt><dd>
1539%% <p> Allow optimizations for floating-point arithmetic that ignore
1540%% the signedness of zero. IEEE 754 arithmetic specifies the behavior
1541%% of distinct <code>+0.0</code> and <code>-0.0</code> values, which
1542%% then prohibits simplification of expressions such as
1543%% <code>x+0.0</code> or <code>0.0*x</code> (even with -clfinite-math
1544%% only). This option implies that the sign of a zero result isn't
1545%% significant.  </p></dd>
1546%% <dt>-cl-unsafe-math-optimizations</dt><dd><p> Allow optimizations
1547%% for floating-point arithmetic that (a) assume that arguments and
1548%% results are valid, (b) may violate IEEE 754 standard and (c) may
1549%% violate the OpenCL numerical compliance requirements as defined in
1550%% section 7.4 for single-precision floating-point, section 9.3.9 for
1551%% double-precision floating-point, and edge case behavior in section
1552%% 7.5. This option includes the -cl-no-signed-zeros and
1553%% -cl-mad-enable options.  </p></dd>
1554%%<dt><span class="term">-cl-finite-math-only</span></dt><dd><p>
1555%% Allow optimizations for floating-point arithmetic that assume that arguments and results
1556%% are not NaNs or ±infinity. This option may violate the OpenCL numerical compliance
1557%% requirements defined in in section 7.4 for single-precision floating-point,
1558%% section 9.3.9 for double-precision floating-point, and edge case behavior in section 7.5.
1559%% </p></dd>
1560%%<dt><span class="term">-cl-fast-relaxed-math</span></dt><dd><p>
1561%% Sets the optimization options -cl-finite-math-only and -cl-unsafe-math-optimizations.
1562%% This allows optimizations for floating-point arithmetic that may violate the IEEE 754
1563%% standard and the OpenCL numerical compliance requirements defined in the specification in section 7.4 for single-precision floating-point, section 9.3.9 for double-precision floating-point,
1564%% and edge case behavior in section 7.5. This option causes the preprocessor macro
1565%%
1566%% <code>__FAST_RELAXED_MATH__</code> to be defined in the OpenCL program.
1567%% </p></dd></dl><p><br />
1568%% </p><h4>Options to Request or Suppress Warnings</h4>
1569%% Warnings are diagnostic messages that report constructions which are not inherently erroneous
1570%% but which are risky or suggest there may have been an error. The following languageindependent
1571%% options do not enable specific warnings but control the kinds of diagnostics
1572%% produced by the OpenCL compiler.
1573%% <dl><dt><span class="term">-w</span></dt><dd><p>
1574%% Inhibit all warning messages.
1575%% </p></dd><dt><span class="term">-Werror</span></dt><dd><p>
1576%% Make all warnings into errors.
1577%% </p></dd>
1578%%</dl>
1579
1580build_program(Program, DeviceList, Options) ->
1581    case async_build_program(Program, DeviceList, Options) of
1582	{ok,Ref} ->
1583	    receive
1584		{cl_async,Ref,Reply} ->
1585		    Reply
1586	    end;
1587	Error ->
1588	    Error
1589    end.
1590
1591async_build_program(_Program, _DeviceList, _Options) ->
1592    ?nif_stub.
1593
1594
1595%%
1596%% @spec unload_compiler() -> 'ok' | {'error', cl_error()}
1597%% @doc Allows the implementation to release the resources allocated by the OpenCL compiler.
1598%%
1599%% This is a hint from the application and does not guarantee that the
1600%% compiler will not be used in the future or that the compiler will
1601%% actually be unloaded by the implementation. Calls to build_program/3
1602%% after unload_compiler/0 will reload the compiler, if necessary, to
1603%% build the appropriate program executable.
1604unload_compiler() ->
1605    ?nif_stub.
1606
1607%% @spec unload_platform_compiler(Platform :: cl_platform_id()) ->
1608%%   'ok' | {'error', cl_error()}
1609-spec unload_platform_compiler(Platform::cl_platform_id()) ->
1610    'ok' | {'error', cl_error()}.
1611unload_platform_compiler(_Platform) ->
1612    ?nif_stub.
1613
1614-spec compile_program(Program::cl_program(),
1615		      DeviceList::[cl_device_id()],
1616		      Options::string(),
1617		      Headers::[cl_program()],
1618		      Names::[string()]) ->
1619    'ok' | {'error', cl_error()}.
1620
1621compile_program(Program, Devices, Options, Headers, Names) ->
1622    case async_compile_program(Program, Devices, Options, Headers, Names) of
1623	{ok,Ref} ->
1624	    receive
1625		{cl_async,Ref,Reply} ->
1626		    Reply
1627	    end;
1628	Error ->
1629	    Error
1630    end.
1631
1632async_compile_program(_Program, _Devices, _Options, _Headers, _Names) ->
1633    ?nif_stub.
1634
1635
1636-spec link_program(Context::cl_context(),
1637		   DeviceList::[cl_device_id()],
1638		   Options::string(),
1639		   Programs::[cl_program()]) ->
1640    {'ok',cl_program()} | {'error', cl_error()}.
1641
1642link_program(Context, DeviceList, Options, Programs) ->
1643    case async_link_program(Context, DeviceList, Options, Programs) of
1644	{ok,{Ref,Program}} ->
1645	    receive
1646		{cl_async,Ref,ok} ->
1647		    {ok,Program};
1648		{cl_async,Ref,Error} ->
1649		    Error
1650	    end;
1651	Error ->
1652	    Error
1653    end.
1654
1655async_link_program(_Context, _DeviceList, _Options, _Programs) ->
1656    ?nif_stub.
1657
1658
1659program_info() ->
1660    [
1661     reference_count,
1662     context,
1663     num_devices,
1664     devices,
1665     source,
1666     binary_sizes,
1667     binaries
1668    ].
1669
1670%% @doc  Returns specific information about the program object.
1671get_program_info(_Program, _Info) ->
1672    ?nif_stub.
1673
1674%% @doc  Returns all information about the program object.
1675get_program_info(Program) when ?is_program(Program) ->
1676    get_info_list(Program, program_info(), fun get_program_info/2).
1677
1678program_build_info() ->
1679    [
1680     status,
1681     options,
1682     log
1683    ].
1684
1685%% @doc Returns specific build information for each device in the program object.
1686get_program_build_info(_Program, _Device, _Info) ->
1687    ?nif_stub.
1688
1689%% @doc Returns all build information for each device in the program object.
1690get_program_build_info(Program, Device) ->
1691    get_info_list(Program, program_build_info(),
1692		  fun(P, I) ->
1693			  get_program_build_info(P, Device, I)
1694		  end).
1695
1696%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1697%% Kernel
1698%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1699
1700%%
1701%% @spec create_kernel(Program::cl_program(),Name::string()) ->
1702%%    {'ok', cl_kernel()} | {'error', cl_error()}
1703%%
1704%% @doc  Creates a kernal object.
1705%%
1706%%  A kernel is a function declared in a program. A kernel is
1707%%  identified by the __kernel qualifier applied to any function in a
1708%%  program. A kernel object encapsulates the specific __kernel
1709%%  function declared in a program and the argument values to be used
1710%%  when executing this __kernel function.
1711create_kernel(_Program, _Name) ->
1712    ?nif_stub.
1713
1714%%
1715%% @spec create_kernels_in_program(Program::cl_program()) ->
1716%%    {'ok', [cl_kernel()]} | {'error', cl_error()}
1717%%
1718%% @doc Creates kernel objects for all kernel functions in a program object.
1719%%
1720%%  Creates kernel objects for all kernel functions in program. Kernel
1721%%  objects are not created for any __kernel functions in program that
1722%%  do not have the same function definition across all devices for
1723%%  which a program executable has been successfully built.
1724
1725%% Kernel objects can only be created once you have a program object
1726%% with a valid program source or binary loaded into the program
1727%% object and the program executable has been successfully built for
1728%% one or more devices associated with program. No changes to the
1729%% program executable are allowed while there are kernel objects
1730%% associated with a program object. This means that calls to
1731%% clBuildProgram return CL_INVALID_OPERATION if there are kernel
1732%% objects attached to a program object. The OpenCL context associated
1733%% with program will be the context associated with kernel. The list
1734%% of devices associated with program are the devices associated with
1735%% kernel. Devices associated with a program object for which a valid
1736%% program executable has been built can be used to execute kernels
1737%% declared in the program object.
1738create_kernels_in_program(_Program) ->
1739    ?nif_stub.
1740
1741%%
1742%% @type cl_kernel_arg() = integer() | float() | binary()
1743%%
1744%% @spec set_kernel_arg(Kernel::cl_kernel(), Index::non_neg_integer(),
1745%%                      Argument::cl_kernel_arg()) ->
1746%%    'ok' | {'error', cl_error()}
1747%% @doc Used to set the argument value for a specific argument of a kernel.
1748%%
1749%% For now set_kernel_arg handles integer and floats
1750%% to set any other type use `<<Foo:Bar/native...>>'
1751%% use the macros defined in cl.hrl to get it right (except for padding)
1752%%
1753%% A kernel object does not update the reference count for objects
1754%% such as memory, sampler objects specified as argument values by
1755%% set_kernel_arg/3, Users may not rely on a kernel object to retain
1756%% objects specified as argument values to the kernel.
1757%%
1758%% Implementations shall not allow cl_kernel objects to hold reference
1759%% counts to cl_kernel arguments, because no mechanism is provided for
1760%% the user to tell the kernel to release that ownership right. If the
1761%% kernel holds ownership rights on kernel args, that would make it
1762%% impossible for the user to tell with certainty when he may safely
1763%% release user allocated resources associated with OpenCL objects
1764%% such as the cl_mem backing store used with CL_MEM_USE_HOST_PTR.
1765
1766set_kernel_arg(_Kernel,_Index,_Argument) ->
1767    ?nif_stub.
1768
1769%%
1770%% @spec set_kernel_arg_size(Kernel::cl_kernel(), Index::non_neg_integer(),
1771%%                           Size::non_neg_integer()) ->
1772%%    'ok' | {'error', cl_error()}
1773%%
1774%% @doc clErlang special to set kernel arg with size only (local mem etc)
1775%%
1776set_kernel_arg_size(_Kernel,_Index,_Size) ->
1777    ?nif_stub.
1778
1779
1780%%
1781%% @spec retain_kernel(Context::cl_kernel()) ->
1782%%    'ok' | {'error', cl_error()}
1783%% @doc  Increments the program kernel reference count.
1784retain_kernel(Kernel) when ?is_kernel(Kernel) ->
1785    ok.
1786
1787%%
1788%% @spec release_kernel(Context::cl_kernel()) ->
1789%%    'ok' | {'error', cl_error()}
1790%% @doc  Decrements the kernel reference count.
1791release_kernel(Kernel) when ?is_kernel(Kernel) ->
1792    ok.
1793
1794kernel_info() ->
1795    [
1796     function_name,
1797     num_args,
1798     reference_count,
1799     context,
1800     program
1801    ].
1802
1803%% @doc Returns specific information about the kernel object.
1804get_kernel_info(_Kernel, _Info) ->
1805    ?nif_stub.
1806
1807%% @doc Returns all information about the kernel object.
1808get_kernel_info(Kernel) when ?is_kernel(Kernel) ->
1809    get_info_list(Kernel, kernel_info(), fun get_kernel_info/2).
1810
1811kernel_workgroup_info() ->
1812    [
1813     work_group_size,
1814     compile_work_group_size,
1815     local_mem_size
1816    ].
1817
1818%% @doc Returns specific information about the kernel object that may
1819%% be specific to a device.
1820get_kernel_workgroup_info(_Kernel, _Device, _Info) ->
1821    ?nif_stub.
1822
1823
1824%% @doc Returns all information about the kernel object that may be
1825%% specific to a device.
1826get_kernel_workgroup_info(Kernel, Device) ->
1827    get_info_list(Kernel, kernel_workgroup_info(),
1828		  fun(K,I) ->
1829			  get_kernel_workgroup_info(K,Device,I)
1830		  end).
1831
1832%% @doc Returns specific information about the kernel argument
1833get_kernel_arg_info(_Kernel, _ArgIndex, _Info) ->
1834    ?nif_stub.
1835
1836get_kernel_arg_info(Kernel, ArgIndex) ->
1837    get_info_list(Kernel, kernel_arg_info(),
1838		       fun(K,I) ->
1839			       get_kernel_arg_info(K,ArgIndex,I)
1840		       end).
1841
1842get_kernel_arg_info(Kernel) ->
1843    case get_kernel_info(Kernel, num_args) of
1844	{ok, N} ->
1845	    {ok,
1846	     lists:map(fun(I) ->
1847			       {ok,Info} = get_kernel_arg_info(Kernel, I),
1848			       {I,Info}
1849		       end, lists:seq(0, N-1))};
1850	Error ->
1851	    Error
1852    end.
1853
1854kernel_arg_info() ->
1855    [address_qualifier,
1856     access_qualifier,
1857     type_name,
1858     type_qualifier,
1859     name].
1860
1861%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1862%% Events
1863%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
1864
1865%% @spec enqueue_task(Queue::cl_queue(), Kernel::cl_kernel(),
1866%%                    WaitList::[cl_event()]) ->
1867%%    {'ok', cl_event()} | {'error', cl_error()}
1868%%
1869%% @doc Enqueues a command to execute a kernel on a device.
1870%%
1871%% The kernel is executed using a single work-item.
1872%% @see enqueue_nd_range_kernel/5
1873-spec enqueue_task(Queue::cl_queue(), Kernel::cl_kernel(),
1874		   WaitList::[cl_event()]) ->
1875    {'ok', cl_event()} | {'error', cl_error()}.
1876
1877enqueue_task(Queue, Kernel, WaitList) ->
1878    enqueue_task(Queue, Kernel, WaitList, true).
1879
1880-spec nowait_enqueue_task(Queue::cl_queue(), Kernel::cl_kernel(),
1881		   WaitList::[cl_event()]) ->
1882    'ok' | {'error', cl_error()}.
1883
1884nowait_enqueue_task(Queue, Kernel, WaitList) ->
1885    enqueue_task(Queue, Kernel, WaitList, false).
1886
1887enqueue_task(_Queue, _Kernel, _WaitList, _WantEvent) ->
1888    ?nif_stub.
1889
1890%%
1891%% @spec enqueue_nd_range_kernel(Queue::cl_queue(), Kernel::cl_kernel(),
1892%%                               Global::[non_neg_integer()],
1893%%                               Local::[non_neg_integer()],
1894%%                               WaitList::[cl_event()]) ->
1895%%    {'ok', cl_event()} | {'error', cl_error()}
1896%%
1897%% @doc Enqueues a command to execute a kernel on a device.
1898%%
1899%% Work-group instances are executed in parallel across multiple
1900%% compute units or concurrently on the same compute unit.
1901%%
1902%% Each work-item is uniquely identified by a global identifier. The
1903%% global ID, which can be read inside the kernel, is computed using
1904%% the value given by global_work_size and global_work_offset. In
1905%% OpenCL 1.0, the starting global ID is always (0, 0, ... 0). In
1906%% addition, a work-item is also identified within a work-group by a
1907%% unique local ID. The local ID, which can also be read by the
1908%% kernel, is computed using the value given by local_work_size. The
1909%% starting local ID is always (0, 0, ... 0).
1910-spec enqueue_nd_range_kernel(Queue::cl_queue(), Kernel::cl_kernel(),
1911			      Global::[non_neg_integer()],
1912			      Local::[non_neg_integer()],
1913			      WaitList::[cl_event()]) ->
1914    {'ok', cl_event()} | {'error', cl_error()}.
1915
1916
1917enqueue_nd_range_kernel(Queue, Kernel, Global, Local, WaitList) ->
1918    enqueue_nd_range_kernel(Queue, Kernel, Global, Local, WaitList, true).
1919
1920
1921-spec nowait_enqueue_nd_range_kernel(Queue::cl_queue(), Kernel::cl_kernel(),
1922				     Global::[non_neg_integer()],
1923				     Local::[non_neg_integer()],
1924				     WaitList::[cl_event()]) ->
1925    'ok' | {'error', cl_error()}.
1926
1927nowait_enqueue_nd_range_kernel(Queue, Kernel, Global, Local, WaitList) ->
1928    enqueue_nd_range_kernel(Queue, Kernel, Global, Local, WaitList, false).
1929
1930enqueue_nd_range_kernel(_Queue, _Kernel, _Global, _Local, _WaitList,
1931			_WantEvent) ->
1932    ?nif_stub.
1933
1934%% @spec enqueue_marker(Queue::cl_queue()) ->
1935%%    {'ok', cl_event()} | {'error', cl_error()}
1936%%
1937%% @doc  Enqueues a marker command.
1938%%
1939%%  Enqueues a marker command to command_queue. The marker command
1940%%  returns an event which can be used to queue a wait on this marker
1941%%  event i.e. wait for all commands queued before the marker command
1942%%  to complete.
1943-spec enqueue_marker(Queue::cl_queue()) ->
1944    {'ok', cl_event()} | {'error', cl_error()}.
1945
1946enqueue_marker(_Queue) ->
1947    ?nif_stub.
1948
1949%%
1950%% @spec enqueue_wait_for_events(Queue::cl_queue(), WaitList::[cl_event()]) ->
1951%%    'ok' | {'error', cl_error()}
1952%%
1953%% @doc Enqueues a wait for a specific event or a list of events
1954%% to complete before any future commands queued in the command-queue are
1955%% executed.
1956%%
1957%% The context associated with events in WaitList and Queue must be the same.
1958-spec enqueue_wait_for_events(Queue::cl_queue(),  WaitList::[cl_event()]) ->
1959    'ok' | {'error', cl_error()}.
1960
1961enqueue_wait_for_events(_Queue, _WaitList) ->
1962    ?nif_stub.
1963
1964
1965%%
1966%% @doc Enqueue commands to read from a buffer object to host memory.
1967%%
1968%% Calling <code>enqueue_read_buffer</code> to read a region of the
1969%% buffer object with the <code>Buffer</code> argument value set to
1970%% <code>host_ptr</code> + <code >offset</code>, where
1971%% <code>host_ptr</code> is a pointer to the memory region specified
1972%% when the buffer object being read is created with
1973%% <code>CL_MEM_USE_HOST_PTR</code>, must meet the following
1974%% requirements in order to avoid undefined behavior:
1975%%
1976%% <ul> <li>All commands that use this buffer object have finished
1977%% execution before the read command begins execution</li>
1978%% <li>The buffer object is not mapped</li>
1979%% <li>The buffer object is not used by any command-queue until the
1980%% read command has finished execution</li>
1981%% </ul>
1982
1983-spec enqueue_read_buffer(Queue::cl_queue(), Buffer::cl_mem(),
1984			  Offset::non_neg_integer(),
1985			  Size::non_neg_integer(),
1986			  WaitList::[cl_event()]) ->
1987    {'ok', cl_event()} | {'error', cl_error()}.
1988
1989
1990enqueue_read_buffer(_Queue, _Buffer, _Offset, _Size, _WaitList) ->
1991    ?nif_stub.
1992
1993%%
1994%% Read rectangular section from buffer memory into host memory
1995%%
1996-spec enqueue_read_buffer_rect(Queue::cl_queue(), Buffer::cl_mem(),
1997			       BufferOrigin::[non_neg_integer()],
1998			       HostOrigin::[non_neg_integer()],
1999			       Region::[non_neg_integer()],
2000			       BufferRowPicth::non_neg_integer(),
2001			       BufferSlicePicth::non_neg_integer(),
2002			       HostRowPicth::non_neg_integer(),
2003			       HostSlicePicth::non_neg_integer(),
2004			       WaitList::[cl_event()]) ->
2005    {'ok', cl_event()} | {'error', cl_error()}.
2006
2007enqueue_read_buffer_rect(_Queue, _Buffer, _BufferOrigin, _HostOrigin,
2008			 _Region, _BufferRowPitch, _BufferSlicePitch,
2009			 _HostRowPitch, _HostSlicePitch,
2010			 _WaitList) ->
2011    ?nif_stub.
2012
2013%%
2014%% @spec enqueue_write_buffer(Queue::cl_queue(), Buffer::cl_mem(),
2015%%                            Offset::non_neg_integer(),
2016%%                            Size::non_neg_integer(),
2017%%                            Data::binary(),
2018%%                            WaitList::[cl_event()]) ->
2019%%    {'ok', cl_event()} | {'error', cl_error()}
2020%%
2021%% @doc Enqueue commands to write to a buffer object from host memory.
2022%%
2023%% Calling <code>enqueue_write_buffer</code> to update the latest bits
2024%% in a region of the buffer object with the <code>Buffer</code>
2025%% argument value set to <code>host_ptr</code> + <code >offset</code>,
2026%% where <code>host_ptr</code> is a pointer to the memory region
2027%% specified when the buffer object being read is created with
2028%% <code>CL_MEM_USE_HOST_PTR</code>, must meet the following
2029%% requirements in order to avoid undefined behavior:
2030%%
2031%% <ul> <li>The host memory region given by <code>(host_ptr + offset, cb)</code>
2032%% contains the latest bits when the enqueued write command begins
2033%% execution. </li>
2034%% <li>The buffer object is not mapped</li>
2035%% <li>The buffer object is not used by any command-queue until the read
2036%% command has finished execution</li> </ul>
2037-spec enqueue_write_buffer(Queue::cl_queue(), Buffer::cl_mem(),
2038			   Offset::non_neg_integer(),
2039			   Size::non_neg_integer(),
2040			   Data::binary(),
2041			   WaitList::[cl_event()]) ->
2042    {'ok', cl_event()} | {'error', cl_error()}.
2043
2044
2045enqueue_write_buffer(Queue, Buffer, Offset, Size, Data, WaitList) ->
2046    enqueue_write_buffer(Queue, Buffer, Offset, Size, Data, WaitList, true).
2047
2048-spec nowait_enqueue_write_buffer(Queue::cl_queue(), Buffer::cl_mem(),
2049			   Offset::non_neg_integer(),
2050			   Size::non_neg_integer(),
2051			   Data::binary(),
2052			   WaitList::[cl_event()]) ->
2053    'ok' | {'error', cl_error()}.
2054
2055nowait_enqueue_write_buffer(Queue, Buffer, Offset, Size, Data, WaitList) ->
2056    enqueue_write_buffer(Queue, Buffer, Offset, Size, Data, WaitList, false).
2057
2058enqueue_write_buffer(_Queue, _Buffer, _Offset, _Size, _Data, _WaitList,
2059		     _WantEvent) ->
2060    ?nif_stub.
2061
2062
2063
2064%%
2065%% Write rectangular section from  host memory into buffer memory
2066%%
2067-spec enqueue_write_buffer_rect(Queue::cl_queue(), Buffer::cl_mem(),
2068				BufferOrigin::[non_neg_integer()],
2069				HostOrigin::[non_neg_integer()],
2070				Region::[non_neg_integer()],
2071				BufferRowPicth::non_neg_integer(),
2072				BufferSlicePicth::non_neg_integer(),
2073				HostRowPicth::non_neg_integer(),
2074				HostSlicePicth::non_neg_integer(),
2075				Data::binary(),
2076				WaitList::[cl_event()]) ->
2077    {'ok', cl_event()} | {'error', cl_error()}.
2078
2079enqueue_write_buffer_rect(_Queue, _Buffer, _BufferOrigin, _HostOrigin,
2080			  _Region, _BufferRowPitch, _BufferSlicePitch,
2081			  _HostRowPitch, _HostSlicePitch,
2082			  _Data,
2083			  _WaitList) ->
2084    ?nif_stub.
2085
2086
2087%%
2088%% Fill buffer memory from pattern,
2089%% Size and Offset must be multiple of Pattern size
2090%% Pattern size must be onle of 1,2,4,8,16,32,64 or 128
2091%%
2092-spec enqueue_fill_buffer(Queue::cl_queue(), Buffer::cl_mem(),
2093			  Pattern::binary(),
2094			  Offset::non_neg_integer(),
2095			  Size::non_neg_integer(),
2096			  WaitList::[cl_event()]) ->
2097    {'ok', cl_event()} | {'error', cl_error()}.
2098
2099enqueue_fill_buffer(_Queue, _Buffer, _Pattern, _Offset, _Size, _WaitList) ->
2100    ?nif_stub.
2101
2102%%
2103%% @spec enqueue_barrier(Queue::cl_queue()) ->
2104%%    'ok' | {'error', cl_error()}
2105%%
2106%% @doc A synchronization point that enqueues a barrier operation.
2107%%
2108%%  enqueue_barrier/1 is a synchronization point that ensures that all
2109%%  queued commands in command_queue have finished execution before
2110%%  the next batch of commands can begin execution.
2111-spec enqueue_barrier(Queue::cl_queue()) ->
2112    'ok' | {'error', cl_error()}.
2113
2114enqueue_barrier(_Queue) ->
2115    ?nif_stub.
2116
2117%% @spec enqueue_marker_with_wait_list(Queue::cl_queue(),
2118%%                    WaitList::[cl_event()]) ->
2119%%    {'ok', cl_event()} | {'error', cl_error()}
2120
2121-spec enqueue_marker_with_wait_list(Queue::cl_queue(),
2122				    WaitList::[cl_event()]) ->
2123    {'ok', cl_event()} | {'error', cl_error()}.
2124
2125enqueue_marker_with_wait_list(_Queue, _WaitList) ->
2126    ?nif_stub.
2127
2128%% @spec enqueue_barrier_with_wait_list(Queue::cl_queue(),
2129%%                    WaitList::[cl_event()]) ->
2130%%    {'ok', cl_event()} | {'error', cl_error()}
2131-spec enqueue_barrier_with_wait_list(Queue::cl_queue(),
2132				     WaitList::[cl_event()]) ->
2133    {'ok', cl_event()} | {'error', cl_error()}.
2134enqueue_barrier_with_wait_list(_Queue, _WaitList) ->
2135    ?nif_stub.
2136
2137
2138
2139enqueue_read_image(_Queue, _Image, _Origin, _Region, _RowPitch, _SlicePitch,
2140		   _WaitList) ->
2141    ?nif_stub.
2142
2143enqueue_write_image(Queue, Image, Origin, Region, RowPitch, SlicePitch,
2144		    Data, WaitList) ->
2145    enqueue_write_image(Queue, Image, Origin, Region, RowPitch, SlicePitch,
2146			Data, WaitList, true).
2147
2148
2149nowait_enqueue_write_image(Queue, Image, Origin, Region, RowPitch, SlicePitch,
2150			   Data, WaitList) ->
2151    enqueue_write_image(Queue, Image, Origin, Region, RowPitch, SlicePitch,
2152			Data, WaitList, false).
2153
2154enqueue_write_image(_Queue, _Image, _Origin, _Region, _RowPitch, _SlicePitch,
2155		    _Data, _WaitList, _WantEvent) ->
2156    ?nif_stub.
2157
2158enqueue_copy_buffer(_Queue, _SrcBuffer, _DstBuffer, _SrcOffset, _DstOffset,
2159			     _Cb, _WaitList) ->
2160    ?nif_stub.
2161
2162enqueue_copy_buffer_rect(_Queue, _SrcBuffer, _DstBuffer,
2163			 _SrcOrigin, _DstOrigin, _Region,
2164			 _SrcRowPitch, _SrcSlicePitch,
2165			 _DstRowPitch, _DstSlicePitch,
2166			 _WaitList) ->
2167    ?nif_stub.
2168
2169enqueue_copy_image(_QUeue, _SrcImage, _DstImage, _Origin, _Region, _WaitList) ->
2170    ?nif_stub.
2171
2172%%  FillColor = <<R:32/unsigned,G:32/unsigned,B:32/unsigned,A:32/unsigned>>
2173%%            | <<R:32/signed,G:32/signed,B:32/signed,A:32/signed>>
2174%%            | <<R:32/float,G:32/float,B:32/float,A:32/float>>
2175%%            Use device endian! check device_info(D, endian_little)
2176-spec enqueue_fill_image(Queue::cl_queue(),
2177			 Image::cl_mem(),
2178			 FillColor::binary(),
2179			 Origin::[non_neg_integer()],
2180			 Region::[non_neg_integer()],
2181			 WaitList::[cl_event()]) ->
2182				{'ok', cl_event()} | {'error', cl_error()}.
2183
2184enqueue_fill_image(_Queue, _Image, _FillColor, _Origin, _Region, _WaitList) ->
2185    ?nif_stub.
2186
2187enqueue_copy_image_to_buffer(_Queue, _SrcImage, _DstBuffer, _Origin, _Region,
2188			     _DstOffset, _WaitList) ->
2189    ?nif_stub.
2190
2191enqueue_copy_buffer_to_image(_Queue, _SrcBuffer, _DstImage, _SrcOffset,
2192			     _DstOrigin, _Region, _WaitList) ->
2193    ?nif_stub.
2194
2195enqueue_map_buffer(_Queue, _Buffer, _MapFlags, _Offset, _Size, _WaitList) ->
2196    ?nif_stub.
2197
2198enqueue_map_image(_Queue, _Image, _MapFlags, _Origin, _Region, _WaitList) ->
2199    ?nif_stub.
2200
2201enqueue_unmap_mem_object(_Queue, _Mem, _WaitList) ->
2202    ?nif_stub.
2203
2204-spec enqueue_migrate_mem_objects(Queue::cl_queue(),
2205				  MemObjects::[cl_mem()],
2206				  Flags::[host|content_undefined],
2207				  WaitList::[cl_event()]) ->
2208    {'ok', cl_event()} | {'error', cl_error()}.
2209
2210enqueue_migrate_mem_objects(_Queue, _MemObjects, _Flags, _WaitList) ->
2211    ?nif_stub.
2212
2213%%
2214%% @spec flush(Queue::cl_queue()) ->
2215%%    'ok' | {'error', cl_error()}
2216%%
2217%% @doc Issues all previously queued OpenCL commands
2218%% in a command-queue to the device associated with the command-queue.
2219%%
2220%% flush only guarantees that all queued commands to command_queue get
2221%% issued to the appropriate device. There is no guarantee that they
2222%% will be complete after clFlush returns.
2223-spec flush(Queue::cl_queue()) ->
2224    'ok' | {'error', cl_error()}.
2225
2226flush(Queue) ->
2227    case async_flush(Queue) of
2228	{ok,Ref} ->
2229	    receive
2230		{cl_async,Ref,Reply} ->
2231		    Reply
2232	    end;
2233	Error -> Error
2234    end.
2235
2236async_flush(_Queue) ->
2237    ?nif_stub.
2238
2239%%
2240%% @spec finish(Queue::cl_queue()) ->
2241%%    'ok' | {'error', cl_error()}
2242%%
2243%% @doc Blocks until all previously queued OpenCL commands
2244%% in a command-queue are issued to the associated device and have
2245%% completed.
2246%%
2247%% finish does not return until all queued commands in command_queue
2248%% have been processed and completed. clFinish is also a
2249%% synchronization point.
2250-spec finish(Queue::cl_queue()) ->
2251    'ok' | {'error', cl_error()}.
2252
2253finish(Queue) ->
2254    case async_finish(Queue) of
2255	{ok,Ref} ->
2256	    receive
2257		{cl_async,Ref,Reply} ->
2258		    Reply
2259	    end;
2260	Error -> Error
2261    end.
2262
2263async_finish(_Queue) ->
2264    ?nif_stub.
2265
2266%%
2267%% @spec retain_event(Event::cl_event()) ->
2268%%    'ok' | {'error', cl_error()}
2269%% @doc  Increments the event reference count.
2270%% NOTE: The OpenCL commands that return an event perform an implicit retain.
2271retain_event(Event) when ?is_event(Event) ->
2272    ok.
2273
2274%%
2275%% @spec release_event(Event::cl_event()) ->
2276%%    'ok' | {'error', cl_error()}
2277%% @doc Decrements the event reference count.
2278%%
2279%%  Decrements the event reference count. The event object is deleted
2280%%  once the reference count becomes zero, the specific command
2281%%  identified by this event has completed (or terminated) and there
2282%%  are no commands in the command-queues of a context that require a
2283%%  wait for this event to complete.
2284release_event(Event) when ?is_event(Event) ->
2285    ok.
2286
2287%% @doc Returns all possible event_info items.
2288event_info() ->
2289    [
2290     command_queue,
2291     command_type,
2292     reference_count,
2293     execution_status
2294    ].
2295
2296%% @doc Returns specific information about the event object.
2297get_event_info(_Event, _Info) ->
2298    ?nif_stub.
2299
2300
2301%% @doc Returns all specific information about the event object.
2302get_event_info(Event) when ?is_event(Event) ->
2303    get_info_list(Event, event_info(), fun get_event_info/2).
2304
2305%% IMAGES
2306%% @doc return a list of image formats [{Order,Type}]
2307
2308get_supported_image_formats(_Context, _Flags, _ImageType) ->
2309    ?nif_stub.
2310
2311-spec create_image2d(Conext::cl_context(), Flags::[cl_mem_flag()],
2312		     ImageFormat::#cl_image_format{},
2313		     Width::non_neg_integer(),
2314		     Height::non_neg_integer(),
2315		     Pitch::non_neg_integer(),
2316		     Data::binary()) ->
2317    {'ok', cl_mem()} | {'error', cl_error()}.
2318
2319create_image2d(_Context, _MemFlags, _ImageFormat, _Width, _Height, _Pitch,
2320		_Data) ->
2321    ?nif_stub.
2322
2323-spec create_image3d(Conext::cl_context(), Flags::[cl_mem_flag()],
2324		     ImageFormat::#cl_image_format{},
2325		     Width::non_neg_integer(),
2326		     Height::non_neg_integer(),
2327		     Depth::non_neg_integer(),
2328		     RowPitch::non_neg_integer(),
2329		     SlicePitch::non_neg_integer(),
2330		     Data::binary()) ->
2331    {'ok', cl_mem()} | {'error', cl_error()}.
2332
2333create_image3d(_Context, _MemFlags, _ImageFormat, _Width, _Height, _Depth,
2334	       _RowPicth, _SlicePitch, _Data) ->
2335    ?nif_stub.
2336
2337-spec create_image(Conext::cl_context(), Flags::[cl_mem_flag()],
2338		   ImageFormat::#cl_image_format{},
2339		   ImageDesc::#cl_image_desc{},
2340		   Data::binary()) ->
2341    {'ok', cl_mem()} | {'error', cl_error()}.
2342
2343create_image(_Context, _MemFlags, _ImageFormat, _ImageDesc, _Data) ->
2344    ?nif_stub.
2345
2346%% Wait for all events in EventList to complete
2347-spec wait_for_events(EventList::[cl_event]) ->
2348			     [{'ok','completed'} |
2349			      {'ok',binary()} |
2350			      {'error',cl_error()}].
2351
2352wait_for_events([Event|Es]) ->
2353    [wait(Event) | wait_for_events(Es)];
2354wait_for_events([]) ->
2355    [].
2356
2357%%
2358%% @spec wait(Event::cl_event) ->
2359%%    {'ok','completed'} | {'ok',Binary} | {'error',cl_error()}
2360%%
2361wait(Event) ->
2362    wait(Event, infinity).
2363
2364%% @spec wait_for_event(Event::cl_event) ->
2365%%    {'ok','completed'} | {'ok',Binary} | {'error',cl_error()}
2366%% @equiv wait(Event, infinity)
2367%%
2368
2369wait_for_event(Event) ->
2370    wait(Event, infinity).
2371
2372%%
2373%% @spec wait(Event::cl_event, Timeout::timeout()) ->
2374%%    {'ok','completed'} | {'ok',Binary} |
2375%%    {'error',cl_error()} | {'error',timeout}
2376%%
2377%%
2378%% @doc  Waits for commands identified by event objects to complete.
2379%%
2380%%  Waits for commands identified by event objects
2381%%  in event_list to complete. A command is considered complete if its
2382%%  execution status is CL_COMPLETE or a negative value.
2383
2384
2385wait(Event, Timeout) when ?is_event(Event) ->
2386    case async_wait_for_event(Event) of
2387	{ok,Ref} ->
2388	    wait1(Ref,Event,Timeout);
2389	Error ->
2390	    Error
2391    end.
2392
2393wait1(Ref, Event, Timeout) when ?is_event(Event) ->
2394    receive
2395	{cl_event, Ref, Binary} when is_binary(Binary) ->
2396	    release_event(Event),
2397	    {ok,Binary};
2398	{cl_event, Ref, complete} ->
2399	    release_event(Event),
2400	    {ok,completed};
2401	{cl_event, Ref, Err} ->
2402	    release_event(Event),
2403	    Err
2404    after Timeout ->
2405	    {error, timeout}
2406    end.
2407
2408%%
2409%% @spec async_wait_for_event(Event::cl_event()) ->
2410%%    {'ok',reference()} | {'error',cl_error()}
2411%%
2412%% @doc  Initiate an asynchronous wait operation.
2413%%
2414%%  Generate a wait operation that will run non blocking.
2415%%  A reference is return that can be used to match the event
2416%%  that is sent when the event has completed or resulted in an error.
2417%%  The event returned has the form <code>{cl_event, Ref, Result}</code>
2418%%  where Ref is the reference that was returned from the call and
2419%%  Result may be one of binary() | 'complete' or {error,cl_error()}.
2420%%
2421-spec async_wait_for_event(Event::cl_event()) ->
2422    {'ok',reference()} | {'error',cl_error()}.
2423
2424async_wait_for_event(_Event) ->
2425    ?nif_stub.
2426
2427%% @hidden
2428%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2429%% Utilities
2430%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
2431
2432get_info_list(Object, InfoList, Fun) ->
2433    get_info_list(Object, InfoList, Fun, undefined, []).
2434
2435get_info_list(Object, [I|Is], Fun, Err, Acc) ->
2436    case Fun(Object, I) of
2437	{error,Reason} ->
2438	    io:format("InfoError: ~s [~p]\n", [I,Reason]),
2439	    get_info_list(Object, Is, Fun, Reason, Acc);
2440	{ok,Value} ->
2441	    get_info_list(Object, Is, Fun, Err, [{I,Value}|Acc])
2442    end;
2443get_info_list(_Object,[], _Fun, undefined, []) ->
2444    {ok, []};
2445get_info_list(_Object,[], _Fun, Err, []) ->
2446    {error, Err};
2447get_info_list(_Object,[], _Fun, _Err, Acc) ->
2448    {ok, reverse(Acc)}.
2449