Documentation on how to get started with OpenCL programming
OpenCL is not native to the Windows operating system, and as such isn’t supported across the board of UWP (Universal Windows Platform) platforms (XBox, Hololens, IoT, PC) and the Microsoft Store. Windows as a traditional content creating platform however can build and execute OpenCL applications when built as traditional Win32 GUI or console applications.
(NOTE: Nothing prevents from using advanced WinRT capabilities to use the ICD in packaged applications (APPX/MSIX), however such applications will most certainly not be able to load a functioning OpenCL runtime on platforms other than PC and a few IoT devices.)
In this guide we’re going to use the following tools:
Steps will be provided to obtain a minimal and productive environment.
Because most tools we’ll be using are not found inside the Microsoft Store, we’ll be installing dependencies from various places.
(NOTE: The author is familiar with the Chocolatey project, however have found that the end-user UX on this particular scenario is not worth the effort. Far better UX could be achieved if these few tools were packaged as MSIX and distributed via the Microsoft Store.)
From https://visualstudio.microsoft.com/downloads/ select Build Tools for Visual Studio 2019
and launch the installer. When prompted which components to install, select the feature pack named “Desktop development with C++”.
Among the individual features list, select C++ CMake tools for Windows
and Clang compiler for Windows
for convenience. The prior will install CMake, our choice of cross-platform build system, while the latter will be useful when we wish to test natively, if our host code conforms closer with ISO standards.
You most likely already have Git installed. If not, we’ll install it, because this is what Vcpkg uses to keep it’s repository up-to-date.
Visiting https://git-scm.com/download/win should immediately kick off the download of the native binary installer for your system.
TODO: step-by-step guide through the installer.
UX for obtaining dependencies for C/C++ projects has improved dramatically in the past few years. This guide will make use of Vcpkg, a community maintained repo of build scripts for a rapidly growing number of open-source libraries.
Navigate to the folder where you want to install Vcpkg and issue on the command-line (almost any shell):
git clone https://github.com/microsoft/vcpkg.git
cd vcpkg
.\bootstrap-vcpkg.bat
This should build the Vcpkg command-line utility that will take care of the all installations. The utility let’s us discover the OpenCL SDK in its repository (beside other packages mentioning OpenCL).
.\vcpkg.exe search opencl
...
opencl 2.2 (2017.07.... C/C++ headers and ICD loader (Installable Client Driver) for OpenCL
We can install it by issuing:
.\vcpkg.exe install opencl
While the compiler installs, you may also fetch the installer of Visual Studio Code from code.visualstudio.com
To build applications on the command-line on Windows, one needs to open a Developer Command Prompt for VS 2019
. This can be done in the Start Menu.
vcvarsall.bat
invoked which sets the env vars.)Inside a Developer Command Prompt navigate to the folder where you wish to build your application. Our application will have a single Main.c
source file:
// C standard includes
#include <stdio.h>
// OpenCL includes
#include <CL/cl.h>
int main()
{
cl_int CL_err = CL_SUCCESS;
cl_uint numPlatforms = 0;
CL_err = clGetPlatformIDs( 0, NULL, &numPlatforms );
if (CL_err == CL_SUCCESS)
printf_s("%u platform(s) found\n", numPlatforms);
else
printf_s("clGetPlatformIDs(%i)\n", CL_err);
return 0;
}
Then invoke the compiler to build our source file.
cl.exe /nologo /TC /W4 /DCL_TARGET_OPENCL_VERSION=100 /I<VCPKGROOT>\installed\x64-windows\include\ Main.c /Fe:HelloOpenCL /link /LIBPATH:<VCPKGROOT>\installed\x64-windows\lib OpenCL.lib
What do the command-line arguments mean?
Main.exe
)Running our executable HelloOpenCL.exe
either prints the number of platforms found or an error code which is often the result of corrupted runtime installations.
cmake.exe
and our build system driver ninja.exe
isn’t on the PATH by default, they are inside a Developer Command Prompt.)The CMake build script for this application that builds it as an ISO C11 app with most sensible compiler warnings turned on looks like:
cmake_minimum_required(VERSION 3.7) # 3.1 << C_STANDARD 11
# 3.7 << OpenCL::OpenCL
project(HelloOpenCL LANGUAGES C)
find_package(OpenCL REQUIRED)
add_executable(${PROJECT_NAME} Main.c)
target_link_libraries(${PROJECT_NAME} PRIVATE OpenCL::OpenCL)
set_target_properties(${PROJECT_NAME} PROPERTIES C_STANDARD 11
C_STANDARD_REQUIRED ON
C_EXTENSIONS OFF)
target_compile_definitions(${PROJECT_NAME} PRIVATE CL_TARGET_OPENCL_VERSION=100)
target_compile_options(${PROJECT_NAME} PRIVATE $<$<CXX_COMPILER_ID:MSVC>:/W4>)
What does the script do?
To invoke this script, place it next to our Main.c
file in a file called CMakeLists.txt
. Once that’s done, cmake may be invoked the following way to generate Ninja makefiles in the advised out-of-source fashion into a subfolder named build
:
cmake -G Ninja -S . -B .\build -D CMAKE_TOOLCHAIN_FILE=C:\Users\mnagy\Source\Repos\vcpkg\scripts\buildsystems\vcpkg.cmake
Which will output something like
-- The C compiler identification is MSVC 19.22.27905.0
-- Check for working C compiler: C:/Kellekek/Microsoft/VisualStudio/2019/BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe
-- Check for working C compiler: C:/Kellekek/Microsoft/VisualStudio/2019/BuildTools/VC/Tools/MSVC/14.22.27905/bin/Hostx64/x64/cl.exe -- works
-- Detecting C compiler ABI info
-- Detecting C compiler ABI info - done
-- Detecting C compile features
-- Detecting C compile features - done
-- Looking for CL_VERSION_2_2
-- Looking for CL_VERSION_2_2 - found
-- Found OpenCL: C:/Users/mnagy/Source/Repos/vcpkg/installed/x64-windows/debug/lib/OpenCL.lib (found version "2.2")
-- Looking for pthread.h
-- Looking for pthread.h - not found
-- Found Threads: TRUE
-- Configuring done
-- Generating done
-- Build files have been written to: C:/Users/mnagy/Source/CL-Min1/build
-D OpenCL_INCLUDE_DIR=C:\Users\<username>\Source\Repos\vcpkg\installed\x64-windows\include -D OpenCL_LIBRARY=C:\Users\<username>\Source\Repos\vcpkg\installed\x64-windows\debug\lib\OpenCL.lib
on the CMake invocation. This very soon becomes tedious. CMake supports loading user-provided scripts very early during configuration allowing to hijack much of CMake’s internal machinery, including finding packages. By using this so called toolchain file provided by Vcpkg, all packages (aka. ports) installed through Vcpkg will be found without further user interaction.)To kick off the build, one may use CMakes build driver:
cmake --build .\build
Once build is complete, we can run it by typing:
.\build\HelloOpenCL.exe
To have a decent developer experience in the IDE, we will need to install a few extensions. (On how to install extensions, refer to the corresponding docs.)
These extensions will help us author, navigate, build, test, debug code. The OpenCL extension provides syntax highlight for OpenCL device code and provide in-editor documentation for API functions.
In order for all the features of IntelliSense and code navigation to shine, the extension has to know what compiler switches were used when building each and every source file. Lucky for us, the extension plays along nicely with CMake Tools, therefore we’ll just tell it to use CMake as a configuration provider whenever possible without any prompts. (If it fails, it will still give us the usual dialog window.)
In Settings, search for “provider” which will let us set C_Cpp: Default: Configuration Provider
which if one cannot set in the UI, one has to set the following value in settings.json
:
"C_Cpp.default.configurationProvider": "vector-of-bool.cmake-tools"
CMake Tools need to be configured in order to be able to use it properly. For an extensive guide, refer to the docs of the extension.
We installed CMake through the Visual Studio Build Tools installer, hence it’s not on the PATH by default, and as such CMake Tools won’t find it. Open up the settings editor and search for “cmake path”. The settings pane should have a Cmake: Cmake Path
entry. Put the full path of cmake.exe
from your build tools install there. Something like: C:\Kellekek\Microsoft\VisualStudio\2019\BuildTools\Common7\IDE\CommonExtensions\Microsoft\CMake\CMake\bin\cmake.exe
. Reloading the window will re-initalize all extensions.
To eliminate most cases of having to .gitignore our build folder inside the source tree, we’ll instruct CMake to build inside the hidden .vscode folder. Search in settings for “build directory” and in the entry titled Cmake: Build Directory
write: ${workspaceRoot}/.vscode/build
.
Issuing the CMake: Scan for Kits
command should populate the cmake-tools-kits.json
file found under C:\Users\<username>\AppData\Local\CMakeTools\cmake-tools-kits.json
. The file can be opened using the CMake: Edit user-local CMake kits
command. The names of the Visual C++ kits are fairly long, so we can rename it to be shorter, but more importantly add the Vcpkg toolchain file for dependency detection in a setup’n’forget manner.
{
"name": "MSVC 19",
"visualStudio": "VisualStudio.16.0",
"visualStudioArchitecture": "amd64",
"toolchainFile": "C:/Users/<username>/Source/Repos/vcpkg/scripts/buildsystems/vcpkg.cmake"
}
I would also suggest enabling Cmake: Configure On Open
to save some time when opening CMake projects.
If Main.c
and the accompanying CMakeLists.txt
were not in a folder up until now, place them in a folder and open the folder with Code.
Selecting the kit we created earlier, after opening both files and dragging them side-by-side, one may arrive at a configured project looking something like this:
Pressing the little gear icon on the bottom status bar will the CMake build driver. Clicking on the [all]
button next to it, one may change build targets.
To launch our program through the debugger, one may click the little button on the bottom status bar and select the target we wish to launch. It will display all messages from the debugger in the Debug Console
interleaved with program standard output in different colors.
On all the capabilities of debugging using the C/C++ extension refer to its docs and on how to obtain the path to executables for setting up launch.json
refer to the corresponding CMake Tools docs section.
If we want to leverage the CTest unit testing framework, we could add a few lines to our CMakeLists.txt
file to check if our program executed fine (exited with return code 0).
if(BUILD_TESTING)
include(CTest)
add_test(NAME PlatformEnumeration
COMMAND ${PROJECT_NAME})
endif(BUILD_TESTING)
Beside adding these few lines to add a test, we should also flip the canonical BUILD_TESTING
switch during configuration (and not hardcode it in our scripts). Under Settings, search for “configure args” and click the Add Item
button. In the text box, enter -DBUILD_TESTING=ON
.
Invoke the CMake: Configure
command. In the Test Explorer sidebar menu our newly added test should show up. (Currently may require to hit the refresh button on the top).
Hitting either the “play” button (Test Explorer: run all tests
) or selectively the next to the test name (needs mouse hover to display), the test will run and show whether it passed or not. If everything went fine, it will show a green checkmark to indicate success.