Aside from online compilation during application execution, OpenCL kernel sources can be compiled offline into binaries that can be loaded into the drivers using special API calls (e.g. clCreateProgramWithBinary
or clCreateProgramWithIL
).
This section describes available open source tools for offline compilation of OpenCL kernels.
- clang is a compiler front-end for the C/C family of languages, including OpenCL C and C for OpenCL. It can produce executable binaries (e.g. AMDGPU), or portable binaries (e.g. SPIR). It is part of the LLVM compiler infrastructure project, and there is information regarding OpenCL kernel language support and standard headers.
- SPIRV-LLVM Translator provides a library and the llvm-spirv tool for bidirectional translation between LLVM IR and SPIR-V.
- clspv compiler and clvk runtime layer enable OpenCL applications to be executed with Vulkan drivers.
- SPIR-V Tools provide a set of utilities to process SPIR-V binaries including spirv-opt optimizer, spirv-link linker, spirv-dis/spirv-as (dis-)assembler, and spirv-val validator.
The open source tools can be used to perform full compilation from OpenCL kernel sources into SPIR-V.
Offline compilation flow for OpenCL kernels into SPIR-V
When tools are used to target OpenCL drivers they operate on OpenCL flavor of SPIR-V and when tools target Vulkan drivers they operate on Vulkan flavor of SPIR-V instead. Some tools can ingest both SPIR-V dialects. However, it is generally not possible to transform or mix the modules of different SPIR-V flavors. For example, it is generally not possible to use spirv-link to link the modules in both OpenCL and Vulkan formats of SPIR-V.
If you want to try the above compilation flow for yourself, after installing the tools, you can use the following commands.
(i) Compiling OpenCL C/C for OpenCL file into SPIR flavor LLVM IR (for 32 bit targets) formats:
clang -c -target spir -O0 -emit-llvm -o test.bc test.cl
Using -cl-std
changes the language version compiled for.
To compile C for OpenCL source pass -cl-std=CLC
or use the file extension .clcpp
.
clang -cl-std=CLC -c -target spir -O0 -emit-llvm -o test.bc test.cl
clang -c -target spir -O0 -emit-llvm -o test.bc test.clcpp
If debugging support is needed then the -g
flag can be used in the clang invocation:
clang -c test.cl -target spir -o test.bc -g
Note: In clang releases up to 12.0, calling most builtin functions requires the extra flags -Xclang -finclude-default-header
to be passed to clang. Refer to the release documentation for more details.
(ii) Converting LLVM IR into SPIR-V.
llvm-spirv test.bc -o test.spv
Note: Converting IR produced with optimization levels other than -O0
is only available as an experimental feature and it is not guaranteed to work. In the majority of cases, the conversion is expected to succeed when optimizations are enabled. Developers are encouraged to file a bug report when issues are encountered. As a workaround when encountering an issue in translating modules obtained with optimizations, generate LLVM IR with optimizations disabled, and then use the stand-alone spirv-opt tool to optimize at the SPIR-V level.
(iii) Linking multiple modules can be done on LLVM IR level by passing multiple .bc
files to llvm-link.
llvm-link test1.bc test2.bc -o app.bc
llvm-spirv app.bc -o app.spv
Alternatively, spirv-link can be used to link SPIR-V modules of the same flavor either OpenCL or Vulkan:
spirv-link -o app.spv test1.spv test2.spv
(iv) Once the SPIR-V binary is produced, it can be loaded in OpenCL applications using the clCreateProgramWithIL
API call.
Compiling OpenCL sources directly to SPIR-V binary format:
clspv test.cl -o test.spv
The SPIR-V binary files can be further optimized or linked using spirv-opt and spirv-link respectively before loading into the Vulkan runtime using vkCreateShaderModule
from Vulkan API or (if clvk is used) clCreateProgramWithIL
from OpenCL API.