Skip to content

Commit 686e3ad

Browse files
committed
build + Kernel creation
1 parent 5dbe8e0 commit 686e3ad

File tree

5 files changed

+209
-12
lines changed

5 files changed

+209
-12
lines changed

Project.toml

Lines changed: 2 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,10 +9,12 @@ Atomix = "a9b6321e-bd34-4604-b9c9-b65b8de01458"
99
EnzymeCore = "f151be2c-9106-41f4-ab19-57ee4f262869"
1010
GPUCompiler = "61eb1bfa-7361-4325-ad38-22787b887f55"
1111
InteractiveUtils = "b77e0a4c-d291-57a0-90e8-8db25a27a240"
12+
LLVM = "929cbde3-209d-540e-8aea-75f648917ca0"
1213
LinearAlgebra = "37e2e46d-f89d-539d-b4ee-838fcccc9c8e"
1314
MacroTools = "1914dd2f-81c6-5fcd-8719-6d5c9610ff09"
1415
OpenCL_jll = "6cb37087-e8b6-5417-8430-1f242f1e46e4"
1516
PrecompileTools = "aea7be01-6a6a-4083-8856-8a6e6704d82a"
17+
Printf = "de0858da-6303-5e67-8744-51eddeeeb8d7"
1618
Requires = "ae029012-a4dd-5104-9daa-d747884805df"
1719
SPIRVIntrinsics = "71d1d633-e7e8-4a92-83a1-de8814b09ba8"
1820
SparseArrays = "2f01184e-e22b-5df5-ae63-d93ebab69eaf"

src/pocl/compiler/compilation.jl

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -64,7 +64,7 @@ end
6464

6565
# link into an executable kernel
6666
function link(@nospecialize(job::CompilerJob), compiled)
67-
prog = if "cl_khr_il_program" in cl.device().extensions
67+
prog = if "cl_khr_il_program" in device().extensions
6868
cl.Program(compiled.obj, context())
6969
else
7070
error("Your device does not support SPIR-V, which is currently required for native execution.")

src/pocl/compiler/execution.jl

Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -184,8 +184,8 @@ end
184184
const clfunction_lock = ReentrantLock()
185185

186186
function clfunction(f::F, tt::TT=Tuple{}; kwargs...) where {F,TT}
187-
ctx = cl.context()
188-
dev = cl.device()
187+
ctx = context()
188+
dev = device()
189189

190190
Base.@lock clfunction_lock begin
191191
# compile the function

src/pocl/nanoOpenCL.jl

Lines changed: 189 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -3,6 +3,8 @@ module nanoOpenCL
33
import OpenCL_jll
44
import pocl_jll
55

6+
using Printf
7+
68
const libopencl = OpenCL_jll.libopencl # TODO directly use POCL
79

810
"""
@@ -302,6 +304,55 @@ const CL_DEVICE_PIPE_SUPPORT = 0x1071
302304

303305
const 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

306357
function check(f)
307358
res = f()
@@ -365,6 +416,11 @@ const cl_context_properties = intptr_t
365416

366417
const 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},
@@ -414,6 +470,29 @@ end
414470
@ccall libopencl.clReleaseProgram(program::cl_program)::cl_int
415471
end
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+
417496
function 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)
742821
end
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+
744933
mutable struct Kernel
745934
const id::cl_kernel
746935

src/pocl/pocl.jl

Lines changed: 15 additions & 9 deletions
Original file line numberDiff line numberDiff line change
@@ -5,25 +5,31 @@ include("nanoOpenCL.jl")
55
import .nanoOpenCL as cl
66

77
function platform()
8-
for p in cl.platforms()
9-
if p.vendor == "The pocl project"
10-
return p
8+
get!(task_local_storage(), :POCLPlatform) do
9+
for p in cl.platforms()
10+
if p.vendor == "The pocl project"
11+
return p
12+
end
1113
end
12-
end
13-
return nothing
14+
error("POCL not available")
15+
end::cl.Platform
1416
end
1517

1618
function device()
17-
p = platform()
18-
return cl.default_device(p)
19+
get!(task_local_storage(), :POCLDevice) do
20+
p = platform()
21+
return cl.default_device(p)
22+
end::cl.Device
1923
end
2024

21-
# TODO: Global Context or TLS Context?
2225
function context()
23-
error("TBD")
26+
get!(task_local_storage(), :POCLContext) do
27+
cl.Context(device())
28+
end::cl.Context
2429
end
2530

2631
using GPUCompiler
32+
import LLVM
2733
using Adapt
2834

2935
import SPIRVIntrinsics

0 commit comments

Comments
 (0)