├── .github └── workflows │ ├── presubmit.yml │ └── release.yml ├── .gitignore ├── CMakeLists.txt ├── CODE_OF_CONDUCT.md ├── LICENSE ├── OpenCL.pc.in ├── README.md ├── cmake ├── DebSourcePkg.cmake ├── JoinPaths.cmake ├── Package.cmake └── PackageSetup.cmake ├── inc └── README.txt ├── include └── cl_khr_icd2.h ├── loader ├── cllayerinfo.c ├── icd.c ├── icd.h ├── icd_cmake_config.h.in ├── icd_dispatch.c ├── icd_dispatch.h ├── icd_dispatch_generated.c ├── icd_envvars.h ├── icd_platform.h ├── icd_version.h ├── linux │ ├── icd_exports.map │ ├── icd_linux.c │ └── icd_linux_envvars.c └── windows │ ├── OpenCL-mingw-i686.def │ ├── OpenCL.def │ ├── OpenCL.rc │ ├── adapter.h │ ├── icd_windows.c │ ├── icd_windows.h │ ├── icd_windows_apppackage.c │ ├── icd_windows_apppackage.h │ ├── icd_windows_dxgk.c │ ├── icd_windows_dxgk.h │ ├── icd_windows_envvars.c │ ├── icd_windows_hkr.c │ └── icd_windows_hkr.h ├── scripts ├── .gitignore ├── README.md ├── gen │ └── __init__.py ├── gen_loader.py ├── gen_print_layer.py ├── icd_dispatch_generated.c.mako └── icd_print_layer_generated.c.mako └── test ├── CMakeLists.txt ├── driver_stub ├── CMakeLists.txt ├── cl.c ├── cl_ext.c ├── cl_gl.c ├── driver_stub.def ├── icd.c ├── icd_driver_exports.map ├── icd_structs.h └── rename_api.h ├── inc └── platform │ └── icd_test_log.h ├── layer ├── CMakeLists.txt ├── icd_print_layer.c ├── icd_print_layer.def ├── icd_print_layer.h ├── icd_print_layer.map └── icd_print_layer_generated.c ├── loader_test ├── CMakeLists.txt ├── callbacks.c ├── icd_test_match.c ├── main.c ├── param_struct.h ├── test_buffer_object.c ├── test_cl_runtime.c ├── test_clgl.c ├── test_create_calls.c ├── test_image_objects.c ├── test_kernel.c ├── test_platforms.c ├── test_program_objects.c └── test_sampler_objects.c ├── log ├── CMakeLists.txt └── icd_test_log.c └── pkgconfig ├── bare └── CMakeLists.txt ├── pkgconfig.c ├── pkgconfig └── CMakeLists.txt └── sdk └── CMakeLists.txt /.github/workflows/release.yml: -------------------------------------------------------------------------------- 1 | name: Release 2 | 3 | on: 4 | push: 5 | tags: 6 | - "v*" 7 | env: 8 | distroseries: jammy 9 | 10 | jobs: 11 | release: 12 | if: false 13 | runs-on: ubuntu-latest 14 | defaults: 15 | run: 16 | shell: bash 17 | steps: 18 | - name: Add PPA 19 | run: sudo add-apt-repository -y ppa:${{ vars.PPA }} 20 | 21 | - name: Install prerequisites 22 | run: sudo apt-get update -qq && sudo apt-get install -y cmake devscripts debhelper-compat=13 opencl-c-headers 23 | 24 | - name: Import GPG signing key 25 | run: echo "${{ secrets.DEB_SIGNING_KEY }}" | gpg --import 26 | 27 | - name: Download and extract source code 28 | run: | 29 | wget -O $GITHUB_WORKSPACE/source.orig.tar.gz https://github.com/$GITHUB_REPOSITORY/archive/refs/tags/$GITHUB_REF_NAME.tar.gz 30 | tar -xvf $GITHUB_WORKSPACE/source.orig.tar.gz 31 | 32 | - name: Configure project out-of-tree 33 | run: cmake 34 | -S $GITHUB_WORKSPACE/OpenCL-ICD-Loader* 35 | -B $GITHUB_WORKSPACE/../build 36 | -D CMAKE_BUILD_TYPE=Release 37 | -D CMAKE_INSTALL_PREFIX=/usr 38 | -D BUILD_TESTING=OFF 39 | -D LATEST_RELEASE_VERSION=$GITHUB_REF_NAME 40 | -D CPACK_DEBIAN_PACKAGE_MAINTAINER="${{ vars.DEB_MAINTAINER }}" 41 | -D DEBIAN_VERSION_SUFFIX=${{ vars.DEB_VERSION_SUFFIX }} 42 | 43 | - name: Generate packaging scripts 44 | run: cmake 45 | -D CMAKE_CACHE_PATH=$GITHUB_WORKSPACE/../build/CMakeCache.txt 46 | -D ORIG_ARCHIVE=$GITHUB_WORKSPACE/source.orig.tar.gz 47 | -D LATEST_RELEASE_VERSION=$GITHUB_REF_NAME 48 | -D DEBIAN_DISTROSERIES=${{ env.distroseries }} 49 | -D DEBIAN_PACKAGE_MAINTAINER="${{ vars.DEB_MAINTAINER }}" 50 | -D DEBIAN_VERSION_SUFFIX=${{ vars.DEB_VERSION_SUFFIX }} 51 | -P $GITHUB_WORKSPACE/OpenCL-ICD-Loader*/cmake/DebSourcePkg.cmake 52 | 53 | - name: Build source package 54 | run: | 55 | cd $GITHUB_WORKSPACE/OpenCL-ICD-Loader*/ 56 | debuild -S -sa 57 | 58 | - name: Build binary package 59 | run: cpack 60 | -G DEB 61 | -C Release 62 | -B $GITHUB_WORKSPACE/../build 63 | --config $GITHUB_WORKSPACE/../build/CPackConfig.cmake 64 | 65 | # The following step does not depend on the previous step "Build binary package", 66 | # but if the binary package build is unsuccessful, it is better not to push the 67 | # source packages to the PPA 68 | - name: Push source package to the PPA 69 | run: dput ppa:${{ vars.PPA }} $GITHUB_WORKSPACE/*source.changes 70 | 71 | - name: Create GitHub release 72 | uses: softprops/action-gh-release@v1 73 | with: 74 | files: ${{ github.workspace }}/../build/*.deb 75 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | # Build dir 2 | [Bb]uild/ 3 | 4 | # Install dir 5 | [Ii]nstall/ 6 | 7 | # External dir 8 | [Ee]xternal/ 9 | 10 | # Package dir 11 | [Pp]ackage[-_\s\d]*/ 12 | 13 | # Tackage dir 14 | [T]esting/ 15 | 16 | # inc subdirs 17 | inc/CL/ 18 | inc/EGL/ 19 | inc/KHR/ 20 | 21 | # Visual Studio Code 22 | .vscode 23 | -------------------------------------------------------------------------------- /CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required (VERSION 3.16) 2 | 3 | # Include guard for including this project multiple times 4 | if(TARGET OpenCL) 5 | return() 6 | endif() 7 | 8 | project (OpenCL-ICD-Loader 9 | VERSION 3.0 10 | LANGUAGES C) 11 | 12 | find_package (Threads REQUIRED) 13 | 14 | set(CMAKE_C_STANDARD 99) 15 | set(CMAKE_C_STANDARD_REQUIRED ON) 16 | # The option below allows building the ICD Loader library as a shared library 17 | # (ON, default) or a static library (OFF). 18 | # 19 | # Khronos OpenCL Working Group strongly recommends building and using the ICD 20 | # loader as a shared library due to the following benefits: 21 | # 22 | # 1. The shared library can be updated independent of the application. This 23 | # allows releasing new fixes and features in the ICD loader without updating 24 | # the application. 25 | # 26 | # In rare cases when there are backward-incompatible changes to the ICD 27 | # loader (due to platform requirements, for instance), using a shared 28 | # library allows updating the library to make the transition seamless to 29 | # installed applications. 30 | # 31 | # 2. On platforms that require the ICD mechanism there are multiple vendors 32 | # shipping their OpenCL implementations. The vendor installers collaborate 33 | # to make sure that the installed ICD shared library version is suitable for 34 | # working with all vendor implementations installed on the system. 35 | # 36 | # If applications statically link to ICD Loader then that version of the ICD 37 | # loader may not work with one or more installed vendor implementations. 38 | # 39 | # Using the OpenCL ICD loader as a static library is NOT recommended for 40 | # end-user installations in general. However in some controlled environments it 41 | # may be useful to simplify the build and distribution of the application. E.g. 42 | # in test farms, or in cases where the end-user system configs are known in 43 | # advance. Use it with discretion. 44 | if(DEFINED BUILD_SHARED_LIBS) 45 | set(OPENCL_ICD_LOADER_BUILD_SHARED_LIBS_DEFAULT ${BUILD_SHARED_LIBS}) 46 | else() 47 | set(OPENCL_ICD_LOADER_BUILD_SHARED_LIBS_DEFAULT ON) 48 | endif() 49 | option(OPENCL_ICD_LOADER_BUILD_SHARED_LIBS "Build OpenCL ICD Loader as shared library" ${OPENCL_ICD_LOADER_BUILD_SHARED_LIBS_DEFAULT}) 50 | 51 | # This option enables/disables support for OpenCL layers in the ICD loader. 52 | # It is currently needed default while the specification is being formalized, 53 | # and to study the performance impact. 54 | option (ENABLE_OPENCL_LAYERS "Enable OpenCL Layers" ON) 55 | option (ENABLE_OPENCL_LOADER_MANAGED_DISPATCH "Enable OpenCL Loader managed dispatch" ON) 56 | include(CMakeDependentOption) 57 | cmake_dependent_option(ENABLE_OPENCL_LAYERINFO "Enable building cllayerinfo tool" ON ENABLE_OPENCL_LAYERS OFF) 58 | 59 | include(GNUInstallDirs) 60 | 61 | set (CMAKE_MODULE_PATH ${CMAKE_MODULE_PATH} "${CMAKE_CURRENT_SOURCE_DIR}/cmake") 62 | include(CheckFunctionExists) 63 | include(JoinPaths) 64 | include(Package) 65 | 66 | check_function_exists(secure_getenv HAVE_SECURE_GETENV) 67 | check_function_exists(__secure_getenv HAVE___SECURE_GETENV) 68 | configure_file(${CMAKE_CURRENT_SOURCE_DIR}/loader/icd_cmake_config.h.in 69 | ${CMAKE_CURRENT_BINARY_DIR}/icd_cmake_config.h) 70 | 71 | set (OPENCL_ICD_LOADER_SOURCES 72 | include/cl_khr_icd2.h 73 | loader/icd.c 74 | loader/icd.h 75 | loader/icd_version.h 76 | loader/icd_dispatch.c 77 | loader/icd_dispatch.h 78 | loader/icd_dispatch_generated.c 79 | loader/icd_envvars.h 80 | loader/icd_platform.h) 81 | include_directories (include) 82 | 83 | if (WIN32) 84 | list (APPEND OPENCL_ICD_LOADER_SOURCES 85 | loader/windows/adapter.h 86 | loader/windows/icd_windows.c 87 | loader/windows/icd_windows.h 88 | loader/windows/icd_windows_dxgk.c 89 | loader/windows/icd_windows_dxgk.h 90 | loader/windows/icd_windows_envvars.c 91 | loader/windows/icd_windows_hkr.c 92 | loader/windows/icd_windows_hkr.h 93 | loader/windows/icd_windows_apppackage.c 94 | loader/windows/icd_windows_apppackage.h 95 | loader/windows/OpenCL.rc) 96 | # Only add the DXSDK include directory if the environment variable is 97 | # defined. Since the DXSDK has merged into the Windows SDK, this is 98 | # only required in rare cases. 99 | if (DEFINED ENV{DXSDK_DIR} AND NOT (MINGW OR MSYS OR CYGWIN)) 100 | include_directories ($ENV{DXSDK_DIR}/Include) 101 | endif () 102 | 103 | # For mingw-i686 builds only we need a special .def file with stdcall 104 | # exports. In all other cases we can use a standard .def file. 105 | if ((CMAKE_SIZEOF_VOID_P EQUAL 4) AND (MINGW OR MSYS OR CYGWIN)) 106 | list (APPEND OPENCL_ICD_LOADER_SOURCES loader/windows/OpenCL-mingw-i686.def) 107 | else () 108 | list (APPEND OPENCL_ICD_LOADER_SOURCES loader/windows/OpenCL.def) 109 | endif () 110 | else () 111 | list (APPEND OPENCL_ICD_LOADER_SOURCES 112 | loader/linux/icd_linux.c 113 | loader/linux/icd_linux_envvars.c 114 | loader/linux/icd_exports.map) 115 | endif () 116 | 117 | set (OPENCL_ICD_LOADER_HEADERS_DIR "${CMAKE_CURRENT_SOURCE_DIR}/inc" CACHE PATH "Path to OpenCL Headers") 118 | 119 | if (${OPENCL_ICD_LOADER_BUILD_SHARED_LIBS}) 120 | add_library (OpenCL SHARED ${OPENCL_ICD_LOADER_SOURCES}) 121 | else() 122 | add_library (OpenCL STATIC ${OPENCL_ICD_LOADER_SOURCES}) 123 | endif() 124 | 125 | add_library (OpenCL::OpenCL ALIAS OpenCL) 126 | 127 | set_target_properties (OpenCL PROPERTIES VERSION 1\.0\.0 SOVERSION "1") 128 | 129 | if (WIN32) 130 | target_link_libraries (OpenCL PRIVATE cfgmgr32.lib runtimeobject.lib) 131 | 132 | # Generate a DLL without a "lib" prefix for mingw. 133 | if (MINGW OR MSYS OR CYGWIN) 134 | set_target_properties(OpenCL PROPERTIES PREFIX "") 135 | set_target_properties(OpenCL PROPERTIES LINK_FLAGS "-Wl,-disable-stdcall-fixup") 136 | endif() 137 | else() 138 | target_link_libraries (OpenCL PRIVATE ${CMAKE_THREAD_LIBS_INIT}) 139 | if (NOT APPLE) 140 | set_target_properties (OpenCL PROPERTIES LINK_FLAGS "-Wl,--version-script -Wl,${CMAKE_CURRENT_SOURCE_DIR}/loader/linux/icd_exports.map") 141 | if (OPENCL_ICD_LOADER_PIC) 142 | set_target_properties(OpenCL PROPERTIES POSITION_INDEPENDENT_CODE ON) 143 | endif () 144 | endif () 145 | endif () 146 | 147 | if (EXISTS ${OPENCL_ICD_LOADER_HEADERS_DIR}/CL/cl.h) 148 | message (STATUS "Defining OpenCL::Headers through OPENCL_ICD_LOADER_HEADERS_DIR") 149 | add_library (OpenCLHeaders INTERFACE) 150 | add_library (OpenCL::Headers ALIAS OpenCLHeaders) 151 | target_include_directories (OpenCLHeaders INTERFACE ${OPENCL_ICD_LOADER_HEADERS_DIR}) 152 | target_include_directories (OpenCL PUBLIC $) 153 | else () 154 | if (NOT TARGET OpenCL::Headers) 155 | find_package (OpenCLHeaders REQUIRED) 156 | endif () 157 | target_link_libraries (OpenCL PUBLIC OpenCL::Headers) 158 | endif () 159 | 160 | set (OPENCL_COMPILE_DEFINITIONS 161 | CL_TARGET_OPENCL_VERSION=300 162 | CL_NO_NON_ICD_DISPATCH_EXTENSION_PROTOTYPES 163 | OPENCL_ICD_LOADER_VERSION_MAJOR=3 164 | OPENCL_ICD_LOADER_VERSION_MINOR=0 165 | OPENCL_ICD_LOADER_VERSION_REV=7 166 | $<$:CL_ENABLE_LAYERS> 167 | $<$:CL_ENABLE_LOADER_MANAGED_DISPATCH> 168 | ) 169 | 170 | target_compile_definitions (OpenCL 171 | PRIVATE 172 | ${OPENCL_COMPILE_DEFINITIONS} 173 | ) 174 | 175 | target_include_directories (OpenCL 176 | PRIVATE 177 | ${CMAKE_CURRENT_BINARY_DIR} 178 | loader 179 | ) 180 | target_link_libraries (OpenCL PUBLIC ${CMAKE_DL_LIBS}) 181 | 182 | if (ENABLE_OPENCL_LAYERINFO) 183 | 184 | set (OPENCL_LAYER_INFO_SOURCES 185 | loader/cllayerinfo.c 186 | ${OPENCL_ICD_LOADER_SOURCES} 187 | ) 188 | 189 | add_executable(cllayerinfo ${OPENCL_LAYER_INFO_SOURCES}) 190 | 191 | add_executable(OpenCL::cllayerinfo ALIAS cllayerinfo) 192 | 193 | target_compile_definitions (cllayerinfo 194 | PRIVATE 195 | CL_LAYER_INFO 196 | ${OPENCL_COMPILE_DEFINITIONS} 197 | ) 198 | 199 | if (EXISTS ${OPENCL_ICD_LOADER_HEADERS_DIR}/CL/cl.h) 200 | target_include_directories (cllayerinfo PUBLIC $) 201 | else () 202 | target_link_libraries (cllayerinfo PUBLIC OpenCL::Headers) 203 | endif () 204 | 205 | if (WIN32) 206 | target_link_libraries (cllayerinfo PRIVATE cfgmgr32.lib runtimeobject.lib) 207 | else () 208 | target_link_libraries (cllayerinfo PRIVATE ${CMAKE_THREAD_LIBS_INIT}) 209 | endif () 210 | 211 | target_link_libraries (cllayerinfo PUBLIC ${CMAKE_DL_LIBS}) 212 | 213 | target_include_directories (cllayerinfo 214 | PRIVATE 215 | ${CMAKE_CURRENT_BINARY_DIR} 216 | loader 217 | ) 218 | endif () 219 | 220 | option (OPENCL_ICD_LOADER_BUILD_TESTING "Enable support for OpenCL ICD Loader testing." OFF) 221 | 222 | if(CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_ICD_LOADER_BUILD_TESTING) 223 | include(CTest) 224 | endif() 225 | if((CMAKE_PROJECT_NAME STREQUAL PROJECT_NAME OR OPENCL_ICD_LOADER_BUILD_TESTING) AND BUILD_TESTING) 226 | add_subdirectory (test) 227 | endif() 228 | 229 | install( 230 | TARGETS OpenCL 231 | EXPORT OpenCLICDLoaderTargets 232 | LIBRARY 233 | DESTINATION ${CMAKE_INSTALL_LIBDIR} # obtained from GNUInstallDirs 234 | ) 235 | install( 236 | # FILES $ is cleanest, but is MSVC link.exe specific. LLVM's lld.exe and lld-link.exe don't support it (configure-time error) 237 | # FILES $/OpenCL.pdb looks OK, but even though there's a PDB, this prop is empty on non-MSVC toolchains 238 | FILES $/OpenCL.pdb # is the most implicit (expect PDB be next to the library), yet the only one that universally works 239 | DESTINATION ${CMAKE_INSTALL_BINDIR} 240 | OPTIONAL 241 | ) 242 | 243 | if (ENABLE_OPENCL_LAYERINFO) 244 | install( 245 | TARGETS cllayerinfo 246 | RUNTIME 247 | DESTINATION ${CMAKE_INSTALL_BINDIR} 248 | COMPONENT cllayerinfo 249 | ) 250 | endif() 251 | 252 | export( 253 | EXPORT OpenCLICDLoaderTargets 254 | FILE ${PROJECT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderTargets.cmake 255 | NAMESPACE OpenCL:: 256 | ) 257 | file( 258 | WRITE ${PROJECT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderConfig.cmake 259 | "include(\"\${CMAKE_CURRENT_LIST_DIR}/OpenCLICDLoaderTargets.cmake\")" 260 | ) 261 | 262 | set(config_package_location ${CMAKE_INSTALL_DATADIR}/cmake/OpenCLICDLoader) 263 | install( 264 | EXPORT OpenCLICDLoaderTargets 265 | FILE OpenCLICDLoaderTargets.cmake 266 | NAMESPACE OpenCL:: 267 | DESTINATION ${config_package_location} 268 | COMPONENT dev 269 | ) 270 | install( 271 | FILES ${CMAKE_CURRENT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderConfig.cmake 272 | DESTINATION ${config_package_location} 273 | COMPONENT dev 274 | ) 275 | 276 | unset(CMAKE_SIZEOF_VOID_P) 277 | include(CMakePackageConfigHelpers) 278 | write_basic_package_version_file( 279 | ${CMAKE_CURRENT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderConfigVersion.cmake 280 | VERSION ${PROJECT_VERSION} 281 | COMPATIBILITY AnyNewerVersion 282 | ) 283 | install( 284 | FILES ${CMAKE_CURRENT_BINARY_DIR}/OpenCLICDLoader/OpenCLICDLoaderConfigVersion.cmake 285 | DESTINATION ${config_package_location} 286 | COMPONENT dev 287 | ) 288 | 289 | # Separate namelink from shared library and symlink for DEB packaging 290 | install (TARGETS OpenCL 291 | LIBRARY 292 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 293 | COMPONENT runtime 294 | NAMELINK_SKIP) 295 | 296 | install (TARGETS OpenCL 297 | LIBRARY 298 | DESTINATION ${CMAKE_INSTALL_LIBDIR} 299 | COMPONENT dev 300 | NAMELINK_ONLY) 301 | -------------------------------------------------------------------------------- /CODE_OF_CONDUCT.md: -------------------------------------------------------------------------------- 1 | A reminder that this issue tracker is managed by the Khronos Group. Interactions here should follow the Khronos Code of Conduct (https://www.khronos.org/developers/code-of-conduct), which prohibits aggressive or derogatory language. Please keep the discussion friendly and civil. 2 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | Apache License 2 | Version 2.0, January 2004 3 | http://www.apache.org/licenses/ 4 | 5 | TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION 6 | 7 | 1. Definitions. 8 | 9 | "License" shall mean the terms and conditions for use, reproduction, 10 | and distribution as defined by Sections 1 through 9 of this document. 11 | 12 | "Licensor" shall mean the copyright owner or entity authorized by 13 | the copyright owner that is granting the License. 14 | 15 | "Legal Entity" shall mean the union of the acting entity and all 16 | other entities that control, are controlled by, or are under common 17 | control with that entity. For the purposes of this definition, 18 | "control" means (i) the power, direct or indirect, to cause the 19 | direction or management of such entity, whether by contract or 20 | otherwise, or (ii) ownership of fifty percent (50%) or more of the 21 | outstanding shares, or (iii) beneficial ownership of such entity. 22 | 23 | "You" (or "Your") shall mean an individual or Legal Entity 24 | exercising permissions granted by this License. 25 | 26 | "Source" form shall mean the preferred form for making modifications, 27 | including but not limited to software source code, documentation 28 | source, and configuration files. 29 | 30 | "Object" form shall mean any form resulting from mechanical 31 | transformation or translation of a Source form, including but 32 | not limited to compiled object code, generated documentation, 33 | and conversions to other media types. 34 | 35 | "Work" shall mean the work of authorship, whether in Source or 36 | Object form, made available under the License, as indicated by a 37 | copyright notice that is included in or attached to the work 38 | (an example is provided in the Appendix below). 39 | 40 | "Derivative Works" shall mean any work, whether in Source or Object 41 | form, that is based on (or derived from) the Work and for which the 42 | editorial revisions, annotations, elaborations, or other modifications 43 | represent, as a whole, an original work of authorship. For the purposes 44 | of this License, Derivative Works shall not include works that remain 45 | separable from, or merely link (or bind by name) to the interfaces of, 46 | the Work and Derivative Works thereof. 47 | 48 | "Contribution" shall mean any work of authorship, including 49 | the original version of the Work and any modifications or additions 50 | to that Work or Derivative Works thereof, that is intentionally 51 | submitted to Licensor for inclusion in the Work by the copyright owner 52 | or by an individual or Legal Entity authorized to submit on behalf of 53 | the copyright owner. For the purposes of this definition, "submitted" 54 | means any form of electronic, verbal, or written communication sent 55 | to the Licensor or its representatives, including but not limited to 56 | communication on electronic mailing lists, source code control systems, 57 | and issue tracking systems that are managed by, or on behalf of, the 58 | Licensor for the purpose of discussing and improving the Work, but 59 | excluding communication that is conspicuously marked or otherwise 60 | designated in writing by the copyright owner as "Not a Contribution." 61 | 62 | "Contributor" shall mean Licensor and any individual or Legal Entity 63 | on behalf of whom a Contribution has been received by Licensor and 64 | subsequently incorporated within the Work. 65 | 66 | 2. Grant of Copyright License. Subject to the terms and conditions of 67 | this License, each Contributor hereby grants to You a perpetual, 68 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 69 | copyright license to reproduce, prepare Derivative Works of, 70 | publicly display, publicly perform, sublicense, and distribute the 71 | Work and such Derivative Works in Source or Object form. 72 | 73 | 3. Grant of Patent License. Subject to the terms and conditions of 74 | this License, each Contributor hereby grants to You a perpetual, 75 | worldwide, non-exclusive, no-charge, royalty-free, irrevocable 76 | (except as stated in this section) patent license to make, have made, 77 | use, offer to sell, sell, import, and otherwise transfer the Work, 78 | where such license applies only to those patent claims licensable 79 | by such Contributor that are necessarily infringed by their 80 | Contribution(s) alone or by combination of their Contribution(s) 81 | with the Work to which such Contribution(s) was submitted. If You 82 | institute patent litigation against any entity (including a 83 | cross-claim or counterclaim in a lawsuit) alleging that the Work 84 | or a Contribution incorporated within the Work constitutes direct 85 | or contributory patent infringement, then any patent licenses 86 | granted to You under this License for that Work shall terminate 87 | as of the date such litigation is filed. 88 | 89 | 4. Redistribution. You may reproduce and distribute copies of the 90 | Work or Derivative Works thereof in any medium, with or without 91 | modifications, and in Source or Object form, provided that You 92 | meet the following conditions: 93 | 94 | (a) You must give any other recipients of the Work or 95 | Derivative Works a copy of this License; and 96 | 97 | (b) You must cause any modified files to carry prominent notices 98 | stating that You changed the files; and 99 | 100 | (c) You must retain, in the Source form of any Derivative Works 101 | that You distribute, all copyright, patent, trademark, and 102 | attribution notices from the Source form of the Work, 103 | excluding those notices that do not pertain to any part of 104 | the Derivative Works; and 105 | 106 | (d) If the Work includes a "NOTICE" text file as part of its 107 | distribution, then any Derivative Works that You distribute must 108 | include a readable copy of the attribution notices contained 109 | within such NOTICE file, excluding those notices that do not 110 | pertain to any part of the Derivative Works, in at least one 111 | of the following places: within a NOTICE text file distributed 112 | as part of the Derivative Works; within the Source form or 113 | documentation, if provided along with the Derivative Works; or, 114 | within a display generated by the Derivative Works, if and 115 | wherever such third-party notices normally appear. The contents 116 | of the NOTICE file are for informational purposes only and 117 | do not modify the License. You may add Your own attribution 118 | notices within Derivative Works that You distribute, alongside 119 | or as an addendum to the NOTICE text from the Work, provided 120 | that such additional attribution notices cannot be construed 121 | as modifying the License. 122 | 123 | You may add Your own copyright statement to Your modifications and 124 | may provide additional or different license terms and conditions 125 | for use, reproduction, or distribution of Your modifications, or 126 | for any such Derivative Works as a whole, provided Your use, 127 | reproduction, and distribution of the Work otherwise complies with 128 | the conditions stated in this License. 129 | 130 | 5. Submission of Contributions. Unless You explicitly state otherwise, 131 | any Contribution intentionally submitted for inclusion in the Work 132 | by You to the Licensor shall be under the terms and conditions of 133 | this License, without any additional terms or conditions. 134 | Notwithstanding the above, nothing herein shall supersede or modify 135 | the terms of any separate license agreement you may have executed 136 | with Licensor regarding such Contributions. 137 | 138 | 6. Trademarks. This License does not grant permission to use the trade 139 | names, trademarks, service marks, or product names of the Licensor, 140 | except as required for reasonable and customary use in describing the 141 | origin of the Work and reproducing the content of the NOTICE file. 142 | 143 | 7. Disclaimer of Warranty. Unless required by applicable law or 144 | agreed to in writing, Licensor provides the Work (and each 145 | Contributor provides its Contributions) on an "AS IS" BASIS, 146 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or 147 | implied, including, without limitation, any warranties or conditions 148 | of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A 149 | PARTICULAR PURPOSE. You are solely responsible for determining the 150 | appropriateness of using or redistributing the Work and assume any 151 | risks associated with Your exercise of permissions under this License. 152 | 153 | 8. Limitation of Liability. In no event and under no legal theory, 154 | whether in tort (including negligence), contract, or otherwise, 155 | unless required by applicable law (such as deliberate and grossly 156 | negligent acts) or agreed to in writing, shall any Contributor be 157 | liable to You for damages, including any direct, indirect, special, 158 | incidental, or consequential damages of any character arising as a 159 | result of this License or out of the use or inability to use the 160 | Work (including but not limited to damages for loss of goodwill, 161 | work stoppage, computer failure or malfunction, or any and all 162 | other commercial damages or losses), even if such Contributor 163 | has been advised of the possibility of such damages. 164 | 165 | 9. Accepting Warranty or Additional Liability. While redistributing 166 | the Work or Derivative Works thereof, You may choose to offer, 167 | and charge a fee for, acceptance of support, warranty, indemnity, 168 | or other liability obligations and/or rights consistent with this 169 | License. However, in accepting such obligations, You may act only 170 | on Your own behalf and on Your sole responsibility, not on behalf 171 | of any other Contributor, and only if You agree to indemnify, 172 | defend, and hold each Contributor harmless for any liability 173 | incurred by, or claims asserted against, such Contributor by reason 174 | of your accepting any such warranty or additional liability. 175 | 176 | END OF TERMS AND CONDITIONS 177 | 178 | APPENDIX: How to apply the Apache License to your work. 179 | 180 | To apply the Apache License to your work, attach the following 181 | boilerplate notice, with the fields enclosed by brackets "[]" 182 | replaced with your own identifying information. (Don't include 183 | the brackets!) The text should be enclosed in the appropriate 184 | comment syntax for the file format. We also recommend that a 185 | file or class name and description of purpose be included on the 186 | same "printed page" as the copyright notice for easier 187 | identification within third-party archives. 188 | 189 | Copyright [yyyy] [name of copyright owner] 190 | 191 | Licensed under the Apache License, Version 2.0 (the "License"); 192 | you may not use this file except in compliance with the License. 193 | You may obtain a copy of the License at 194 | 195 | http://www.apache.org/licenses/LICENSE-2.0 196 | 197 | Unless required by applicable law or agreed to in writing, software 198 | distributed under the License is distributed on an "AS IS" BASIS, 199 | WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 200 | See the License for the specific language governing permissions and 201 | limitations under the License. 202 | -------------------------------------------------------------------------------- /OpenCL.pc.in: -------------------------------------------------------------------------------- 1 | prefix=@PKGCONFIG_PREFIX@ 2 | exec_prefix=${prefix} 3 | libdir=@OPENCL_LIBDIR_PC@ 4 | 5 | Name: OpenCL 6 | Description: Khronos OpenCL ICD Loader 7 | Requires: OpenCL-Headers 8 | Version: 3.0 9 | Libs: -L${libdir} -lOpenCL 10 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # OpenCLTM ICD Loader 2 | 3 | This repo contains the source code and tests for the Khronos official OpenCL ICD Loader. 4 | 5 | ## CI Build Status 6 | 7 | [![Windows Build Status](https://github.com/KhronosGroup/OpenCL-ICD-Loader/workflows/Windows/badge.svg)](https://github.com/KhronosGroup/OpenCL-ICD-Loader/actions?query=workflow%3AWindows) 8 | [![Linux Build Status](https://github.com/KhronosGroup/OpenCL-ICD-Loader/workflows/Linux/badge.svg)](https://github.com/KhronosGroup/OpenCL-ICD-Loader/actions?query=workflow%3ALinux) 9 | [![MacOS Build Status](https://github.com/KhronosGroup/OpenCL-ICD-Loader/workflows/MacOS/badge.svg)](https://github.com/KhronosGroup/OpenCL-ICD-Loader/actions?query=workflow%3AMacOS) 10 | 11 | ## Introduction 12 | 13 | OpenCL defines an *Installable Client Driver* (ICD) mechanism to allow developers to build applications against an *Installable Client Driver* loader (ICD loader) rather than linking their applications against a specific OpenCL implementation. 14 | The ICD Loader is responsible for: 15 | 16 | * Exporting OpenCL API entry points 17 | * Enumerating OpenCL implementations 18 | * Forwarding OpenCL API calls to the correct implementation 19 | 20 | This repo contains the source code and tests for the Khronos official OpenCL ICD Loader. 21 | 22 | Note that this repo does not contain an OpenCL implementation (ICD). 23 | You will need to obtain and install an OpenCL implementation for your OpenCL device that supports the OpenCL ICD extension `cl_khr_icd` to run an application using the OpenCL ICD Loader. 24 | 25 | The OpenCL *Installable Client Driver* extension (`cl_khr_icd`) is described in the OpenCL extensions specification, which may be found on the [Khronos OpenCL Registry](https://www.khronos.org/registry/OpenCL/). 26 | 27 | ## Build Instructions 28 | 29 | > While the ICD Loader can be built and installed in isolation, it is part of the [OpenCL SDK](https://github.com/KhronosGroup/OpenCL-SDK). If looking for streamlined build experience and a complete development package, refer to the SDK build instructions instead of the following guide. 30 | 31 | ### Dependencies 32 | 33 | The OpenCL ICD Loader requires: 34 | - the [OpenCL Headers](https://github.com/KhronosGroup/OpenCL-Headers/). 35 | - It is recommended to install the headers via CMake, however a convenience shorthand is provided. Providing `OPENCL_ICD_LOADER_HEADERS_DIR` to CMake, one may specify the location of OpenCL Headers. By default, the OpenCL ICD Loader will look for OpenCL Headers in the inc directory. 36 | - The OpenCL ICD Loader uses CMake for its build system. 37 | If CMake is not provided by your build system or OS package manager, please consult the [CMake website](https://cmake.org). 38 | 39 | ### Example Build 40 | 41 | For most Windows and Linux usages, the following steps are sufficient to build the OpenCL ICD Loader: 42 | 43 | 1. Clone this repo and the OpenCL Headers: 44 | 45 | git clone https://github.com/KhronosGroup/OpenCL-ICD-Loader 46 | git clone https://github.com/KhronosGroup/OpenCL-Headers 47 | 48 | 1. Install OpenCL Headers CMake package 49 | 50 | cmake -D CMAKE_INSTALL_PREFIX=./OpenCL-Headers/install -S ./OpenCL-Headers -B ./OpenCL-Headers/build 51 | cmake --build ./OpenCL-Headers/build --target install 52 | 53 | 1. Build and install OpenCL ICD Loader CMake package. _(Note that `CMAKE_PREFIX_PATH` need to be an absolute path. Update as needed.)_ 54 | 55 | cmake -D CMAKE_PREFIX_PATH=/absolute/path/to/OpenCL-Headers/install -D CMAKE_INSTALL_PREFIX=./OpenCL-ICD-Loader/install -S ./OpenCL-ICD-Loader -B ./OpenCL-ICD-Loader/build 56 | cmake --build ./OpenCL-ICD-Loader/build --target install 57 | 58 | Notes: 59 | 60 | * For x64 Windows builds, you need to instruct the default Visual Studio generator by adding `-A x64` to all your command-lines. 61 | 62 | * Some users may prefer to use a CMake GUI frontend, such as `cmake-gui` or `ccmake`, vs. the command-line CMake. 63 | 64 | ### Example Use 65 | 66 | Example CMake invocation 67 | 68 | ```bash 69 | cmake -D CMAKE_PREFIX_PATH="/chosen/install/prefix/of/headers;/chosen/install/prefix/of/loader" /path/to/opencl/app 70 | ``` 71 | 72 | and sample `CMakeLists.txt` 73 | 74 | ```cmake 75 | cmake_minimum_required(VERSION 3.0) 76 | cmake_policy(VERSION 3.0...3.18.4) 77 | project(proj) 78 | add_executable(app main.cpp) 79 | find_package(OpenCLHeaders REQUIRED) 80 | find_package(OpenCLICDLoader REQUIRED) 81 | target_link_libraries(app PRIVATE OpenCL::Headers OpenCL::OpenCL) 82 | ``` 83 | 84 | ## OpenCL ICD Loader Tests 85 | 86 | OpenCL ICD Loader Tests can be run using `ctest` from the `build` directory. CTest which is a companion to CMake. The OpenCL ICD Loader Tests can also be run directly by executing `icd_loader_test[.exe]` executable from the bin folder. 87 | 88 | _(Note that running the tests manually requires setting up it's env manually, by setting `OCL_ICD_FILENAMES` to the full path of `libOpenCLDriverStub.so`/`OpenCLDriverStub.dll`, something otherwise done by CTest.)_ 89 | 90 | ## Registering ICDs 91 | 92 | The method to installing an ICD is operating system dependent. 93 | 94 | ### Registering an ICD on Linux 95 | 96 | Install your ICD by creating a file with the full path to the library of your implementation in `/etc/OpenCL/vendors` for eg.: 97 | 98 | echo full/path/to/libOpenCLDriverStub.so > /etc/OpenCL/vendors/test.icd 99 | 100 | ### Registering an ICD on Windows 101 | 102 | Install your ICD by adding a `REG_DWORD` value to the registry keys: 103 | 104 | // For 32-bit operating systems, or 64-bit tests on a 64-bit operating system: 105 | HKEY_LOCAL_MACHINE\SOFTWARE\Khronos\OpenCL\Vendors 106 | 107 | // For 32-bit tests on a 64-bit operating system: 108 | HKEY_LOCAL_MACHINE\SOFTWARE\Wow6432Node\Khronos\OpenCL\Vendors 109 | 110 | // The name of the REG_DWORD value should be the full path to the library of your implementation, for eg. 111 | // OpenCLDriverStub.dll, and the data for this value should be 0. 112 | 113 | ## About Layers 114 | 115 | Layers have been added as an experimental feature in the OpenCL ICD Loader. We do not 116 | expect the API or ABI to change significantly, but the OpenCL Working Group reserves 117 | the right to do so. The layer support can also be completely deactivated during 118 | configuration by using the `ENABLE_OPENCL_LAYERS` (`ON` by default) cmake variable: 119 | 120 | ```bash 121 | cmake -DENABLE_OPENCL_LAYERS=OFF 122 | ``` 123 | 124 | For now, runtime configuration of layers is done using the `OPENCL_LAYERS` environment 125 | variable. A colon (Linux) or semicolon (Windows) list of layers to use can be provided 126 | through this environment variable. 127 | 128 | We are looking for feedback. 129 | 130 | ## Support 131 | 132 | Please create a GitHub issue to report an issue or ask questions. 133 | 134 | ## Contributing 135 | 136 | Contributions to the OpenCL ICD Loader are welcomed and encouraged. 137 | You will be prompted with a one-time "click-through" CLA dialog as part of submitting your pull request or other contribution to GitHub. 138 | 139 | ## Table of Debug Environment Variables 140 | 141 | The following debug environment variables are available for use with the OpenCL ICD loader: 142 | 143 | | Environment Variable | Behavior | Example Format | 144 | |:---------------------------------:|---------------------|----------------------| 145 | | OCL_ICD_FILENAMES | Specifies a list of additional ICDs to load. The ICDs will be enumerated first, before any ICDs discovered via default mechanisms. | `export OCL_ICD_FILENAMES=libVendorA.so:libVendorB.so`

`set OCL_ICD_FILENAMES=vendor_a.dll;vendor_b.dll` | 146 | | OCL_ICD_VENDORS | On Linux and Android, specifies a directory to scan for ICDs to enumerate in place of the default `/etc/OpenCL/vendors'. | `export OCL_ICD_VENDORS=/my/local/icd/search/path` | 147 | | OPENCL_LAYERS | Specifies a list of layers to load. | `export OPENCL_LAYERS=libLayerA.so:libLayerB.so`

`set OPENCL_LAYERS=libLayerA.dll;libLayerB.dll` | 148 | | OPENCL_LAYER_PATH | On Linux and Android, specifies a directory to scan for layers to enumerate in place of the default `/etc/OpenCL/layers'. | `export OPENCL_LAYER_PATH=/my/local/layers/search/path` | 149 | | OCL_ICD_ENABLE_TRACE | Enable the trace mechanism | `export OCL_ICD_ENABLE_TRACE=True`

`set OCL_ICD_ENABLE_TRACE=True`
`true, T, 1 can also be used here.` | 150 | -------------------------------------------------------------------------------- /cmake/DebSourcePkg.cmake: -------------------------------------------------------------------------------- 1 | # This script produces the changelog, control and rules file in the debian 2 | # directory. These files are needed to build a Debian source package from the repository. 3 | # Run this in CMake script mode, e.g. 4 | # $ cd OpenCL-ICD-Loader 5 | # $ cmake -S . -B ../build -D BUILD_TESTING=OFF 6 | # $ cmake 7 | # -DCMAKE_CACHE_PATH=../build/CMakeCache.txt 8 | # -DCPACK_DEBIAN_PACKAGE_MAINTAINER="Example Name " 9 | # -DDEBIAN_DISTROSERIES=jammy 10 | # -DORIG_ARCHIVE=../OpenCL-ICD-Loader.tar.gz 11 | # -DLATEST_RELEASE_VERSION=v2023.08.29 12 | # -P cmake/DebSourcePkg.cmake 13 | # $ debuild -S -sa 14 | 15 | cmake_minimum_required(VERSION 3.21) # file(COPY_FILE) is added in CMake 3.21 16 | 17 | if(NOT EXISTS "${CMAKE_CACHE_PATH}") 18 | message(FATAL_ERROR "CMAKE_CACHE_PATH is not set or does not exist") 19 | endif() 20 | if(NOT DEFINED DEBIAN_PACKAGE_MAINTAINER) 21 | message(FATAL_ERROR "DEBIAN_PACKAGE_MAINTAINER is not set") 22 | endif() 23 | if(NOT DEFINED DEBIAN_DISTROSERIES) 24 | message(FATAL_ERROR "DEBIAN_DISTROSERIES is not set") 25 | endif() 26 | if(NOT DEFINED ORIG_ARCHIVE) 27 | message(WARNING "ORIG_ARCHIVE is not set") 28 | elseif(NOT EXISTS "${ORIG_ARCHIVE}") 29 | message(FATAL_ERROR "ORIG_ARCHIVE is defined, but the file does not exist at \"${ORIG_ARCHIVE}\"") 30 | endif() 31 | if(NOT DEFINED LATEST_RELEASE_VERSION) 32 | message(WARNING "LATEST_RELEASE_VERSION is not set") 33 | endif() 34 | if(NOT DEFINED DEBIAN_VERSION_SUFFIX) 35 | message(WARNING "DEBIAN_VERSION_SUFFIX is not set") 36 | endif() 37 | 38 | # Extracting the project version from the main CMakeLists.txt via regex 39 | file(READ "${CMAKE_CACHE_PATH}" CMAKE_CACHE) 40 | string(REGEX MATCH "CMAKE_PROJECT_VERSION[^=]*=([^\n]*)" REGEX_MATCH "${CMAKE_CACHE}") 41 | if(NOT REGEX_MATCH) 42 | message(FATAL_ERROR "Could not extract project version from CMakeLists.txt") 43 | endif() 44 | set(PROJECT_VERSION "${CMAKE_MATCH_1}") 45 | 46 | list(APPEND CMAKE_MODULE_PATH "${CMAKE_CURRENT_LIST_DIR}") 47 | # Package.cmake contains all details for packaging 48 | include(PackageSetup) 49 | 50 | # Append a space after every newline in the description. This format is required 51 | # in the control file. 52 | string(REPLACE "\n" "\n " CPACK_DEBIAN_DEV_DESCRIPTION "${CPACK_DEBIAN_DEV_DESCRIPTION}") 53 | string(REPLACE "\n" "\n " CPACK_DEBIAN_RUNTIME_DESCRIPTION "${CPACK_DEBIAN_RUNTIME_DESCRIPTION}") 54 | string(REPLACE "\n" "\n " CPACK_DEBIAN_CLLAYERINFO_DESCRIPTION "${CPACK_DEBIAN_CLLAYERINFO_DESCRIPTION}") 55 | 56 | set(DEB_SOURCE_PKG_DIR "${CMAKE_CURRENT_LIST_DIR}/../debian") 57 | # Write debian/control 58 | file(WRITE "${DEB_SOURCE_PKG_DIR}/control" 59 | "Source: ${PACKAGE_NAME_PREFIX} 60 | Section: ${CPACK_DEBIAN_DEV_PACKAGE_SECTION} 61 | Priority: optional 62 | Maintainer: ${DEBIAN_PACKAGE_MAINTAINER} 63 | Build-Depends: cmake, debhelper-compat (=13), opencl-c-headers 64 | Rules-Requires-Root: no 65 | Homepage: ${CPACK_DEBIAN_PACKAGE_HOMEPAGE} 66 | Standards-Version: 4.6.2 67 | 68 | Package: ${CPACK_DEBIAN_DEV_PACKAGE_NAME} 69 | Architecture: any 70 | Multi-Arch: same 71 | Depends: ${CPACK_DEBIAN_DEV_PACKAGE_DEPENDS}, ${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME} (=${PACKAGE_VERSION_REVISION}) 72 | Recommends: ${CPACK_DEBIAN_DEV_PACKAGE_RECOMMENDS} 73 | Conflicts: ${CPACK_DEBIAN_DEV_PACKAGE_CONFLICTS} 74 | Breaks: ${CPACK_DEBIAN_DEV_PACKAGE_BREAKS} 75 | Replaces: ${CPACK_DEBIAN_DEV_PACKAGE_REPLACES} 76 | Provides: ${CPACK_DEBIAN_DEV_PACKAGE_PROVIDES} 77 | Description: ${CPACK_DEBIAN_DEV_DESCRIPTION} 78 | 79 | Package: ${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME} 80 | Section: ${CPACK_DEBIAN_RUNTIME_PACKAGE_SECTION} 81 | Architecture: any 82 | Multi-Arch: same 83 | Depends: ${CPACK_DEBIAN_RUNTIME_PACKAGE_DEPENDS} 84 | # Conflicts and replaces deliberately not added 85 | # The runtime package provides libOpenCL.so.1.0.0 and libOpenCL.so.1 via update-alternatives 86 | # Conflicts: ${CPACK_DEBIAN_RUNTIME_PACKAGE_CONFLICTS} 87 | # Replaces: ${CPACK_DEBIAN_RUNTIME_PACKAGE_REPLACES} 88 | Provides: ${CPACK_DEBIAN_RUNTIME_PACKAGE_PROVIDES} 89 | Description: ${CPACK_DEBIAN_RUNTIME_DESCRIPTION} 90 | 91 | Package: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_NAME} 92 | Section: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_SECTION} 93 | Architecture: any 94 | Depends: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_DEPENDS}, ${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME} (=${PACKAGE_VERSION_REVISION}) 95 | Conflicts: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_CONFLICTS} 96 | Replaces: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_REPLACES} 97 | Provides: ${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_PROVIDES} 98 | Description: ${CPACK_DEBIAN_CLLAYERINFO_DESCRIPTION} 99 | " 100 | ) 101 | # Write debian/changelog 102 | string(TIMESTAMP CURRENT_TIMESTAMP "%a, %d %b %Y %H:%M:%S +0000" UTC) 103 | file(WRITE "${DEB_SOURCE_PKG_DIR}/changelog" 104 | "${PACKAGE_NAME_PREFIX} (${PACKAGE_VERSION_REVISION}) ${DEBIAN_DISTROSERIES}; urgency=medium 105 | 106 | * Released version ${PACKAGE_VERSION_REVISION} 107 | 108 | -- ${DEBIAN_PACKAGE_MAINTAINER} ${CURRENT_TIMESTAMP} 109 | ") 110 | # Write debian/rules 111 | file(WRITE "${DEB_SOURCE_PKG_DIR}/rules" 112 | "#!/usr/bin/make -f 113 | %: 114 | \tdh $@ 115 | 116 | override_dh_auto_configure: 117 | \tdh_auto_configure -- -DCMAKE_BUILD_TYPE=Release -DBUILD_TESTING=OFF 118 | 119 | GENERATED_MAINTAINER_SCRIPTS := $(patsubst %.in,%,$(wildcard debian/*.alternatives.in)) 120 | 121 | $(GENERATED_MAINTAINER_SCRIPTS): %: %.in 122 | \tsed \"s%@DEB_HOST_MULTIARCH@%$(DEB_HOST_MULTIARCH)%g\" < $< > $@ 123 | 124 | execute_before_dh_install: $(GENERATED_MAINTAINER_SCRIPTS) 125 | \ttrue # An empty rule would confuse dh 126 | ") 127 | file(WRITE "${DEB_SOURCE_PKG_DIR}/${CPACK_DEBIAN_DEV_PACKAGE_NAME}.install" 128 | "usr/lib/*/pkgconfig 129 | usr/lib/*/lib*.so 130 | usr/share 131 | ") 132 | # The .so files are installed to a different directory, and then linked back 133 | # the the original location via update-alternatives. 134 | file(WRITE "${DEB_SOURCE_PKG_DIR}/${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME}.install" 135 | "usr/lib/*/lib*.so.* usr/lib/\${DEB_HOST_MULTIARCH}/KhronosOpenCLICDLoader 136 | ") 137 | file(WRITE "${DEB_SOURCE_PKG_DIR}/${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME}.alternatives.in" 138 | "Name: libOpenCL.so.1.0.0-@DEB_HOST_MULTIARCH@ 139 | Link: /usr/lib/@DEB_HOST_MULTIARCH@/libOpenCL.so.1.0.0 140 | Alternative: /usr/lib/@DEB_HOST_MULTIARCH@/KhronosOpenCLICDLoader/libOpenCL.so.1.0.0 141 | Dependents: 142 | /usr/lib/@DEB_HOST_MULTIARCH@/libOpenCL.so.1 libOpenCL.so.1-@DEB_HOST_MULTIARCH@ /usr/lib/@DEB_HOST_MULTIARCH@/KhronosOpenCLICDLoader/libOpenCL.so.1 143 | Priority: 100 144 | ") 145 | file(WRITE "${DEB_SOURCE_PKG_DIR}/${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_NAME}.install" 146 | "usr/bin 147 | ") 148 | 149 | if(DEFINED ORIG_ARCHIVE) 150 | # Copy the passed orig.tar.gz file. The target filename is deduced from the version number, as expected by debuild 151 | cmake_path(IS_ABSOLUTE ORIG_ARCHIVE IS_ORIG_ARCHIVE_ABSOLUTE) 152 | if (NOT IS_ORIG_ARCHIVE_ABSOLUTE) 153 | message(FATAL_ERROR "ORIG_ARCHIVE must be an absolute path (passed: \"${ORIG_ARCHIVE}\")") 154 | endif() 155 | cmake_path(GET ORIG_ARCHIVE EXTENSION ORIG_ARCHIVE_EXT) 156 | cmake_path(GET ORIG_ARCHIVE PARENT_PATH ORIG_ARCHIVE_PARENT) 157 | set(TARGET_PATH "${ORIG_ARCHIVE_PARENT}/${PACKAGE_NAME_PREFIX}_${CPACK_DEBIAN_PACKAGE_VERSION}${ORIG_ARCHIVE_EXT}") 158 | message(STATUS "Copying \"${ORIG_ARCHIVE}\" to \"${TARGET_PATH}\"") 159 | file(COPY_FILE "${ORIG_ARCHIVE}" "${TARGET_PATH}") 160 | endif() 161 | -------------------------------------------------------------------------------- /cmake/JoinPaths.cmake: -------------------------------------------------------------------------------- 1 | # This module provides function for joining paths 2 | # known from from most languages 3 | # 4 | # Original license: 5 | # SPDX-License-Identifier: (MIT OR CC0-1.0) 6 | # Explicit permission given to distribute this module under 7 | # the terms of the project as described in /LICENSE.rst. 8 | # Copyright 2020 Jan Tojnar 9 | # https://github.com/jtojnar/cmake-snips 10 | # 11 | # Modelled after Python’s os.path.join 12 | # https://docs.python.org/3.7/library/os.path.html#os.path.join 13 | # Windows not supported 14 | function(join_paths joined_path first_path_segment) 15 | set(temp_path "${first_path_segment}") 16 | foreach(current_segment IN LISTS ARGN) 17 | if(NOT ("${current_segment}" STREQUAL "")) 18 | if(IS_ABSOLUTE "${current_segment}") 19 | set(temp_path "${current_segment}") 20 | else() 21 | set(temp_path "${temp_path}/${current_segment}") 22 | endif() 23 | endif() 24 | endforeach() 25 | set(${joined_path} "${temp_path}" PARENT_SCOPE) 26 | endfunction() 27 | -------------------------------------------------------------------------------- /cmake/Package.cmake: -------------------------------------------------------------------------------- 1 | include("${CMAKE_CURRENT_LIST_DIR}/PackageSetup.cmake") 2 | 3 | # Configuring pkgconfig 4 | 5 | # We need two different instances of OpenCL.pc 6 | # One for installing (cmake --install), which contains CMAKE_INSTALL_PREFIX as prefix 7 | # And another for the Debian development package, which contains CPACK_PACKAGING_INSTALL_PREFIX as prefix 8 | 9 | join_paths(OPENCL_INCLUDEDIR_PC "\${prefix}" "${CMAKE_INSTALL_INCLUDEDIR}") 10 | join_paths(OPENCL_LIBDIR_PC "\${exec_prefix}" "${CMAKE_INSTALL_LIBDIR}") 11 | 12 | set(pkg_config_location ${CMAKE_INSTALL_LIBDIR}/pkgconfig) 13 | set(PKGCONFIG_PREFIX "${CMAKE_INSTALL_PREFIX}") 14 | 15 | # Configure and install OpenCL.pc for installing the project 16 | configure_file( 17 | OpenCL.pc.in 18 | ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig_install/OpenCL.pc 19 | @ONLY) 20 | install( 21 | FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig_install/OpenCL.pc 22 | DESTINATION ${pkg_config_location} 23 | COMPONENT pkgconfig_install) 24 | 25 | # Configure and install OpenCL.pc for the Debian package 26 | set(PKGCONFIG_PREFIX "${CPACK_PACKAGING_INSTALL_PREFIX}") 27 | configure_file( 28 | OpenCL.pc.in 29 | ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig_package/OpenCL.pc 30 | @ONLY) 31 | 32 | install( 33 | FILES ${CMAKE_CURRENT_BINARY_DIR}/pkgconfig_package/OpenCL.pc 34 | DESTINATION ${pkg_config_location} 35 | COMPONENT dev 36 | EXCLUDE_FROM_ALL) 37 | 38 | set(CPACK_DEBIAN_PACKAGE_DEBUG ON) 39 | 40 | include(CPack) 41 | -------------------------------------------------------------------------------- /cmake/PackageSetup.cmake: -------------------------------------------------------------------------------- 1 | set(CPACK_PACKAGE_VENDOR "khronos") 2 | 3 | set(CPACK_DEBIAN_RUNTIME_DESCRIPTION "Generic OpenCL ICD Loader 4 | OpenCL (Open Computing Language) is a multivendor open standard for 5 | general-purpose parallel programming of heterogeneous systems that include 6 | CPUs, GPUs and other processors. 7 | . 8 | This package contains an installable client driver loader (ICD Loader) 9 | library that can be used to load any (free or non-free) installable client 10 | driver (ICD) for OpenCL. It acts as a demultiplexer so several ICD can 11 | be installed and used together.") 12 | 13 | set(CPACK_DEBIAN_DEV_DESCRIPTION "OpenCL development files 14 | OpenCL (Open Computing Language) is a multivendor open standard for 15 | general-purpose parallel programming of heterogeneous systems that include 16 | CPUs, GPUs and other processors. 17 | . 18 | This package provides the development files: headers and libraries. 19 | . 20 | It also ensures that the ocl-icd ICD loader is installed so its additional 21 | features (compared to the OpenCL norm) can be used: .pc file, ability to 22 | select an ICD without root privilege, etc.") 23 | 24 | set(CPACK_DEBIAN_CLLAYERINFO_DESCRIPTION "Query OpenCL Layer system information 25 | OpenCL (Open Computing Language) is a multivendor open standard for 26 | general-purpose parallel programming of heterogeneous systems that include 27 | CPUs, GPUs and other processors. It supports system and user configured layers 28 | to intercept OpenCL API calls. 29 | . 30 | This package contains a tool that lists the layers loaded by the the ocl-icd 31 | OpenCL ICD Loader.") 32 | 33 | set(CPACK_RESOURCE_FILE_LICENSE "${CMAKE_CURRENT_SOURCE_DIR}/LICENSE") 34 | 35 | set(CPACK_RESOURCE_FILE_README "${CMAKE_CURRENT_SOURCE_DIR}/README.md") 36 | 37 | if(NOT CPACK_PACKAGING_INSTALL_PREFIX) 38 | set(CPACK_PACKAGING_INSTALL_PREFIX "${CMAKE_INSTALL_PREFIX}") 39 | endif() 40 | 41 | # DEB packaging configuration 42 | set(CPACK_DEBIAN_PACKAGE_MAINTAINER ${CPACK_PACKAGE_VENDOR}) 43 | 44 | set(CPACK_DEBIAN_PACKAGE_HOMEPAGE 45 | "https://github.com/KhronosGroup/OpenCL-ICD-Loader") 46 | 47 | # Version number [epoch:]upstream_version[-debian_revision] 48 | set(CPACK_DEBIAN_PACKAGE_VERSION "${PROJECT_VERSION}") # upstream_version 49 | if(DEFINED LATEST_RELEASE_VERSION) 50 | # Remove leading "v", if exists 51 | string(LENGTH "${LATEST_RELEASE_VERSION}" LATEST_RELEASE_VERSION_LENGTH) 52 | string(SUBSTRING "${LATEST_RELEASE_VERSION}" 0 1 LATEST_RELEASE_VERSION_FRONT) 53 | if(LATEST_RELEASE_VERSION_FRONT STREQUAL "v") 54 | string(SUBSTRING "${LATEST_RELEASE_VERSION}" 1 ${LATEST_RELEASE_VERSION_LENGTH} LATEST_RELEASE_VERSION) 55 | endif() 56 | 57 | string(APPEND CPACK_DEBIAN_PACKAGE_VERSION "~${LATEST_RELEASE_VERSION}") 58 | endif() 59 | set(CPACK_DEBIAN_PACKAGE_RELEASE "1") # debian_revision (because this is a 60 | # non-native pkg) 61 | set(PACKAGE_VERSION_REVISION "${CPACK_DEBIAN_PACKAGE_VERSION}-${CPACK_DEBIAN_PACKAGE_RELEASE}${DEBIAN_VERSION_SUFFIX}") 62 | 63 | # Get architecture 64 | execute_process(COMMAND dpkg "--print-architecture" OUTPUT_VARIABLE CPACK_DEBIAN_PACKAGE_ARCHITECTURE) 65 | string(STRIP "${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}" CPACK_DEBIAN_PACKAGE_ARCHITECTURE) 66 | 67 | ########################################################## 68 | # Components # 69 | ########################################################## 70 | 71 | set(CPACK_DEB_COMPONENT_INSTALL ON) 72 | set(CPACK_DEBIAN_ENABLE_COMPONENT_DEPENDS OFF) # Component dependencies are NOT reflected in package relationships 73 | set(CPACK_COMPONENTS_ALL runtime dev cllayerinfo) 74 | 75 | set(PACKAGE_NAME_PREFIX "khronos-opencl-loader") 76 | 77 | ## Package runtime component 78 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_NAME "${PACKAGE_NAME_PREFIX}-libopencl1") 79 | 80 | # Package file name in deb format: 81 | # _-_.deb 82 | set(CPACK_DEBIAN_RUNTIME_FILE_NAME "${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME}_${PACKAGE_VERSION_REVISION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") 83 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_SECTION "libs") 84 | # Dependencies 85 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_DEPENDS "libc6") 86 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_SUGGESTS "opencl-icd") 87 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_CONFLICTS "amd-app, libopencl1, nvidia-libopencl1-dev") 88 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_REPLACES "amd-app, libopencl1, nvidia-libopencl1-dev") 89 | set(CPACK_DEBIAN_RUNTIME_PACKAGE_PROVIDES "libopencl-1.1-1, libopencl-1.2-1, libopencl-2.0-1, libopencl-2.1-1, libopencl-2.2-1, libopencl-3.0-1, libopencl1") 90 | 91 | ## Package dev component 92 | set(CPACK_DEBIAN_DEV_PACKAGE_NAME "${PACKAGE_NAME_PREFIX}-opencl-dev") 93 | 94 | # Package file name in deb format: 95 | # _-_.deb 96 | set(CPACK_DEBIAN_DEV_FILE_NAME "${CPACK_DEBIAN_DEV_PACKAGE_NAME}_${PACKAGE_VERSION_REVISION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") 97 | set(CPACK_DEBIAN_DEV_PACKAGE_SECTION "libdevel") 98 | 99 | # Dependencies 100 | set(CPACK_DEBIAN_DEV_PACKAGE_DEPENDS "opencl-c-headers (>= ${CPACK_DEBIAN_PACKAGE_VERSION}) | opencl-headers (>= ${CPACK_DEBIAN_PACKAGE_VERSION}), ${CPACK_DEBIAN_RUNTIME_PACKAGE_NAME} (>= ${CPACK_DEBIAN_PACKAGE_VERSION}) | libopencl1") 101 | set(CPACK_DEBIAN_DEV_PACKAGE_RECOMMENDS "libgl1-mesa-dev | libgl-dev") 102 | set(CPACK_DEBIAN_DEV_PACKAGE_CONFLICTS "opencl-dev") 103 | set(CPACK_DEBIAN_DEV_PACKAGE_BREAKS "amd-libopencl1, nvidia-libopencl1") 104 | set(CPACK_DEBIAN_DEV_PACKAGE_REPLACES "amd-libopencl1, nvidia-libopencl1, opencl-dev") 105 | set(CPACK_DEBIAN_DEV_PACKAGE_PROVIDES "opencl-dev") 106 | 107 | ## Package cllayerinfo component 108 | set(CPACK_DEBIAN_CLLAYERINFO_PACKAGE_NAME "${PACKAGE_NAME_PREFIX}-cllayerinfo") 109 | set(CPACK_DEBIAN_CLLAYERINFO_FILE_NAME "${CPACK_DEBIAN_CLLAYERINFO_PACKAGE_NAME}_${PACKAGE_VERSION_REVISION}_${CPACK_DEBIAN_PACKAGE_ARCHITECTURE}.deb") 110 | # Dependencies 111 | set(CPACK_DEBIAN_CLLAYERINFO_PACKAGE_DEPENDS "libc6") 112 | set(CPACK_DEBIAN_CLLAYERINFO_PACKAGE_SECTION "admin") 113 | -------------------------------------------------------------------------------- /inc/README.txt: -------------------------------------------------------------------------------- 1 | Copy or symlink OpenCL headers here, inside a CL directory, so that 2 | the structure of the inc directory looks something like this: 3 | 4 | inc/CL/cl_d3d10.h 5 | inc/CL/cl_d3d11.h 6 | inc/CL/cl_dx9_media_sharing.h 7 | inc/CL/cl_egl.h 8 | inc/CL/cl_ext.h 9 | inc/CL/cl_gl.h 10 | inc/CL/cl.h 11 | inc/CL/cl.hpp 12 | inc/CL/cl_platform.h 13 | inc/CL/opencl.h 14 | -------------------------------------------------------------------------------- /include/cl_khr_icd2.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2025 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | 21 | #if !defined(CL_ICD2_TAG_KHR) 22 | #if INTPTR_MAX == INT32_MAX 23 | #define CL_ICD2_TAG_KHR ((intptr_t)0x434C3331) 24 | #else 25 | #define CL_ICD2_TAG_KHR ((intptr_t)0x4F50454E434C3331) 26 | #endif 27 | 28 | typedef void * CL_API_CALL 29 | clIcdGetFunctionAddressForPlatformKHR_t( 30 | cl_platform_id platform, 31 | const char* func_name); 32 | 33 | typedef clIcdGetFunctionAddressForPlatformKHR_t * 34 | clIcdGetFunctionAddressForPlatformKHR_fn; 35 | 36 | typedef cl_int CL_API_CALL 37 | clIcdSetPlatformDispatchDataKHR_t( 38 | cl_platform_id platform, 39 | void *disp_data); 40 | 41 | typedef clIcdSetPlatformDispatchDataKHR_t * 42 | clIcdSetPlatformDispatchDataKHR_fn; 43 | #endif // !defined(CL_ICD2_TAG_KHR) 44 | -------------------------------------------------------------------------------- /loader/cllayerinfo.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2022 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include "icd.h" 20 | #include 21 | #include 22 | #include 23 | #if defined(_WIN32) 24 | #include 25 | #include 26 | #include 27 | #else 28 | #include 29 | #endif 30 | #include 31 | 32 | int stdout_bak, stderr_bak; 33 | 34 | // Temporarily deactivate stdout: 35 | // https://stackoverflow.com/a/4832902 36 | 37 | #if defined(_WIN32) 38 | #define SECURE 1 39 | #define OPEN _open 40 | #define OPEN_FLAGS _O_WRONLY 41 | #define CLOSE _close 42 | #define DUP _dup 43 | #define DUP2 _dup2 44 | #define NULL_STREAM "nul" 45 | #else 46 | #define OPEN open 47 | #define OPEN_FLAGS O_WRONLY 48 | #define CLOSE close 49 | #define DUP dup 50 | #define DUP2 dup2 51 | #define NULL_STREAM "/dev/null" 52 | #endif 53 | 54 | static inline int 55 | silence_stream(FILE *file, int fd) 56 | { 57 | int new_fd, fd_bak; 58 | fflush(file); 59 | fd_bak = DUP(fd); 60 | #if defined(_WIN32) && SECURE 61 | _sopen_s(&new_fd, NULL_STREAM, OPEN_FLAGS, _SH_DENYNO, _S_IWRITE); 62 | #else 63 | new_fd = OPEN(NULL_STREAM, OPEN_FLAGS); 64 | #endif 65 | DUP2(new_fd, fd); 66 | CLOSE(new_fd); 67 | return fd_bak; 68 | } 69 | 70 | static void silence_layers(void) 71 | { 72 | stdout_bak = silence_stream(stdout, 1); 73 | stderr_bak = silence_stream(stderr, 2); 74 | } 75 | 76 | static inline void 77 | restore_stream(FILE *file, int fd, int fd_bak) 78 | { 79 | fflush(file); 80 | DUP2(fd_bak, fd); 81 | CLOSE(fd_bak); 82 | } 83 | 84 | static void restore_outputs(void) 85 | { 86 | restore_stream(stdout, 1, stdout_bak); 87 | restore_stream(stderr, 2, stderr_bak); 88 | } 89 | 90 | void printLayerInfo(const struct KHRLayer *layer) 91 | { 92 | cl_layer_api_version api_version = 0; 93 | pfn_clGetLayerInfo p_clGetLayerInfo = (pfn_clGetLayerInfo)(size_t)layer->p_clGetLayerInfo; 94 | cl_int result = CL_SUCCESS; 95 | size_t sz; 96 | 97 | printf("%s:\n", layer->libraryName); 98 | result = p_clGetLayerInfo(CL_LAYER_API_VERSION, sizeof(api_version), &api_version, NULL); 99 | if (CL_SUCCESS == result) 100 | printf("\tCL_LAYER_API_VERSION: %d\n", (int)api_version); 101 | 102 | result = p_clGetLayerInfo(CL_LAYER_NAME, 0, NULL, &sz); 103 | if (CL_SUCCESS == result) 104 | { 105 | char *name = (char *)malloc(sz); 106 | if (name) 107 | { 108 | result = p_clGetLayerInfo(CL_LAYER_NAME, sz, name, NULL); 109 | if (CL_SUCCESS == result) 110 | printf("\tCL_LAYER_NAME: %s\n", name); 111 | free(name); 112 | } 113 | } 114 | } 115 | 116 | int main (int argc, char *argv[]) 117 | { 118 | (void)argc; 119 | (void)argv; 120 | silence_layers(); 121 | atexit(restore_outputs); 122 | khrIcdInitialize(); 123 | restore_outputs(); 124 | atexit(silence_layers); 125 | const struct KHRLayer *layer = khrFirstLayer; 126 | while (layer) 127 | { 128 | printLayerInfo(layer); 129 | layer = layer->next; 130 | } 131 | return 0; 132 | } 133 | -------------------------------------------------------------------------------- /loader/icd.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef _ICD_H_ 20 | #define _ICD_H_ 21 | 22 | #include "icd_platform.h" 23 | #include "icd_dispatch.h" 24 | 25 | #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS 26 | #define CL_USE_DEPRECATED_OPENCL_1_0_APIS 27 | #endif 28 | 29 | #ifndef CL_USE_DEPRECATED_OPENCL_1_1_APIS 30 | #define CL_USE_DEPRECATED_OPENCL_1_1_APIS 31 | #endif 32 | 33 | #ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS 34 | #define CL_USE_DEPRECATED_OPENCL_1_2_APIS 35 | #endif 36 | 37 | #ifndef CL_USE_DEPRECATED_OPENCL_2_0_APIS 38 | #define CL_USE_DEPRECATED_OPENCL_2_0_APIS 39 | #endif 40 | 41 | #ifndef CL_USE_DEPRECATED_OPENCL_2_1_APIS 42 | #define CL_USE_DEPRECATED_OPENCL_2_1_APIS 43 | #endif 44 | 45 | #ifndef CL_USE_DEPRECATED_OPENCL_2_2_APIS 46 | #define CL_USE_DEPRECATED_OPENCL_2_2_APIS 47 | #endif 48 | 49 | #include 50 | #include 51 | #include 52 | #include 53 | 54 | /* 55 | * type definitions 56 | */ 57 | 58 | typedef cl_int (CL_API_CALL *pfn_clIcdGetPlatformIDs)( 59 | cl_uint num_entries, 60 | cl_platform_id *platforms, 61 | cl_uint *num_platforms) CL_API_SUFFIX__VERSION_1_0; 62 | 63 | typedef cl_int (CL_API_CALL *pfn_clGetPlatformInfo)( 64 | cl_platform_id platform, 65 | cl_platform_info param_name, 66 | size_t param_value_size, 67 | void * param_value, 68 | size_t * param_value_size_ret) CL_API_SUFFIX__VERSION_1_0; 69 | 70 | typedef void *(CL_API_CALL *pfn_clGetExtensionFunctionAddress)( 71 | const char *function_name) CL_API_SUFFIX__VERSION_1_0; 72 | 73 | typedef struct KHRicdVendorRec KHRicdVendor; 74 | 75 | /* 76 | * KHRicdVendor 77 | * 78 | * Data for a single ICD vendor platform. 79 | */ 80 | struct KHRicdVendorRec 81 | { 82 | // the loaded library object (true type varies on Linux versus Windows) 83 | void *library; 84 | 85 | // the extension suffix for this platform 86 | char *suffix; 87 | 88 | // function pointer to the ICD platform IDs extracted from the library 89 | pfn_clGetExtensionFunctionAddress clGetExtensionFunctionAddress; 90 | 91 | // the platform retrieved from clGetIcdPlatformIDsKHR 92 | cl_platform_id platform; 93 | 94 | #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) 95 | // the loader populated dispatch table for cl_khr_icd2 compliant platforms 96 | struct KHRDisp dispData; 97 | #endif 98 | 99 | // next vendor in the list vendors 100 | KHRicdVendor *next; 101 | }; 102 | 103 | // the global state 104 | extern KHRicdVendor * khrIcdVendors; 105 | 106 | extern int khrEnableTrace; 107 | 108 | #if defined(CL_ENABLE_LAYERS) 109 | /* 110 | * KHRLayer 111 | * 112 | * Data for a single Layer 113 | */ 114 | struct KHRLayer; 115 | struct KHRLayer 116 | { 117 | // the loaded library object (true type varies on Linux versus Windows) 118 | void *library; 119 | // the dispatch table of the layer 120 | struct _cl_icd_dispatch dispatch; 121 | // The next layer in the chain 122 | struct KHRLayer *next; 123 | #ifdef CL_LAYER_INFO 124 | // The layer library name 125 | char *libraryName; 126 | // the pointer to the clGetLayerInfo funciton 127 | void *p_clGetLayerInfo; 128 | #endif 129 | }; 130 | 131 | // the global layer state 132 | extern struct KHRLayer * khrFirstLayer; 133 | extern struct _cl_icd_dispatch khrMasterDispatch; 134 | #endif // defined(CL_ENABLE_LAYERS) 135 | 136 | /* 137 | * khrIcd interface 138 | */ 139 | 140 | // read vendors from system configuration and store the data 141 | // loaded into khrIcdState. this will call the OS-specific 142 | // function khrIcdEnumerateVendors. this is called at every 143 | // dispatch function which may be a valid first call into the 144 | // API (e.g, getPlatformIDs, etc). 145 | void khrIcdInitialize(void); 146 | 147 | // entrypoint to check and initialize trace. 148 | void khrIcdInitializeTrace(void); 149 | 150 | // go through the list of vendors (in /etc/OpenCL.conf or through 151 | // the registry) and call khrIcdVendorAdd for each vendor encountered 152 | // n.b, this call is OS-specific 153 | void khrIcdOsVendorsEnumerateOnce(void); 154 | 155 | // read vendors from environment variables 156 | void khrIcdVendorsEnumerateEnv(void); 157 | 158 | // add a vendor's implementation to the list of libraries 159 | void khrIcdVendorAdd(const char *libraryName); 160 | 161 | // read layers from environment variables 162 | void khrIcdLayersEnumerateEnv(void); 163 | 164 | // add a layer to the layer chain 165 | void khrIcdLayerAdd(const char *libraryName); 166 | 167 | // dynamically load a library. returns NULL on failure 168 | // n.b, this call is OS-specific 169 | void *khrIcdOsLibraryLoad(const char *libraryName); 170 | 171 | // get a function pointer from a loaded library. returns NULL on failure. 172 | // n.b, this call is OS-specific 173 | void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName); 174 | 175 | // unload a library. 176 | // n.b, this call is OS-specific 177 | void khrIcdOsLibraryUnload(void *library); 178 | 179 | // parse properties and determine the platform to use from them 180 | void khrIcdContextPropertiesGetPlatform( 181 | const cl_context_properties *properties, 182 | cl_platform_id *outPlatform); 183 | 184 | // internal tracing macros 185 | #define KHR_ICD_TRACE(...) \ 186 | do \ 187 | { \ 188 | if (khrEnableTrace) \ 189 | { \ 190 | fprintf(stderr, "KHR ICD trace at %s:%d: ", __FILE__, __LINE__); \ 191 | fprintf(stderr, __VA_ARGS__); \ 192 | } \ 193 | } while (0) 194 | 195 | #ifdef _WIN32 196 | #define KHR_ICD_WIDE_TRACE(...) \ 197 | do \ 198 | { \ 199 | if (khrEnableTrace) \ 200 | { \ 201 | fwprintf(stderr, L"KHR ICD trace at %hs:%d: ", __FILE__, __LINE__); \ 202 | fwprintf(stderr, __VA_ARGS__); \ 203 | } \ 204 | } while (0) 205 | 206 | #else 207 | #define KHR_ICD_WIDE_TRACE(...) 208 | #endif 209 | 210 | #define KHR_ICD_ERROR_RETURN_ERROR(_error) \ 211 | do { \ 212 | return _error; \ 213 | } while(0) 214 | 215 | #define KHR_ICD_ERROR_RETURN_HANDLE(_error) \ 216 | do { \ 217 | if (errcode_ret) { \ 218 | *errcode_ret = _error; \ 219 | } \ 220 | return NULL; \ 221 | } while(0) 222 | 223 | // Check if the passed-in handle is NULL, and if it is, return the error. 224 | #define KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(_handle, _error) \ 225 | do { \ 226 | if (!_handle) { \ 227 | KHR_ICD_ERROR_RETURN_ERROR(_error); \ 228 | } \ 229 | } while (0) 230 | 231 | // Check if the passed-in handle is NULL, and if it is, first check and set 232 | // errcode_ret to the error, then return NULL (NULL being an invalid handle). 233 | #define KHR_ICD_VALIDATE_HANDLE_RETURN_HANDLE(_handle, _error) \ 234 | do { \ 235 | if (!_handle) { \ 236 | KHR_ICD_ERROR_RETURN_HANDLE(_error); \ 237 | } \ 238 | } while (0) 239 | 240 | // Check if the passed-in function pointer is NULL, and if it is, return 241 | // CL_INVALID_OPERATION. 242 | #define KHR_ICD_VALIDATE_POINTER_RETURN_ERROR(_pointer) \ 243 | do { \ 244 | if (!_pointer) { \ 245 | KHR_ICD_ERROR_RETURN_ERROR(CL_INVALID_OPERATION); \ 246 | } \ 247 | } while (0) 248 | 249 | // Check if the passed-in function pointer is NULL, and if it is, first 250 | // check and set errcode_ret to CL_INVALID_OPERATION, then return NULL 251 | // (NULL being an invalid handle). 252 | #define KHR_ICD_VALIDATE_POINTER_RETURN_HANDLE(_pointer) \ 253 | do { \ 254 | if (!_pointer) { \ 255 | KHR_ICD_ERROR_RETURN_HANDLE(CL_INVALID_OPERATION); \ 256 | } \ 257 | } while (0) 258 | 259 | #endif 260 | -------------------------------------------------------------------------------- /loader/icd_cmake_config.h.in: -------------------------------------------------------------------------------- 1 | #cmakedefine HAVE_SECURE_GETENV 2 | #cmakedefine HAVE___SECURE_GETENV 3 | -------------------------------------------------------------------------------- /loader/icd_dispatch.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2012-2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include "icd.h" 20 | #include "icd_dispatch.h" 21 | #include "icd_version.h" 22 | 23 | #include 24 | #include 25 | 26 | static clGetICDLoaderInfoOCLICD_t clGetICDLoaderInfoOCLICD; 27 | cl_int CL_API_CALL 28 | clGetICDLoaderInfoOCLICD( 29 | cl_icdl_info param_name, 30 | size_t param_value_size, 31 | void * param_value, 32 | size_t * param_value_size_ret) 33 | { 34 | static const char cl_icdl_OCL_VERSION[] = OPENCL_ICD_LOADER_OCL_VERSION_STRING; 35 | static const char cl_icdl_VERSION[] = OPENCL_ICD_LOADER_VERSION_STRING; 36 | static const char cl_icdl_NAME[] = OPENCL_ICD_LOADER_NAME_STRING; 37 | static const char cl_icdl_VENDOR[] = OPENCL_ICD_LOADER_VENDOR_STRING; 38 | size_t pvs; 39 | const void * pv = NULL; 40 | 41 | #define KHR_ICD_CASE_STRING_PARAM_NAME(name) \ 42 | case CL_ICDL_ ## name: \ 43 | pvs = strlen(cl_icdl_ ## name) + 1; \ 44 | pv = (const void *)cl_icdl_ ## name; \ 45 | break 46 | 47 | switch (param_name) { 48 | KHR_ICD_CASE_STRING_PARAM_NAME(OCL_VERSION); 49 | KHR_ICD_CASE_STRING_PARAM_NAME(VERSION); 50 | KHR_ICD_CASE_STRING_PARAM_NAME(NAME); 51 | KHR_ICD_CASE_STRING_PARAM_NAME(VENDOR); 52 | default: 53 | return CL_INVALID_VALUE; 54 | } 55 | 56 | #undef KHR_ICD_CASE_PARAM_NAME 57 | 58 | if (param_value) { 59 | if (param_value_size < pvs) 60 | return CL_INVALID_VALUE; 61 | memcpy(param_value, pv, pvs); 62 | } 63 | if (param_value_size_ret != NULL) 64 | *param_value_size_ret = pvs; 65 | return CL_SUCCESS; 66 | } 67 | 68 | static void* khrIcdGetExtensionFunctionAddress(const char* function_name) 69 | { 70 | // Most extensions, including multi-vendor KHR and EXT extensions, 71 | // do not need to be ICD-aware and do not require any ICD loader 72 | // modifications. The KHR and EXT extensions below were added for 73 | // backwards compatibility only. 74 | #define KHR_ICD_CHECK_EXTENSION_FUNCTION(name) \ 75 | do \ 76 | { \ 77 | if (!strcmp(function_name, #name)) \ 78 | { \ 79 | return (void*)(size_t)&name; \ 80 | } \ 81 | } while (0) 82 | 83 | // Functions supporting the creation of OpenCL Memory Objects 84 | // from OpenGL Objects (cl_apple_gl_sharing, cl_khr_gl_sharing) 85 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLBuffer); 86 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture); 87 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture2D); 88 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLTexture3D); 89 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromGLRenderbuffer); 90 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLObjectInfo); 91 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLTextureInfo); 92 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireGLObjects); 93 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseGLObjects); 94 | 95 | // cl_khr_gl_sharing 96 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetGLContextInfoKHR); 97 | 98 | // cl_khr_gl_event 99 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateEventFromGLsyncKHR); 100 | 101 | #if defined(_WIN32) 102 | // cl_khr_d3d10_sharing 103 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromD3D10KHR); 104 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10BufferKHR); 105 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10Texture2DKHR); 106 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D10Texture3DKHR); 107 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireD3D10ObjectsKHR); 108 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseD3D10ObjectsKHR); 109 | // cl_khr_d3d11_sharing 110 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromD3D11KHR); 111 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11BufferKHR); 112 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11Texture2DKHR); 113 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromD3D11Texture3DKHR); 114 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireD3D11ObjectsKHR); 115 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseD3D11ObjectsKHR); 116 | // cl_khr_dx9_media_sharing 117 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetDeviceIDsFromDX9MediaAdapterKHR); 118 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromDX9MediaSurfaceKHR); 119 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireDX9MediaSurfacesKHR); 120 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseDX9MediaSurfacesKHR); 121 | #endif 122 | 123 | // cl_ext_device_fission 124 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateSubDevicesEXT); 125 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clRetainDeviceEXT); 126 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clReleaseDeviceEXT); 127 | 128 | // cl_khr_egl_image 129 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateFromEGLImageKHR); 130 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueAcquireEGLObjectsKHR); 131 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clEnqueueReleaseEGLObjectsKHR); 132 | 133 | // cl_khr_egl_event 134 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clCreateEventFromEGLSyncKHR); 135 | 136 | // cl_khr_sub_groups 137 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetKernelSubGroupInfoKHR); 138 | 139 | // cl_icdl 140 | KHR_ICD_CHECK_EXTENSION_FUNCTION(clGetICDLoaderInfoOCLICD); 141 | 142 | #undef KHR_ICD_CHECK_EXTENSION_FUNCTION 143 | 144 | return NULL; 145 | } 146 | 147 | #ifdef __cplusplus 148 | extern "C" { 149 | #endif 150 | 151 | static inline cl_int clGetPlatformIDs_body( 152 | cl_uint num_entries, 153 | cl_platform_id* platforms, 154 | cl_uint* num_platforms) 155 | { 156 | KHRicdVendor* vendor = NULL; 157 | cl_uint i; 158 | 159 | if (!num_entries && platforms) 160 | { 161 | return CL_INVALID_VALUE; 162 | } 163 | if (!platforms && !num_platforms) 164 | { 165 | return CL_INVALID_VALUE; 166 | } 167 | // set num_platforms to 0 and set all platform pointers to NULL 168 | if (num_platforms) 169 | { 170 | *num_platforms = 0; 171 | } 172 | for (i = 0; i < num_entries && platforms; ++i) 173 | { 174 | platforms[i] = NULL; 175 | } 176 | // return error if we have no platforms 177 | if (!khrIcdVendors) 178 | { 179 | return CL_PLATFORM_NOT_FOUND_KHR; 180 | } 181 | // otherwise enumerate all platforms 182 | for (vendor = khrIcdVendors; vendor; vendor = vendor->next) 183 | { 184 | if (num_entries && platforms) 185 | { 186 | *(platforms++) = vendor->platform; 187 | --num_entries; 188 | } 189 | if (num_platforms) 190 | { 191 | ++(*num_platforms); 192 | } 193 | } 194 | return CL_SUCCESS; 195 | } 196 | 197 | cl_int CL_API_CALL clGetPlatformIDs_disp( 198 | cl_uint num_entries, 199 | cl_platform_id* platforms, 200 | cl_uint* num_platforms) 201 | { 202 | return clGetPlatformIDs_body( 203 | num_entries, 204 | platforms, 205 | num_platforms); 206 | } 207 | 208 | CL_API_ENTRY cl_int CL_API_CALL clGetPlatformIDs( 209 | cl_uint num_entries, 210 | cl_platform_id* platforms, 211 | cl_uint* num_platforms) 212 | { 213 | // initialize the platforms (in case they have not been already) 214 | khrIcdInitialize(); 215 | 216 | #if defined(CL_ENABLE_LAYERS) 217 | if (khrFirstLayer) 218 | return khrFirstLayer->dispatch.clGetPlatformIDs( 219 | num_entries, 220 | platforms, 221 | num_platforms); 222 | #endif // defined(CL_ENABLE_LAYERS) 223 | return clGetPlatformIDs_body( 224 | num_entries, 225 | platforms, 226 | num_platforms); 227 | } 228 | 229 | static inline void* clGetExtensionFunctionAddress_body( 230 | const char* function_name) 231 | { 232 | void* function_address = NULL; 233 | size_t function_name_length = 0; 234 | KHRicdVendor* vendor = NULL; 235 | 236 | KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(function_name, NULL); 237 | 238 | // check if this is an ICD-aware extension 239 | function_address = khrIcdGetExtensionFunctionAddress(function_name); 240 | if (function_address) 241 | { 242 | return function_address; 243 | } 244 | 245 | // fall back to vendor extension detection 246 | function_name_length = strlen(function_name); 247 | for (vendor = khrIcdVendors; vendor; vendor = vendor->next) 248 | { 249 | size_t vendor_suffix_length = strlen(vendor->suffix); 250 | if (vendor_suffix_length <= function_name_length && 251 | vendor_suffix_length > 0) 252 | { 253 | const char* function_suffix = 254 | function_name + function_name_length - vendor_suffix_length; 255 | if (!strcmp(function_suffix, vendor->suffix)) 256 | { 257 | return vendor->clGetExtensionFunctionAddress(function_name); 258 | } 259 | } 260 | } 261 | 262 | return NULL; 263 | } 264 | 265 | void* CL_API_CALL clGetExtensionFunctionAddress_disp( 266 | const char* function_name) 267 | { 268 | return clGetExtensionFunctionAddress_body( 269 | function_name); 270 | } 271 | 272 | CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddress( 273 | const char* function_name) 274 | { 275 | // make sure the ICD is initialized 276 | khrIcdInitialize(); 277 | 278 | #if defined(CL_ENABLE_LAYERS) 279 | if (khrFirstLayer) 280 | return khrFirstLayer->dispatch.clGetExtensionFunctionAddress( 281 | function_name); 282 | #endif // defined(CL_ENABLE_LAYERS) 283 | return clGetExtensionFunctionAddress_body( 284 | function_name); 285 | } 286 | 287 | static inline void* clGetExtensionFunctionAddressForPlatform_body( 288 | cl_platform_id platform, 289 | const char* function_name) 290 | { 291 | void* function_address = NULL; 292 | 293 | KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(function_name, NULL); 294 | 295 | // check if this is an ICD-aware extension 296 | function_address = khrIcdGetExtensionFunctionAddress(function_name); 297 | if (function_address) 298 | { 299 | return function_address; 300 | } 301 | 302 | // This is not an ICD-aware extension, so call into the implementation 303 | // to get the extension function address. 304 | 305 | KHR_ICD_VALIDATE_HANDLE_RETURN_ERROR(platform, NULL); 306 | return KHR_ICD2_DISPATCH(platform)->clGetExtensionFunctionAddressForPlatform( 307 | platform, 308 | function_name); 309 | } 310 | 311 | void* CL_API_CALL clGetExtensionFunctionAddressForPlatform_disp( 312 | cl_platform_id platform, 313 | const char* function_name) 314 | { 315 | return clGetExtensionFunctionAddressForPlatform_body( 316 | platform, 317 | function_name); 318 | } 319 | 320 | CL_API_ENTRY void* CL_API_CALL clGetExtensionFunctionAddressForPlatform( 321 | cl_platform_id platform, 322 | const char* function_name) 323 | { 324 | // make sure the ICD is initialized 325 | khrIcdInitialize(); 326 | #if defined(CL_ENABLE_LAYERS) 327 | if (khrFirstLayer) 328 | return khrFirstLayer->dispatch.clGetExtensionFunctionAddressForPlatform( 329 | platform, 330 | function_name); 331 | #endif // defined(CL_ENABLE_LAYERS) 332 | return clGetExtensionFunctionAddressForPlatform_body( 333 | platform, 334 | function_name); 335 | } 336 | 337 | #ifdef __cplusplus 338 | } 339 | #endif 340 | -------------------------------------------------------------------------------- /loader/icd_dispatch.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef _ICD_DISPATCH_H_ 20 | #define _ICD_DISPATCH_H_ 21 | 22 | #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS 23 | #define CL_USE_DEPRECATED_OPENCL_1_0_APIS 24 | #endif 25 | 26 | #ifndef CL_USE_DEPRECATED_OPENCL_1_1_APIS 27 | #define CL_USE_DEPRECATED_OPENCL_1_1_APIS 28 | #endif 29 | 30 | #ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS 31 | #define CL_USE_DEPRECATED_OPENCL_1_2_APIS 32 | #endif 33 | 34 | #ifndef CL_USE_DEPRECATED_OPENCL_2_0_APIS 35 | #define CL_USE_DEPRECATED_OPENCL_2_0_APIS 36 | #endif 37 | 38 | #ifndef CL_USE_DEPRECATED_OPENCL_2_1_APIS 39 | #define CL_USE_DEPRECATED_OPENCL_2_1_APIS 40 | #endif 41 | 42 | #ifndef CL_USE_DEPRECATED_OPENCL_2_2_APIS 43 | #define CL_USE_DEPRECATED_OPENCL_2_2_APIS 44 | #endif 45 | 46 | // cl.h 47 | #include 48 | 49 | // cl_gl.h and required files 50 | #ifdef _WIN32 51 | #include 52 | #include 53 | #include 54 | #include 55 | #include 56 | #include 57 | #endif 58 | #include 59 | #include 60 | #include 61 | #include 62 | #include "cl_khr_icd2.h" 63 | 64 | #if defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) 65 | 66 | extern void khrIcd2PopulateDispatchTable( 67 | cl_platform_id platform, 68 | clIcdGetFunctionAddressForPlatformKHR_fn p_clIcdGetFunctionAddressForPlatform, 69 | struct _cl_icd_dispatch* dispatch); 70 | 71 | struct KHRDisp 72 | { 73 | struct _cl_icd_dispatch dispatch; 74 | }; 75 | 76 | #define KHR_ICD2_HAS_TAG(object) \ 77 | (((intptr_t)((object)->dispatch->clGetPlatformIDs)) == CL_ICD2_TAG_KHR) 78 | 79 | #define KHR_ICD2_DISPATCH(object) \ 80 | (KHR_ICD2_HAS_TAG(object) ? \ 81 | &(object)->dispData->dispatch : \ 82 | (object)->dispatch) 83 | 84 | #define KHR_ICD_OBJECT_BODY { \ 85 | cl_icd_dispatch *dispatch; \ 86 | struct KHRDisp *dispData; \ 87 | } 88 | 89 | #else // ! defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) 90 | 91 | #define KHR_ICD2_DISPATCH(object) ((object)->dispatch) 92 | 93 | #define KHR_ICD_OBJECT_BODY { \ 94 | cl_icd_dispatch *dispatch; \ 95 | } 96 | 97 | #endif // defined(CL_ENABLE_LOADER_MANAGED_DISPATCH) 98 | 99 | /* 100 | * 101 | * vendor dispatch table structure 102 | * 103 | */ 104 | 105 | struct _cl_platform_id 106 | KHR_ICD_OBJECT_BODY; 107 | 108 | struct _cl_device_id 109 | KHR_ICD_OBJECT_BODY; 110 | 111 | struct _cl_context 112 | KHR_ICD_OBJECT_BODY; 113 | 114 | struct _cl_command_queue 115 | KHR_ICD_OBJECT_BODY; 116 | 117 | struct _cl_mem 118 | KHR_ICD_OBJECT_BODY; 119 | 120 | struct _cl_program 121 | KHR_ICD_OBJECT_BODY; 122 | 123 | struct _cl_kernel 124 | KHR_ICD_OBJECT_BODY; 125 | 126 | struct _cl_event 127 | KHR_ICD_OBJECT_BODY; 128 | 129 | struct _cl_sampler 130 | KHR_ICD_OBJECT_BODY; 131 | 132 | #endif // _ICD_DISPATCH_H_ 133 | 134 | -------------------------------------------------------------------------------- /loader/icd_envvars.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef _ICD_ENVVARS_H_ 20 | #define _ICD_ENVVARS_H_ 21 | 22 | char *khrIcd_getenv(const char *name); 23 | char *khrIcd_secure_getenv(const char *name); 24 | void khrIcd_free_getenv(char *val); 25 | 26 | #endif 27 | -------------------------------------------------------------------------------- /loader/icd_platform.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef _ICD_PLATFORM_H_ 20 | #define _ICD_PLATFORM_H_ 21 | 22 | #if defined(__linux__) || defined(__APPLE__) || defined(__FreeBSD__) || defined(__QNXNTO__) 23 | 24 | #define PATH_SEPARATOR ':' 25 | #define DIRECTORY_SYMBOL '/' 26 | #ifdef __ANDROID__ 27 | #define ICD_VENDOR_PATH "/system/vendor/Khronos/OpenCL/vendors" 28 | #define LAYER_PATH "/system/vendor/Khronos/OpenCL/layers" 29 | #else 30 | #define ICD_VENDOR_PATH "/etc/OpenCL/vendors" 31 | #define LAYER_PATH "/etc/OpenCL/layers" 32 | #endif // ANDROID 33 | 34 | #elif defined(_WIN32) 35 | 36 | #define PATH_SEPARATOR ';' 37 | #define DIRECTORY_SYMBOL '\\' 38 | 39 | #else 40 | #error Unknown OS! 41 | #endif 42 | 43 | #ifdef __MINGW32__ 44 | #if !defined(_WIN32_WINNT) || (_WIN32_WINNT < 0x0600) 45 | #undef _WIN32_WINNT 46 | #define _WIN32_WINNT 0x0600 47 | #endif 48 | #endif // __MINGW32__ 49 | 50 | #endif 51 | -------------------------------------------------------------------------------- /loader/icd_version.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef _ICD_VERSION_H_ 20 | #define _ICD_VERSION_H_ 21 | 22 | #define OPENCL_ICD_LOADER_NAME_STRING "Khronos OpenCL ICD Loader" 23 | #define OPENCL_ICD_LOADER_VENDOR_STRING "Khronos Group" 24 | 25 | #define OPENCL_ICD_LOADER_VAL(_v) #_v 26 | #define OPENCL_ICD_LOADER_TOSTRING(_d) OPENCL_ICD_LOADER_VAL(_d) 27 | #define OPENCL_ICD_LOADER_VERSION_STRING \ 28 | OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_MAJOR) "." \ 29 | OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_MINOR) "." \ 30 | OPENCL_ICD_LOADER_TOSTRING(OPENCL_ICD_LOADER_VERSION_REV) 31 | 32 | #if CL_TARGET_OPENCL_VERSION == 100 33 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "1.0" 34 | #endif 35 | #if CL_TARGET_OPENCL_VERSION == 110 36 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "1.1" 37 | #endif 38 | #if CL_TARGET_OPENCL_VERSION == 120 39 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "1.2" 40 | #endif 41 | #if CL_TARGET_OPENCL_VERSION == 200 42 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "2.0" 43 | #endif 44 | #if CL_TARGET_OPENCL_VERSION == 210 45 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "2.1" 46 | #endif 47 | #if CL_TARGET_OPENCL_VERSION == 220 48 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "2.2" 49 | #endif 50 | #if CL_TARGET_OPENCL_VERSION == 300 51 | #define OPENCL_ICD_LOADER_OCL_VERSION_NUMBER "3.0" 52 | #endif 53 | 54 | #define OPENCL_ICD_LOADER_OCL_VERSION_STRING \ 55 | "OpenCL " OPENCL_ICD_LOADER_OCL_VERSION_NUMBER 56 | 57 | #endif 58 | -------------------------------------------------------------------------------- /loader/linux/icd_exports.map: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | OPENCL_1.0 { 20 | global: 21 | clBuildProgram; 22 | clCreateBuffer; 23 | clCreateCommandQueue; 24 | clCreateContext; 25 | clCreateContextFromType; 26 | clCreateFromGLBuffer; 27 | clCreateFromGLRenderbuffer; 28 | clCreateFromGLTexture2D; 29 | clCreateFromGLTexture3D; 30 | clCreateImage2D; 31 | clCreateImage3D; 32 | clCreateKernel; 33 | clCreateKernelsInProgram; 34 | clCreateProgramWithBinary; 35 | clCreateProgramWithSource; 36 | clCreateSampler; 37 | clEnqueueAcquireGLObjects; 38 | clEnqueueBarrier; 39 | clEnqueueCopyBuffer; 40 | clEnqueueCopyBufferToImage; 41 | clEnqueueCopyImage; 42 | clEnqueueCopyImageToBuffer; 43 | clEnqueueMapBuffer; 44 | clEnqueueMapImage; 45 | clEnqueueMarker; 46 | clEnqueueNDRangeKernel; 47 | clEnqueueNativeKernel; 48 | clEnqueueReadBuffer; 49 | clEnqueueReadImage; 50 | clEnqueueReleaseGLObjects; 51 | clEnqueueTask; 52 | clEnqueueUnmapMemObject; 53 | clEnqueueWaitForEvents; 54 | clEnqueueWriteBuffer; 55 | clEnqueueWriteImage; 56 | clFinish; 57 | clFlush; 58 | clGetCommandQueueInfo; 59 | clGetContextInfo; 60 | clGetDeviceIDs; 61 | clGetDeviceInfo; 62 | clGetEventInfo; 63 | clGetEventProfilingInfo; 64 | clGetExtensionFunctionAddress; 65 | clGetGLObjectInfo; 66 | clGetGLTextureInfo; 67 | clGetImageInfo; 68 | clGetKernelInfo; 69 | clGetKernelWorkGroupInfo; 70 | clGetMemObjectInfo; 71 | clGetPlatformIDs; 72 | clGetPlatformInfo; 73 | clGetProgramBuildInfo; 74 | clGetProgramInfo; 75 | clGetSamplerInfo; 76 | clGetSupportedImageFormats; 77 | clReleaseCommandQueue; 78 | clReleaseContext; 79 | clReleaseEvent; 80 | clReleaseKernel; 81 | clReleaseMemObject; 82 | clReleaseProgram; 83 | clReleaseSampler; 84 | clRetainCommandQueue; 85 | clRetainContext; 86 | clRetainEvent; 87 | clRetainKernel; 88 | clRetainMemObject; 89 | clRetainProgram; 90 | clRetainSampler; 91 | clSetCommandQueueProperty; 92 | clSetKernelArg; 93 | clUnloadCompiler; 94 | clWaitForEvents; 95 | 96 | local: 97 | /* Everything else is local to ICD. */ 98 | *; 99 | }; 100 | 101 | OPENCL_1.1 { 102 | global: 103 | clCreateSubBuffer; 104 | clCreateUserEvent; 105 | clEnqueueCopyBufferRect; 106 | clEnqueueReadBufferRect; 107 | clEnqueueWriteBufferRect; 108 | clSetEventCallback; 109 | clSetMemObjectDestructorCallback; 110 | clSetUserEventStatus; 111 | } OPENCL_1.0; 112 | 113 | OPENCL_1.2 { 114 | global: 115 | clCompileProgram; 116 | clCreateFromGLTexture; 117 | clCreateImage; 118 | clCreateProgramWithBuiltInKernels; 119 | clCreateSubDevices; 120 | clEnqueueBarrierWithWaitList; 121 | clEnqueueFillBuffer; 122 | clEnqueueFillImage; 123 | clEnqueueMarkerWithWaitList; 124 | clEnqueueMigrateMemObjects; 125 | clGetExtensionFunctionAddressForPlatform; 126 | clGetKernelArgInfo; 127 | clLinkProgram; 128 | clReleaseDevice; 129 | clRetainDevice; 130 | clUnloadPlatformCompiler; 131 | } OPENCL_1.1; 132 | 133 | OPENCL_2.0 { 134 | global: 135 | clCreateCommandQueueWithProperties; 136 | clCreatePipe; 137 | clGetPipeInfo; 138 | clSVMAlloc; 139 | clSVMFree; 140 | clEnqueueSVMFree; 141 | clEnqueueSVMMemcpy; 142 | clEnqueueSVMMemFill; 143 | clEnqueueSVMMap; 144 | clEnqueueSVMUnmap; 145 | clCreateSamplerWithProperties; 146 | clSetKernelArgSVMPointer; 147 | clSetKernelExecInfo; 148 | } OPENCL_1.2; 149 | 150 | OPENCL_2.1 { 151 | global: 152 | clCloneKernel; 153 | clCreateProgramWithIL; 154 | clEnqueueSVMMigrateMem; 155 | clGetDeviceAndHostTimer; 156 | clGetHostTimer; 157 | clGetKernelSubGroupInfo; 158 | clSetDefaultDeviceCommandQueue; 159 | } OPENCL_2.0; 160 | 161 | OPENCL_2.2 { 162 | global: 163 | clSetProgramReleaseCallback; 164 | clSetProgramSpecializationConstant; 165 | } OPENCL_2.1; 166 | 167 | OPENCL_3.0 { 168 | global: 169 | clCreateBufferWithProperties; 170 | clCreateImageWithProperties; 171 | clSetContextDestructorCallback; 172 | } OPENCL_2.2; 173 | -------------------------------------------------------------------------------- /loader/linux/icd_linux.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include "icd.h" 20 | #include "icd_envvars.h" 21 | 22 | #include 23 | #include 24 | #include 25 | #include 26 | #include 27 | #include 28 | #include 29 | #include 30 | #include 31 | 32 | static pthread_once_t initialized = PTHREAD_ONCE_INIT; 33 | 34 | /* 35 | * 36 | * Vendor enumeration functions 37 | * 38 | */ 39 | 40 | typedef void khrIcdFileAdd(const char *); 41 | 42 | static inline void khrIcdOsDirEntryValidateAndAdd(const char *d_name, const char *path, 43 | const char *extension, khrIcdFileAdd addFunc) 44 | { 45 | struct stat statBuff; 46 | char* fileName = NULL; 47 | 48 | // make sure the file name ends in `extension` (eg. .icd, or .lay) 49 | if (strlen(extension) > strlen(d_name)) 50 | { 51 | return; 52 | } 53 | if (strcmp(d_name + strlen(d_name) - strlen(extension), extension)) 54 | { 55 | return; 56 | } 57 | 58 | // allocate space for the full path of the vendor library name 59 | fileName = malloc(strlen(d_name) + strlen(path) + 2); 60 | if (!fileName) 61 | { 62 | KHR_ICD_TRACE("Failed allocate space for ICD file path\n"); 63 | return; 64 | } 65 | sprintf(fileName, "%s/%s", path, d_name); 66 | 67 | if (stat(fileName, &statBuff)) 68 | { 69 | KHR_ICD_TRACE("Failed stat for: %s, continuing\n", fileName); 70 | free(fileName); 71 | return; 72 | } 73 | 74 | if (S_ISREG(statBuff.st_mode) || S_ISLNK(statBuff.st_mode)) 75 | { 76 | FILE *fin = NULL; 77 | char* buffer = NULL; 78 | long bufferSize = 0; 79 | 80 | // open the file and read its contents 81 | fin = fopen(fileName, "r"); 82 | if (!fin) 83 | { 84 | free(fileName); 85 | return; 86 | } 87 | fseek(fin, 0, SEEK_END); 88 | bufferSize = ftell(fin); 89 | 90 | buffer = malloc(bufferSize+1); 91 | if (!buffer) 92 | { 93 | free(fileName); 94 | fclose(fin); 95 | return; 96 | } 97 | memset(buffer, 0, bufferSize+1); 98 | fseek(fin, 0, SEEK_SET); 99 | if (bufferSize != (long)fread(buffer, 1, bufferSize, fin)) 100 | { 101 | free(fileName); 102 | free(buffer); 103 | fclose(fin); 104 | return; 105 | } 106 | // ignore a newline at the end of the file 107 | if (buffer[bufferSize-1] == '\n') buffer[bufferSize-1] = '\0'; 108 | 109 | // load the string read from the file 110 | addFunc(buffer); 111 | 112 | free(fileName); 113 | free(buffer); 114 | fclose(fin); 115 | } 116 | else 117 | { 118 | KHR_ICD_TRACE("File %s is not a regular file nor symbolic link, continuing\n", fileName); 119 | free(fileName); 120 | } 121 | } 122 | 123 | struct dirElem 124 | { 125 | char *d_name; 126 | unsigned char d_type; 127 | }; 128 | 129 | static int compareDirElem(const void *a, const void *b) 130 | { 131 | // sort files the same way libc alpahnumerically sorts directory entries. 132 | return strcoll(((const struct dirElem *)a)->d_name, ((const struct dirElem *)b)->d_name); 133 | } 134 | 135 | static inline void khrIcdOsDirEnumerate(const char *path, const char *env, 136 | const char *extension, 137 | khrIcdFileAdd addFunc, int bSort) 138 | { 139 | DIR *dir = NULL; 140 | char* envPath = NULL; 141 | 142 | envPath = khrIcd_secure_getenv(env); 143 | if (NULL != envPath) 144 | { 145 | path = envPath; 146 | } 147 | 148 | dir = opendir(path); 149 | if (NULL == dir) 150 | { 151 | KHR_ICD_TRACE("Failed to open path %s, continuing\n", path); 152 | } 153 | else 154 | { 155 | struct dirent *dirEntry = NULL; 156 | 157 | // attempt to load all files in the directory 158 | if (bSort) { 159 | // store the entries name and type in a buffer for sorting 160 | size_t sz = 0; 161 | size_t elemCount = 0; 162 | size_t elemAlloc = 0; 163 | struct dirElem *dirElems = NULL; 164 | struct dirElem *newDirElems = NULL; 165 | const size_t startupAlloc = 8; 166 | 167 | // start with a small buffer 168 | dirElems = (struct dirElem *)malloc(startupAlloc*sizeof(struct dirElem)); 169 | if (NULL != dirElems) { 170 | elemAlloc = startupAlloc; 171 | for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) ) { 172 | char *nameCopy = NULL; 173 | 174 | if (elemCount + 1 > elemAlloc) { 175 | // double buffer size if necessary and possible 176 | if (elemAlloc >= UINT_MAX/2) 177 | break; 178 | newDirElems = (struct dirElem *)realloc(dirElems, elemAlloc*2*sizeof(struct dirElem)); 179 | if (NULL == newDirElems) 180 | break; 181 | dirElems = newDirElems; 182 | elemAlloc *= 2; 183 | } 184 | sz = strlen(dirEntry->d_name) + 1; 185 | nameCopy = (char *)malloc(sz); 186 | if (NULL == nameCopy) 187 | break; 188 | memcpy(nameCopy, dirEntry->d_name, sz); 189 | dirElems[elemCount].d_name = nameCopy; 190 | #if defined(__QNXNTO__) 191 | dirElems[elemCount].d_type = _DEXTRA_FIRST(dirEntry)->d_type; 192 | #else 193 | dirElems[elemCount].d_type = dirEntry->d_type; 194 | #endif 195 | elemCount++; 196 | } 197 | qsort(dirElems, elemCount, sizeof(struct dirElem), compareDirElem); 198 | for (struct dirElem *elem = dirElems; elem < dirElems + elemCount; ++elem) { 199 | khrIcdOsDirEntryValidateAndAdd(elem->d_name, path, extension, addFunc); 200 | free(elem->d_name); 201 | } 202 | free(dirElems); 203 | } 204 | } else 205 | // use system provided ordering 206 | for (dirEntry = readdir(dir); dirEntry; dirEntry = readdir(dir) ) 207 | khrIcdOsDirEntryValidateAndAdd(dirEntry->d_name, path, extension, addFunc); 208 | 209 | closedir(dir); 210 | } 211 | 212 | if (NULL != envPath) 213 | { 214 | khrIcd_free_getenv(envPath); 215 | } 216 | } 217 | 218 | // go through the list of vendors in the two configuration files 219 | void khrIcdOsVendorsEnumerate(void) 220 | { 221 | khrIcdInitializeTrace(); 222 | khrIcdVendorsEnumerateEnv(); 223 | 224 | khrIcdOsDirEnumerate(ICD_VENDOR_PATH, "OCL_ICD_VENDORS", ".icd", khrIcdVendorAdd, 0); 225 | 226 | #if defined(CL_ENABLE_LAYERS) 227 | // system layers should be closer to the driver 228 | khrIcdOsDirEnumerate(LAYER_PATH, "OPENCL_LAYER_PATH", ".lay", khrIcdLayerAdd, 1); 229 | 230 | khrIcdLayersEnumerateEnv(); 231 | #endif // defined(CL_ENABLE_LAYERS) 232 | } 233 | 234 | // go through the list of vendors only once 235 | void khrIcdOsVendorsEnumerateOnce(void) 236 | { 237 | pthread_once(&initialized, khrIcdOsVendorsEnumerate); 238 | } 239 | 240 | /* 241 | * 242 | * Dynamic library loading functions 243 | * 244 | */ 245 | 246 | // dynamically load a library. returns NULL on failure 247 | void *khrIcdOsLibraryLoad(const char *libraryName) 248 | { 249 | void* ret = dlopen (libraryName, RTLD_NOW); 250 | if (NULL == ret) 251 | { 252 | KHR_ICD_TRACE("Failed to load driver because %s.\n", dlerror()); 253 | } 254 | return ret; 255 | } 256 | 257 | // get a function pointer from a loaded library. returns NULL on failure. 258 | void *khrIcdOsLibraryGetFunctionAddress(void *library, const char *functionName) 259 | { 260 | return dlsym(library, functionName); 261 | } 262 | 263 | // unload a library 264 | void khrIcdOsLibraryUnload(void *library) 265 | { 266 | dlclose(library); 267 | } 268 | -------------------------------------------------------------------------------- /loader/linux/icd_linux_envvars.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | // for secure_getenv(): 20 | #ifndef _GNU_SOURCE 21 | #define _GNU_SOURCE 22 | #endif 23 | 24 | #include "icd_cmake_config.h" 25 | 26 | #include 27 | #include 28 | 29 | char *khrIcd_getenv(const char *name) { 30 | // No allocation of memory necessary for Linux. 31 | return getenv(name); 32 | } 33 | 34 | char *khrIcd_secure_getenv(const char *name) { 35 | #if defined(__APPLE__) || defined(__QNXNTO__) 36 | // Apple does not appear to have a secure getenv implementation. 37 | // The main difference between secure getenv and getenv is that secure getenv 38 | // returns NULL if the process is being run with elevated privileges by a normal user. 39 | // The idea is to prevent the reading of malicious environment variables by a process 40 | // that can do damage. 41 | // This algorithm is derived from glibc code that sets an internal 42 | // variable (__libc_enable_secure) if the process is running under setuid or setgid. 43 | return geteuid() != getuid() || getegid() != getgid() ? NULL : khrIcd_getenv(name); 44 | #else 45 | // Linux 46 | #ifdef HAVE_SECURE_GETENV 47 | return secure_getenv(name); 48 | #elif defined(HAVE___SECURE_GETENV) 49 | return __secure_getenv(name); 50 | #else 51 | #pragma message( \ 52 | "Warning: Falling back to non-secure getenv for environmental lookups! Consider" \ 53 | " updating to a different libc.") 54 | return khrIcd_getenv(name); 55 | #endif 56 | #endif 57 | } 58 | 59 | void khrIcd_free_getenv(char *val) { 60 | // No freeing of memory necessary for Linux, but we should at least touch 61 | // val to get rid of compiler warnings. 62 | (void)val; 63 | } 64 | -------------------------------------------------------------------------------- /loader/windows/OpenCL-mingw-i686.def: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (c) 2022 The Khronos Group Inc. 3 | ; 4 | ; Licensed under the Apache License, Version 2.0 (the "License"); 5 | ; you may not use this file except in compliance with the License. 6 | ; You may obtain a copy of the License at 7 | ; 8 | ; http://www.apache.org/licenses/LICENSE-2.0 9 | ; 10 | ; Unless required by applicable law or agreed to in writing, software 11 | ; distributed under the License is distributed on an "AS IS" BASIS, 12 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | ; See the License for the specific language governing permissions and 14 | ; limitations under the License. 15 | ; 16 | ; OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | 18 | EXPORTS 19 | 20 | ; 21 | ; Note: This is a special .def file that should only be needed for i686 22 | ; (32-bit) mingw builds. In this case we need to export the stdcall- 23 | ; decorated functions. In all other cases we can use the standard .def 24 | ; file that does not have decorated functions. 25 | ; 26 | 27 | ; OpenCL 1.0 API 28 | clBuildProgram@24 == clBuildProgram 29 | clCreateBuffer@24 == clCreateBuffer 30 | clCreateCommandQueue@20 == clCreateCommandQueue 31 | clCreateContext@24 == clCreateContext 32 | clCreateContextFromType@24 == clCreateContextFromType 33 | clCreateFromGLBuffer@20 == clCreateFromGLBuffer 34 | clCreateFromGLRenderbuffer@20 == clCreateFromGLRenderbuffer 35 | clCreateFromGLTexture2D@28 == clCreateFromGLTexture2D 36 | clCreateFromGLTexture3D@28 == clCreateFromGLTexture3D 37 | clCreateImage2D@36 == clCreateImage2D 38 | clCreateImage3D@44 == clCreateImage3D 39 | clCreateKernel@12 == clCreateKernel 40 | clCreateKernelsInProgram@16 == clCreateKernelsInProgram 41 | clCreateProgramWithBinary@28 == clCreateProgramWithBinary 42 | clCreateProgramWithSource@20 == clCreateProgramWithSource 43 | clCreateSampler@20 == clCreateSampler 44 | clEnqueueAcquireGLObjects@24 == clEnqueueAcquireGLObjects 45 | clEnqueueBarrier@4 == clEnqueueBarrier 46 | clEnqueueCopyBuffer@36 == clEnqueueCopyBuffer 47 | clEnqueueCopyBufferToImage@36 == clEnqueueCopyBufferToImage 48 | clEnqueueCopyImage@36 == clEnqueueCopyImage 49 | clEnqueueCopyImageToBuffer@36 == clEnqueueCopyImageToBuffer 50 | clEnqueueMapBuffer@44 == clEnqueueMapBuffer 51 | clEnqueueMapImage@52 == clEnqueueMapImage 52 | clEnqueueMarker@8 == clEnqueueMarker 53 | clEnqueueNDRangeKernel@36 == clEnqueueNDRangeKernel 54 | clEnqueueNativeKernel@40 == clEnqueueNativeKernel 55 | clEnqueueReadBuffer@36 == clEnqueueReadBuffer 56 | clEnqueueReadImage@44 == clEnqueueReadImage 57 | clEnqueueReleaseGLObjects@24 == clEnqueueReleaseGLObjects 58 | clEnqueueTask@20 == clEnqueueTask 59 | clEnqueueUnmapMemObject@24 == clEnqueueUnmapMemObject 60 | clEnqueueWaitForEvents@12 == clEnqueueWaitForEvents 61 | clEnqueueWriteBuffer@36 == clEnqueueWriteBuffer 62 | clEnqueueWriteImage@44 == clEnqueueWriteImage 63 | clFinish@4 == clFinish 64 | clFlush@4 == clFlush 65 | clGetCommandQueueInfo@20 == clGetCommandQueueInfo 66 | clGetContextInfo@20 == clGetContextInfo 67 | clGetDeviceIDs@24 == clGetDeviceIDs 68 | clGetDeviceInfo@20 == clGetDeviceInfo 69 | clGetEventInfo@20 == clGetEventInfo 70 | clGetEventProfilingInfo@20 == clGetEventProfilingInfo 71 | clGetExtensionFunctionAddress@4 == clGetExtensionFunctionAddress 72 | clGetGLObjectInfo@12 == clGetGLObjectInfo 73 | clGetGLTextureInfo@20 == clGetGLTextureInfo 74 | clGetImageInfo@20 == clGetImageInfo 75 | clGetKernelInfo@20 == clGetKernelInfo 76 | clGetKernelWorkGroupInfo@24 == clGetKernelWorkGroupInfo 77 | clGetMemObjectInfo@20 == clGetMemObjectInfo 78 | clGetPlatformIDs@12 == clGetPlatformIDs 79 | clGetPlatformInfo@20 == clGetPlatformInfo 80 | clGetProgramBuildInfo@24 == clGetProgramBuildInfo 81 | clGetProgramInfo@20 == clGetProgramInfo 82 | clGetSamplerInfo@20 == clGetSamplerInfo 83 | clGetSupportedImageFormats@28 == clGetSupportedImageFormats 84 | clReleaseCommandQueue@4 == clReleaseCommandQueue 85 | clReleaseContext@4 == clReleaseContext 86 | clReleaseEvent@4 == clReleaseEvent 87 | clReleaseKernel@4 == clReleaseKernel 88 | clReleaseMemObject@4 == clReleaseMemObject 89 | clReleaseProgram@4 == clReleaseProgram 90 | clReleaseSampler@4 == clReleaseSampler 91 | clRetainCommandQueue@4 == clRetainCommandQueue 92 | clRetainContext@4 == clRetainContext 93 | clRetainEvent@4 == clRetainEvent 94 | clRetainKernel@4 == clRetainKernel 95 | clRetainMemObject@4 == clRetainMemObject 96 | clRetainProgram@4 == clRetainProgram 97 | clRetainSampler@4 == clRetainSampler 98 | clSetCommandQueueProperty@20 == clSetCommandQueueProperty 99 | clSetKernelArg@16 == clSetKernelArg 100 | clUnloadCompiler@0 == clUnloadCompiler 101 | clWaitForEvents@8 == clWaitForEvents 102 | 103 | ; OpenCL 1.1 API 104 | clCreateSubBuffer@24 == clCreateSubBuffer 105 | clCreateUserEvent@8 == clCreateUserEvent 106 | clEnqueueCopyBufferRect@52 == clEnqueueCopyBufferRect 107 | clEnqueueReadBufferRect@56 == clEnqueueReadBufferRect 108 | clEnqueueWriteBufferRect@56 == clEnqueueWriteBufferRect 109 | clSetEventCallback@16 == clSetEventCallback 110 | clSetMemObjectDestructorCallback@12 == clSetMemObjectDestructorCallback 111 | clSetUserEventStatus@8 == clSetUserEventStatus 112 | 113 | ; OpenCL 1.2 API 114 | clCompileProgram@36 == clCompileProgram 115 | clCreateFromGLTexture@28 == clCreateFromGLTexture 116 | clCreateImage@28 == clCreateImage 117 | clCreateProgramWithBuiltInKernels@20 == clCreateProgramWithBuiltInKernels 118 | clCreateSubDevices@20 == clCreateSubDevices 119 | clEnqueueBarrierWithWaitList@16 == clEnqueueBarrierWithWaitList 120 | clEnqueueFillBuffer@36 == clEnqueueFillBuffer 121 | clEnqueueFillImage@32 == clEnqueueFillImage 122 | clEnqueueMarkerWithWaitList@16 == clEnqueueMarkerWithWaitList 123 | clEnqueueMigrateMemObjects@32 == clEnqueueMigrateMemObjects 124 | clGetExtensionFunctionAddressForPlatform@8 == clGetExtensionFunctionAddressForPlatform 125 | clGetKernelArgInfo@24 == clGetKernelArgInfo 126 | clLinkProgram@36 == clLinkProgram 127 | clReleaseDevice@4 == clReleaseDevice 128 | clRetainDevice@4 == clRetainDevice 129 | clUnloadPlatformCompiler@4 == clUnloadPlatformCompiler 130 | 131 | ; OpenCL 2.0 API 132 | clCreateCommandQueueWithProperties@16 == clCreateCommandQueueWithProperties 133 | clCreatePipe@28 == clCreatePipe 134 | clCreateSamplerWithProperties@12 == clCreateSamplerWithProperties 135 | clEnqueueSVMFree@32 == clEnqueueSVMFree 136 | clEnqueueSVMMap@36 == clEnqueueSVMMap 137 | clEnqueueSVMMemcpy@32 == clEnqueueSVMMemcpy 138 | clEnqueueSVMMemFill@32 == clEnqueueSVMMemFill 139 | clEnqueueSVMUnmap@20 == clEnqueueSVMUnmap 140 | clGetPipeInfo@20 == clGetPipeInfo 141 | clSetKernelArgSVMPointer@12 == clSetKernelArgSVMPointer 142 | clSetKernelExecInfo@16 == clSetKernelExecInfo 143 | clSVMAlloc@20 == clSVMAlloc 144 | clSVMFree@8 == clSVMFree 145 | 146 | ; OpenCL 2.1 API 147 | clCloneKernel@8 == clCloneKernel 148 | clCreateProgramWithIL@16 == clCreateProgramWithIL 149 | clEnqueueSVMMigrateMem@36 == clEnqueueSVMMigrateMem 150 | clGetDeviceAndHostTimer@12 == clGetDeviceAndHostTimer 151 | clGetHostTimer@8 == clGetHostTimer 152 | clGetKernelSubGroupInfo@32 == clGetKernelSubGroupInfo 153 | clSetDefaultDeviceCommandQueue@12 == clSetDefaultDeviceCommandQueue 154 | 155 | ; OpenCL 2.2 API 156 | clSetProgramReleaseCallback@12 == clSetProgramReleaseCallback 157 | clSetProgramSpecializationConstant@16 == clSetProgramSpecializationConstant 158 | 159 | ; OpenCL 3.0 API 160 | clCreateBufferWithProperties@28 == clCreateBufferWithProperties 161 | clCreateImageWithProperties@32 == clCreateImageWithProperties 162 | clSetContextDestructorCallback@12 == clSetContextDestructorCallback 163 | -------------------------------------------------------------------------------- /loader/windows/OpenCL.def: -------------------------------------------------------------------------------- 1 | ; 2 | ; Copyright (c) 2016-2019 The Khronos Group Inc. 3 | ; 4 | ; Licensed under the Apache License, Version 2.0 (the "License"); 5 | ; you may not use this file except in compliance with the License. 6 | ; You may obtain a copy of the License at 7 | ; 8 | ; http://www.apache.org/licenses/LICENSE-2.0 9 | ; 10 | ; Unless required by applicable law or agreed to in writing, software 11 | ; distributed under the License is distributed on an "AS IS" BASIS, 12 | ; WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | ; See the License for the specific language governing permissions and 14 | ; limitations under the License. 15 | ; 16 | ; OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | 18 | EXPORTS 19 | 20 | ; 21 | ; Note: 22 | ; 23 | ; 1. Functions are grouped into blocks according to the OpenCL API version they 24 | ; were introduced in. 25 | ; 26 | ; 2. Function blocks are sorted in ascending order of the API version. 27 | ; 28 | ; 3. Functions within a block are sorted alphabetically. 29 | ; 30 | 31 | ; OpenCL 1.0 API 32 | clBuildProgram 33 | clCreateBuffer 34 | clCreateCommandQueue 35 | clCreateContext 36 | clCreateContextFromType 37 | clCreateFromGLBuffer 38 | clCreateFromGLRenderbuffer 39 | clCreateFromGLTexture2D 40 | clCreateFromGLTexture3D 41 | clCreateImage2D 42 | clCreateImage3D 43 | clCreateKernel 44 | clCreateKernelsInProgram 45 | clCreateProgramWithBinary 46 | clCreateProgramWithSource 47 | clCreateSampler 48 | clEnqueueAcquireGLObjects 49 | clEnqueueBarrier 50 | clEnqueueCopyBuffer 51 | clEnqueueCopyBufferToImage 52 | clEnqueueCopyImage 53 | clEnqueueCopyImageToBuffer 54 | clEnqueueMapBuffer 55 | clEnqueueMapImage 56 | clEnqueueMarker 57 | clEnqueueNDRangeKernel 58 | clEnqueueNativeKernel 59 | clEnqueueReadBuffer 60 | clEnqueueReadImage 61 | clEnqueueReleaseGLObjects 62 | clEnqueueTask 63 | clEnqueueUnmapMemObject 64 | clEnqueueWaitForEvents 65 | clEnqueueWriteBuffer 66 | clEnqueueWriteImage 67 | clFinish 68 | clFlush 69 | clGetCommandQueueInfo 70 | clGetContextInfo 71 | clGetDeviceIDs 72 | clGetDeviceInfo 73 | clGetEventInfo 74 | clGetEventProfilingInfo 75 | clGetExtensionFunctionAddress 76 | clGetGLObjectInfo 77 | clGetGLTextureInfo 78 | clGetImageInfo 79 | clGetKernelInfo 80 | clGetKernelWorkGroupInfo 81 | clGetMemObjectInfo 82 | clGetPlatformIDs 83 | clGetPlatformInfo 84 | clGetProgramBuildInfo 85 | clGetProgramInfo 86 | clGetSamplerInfo 87 | clGetSupportedImageFormats 88 | clReleaseCommandQueue 89 | clReleaseContext 90 | clReleaseEvent 91 | clReleaseKernel 92 | clReleaseMemObject 93 | clReleaseProgram 94 | clReleaseSampler 95 | clRetainCommandQueue 96 | clRetainContext 97 | clRetainEvent 98 | clRetainKernel 99 | clRetainMemObject 100 | clRetainProgram 101 | clRetainSampler 102 | clSetCommandQueueProperty 103 | clSetKernelArg 104 | clUnloadCompiler 105 | clWaitForEvents 106 | 107 | ; OpenCL 1.1 API 108 | clCreateSubBuffer 109 | clCreateUserEvent 110 | clEnqueueCopyBufferRect 111 | clEnqueueReadBufferRect 112 | clEnqueueWriteBufferRect 113 | clSetEventCallback 114 | clSetMemObjectDestructorCallback 115 | clSetUserEventStatus 116 | 117 | ; OpenCL 1.2 API 118 | clCompileProgram 119 | clCreateFromGLTexture 120 | clCreateImage 121 | clCreateProgramWithBuiltInKernels 122 | clCreateSubDevices 123 | clEnqueueBarrierWithWaitList 124 | clEnqueueFillBuffer 125 | clEnqueueFillImage 126 | clEnqueueMarkerWithWaitList 127 | clEnqueueMigrateMemObjects 128 | clGetExtensionFunctionAddressForPlatform 129 | clGetKernelArgInfo 130 | clLinkProgram 131 | clReleaseDevice 132 | clRetainDevice 133 | clUnloadPlatformCompiler 134 | 135 | ; OpenCL 2.0 API 136 | clCreateCommandQueueWithProperties 137 | clCreatePipe 138 | clCreateSamplerWithProperties 139 | clEnqueueSVMFree 140 | clEnqueueSVMMap 141 | clEnqueueSVMMemcpy 142 | clEnqueueSVMMemFill 143 | clEnqueueSVMUnmap 144 | clGetPipeInfo 145 | clSetKernelArgSVMPointer 146 | clSetKernelExecInfo 147 | clSVMAlloc 148 | clSVMFree 149 | 150 | ; OpenCL 2.1 API 151 | clCloneKernel 152 | clCreateProgramWithIL 153 | clEnqueueSVMMigrateMem 154 | clGetDeviceAndHostTimer 155 | clGetHostTimer 156 | clGetKernelSubGroupInfo 157 | clSetDefaultDeviceCommandQueue 158 | 159 | ; OpenCL 2.2 API 160 | clSetProgramReleaseCallback 161 | clSetProgramSpecializationConstant 162 | 163 | ; OpenCL 3.0 API 164 | clCreateBufferWithProperties 165 | clCreateImageWithProperties 166 | clSetContextDestructorCallback 167 | -------------------------------------------------------------------------------- /loader/windows/OpenCL.rc: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2023 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #ifdef RC_INVOKED 23 | 24 | VS_VERSION_INFO VERSIONINFO 25 | FILEVERSION OPENCL_ICD_LOADER_VERSION_MAJOR,OPENCL_ICD_LOADER_VERSION_MINOR,OPENCL_ICD_LOADER_VERSION_REV,0 26 | PRODUCTVERSION OPENCL_ICD_LOADER_VERSION_MAJOR,OPENCL_ICD_LOADER_VERSION_MINOR,OPENCL_ICD_LOADER_VERSION_REV,0 27 | FILETYPE VFT_DLL 28 | 29 | BEGIN 30 | BLOCK "StringFileInfo" 31 | BEGIN 32 | BLOCK "040904E4" 33 | BEGIN 34 | VALUE "FileDescription" ,"OpenCL Client DLL" 35 | VALUE "ProductName" ,OPENCL_ICD_LOADER_NAME_STRING 36 | VALUE "LegalCopyright" ,L"Copyright \251 The Khronos Group Inc 2016-2023" 37 | VALUE "FileVersion" ,OPENCL_ICD_LOADER_VERSION_STRING ".0" 38 | VALUE "CompanyName" ,OPENCL_ICD_LOADER_VENDOR_STRING 39 | VALUE "InternalName" ,"OpenCL" 40 | VALUE "OriginalFilename","OpenCL.dll" 41 | END 42 | END 43 | 44 | BLOCK "VarFileInfo" 45 | BEGIN 46 | // extend this line for localized versions 47 | VALUE "Translation", 0x0409, 0x04E4 48 | END 49 | END 50 | 51 | #endif 52 | 53 | -------------------------------------------------------------------------------- /loader/windows/adapter.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2019 The Khronos Group Inc. 3 | * Copyright (c) 2019 Valve Corporation 4 | * Copyright (c) 2019 LunarG, Inc. 5 | * 6 | * Licensed under the Apache License, Version 2.0 (the "License"); 7 | * you may not use this file except in compliance with the License. 8 | * You may obtain a copy of the License at 9 | * 10 | * http://www.apache.org/licenses/LICENSE-2.0 11 | * 12 | * Unless required by applicable law or agreed to in writing, software 13 | * distributed under the License is distributed on an "AS IS" BASIS, 14 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 15 | * See the License for the specific language governing permissions and 16 | * limitations under the License. 17 | * 18 | * Author: Lenny Komow 19 | */ 20 | 21 | typedef struct LoaderEnumAdapters2 { 22 | ULONG adapter_count; 23 | struct { 24 | UINT handle; 25 | LUID luid; 26 | ULONG source_count; 27 | BOOL present_move_regions_preferred; 28 | } * adapters; 29 | } LoaderEnumAdapters2; 30 | 31 | typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderEnumAdapters2)(const LoaderEnumAdapters2 *); 32 | 33 | typedef enum AdapterInfoType { 34 | LOADER_QUERY_TYPE_REGISTRY = 48, 35 | } AdapterInfoType; 36 | 37 | typedef struct LoaderQueryAdapterInfo { 38 | UINT handle; 39 | AdapterInfoType type; 40 | VOID *private_data; 41 | UINT private_data_size; 42 | } LoaderQueryAdapterInfo; 43 | 44 | typedef _Check_return_ NTSTATUS(APIENTRY *PFN_LoaderQueryAdapterInfo)(const LoaderQueryAdapterInfo *); 45 | 46 | typedef enum LoaderQueryRegistryType { 47 | LOADER_QUERY_REGISTRY_ADAPTER_KEY = 1, 48 | } LoaderQueryRegistryType; 49 | 50 | typedef enum LoaderQueryRegistryStatus { 51 | LOADER_QUERY_REGISTRY_STATUS_SUCCESS = 0, 52 | LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW = 1, 53 | } LoaderQueryRegistryStatus; 54 | 55 | typedef struct LoaderQueryRegistryFlags { 56 | union { 57 | struct { 58 | UINT translate_path : 1; 59 | UINT mutable_value : 1; 60 | UINT reserved : 30; 61 | }; 62 | UINT value; 63 | }; 64 | } LoaderQueryRegistryFlags; 65 | 66 | typedef struct LoaderQueryRegistryInfo { 67 | LoaderQueryRegistryType query_type; 68 | LoaderQueryRegistryFlags query_flags; 69 | WCHAR value_name[MAX_PATH]; 70 | ULONG value_type; 71 | ULONG physical_adapter_index; 72 | ULONG output_value_size; 73 | LoaderQueryRegistryStatus status; 74 | union { 75 | DWORD output_dword; 76 | UINT64 output_qword; 77 | WCHAR output_string[1]; 78 | BYTE output_binary[1]; 79 | }; 80 | } LoaderQueryRegistryInfo; 81 | -------------------------------------------------------------------------------- /loader/windows/icd_windows.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include 21 | 22 | #ifdef _LP64 23 | #define PRIDW_PREFIX 24 | #define PRIUL_PREFIX 25 | #else 26 | #define PRIDW_PREFIX "l" 27 | #define PRIUL_PREFIX "l" 28 | #endif 29 | #define PRIuDW PRIDW_PREFIX "u" 30 | #define PRIxDW PRIDW_PREFIX "x" 31 | #define PRIuUL PRIUL_PREFIX "u" 32 | #define PRIxUL PRIUL_PREFIX "x" 33 | 34 | #ifdef __cplusplus 35 | extern "C" { 36 | #endif 37 | extern const LUID ZeroLuid; 38 | 39 | BOOL adapterAdd(const char* szName, LUID luid); 40 | 41 | // Do not free the memory returned by this function. 42 | const char* getOpenCLRegKeyName(void); 43 | 44 | #ifdef __cplusplus 45 | } 46 | #endif 47 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_apppackage.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2022 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include "icd_windows_apppackage.h" 21 | 22 | typedef _Check_return_ LONG(WINAPI *PFN_GetPackagesByPackageFamily)( 23 | _In_ PCWSTR packageFamilyName, 24 | _Inout_ UINT32* count, 25 | _Out_writes_opt_(*count) PWSTR* packageFullNames, 26 | _Inout_ UINT32* bufferLength, 27 | _Out_writes_opt_(*bufferLength) WCHAR* buffer 28 | ); 29 | 30 | typedef LONG (WINAPI *PFN_GetPackagePathByFullName)( 31 | _In_ PCWSTR packageFullName, 32 | _Inout_ UINT32* pathLength, 33 | _Out_writes_opt_(*pathLength) PWSTR path 34 | ); 35 | 36 | bool khrIcdOsVendorsEnumerateAppPackage(void) 37 | { 38 | bool ret = false; 39 | WCHAR *buffer = NULL; 40 | PWSTR *packages = NULL; 41 | 42 | HMODULE h = LoadLibraryA("kernel32.dll"); 43 | if (h == NULL) 44 | return ret; 45 | 46 | PFN_GetPackagesByPackageFamily pGetPackagesByPackageFamily = 47 | (PFN_GetPackagesByPackageFamily)(void*)GetProcAddress(h, "GetPackagesByPackageFamily"); 48 | if (!pGetPackagesByPackageFamily) 49 | { 50 | KHR_ICD_TRACE("GetProcAddress failed for GetPackagesByPackageFamily\n"); 51 | goto cleanup; 52 | } 53 | 54 | PFN_GetPackagePathByFullName pGetPackagePathByFullName = 55 | (PFN_GetPackagePathByFullName)(void*)GetProcAddress(h, "GetPackagePathByFullName"); 56 | if (!pGetPackagePathByFullName) 57 | { 58 | KHR_ICD_TRACE("GetProcAddress failed for GetPackagePathByFullName\n"); 59 | goto cleanup; 60 | } 61 | 62 | UINT32 numPackages = 0, bufferLength = 0; 63 | PCWSTR familyName = L"Microsoft.D3DMappingLayers_8wekyb3d8bbwe"; 64 | if (ERROR_INSUFFICIENT_BUFFER != pGetPackagesByPackageFamily(familyName, 65 | &numPackages, NULL, 66 | &bufferLength, NULL) || 67 | numPackages == 0 || bufferLength == 0) 68 | { 69 | KHR_ICD_TRACE("Failed to find mapping layers packages by family name\n"); 70 | goto cleanup; 71 | } 72 | 73 | buffer = malloc(sizeof(WCHAR) * bufferLength); 74 | packages = malloc(sizeof(PWSTR) * numPackages); 75 | if (!buffer || !packages) 76 | { 77 | KHR_ICD_TRACE("Failed to allocate memory for package names\n"); 78 | goto cleanup; 79 | } 80 | 81 | if (ERROR_SUCCESS != pGetPackagesByPackageFamily(familyName, 82 | &numPackages, packages, 83 | &bufferLength, buffer)) 84 | { 85 | KHR_ICD_TRACE("Failed to get mapping layers package full names\n"); 86 | goto cleanup; 87 | } 88 | 89 | UINT32 pathLength = 0; 90 | WCHAR path[MAX_PATH]; 91 | if (ERROR_INSUFFICIENT_BUFFER != pGetPackagePathByFullName(packages[0], &pathLength, NULL) || 92 | pathLength > MAX_PATH || 93 | ERROR_SUCCESS != pGetPackagePathByFullName(packages[0], &pathLength, path)) 94 | { 95 | KHR_ICD_TRACE("Failed to get mapping layers package path length\n"); 96 | goto cleanup; 97 | } 98 | 99 | #if defined(_M_AMD64) 100 | #define PLATFORM_PATH L"x64" 101 | #elif defined(_M_ARM) 102 | #define PLATFORM_PATH L"arm" 103 | #elif defined(_M_ARM64) 104 | #define PLATFORM_PATH L"arm64" 105 | #elif defined(_M_IX86) 106 | #define PLATFORM_PATH L"x86" 107 | #endif 108 | 109 | wchar_t dllPath[MAX_PATH]; 110 | wcscpy_s(dllPath, MAX_PATH, path); 111 | wcscat_s(dllPath, MAX_PATH, L"\\" PLATFORM_PATH L"\\OpenCLOn12.dll"); 112 | 113 | char narrowDllPath[MAX_PATH]; 114 | WideCharToMultiByte(CP_UTF8, 0, dllPath, -1, narrowDllPath, MAX_PATH, NULL, NULL); 115 | 116 | ret = adapterAdd(narrowDllPath, ZeroLuid); 117 | 118 | cleanup: 119 | FreeLibrary(h); 120 | free(buffer); 121 | free(packages); 122 | return ret; 123 | } 124 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_apppackage.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include "icd_windows.h" 21 | 22 | bool khrIcdOsVendorsEnumerateAppPackage(void); 23 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_dxgk.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include "icd.h" 20 | #include "icd_windows_dxgk.h" 21 | 22 | #include 23 | #include "adapter.h" 24 | 25 | #ifndef NTSTATUS 26 | typedef LONG NTSTATUS; 27 | #define STATUS_SUCCESS ((NTSTATUS)0x00000000L) 28 | #define STATUS_BUFFER_TOO_SMALL ((NTSTATUS)0xC0000023) 29 | #define NT_SUCCESS(status) (((NTSTATUS)(status)) >= 0) 30 | #endif 31 | 32 | bool khrIcdOsVendorsEnumerateDXGK(void) 33 | { 34 | bool ret = false; 35 | int result = 0; 36 | 37 | // Get handle to GDI Runtime 38 | HMODULE h = LoadLibraryA("gdi32.dll"); 39 | if (h == NULL) 40 | return ret; 41 | 42 | if(GetProcAddress(h, "D3DKMTSubmitPresentBltToHwQueue")) // OS Version check 43 | { 44 | LoaderEnumAdapters2 EnumAdapters; 45 | NTSTATUS status = STATUS_SUCCESS; 46 | 47 | EnumAdapters.adapter_count = 0; 48 | EnumAdapters.adapters = NULL; 49 | PFN_LoaderEnumAdapters2 pEnumAdapters2 = (PFN_LoaderEnumAdapters2)(void*)GetProcAddress(h, "D3DKMTEnumAdapters2"); 50 | if (!pEnumAdapters2) 51 | { 52 | KHR_ICD_TRACE("GetProcAddress failed for D3DKMTEnumAdapters2\n"); 53 | goto out; 54 | } 55 | PFN_LoaderQueryAdapterInfo pQueryAdapterInfo = (PFN_LoaderQueryAdapterInfo)(void*)GetProcAddress(h, "D3DKMTQueryAdapterInfo"); 56 | if (!pQueryAdapterInfo) 57 | { 58 | KHR_ICD_TRACE("GetProcAddress failed for D3DKMTQueryAdapterInfo\n"); 59 | goto out; 60 | } 61 | while (1) 62 | { 63 | EnumAdapters.adapter_count = 0; 64 | EnumAdapters.adapters = NULL; 65 | status = pEnumAdapters2(&EnumAdapters); 66 | if (status == STATUS_BUFFER_TOO_SMALL) 67 | { 68 | // Number of Adapters increased between calls, retry; 69 | continue; 70 | } 71 | else if (!NT_SUCCESS(status)) 72 | { 73 | KHR_ICD_TRACE("D3DKMTEnumAdapters2 status != SUCCESS\n"); 74 | goto out; 75 | } 76 | break; 77 | } 78 | EnumAdapters.adapters = malloc(sizeof(*EnumAdapters.adapters)*(EnumAdapters.adapter_count)); 79 | if (EnumAdapters.adapters == NULL) 80 | { 81 | KHR_ICD_TRACE("Allocation failure for adapters buffer\n"); 82 | goto out; 83 | } 84 | status = pEnumAdapters2(&EnumAdapters); 85 | if (!NT_SUCCESS(status)) 86 | { 87 | KHR_ICD_TRACE("D3DKMTEnumAdapters2 status != SUCCESS\n"); 88 | goto out; 89 | } 90 | const char* cszOpenCLRegKeyName = getOpenCLRegKeyName(); 91 | const int szOpenCLRegKeyName = (int)(strlen(cszOpenCLRegKeyName) + 1)*sizeof(cszOpenCLRegKeyName[0]); 92 | for (UINT AdapterIndex = 0; AdapterIndex < EnumAdapters.adapter_count; AdapterIndex++) 93 | { 94 | LoaderQueryRegistryInfo queryArgs = {0}; 95 | LoaderQueryRegistryInfo* pQueryArgs = &queryArgs; 96 | LoaderQueryRegistryInfo* pQueryBuffer = NULL; 97 | queryArgs.query_type = LOADER_QUERY_REGISTRY_ADAPTER_KEY; 98 | queryArgs.query_flags.translate_path = TRUE; 99 | queryArgs.value_type = REG_SZ; 100 | result = MultiByteToWideChar( 101 | CP_UTF8, 102 | 0, 103 | cszOpenCLRegKeyName, 104 | szOpenCLRegKeyName, 105 | queryArgs.value_name, 106 | ARRAYSIZE(queryArgs.value_name)); 107 | if (!result) 108 | { 109 | KHR_ICD_TRACE("MultiByteToWideChar status != SUCCESS\n"); 110 | continue; 111 | } 112 | LoaderQueryAdapterInfo queryAdapterInfo = {0}; 113 | queryAdapterInfo.handle = EnumAdapters.adapters[AdapterIndex].handle; 114 | queryAdapterInfo.type = LOADER_QUERY_TYPE_REGISTRY; 115 | queryAdapterInfo.private_data = &queryArgs; 116 | queryAdapterInfo.private_data_size = sizeof(queryArgs); 117 | status = pQueryAdapterInfo(&queryAdapterInfo); 118 | if (!NT_SUCCESS(status)) 119 | { 120 | // Try a different value type. Some vendors write the key as a multi-string type. 121 | queryArgs.value_type = REG_MULTI_SZ; 122 | status = pQueryAdapterInfo(&queryAdapterInfo); 123 | if (NT_SUCCESS(status)) 124 | { 125 | KHR_ICD_TRACE("Accepting multi-string registry key type\n"); 126 | } 127 | else 128 | { 129 | // Continue trying to get as much info on each adapter as possible. 130 | // It's too late to return FALSE and claim WDDM2_4 enumeration is not available here. 131 | continue; 132 | } 133 | } 134 | if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_BUFFER_OVERFLOW) 135 | { 136 | ULONG queryBufferSize = sizeof(LoaderQueryRegistryInfo) + queryArgs.output_value_size; 137 | pQueryBuffer = malloc(queryBufferSize); 138 | if (pQueryBuffer == NULL) 139 | continue; 140 | memcpy(pQueryBuffer, &queryArgs, sizeof(LoaderQueryRegistryInfo)); 141 | queryAdapterInfo.private_data = pQueryBuffer; 142 | queryAdapterInfo.private_data_size = queryBufferSize; 143 | status = pQueryAdapterInfo(&queryAdapterInfo); 144 | pQueryArgs = pQueryBuffer; 145 | } 146 | if (NT_SUCCESS(status) && pQueryArgs->status == LOADER_QUERY_REGISTRY_STATUS_SUCCESS) 147 | { 148 | char cszLibraryName[MAX_PATH]; 149 | result = WideCharToMultiByte( 150 | CP_UTF8, 151 | 0, 152 | pQueryArgs->output_string, 153 | -1, 154 | cszLibraryName, 155 | MAX_PATH, 156 | NULL, 157 | NULL); 158 | if (!result) 159 | { 160 | KHR_ICD_TRACE("WideCharToMultiByte status != SUCCESS\n"); 161 | } 162 | else 163 | { 164 | ret |= adapterAdd(cszLibraryName, EnumAdapters.adapters[AdapterIndex].luid); 165 | } 166 | } 167 | else if (status == (NTSTATUS)STATUS_INVALID_PARAMETER) 168 | { 169 | free(pQueryBuffer); 170 | goto out; 171 | } 172 | free(pQueryBuffer); 173 | } 174 | out: 175 | free(EnumAdapters.adapters); 176 | } 177 | 178 | FreeLibrary(h); 179 | 180 | return ret; 181 | } 182 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_dxgk.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include "icd_windows.h" 21 | 22 | bool khrIcdOsVendorsEnumerateDXGK(void); 23 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_envvars.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2016-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include 21 | #include 22 | 23 | char *khrIcd_getenv(const char *name) { 24 | char *retVal; 25 | DWORD valSize; 26 | 27 | valSize = GetEnvironmentVariableA(name, NULL, 0); 28 | 29 | // valSize DOES include the null terminator, so for any set variable 30 | // will always be at least 1. If it's 0, the variable wasn't set. 31 | if (valSize == 0) return NULL; 32 | 33 | // Allocate the space necessary for the registry entry 34 | retVal = (char *)malloc(valSize); 35 | 36 | if (NULL != retVal) { 37 | GetEnvironmentVariableA(name, retVal, valSize); 38 | } 39 | 40 | return retVal; 41 | } 42 | 43 | static bool khrIcd_IsHighIntegrityLevel() 44 | { 45 | bool isHighIntegrityLevel = false; 46 | 47 | HANDLE processToken; 48 | if (OpenProcessToken(GetCurrentProcess(), TOKEN_QUERY | TOKEN_QUERY_SOURCE, &processToken)) { 49 | // Maximum possible size of SID_AND_ATTRIBUTES is maximum size of a SID + size of attributes DWORD. 50 | char mandatoryLabelBuffer[SECURITY_MAX_SID_SIZE + sizeof(DWORD)] = {0}; 51 | DWORD bufferSize; 52 | if (GetTokenInformation(processToken, TokenIntegrityLevel, mandatoryLabelBuffer, sizeof(mandatoryLabelBuffer), 53 | &bufferSize) != 0) { 54 | const TOKEN_MANDATORY_LABEL* mandatoryLabel = (const TOKEN_MANDATORY_LABEL*)(mandatoryLabelBuffer); 55 | const DWORD subAuthorityCount = *GetSidSubAuthorityCount(mandatoryLabel->Label.Sid); 56 | const DWORD integrityLevel = *GetSidSubAuthority(mandatoryLabel->Label.Sid, subAuthorityCount - 1); 57 | 58 | isHighIntegrityLevel = integrityLevel > SECURITY_MANDATORY_MEDIUM_RID; 59 | } 60 | 61 | CloseHandle(processToken); 62 | } 63 | 64 | return isHighIntegrityLevel; 65 | } 66 | 67 | char *khrIcd_secure_getenv(const char *name) { 68 | if (khrIcd_IsHighIntegrityLevel()) { 69 | KHR_ICD_TRACE("Running at a high integrity level, so secure_getenv is returning NULL\n"); 70 | return NULL; 71 | } 72 | 73 | return khrIcd_getenv(name); 74 | } 75 | 76 | void khrIcd_free_getenv(char *val) { 77 | free((void *)val); 78 | } 79 | -------------------------------------------------------------------------------- /loader/windows/icd_windows_hkr.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2017-2019 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include 20 | #include "icd_windows.h" 21 | 22 | bool khrIcdOsVendorsEnumerateHKR(void); 23 | -------------------------------------------------------------------------------- /scripts/.gitignore: -------------------------------------------------------------------------------- 1 | gen/__pycache__ 2 | *.c 3 | -------------------------------------------------------------------------------- /scripts/README.md: -------------------------------------------------------------------------------- 1 | # OpenCL ICD Loader Code Generation 2 | 3 | ## Introduction 4 | 5 | In order to ease maintenance and enable faster development of related OpenCL ICD loader features, the OpenCL ICD loader API dispatch functions are generated from the OpenCL XML machine readable grammar. 6 | 7 | ## Dependencies 8 | 9 | The API dispatch functions are generated using Python [Mako Templates](https://www.makotemplates.org/). 10 | 11 | In most cases, after installing Python for your platform, Mako may be installed using: 12 | 13 | ```sh 14 | $ pip install Mako 15 | ``` 16 | 17 | ## Making Changes 18 | 19 | Most changes only require modifications to the Mako templates. 20 | Small changes modifying syntax or layout are simple and straightforward. 21 | Occasionally more complicated changes will be required, say when a new API is added that is unlike any previous API, but this should be rare. 22 | 23 | The Python script should only need to be modified if additional information needs to be propagated from the XML file into the Mako template itself. 24 | 25 | ## Generating Files 26 | 27 | Files for the OpenCL ICD loader, or the test layer, may be generated by executing the scripts `gen_loader.py`, or `gen_print_layer.py`, respectively. 28 | 29 | The script requires the `cl.xml` machine readable grammar. 30 | By default, the script searches for `cl.xml` in the current directory. 31 | The latest version of `cl.xml` may be found in the Khronos OpenCL-Docs repo [here](https://github.com/KhronosGroup/OpenCL-Docs/blob/main/xml/cl.xml). 32 | 33 | The output from the script is placed in the current directory by default, to allow easy comparisons between the generated files and the current files. 34 | After the generated files are evaluated, they should be manually copied into the source tree. 35 | These steps may be automated in the future. 36 | -------------------------------------------------------------------------------- /scripts/gen/__init__.py: -------------------------------------------------------------------------------- 1 | # Copyright (c) 2020 The Khronos Group Inc. 2 | # 3 | # Licensed under the Apache License, Version 2.0 (the "License"); 4 | # you may not use this file except in compliance with the License. 5 | # You may obtain a copy of the License at 6 | # 7 | # http://www.apache.org/licenses/LICENSE-2.0 8 | # 9 | # Unless required by applicable law or agreed to in writing, software 10 | # distributed under the License is distributed on an "AS IS" BASIS, 11 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 12 | # See the License for the specific language governing permissions and 13 | # limitations under the License. 14 | 15 | from collections import OrderedDict 16 | from collections import namedtuple 17 | 18 | import argparse 19 | import sys 20 | import urllib 21 | import xml.etree.ElementTree as etree 22 | import urllib.request 23 | 24 | # parse_xml - Helper function to parse the XML file from a URL or local file. 25 | def parse_xml(path): 26 | file = urllib.request.urlopen(path) if path.startswith("http") else open(path, 'r') 27 | with file: 28 | tree = etree.parse(file) 29 | return tree 30 | 31 | # noneStr - returns string argument, or "" if argument is None. 32 | def noneStr(s): 33 | if s: 34 | return s 35 | return "" 36 | 37 | def parse_args(): 38 | parser = argparse.ArgumentParser() 39 | 40 | # To pull the latest registry file from GitHub, pass: 41 | # -registry "https://raw.githubusercontent.com/KhronosGroup/OpenCL-Docs/main/xml/cl.xml" 42 | 43 | parser.add_argument('-registry', action='store', 44 | default='cl.xml', 45 | help='Use specified registry file instead of cl.xml') 46 | parser.add_argument('-o', action='store', dest='directory', 47 | default='.', 48 | help='Create target and related files in specified directory') 49 | 50 | args = parser.parse_args() 51 | return args 52 | 53 | def load_spec(args): 54 | specpath = args.registry 55 | 56 | print('Parsing XML file from: ' + specpath) 57 | spec = parse_xml(specpath) 58 | return spec 59 | 60 | def get_apisigs(spec): 61 | # Generate the API function signatures dictionary: 62 | apisigs = OrderedDict() 63 | ApiSignature = namedtuple('ApiSignature', 'Name RetType Params Suffix') 64 | ApiParam = namedtuple('ApiParam', 'Type TypeEnd Name') 65 | print('Generating API signatures dictionary...') 66 | for command in spec.findall('commands/command'): 67 | suffix = noneStr(command.get('suffix')) 68 | proto = command.find('proto') 69 | ret = noneStr(proto.text) 70 | name = "" 71 | params = "" 72 | for elem in proto: 73 | if elem.tag == 'name': 74 | name = noneStr(elem.text) + noneStr(elem.tail) 75 | else: 76 | ret = ret + noneStr(elem.text) + noneStr(elem.tail) 77 | ret = ret.strip() 78 | name = name.strip() 79 | 80 | plist = [] 81 | for param in command.findall('param'): 82 | ptype = noneStr(param.text) 83 | ptypeend = "" 84 | pname = "" 85 | for elem in param: 86 | if elem.tag == 'name': 87 | pname = noneStr(elem.text) 88 | ptypeend = noneStr(elem.tail) 89 | else: 90 | ptype = ptype + noneStr(elem.text) + noneStr(elem.tail) 91 | ptype = ptype.strip() 92 | ptypeend = ptypeend.strip() 93 | pname = pname.strip() 94 | plist.append(ApiParam(ptype, ptypeend, pname)) 95 | 96 | # For an empty parameter list (for e.g. clUnloadCompiler), add a single 97 | # unnamed void parameter to make generation easier. 98 | if len(plist) == 0: 99 | plist.append(ApiParam("void", "", "")) 100 | 101 | apisigs[name] = ApiSignature(name, ret, plist, suffix) 102 | return apisigs 103 | 104 | def get_apis(spec, apisigs): 105 | # Generate the core API dictionary: 106 | coreapis = OrderedDict() 107 | print('Generating core API dictionary...') 108 | for feature in spec.findall('feature'): 109 | version = noneStr(feature.get('name')) 110 | 111 | alist = [] 112 | for function in feature.findall('require/command'): 113 | name = function.get('name') 114 | alist.append(apisigs[name]) 115 | coreapis[version] = alist 116 | 117 | # Generate the extensions API dictionary: 118 | extapis = OrderedDict() 119 | print('Generating API extensions dictionary...') 120 | for feature in spec.findall('extensions/extension'): 121 | extension = noneStr(feature.get('name')) 122 | 123 | alist = [] 124 | for function in feature.findall('require/command'): 125 | name = function.get('name') 126 | alist.append(apisigs[name]) 127 | extapis[extension] = alist 128 | return (coreapis, extapis) 129 | 130 | 131 | -------------------------------------------------------------------------------- /scripts/gen_loader.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Copyright (c) 2020 The Khronos Group Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import gen 18 | from mako.template import Template 19 | from mako.exceptions import RichTraceback 20 | 21 | if __name__ == "__main__": 22 | args = gen.parse_args() 23 | spec = gen.load_spec(args) 24 | apisigs = gen.get_apisigs(spec) 25 | (coreapis, extapis) = gen.get_apis(spec, apisigs) 26 | 27 | try: 28 | # Create the loader cpp file from the API dictionary: 29 | test = open(args.directory + '/icd_dispatch_generated.c', 'wb') 30 | icd_dispatch_generated_template = Template(filename='icd_dispatch_generated.c.mako') 31 | test.write( 32 | icd_dispatch_generated_template.render_unicode( 33 | spec=spec, 34 | apisigs=apisigs, 35 | coreapis=coreapis, 36 | extapis=extapis). 37 | encode('utf-8', 'replace')) 38 | except: 39 | traceback = RichTraceback() 40 | for (filename, lineno, function, line) in traceback.traceback: 41 | print('%s(%s) : error in %s' % (filename, lineno, function)) 42 | print(' ', line) 43 | print('%s: %s' % (str(traceback.error.__class__.__name__), traceback.error)) 44 | -------------------------------------------------------------------------------- /scripts/gen_print_layer.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/python3 2 | 3 | # Copyright (c) 2020 The Khronos Group Inc. 4 | # 5 | # Licensed under the Apache License, Version 2.0 (the "License"); 6 | # you may not use this file except in compliance with the License. 7 | # You may obtain a copy of the License at 8 | # 9 | # http://www.apache.org/licenses/LICENSE-2.0 10 | # 11 | # Unless required by applicable law or agreed to in writing, software 12 | # distributed under the License is distributed on an "AS IS" BASIS, 13 | # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 14 | # See the License for the specific language governing permissions and 15 | # limitations under the License. 16 | 17 | import gen 18 | from mako.template import Template 19 | from mako.exceptions import RichTraceback 20 | 21 | if __name__ == "__main__": 22 | args = gen.parse_args() 23 | spec = gen.load_spec(args) 24 | apisigs = gen.get_apisigs(spec) 25 | (coreapis, extapis) = gen.get_apis(spec, apisigs) 26 | 27 | try: 28 | # Create the layer cpp file from the API dictionary: 29 | test = open(args.directory + '/icd_print_layer_generated.c', 'wb') 30 | icd_layer_generated_template = Template(filename='icd_print_layer_generated.c.mako') 31 | test.write( 32 | icd_layer_generated_template.render_unicode( 33 | spec=spec, 34 | apisigs=apisigs, 35 | coreapis=coreapis, 36 | extapis=extapis). 37 | encode('utf-8', 'replace')) 38 | except: 39 | traceback = RichTraceback() 40 | for (filename, lineno, function, line) in traceback.traceback: 41 | print('%s(%s) : error in %s' % (filename, lineno, function)) 42 | print(' ', line) 43 | print('%s: %s' % (str(traceback.error.__class__.__name__), traceback.error)) 44 | -------------------------------------------------------------------------------- /test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | include_directories (./inc) 2 | 3 | add_subdirectory (log) 4 | add_subdirectory (driver_stub) 5 | add_subdirectory (loader_test) 6 | if (ENABLE_OPENCL_LAYERS) 7 | add_subdirectory (layer) 8 | endif () 9 | 10 | set_target_properties (IcdLog OpenCLDriverStub OpenCLDriverStubICD2 icd_loader_test 11 | PROPERTIES 12 | ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" 13 | LIBRARY_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" 14 | RUNTIME_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" 15 | PDB_OUTPUT_DIRECTORY "${CMAKE_BINARY_DIR}" 16 | ) 17 | add_test ( 18 | NAME opencl_icd_loader_test 19 | COMMAND icd_loader_test 20 | ) 21 | add_test ( 22 | NAME opencl_icd_loader_icd2_test 23 | COMMAND icd_loader_test 24 | ) 25 | 26 | if (ENABLE_OPENCL_LAYERINFO) 27 | add_test ( 28 | NAME cllayerinfo_test 29 | COMMAND cllayerinfo 30 | ) 31 | endif () 32 | 33 | get_property(GENERATOR_IS_MULTI_CONFIG GLOBAL PROPERTY GENERATOR_IS_MULTI_CONFIG) 34 | if (GENERATOR_IS_MULTI_CONFIG) 35 | set (TEST_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}/$") 36 | else () 37 | set (TEST_WORKING_DIRECTORY "${CMAKE_BINARY_DIR}") 38 | endif() 39 | 40 | set_tests_properties(opencl_icd_loader_test 41 | PROPERTIES 42 | ENVIRONMENT OCL_ICD_FILENAMES=$ 43 | WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}" 44 | ) 45 | set_tests_properties(opencl_icd_loader_icd2_test 46 | PROPERTIES 47 | ENVIRONMENT "OCL_ICD_FILENAMES=$;APP_LOG_FILE=icd_test_app_log_icd2.txt;APP_STUB_FILE=icd_test_stub_log_icd2.txt;APP_PLATFORM=ICD_LOADER_TEST_OPENCL_STUB_ICD2" 48 | WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}" 49 | ) 50 | if (ENABLE_OPENCL_LAYERINFO) 51 | set_tests_properties(cllayerinfo_test 52 | PROPERTIES 53 | ENVIRONMENT OPENCL_LAYERS=$ 54 | WORKING_DIRECTORY "${TEST_WORKING_DIRECTORY}" 55 | ) 56 | endif() 57 | -------------------------------------------------------------------------------- /test/driver_stub/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | 2 | set (OPENCL_DRIVER_STUB_SOURCES cl.c cl_ext.c cl_gl.c icd.c ${CMAKE_SOURCE_DIR}/include/cl_khr_icd2.h) 3 | 4 | if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") 5 | list (APPEND OPENCL_DRIVER_STUB_SOURCES driver_stub.def) 6 | endif () 7 | 8 | add_library (OpenCLDriverStub SHARED ${OPENCL_DRIVER_STUB_SOURCES}) 9 | 10 | target_link_libraries (OpenCLDriverStub IcdLog OpenCL::Headers) 11 | 12 | target_compile_definitions (OpenCLDriverStub PRIVATE CL_TARGET_OPENCL_VERSION=300) 13 | 14 | set (OPENCL_DRIVER_STUB_ICD2_SOURCES cl.c cl_ext.c cl_gl.c icd.c) 15 | 16 | if (NOT "${CMAKE_SYSTEM_NAME}" STREQUAL "Linux") 17 | list (APPEND OPENCL_DRIVER_STUB_ICD2_SOURCES driver_stub.def) 18 | endif () 19 | 20 | add_library (OpenCLDriverStubICD2 SHARED ${OPENCL_DRIVER_STUB_ICD2_SOURCES}) 21 | 22 | target_link_libraries (OpenCLDriverStubICD2 IcdLog OpenCL::Headers) 23 | 24 | target_compile_definitions (OpenCLDriverStubICD2 PRIVATE CL_TARGET_OPENCL_VERSION=300 CL_ENABLE_ICD2=1) 25 | -------------------------------------------------------------------------------- /test/driver_stub/cl_ext.c: -------------------------------------------------------------------------------- 1 | #include 2 | 3 | #define CL_USE_DEPRECATED_OPENCL_1_1_APIS 4 | #include "CL/cl.h" 5 | #include "CL/cl_ext.h" 6 | #include "cl_khr_icd2.h" 7 | 8 | #if defined(CL_ENABLE_ICD2) 9 | CL_API_ENTRY clIcdGetFunctionAddressForPlatformKHR_t clIcdGetFunctionAddressForPlatformKHR; 10 | CL_API_ENTRY clIcdSetPlatformDispatchDataKHR_t clIcdSetPlatformDispatchDataKHR; 11 | #endif 12 | 13 | struct driverStubextFunc_st 14 | { 15 | const char *name; 16 | void *func; 17 | }; 18 | 19 | #define EXT_FUNC(name) { #name, (void*)(intptr_t)(name) } 20 | 21 | static struct driverStubextFunc_st clExtensions[] = 22 | { 23 | EXT_FUNC(clIcdGetPlatformIDsKHR), 24 | #ifdef CL_ENABLE_ICD2 25 | EXT_FUNC(clIcdGetFunctionAddressForPlatformKHR), 26 | EXT_FUNC(clIcdSetPlatformDispatchDataKHR), 27 | #endif //CL_ENABLE_ICD2 28 | }; 29 | 30 | static const int clExtensionCount = sizeof(clExtensions) / sizeof(clExtensions[0]); 31 | 32 | CL_API_ENTRY void * CL_API_CALL 33 | clGetExtensionFunctionAddress(const char *name) 34 | { 35 | int ii; 36 | 37 | for (ii = 0; ii < clExtensionCount; ii++) { 38 | if (!strcmp(name, clExtensions[ii].name)) { 39 | return clExtensions[ii].func; 40 | } 41 | } 42 | 43 | return NULL; 44 | } 45 | 46 | -------------------------------------------------------------------------------- /test/driver_stub/cl_gl.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | 4 | // Need to rename all CL API functions to prevent ICD loader functions calling 5 | // themselves via the dispatch table. Include this before cl headers. 6 | #include "rename_api.h" 7 | 8 | #define SIZE_T_MAX (size_t) 0xFFFFFFFFFFFFFFFFULL 9 | 10 | CL_API_ENTRY cl_mem CL_API_CALL 11 | clCreateFromGLBuffer(cl_context context , 12 | cl_mem_flags flags , 13 | cl_GLuint bufret_mem , 14 | int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 15 | { 16 | cl_mem ret_mem = (cl_mem)(SIZE_T_MAX); 17 | test_icd_stub_log("clCreateFromGLBuffer(%p, %x, %u, %p)\n", 18 | context, 19 | flags, 20 | bufret_mem, 21 | errcode_ret); 22 | test_icd_stub_log("Value returned: %p\n", 23 | ret_mem); 24 | return ret_mem; 25 | } 26 | 27 | CL_API_ENTRY cl_mem CL_API_CALL 28 | clCreateFromGLTexture(cl_context context , 29 | cl_mem_flags flags , 30 | cl_GLenum target , 31 | cl_GLint miplevel , 32 | cl_GLuint texture , 33 | cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_2 34 | { 35 | cl_mem ret_mem = (cl_mem)(SIZE_T_MAX); 36 | test_icd_stub_log("clCreateFromGLTexture(%p, %x, %d, %d, %u, %p)\n", 37 | context , 38 | flags , 39 | target , 40 | miplevel , 41 | texture , 42 | errcode_ret ); 43 | test_icd_stub_log("Value returned: %p\n", 44 | ret_mem); 45 | return ret_mem; 46 | } 47 | 48 | CL_API_ENTRY cl_mem CL_API_CALL 49 | clCreateFromGLTexture2D(cl_context context, 50 | cl_mem_flags flags, 51 | cl_GLenum target, 52 | cl_GLint miplevel, 53 | cl_GLuint texture, 54 | cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 55 | { 56 | cl_mem ret_mem = (cl_mem)(SIZE_T_MAX); 57 | test_icd_stub_log("clCreateFromGLTexture2D(%p, %x, %d, %d, %u, %p)\n", 58 | context, 59 | flags, 60 | target, 61 | miplevel, 62 | texture, 63 | errcode_ret ); 64 | test_icd_stub_log("Value returned: %p\n", 65 | ret_mem); 66 | return ret_mem; 67 | } 68 | 69 | CL_API_ENTRY cl_mem CL_API_CALL 70 | clCreateFromGLTexture3D(cl_context context, 71 | cl_mem_flags flags, 72 | cl_GLenum target, 73 | cl_GLint miplevel, 74 | cl_GLuint texture, 75 | cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 76 | 77 | { 78 | cl_mem ret_mem = (cl_mem)(SIZE_T_MAX); 79 | test_icd_stub_log("clCreateFromGLTexture3D(%p, %x, %d, %d, %u, %p)\n", 80 | context, 81 | flags, 82 | target, 83 | miplevel, 84 | texture, 85 | errcode_ret ); 86 | test_icd_stub_log("Value returned: %p\n", 87 | ret_mem); 88 | return ret_mem; 89 | } 90 | 91 | CL_API_ENTRY cl_mem CL_API_CALL 92 | clCreateFromGLRenderbuffer(cl_context context, 93 | cl_mem_flags flags, 94 | cl_GLuint renderbuffer, 95 | cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_0 96 | { 97 | cl_mem ret_mem = (cl_mem)(SIZE_T_MAX); 98 | test_icd_stub_log("clCreateFromGLRenderbuffer(%p, %x, %d, %p)\n", 99 | context, 100 | flags, 101 | renderbuffer, 102 | errcode_ret); 103 | test_icd_stub_log("Value returned: %p\n", 104 | ret_mem); 105 | return ret_mem; 106 | } 107 | 108 | CL_API_ENTRY cl_int CL_API_CALL 109 | clGetGLObjectInfo(cl_mem memobj, 110 | cl_gl_object_type * gl_object_type, 111 | cl_GLuint * gl_object_name ) CL_API_SUFFIX__VERSION_1_0 112 | { 113 | cl_int ret_val = -5; 114 | test_icd_stub_log("clGetGLObjectInfo(%p, %p, %p)\n", 115 | memobj, 116 | gl_object_type, 117 | gl_object_name); 118 | test_icd_stub_log("Value returned: %p\n", 119 | ret_val); 120 | return ret_val; 121 | } 122 | 123 | CL_API_ENTRY cl_int CL_API_CALL 124 | clGetGLTextureInfo(cl_mem memobj, 125 | cl_gl_texture_info param_name, 126 | size_t param_value_size, 127 | void * param_value, 128 | size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0 129 | { 130 | cl_int ret_val = -5; 131 | test_icd_stub_log("clGetGLTextureInfo(%p, %u, %u, %p, %p)\n", 132 | memobj, 133 | param_name, 134 | param_value_size, 135 | param_value, 136 | param_value_size_ret ); 137 | test_icd_stub_log("Value returned: %p\n", 138 | ret_val); 139 | return ret_val; 140 | } 141 | 142 | CL_API_ENTRY cl_int CL_API_CALL 143 | clEnqueueAcquireGLObjects(cl_command_queue command_queue, 144 | cl_uint num_objects, 145 | const cl_mem * mem_objects, 146 | cl_uint num_events_in_wait_list, 147 | const cl_event * event_wait_list, 148 | cl_event * event ) CL_API_SUFFIX__VERSION_1_0 149 | { 150 | cl_int ret_val = -5; 151 | test_icd_stub_log("clEnqueueAcquireGLObjects(%p, %u, %p, %u, %p, %p)\n", 152 | command_queue, 153 | num_objects, 154 | mem_objects, 155 | num_events_in_wait_list, 156 | event_wait_list, 157 | event); 158 | 159 | test_icd_stub_log("Value returned: %p\n", 160 | ret_val); 161 | return ret_val; 162 | } 163 | 164 | CL_API_ENTRY cl_int CL_API_CALL 165 | clEnqueueReleaseGLObjects(cl_command_queue command_queue, 166 | cl_uint num_objects, 167 | const cl_mem * mem_objects, 168 | cl_uint num_events_in_wait_list, 169 | const cl_event * event_wait_list, 170 | cl_event * event ) CL_API_SUFFIX__VERSION_1_0 171 | 172 | { 173 | cl_int ret_val = -5; 174 | test_icd_stub_log("clEnqueueReleaseGLObjects(%p, %u, %p, %u, %p, %p)\n", 175 | command_queue, 176 | num_objects, 177 | mem_objects, 178 | num_events_in_wait_list, 179 | event_wait_list, 180 | event); 181 | test_icd_stub_log("Value returned: %p\n", 182 | ret_val); 183 | return ret_val; 184 | } 185 | 186 | CL_API_ENTRY cl_int CL_API_CALL 187 | clGetGLContextInfoKHR(const cl_context_properties * properties, 188 | cl_gl_context_info param_name, 189 | size_t param_value_size, 190 | void * param_value, 191 | size_t * param_value_size_ret ) CL_API_SUFFIX__VERSION_1_0 192 | { 193 | cl_int ret_val = -5; 194 | test_icd_stub_log("clGetGLContextInfoKHR(%p, %u, %u, %p, %p)\n", 195 | properties, 196 | param_name, 197 | param_value_size, 198 | param_value, 199 | param_value_size_ret); 200 | 201 | test_icd_stub_log("Value returned: %p\n", 202 | ret_val); 203 | return ret_val; 204 | } 205 | 206 | CL_API_ENTRY cl_event CL_API_CALL 207 | clCreateEventFromGLsyncKHR(cl_context context , 208 | cl_GLsync cl_GLsync , 209 | cl_int * errcode_ret ) CL_API_SUFFIX__VERSION_1_1 210 | 211 | { 212 | cl_event ret_event = (cl_event)(SIZE_T_MAX); 213 | test_icd_stub_log("clCreateEventFromGLsyncKHR(%p, %p, %p)\n", 214 | context, 215 | cl_GLsync, 216 | errcode_ret); 217 | test_icd_stub_log("Value returned: %p\n", 218 | ret_event); 219 | return ret_event; 220 | } 221 | -------------------------------------------------------------------------------- /test/driver_stub/driver_stub.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | clGetExtensionFunctionAddress 3 | -------------------------------------------------------------------------------- /test/driver_stub/icd_driver_exports.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | clGetExtensionFunctionAddress; 4 | clGetPlatformInfo; 5 | 6 | local: 7 | *; 8 | }; 9 | -------------------------------------------------------------------------------- /test/driver_stub/icd_structs.h: -------------------------------------------------------------------------------- 1 | #ifndef _ICD_STRUCTS_H_ 2 | #define _ICD_STRUCTS_H_ 3 | 4 | typedef struct CLIicdDispatchTable_st CLIicdDispatchTable; 5 | typedef struct CLIplatform_st CLIplatform; 6 | 7 | struct CLIicdDispatchTable_st 8 | { 9 | void *entries[256]; 10 | int entryCount; 11 | }; 12 | 13 | #ifdef CL_ENABLE_ICD2 14 | 15 | #define CL_OBJECT_BODY \ 16 | CLIicdDispatchTable* dispatch; \ 17 | void* dispData 18 | 19 | #define CL_INIT_OBJECT(obj, parent) \ 20 | do \ 21 | { \ 22 | obj->dispatch = parent->dispatch; \ 23 | obj->dispData = parent->dispData; \ 24 | } while (0) 25 | 26 | #define CL_INIT_PLATFORM(obj, table) \ 27 | do \ 28 | { \ 29 | obj->dispatch = table; \ 30 | obj->dispData = NULL; \ 31 | } while (0) 32 | 33 | #else //defined(CL_ENABLE_ICD2) 34 | 35 | #define CL_OBJECT_BODY \ 36 | CLIicdDispatchTable* dispatch 37 | 38 | #define CL_INIT_OBJECT(obj, parent) \ 39 | do \ 40 | { \ 41 | obj->dispatch = parent->dispatch; \ 42 | } while (0) 43 | 44 | #define CL_INIT_PLATFORM(obj, table) \ 45 | do \ 46 | { \ 47 | obj->dispatch = table; \ 48 | } while (0) 49 | 50 | #endif //defined(CL_ENABLE_ICD2) 51 | 52 | struct CLIplatform_st 53 | { 54 | CL_OBJECT_BODY; 55 | }; 56 | 57 | #endif /* _ICD_STRUCTS_H_ */ 58 | -------------------------------------------------------------------------------- /test/driver_stub/rename_api.h: -------------------------------------------------------------------------------- 1 | #ifndef _RENAME_API_H_ 2 | #define _RENAME_API_H_ 3 | 4 | #define clGetPlatformIDs ___clGetPlatformIDs 5 | #define clGetPlatformInfo ___clGetPlatformInfo 6 | #define clGetDeviceIDs ___clGetDeviceIDs 7 | #define clGetDeviceInfo ___clGetDeviceInfo 8 | #define clCreateSubDevices ___clCreateSubDevices 9 | #define clRetainDevice ___clRetainDevice 10 | #define clReleaseDevice ___clReleaseDevice 11 | #define clCreateContext ___clCreateContext 12 | #define clCreateContextFromType ___clCreateContextFromType 13 | #define clRetainContext ___clRetainContext 14 | #define clReleaseContext ___clReleaseContext 15 | #define clGetContextInfo ___clGetContextInfo 16 | #define clCreateCommandQueue ___clCreateCommandQueue 17 | #define clSetCommandQueueProperty ___clSetCommandQueueProperty 18 | #define clRetainCommandQueue ___clRetainCommandQueue 19 | #define clReleaseCommandQueue ___clReleaseCommandQueue 20 | #define clGetCommandQueueInfo ___clGetCommandQueueInfo 21 | #define clCreateBuffer ___clCreateBuffer 22 | #define clCreateSubBuffer ___clCreateSubBuffer 23 | #define clCreateImage ___clCreateImage 24 | #define clCreateImage2D ___clCreateImage2D 25 | #define clCreateImage3D ___clCreateImage3D 26 | #define clRetainMemObject ___clRetainMemObject 27 | #define clReleaseMemObject ___clReleaseMemObject 28 | #define clGetSupportedImageFormats ___clGetSupportedImageFormats 29 | #define clGetMemObjectInfo ___clGetMemObjectInfo 30 | #define clGetImageInfo ___clGetImageInfo 31 | #define clSetMemObjectDestructorCallback ___clSetMemObjectDestructorCallback 32 | #define clCreateSampler ___clCreateSampler 33 | #define clRetainSampler ___clRetainSampler 34 | #define clReleaseSampler ___clReleaseSampler 35 | #define clGetSamplerInfo ___clGetSamplerInfo 36 | #define clCreateProgramWithSource ___clCreateProgramWithSource 37 | #define clCreateProgramWithBinary ___clCreateProgramWithBinary 38 | #define clCreateProgramWithBuiltInKernels ___clCreateProgramWithBuiltInKernels 39 | #define clRetainProgram ___clRetainProgram 40 | #define clReleaseProgram ___clReleaseProgram 41 | #define clBuildProgram ___clBuildProgram 42 | #define clUnloadCompiler ___clUnloadCompiler 43 | #define clCompileProgram ___clCompileProgram 44 | #define clLinkProgram ___clLinkProgram 45 | #define clUnloadPlatformCompiler ___clUnloadPlatformCompiler 46 | #define clGetProgramInfo ___clGetProgramInfo 47 | #define clGetProgramBuildInfo ___clGetProgramBuildInfo 48 | #define clCreateKernel ___clCreateKernel 49 | #define clCreateKernelsInProgram ___clCreateKernelsInProgram 50 | #define clRetainKernel ___clRetainKernel 51 | #define clReleaseKernel ___clReleaseKernel 52 | #define clSetKernelArg ___clSetKernelArg 53 | #define clGetKernelInfo ___clGetKernelInfo 54 | #define clGetKernelArgInfo ___clGetKernelArgInfo 55 | #define clGetKernelWorkGroupInfo ___clGetKernelWorkGroupInfo 56 | #define clWaitForEvents ___clWaitForEvents 57 | #define clGetEventInfo ___clGetEventInfo 58 | #define clCreateUserEvent ___clCreateUserEvent 59 | #define clRetainEvent ___clRetainEvent 60 | #define clReleaseEvent ___clReleaseEvent 61 | #define clSetUserEventStatus ___clSetUserEventStatus 62 | #define clSetEventCallback ___clSetEventCallback 63 | #define clGetEventProfilingInfo ___clGetEventProfilingInfo 64 | #define clFlush ___clFlush 65 | #define clFinish ___clFinish 66 | #define clEnqueueReadBuffer ___clEnqueueReadBuffer 67 | #define clEnqueueReadBufferRect ___clEnqueueReadBufferRect 68 | #define clEnqueueWriteBuffer ___clEnqueueWriteBuffer 69 | #define clEnqueueWriteBufferRect ___clEnqueueWriteBufferRect 70 | #define clEnqueueCopyBuffer ___clEnqueueCopyBuffer 71 | #define clEnqueueCopyBufferRect ___clEnqueueCopyBufferRect 72 | #define clEnqueueFillBuffer ___clEnqueueFillBuffer 73 | #define clEnqueueFillImage ___clEnqueueFillImage 74 | #define clEnqueueReadImage ___clEnqueueReadImage 75 | #define clEnqueueWriteImage ___clEnqueueWriteImage 76 | #define clEnqueueCopyImage ___clEnqueueCopyImage 77 | #define clEnqueueCopyImageToBuffer ___clEnqueueCopyImageToBuffer 78 | #define clEnqueueCopyBufferToImage ___clEnqueueCopyBufferToImage 79 | #define clEnqueueMapBuffer ___clEnqueueMapBuffer 80 | #define clEnqueueMapImage ___clEnqueueMapImage 81 | #define clEnqueueUnmapMemObject ___clEnqueueUnmapMemObject 82 | #define clEnqueueMigrateMemObjects ___clEnqueueMigrateMemObjects 83 | #define clEnqueueNDRangeKernel ___clEnqueueNDRangeKernel 84 | #define clEnqueueTask ___clEnqueueTask 85 | #define clEnqueueNativeKernel ___clEnqueueNativeKernel 86 | #define clGetExtensionFunctionAddressForPlatform ___clGetExtensionFunctionAddressForPlatform 87 | #define clEnqueueMarkerWithWaitList ___clEnqueueMarkerWithWaitList 88 | #define clEnqueueBarrierWithWaitList ___clEnqueueBarrierWithWaitList 89 | #define clSetPrintfCallback ___clSetPrintfCallback 90 | #define clEnqueueMarker ___clEnqueueMarker 91 | #define clEnqueueWaitForEvents ___clEnqueueWaitForEvents 92 | #define clEnqueueBarrier ___clEnqueueBarrier 93 | 94 | #define clCreateFromGLBuffer ___clCreateFromGLBuffer 95 | #define clCreateFromGLTexture ___clCreateFromGLTexture 96 | #define clCreateFromGLTexture2D ___clCreateFromGLTexture2D 97 | #define clCreateFromGLTexture3D ___clCreateFromGLTexture3D 98 | #define clCreateFromGLRenderbuffer ___clCreateFromGLRenderbuffer 99 | #define clGetGLObjectInfo ___clGetGLObjectInfo 100 | #define clGetGLTextureInfo ___clGetGLTextureInfo 101 | #define clEnqueueAcquireGLObjects ___clEnqueueAcquireGLObjects 102 | #define clEnqueueReleaseGLObjects ___clEnqueueReleaseGLObjects 103 | #define clGetGLContextInfoKHR ___clGetGLContextInfoKHR 104 | #define clCreateEventFromGLsyncKHR ___clCreateEventFromGLsyncKHR 105 | #define clCreateBufferWithProperties ___clCreateBufferWithProperties 106 | #define clCreateImageWithProperties ___clCreateImageWithProperties 107 | #define clSetContextDestructorCallback ___clSetContextDestructorCallback 108 | 109 | #endif /* __RENAME_API_H__ */ 110 | -------------------------------------------------------------------------------- /test/inc/platform/icd_test_log.h: -------------------------------------------------------------------------------- 1 | #ifndef _ICD_TEST_LOG_H_ 2 | #define _ICD_TEST_LOG_H_ 3 | 4 | #if defined(_WIN32) 5 | #include 6 | #else 7 | #include 8 | #endif 9 | 10 | #if defined(_WIN32) || defined(__CYGWIN__) 11 | #define DllExport __declspec(dllexport) 12 | #else 13 | #ifndef __has_attribute 14 | #define __has_attribute(x) 0 // Compatibility with non-clang compilers. 15 | #endif 16 | #if (defined(__GNUC__) && (__GNUC__ >= 4)) ||\ 17 | (defined(__clang__) && __has_attribute(visibility)) 18 | #define DllExport __attribute__((visibility("default"))) 19 | #else 20 | #define DllExport 21 | #endif 22 | #endif 23 | 24 | DllExport const char * log_getenv(const char *name, const char *dflt); 25 | DllExport void log_freeenv(const char *var); 26 | 27 | DllExport int test_icd_initialize_app_log(void); 28 | DllExport void test_icd_app_log(const char *format, ...); 29 | DllExport void test_icd_close_app_log(void); 30 | DllExport char *test_icd_get_stub_log(void); 31 | 32 | DllExport int test_icd_initialize_stub_log(void); 33 | DllExport void test_icd_stub_log(const char *format, ...); 34 | DllExport void test_icd_close_stub_log(void); 35 | DllExport char *test_icd_get_app_log(void); 36 | 37 | #endif /* _ICD_TEST_LOG_H_ */ 38 | -------------------------------------------------------------------------------- /test/layer/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | set (OPENCL_PRINT_LAYER_SOURCES 2 | icd_print_layer.c 3 | icd_print_layer.h 4 | icd_print_layer_generated.c) 5 | 6 | if (WIN32) 7 | list (APPEND OPENCL_PRINT_LAYER_SOURCES icd_print_layer.def) 8 | else () 9 | if (NOT APPLE) 10 | list (APPEND OPENCL_PRINT_LAYER_SOURCES icd_print_layer.map) 11 | endif () 12 | endif () 13 | 14 | add_library (PrintLayer SHARED ${OPENCL_PRINT_LAYER_SOURCES}) 15 | 16 | target_include_directories(PrintLayer PRIVATE ${PARENT_DIR}/include) 17 | target_link_libraries(PrintLayer PUBLIC OpenCL::Headers) 18 | target_compile_definitions (PrintLayer PRIVATE CL_TARGET_OPENCL_VERSION=300) 19 | 20 | if (NOT WIN32 AND NOT APPLE) 21 | set_target_properties (PrintLayer PROPERTIES LINK_FLAGS "-Wl,--version-script -Wl,${CMAKE_CURRENT_SOURCE_DIR}/icd_print_layer.map") 22 | endif () 23 | -------------------------------------------------------------------------------- /test/layer/icd_print_layer.c: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #include "icd_print_layer.h" 20 | #include 21 | #include 22 | #include 23 | 24 | struct _cl_icd_dispatch dispatch; 25 | 26 | const struct _cl_icd_dispatch *tdispatch; 27 | 28 | static cl_layer_api_version api_version = CL_LAYER_API_VERSION_100; 29 | static const char name[] = "print_layer"; 30 | 31 | static inline cl_int 32 | set_param_value( 33 | size_t param_value_size, 34 | void *param_value, 35 | size_t *param_value_size_ret, 36 | size_t src_size, 37 | const void *src) { 38 | if (param_value && param_value_size < src_size) 39 | return CL_INVALID_VALUE; 40 | if (param_value) 41 | memcpy(param_value, src, src_size); 42 | if (param_value_size_ret) 43 | *param_value_size_ret = src_size; 44 | return CL_SUCCESS; 45 | } 46 | 47 | CL_API_ENTRY cl_int CL_API_CALL 48 | clGetLayerInfo( 49 | cl_layer_info param_name, 50 | size_t param_value_size, 51 | void *param_value, 52 | size_t *param_value_size_ret) { 53 | size_t sz = 0; 54 | const void *src = NULL; 55 | if (param_value_size && !param_value) 56 | return CL_INVALID_VALUE; 57 | if (!param_value && !param_value_size_ret) 58 | return CL_INVALID_VALUE; 59 | switch (param_name) { 60 | case CL_LAYER_API_VERSION: 61 | sz = sizeof(api_version); 62 | src = &api_version; 63 | break; 64 | case CL_LAYER_NAME: 65 | sz = sizeof(name); 66 | src = name; 67 | break; 68 | default: 69 | return CL_INVALID_VALUE; 70 | } 71 | return set_param_value(param_value_size, param_value, param_value_size_ret, sz, src); 72 | } 73 | 74 | CL_API_ENTRY cl_int CL_API_CALL 75 | clInitLayer( 76 | cl_uint num_entries, 77 | const struct _cl_icd_dispatch *target_dispatch, 78 | cl_uint *num_entries_out, 79 | const struct _cl_icd_dispatch **layer_dispatch_ret) { 80 | if (!target_dispatch || !layer_dispatch_ret || !num_entries_out || num_entries < sizeof(dispatch)/sizeof(dispatch.clGetPlatformIDs)) 81 | return CL_INVALID_VALUE; 82 | 83 | _init_dispatch(); 84 | 85 | tdispatch = target_dispatch; 86 | *layer_dispatch_ret = &dispatch; 87 | *num_entries_out = sizeof(dispatch)/sizeof(dispatch.clGetPlatformIDs); 88 | 89 | return CL_SUCCESS; 90 | } 91 | 92 | 93 | -------------------------------------------------------------------------------- /test/layer/icd_print_layer.def: -------------------------------------------------------------------------------- 1 | EXPORTS 2 | clGetLayerInfo 3 | clInitLayer 4 | -------------------------------------------------------------------------------- /test/layer/icd_print_layer.h: -------------------------------------------------------------------------------- 1 | /* 2 | * Copyright (c) 2020 The Khronos Group Inc. 3 | * 4 | * Licensed under the Apache License, Version 2.0 (the "License"); 5 | * you may not use this file except in compliance with the License. 6 | * You may obtain a copy of the License at 7 | * 8 | * http://www.apache.org/licenses/LICENSE-2.0 9 | * 10 | * Unless required by applicable law or agreed to in writing, software 11 | * distributed under the License is distributed on an "AS IS" BASIS, 12 | * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. 13 | * See the License for the specific language governing permissions and 14 | * limitations under the License. 15 | * 16 | * OpenCL is a trademark of Apple Inc. used under license by Khronos. 17 | */ 18 | 19 | #ifndef __ICD_PRINT_LAYER_H 20 | #define __ICD_PRINT_LAYER_H 21 | 22 | #ifndef CL_USE_DEPRECATED_OPENCL_1_0_APIS 23 | #define CL_USE_DEPRECATED_OPENCL_1_0_APIS 24 | #endif 25 | 26 | #ifndef CL_USE_DEPRECATED_OPENCL_1_1_APIS 27 | #define CL_USE_DEPRECATED_OPENCL_1_1_APIS 28 | #endif 29 | 30 | #ifndef CL_USE_DEPRECATED_OPENCL_1_2_APIS 31 | #define CL_USE_DEPRECATED_OPENCL_1_2_APIS 32 | #endif 33 | 34 | #ifndef CL_USE_DEPRECATED_OPENCL_2_0_APIS 35 | #define CL_USE_DEPRECATED_OPENCL_2_0_APIS 36 | #endif 37 | 38 | #ifndef CL_USE_DEPRECATED_OPENCL_2_1_APIS 39 | #define CL_USE_DEPRECATED_OPENCL_2_1_APIS 40 | #endif 41 | 42 | #ifndef CL_USE_DEPRECATED_OPENCL_2_2_APIS 43 | #define CL_USE_DEPRECATED_OPENCL_2_2_APIS 44 | #endif 45 | 46 | #include 47 | #include 48 | 49 | #ifdef __cplusplus 50 | extern "C" { 51 | #endif 52 | 53 | extern struct _cl_icd_dispatch dispatch; 54 | 55 | extern const struct _cl_icd_dispatch *tdispatch; 56 | 57 | extern void _init_dispatch(void); 58 | 59 | #ifdef __cplusplus 60 | } 61 | #endif 62 | 63 | #endif /* __ICD_PRINT_LAYER_H */ 64 | -------------------------------------------------------------------------------- /test/layer/icd_print_layer.map: -------------------------------------------------------------------------------- 1 | { 2 | global: 3 | clGetLayerInfo; 4 | clInitLayer; 5 | 6 | local: 7 | *; 8 | }; 9 | -------------------------------------------------------------------------------- /test/loader_test/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | add_executable (icd_loader_test 2 | test_kernel.c 3 | main.c 4 | test_platforms.c 5 | icd_test_match.c 6 | test_program_objects.c 7 | test_sampler_objects.c 8 | test_buffer_object.c 9 | test_cl_runtime.c 10 | callbacks.c 11 | test_create_calls.c 12 | test_clgl.c 13 | test_image_objects.c ) 14 | 15 | target_compile_definitions(icd_loader_test 16 | PRIVATE 17 | CL_TARGET_OPENCL_VERSION=300 18 | ) 19 | 20 | target_link_libraries (icd_loader_test OpenCL IcdLog OpenCL::Headers) 21 | -------------------------------------------------------------------------------- /test/loader_test/callbacks.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | 5 | void CL_CALLBACK createcontext_callback(const char* _a, const void* _b, size_t _c, void* _d) 6 | { 7 | test_icd_app_log("createcontext_callback(%p, %p, %u, %p)\n", 8 | _a, 9 | _b, 10 | _c, 11 | _d); 12 | } 13 | 14 | void CL_CALLBACK setcontextdestructor_callback(cl_context _a, void* _b) 15 | { 16 | test_icd_app_log("setcontextdestructor_callback(%p, %p)\n", _a, _b); 17 | } 18 | 19 | void CL_CALLBACK setmemobjectdestructor_callback(cl_mem _a, void* _b) 20 | { 21 | test_icd_app_log("setmemobjectdestructor_callback(%p, %p)\n", 22 | _a, 23 | _b); 24 | } 25 | 26 | void CL_CALLBACK program_callback(cl_program _a, void* _b) 27 | { 28 | test_icd_app_log("program_callback(%p, %p)\n", 29 | _a, 30 | _b); 31 | } 32 | 33 | void CL_CALLBACK setevent_callback(cl_event _a, cl_int _b, void* _c) 34 | { 35 | test_icd_app_log("setevent_callback(%p, %d, %p)\n", 36 | _a, 37 | _b, 38 | _c); 39 | } 40 | 41 | void CL_CALLBACK setprintf_callback(cl_context _a, cl_uint _b, char* _c, void* _d ) 42 | { 43 | test_icd_app_log("setprintf_callback(%p, %u, %p, %p)\n", 44 | _a, 45 | _b, 46 | _c, 47 | _d); 48 | } 49 | -------------------------------------------------------------------------------- /test/loader_test/icd_test_match.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #ifndef __APPLE__ 5 | #include 6 | #endif 7 | #include 8 | 9 | int test_icd_match(void) 10 | { 11 | int error = 0; 12 | char *app_log = NULL, *stub_log = NULL; 13 | 14 | app_log = test_icd_get_app_log(); 15 | if (!app_log) { 16 | printf("ERROR: Could not retrieve app log\n"); 17 | error = 1; 18 | goto End; 19 | } 20 | 21 | stub_log = test_icd_get_stub_log(); 22 | if (!stub_log) { 23 | printf("ERROR: Could not retrieve stub log\n"); 24 | error = 1; 25 | goto End; 26 | } 27 | 28 | if (strcmp(app_log, stub_log)) { 29 | printf("ERROR: App log and stub log differ.\n\n"); 30 | printf("APPLOG:\n%s\n\n", app_log); 31 | printf("STUBLOG:\n%s\n\n", stub_log); 32 | error = 1; 33 | goto End; 34 | } 35 | 36 | End: 37 | free(app_log); 38 | free(stub_log); 39 | return error; 40 | } 41 | -------------------------------------------------------------------------------- /test/loader_test/main.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include 3 | #include 4 | #include "param_struct.h" 5 | 6 | extern int test_create_calls(void); 7 | extern int test_platforms(void); 8 | extern int test_cl_runtime(void); 9 | extern int test_kernel(void); 10 | extern int test_buffer_object(void); 11 | extern int test_program_objects(void); 12 | extern int test_image_objects(void); 13 | extern int test_sampler_objects(void); 14 | extern int test_OpenGL_share(void); 15 | extern int test_release_calls(void); 16 | extern int test_icd_match(void); 17 | 18 | int main(int argc, char **argv) 19 | { 20 | (void)argc; 21 | (void)argv; 22 | test_icd_initialize_app_log(); 23 | test_icd_initialize_stub_log(); 24 | 25 | test_create_calls(); 26 | test_platforms(); 27 | test_cl_runtime(); 28 | test_kernel(); 29 | test_buffer_object(); 30 | test_program_objects(); 31 | test_image_objects(); 32 | test_sampler_objects(); 33 | test_OpenGL_share(); 34 | test_release_calls(); 35 | 36 | test_icd_close_app_log(); 37 | test_icd_close_stub_log(); 38 | 39 | if (test_icd_match()) { 40 | printf("ICD Loader Test FAILED\n"); 41 | return 1; 42 | } else { 43 | printf("ICD Loader Test PASSED\n"); 44 | return 0; 45 | } 46 | } 47 | -------------------------------------------------------------------------------- /test/loader_test/test_cl_runtime.c: -------------------------------------------------------------------------------- 1 | #include 2 | #include "param_struct.h" 3 | #include 4 | 5 | extern cl_command_queue command_queue; 6 | 7 | const struct clRetainCommandQueue_st clRetainCommandQueueData[NUM_ITEMS_clRetainCommandQueue] = { 8 | {NULL} 9 | }; 10 | 11 | const struct clGetCommandQueueInfo_st clGetCommandQueueInfoData[NUM_ITEMS_clGetCommandQueueInfo] = { 12 | {NULL, 0, 0, NULL, NULL} 13 | }; 14 | 15 | int test_clRetainCommandQueue(const struct clRetainCommandQueue_st *data) 16 | { 17 | (void)data; 18 | cl_int ret_val; 19 | 20 | test_icd_app_log("clRetainCommandQueue(%p)\n", command_queue); 21 | 22 | ret_val = clRetainCommandQueue(command_queue); 23 | 24 | test_icd_app_log("Value returned: %d\n", ret_val); 25 | 26 | return 0; 27 | 28 | } 29 | 30 | int test_clGetCommandQueueInfo(const struct clGetCommandQueueInfo_st *data) 31 | { 32 | cl_int ret_val; 33 | 34 | test_icd_app_log("clGetCommandQueueInfo(%p, %u, %u, %p, %p)\n", 35 | command_queue, 36 | data->param_name, 37 | data->param_value_size, 38 | data->param_value, 39 | data->param_value_size_ret); 40 | 41 | ret_val = clGetCommandQueueInfo(command_queue, 42 | data->param_name, 43 | data->param_value_size, 44 | data->param_value, 45 | data->param_value_size_ret); 46 | 47 | test_icd_app_log("Value returned: %d\n", ret_val); 48 | 49 | return 0; 50 | 51 | } 52 | 53 | int test_cl_runtime(void) 54 | { 55 | int i; 56 | 57 | for (i=0; i 2 | #include "param_struct.h" 3 | #include 4 | 5 | extern cl_context context; 6 | 7 | extern cl_platform_id platform; 8 | 9 | extern cl_device_id devices; 10 | 11 | extern void CL_CALLBACK setcontextdestructor_callback(cl_context _a, void* _b); 12 | 13 | struct clRetainContext_st clRetainContextData[NUM_ITEMS_clRetainContext] = 14 | { 15 | {NULL} 16 | }; 17 | 18 | struct clGetContextInfo_st clGetContextInfoData[NUM_ITEMS_clGetContextInfo] = 19 | { 20 | {NULL, 0, 0, NULL, NULL} 21 | }; 22 | 23 | struct clSetContextDestructorCallback_st clSetContextDestructorCallbackData[NUM_ITEMS_clSetContextDestructorCallback] = 24 | { 25 | {NULL, setcontextdestructor_callback, NULL} 26 | }; 27 | 28 | struct clGetPlatformInfo_st clGetPlatformInfoData[NUM_ITEMS_clGetPlatformInfo] = 29 | { 30 | {NULL, 0, 0, NULL, NULL} 31 | }; 32 | 33 | struct clGetDeviceInfo_st clGetDeviceInfoData[NUM_ITEMS_clGetDeviceInfo] = 34 | { 35 | {NULL, 0, 0, NULL, NULL} 36 | }; 37 | 38 | struct clCreateSubDevices_st clCreateSubDevicesData[NUM_ITEMS_clCreateSubDevices] = 39 | { 40 | {NULL, NULL, 0, NULL, NULL} 41 | }; 42 | 43 | 44 | struct clRetainDevice_st clRetainDeviceData[NUM_ITEMS_clRetainDevice] = 45 | { 46 | {NULL} 47 | }; 48 | 49 | 50 | int test_clRetainContext(const struct clRetainContext_st* data) 51 | { 52 | (void)data; 53 | cl_int ret_val; 54 | 55 | test_icd_app_log("clRetainContext(%p)\n", context); 56 | 57 | ret_val = clRetainContext(context); 58 | 59 | test_icd_app_log("Value returned: %d\n", ret_val); 60 | 61 | return 0; 62 | } 63 | 64 | 65 | int test_clGetContextInfo(const struct clGetContextInfo_st* data) 66 | { 67 | cl_int ret_val; 68 | 69 | test_icd_app_log("clGetContextInfo(%p, %u, %u, %p, %p)\n", 70 | context, 71 | data->param_name, 72 | data->param_value_size, 73 | data->param_value, 74 | data->param_value_size_ret); 75 | 76 | 77 | ret_val = clGetContextInfo(context, 78 | data->param_name, 79 | data->param_value_size, 80 | data->param_value, 81 | data->param_value_size_ret); 82 | 83 | test_icd_app_log("Value returned: %d\n", ret_val); 84 | 85 | return 0; 86 | } 87 | 88 | 89 | int test_clSetContextDestructorCallback( 90 | const struct clSetContextDestructorCallback_st* data) 91 | { 92 | cl_int ret_val; 93 | 94 | test_icd_app_log( 95 | "clSetContextDestructorCallback(%p, %p, %p)\n", 96 | context, 97 | data->pfn_notify, 98 | data->user_data); 99 | 100 | ret_val = clSetContextDestructorCallback( 101 | context, 102 | data->pfn_notify, 103 | data->user_data); 104 | 105 | test_icd_app_log("Value returned: %d\n", ret_val); 106 | 107 | return 0; 108 | } 109 | 110 | 111 | int test_clGetPlatformInfo(const struct clGetPlatformInfo_st* data) 112 | { 113 | cl_int ret_val; 114 | 115 | test_icd_app_log("clGetPlatformInfo(%p, %u, %u, %p, %p)\n", 116 | platform, 117 | data->param_name, 118 | data->param_value_size, 119 | data->param_value, 120 | data->param_value_size_ret); 121 | 122 | ret_val = clGetPlatformInfo(platform, 123 | data->param_name, 124 | data->param_value_size, 125 | data->param_value, 126 | data->param_value_size_ret); 127 | 128 | test_icd_app_log("Value returned: %d\n", ret_val); 129 | 130 | return 0; 131 | 132 | } 133 | 134 | int test_clGetDeviceInfo(const struct clGetDeviceInfo_st* data) 135 | { 136 | cl_int ret_val; 137 | 138 | test_icd_app_log("clGetDeviceInfo(%p, %u, %u, %p, %p)\n", 139 | devices, 140 | data->param_name, 141 | data->param_value_size, 142 | data->param_value, 143 | data->param_value_size_ret); 144 | 145 | ret_val = clGetDeviceInfo(devices, 146 | data->param_name, 147 | data->param_value_size, 148 | data->param_value, 149 | data->param_value_size_ret); 150 | 151 | test_icd_app_log("Value returned: %d\n", ret_val); 152 | 153 | return 0; 154 | } 155 | 156 | int test_clCreateSubDevices(const struct clCreateSubDevices_st* data) 157 | { 158 | cl_int ret_val; 159 | 160 | test_icd_app_log("clCreateSubDevices(%p, %p, %u, %p, %p)\n", 161 | devices, 162 | data->properties, 163 | data->num_entries, 164 | &devices, 165 | data->num_devices); 166 | 167 | ret_val = clCreateSubDevices(devices, 168 | data->properties, 169 | data->num_entries, 170 | &devices, 171 | data->num_devices); 172 | 173 | test_icd_app_log("Value returned: %d\n", ret_val); 174 | 175 | return 0; 176 | } 177 | 178 | int test_clRetainDevice(const struct clRetainDevice_st* data) 179 | { 180 | (void)data; 181 | cl_int ret_val; 182 | 183 | test_icd_app_log("clRetainDevice(%p)\n", devices); 184 | 185 | ret_val = clRetainDevice(devices); 186 | 187 | test_icd_app_log("Value returned: %d\n", ret_val); 188 | 189 | return 0; 190 | } 191 | 192 | int test_platforms(void) 193 | { 194 | int i; 195 | 196 | for (i = 0;i 2 | #include "param_struct.h" 3 | #include 4 | 5 | extern cl_context context; 6 | extern cl_program program; 7 | extern cl_platform_id platform; 8 | extern cl_device_id devices; 9 | 10 | extern void CL_CALLBACK program_callback(cl_program _a, void* _b); 11 | 12 | const struct clRetainProgram_st clRetainProgramData[NUM_ITEMS_clRetainProgram]= 13 | { 14 | {NULL} 15 | }; 16 | 17 | const struct clBuildProgram_st clBuildProgramData[NUM_ITEMS_clBuildProgram]= 18 | { 19 | {NULL,0,NULL,NULL,program_callback,NULL} 20 | }; 21 | 22 | const struct clCompileProgram_st clCompileProgramData[NUM_ITEMS_clCompileProgram]= 23 | { 24 | {NULL,0,NULL,NULL,0,NULL,NULL,program_callback,NULL} 25 | }; 26 | 27 | const struct clLinkProgram_st clLinkProgramData[NUM_ITEMS_clLinkProgram]= 28 | { 29 | {NULL,0,NULL,NULL,0,NULL,program_callback,NULL,NULL} 30 | }; 31 | 32 | const struct clUnloadPlatformCompiler_st clUnloadPlatformCompilerData[NUM_ITEMS_clUnloadPlatformCompiler]= 33 | { 34 | {NULL} 35 | }; 36 | 37 | const struct clGetExtensionFunctionAddressForPlatform_st clGetExtensionFunctionAddressForPlatformData[NUM_ITEMS_clGetExtensionFunctionAddressForPlatform]= 38 | { 39 | {NULL, ""} 40 | }; 41 | 42 | const struct clGetProgramInfo_st clGetProgramInfoData[NUM_ITEMS_clGetProgramInfo]= 43 | { 44 | {NULL,0,0,NULL,NULL} 45 | }; 46 | 47 | const struct clGetProgramBuildInfo_st clGetProgramBuildInfoData[NUM_ITEMS_clGetProgramBuildInfo]= 48 | { 49 | {NULL,NULL,0,0,NULL,NULL} 50 | }; 51 | 52 | int test_clRetainProgram(const struct clRetainProgram_st *data) 53 | { 54 | (void)data; 55 | cl_int ret_val; 56 | 57 | test_icd_app_log("clRetainProgram(%p)\n", 58 | program); 59 | 60 | ret_val=clRetainProgram(program); 61 | 62 | test_icd_app_log("Value returned: %d\n", 63 | ret_val); 64 | 65 | return 0; 66 | 67 | } 68 | 69 | int test_clBuildProgram(const struct clBuildProgram_st *data) 70 | { 71 | cl_int ret_val; 72 | 73 | test_icd_app_log("clBuildProgram(%p, %u, %p, %p, %p, %p)\n", 74 | program, 75 | data->num_devices, 76 | &devices, 77 | data->options, 78 | data->pfn_notify, 79 | data->user_data); 80 | 81 | ret_val=clBuildProgram(program, 82 | data->num_devices, 83 | &devices, 84 | data->options, 85 | data->pfn_notify, 86 | data->user_data); 87 | 88 | test_icd_app_log("Value returned: %d\n", ret_val); 89 | 90 | return 0; 91 | 92 | } 93 | 94 | int test_clCompileProgram(const struct clCompileProgram_st *data) 95 | { 96 | cl_int ret_val; 97 | 98 | test_icd_app_log("clCompileProgram(%p, %u, %p, %p, %u, %p, %p, %p)\n", 99 | program, 100 | data->num_devices, 101 | &devices, 102 | data->options, 103 | data->num_input_headers, 104 | data->header_include_names, 105 | data->pfn_notify, 106 | data->user_data); 107 | 108 | ret_val=clCompileProgram(program, 109 | data->num_devices, 110 | &devices, 111 | data->options, 112 | data->num_input_headers, 113 | data->headers, 114 | data->header_include_names, 115 | data->pfn_notify, 116 | data->user_data); 117 | 118 | test_icd_app_log("Value returned: %d\n", ret_val); 119 | 120 | return 0; 121 | 122 | } 123 | 124 | int test_clLinkProgram(const struct clLinkProgram_st *data) 125 | { 126 | cl_program linked_program; 127 | cl_int ret_val; 128 | test_icd_app_log("clLinkProgram(%p, %u, %p, %p, %u, %p, %p, %p, %p)\n", 129 | context, 130 | data->num_devices, 131 | data->device_list, 132 | data->options, 133 | data->num_input_programs, 134 | data->input_programs, 135 | data->pfn_notify, 136 | data->user_data, 137 | data->errcode_ret); 138 | 139 | linked_program=clLinkProgram(context, 140 | data->num_devices, 141 | data->device_list, 142 | data->options, 143 | data->num_input_programs, 144 | data->input_programs, 145 | data->pfn_notify, 146 | data->user_data, 147 | data->errcode_ret); 148 | 149 | test_icd_app_log("Value returned: %p\n", linked_program); 150 | 151 | test_icd_app_log("clReleaseProgram(%p)\n", linked_program); 152 | ret_val = clReleaseProgram(linked_program); 153 | test_icd_app_log("Value returned: %d\n", ret_val); 154 | 155 | return 0; 156 | 157 | } 158 | 159 | int test_clUnloadPlatformCompiler(const struct clUnloadPlatformCompiler_st *data) 160 | { 161 | (void)data; 162 | cl_int ret_val; 163 | 164 | test_icd_app_log("clUnloadPlatformCompiler(%p)\n", platform); 165 | 166 | ret_val=clUnloadPlatformCompiler(platform); 167 | 168 | test_icd_app_log("Value returned: %d\n", ret_val); 169 | 170 | return 0; 171 | 172 | } 173 | 174 | int test_clGetExtensionFunctionAddressForPlatform(const struct clGetExtensionFunctionAddressForPlatform_st *data) 175 | { 176 | void *return_value; 177 | test_icd_app_log("clGetExtensionFunctionAddressForPlatform(%p, %p)\n", 178 | platform, 179 | data->func_name); 180 | 181 | return_value=clGetExtensionFunctionAddressForPlatform(platform, 182 | data->func_name); 183 | 184 | test_icd_app_log("Value returned: %p\n", return_value); 185 | 186 | return 0; 187 | 188 | } 189 | 190 | int test_clGetProgramInfo(const struct clGetProgramInfo_st *data) 191 | { 192 | cl_int ret_val; 193 | 194 | test_icd_app_log("clGetProgramInfo(%p, %u, %u, %p, %p)\n", 195 | program, 196 | data->param_name, 197 | data->param_value_size, 198 | data->param_value, 199 | data->param_value_size_ret); 200 | 201 | ret_val=clGetProgramInfo(program, 202 | data->param_name, 203 | data->param_value_size, 204 | data->param_value, 205 | data->param_value_size_ret); 206 | 207 | test_icd_app_log("Value returned: %d\n", ret_val); 208 | 209 | return 0; 210 | 211 | } 212 | 213 | int test_clGetProgramBuildInfo(const struct clGetProgramBuildInfo_st *data) 214 | { 215 | cl_int ret_val; 216 | 217 | test_icd_app_log("clGetProgramBuildInfo(%p, %p, %u, %u, %p, %p)\n", 218 | program, 219 | data->device, 220 | data->param_name, 221 | data->param_value_size, 222 | data->param_value, 223 | data->param_value_size_ret); 224 | 225 | ret_val=clGetProgramBuildInfo(program, 226 | data->device, 227 | data->param_name, 228 | data->param_value_size, 229 | data->param_value, 230 | data->param_value_size_ret); 231 | 232 | test_icd_app_log("Value returned: %d\n", ret_val); 233 | 234 | return 0; 235 | 236 | } 237 | 238 | int test_program_objects(void) 239 | { 240 | int i; 241 | 242 | for (i=0;i 2 | #include "param_struct.h" 3 | #include 4 | 5 | extern cl_sampler sampler; 6 | 7 | const struct clRetainSampler_st clRetainSamplerData[NUM_ITEMS_clRetainSampler]= 8 | { 9 | { NULL } 10 | }; 11 | 12 | const struct clGetSamplerInfo_st clGetSamplerInfoData[NUM_ITEMS_clGetSamplerInfo]= 13 | { 14 | { NULL, 0, 0, NULL, NULL } 15 | }; 16 | 17 | 18 | int test_clRetainSampler(const struct clRetainSampler_st *data) 19 | { 20 | (void)data; 21 | cl_int ret_val; 22 | 23 | test_icd_app_log("clRetainSampler(%p)\n", sampler); 24 | 25 | ret_val=clRetainSampler(sampler); 26 | 27 | test_icd_app_log("Value returned: %d\n", ret_val); 28 | 29 | return 0; 30 | } 31 | 32 | int test_clGetSamplerInfo(const struct clGetSamplerInfo_st *data) 33 | { 34 | cl_int ret_val; 35 | 36 | test_icd_app_log("clGetSamplerInfo(%p, %u, %u, %p, %p)\n", 37 | sampler, 38 | data->param_name, 39 | data->param_value_size, 40 | data->param_value, 41 | data->param_value_size_ret); 42 | 43 | ret_val=clGetSamplerInfo(sampler, 44 | data->param_name, 45 | data->param_value_size, 46 | data->param_value, 47 | data->param_value_size_ret); 48 | 49 | test_icd_app_log("Value returned: %d\n", ret_val); 50 | 51 | return 0; 52 | } 53 | 54 | int test_sampler_objects(void) 55 | { 56 | int i; 57 | 58 | for (i=0;i 2 | #include 3 | #include 4 | #include 5 | #include 6 | #include 7 | 8 | #if defined(_WIN32) 9 | #include 10 | #endif 11 | 12 | #define APP_LOG_FILE "icd_test_app_log.txt" 13 | #define STUB_LOG_FILE "icd_test_stub_log.txt" 14 | 15 | const char * log_getenv(const char *name, const char *dflt) { 16 | #if defined(_WIN32) 17 | char *retVal = NULL; 18 | DWORD valSize; 19 | 20 | valSize = GetEnvironmentVariableA(name, NULL, 0); 21 | 22 | // valSize DOES include the null terminator, so for any set variable 23 | // will always be at least 1. If it's 0, the variable wasn't set. 24 | if (valSize == 0) { 25 | if (dflt) { 26 | size_t sz = strlen(dflt) + 1; 27 | retVal = (char *)malloc(sz); 28 | if (retVal) 29 | strcpy(retVal, dflt); 30 | } 31 | return retVal; 32 | } 33 | 34 | // Allocate the space necessary for the registry entry 35 | retVal = (char *)malloc(valSize); 36 | 37 | if (NULL != retVal) { 38 | GetEnvironmentVariableA(name, retVal, valSize); 39 | } 40 | 41 | return retVal; 42 | #else 43 | const char *var = NULL; 44 | var = getenv(name); 45 | if (!var) 46 | var = dflt; 47 | return var; 48 | #endif 49 | } 50 | 51 | void log_freeenv(const char *var) { 52 | #if defined(_WIN32) 53 | if (var) 54 | free((void *)var); 55 | #else 56 | (void)var; 57 | #endif 58 | } 59 | 60 | static FILE *app_log_file; 61 | static FILE *stub_log_file; 62 | 63 | static const char *test_icd_get_app_log_file_name(void) 64 | { 65 | return log_getenv("APP_LOG_FILE", APP_LOG_FILE); 66 | } 67 | 68 | static const char *test_icd_get_stub_log_file_name(void) 69 | { 70 | return log_getenv("APP_STUB_FILE", STUB_LOG_FILE); 71 | } 72 | 73 | int test_icd_initialize_app_log(void) 74 | { 75 | const char *app_log_file_name = test_icd_get_app_log_file_name(); 76 | app_log_file = fopen(app_log_file_name, "w"); 77 | if (!app_log_file) { 78 | printf("Unable to open file %s\n", app_log_file_name); 79 | log_freeenv(app_log_file_name); 80 | return -1; 81 | } 82 | 83 | log_freeenv(app_log_file_name); 84 | return 0; 85 | } 86 | 87 | void test_icd_close_app_log(void) 88 | { 89 | fclose(app_log_file); 90 | } 91 | 92 | void test_icd_app_log(const char *format, ...) 93 | { 94 | va_list args; 95 | va_start(args, format); 96 | vfprintf(app_log_file, format, args); 97 | va_end(args); 98 | } 99 | 100 | int test_icd_initialize_stub_log(void) 101 | { 102 | const char *stub_log_file_name = test_icd_get_stub_log_file_name(); 103 | stub_log_file = fopen(stub_log_file_name, "w"); 104 | if (!stub_log_file) { 105 | printf("Unable to open file %s\n", stub_log_file_name); 106 | log_freeenv(stub_log_file_name); 107 | return -1; 108 | } 109 | 110 | log_freeenv(stub_log_file_name); 111 | return 0; 112 | } 113 | 114 | void test_icd_close_stub_log(void) 115 | { 116 | fclose(stub_log_file); 117 | } 118 | 119 | void test_icd_stub_log(const char *format, ...) 120 | { 121 | va_list args; 122 | va_start(args, format); 123 | vfprintf(stub_log_file, format, args); 124 | va_end(args); 125 | } 126 | 127 | static char *test_icd_get_log(const char *filename) 128 | { 129 | struct stat statbuf; 130 | FILE *fp; 131 | char *source = NULL; 132 | 133 | fp = fopen(filename, "rb"); 134 | log_freeenv(filename); 135 | 136 | if (fp) { 137 | size_t fsize = 0; 138 | stat(filename, &statbuf); 139 | fsize = statbuf.st_size; 140 | source = (char *)malloc(fsize+1); // +1 for NULL terminator 141 | if (source) { 142 | if (fsize) { 143 | if (fread(source, fsize, 1, fp) != 1) { 144 | free(source); 145 | source = NULL; 146 | } else { 147 | source[fsize] = '\0'; 148 | } 149 | } else { 150 | // Don't fail when fsize = 0, just return empty string 151 | source[fsize] = '\0'; 152 | } 153 | } 154 | fclose(fp); 155 | } 156 | 157 | return source; 158 | } 159 | 160 | char *test_icd_get_app_log(void) 161 | { 162 | return test_icd_get_log(test_icd_get_app_log_file_name()); 163 | } 164 | 165 | char *test_icd_get_stub_log(void) 166 | { 167 | return test_icd_get_log(test_icd_get_stub_log_file_name()); 168 | } 169 | -------------------------------------------------------------------------------- /test/pkgconfig/bare/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(PkgConfigTest 4 | LANGUAGES C 5 | ) 6 | 7 | find_package(OpenCLHeaders 8 | REQUIRED 9 | CONFIG 10 | ) 11 | find_package(OpenCLICDLoader 12 | REQUIRED 13 | CONFIG 14 | ) 15 | 16 | add_executable(${PROJECT_NAME} 17 | ../pkgconfig.c 18 | ) 19 | 20 | target_link_libraries(${PROJECT_NAME} 21 | PRIVATE 22 | OpenCL::Headers 23 | OpenCL::OpenCL 24 | ) 25 | 26 | target_compile_definitions(${PROJECT_NAME} 27 | PRIVATE 28 | CL_TARGET_OPENCL_VERSION=120 29 | ) 30 | 31 | include(CTest) 32 | 33 | add_test( 34 | NAME ${PROJECT_NAME} 35 | COMMAND ${PROJECT_NAME} 36 | ) 37 | 38 | if(DEFINED DRIVER_STUB_PATH) 39 | file(TO_CMAKE_PATH "${DRIVER_STUB_PATH}" DRIVER_STUB_PATH_CMAKE) 40 | string(REGEX MATCH ".*/" DRIVER_STUB_DIR "${DRIVER_STUB_PATH_CMAKE}") 41 | set_tests_properties(${PROJECT_NAME} 42 | PROPERTIES 43 | ENVIRONMENT "OCL_ICD_FILENAMES=${DRIVER_STUB_PATH}" 44 | WORKING_DIRECTORY "${DRIVER_STUB_DIR}" 45 | ) 46 | endif() 47 | -------------------------------------------------------------------------------- /test/pkgconfig/pkgconfig.c: -------------------------------------------------------------------------------- 1 | #ifdef __APPLE__ //Mac OSX has a different name for the header file 2 | #include 3 | #else 4 | #include 5 | #endif 6 | 7 | #include // printf 8 | #include // malloc 9 | #include // UINTMAX_MAX 10 | #include // strcmp 11 | 12 | void checkErr(cl_int err, const char * name) 13 | { 14 | if (err != CL_SUCCESS) 15 | { 16 | printf("ERROR: %s (%i)\n", name, err); 17 | exit( err ); 18 | } 19 | } 20 | 21 | int main(void) 22 | { 23 | cl_int CL_err = CL_SUCCESS; 24 | cl_uint numPlatforms = 0; 25 | cl_int stub_platform_found = CL_FALSE; 26 | 27 | CL_err = clGetPlatformIDs(0, NULL, &numPlatforms); 28 | checkErr(CL_err, "clGetPlatformIDs(numPlatforms)"); 29 | 30 | if (numPlatforms == 0) 31 | { 32 | printf("No OpenCL platform detected.\n"); 33 | exit( -1 ); 34 | } 35 | printf("Found %u platform(s)\n\n", numPlatforms); 36 | fflush(NULL); 37 | 38 | cl_platform_id* platforms = (cl_platform_id*)malloc(numPlatforms * sizeof(cl_platform_id)); 39 | CL_err = clGetPlatformIDs(numPlatforms, platforms, NULL); 40 | checkErr(CL_err, "clGetPlatformIDs(platforms)"); 41 | 42 | for (cl_uint i = 0; i < numPlatforms; ++i) 43 | { 44 | size_t vendor_length; 45 | CL_err = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, 0, NULL, &vendor_length); 46 | checkErr(CL_err, "clGetPlatformInfo(CL_PLATFORM_VENDOR, NULL, &vendor_length)"); 47 | 48 | char* platform_name = (char*)malloc(vendor_length * sizeof(char)); 49 | CL_err = clGetPlatformInfo(platforms[i], CL_PLATFORM_VENDOR, vendor_length, platform_name, NULL); 50 | checkErr(CL_err, "clGetPlatformInfo(CL_PLATFORM_VENDOR, vendor_length, platform_name)"); 51 | 52 | printf("%s\n", platform_name); 53 | 54 | if (strcmp(platform_name, "stubvendorxxx") == 0) 55 | { 56 | stub_platform_found = CL_TRUE; 57 | } 58 | 59 | fflush(NULL); 60 | free(platform_name); 61 | } 62 | 63 | if (!stub_platform_found) 64 | { 65 | printf("Did not locate stub platform\n"); 66 | return -1; 67 | } 68 | 69 | return 0; 70 | } 71 | -------------------------------------------------------------------------------- /test/pkgconfig/pkgconfig/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | find_package(PkgConfig REQUIRED) 3 | 4 | project(PkgConfigTest 5 | LANGUAGES C 6 | ) 7 | 8 | pkg_check_modules(OPENCL REQUIRED OpenCL) 9 | 10 | if(CMAKE_VERSION VERSION_LESS 3.12) 11 | link_directories("${OPENCL_LIBRARY_DIRS}") 12 | endif() 13 | 14 | add_executable(${PROJECT_NAME} 15 | ../pkgconfig.c 16 | ) 17 | 18 | target_include_directories(${PROJECT_NAME} 19 | PRIVATE 20 | ${OPENCL_INCLUDE_DIRS} 21 | ) 22 | 23 | if(CMAKE_VERSION VERSION_LESS 3.12) 24 | target_link_libraries(${PROJECT_NAME} 25 | PRIVATE 26 | ${OPENCL_LIBRARIES} 27 | ) 28 | else() 29 | target_link_libraries(${PROJECT_NAME} 30 | PRIVATE 31 | ${OPENCL_LINK_LIBRARIES} 32 | ) 33 | endif() 34 | 35 | target_compile_options(${PROJECT_NAME} 36 | PRIVATE 37 | ${OPENCL_CFLAGS_OTHER} 38 | ) 39 | 40 | target_compile_definitions(${PROJECT_NAME} 41 | PRIVATE 42 | CL_TARGET_OPENCL_VERSION=120 43 | ) 44 | 45 | include(CTest) 46 | 47 | add_test( 48 | NAME ${PROJECT_NAME} 49 | COMMAND ${PROJECT_NAME} 50 | ) 51 | 52 | if(DEFINED DRIVER_STUB_PATH) 53 | file(TO_CMAKE_PATH "${DRIVER_STUB_PATH}" DRIVER_STUB_PATH_CMAKE) 54 | string(REGEX MATCH ".*/" DRIVER_STUB_DIR "${DRIVER_STUB_PATH_CMAKE}") 55 | set_tests_properties(${PROJECT_NAME} 56 | PROPERTIES 57 | ENVIRONMENT "OCL_ICD_FILENAMES=${DRIVER_STUB_PATH}" 58 | WORKING_DIRECTORY "${DRIVER_STUB_DIR}" 59 | ) 60 | endif() 61 | -------------------------------------------------------------------------------- /test/pkgconfig/sdk/CMakeLists.txt: -------------------------------------------------------------------------------- 1 | cmake_minimum_required(VERSION 3.16) 2 | 3 | project(PkgConfigTest 4 | LANGUAGES C 5 | ) 6 | 7 | find_package(OpenCL 8 | REQUIRED 9 | CONFIG 10 | COMPONENTS 11 | Headers 12 | OpenCL 13 | ) 14 | 15 | add_executable(${PROJECT_NAME} 16 | ../pkgconfig.c 17 | ) 18 | 19 | target_link_libraries(${PROJECT_NAME} 20 | PRIVATE 21 | OpenCL::Headers 22 | OpenCL::OpenCL 23 | ) 24 | 25 | target_compile_definitions(${PROJECT_NAME} 26 | PRIVATE 27 | CL_TARGET_OPENCL_VERSION=120 28 | ) 29 | 30 | include(CTest) 31 | 32 | add_test( 33 | NAME ${PROJECT_NAME} 34 | COMMAND ${PROJECT_NAME} 35 | ) 36 | 37 | if(DEFINED DRIVER_STUB_PATH) 38 | file(TO_CMAKE_PATH "${DRIVER_STUB_PATH}" DRIVER_STUB_PATH_CMAKE) 39 | string(REGEX MATCH ".*/" DRIVER_STUB_DIR "${DRIVER_STUB_PATH_CMAKE}") 40 | set_tests_properties(${PROJECT_NAME} 41 | PROPERTIES 42 | ENVIRONMENT "OCL_ICD_FILENAMES=${DRIVER_STUB_PATH}" 43 | WORKING_DIRECTORY "${DRIVER_STUB_DIR}" 44 | ) 45 | endif() 46 | --------------------------------------------------------------------------------