@@ -3,6 +3,8 @@ module nanoOpenCL
3
3
import OpenCL_jll
4
4
import pocl_jll
5
5
6
+ using Printf
7
+
6
8
const libopencl = OpenCL_jll. libopencl # TODO directly use POCL
7
9
8
10
"""
@@ -302,6 +304,55 @@ const CL_DEVICE_PIPE_SUPPORT = 0x1071
302
304
303
305
const CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED = 0x1072
304
306
307
+ const CL_PROGRAM_REFERENCE_COUNT = 0x1160
308
+
309
+ const CL_PROGRAM_CONTEXT = 0x1161
310
+
311
+ const CL_PROGRAM_NUM_DEVICES = 0x1162
312
+
313
+ const CL_PROGRAM_DEVICES = 0x1163
314
+
315
+ const CL_PROGRAM_SOURCE = 0x1164
316
+
317
+ const CL_PROGRAM_BINARY_SIZES = 0x1165
318
+
319
+ const CL_PROGRAM_BINARIES = 0x1166
320
+
321
+ const CL_PROGRAM_NUM_KERNELS = 0x1167
322
+
323
+ const CL_PROGRAM_KERNEL_NAMES = 0x1168
324
+
325
+ const CL_PROGRAM_IL = 0x1169
326
+
327
+ const CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT = 0x116a
328
+
329
+ const CL_PROGRAM_SCOPE_GLOBAL_DTORS_PRESENT = 0x116b
330
+
331
+ const CL_PROGRAM_BUILD_STATUS = 0x1181
332
+
333
+ const CL_PROGRAM_BUILD_OPTIONS = 0x1182
334
+
335
+ const CL_PROGRAM_BUILD_LOG = 0x1183
336
+
337
+ const CL_PROGRAM_BINARY_TYPE = 0x1184
338
+
339
+ const CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE = 0x1185
340
+
341
+ const CL_PROGRAM_BINARY_TYPE_NONE = 0x00
342
+
343
+ const CL_PROGRAM_BINARY_TYPE_COMPILED_OBJECT = 0x01
344
+
345
+ const CL_PROGRAM_BINARY_TYPE_LIBRARY = 0x02
346
+
347
+ const CL_PROGRAM_BINARY_TYPE_EXECUTABLE = 0x04
348
+
349
+ const CL_BUILD_SUCCESS = 0
350
+
351
+ const CL_BUILD_NONE = - 1
352
+
353
+ const CL_BUILD_ERROR = - 2
354
+
355
+ const CL_BUILD_IN_PROGRESS = - 3
305
356
306
357
function check (f)
307
358
res = f ()
@@ -365,6 +416,11 @@ const cl_context_properties = intptr_t
365
416
366
417
const cl_context_info = cl_uint
367
418
419
+ const cl_build_status = cl_int
420
+
421
+ const cl_program_info = cl_uint
422
+
423
+ const cl_program_build_info = cl_uint
368
424
369
425
@checked function clGetPlatformIDs (num_entries, platforms, num_platforms)
370
426
@ccall libopencl. clGetPlatformIDs (num_entries:: cl_uint , platforms:: Ptr{cl_platform_id} ,
414
470
@ccall libopencl. clReleaseProgram (program:: cl_program ):: cl_int
415
471
end
416
472
473
+ @checked function clBuildProgram (program, num_devices, device_list, options, pfn_notify,
474
+ user_data)
475
+ @ccall libopencl. clBuildProgram (program:: cl_program , num_devices:: cl_uint ,
476
+ device_list:: Ptr{cl_device_id} , options:: Ptr{Cchar} ,
477
+ pfn_notify:: Ptr{Cvoid} , user_data:: Ptr{Cvoid} ):: cl_int
478
+ end
479
+
480
+ @checked function clGetProgramInfo (program, param_name, param_value_size, param_value,
481
+ param_value_size_ret)
482
+ @ccall libopencl. clGetProgramInfo (program:: cl_program , param_name:: cl_program_info ,
483
+ param_value_size:: Csize_t , param_value:: Ptr{Cvoid} ,
484
+ param_value_size_ret:: Ptr{Csize_t} ):: cl_int
485
+ end
486
+
487
+ @checked function clGetProgramBuildInfo (program, device, param_name, param_value_size,
488
+ param_value, param_value_size_ret)
489
+ @ccall libopencl. clGetProgramBuildInfo (program:: cl_program , device:: cl_device_id ,
490
+ param_name:: cl_program_build_info ,
491
+ param_value_size:: Csize_t ,
492
+ param_value:: Ptr{Cvoid} ,
493
+ param_value_size_ret:: Ptr{Csize_t} ):: cl_int
494
+ end
495
+
417
496
function clCreateKernel (program, kernel_name, errcode_ret)
418
497
@ccall libopencl. clCreateKernel (program:: cl_program , kernel_name:: Ptr{Cchar} ,
419
498
errcode_ret:: Ptr{cl_int} ):: cl_kernel
@@ -741,6 +820,116 @@ function Program(il, ctx)
741
820
Program (program_id)
742
821
end
743
822
823
+ # TODO : build callback...
824
+ function build! (p:: Program ; options= " " )
825
+ opts = String (options)
826
+ ndevices = 0
827
+ device_ids = C_NULL
828
+ try
829
+ clBuildProgram (p, cl_uint (ndevices), device_ids, opts, C_NULL , C_NULL )
830
+ catch err
831
+ isa (err, CLError) || throw (err)
832
+
833
+ for (dev, status) in p. build_status
834
+ if status == CL_BUILD_ERROR
835
+ io = IOBuffer ()
836
+ println (io, " Failed to compile program" )
837
+ if p. source != = nothing
838
+ println (io)
839
+ println (io, " Source code:" )
840
+ for (i,line) in enumerate (split (p. source, " \n " ))
841
+ println (io, @sprintf (" %s%-2d: %s" , " " , i, line))
842
+ end
843
+ end
844
+ println (io)
845
+ println (io, " Build log:" )
846
+ println (io, strip (p. build_log[dev]))
847
+ error (String (take! (io)))
848
+ end
849
+ end
850
+ end
851
+ return p
852
+ end
853
+
854
+ function Base. getproperty (p:: Program , s:: Symbol )
855
+ if s == :reference_count
856
+ count = Ref {Cuint} ()
857
+ clGetProgramInfo (p, CL_PROGRAM_REFERENCE_COUNT, sizeof (Cuint), count, C_NULL )
858
+ return Int (count[])
859
+ elseif s == :num_devices
860
+ count = Ref {Cuint} ()
861
+ clGetProgramInfo (p, CL_PROGRAM_NUM_DEVICES, sizeof (Cuint), count, C_NULL )
862
+ return Int (count[])
863
+ elseif s == :devices
864
+ device_ids = Vector {cl_device_id} (undef, p. num_devices)
865
+ clGetProgramInfo (p, CL_PROGRAM_DEVICES, sizeof (device_ids), device_ids, C_NULL )
866
+ return [Device (id) for id in device_ids]
867
+ elseif s == :source
868
+ src_len = Ref {Csize_t} ()
869
+ clGetProgramInfo (p, CL_PROGRAM_SOURCE, 0 , C_NULL , src_len)
870
+ src_len[] <= 1 && return nothing
871
+ src = Vector {Cchar} (undef, src_len[])
872
+ clGetProgramInfo (p, CL_PROGRAM_SOURCE, src_len[], src, C_NULL )
873
+ return GC. @preserve src unsafe_string (pointer (src))
874
+ elseif s == :binary_sizes
875
+ sizes = Vector {Csize_t} (undef, p. num_devices)
876
+ clGetProgramInfo (p, CL_PROGRAM_BINARY_SIZES, sizeof (sizes), sizes, C_NULL )
877
+ return sizes
878
+ elseif s == :binaries
879
+ sizes = p. binary_sizes
880
+
881
+ bins = Vector {Ptr{UInt8}} (undef, length (sizes))
882
+ # keep a reference to the underlying binary arrays
883
+ # as storing the pointer to the array hides the additional
884
+ # reference from julia's garbage collector
885
+ bin_arrays = Any[]
886
+ for (i, s) in enumerate (sizes)
887
+ if s > 0
888
+ bin = Vector {UInt8} (undef, s)
889
+ bins[i] = pointer (bin)
890
+ push! (bin_arrays, bin)
891
+ else
892
+ bins[i] = Base. unsafe_convert (Ptr{UInt8}, C_NULL )
893
+ end
894
+ end
895
+ clGetProgramInfo (p, CL_PROGRAM_BINARIES, sizeof (bins), bins, C_NULL )
896
+
897
+ binary_dict = Dict {Device, Array{UInt8}} ()
898
+ bidx = 1
899
+ for (i, d) in enumerate (p. devices)
900
+ if sizes[i] > 0
901
+ binary_dict[d] = bin_arrays[bidx]
902
+ bidx += 1
903
+ end
904
+ end
905
+ return binary_dict
906
+ elseif s == :context
907
+ ctx = Ref {cl_context} ()
908
+ clGetProgramInfo (p, CL_PROGRAM_CONTEXT, sizeof (cl_context), ctx, C_NULL )
909
+ return Context (ctx[], retain= true )
910
+ elseif s == :build_status
911
+ status_dict = Dict {Device, cl_build_status} ()
912
+ for device in p. devices
913
+ status = Ref {cl_build_status} ()
914
+ clGetProgramBuildInfo (p, device, CL_PROGRAM_BUILD_STATUS, sizeof (cl_build_status), status, C_NULL )
915
+ status_dict[device] = status[]
916
+ end
917
+ return status_dict
918
+ elseif s == :build_log
919
+ log_dict = Dict {Device, String} ()
920
+ for device in p. devices
921
+ size = Ref {Csize_t} ()
922
+ clGetProgramBuildInfo (p, device, CL_PROGRAM_BUILD_LOG, 0 , C_NULL , size)
923
+ log = Vector {Cchar} (undef, size[])
924
+ clGetProgramBuildInfo (p, device, CL_PROGRAM_BUILD_LOG, size[], log, C_NULL )
925
+ log_dict[device] = GC. @preserve log unsafe_string (pointer (log))
926
+ end
927
+ return log_dict
928
+ else
929
+ return getfield (p, s)
930
+ end
931
+ end
932
+
744
933
mutable struct Kernel
745
934
const id:: cl_kernel
746
935
0 commit comments