@@ -3,6 +3,8 @@ module nanoOpenCL
33import OpenCL_jll
44import pocl_jll
55
6+ using Printf
7+
68const libopencl = OpenCL_jll. libopencl # TODO directly use POCL
79
810"""
@@ -302,6 +304,55 @@ const CL_DEVICE_PIPE_SUPPORT = 0x1071
302304
303305const CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED = 0x1072
304306
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
305356
306357function check (f)
307358 res = f ()
@@ -365,6 +416,11 @@ const cl_context_properties = intptr_t
365416
366417const cl_context_info = cl_uint
367418
419+ const cl_build_status = cl_int
420+
421+ const cl_program_info = cl_uint
422+
423+ const cl_program_build_info = cl_uint
368424
369425@checked function clGetPlatformIDs (num_entries, platforms, num_platforms)
370426 @ccall libopencl. clGetPlatformIDs (num_entries:: cl_uint , platforms:: Ptr{cl_platform_id} ,
414470 @ccall libopencl. clReleaseProgram (program:: cl_program ):: cl_int
415471end
416472
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+
417496function clCreateKernel (program, kernel_name, errcode_ret)
418497 @ccall libopencl. clCreateKernel (program:: cl_program , kernel_name:: Ptr{Cchar} ,
419498 errcode_ret:: Ptr{cl_int} ):: cl_kernel
@@ -741,6 +820,116 @@ function Program(il, ctx)
741820 Program (program_id)
742821end
743822
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+
744933mutable struct Kernel
745934 const id:: cl_kernel
746935
0 commit comments