diff --git a/.appveyor.yml b/.appveyor.yml
index f1c9b99..44ca24b 100644
--- a/.appveyor.yml
+++ b/.appveyor.yml
@@ -10,6 +10,10 @@ configuration:
#- Debug
- Release
+skip_commits:
+ files:
+ - '**/*.md'
+
before_build:
- git clone --depth=1 https://github.com/KhronosGroup/OpenCL-Headers external/OpenCL-Headers
- git clone --depth=1 https://github.com/KhronosGroup/OpenCL-ICD-Loader external/opencl-icd-loader
diff --git a/.github/workflows/build.yml b/.github/workflows/build.yml
new file mode 100644
index 0000000..e60eabd
--- /dev/null
+++ b/.github/workflows/build.yml
@@ -0,0 +1,82 @@
+name: build
+
+on:
+ push:
+ paths-ignore:
+ - '**/*.md'
+ pull_request:
+ branches:
+ - main
+
+env:
+ BUILD_TYPE: RelWithDebInfo
+
+jobs:
+ check:
+ runs-on: ubuntu-latest
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Check Tabs
+ run: |
+ if git grep -n $'\t' samples/*.cpp samples/*.h tutorials/*.cpp tutorials/*.h; then echo 'Please replace tabs with spaces in source files.'; false; fi
+
+ - name: Check Whitespace
+ run: |
+ if git grep -n '[[:blank:]]$' samples/*.cpp samples/*.h tutorials/*.cpp tutorials/*.h; then echo 'Please remove trailing whitespace from source files.'; false; fi
+
+ build:
+ needs: check
+
+ strategy:
+ matrix:
+ os: [ubuntu-latest, windows-latest]
+ ext: [YES, NO]
+
+ runs-on: ${{matrix.os}}
+
+ steps:
+ - uses: actions/checkout@v3
+
+ - name: Get Ubuntu OpenGL Dependencies
+ if: matrix.os == 'ubuntu-latest'
+ run: |
+ sudo apt-get update
+ sudo apt-get install -y libglfw3-dev
+
+ - name: Get OpenCL Headers
+ uses: actions/checkout@v3
+ with:
+ repository: KhronosGroup/OpenCL-Headers
+ path: external/OpenCL-Headers
+
+ - name: Get OpenCL ICD Loader
+ uses: actions/checkout@v3
+ with:
+ repository: KhronosGroup/OpenCL-ICD-Loader
+ path: external/opencl-icd-loader
+
+ - name: Get OpenCL Extension Loader
+ if: matrix.ext == 'YES'
+ uses: actions/checkout@v3
+ with:
+ repository: bashbaug/opencl-extension-loader
+ path: external/opencl-extension-loader
+
+ - name: Create Build Directory
+ run: cmake -E make_directory ${{runner.workspace}}/build
+
+ - name: Run CMake
+ shell: bash
+ working-directory: ${{runner.workspace}}/build
+ run: cmake -DOpenCL_INCLUDE_DIRS=$GITHUB_WORKSPACE/external/OpenCL-Headers -DCMAKE_BUILD_TYPE=$BUILD_TYPE $GITHUB_WORKSPACE
+
+ - name: Build
+ working-directory: ${{runner.workspace}}/build
+ shell: bash
+ run: cmake --build . --parallel --config $BUILD_TYPE
+
+ #- name: Test
+ # working-directory: ${{runner.workspace}}/build
+ # shell: bash
+ # run: ctest -C $BUILD_TYPE
diff --git a/CMakeLists.txt b/CMakeLists.txt
index 8be375e..f421ce2 100644
--- a/CMakeLists.txt
+++ b/CMakeLists.txt
@@ -32,21 +32,33 @@ set_property(GLOBAL PROPERTY USE_FOLDERS ON)
project(SimpleOpenCLSamples VERSION 1.0)
+option(SAMPLES_ENABLE_EXCEPTIONS "Enable Exceptions for OpenCL Errors")
+
set(OpenCL_INCLUDE_DIR ${CMAKE_CURRENT_SOURCE_DIR}/external/OpenCL-Headers CACHE PATH "Path to OpenCL Headers")
find_package(OpenCL)
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${OpenCL_INCLUDE_DIR})
+add_subdirectory(external/OpenCL-Headers)
add_subdirectory(external/opencl-icd-loader)
set_target_properties(OpenCL PROPERTIES FOLDER "OpenCL-ICD-Loader")
+set_target_properties(cllayerinfo PROPERTIES FOLDER "OpenCL-ICD-Loader")
set(OpenCL_LIBRARIES OpenCL)
+if(IS_DIRECTORY ${CMAKE_CURRENT_SOURCE_DIR}/external/opencl-extension-loader)
+ add_subdirectory(external/opencl-extension-loader)
+else()
+ message(STATUS "OpenCL Extension Loader is not found.")
+endif()
+
if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME)
enable_testing()
endif()
+add_subdirectory(layers)
add_subdirectory(samples)
+add_subdirectory(tutorials)
if(CMAKE_INSTALL_PREFIX_INITIALIZED_TO_DEFAULT)
set(CMAKE_INSTALL_PREFIX "${CMAKE_CURRENT_SOURCE_DIR}/install" CACHE PATH "Install Path" FORCE)
diff --git a/README.md b/README.md
index 4cfd667..935110f 100644
--- a/README.md
+++ b/README.md
@@ -1,9 +1,14 @@
# Simple OpenCLTM Samples
+[![build](https://github.com/bashbaug/SimpleOpenCLSamples/workflows/build/badge.svg?branch=main)](https://github.com/bashbaug/SimpleOpenCLSamples/actions?query=workflow%3Abuild+branch%3Amain)
+
This repo contains simple OpenCL samples that demonstrate how to build
OpenCL applications using only the Khronos-provided headers and libs.
All samples have been tested on Windows and Linux.
+Most of the samples are written in C and C++ using the OpenCL C++ bindings.
+A few of the samples have been ported to Python using [PyOpenCL](https://pypi.org/project/pyopencl/).
+
## Code Structure
@@ -13,7 +18,9 @@ LICENSE License information
CMakeLists.txt Top-level CMakefile
external/ External Projects (headers and libs)
include/ Include Files (OpenCL C++ bindings)
-samples/ Samples
+layers/ Sample Layers
+samples/ Sample Applications
+tutorials/ Tutorials
```
## How to Build the Samples
@@ -28,6 +35,10 @@ OpenCL ICD Loader:
git clone https://github.com/KhronosGroup/opencl-icd-loader external/opencl-icd-loader
+Many samples that use extensions additionally require the OpenCL Extension Loader:
+
+ git clone https://github.com/bashbaug/opencl-extension-loader external/opencl-extension-loader
+
After satisfying the external dependencies create build files using CMake. For example:
mkdir build && cd build
@@ -48,10 +59,21 @@ implementations as well.
## Further Reading
-* [Environment Setup for Ubuntu 18.04](docs/env/ubuntu/18.04.md)
+* [Environment Setup for Ubuntu 22.04](docs/env/ubuntu/22.04.md)
* [OpenCLPapers](https://github.com/bashbaug/OpenCLPapers)
-* [OpenCL Specs](https://www.khronos.org/registry/OpenCL/specs/)
-* [OpenCL Return Codes](https://streamhpc.com/blog/2013-04-28/opencl-error-codes/)
+* [OpenCL Specs](https://registry.khronos.org/OpenCL/)
+* [OpenCL Error Codes](https://registry.khronos.org/OpenCL/specs/3.0-unified/html/OpenCL_API.html#error_codes)
+
+## A Note About Error Checking
+
+For brevity, most samples do not include error checking. This means that a
+sample may crash or incorrectly report success if an OpenCL error occurs. By
+defining the CMake variable `SAMPLES_ENABLE_EXCEPTIONS` many samples can instead
+throw an exception if an OpenCL error occurs.
+
+Tools like the [OpenCL Intercept Layer](https://github.com/intel/opencl-intercept-layer)
+can also be useful to detect when an OpenCL error occurs and to identify the
+cause of the error.
## License
@@ -62,6 +84,11 @@ Notes:
[Khronos OpenCL-CLHPP Repo](https://github.com/KhronosGroup/OpenCL-CLHPP),
and is licensed under the
[Khronos(tm) License](https://github.com/KhronosGroup/OpenCL-CLHPP/blob/master/LICENSE.txt).
+* The samples use [popl](https://github.com/badaix/popl) for its options
+parsing, which is licensed under the MIT License.
+* The samples use [stb](https://github.com/nothings/stb) for image reading and
+ writing, which is dual-licensed under a public domain license and the MIT
+ license.
---
OpenCL and the OpenCL logo are trademarks of Apple Inc. used by permission by Khronos.
diff --git a/docs/env/ubuntu/18.04.md b/docs/env/ubuntu/18.04.md
index d935ca8..c7f5190 100644
--- a/docs/env/ubuntu/18.04.md
+++ b/docs/env/ubuntu/18.04.md
@@ -34,7 +34,7 @@ OpenCL applications generally link against an OpenCL Installable Compute Device
### AMD
-TODO
+AMD supports OpenCL through their ROCm platform. Installation instructions are [here](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html#ubuntu).
### Intel
Intel's OpenCL support is provided through the NEO compute runtime, available as a PPA.
diff --git a/docs/env/ubuntu/19.04.md b/docs/env/ubuntu/19.04.md
index d935ca8..5f2b835 100644
--- a/docs/env/ubuntu/19.04.md
+++ b/docs/env/ubuntu/19.04.md
@@ -34,7 +34,7 @@ OpenCL applications generally link against an OpenCL Installable Compute Device
### AMD
-TODO
+AMD provides official support for LTS releases only.
### Intel
Intel's OpenCL support is provided through the NEO compute runtime, available as a PPA.
diff --git a/docs/env/ubuntu/19.10.md b/docs/env/ubuntu/19.10.md
index f26406d..7beb08a 100644
--- a/docs/env/ubuntu/19.10.md
+++ b/docs/env/ubuntu/19.10.md
@@ -34,7 +34,7 @@ OpenCL applications generally link against an OpenCL Installable Compute Device
### AMD
-TODO
+AMD provides official support for LTS releases only.
### Intel
Intel's OpenCL support is provided through the NEO compute runtime, available as a PPA.
diff --git a/docs/env/ubuntu/20.04.md b/docs/env/ubuntu/20.04.md
index e025a9b..c7026fd 100644
--- a/docs/env/ubuntu/20.04.md
+++ b/docs/env/ubuntu/20.04.md
@@ -36,7 +36,7 @@ OpenCL applications generally link against an OpenCL Installable Compute Device
### AMD Compute Runtime
-TODO
+AMD supports OpenCL through their ROCm platform. Installation instructions are [here](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html#ubuntu).
### Intel Compute Runtime
diff --git a/docs/env/ubuntu/22.04.md b/docs/env/ubuntu/22.04.md
new file mode 100644
index 0000000..396c27d
--- /dev/null
+++ b/docs/env/ubuntu/22.04.md
@@ -0,0 +1,82 @@
+# Ubuntu 22.04 Setup Instructions
+
+## Verify Hardware Support
+
+Most modern GPUs support OpenCL. For integrated graphics devices (iGPUs), use `lscpu` to get the processor SKU. Detailed information for Intel SKUs is available from [ark.intel.com](ark.intel.com). Detailed information for AMD processors is available from [AMD's product page](https://www.amd.com/en/products/specifications/processors).
+
+## Build Dependencies
+
+OCL Headers:
+
+```bash
+sudo apt install opencl-c-headers opencl-clhpp-headers
+```
+
+The OpenCL API has its own set of header files; the above command installs both C and C++ headers files. The C header can be found in ``; the C++ header is in ``.
+
+OCL ICD Loader:
+
+```bash
+sudo apt install ocl-icd-opencl-dev
+```
+
+OpenCL applications generally link against an OpenCL Installable Compute Device (ICD) loader instead of a specific OpenCL implementation; see [https://github.com/bashbaug/OpenCLPapers/blob/master/OpenCLOnLinux.asciidoc](https://github.com/bashbaug/OpenCLPapers/blob/master/OpenCLOnLinux.asciidoc) for more information about this system.
+
+## Runtime Dependencies
+
+OpenCL requires a compute runtime to manage the interaction between the OpenCL API and the GPU.
+
+### OCL ICD Loader
+
+```bash
+sudo apt install ocl-icd-libopencl1
+```
+
+OpenCL applications generally link against an OpenCL Installable Compute Device (ICD) loader instead of a specific OpenCL implementation; see [https://github.com/bashbaug/OpenCLPapers/blob/master/OpenCLOnLinux.asciidoc](https://github.com/bashbaug/OpenCLPapers/blob/master/OpenCLOnLinux.asciidoc) for more information about this system.
+
+### AMD Compute Runtime
+
+AMD supports OpenCL through their ROCm platform. Installation instructions are [here](https://rocmdocs.amd.com/en/latest/Installation_Guide/Installation-Guide.html#ubuntu).
+
+### Intel Compute Runtime
+
+Intel's OpenCL support is provided through the NEO compute runtime. Download packages from the project's [GitHub releases page](https://github.com/intel/compute-runtime/releases).
+
+### Nvidia Compute Runtime
+
+Nvidia provides OpenCL support through their proprietary driver, available from the [graphics-drivers PPA](https://launchpad.net/~graphics-drivers/+archive/ubuntu/ppa).
+
+```bash
+sudo add-apt-repository ppa:graphics-drivers/ppa
+sudo apt update
+sudo apt install nvidia-graphics-drivers-
+```
+
+### Configure Permissions
+
+```bash
+sudo usermod -a -G video $USER
+sudo usermod -a -G render $USER
+```
+
+Users running OpenCL applications on a GPU require additional permissions granted by the groups above.
+
+## Verification
+
+The `clinfo` utility can be used to verify the environment has been properly configured.
+
+```bash
+$ sudo apt install clinfo
+$ clinfo
+
+```
+
+## Troubleshooting
+
+If `clinfo` indicates there are 0 supported platforms:
+
+1. Verify your host has OpenCL-capable hardware attached
+2. Verify clinfo is running as a user with appropriate group membership
+3. Verify new group membership has been applied (this may require logout or reboot)
+4. Verify the correct compute runtime is installed
+5. Check the kernel log (`sudo dmesg`) for related errors
diff --git a/include/CL/opencl.hpp b/include/CL/opencl.hpp
index 2567073..1c43ae0 100644
--- a/include/CL/opencl.hpp
+++ b/include/CL/opencl.hpp
@@ -16,9 +16,8 @@
/*! \file
*
- * \brief C++ bindings for OpenCL 1.0 (rev 48), OpenCL 1.1 (rev 33),
- * OpenCL 1.2 (rev 15), OpenCL 2.0 (rev 29), OpenCL 2.1 (rev 17),
- * and OpenCL 2.2 (V2.2-11).
+ * \brief C++ bindings for OpenCL 1.0, OpenCL 1.1, OpenCL 1.2,
+ * OpenCL 2.0, OpenCL 2.1, OpenCL 2.2, and OpenCL 3.0.
* \author Lee Howes and Bruce Merry
*
* Derived from the OpenCL 1.x C++ bindings written by
@@ -61,10 +60,10 @@
* For many large applications C++ is the language of choice and so it seems
* reasonable to define C++ bindings for OpenCL.
*
- * The interface is contained with a single C++ header file \em cl2.hpp and all
+ * The interface is contained with a single C++ header file \em opencl.hpp and all
* definitions are contained within the namespace \em cl. There is no additional
* requirement to include \em cl.h and to use either the C++ or original C
- * bindings; it is enough to simply include \em cl2.hpp.
+ * bindings; it is enough to simply include \em opencl.hpp.
*
* The bindings themselves are lightweight and correspond closely to the
* underlying C API. Using the C++ bindings introduces no additional execution
@@ -73,7 +72,7 @@
* There are numerous compatibility, portability and memory management
* fixes in the new header as well as additional OpenCL 2.0 features.
* As a result the header is not directly backward compatible and for this
- * reason we release it as cl2.hpp rather than a new version of cl.hpp.
+ * reason we release it as opencl.hpp rather than a new version of cl.hpp.
*
*
* \section compatibility Compatibility
@@ -145,26 +144,26 @@
* - CL_HPP_NO_STD_STRING
*
* Do not use the standard library string class. cl::string is not
- * defined and may be defined by the user before cl2.hpp is
+ * defined and may be defined by the user before opencl.hpp is
* included.
*
* - CL_HPP_NO_STD_VECTOR
*
* Do not use the standard library vector class. cl::vector is not
- * defined and may be defined by the user before cl2.hpp is
+ * defined and may be defined by the user before opencl.hpp is
* included.
*
* - CL_HPP_NO_STD_ARRAY
*
* Do not use the standard library array class. cl::array is not
- * defined and may be defined by the user before cl2.hpp is
+ * defined and may be defined by the user before opencl.hpp is
* included.
*
* - CL_HPP_NO_STD_UNIQUE_PTR
*
* Do not use the standard library unique_ptr class. cl::pointer and
* the cl::allocate_pointer functions are not defined and may be
- * defined by the user before cl2.hpp is included.
+ * defined by the user before opencl.hpp is included.
*
* - CL_HPP_ENABLE_DEVICE_FISSION
*
@@ -215,7 +214,7 @@
#define CL_HPP_ENABLE_EXCEPTIONS
#define CL_HPP_TARGET_OPENCL_VERSION 200
- #include
+ #include
#include
#include
#include
@@ -435,8 +434,8 @@
/* Detect which version to target */
#if !defined(CL_HPP_TARGET_OPENCL_VERSION)
-# pragma message("opencl.hpp: CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 220 (OpenCL 2.2)")
-# define CL_HPP_TARGET_OPENCL_VERSION 220
+# pragma message("opencl.hpp: CL_HPP_TARGET_OPENCL_VERSION is not defined. It will default to 300 (OpenCL 3.0)")
+# define CL_HPP_TARGET_OPENCL_VERSION 300
#endif
#if CL_HPP_TARGET_OPENCL_VERSION != 100 && \
CL_HPP_TARGET_OPENCL_VERSION != 110 && \
@@ -445,9 +444,9 @@
CL_HPP_TARGET_OPENCL_VERSION != 210 && \
CL_HPP_TARGET_OPENCL_VERSION != 220 && \
CL_HPP_TARGET_OPENCL_VERSION != 300
-# pragma message("opencl.hpp: CL_HPP_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120, 200, 210, 220 or 300). It will be set to 220")
+# pragma message("opencl.hpp: CL_HPP_TARGET_OPENCL_VERSION is not a valid value (100, 110, 120, 200, 210, 220 or 300). It will be set to 300 (OpenCL 3.0).")
# undef CL_HPP_TARGET_OPENCL_VERSION
-# define CL_HPP_TARGET_OPENCL_VERSION 220
+# define CL_HPP_TARGET_OPENCL_VERSION 300
#endif
/* Forward target OpenCL version to C headers if necessary */
@@ -549,19 +548,19 @@
// Define deprecated prefixes and suffixes to ensure compilation
// in case they are not pre-defined
-#if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
-#define CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
-#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
-#if !defined(CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED)
-#define CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
-#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_1_DEPRECATED)
-
-#if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
-#define CL_EXT_PREFIX__VERSION_1_2_DEPRECATED
-#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
-#if !defined(CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED)
-#define CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED
-#endif // #if !defined(CL_EXT_PREFIX__VERSION_1_2_DEPRECATED)
+#if !defined(CL_API_PREFIX__VERSION_1_1_DEPRECATED)
+#define CL_API_PREFIX__VERSION_1_1_DEPRECATED
+#endif // #if !defined(CL_API_PREFIX__VERSION_1_1_DEPRECATED)
+#if !defined(CL_API_SUFFIX__VERSION_1_1_DEPRECATED)
+#define CL_API_SUFFIX__VERSION_1_1_DEPRECATED
+#endif // #if !defined(CL_API_PREFIX__VERSION_1_1_DEPRECATED)
+
+#if !defined(CL_API_PREFIX__VERSION_1_2_DEPRECATED)
+#define CL_API_PREFIX__VERSION_1_2_DEPRECATED
+#endif // #if !defined(CL_API_PREFIX__VERSION_1_2_DEPRECATED)
+#if !defined(CL_API_SUFFIX__VERSION_1_2_DEPRECATED)
+#define CL_API_SUFFIX__VERSION_1_2_DEPRECATED
+#endif // #if !defined(CL_API_PREFIX__VERSION_1_2_DEPRECATED)
#if !defined(CL_CALLBACK)
#define CL_CALLBACK
@@ -970,6 +969,11 @@ static inline cl_int errHandler (cl_int err, const char * errStr = NULL)
#define __CLONE_KERNEL_ERR CL_HPP_ERR_STR_(clCloneKernel)
#endif // CL_HPP_TARGET_OPENCL_VERSION >= 210
+#if defined(cl_khr_command_buffer)
+#define __GET_COMMAND_BUFFER_INFO_KHR_ERR CL_HPP_ERR_STR_(clGetCommandBufferInfoKHR)
+#define __FINALIZE_COMMAND_BUFFER_KHR_ERR CL_HPP_ERR_STR_(clFinalizeCommandBufferKHR)
+#endif // cl_khr_command_buffer
+
#endif // CL_HPP_USER_OVERRIDE_ERROR_STRINGS
//! \endcond
@@ -1318,13 +1322,20 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_kernel_arg_info, CL_KERNEL_ARG_NAME, string) \
F(cl_kernel_arg_info, CL_KERNEL_ARG_TYPE_QUALIFIER, cl_kernel_arg_type_qualifier) \
\
+ F(cl_kernel_work_group_info, CL_KERNEL_GLOBAL_WORK_SIZE, cl::detail::size_t_array) \
+ \
+ F(cl_device_info, CL_DEVICE_LINKER_AVAILABLE, cl_bool) \
+ F(cl_device_info, CL_DEVICE_IMAGE_MAX_BUFFER_SIZE, size_type) \
+ F(cl_device_info, CL_DEVICE_IMAGE_MAX_ARRAY_SIZE, size_type) \
F(cl_device_info, CL_DEVICE_PARENT_DEVICE, cl::Device) \
+ F(cl_device_info, CL_DEVICE_PARTITION_MAX_SUB_DEVICES, cl_uint) \
F(cl_device_info, CL_DEVICE_PARTITION_PROPERTIES, cl::vector) \
F(cl_device_info, CL_DEVICE_PARTITION_TYPE, cl::vector) \
F(cl_device_info, CL_DEVICE_REFERENCE_COUNT, cl_uint) \
- F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, size_type) \
+ F(cl_device_info, CL_DEVICE_PREFERRED_INTEROP_USER_SYNC, cl_bool) \
F(cl_device_info, CL_DEVICE_PARTITION_AFFINITY_DOMAIN, cl_device_affinity_domain) \
F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS, string) \
+ F(cl_device_info, CL_DEVICE_PRINTF_BUFFER_SIZE, size_type) \
\
F(cl_image_info, CL_IMAGE_ARRAY_SIZE, size_type) \
F(cl_image_info, CL_IMAGE_NUM_MIP_LEVELS, cl_uint) \
@@ -1344,7 +1355,14 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_device_info, CL_DEVICE_PREFERRED_PLATFORM_ATOMIC_ALIGNMENT, cl_uint) \
F(cl_device_info, CL_DEVICE_PREFERRED_GLOBAL_ATOMIC_ALIGNMENT, cl_uint) \
F(cl_device_info, CL_DEVICE_PREFERRED_LOCAL_ATOMIC_ALIGNMENT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_IMAGE_PITCH_ALIGNMENT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_IMAGE_BASE_ADDRESS_ALIGNMENT, cl_uint) \
+ F(cl_device_info, CL_DEVICE_MAX_READ_WRITE_IMAGE_ARGS, cl_uint ) \
+ F(cl_device_info, CL_DEVICE_MAX_GLOBAL_VARIABLE_SIZE, size_type ) \
+ F(cl_device_info, CL_DEVICE_GLOBAL_VARIABLE_PREFERRED_TOTAL_SIZE, size_type ) \
F(cl_profiling_info, CL_PROFILING_COMMAND_COMPLETE, cl_ulong) \
+ F(cl_kernel_exec_info, CL_KERNEL_EXEC_INFO_SVM_FINE_GRAIN_SYSTEM, cl_bool) \
+ F(cl_kernel_exec_info, CL_KERNEL_EXEC_INFO_SVM_PTRS, void**) \
F(cl_command_queue_info, CL_QUEUE_SIZE, cl_uint) \
F(cl_mem_info, CL_MEM_USES_SVM_POINTER, cl_bool) \
F(cl_program_build_info, CL_PROGRAM_BUILD_GLOBAL_VARIABLE_TOTAL_SIZE, size_type) \
@@ -1360,17 +1378,17 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_program_info, CL_PROGRAM_IL_KHR, cl::vector)
#define CL_HPP_PARAM_NAME_INFO_2_1_(F) \
- F(cl_platform_info, CL_PLATFORM_HOST_TIMER_RESOLUTION, size_type) \
+ F(cl_platform_info, CL_PLATFORM_HOST_TIMER_RESOLUTION, cl_ulong) \
F(cl_program_info, CL_PROGRAM_IL, cl::vector) \
- F(cl_kernel_info, CL_KERNEL_MAX_NUM_SUB_GROUPS, size_type) \
- F(cl_kernel_info, CL_KERNEL_COMPILE_NUM_SUB_GROUPS, size_type) \
F(cl_device_info, CL_DEVICE_MAX_NUM_SUB_GROUPS, cl_uint) \
F(cl_device_info, CL_DEVICE_IL_VERSION, string) \
F(cl_device_info, CL_DEVICE_SUB_GROUP_INDEPENDENT_FORWARD_PROGRESS, cl_bool) \
F(cl_command_queue_info, CL_QUEUE_DEVICE_DEFAULT, cl::DeviceCommandQueue) \
F(cl_kernel_sub_group_info, CL_KERNEL_MAX_SUB_GROUP_SIZE_FOR_NDRANGE, size_type) \
F(cl_kernel_sub_group_info, CL_KERNEL_SUB_GROUP_COUNT_FOR_NDRANGE, size_type) \
- F(cl_kernel_sub_group_info, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, cl::detail::size_t_array)
+ F(cl_kernel_sub_group_info, CL_KERNEL_LOCAL_SIZE_FOR_SUB_GROUP_COUNT, cl::detail::size_t_array) \
+ F(cl_kernel_sub_group_info, CL_KERNEL_MAX_NUM_SUB_GROUPS, size_type) \
+ F(cl_kernel_sub_group_info, CL_KERNEL_COMPILE_NUM_SUB_GROUPS, size_type)
#define CL_HPP_PARAM_NAME_INFO_2_2_(F) \
F(cl_program_info, CL_PROGRAM_SCOPE_GLOBAL_CTORS_PRESENT, cl_bool) \
@@ -1383,7 +1401,7 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_device_info, CL_DEVICE_REFERENCE_COUNT_EXT , cl_uint) \
F(cl_device_info, CL_DEVICE_PARTITION_STYLE_EXT, cl::vector)
-#define CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_SHARED_(F) \
+#define CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_CL3_SHARED_(F) \
F(cl_platform_info, CL_PLATFORM_NUMERIC_VERSION_KHR, cl_version_khr) \
F(cl_platform_info, CL_PLATFORM_EXTENSIONS_WITH_VERSION_KHR, cl::vector) \
\
@@ -1392,7 +1410,7 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_device_info, CL_DEVICE_ILS_WITH_VERSION_KHR, cl::vector) \
F(cl_device_info, CL_DEVICE_BUILT_IN_KERNELS_WITH_VERSION_KHR, cl::vector)
-#define CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_UNIQUE_(F) \
+#define CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_KHRONLY_(F) \
F(cl_device_info, CL_DEVICE_OPENCL_C_NUMERIC_VERSION_KHR, cl_version_khr)
#define CL_HPP_PARAM_NAME_INFO_3_0_(F) \
@@ -1411,15 +1429,20 @@ inline cl_int getInfoHelper(Func f, cl_uint name, T* param, int, typename T::cl_
F(cl_device_info, CL_DEVICE_WORK_GROUP_COLLECTIVE_FUNCTIONS_SUPPORT, cl_bool) \
F(cl_device_info, CL_DEVICE_GENERIC_ADDRESS_SPACE_SUPPORT, cl_bool) \
F(cl_device_info, CL_DEVICE_OPENCL_C_FEATURES, cl::vector) \
+ F(cl_device_info, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES, cl_device_device_enqueue_capabilities) \
F(cl_device_info, CL_DEVICE_PIPE_SUPPORT, cl_bool) \
+ F(cl_device_info, CL_DEVICE_LATEST_CONFORMANCE_VERSION_PASSED, string) \
\
F(cl_command_queue_info, CL_QUEUE_PROPERTIES_ARRAY, cl::vector) \
F(cl_mem_info, CL_MEM_PROPERTIES, cl::vector) \
F(cl_pipe_info, CL_PIPE_PROPERTIES, cl::vector) \
F(cl_sampler_info, CL_SAMPLER_PROPERTIES, cl::vector)
-// TODO: Add this to CL_HPP_PARAM_NAME_INFO_3_0_ once CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES is in the headers!
-// F(cl_device_info, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES, cl_device_device_enqueue_capabilities) \
+#define CL_HPP_PARAM_NAME_CL_INTEL_COMMAND_QUEUE_FAMILIES_(F) \
+ F(cl_device_info, CL_DEVICE_QUEUE_FAMILY_PROPERTIES_INTEL, cl::vector) \
+ \
+ F(cl_command_queue_info, CL_QUEUE_FAMILY_INTEL, cl_uint) \
+ F(cl_command_queue_info, CL_QUEUE_INDEX_INTEL, cl_uint)
template
@@ -1452,17 +1475,8 @@ CL_HPP_PARAM_NAME_INFO_2_2_(CL_HPP_DECLARE_PARAM_TRAITS_)
#endif // CL_HPP_TARGET_OPENCL_VERSION >= 220
#if CL_HPP_TARGET_OPENCL_VERSION >= 300
CL_HPP_PARAM_NAME_INFO_3_0_(CL_HPP_DECLARE_PARAM_TRAITS_)
-// TODO: Remove this when the headers are updated!
-#if defined(CL_DEVICE_DEVICE_ENQUEUE_SUPPORT)
-CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_DEVICE_ENQUEUE_SUPPORT, cl_bool)
-#endif // CL_DEVICE_DEVICE_ENQUEUE_SUPPORT
-// TODO: Move this into CL_HPP_PARAM_NAME_INFO_3_0_ when the headers are updated!
-#if defined(CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES)
-CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES, cl_device_device_enqueue_capabilities)
-#endif // CL_DEVICE_DEVICE_ENQUEUE_CAPABILITIES
#endif // CL_HPP_TARGET_OPENCL_VERSION >= 300
-
#if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR) && CL_HPP_TARGET_OPENCL_VERSION < 210
CL_HPP_PARAM_NAME_INFO_SUBGROUP_KHR_(CL_HPP_DECLARE_PARAM_TRAITS_)
#endif // #if defined(CL_HPP_USE_CL_SUB_GROUPS_KHR) && CL_HPP_TARGET_OPENCL_VERSION < 210
@@ -1500,11 +1514,56 @@ CL_HPP_PARAM_NAME_DEVICE_FISSION_(CL_HPP_DECLARE_PARAM_TRAITS_);
#if defined(cl_khr_extended_versioning)
#if CL_HPP_TARGET_OPENCL_VERSION < 300
-CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_SHARED_(CL_HPP_DECLARE_PARAM_TRAITS_);
+CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_CL3_SHARED_(CL_HPP_DECLARE_PARAM_TRAITS_)
#endif // CL_HPP_TARGET_OPENCL_VERSION < 300
-CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_UNIQUE_(CL_HPP_DECLARE_PARAM_TRAITS_);
+CL_HPP_PARAM_NAME_CL_KHR_EXTENDED_VERSIONING_KHRONLY_(CL_HPP_DECLARE_PARAM_TRAITS_)
#endif // cl_khr_extended_versioning
+#if defined(cl_khr_device_uuid)
+using uuid_array = array;
+using luid_array = array;
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_UUID_KHR, uuid_array)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DRIVER_UUID_KHR, uuid_array)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LUID_VALID_KHR, cl_bool)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_LUID_KHR, luid_array)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_NODE_MASK_KHR, cl_uint)
+#endif
+
+#if defined(cl_khr_pci_bus_info)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_PCI_BUS_INFO_KHR, cl_device_pci_bus_info_khr)
+#endif
+
+#if defined(cl_khr_integer_dot_product)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_INTEGER_DOT_PRODUCT_CAPABILITIES_KHR, cl_device_integer_dot_product_capabilities_khr)
+#endif
+
+#if defined(cl_khr_command_buffer)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMMAND_BUFFER_CAPABILITIES_KHR, cl_device_command_buffer_capabilities_khr)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMMAND_BUFFER_REQUIRED_QUEUE_PROPERTIES_KHR, cl_command_queue_properties)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_command_buffer_info_khr, CL_COMMAND_BUFFER_QUEUES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_command_buffer_info_khr, CL_COMMAND_BUFFER_NUM_QUEUES_KHR, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_command_buffer_info_khr, CL_COMMAND_BUFFER_REFERENCE_COUNT_KHR, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_command_buffer_info_khr, CL_COMMAND_BUFFER_STATE_KHR, cl_command_buffer_state_khr)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_command_buffer_info_khr, CL_COMMAND_BUFFER_PROPERTIES_ARRAY_KHR, cl::vector)
+#endif // cl_khr_command_buffer
+
+#if defined(cl_khr_external_memory)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_EXTERNAL_MEMORY_IMPORT_HANDLE_TYPES_KHR, cl::vector)
+#endif // cl_khr_external_memory
+
+#if defined(cl_khr_semaphore)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_SEMAPHORE_TYPES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SEMAPHORE_TYPES_KHR, cl::vector)
+#endif // cl_khr_external_memory
+
+#if defined(cl_khr_external_semaphore)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SEMAPHORE_IMPORT_HANDLE_TYPES_KHR, cl::vector)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SEMAPHORE_EXPORT_HANDLE_TYPES_KHR, cl::vector)
+#endif // cl_khr_external_semaphore
+
#ifdef CL_PLATFORM_ICD_SUFFIX_KHR
CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, string)
#endif
@@ -1512,7 +1571,6 @@ CL_HPP_DECLARE_PARAM_TRAITS_(cl_platform_info, CL_PLATFORM_ICD_SUFFIX_KHR, strin
#ifdef CL_DEVICE_PROFILING_TIMER_OFFSET_AMD
CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_PROFILING_TIMER_OFFSET_AMD, cl_ulong)
#endif
-
#ifdef CL_DEVICE_GLOBAL_FREE_MEMORY_AMD
CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_GLOBAL_FREE_MEMORY_AMD, vector)
#endif
@@ -1550,6 +1608,15 @@ CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_UNITS_BITFIELD_AR
#ifdef CL_DEVICE_JOB_SLOTS_ARM
CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_JOB_SLOTS_ARM, cl_uint)
#endif
+#ifdef CL_DEVICE_SCHEDULING_CONTROLS_CAPABILITIES_ARM
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_SCHEDULING_CONTROLS_CAPABILITIES_ARM, cl_bitfield)
+#endif
+#ifdef CL_KERNEL_EXEC_INFO_WORKGROUP_BATCH_SIZE_ARM
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_kernel_exec_info, CL_KERNEL_EXEC_INFO_WORKGROUP_BATCH_SIZE_ARM, cl_uint)
+#endif
+#ifdef CL_KERNEL_EXEC_INFO_WORKGROUP_BATCH_SIZE_MODIFIER_ARM
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_kernel_exec_info, CL_KERNEL_EXEC_INFO_WORKGROUP_BATCH_SIZE_MODIFIER_ARM, cl_int)
+#endif
#ifdef CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV
CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_COMPUTE_CAPABILITY_MAJOR_NV, cl_uint)
@@ -1573,6 +1640,20 @@ CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_KERNEL_EXEC_TIMEOUT_NV, c
CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_INTEGRATED_MEMORY_NV, cl_bool)
#endif
+#if defined(cl_intel_command_queue_families)
+CL_HPP_PARAM_NAME_CL_INTEL_COMMAND_QUEUE_FAMILIES_(CL_HPP_DECLARE_PARAM_TRAITS_)
+#endif // cl_intel_command_queue_families
+
+#if defined(cl_intel_device_attribute_query)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_IP_VERSION_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_ID_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_NUM_SLICES_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_NUM_SUB_SLICES_PER_SLICE_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_NUM_EUS_PER_SUB_SLICE_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_NUM_THREADS_PER_EU_INTEL, cl_uint)
+CL_HPP_DECLARE_PARAM_TRAITS_(cl_device_info, CL_DEVICE_FEATURE_CAPABILITIES_INTEL, cl_device_feature_capabilities_intel)
+#endif // cl_intel_device_attribute_query
+
// Convenience functions
template
@@ -1741,6 +1822,16 @@ struct ReferenceHandler
{ return ::clReleaseEvent(event); }
};
+#if defined(cl_khr_command_buffer)
+template <>
+struct ReferenceHandler
+{
+ static cl_int retain(cl_command_buffer_khr cmdbuf)
+ { return ::clRetainCommandBufferKHR(cmdbuf); }
+ static cl_int release(cl_command_buffer_khr cmdbuf)
+ { return ::clReleaseCommandBufferKHR(cmdbuf); }
+};
+#endif // cl_khr_command_buffer
#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
// Extracts version number with major in the upper 16 bits, minor in the lower 16
@@ -1904,8 +1995,9 @@ class Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 120
#if CL_HPP_MINIMUM_OPENCL_VERSION < 120
if (device != NULL) {
- int version = getDevicePlatformVersion(device);
- if(version > ((1 << 16) + 1)) {
+ cl_platform_id platform = getDevicePlatform(device);
+ cl_uint version = getPlatformVersion(platform);
+ if (version >= 0x10002) {
retVal = true;
}
}
@@ -2097,6 +2189,9 @@ struct ImageFormat : public cl_image_format
image_channel_data_type = type;
}
+ //! \brief Copy constructor.
+ ImageFormat(const ImageFormat &other) { *this = other; }
+
//! \brief Assignment operator.
ImageFormat& operator = (const ImageFormat& rhs)
{
@@ -2350,7 +2445,7 @@ class Device : public detail::Wrapper
const cl_device_partition_property_ext * /* properties */,
cl_uint /*num_entries*/,
cl_device_id * /*out_devices*/,
- cl_uint * /*num_devices*/ ) CL_EXT_SUFFIX__VERSION_1_1;
+ cl_uint * /*num_devices*/ ) CL_API_SUFFIX__VERSION_1_1;
static PFN_clCreateSubDevicesEXT pfn_clCreateSubDevicesEXT = NULL;
CL_HPP_INIT_CL_EXT_FCN_PTR_(clCreateSubDevicesEXT);
@@ -2760,8 +2855,8 @@ CL_HPP_DEFINE_STATIC_MEMBER_ cl_int Platform::default_error_ = CL_SUCCESS;
* Unload the OpenCL compiler.
* \note Deprecated for OpenCL 1.2. Use Platform::unloadCompiler instead.
*/
-inline CL_EXT_PREFIX__VERSION_1_1_DEPRECATED cl_int
-UnloadCompiler() CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+inline CL_API_PREFIX__VERSION_1_1_DEPRECATED cl_int
+UnloadCompiler() CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
inline cl_int
UnloadCompiler()
{
@@ -2851,7 +2946,7 @@ class Context
*/
Context(
const vector& devices,
- cl_context_properties* properties = NULL,
+ const cl_context_properties* properties = NULL,
void (CL_CALLBACK * notifyFptr)(
const char *,
const void *,
@@ -2880,9 +2975,13 @@ class Context
}
}
+ /*! \brief Constructs a context including a specific device.
+ *
+ * Wraps clCreateContext().
+ */
Context(
const Device& device,
- cl_context_properties* properties = NULL,
+ const cl_context_properties* properties = NULL,
void (CL_CALLBACK * notifyFptr)(
const char *,
const void *,
@@ -2912,7 +3011,7 @@ class Context
*/
Context(
cl_device_type type,
- cl_context_properties* properties = NULL,
+ const cl_context_properties* properties = NULL,
void (CL_CALLBACK * notifyFptr)(
const char *,
const void *,
@@ -3278,7 +3377,7 @@ class Event : public detail::Wrapper
*/
cl_int setCallback(
cl_int type,
- void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *),
+ void (CL_CALLBACK * pfn_notify)(cl_event, cl_int, void *),
void * user_data = NULL)
{
return detail::errHandler(
@@ -3467,7 +3566,7 @@ class Memory : public detail::Wrapper
* value - not the Memory class instance.
*/
cl_int setDestructorCallback(
- void (CL_CALLBACK * pfn_notify)(cl_mem, void *),
+ void (CL_CALLBACK * pfn_notify)(cl_mem, void *),
void * user_data = NULL)
{
return detail::errHandler(
@@ -4058,7 +4157,7 @@ class Buffer : public Memory
}
return result;
- }
+ }
#endif // CL_HPP_TARGET_OPENCL_VERSION >= 110
};
@@ -4474,12 +4573,11 @@ class Image1D : public Image
cl_int* err = NULL)
{
cl_int error;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE1D,
- width,
- 0, 0, 0, 0, 0, 0, 0, 0
- };
+
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE1D;
+ desc.image_width = width;
+
object_ = ::clCreateImage(
context(),
flags,
@@ -4562,13 +4660,12 @@ class Image1DBuffer : public Image
cl_int* err = NULL)
{
cl_int error;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE1D_BUFFER,
- width,
- 0, 0, 0, 0, 0, 0, 0,
- buffer()
- };
+
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE1D_BUFFER;
+ desc.image_width = width;
+ desc.buffer = buffer();
+
object_ = ::clCreateImage(
context(),
flags,
@@ -4648,15 +4745,13 @@ class Image1DArray : public Image
cl_int* err = NULL)
{
cl_int error;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE1D_ARRAY,
- width,
- 0, 0, // height, depth (unused)
- arraySize,
- rowPitch,
- 0, 0, 0, 0
- };
+
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE1D_ARRAY;
+ desc.image_width = width;
+ desc.image_array_size = arraySize;
+ desc.image_row_pitch = rowPitch;
+
object_ = ::clCreateImage(
context(),
flags,
@@ -4751,7 +4846,8 @@ class Image2D : public Image
#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getContextPlatform(context());
+ cl_uint version = detail::getPlatformVersion(platform);
useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 120
@@ -4763,15 +4859,12 @@ class Image2D : public Image
#if CL_HPP_TARGET_OPENCL_VERSION >= 120
if (useCreateImage)
{
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE2D,
- width,
- height,
- 0, 0, // depth, array size (unused)
- row_pitch,
- 0, 0, 0, 0
- };
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = width;
+ desc.image_height = height;
+ desc.image_row_pitch = row_pitch;
+
object_ = ::clCreateImage(
context(),
flags,
@@ -4817,17 +4910,13 @@ class Image2D : public Image
{
cl_int error;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE2D,
- width,
- height,
- 0, 0, // depth, array size (unused)
- row_pitch,
- 0, 0, 0,
- // Use buffer as input to image
- sourceBuffer()
- };
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = width;
+ desc.image_height = height;
+ desc.image_row_pitch = row_pitch;
+ desc.buffer = sourceBuffer();
+
object_ = ::clCreateImage(
context(),
0, // flags inherited from buffer
@@ -4881,19 +4970,16 @@ class Image2D : public Image
// Update only the channel order.
// Channel format inherited from source.
sourceFormat.image_channel_order = order;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE2D,
- sourceWidth,
- sourceHeight,
- 0, 0, // depth (unused), array size (unused)
- sourceRowPitch,
- 0, // slice pitch (unused)
- sourceNumMIPLevels,
- sourceNumSamples,
- // Use buffer as input to image
- sourceImage()
- };
+
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D;
+ desc.image_width = sourceWidth;
+ desc.image_height = sourceHeight;
+ desc.image_row_pitch = sourceRowPitch;
+ desc.num_mip_levels = sourceNumMIPLevels;
+ desc.num_samples = sourceNumSamples;
+ desc.buffer = sourceImage();
+
object_ = ::clCreateImage(
context(),
0, // flags should be inherited from mem_object
@@ -4973,7 +5059,7 @@ class Image2D : public Image
* \see Memory
* \note Deprecated for OpenCL 1.2. Please use ImageGL instead.
*/
-class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D
+class CL_API_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D
{
public:
/*! \brief Constructs an Image2DGL in a specified context, from a given
@@ -5056,7 +5142,7 @@ class CL_EXT_PREFIX__VERSION_1_1_DEPRECATED Image2DGL : public Image2D
return *this;
}
-} CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED;
+} CL_API_SUFFIX__VERSION_1_1_DEPRECATED;
#endif // CL_USE_DEPRECATED_OPENCL_1_1_APIS
#if CL_HPP_TARGET_OPENCL_VERSION >= 120
@@ -5079,17 +5165,15 @@ class Image2DArray : public Image
cl_int* err = NULL)
{
cl_int error;
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE2D_ARRAY,
- width,
- height,
- 0, // depth (unused)
- arraySize,
- rowPitch,
- slicePitch,
- 0, 0, 0
- };
+
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE2D_ARRAY;
+ desc.image_width = width;
+ desc.image_height = height;
+ desc.image_array_size = arraySize;
+ desc.image_row_pitch = rowPitch;
+ desc.image_slice_pitch = slicePitch;
+
object_ = ::clCreateImage(
context(),
flags,
@@ -5182,7 +5266,8 @@ class Image3D : public Image
#if CL_HPP_TARGET_OPENCL_VERSION >= 120 && CL_HPP_MINIMUM_OPENCL_VERSION < 120
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getContextPlatform(context());
+ cl_uint version = detail::getPlatformVersion(platform);
useCreateImage = (version >= 0x10002); // OpenCL 1.2 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 120
@@ -5194,17 +5279,14 @@ class Image3D : public Image
#if CL_HPP_TARGET_OPENCL_VERSION >= 120
if (useCreateImage)
{
- cl_image_desc desc =
- {
- CL_MEM_OBJECT_IMAGE3D,
- width,
- height,
- depth,
- 0, // array size (unused)
- row_pitch,
- slice_pitch,
- 0, 0, 0
- };
+ cl_image_desc desc = {0};
+ desc.image_type = CL_MEM_OBJECT_IMAGE3D;
+ desc.image_width = width;
+ desc.image_height = height;
+ desc.image_depth = depth;
+ desc.image_row_pitch = row_pitch;
+ desc.image_slice_pitch = slice_pitch;
+
object_ = ::clCreateImage(
context(),
flags,
@@ -6186,6 +6268,23 @@ class Kernel : public detail::Wrapper
sizeof(void*)*(1 + sizeof...(Ts)),
pointerList.data()));
}
+
+ template
+ cl_int setExecInfo(cl_kernel_exec_info param_name, const T& val)
+ {
+ return detail::errHandler(
+ ::clSetKernelExecInfo(
+ object_,
+ param_name,
+ sizeof(T),
+ &val));
+ }
+
+ template
+ cl_int setExecInfo(typename detail::param_traits::param_type& val)
+ {
+ return setExecInfo(name, val);
+ }
#endif // #if CL_HPP_TARGET_OPENCL_VERSION >= 200
#if CL_HPP_TARGET_OPENCL_VERSION >= 210
@@ -6665,6 +6764,7 @@ class Program : public detail::Wrapper
void* data = NULL) const
{
cl_device_id deviceID = device();
+
cl_int buildError = ::clBuildProgram(
object_,
1,
@@ -6691,7 +6791,6 @@ class Program : public detail::Wrapper
notifyFptr,
data);
-
return detail::buildErrHandler(buildError, __BUILD_PROGRAM_ERR, getBuildInfo());
}
@@ -6845,9 +6944,9 @@ class Program : public detail::Wrapper
* on a callback stack associated with program. The registered user callback
* functions are called in the reverse order in which they were registered.
*/
- CL_EXT_PREFIX__VERSION_2_2_DEPRECATED cl_int setReleaseCallback(
+ CL_API_PREFIX__VERSION_2_2_DEPRECATED cl_int setReleaseCallback(
void (CL_CALLBACK * pfn_notify)(cl_program program, void * user_data),
- void * user_data = NULL) CL_EXT_SUFFIX__VERSION_2_2_DEPRECATED
+ void * user_data = NULL) CL_API_SUFFIX__VERSION_2_2_DEPRECATED
{
return detail::errHandler(
::clSetProgramReleaseCallback(
@@ -7040,6 +7139,93 @@ inline Kernel::Kernel(const Program& program, const char* name, cl_int* err)
}
+#if defined(cl_khr_command_buffer)
+
+/*! \class CommandBuffer
+ * \brief CommandBuffer interface for cl_command_buffer_khr.
+ */
+class CommandBuffer : public detail::Wrapper
+{
+public:
+ CommandBuffer() {}
+
+ /*! \brief Constructor from cl_command_queue - takes ownership.
+ *
+ * \param retainObject will cause the constructor to retain its cl object.
+ * Defaults to false to maintain compatibility with
+ * earlier versions.
+ */
+ explicit CommandBuffer(cl_command_buffer_khr cmdbuf, bool retainObject = false) :
+ detail::Wrapper(cmdbuf, retainObject) { }
+
+ // TODO: other overloads!
+
+ CommandBuffer& operator = (const cl_command_buffer_khr& rhs)
+ {
+ detail::Wrapper::operator=(rhs);
+ return *this;
+ }
+
+ /*! \brief Copy constructor to forward copy to the superclass correctly.
+ * Required for MSVC.
+ */
+ CommandBuffer(const CommandBuffer& cmdbuf) : detail::Wrapper(cmdbuf) {}
+
+ /*! \brief Copy assignment to forward copy to the superclass correctly.
+ * Required for MSVC.
+ */
+ CommandBuffer& operator = (const CommandBuffer& cmdbuf)
+ {
+ detail::Wrapper::operator=(cmdbuf);
+ return *this;
+ }
+
+ /*! \brief Move constructor to forward move to the superclass correctly.
+ * Required for MSVC.
+ */
+ CommandBuffer(CommandBuffer&& cmdbuf) CL_HPP_NOEXCEPT_ : detail::Wrapper(std::move(cmdbuf)) {}
+
+ /*! \brief Move assignment to forward move to the superclass correctly.
+ * Required for MSVC.
+ */
+ CommandBuffer& operator = (CommandBuffer &&cmdbuf)
+ {
+ detail::Wrapper::operator=(std::move(cmdbuf));
+ return *this;
+ }
+
+ template
+ cl_int getInfo(cl_command_buffer_info_khr name, T* param) const
+ {
+ return detail::errHandler(
+ detail::getInfo(
+ &::clGetCommandBufferInfoKHR, object_, name, param),
+ __GET_COMMAND_BUFFER_INFO_KHR_ERR);
+ }
+
+ template typename
+ detail::param_traits::param_type
+ getInfo(cl_int* err = NULL) const
+ {
+ typename detail::param_traits<
+ detail::cl_command_buffer_info_khr, name>::param_type param;
+ cl_int result = getInfo(name, ¶m);
+ if (err != NULL) {
+ *err = result;
+ }
+ return param;
+ }
+
+ cl_int finalize(void)
+ {
+ return detail::errHandler(
+ ::clFinalizeCommandBufferKHR(object_),
+ __FINALIZE_COMMAND_BUFFER_KHR_ERR);
+ }
+}; // CommandBuffer
+
+#endif // cl_khr_command_buffer
+
enum class QueueProperties : cl_command_queue_properties
{
None = 0,
@@ -7142,7 +7328,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(device());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -7208,7 +7395,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(device());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -7273,7 +7461,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(devices[0]());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -7340,7 +7529,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(devices[0]());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -7391,7 +7581,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(device());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -7442,7 +7633,8 @@ class CommandQueue : public detail::Wrapper
#if CL_HPP_TARGET_OPENCL_VERSION >= 200 && CL_HPP_MINIMUM_OPENCL_VERSION < 200
// Run-time decision based on the actual platform
{
- cl_uint version = detail::getContextPlatformVersion(context());
+ cl_platform_id platform = detail::getDevicePlatform(device());
+ cl_uint version = detail::getPlatformVersion(platform);
useWithProperties = (version >= 0x20000); // OpenCL 2.0 or above
}
#elif CL_HPP_TARGET_OPENCL_VERSION >= 200
@@ -8193,7 +8385,7 @@ class CommandQueue : public detail::Wrapper
{
cl_event tmp;
cl_int err = detail::errHandler(::clEnqueueSVMMap(
- object_, blocking, flags, static_cast(container.data()), container.size(),
+ object_, blocking, flags, static_cast(container.data()), container.size()*sizeof(T),
(events != NULL) ? (cl_uint)events->size() : 0,
(events != NULL && events->size() > 0) ? (cl_event*)&events->front() : NULL,
(event != NULL) ? &tmp : NULL),
@@ -8552,10 +8744,10 @@ class CommandQueue : public detail::Wrapper
}
#if defined(CL_USE_DEPRECATED_OPENCL_1_2_APIS)
- CL_EXT_PREFIX__VERSION_1_2_DEPRECATED cl_int enqueueTask(
+ CL_API_PREFIX__VERSION_1_2_DEPRECATED cl_int enqueueTask(
const Kernel& kernel,
const vector* events = NULL,
- Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_2_DEPRECATED
+ Event* event = NULL) const CL_API_SUFFIX__VERSION_1_2_DEPRECATED
{
cl_event tmp;
cl_int err = detail::errHandler(
@@ -8612,8 +8804,8 @@ class CommandQueue : public detail::Wrapper
* Deprecated APIs for 1.2
*/
#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
- CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
- cl_int enqueueMarker(Event* event = NULL) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ CL_API_PREFIX__VERSION_1_1_DEPRECATED
+ cl_int enqueueMarker(Event* event = NULL) const CL_API_SUFFIX__VERSION_1_1_DEPRECATED
{
cl_event tmp;
cl_int err = detail::errHandler(
@@ -8628,8 +8820,8 @@ class CommandQueue : public detail::Wrapper
return err;
}
- CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
- cl_int enqueueWaitForEvents(const vector& events) const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ CL_API_PREFIX__VERSION_1_1_DEPRECATED
+ cl_int enqueueWaitForEvents(const vector& events) const CL_API_SUFFIX__VERSION_1_1_DEPRECATED
{
return detail::errHandler(
::clEnqueueWaitForEvents(
@@ -8765,8 +8957,8 @@ typedef CL_API_ENTRY cl_int (CL_API_CALL *PFN_clEnqueueReleaseD3D10ObjectsKHR)(
* Deprecated APIs for 1.2
*/
#if defined(CL_USE_DEPRECATED_OPENCL_1_1_APIS)
- CL_EXT_PREFIX__VERSION_1_1_DEPRECATED
- cl_int enqueueBarrier() const CL_EXT_SUFFIX__VERSION_1_1_DEPRECATED
+ CL_API_PREFIX__VERSION_1_1_DEPRECATED
+ cl_int enqueueBarrier() const CL_API_SUFFIX__VERSION_1_1_DEPRECATED
{
return detail::errHandler(
::clEnqueueBarrier(object_),
@@ -10277,6 +10469,8 @@ namespace compatibility {
#undef __CLONE_KERNEL_ERR
#undef __GET_HOST_TIMER_ERR
#undef __GET_DEVICE_AND_HOST_TIMER_ERR
+#undef __GET_COMMAND_BUFFER_INFO_KHR_ERR
+#undef __FINALIZE_COMMAND_BUFFER_KHR_ERR
#endif //CL_HPP_USER_OVERRIDE_ERROR_STRINGS
diff --git a/include/layer_util.hpp b/include/layer_util.hpp
new file mode 100644
index 0000000..d826cec
--- /dev/null
+++ b/include/layer_util.hpp
@@ -0,0 +1,136 @@
+/*
+// Copyright (c) 2022 Ben Ashbaugh
+//
+// SPDX-License-Identifier: MIT
+*/
+#pragma once
+
+#include
+
+#include
+#include
+#include
+
+template
+cl_int writeParamToMemory(
+ size_t param_value_size,
+ T param,
+ size_t* param_value_size_ret,
+ T* pointer)
+{
+ if (pointer != nullptr) {
+ if (param_value_size < sizeof(param)) {
+ return CL_INVALID_VALUE;
+ }
+ *pointer = param;
+ }
+
+ if (param_value_size_ret != nullptr) {
+ *param_value_size_ret = sizeof(param);
+ }
+
+ return CL_SUCCESS;
+}
+
+template
+cl_int writeVectorToMemory(
+ size_t param_value_size,
+ const std::vector& param,
+ size_t *param_value_size_ret,
+ T* pointer )
+{
+ size_t size = param.size() * sizeof(T);
+
+ if (pointer != nullptr) {
+ if (param_value_size < size) {
+ return CL_INVALID_VALUE;
+ }
+ memcpy(pointer, param.data(), size);
+ }
+
+ if (param_value_size_ret != nullptr) {
+ *param_value_size_ret = size;
+ }
+
+ return CL_SUCCESS;
+}
+
+static inline cl_int writeStringToMemory(
+ size_t param_value_size,
+ const char* param,
+ size_t* param_value_size_ret,
+ char* pointer )
+{
+ size_t size = strlen(param) + 1;
+
+ if (pointer != nullptr) {
+ if (param_value_size < size) {
+ return CL_INVALID_VALUE;
+ }
+ strcpy(pointer, param);
+ }
+
+ if (param_value_size_ret != nullptr) {
+ *param_value_size_ret = size;
+ }
+
+ return CL_SUCCESS;
+}
+
+static cl_uint getOpenCLVersionFromString(
+ const char* str)
+{
+ cl_uint major = 0;
+ cl_uint minor = 0;
+
+ // The device version string has the form:
+ // OpenCL .
+ const char* prefix = "OpenCL ";
+ size_t sz = strlen(prefix);
+ if (strlen(str) > sz &&
+ strncmp(str, prefix, sz) == 0) {
+ const char* check = str + sz;
+ while (isdigit(check[0])) {
+ major *= 10;
+ major += check[0] - '0';
+ ++check;
+ }
+ if (check[0] == '.') {
+ ++check;
+ }
+ while (isdigit(check[0])) {
+ minor *= 10;
+ minor += check[0] - '0';
+ ++check;
+ }
+ }
+
+ return (major << 16) | minor;
+}
+
+static inline bool checkStringForExtension(
+ const char* str,
+ const char* extensionName )
+{
+ bool supported = false;
+
+ if (extensionName && !strchr(extensionName, ' ')) {
+ const char* start = str;
+ while (true) {
+ const char* where = strstr(start, extensionName);
+ if (!where) {
+ break;
+ }
+ const char* terminator = where + strlen(extensionName);
+ if (where == start || *(where - 1) == ' ') {
+ if (*terminator == ' ' || *terminator == '\0') {
+ supported = true;
+ break;
+ }
+ }
+ start = terminator;
+ }
+ }
+
+ return supported;
+}
diff --git a/include/popl/popl.hpp b/include/popl/popl.hpp
new file mode 100644
index 0000000..23cbb12
--- /dev/null
+++ b/include/popl/popl.hpp
@@ -0,0 +1,1257 @@
+/***
+ ____ __ ____ __
+ ( _ \ / \( _ \( )
+ ) __/( O )) __// (_/\
+ (__) \__/(__) \____/
+ version 1.2.0
+ https://github.com/badaix/popl
+
+ This file is part of popl (program options parser lib)
+ Copyright (C) 2015-2018 Johannes Pohl
+
+ This software may be modified and distributed under the terms
+ of the MIT license. See the LICENSE file for details.
+***/
+
+/// checked with clang-tidy:
+/// run-clang-tidy-3.8.py -header-filter='.*' -checks='*,-misc-definitions-in-headers,-google-readability-braces-around-statements,-readability-braces-around-statements,-cppcoreguidelines-pro-bounds-pointer-arithmetic,-google-build-using-namespace,-google-build-using-namespace'
+
+#ifndef POPL_HPP
+#define POPL_HPP
+
+#ifndef NOMINMAX
+#define NOMINMAX
+#endif // NOMINMAX
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+
+namespace popl
+{
+
+#define POPL_VERSION "1.2.0"
+
+
+/// Option's argument type
+/**
+ * Switch has "no" argument
+ * Value has "required" argument
+ * Implicit has "optional" argument
+ */
+enum class Argument
+{
+ no = 0, // option never takes an argument
+ required, // option always requires an argument
+ optional // option may take an argument
+};
+
+
+/// Option's attribute
+/**
+ * inactive: Option is not set and will not be parsed
+ * hidden: Option is active, but will not show up in the help message
+ * required: Option must be set on the command line. Otherwise an exception will be thrown
+ * optional: Option must not be set. Default attribute.
+ * advanced: Option is advanced and will only show up in the advanced help message
+ * expoert: Option is expert and will only show up in the expert help message
+ */
+enum class Attribute
+{
+ inactive = 0,
+ hidden = 1,
+ required = 2,
+ optional = 3,
+ advanced = 4,
+ expert = 5
+};
+
+
+/// Option name type. Used in invalid_option exception.
+/**
+ * unspecified: not specified
+ * short_name: The option's short name
+ * long_name: The option's long name
+ */
+enum class OptionName
+{
+ unspecified,
+ short_name,
+ long_name
+};
+
+
+/// Abstract Base class for Options
+/**
+ * Base class for Options
+ * holds just configuration data, no runtime data.
+ * Option is not bound to a special type "T"
+ */
+class Option
+{
+friend class OptionParser;
+public:
+ /// Construct an Option
+ /// @param short_name the options's short name. Must be empty or one character.
+ /// @param long_name the option's long name. Can be empty.
+ /// @param description the Option's description that will be shown in the help message
+ Option(const std::string& short_name, const std::string& long_name, std::string description);
+
+ /// Destructor
+ virtual ~Option() = default;
+
+ /// default copy constructor
+ Option(const Option&) = default;
+
+ /// default move constructor
+ Option(Option&&) = default;
+
+ /// default assignement operator
+ Option& operator=(const Option&) = default;
+
+ /// default move assignement operator
+ Option& operator=(Option&&) = default;
+
+ /// Get the Option's short name
+ /// @return character of the options's short name or 0 if no short name is defined
+ char short_name() const;
+
+ /// Get the Option's long name
+ /// @return the long name of the Option. Empty string if no long name is defined
+ std::string long_name() const;
+
+ /// Get the Option's long or short name
+ /// @param what_name the option's name to return
+ /// @param what_hyphen preced the returned name with (double-)hypen
+ /// @return the requested name of the Option. Empty string if not defined.
+ std::string name(OptionName what_name, bool with_hypen = false) const;
+
+ /// Get the Option's description
+ /// @return the description
+ std::string description() const;
+
+ /// Get the Option's default value
+ /// @param out stream to write the default value to
+ /// @return true if a default value is available, false if not
+ virtual bool get_default(std::ostream& out) const = 0;
+
+ /// Set the Option's attribute
+ /// @param attribute
+ void set_attribute(const Attribute& attribute);
+
+ /// Get the Option's attribute
+ /// @return the Options's attribute
+ Attribute attribute() const;
+
+ /// Get the Option's argument type
+ /// @return argument type (no, required, optional)
+ virtual Argument argument_type() const = 0;
+
+ /// Check how often the Option is set on command line
+ /// @return the Option's count on command line
+ virtual size_t count() const = 0;
+
+ /// Check if the Option is set
+ /// @return true if set at least once
+ virtual bool is_set() const = 0;
+
+protected:
+ /// Parse the command line option and fill the internal data structure
+ /// @param what_name short or long option name
+ /// @param value the value as given on command line
+ virtual void parse(OptionName what_name, const char* value) = 0;
+
+ /// Clear the internal data structure
+ virtual void clear() = 0;
+
+ std::string short_name_;
+ std::string long_name_;
+ std::string description_;
+ Attribute attribute_;
+};
+
+
+
+
+/// Value option with optional default value
+/**
+ * Value option with optional default value
+ * If set, it requires an argument
+ */
+template
+class Value : public Option
+{
+public:
+ /// Construct an Value Option
+ /// @param short_name the option's short name. Must be empty or one character.
+ /// @param long_name the option's long name. Can be empty.
+ /// @param description the Option's description that will be shown in the help message
+ Value(const std::string& short_name, const std::string& long_name, const std::string& description);
+
+ /// Construct an Value Option
+ /// @param short_name the option's short name. Must be empty or one character.
+ /// @param long_name the option's long name. Can be empty.
+ /// @param description the Option's description that will be shown in the help message
+ /// @param default_val the Option's default value
+ /// @param assign_to pointer to a variable to assign the parsed command line value to
+ Value(const std::string& short_name, const std::string& long_name, const std::string& description, const T& default_val, T* assign_to = nullptr);
+
+ size_t count() const override;
+ bool is_set() const override;
+
+ /// Assign the last parsed command line value to "var"
+ /// @param var pointer to the variable where is value is written to
+ void assign_to(T* var);
+
+ /// Manually set the Option's value. Deletes current value(s)
+ /// @param value the new value of the option
+ void set_value(const T& value);
+
+ /// Get the Option's value. Will throw if option at index idx is not available
+ /// @param idx the zero based index of the value (if set multiple times)
+ /// @return the Option's value at index "idx"
+ T value(size_t idx = 0) const;
+
+ /// Set the Option's default value
+ /// @param value the default value if not specified on command line
+ void set_default(const T& value);
+
+ /// Check if the Option has a default value
+ /// @return true if the Option has a default value
+ bool has_default() const;
+
+ /// Get the Option's default value. Will throw if no default is set.
+ /// @return the Option's default value
+ T get_default() const;
+ bool get_default(std::ostream& out) const override;
+
+ Argument argument_type() const override;
+
+protected:
+ void parse(OptionName what_name, const char* value) override;
+ std::unique_ptr default_;
+
+ virtual void update_reference();
+ virtual void add_value(const T& value);
+ void clear() override;
+
+ T* assign_to_;
+ std::vector values_;
+};
+
+
+
+
+/// Value option with implicit default value
+/**
+ * Value option with implicit default value
+ * If set, an argument is optional
+ * -without argument it carries the implicit default value
+ * -with argument it carries the explicit value
+ */
+template
+class Implicit : public Value
+{
+public:
+ Implicit(const std::string& short_name, const std::string& long_name, const std::string& description, const T& implicit_val, T* assign_to = nullptr);
+
+ Argument argument_type() const override;
+
+protected:
+ void parse(OptionName what_name, const char* value) override;
+};
+
+
+
+
+/// Value option without value
+/**
+ * Value option without value
+ * Does not require an argument
+ * Can be either set or not set
+ */
+class Switch : public Value
+{
+public:
+ Switch(const std::string& short_name, const std::string& long_name, const std::string& description, bool* assign_to = nullptr);
+
+ void set_default(const bool& value) = delete;
+ Argument argument_type() const override;
+
+protected:
+ void parse(OptionName what_name, const char* value) override;
+};
+
+
+
+
+using Option_ptr = std::shared_ptr