Log in | Imprint
last updated 3/28/2016 | 383270 views
On Twitter
On Vimeo
On YouTube

Main . Blog

3/28/2016: The Future is Now: Compiling C++17 to the GPU (Vulkan/OpenCL/SPIR-V)

Update 9/21/2019:

The newest clang release officially brings experimental C++ support for OpenCL, superseding the experimental modifications discussed in this blog post! :)

Original 2016 experiment:

The release of SPIRV-LLVM and all the talk about Vulkan at GDC made me curious as to how far we actually are from compiling other languages, particularly full-featured C++, to the GPU. So far, using somewhat current versions of C++ on the GPU has been a privilege reserved to CUDA programmers specifically targeting NVIDIA GPUs. TLDR: As it turns out, it is already possible today. See command lines in the center, experimental compiler binaries at the bottom.

Interestingly, clang implements OpenCL with very few additions to the C99 front end, which in turn shares most of its logic with the C++ front end. As it turns out, a miniscule set of changes allows the use of any C++ standard in combination with the OpenCL extensions. Merging in the OpenCL headers and SPIR-V code emission from Khronos' OpenCL C Compiler, we can in fact already obtain an end-to-end solution compiling C++17 to SPIR-V. New commits can easily be merged in as clang continues to evolve. You can find my experimentally patched version of the current clang master branch here: https://github.com/tszirr/clang

Compilation of this patched version of clang will also require an up-to-date port of LLVM-SPIRV to the LLVM master branch, which I did here: https://github.com/tszirr/SPIRV-LLVM

Now, we can simply compile C++ kernels to SPIR-V bit code using the following command line:

clang -cc1 -std=c++1y -triple spir-unknown-unknown -emit-spirv -x cl -o mykernels.cpp.sv mykernels.cpp

We can investigate the generated SPIR-V bit code using the LLVM-SPIRV tool:

llvm-spirv -to-text -o mykernels.cpp.sv.txt mykernels.cpp.sv

I successfully compiled a few templates, classes with constructors and destructors, and group-shared/global/generic/image memory accesses. Note that so far, however, this combination of languages is officially unsupported and will only partly follow the OpenCL C language specification, particularly not the provisional OpenCL 2.1 C++ specification. I have been in contact with the clang/LLVM codebase for merely a day, therefore I am certainly no clang/LLVM expert and cannot assess the full extent of code paths where C++ and C99 front ends diverge. I fixed one minor issue for C++ declarations involving memory spaces, but more might turn up elsewhere.

Since building clang and LLVM takes quite some time, I compiled a minimal set of experimental x64 Windows binaries that can get you started: http://alphanew.net/releases/experimental/clang-oclxx-spirv.zip

Backwards Compatibility
(Note on legacy OpenCL/SPIR compatibility: For OpenCL implementations only supporting the old LLVM 3.x-derived SPIR format, you can use SPIR-V as a stable intermediate format that can then be fed to the official LLVM 3.x-based SPIRV-LLVM tool for reverse conversion from SPIR-V to SPIR. Be aware that you will have to obtain that official binary elsewhere, since the llvm-spirv binary provided in the above zip file is based on the current LLVM master branch and therefore unsuitable for that purpose, it merely serves for debugging/disassembling purposes.)

« Back

© 2024 Tobias Zirr. All rights reserved.