diff --git a/.github/workflows/cmake.yml b/.github/workflows/cmake.yml index 8f32e6058b..a703fd8d84 100644 --- a/.github/workflows/cmake.yml +++ b/.github/workflows/cmake.yml @@ -17,6 +17,7 @@ jobs: build_type: Release compiler: {c: clang, cxx: clang++} libbacktrace: '-DVAL_USE_LIBBACKTRACE_BACKTRACE=OFF' + fuzztest: ON - os: 'ubuntu-22.04' build_type: Release compiler: {c: gcc, cxx: g++} @@ -25,6 +26,7 @@ jobs: build_type: Release compiler: {c: clang, cxx: clang++} libbacktrace: '-DVAL_USE_LIBBACKTRACE_BACKTRACE=ON' + fuzztest: ON - os: 'ubuntu-20.04' build_type: Release compiler: {c: gcc-7, cxx: g++-7} @@ -70,7 +72,6 @@ jobs: -DCMAKE_C_COMPILER=${{matrix.compiler.c}} -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} -DUR_ENABLE_TRACING=ON - -DUR_DEVELOPER_MODE=ON -DCMAKE_BUILD_TYPE=${{matrix.build_type}} -DUR_BUILD_TESTS=ON -DUR_FORMAT_CPP_STYLE=ON @@ -89,6 +90,60 @@ jobs: working-directory: ${{github.workspace}}/build run: ctest -C ${{matrix.build_type}} --output-on-failure -L "python|umf|loader|validation|tracing|unit|urtrace" + - name: Fuzz test + working-directory: ${{github.workspace}}/build + if: matrix.fuzztest == 'ON' + run: ctest -C ${{matrix.build_type}} --output-on-failure -L "fuzz" + + adapter-build: + name: Build - Adapters on Ubuntu + strategy: + matrix: + os: ['ubuntu-22.04'] + adapter: [CUDA, HIP, L0] + build_type: [Debug, Release] + compiler: [{c: gcc, cxx: g++}, {c: clang, cxx: clang++}] + + runs-on: ${{matrix.os}} + + steps: + - uses: actions/checkout@v3 + + - name: Install apt packages + run: | + sudo apt-get update + sudo apt-get install -y doxygen ${{matrix.compiler.c}} + + - name: Install pip packages + run: pip install -r third_party/requirements.txt + + - name: Install CUDA specific dependencies + if: matrix.adapter == 'CUDA' + run: | + sudo apt-get install nvidia-cuda-toolkit nvidia-cuda-toolkit-gcc + + - name: Install HIP specific dependencies + if: matrix.adapter == 'HIP' + run: | + wget https://repo.radeon.com/amdgpu-install/5.6/ubuntu/jammy/amdgpu-install_5.6.50600-1_all.deb + sudo apt install ./amdgpu-install_5.6.50600-1_all.deb + sudo amdgpu-install --usecase=rocm + + - name: Configure CMake + run: > + cmake + -B${{github.workspace}}/build + -DCMAKE_C_COMPILER=${{matrix.compiler.c}} + -DCMAKE_CXX_COMPILER=${{matrix.compiler.cxx}} + -DUR_ENABLE_TRACING=ON + -DCMAKE_BUILD_TYPE=${{matrix.build_type}} + -DUR_BUILD_TESTS=ON + -DUR_FORMAT_CPP_STYLE=ON + -DUR_BUILD_ADAPTER_${{matrix.adapter}}=ON + + - name: Build + run: cmake --build ${{github.workspace}}/build -j $(nproc) + windows-build: name: Build - Windows strategy: diff --git a/.gitignore b/.gitignore index a1a488bc14..263b72d4d4 100644 --- a/.gitignore +++ b/.gitignore @@ -83,3 +83,6 @@ out/ # IDE Files /.vscode /.devcontainer + +# External content +/external diff --git a/CMakeLists.txt b/CMakeLists.txt index b8e58472ff..9971d3f40d 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -36,6 +36,9 @@ option(UR_ENABLE_TRACING "enable api tracing through xpti" OFF) option(VAL_USE_LIBBACKTRACE_BACKTRACE "enable libbacktrace validation backtrace for linux" OFF) option(UR_BUILD_TOOLS "build ur tools" ON) option(UMF_ENABLE_POOL_TRACKING "Build UMF with pool tracking" OFF) +option(UR_BUILD_ADAPTER_L0 "build level 0 adapter from SYCL" OFF) +option(UR_BUILD_ADAPTER_CUDA "build cuda adapter from SYCL" OFF) +option(UR_BUILD_ADAPTER_HIP "build hip adapter from SYCL" OFF) set(CMAKE_LIBRARY_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) set(CMAKE_ARCHIVE_OUTPUT_DIRECTORY ${CMAKE_BINARY_DIR}/lib) @@ -88,7 +91,7 @@ if(UR_ENABLE_TRACING) set(XPTI_DIR ${xpti_SOURCE_DIR}) set(XPTI_ENABLE_TESTS OFF CACHE INTERNAL "Turn off xptifw tests") - FetchContentSparse_Declare(xptifw https://github.com/intel/llvm.git "sycl-nightly/20230304" "xptifw") + FetchContentSparse_Declare(xptifw https://github.com/intel/llvm.git "sycl-nightly/20230703" "xptifw") FetchContent_MakeAvailable(xptifw) diff --git a/README.md b/README.md index b0583f5ba4..3ef600f341 100644 --- a/README.md +++ b/README.md @@ -5,20 +5,28 @@ [![Bandit](https://github.com/oneapi-src/unified-runtime/actions/workflows/bandit.yml/badge.svg)](https://github.com/oneapi-src/unified-runtime/actions/workflows/bandit.yml) [![Coverity](https://scan.coverity.com/projects/28213/badge.svg)](https://scan.coverity.com/projects/oneapi-src-unified-runtime) +## Adapters +Adapter implementations for Unified Runtime currently reside in the [SYCL repository](https://github.com/intel/llvm/tree/sycl/sycl/plugins/unified_runtime/ur). This branch contains scripts to automatically +fetch and build them directly in the UR tree. The adapters are disabled by default, +see cmake options for details. + ## Table of contents -1. [Contents of the repo](#contents-of-the-repo) -2. [Integration](#integration) +- [Unified Runtime](#unified-runtime) + - [Adapters](#adapters) + - [Table of contents](#table-of-contents) + - [Contents of the repo](#contents-of-the-repo) + - [Integration](#integration) - [Weekly tags](#weekly-tags) -3. [Third-Party tools](#third-party-tools) -4. [Building](#building) + - [Third-Party tools](#third-party-tools) + - [Building](#building) - [Windows](#windows) - [Linux](#linux) - [CMake standard options](#cmake-standard-options) - [Additional make targets](#additional-make-targets) -5. [Contributions](#contributions) + - [Contributions](#contributions) - [Adapter naming convention](#adapter-naming-convention) - [Source code generation](#source-code-generation) - [Documentation](#documentation) @@ -112,6 +120,10 @@ List of options provided by CMake: | UR_USE_UBSAN | Enable UndefinedBehavior Sanitizer | ON/OFF | OFF | | UR_USE_MSAN | Enable MemorySanitizer (clang only) | ON/OFF | OFF | | UR_ENABLE_TRACING | Enable XPTI-based tracing layer | ON/OFF | OFF | +| UR_BUILD_ADAPTER_L0 | Fetch and use level-zero adapter from SYCL | ON/OFF | OFF | +| UR_BUILD_ADAPTER_CUDA | Fetch and use cuda adapter from SYCL | ON/OFF | OFF | +| UR_BUILD_ADAPTER_HIP | Fetch and use hip adapter from SYCL | ON/OFF | OFF | +| UR_HIP_PLATFORM | Build hip adapter for AMD or NVIDIA platform | AMD/NVIDIA | AMD | ### Additional make targets diff --git a/cmake/helpers.cmake b/cmake/helpers.cmake index f355592370..cd3497fc0e 100644 --- a/cmake/helpers.cmake +++ b/cmake/helpers.cmake @@ -109,22 +109,30 @@ endfunction() include(FetchContent) +function(FetchSource GIT_REPOSITORY GIT_TAG GIT_DIR DEST) + message(STATUS "Fetching sparse source ${GIT_DIR} from ${GIT_REPOSITORY} ${GIT_TAG}") + IF(NOT EXISTS ${DEST}) + file(MAKE_DIRECTORY ${DEST}) + execute_process(COMMAND git init + WORKING_DIRECTORY ${DEST}) + execute_process(COMMAND git checkout -b main + WORKING_DIRECTORY ${DEST}) + execute_process(COMMAND git remote add origin ${GIT_REPOSITORY} + WORKING_DIRECTORY ${DEST}) + execute_process(COMMAND git config core.sparsecheckout true + WORKING_DIRECTORY ${DEST}) + file(APPEND ${DEST}/.git/info/sparse-checkout ${GIT_DIR}/) + endif() + execute_process(COMMAND git fetch --depth=1 origin refs/tags/${GIT_TAG}:refs/tags/${GIT_TAG} + WORKING_DIRECTORY ${DEST}) + execute_process(COMMAND git checkout --quiet ${GIT_TAG} + WORKING_DIRECTORY ${DEST}) +endfunction() + # A wrapper around FetchContent_Declare that supports git sparse checkout. # This is useful for including subprojects from large repositories. function(FetchContentSparse_Declare name GIT_REPOSITORY GIT_TAG GIT_DIR) set(content-build-dir ${CMAKE_BINARY_DIR}/content-${name}) - message(STATUS "Fetching sparse content ${GIT_DIR} from ${GIT_REPOSITORY} ${GIT_TAG}") - IF(NOT EXISTS ${content-build-dir}) - file(MAKE_DIRECTORY ${content-build-dir}) - execute_process(COMMAND git init -b main - WORKING_DIRECTORY ${content-build-dir}) - execute_process(COMMAND git remote add origin ${GIT_REPOSITORY} - WORKING_DIRECTORY ${content-build-dir}) - execute_process(COMMAND git config core.sparsecheckout true - WORKING_DIRECTORY ${content-build-dir}) - file(APPEND ${content-build-dir}/.git/info/sparse-checkout ${GIT_DIR}/) - endif() - execute_process(COMMAND git pull --depth=1 origin ${GIT_TAG} - WORKING_DIRECTORY ${content-build-dir}) + FetchSource(${GIT_REPOSITORY} ${GIT_TAG} ${GIT_DIR} ${content-build-dir}) FetchContent_Declare(${name} SOURCE_DIR ${content-build-dir}/${GIT_DIR}) endfunction() diff --git a/source/adapters/CMakeLists.txt b/source/adapters/CMakeLists.txt index 767fa38735..8de581ac68 100644 --- a/source/adapters/CMakeLists.txt +++ b/source/adapters/CMakeLists.txt @@ -3,4 +3,47 @@ # See LICENSE.TXT # SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception +function(add_ur_adapter name) + add_ur_library(${name} ${ARGN}) + if(MSVC) + set(TARGET_LIBNAME ${name}) + string(TOUPPER ${TARGET_LIBNAME} TARGET_LIBNAME) + + set(ADAPTER_VERSION_SCRIPT ${name}.def) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../adapter.def.in ${ADAPTER_VERSION_SCRIPT} @ONLY) + set_target_properties(${name} PROPERTIES + LINK_FLAGS "/DEF:${ADAPTER_VERSION_SCRIPT}" + ) + elseif(APPLE) + target_compile_options(${name} PRIVATE "-fvisibility=hidden") + else() + set(TARGET_LIBNAME lib${name}_${PROJECT_VERSION_MAJOR}.0) + string(TOUPPER ${TARGET_LIBNAME} TARGET_LIBNAME) + + set(ADAPTER_VERSION_SCRIPT ${CMAKE_CURRENT_BINARY_DIR}/${name}.map) + + configure_file(${CMAKE_CURRENT_SOURCE_DIR}/../adapter.map.in ${ADAPTER_VERSION_SCRIPT} @ONLY) + target_link_options(${name} PRIVATE "-Wl,--version-script=${ADAPTER_VERSION_SCRIPT}") + endif() +endfunction() + add_subdirectory(null) + +if(UR_BUILD_ADAPTER_L0 OR UR_BUILD_ADAPTER_CUDA OR UR_BUILD_ADAPTER_HIP) + # fetch adapter sources from SYCL + set(SYCL_ADAPTER_DIR "${CMAKE_CURRENT_SOURCE_DIR}/external") + FetchSource(https://github.com/intel/llvm.git nightly-2023-08-01 "sycl/plugins/unified_runtime/ur" ${SYCL_ADAPTER_DIR}) +endif() + +if(UR_BUILD_ADAPTER_L0) + add_subdirectory(level_zero) +endif() + +if(UR_BUILD_ADAPTER_CUDA) + add_subdirectory(cuda) +endif() + +if(UR_BUILD_ADAPTER_HIP) + add_subdirectory(hip) +endif() diff --git a/source/adapters/adapter.def.in b/source/adapters/adapter.def.in new file mode 100644 index 0000000000..bfe14a6a03 --- /dev/null +++ b/source/adapters/adapter.def.in @@ -0,0 +1,20 @@ +LIBRARY @TARGET_LIBNAME@ +EXPORTS + urGetBindlessImagesExpProcAddrTable + urGetCommandBufferExpProcAddrTable + urGetContextProcAddrTable + urGetDeviceProcAddrTable + urGetEnqueueProcAddrTable + urGetEventProcAddrTable + urGetGlobalProcAddrTable + urGetKernelProcAddrTable + urGetMemProcAddrTable + urGetPhysicalMemProcAddrTable + urGetPlatformProcAddrTable + urGetProgramProcAddrTable + urGetQueueProcAddrTable + urGetSamplerProcAddrTable + urGetUSMExpProcAddrTable + urGetUsmP2PExpProcAddrTable + urGetUSMProcAddrTable + urGetVirtualMemProcAddrTable diff --git a/source/adapters/adapter.map.in b/source/adapters/adapter.map.in new file mode 100644 index 0000000000..cbb5c6c4cb --- /dev/null +++ b/source/adapters/adapter.map.in @@ -0,0 +1,23 @@ +@TARGET_LIBNAME@ { + global: + urGetBindlessImagesExpProcAddrTable; + urGetCommandBufferExpProcAddrTable; + urGetContextProcAddrTable; + urGetDeviceProcAddrTable; + urGetEnqueueProcAddrTable; + urGetEventProcAddrTable; + urGetGlobalProcAddrTable; + urGetKernelProcAddrTable; + urGetMemProcAddrTable; + urGetPhysicalMemProcAddrTable; + urGetPlatformProcAddrTable; + urGetProgramProcAddrTable; + urGetQueueProcAddrTable; + urGetSamplerProcAddrTable; + urGetUSMExpProcAddrTable; + urGetUsmP2PExpProcAddrTable; + urGetUSMProcAddrTable; + urGetVirtualMemProcAddrTable; + local: + *; +}; diff --git a/source/adapters/cuda/CMakeLists.txt b/source/adapters/cuda/CMakeLists.txt new file mode 100644 index 0000000000..f85d759c09 --- /dev/null +++ b/source/adapters/cuda/CMakeLists.txt @@ -0,0 +1,80 @@ +# Copyright (C) 2022 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set(CUDA_DIR "${SYCL_ADAPTER_DIR}/sycl/plugins/unified_runtime/ur/adapters/cuda") + +set(TARGET_NAME ur_adapter_cuda) + +add_ur_adapter(${TARGET_NAME} + SHARED + ${CUDA_DIR}/ur_interface_loader.cpp + ${CUDA_DIR}/adapter.hpp + ${CUDA_DIR}/adapter.cpp + ${CUDA_DIR}/command_buffer.hpp + ${CUDA_DIR}/command_buffer.cpp + ${CUDA_DIR}/common.hpp + ${CUDA_DIR}/common.cpp + ${CUDA_DIR}/context.hpp + ${CUDA_DIR}/context.cpp + ${CUDA_DIR}/device.hpp + ${CUDA_DIR}/device.cpp + ${CUDA_DIR}/enqueue.cpp + ${CUDA_DIR}/event.hpp + ${CUDA_DIR}/event.cpp + ${CUDA_DIR}/kernel.hpp + ${CUDA_DIR}/kernel.cpp + ${CUDA_DIR}/memory.hpp + ${CUDA_DIR}/memory.cpp + ${CUDA_DIR}/platform.hpp + ${CUDA_DIR}/platform.cpp + ${CUDA_DIR}/program.hpp + ${CUDA_DIR}/program.cpp + ${CUDA_DIR}/queue.hpp + ${CUDA_DIR}/queue.cpp + ${CUDA_DIR}/sampler.hpp + ${CUDA_DIR}/sampler.cpp + ${CUDA_DIR}/tracing.cpp + ${CUDA_DIR}/usm.cpp + ${CUDA_DIR}/usm_p2p.cpp + ${CUDA_DIR}/../../ur.cpp + ${CUDA_DIR}/../../ur.hpp +) + +set_target_properties(${TARGET_NAME} PROPERTIES + VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SOVERSION "${PROJECT_VERSION_MAJOR}" +) + +find_package(Threads REQUIRED) +find_package(CUDA 10.1 REQUIRED) + +# Make imported library global to use it within the project. +add_library(cudadrv SHARED IMPORTED GLOBAL) + +if (WIN32) + set_target_properties( + cudadrv PROPERTIES + IMPORTED_IMPLIB ${CUDA_CUDA_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${CUDA_INCLUDE_DIRS} + ) +else() + set_target_properties( + cudadrv PROPERTIES + IMPORTED_LOCATION ${CUDA_CUDA_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES ${CUDA_INCLUDE_DIRS} + ) +endif() + +target_link_libraries(${TARGET_NAME} PRIVATE + ${PROJECT_NAME}::headers + ${PROJECT_NAME}::common + ${PROJECT_NAME}::unified_malloc_framework + Threads::Threads + cudadrv +) + +target_include_directories(${TARGET_NAME} PRIVATE + ${CUDA_DIR}/../../../ +) diff --git a/source/adapters/hip/CMakeLists.txt b/source/adapters/hip/CMakeLists.txt new file mode 100644 index 0000000000..2f205d84e6 --- /dev/null +++ b/source/adapters/hip/CMakeLists.txt @@ -0,0 +1,152 @@ +# Copyright (C) 2022 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set(HIP_DIR "${SYCL_ADAPTER_DIR}/sycl/plugins/unified_runtime/ur/adapters/hip") + +set(TARGET_NAME ur_adapter_hip) + +# Set default UR HIP platform to AMD +set(UR_HIP_PLATFORM "AMD" CACHE STRING "UR HIP platform, AMD or NVIDIA") + +# Set default ROCm installation directory +set(UR_HIP_ROCM_DIR "/opt/rocm" CACHE STRING "ROCm installation dir") + +set(UR_HIP_INCLUDE_DIR "${UR_HIP_ROCM_DIR}/include") + +set(UR_HIP_HSA_INCLUDE_DIR "${UR_HIP_ROCM_DIR}/hsa/include") + +# Set HIP lib dir +set(UR_HIP_LIB_DIR "${UR_HIP_ROCM_DIR}/hip/lib") + +# Check if HIP library path exists (AMD platform only) +if("${UR_HIP_PLATFORM}" STREQUAL "AMD") + if(NOT EXISTS "${UR_HIP_LIB_DIR}") + message(FATAL_ERROR "Couldn't find the HIP library directory at '${UR_HIP_LIB_DIR}'," + " please check ROCm installation.") + endif() + # Check if HIP include path exists + if(NOT EXISTS "${UR_HIP_INCLUDE_DIR}") + message(FATAL_ERROR "Couldn't find the HIP include directory at '${UR_HIP_INCLUDE_DIR}'," + " please check ROCm installation.") + endif() + + # Check if HSA include path exists + if(NOT EXISTS "${UR_HIP_HSA_INCLUDE_DIR}") + message(FATAL_ERROR "Couldn't find the HSA include directory at '${UR_HIP_HSA_INCLUDE_DIR}'," + " please check ROCm installation.") + endif() +endif() + +# Set includes used in added library (rocmdrv) +set(HIP_HEADERS "${UR_HIP_INCLUDE_DIR};${UR_HIP_HSA_INCLUDE_DIR}") + +add_ur_adapter(${TARGET_NAME} + SHARED + ${HIP_DIR}/ur_interface_loader.cpp + ${HIP_DIR}/adapter.hpp + ${HIP_DIR}/adapter.cpp + ${HIP_DIR}/command_buffer.hpp + ${HIP_DIR}/command_buffer.cpp + ${HIP_DIR}/common.hpp + ${HIP_DIR}/common.cpp + ${HIP_DIR}/context.hpp + ${HIP_DIR}/context.cpp + ${HIP_DIR}/device.hpp + ${HIP_DIR}/device.cpp + ${HIP_DIR}/enqueue.cpp + ${HIP_DIR}/event.hpp + ${HIP_DIR}/event.cpp + ${HIP_DIR}/kernel.hpp + ${HIP_DIR}/kernel.cpp + ${HIP_DIR}/memory.hpp + ${HIP_DIR}/memory.cpp + ${HIP_DIR}/platform.hpp + ${HIP_DIR}/platform.cpp + ${HIP_DIR}/program.hpp + ${HIP_DIR}/program.cpp + ${HIP_DIR}/queue.hpp + ${HIP_DIR}/queue.cpp + ${HIP_DIR}/sampler.hpp + ${HIP_DIR}/sampler.cpp + ${HIP_DIR}/usm.cpp + ${HIP_DIR}/usm_p2p.cpp + ${HIP_DIR}/../../ur.cpp + ${HIP_DIR}/../../ur.hpp +) + +if(NOT MSVC) + target_compile_options(${TARGET_NAME} PRIVATE + -Wno-deprecated-declarations + ) +endif() + +set_target_properties(${TARGET_NAME} PROPERTIES + VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SOVERSION "${PROJECT_VERSION_MAJOR}" +) + +if("${UR_HIP_PLATFORM}" STREQUAL "AMD") + # Import HIP runtime library + add_library(rocmdrv SHARED IMPORTED GLOBAL) + + set_target_properties( + rocmdrv PROPERTIES + IMPORTED_LOCATION "${UR_HIP_LIB_DIR}/libamdhip64.so" + INTERFACE_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + ) + + target_link_libraries(${TARGET_NAME} PRIVATE + ${PROJECT_NAME}::headers + ${PROJECT_NAME}::common + ${PROJECT_NAME}::unified_malloc_framework + rocmdrv + ) + + # Set HIP define to select AMD platform + target_compile_definitions(${TARGET_NAME} PRIVATE __HIP_PLATFORM_AMD__) +elseif("${UR_HIP_PLATFORM}" STREQUAL "NVIDIA") + # Import CUDA libraries + find_package(CUDA REQUIRED) + find_package(Threads REQUIRED) + + list(APPEND HIP_HEADERS ${CUDA_INCLUDE_DIRS}) + + # cudadrv may be defined by the CUDA plugin + if(NOT TARGET cudadrv) + add_library(cudadrv SHARED IMPORTED GLOBAL) + set_target_properties( + cudadrv PROPERTIES + IMPORTED_LOCATION ${CUDA_CUDA_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + ) + endif() + + add_library(cudart SHARED IMPORTED GLOBAL) + set_target_properties( + cudart PROPERTIES + IMPORTED_LOCATION ${CUDA_CUDART_LIBRARY} + INTERFACE_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + INTERFACE_SYSTEM_INCLUDE_DIRECTORIES "${HIP_HEADERS}" + ) + + target_link_libraries(${TARGET_NAME} PRIVATE + ${PROJECT_NAME}::headers + ${PROJECT_NAME}::common + Threads::Threads + cudadrv + cudart + ) + + # Set HIP define to select NVIDIA platform + target_compile_definitions(${TARGET_NAME} PRIVATE __HIP_PLATFORM_NVIDIA__) +else() + message(FATAL_ERROR "Unspecified UR HIP platform please set UR_HIP_PLATFORM to 'AMD' or 'NVIDIA'") +endif() + +target_include_directories(${TARGET_NAME} PRIVATE + ${HIP_DIR}/../../../ +) diff --git a/source/adapters/level_zero/CMakeLists.txt b/source/adapters/level_zero/CMakeLists.txt new file mode 100644 index 0000000000..c361c230d3 --- /dev/null +++ b/source/adapters/level_zero/CMakeLists.txt @@ -0,0 +1,124 @@ +# Copyright (C) 2022 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +set(L0_DIR "${SYCL_ADAPTER_DIR}/sycl/plugins/unified_runtime/ur/adapters/level_zero") + +set(TARGET_NAME ur_adapter_level_zero) + +if (NOT DEFINED LEVEL_ZERO_LIBRARY OR NOT DEFINED LEVEL_ZERO_INCLUDE_DIR) + message(STATUS "Download Level Zero loader and headers from github.com") + + set(LEVEL_ZERO_LOADER_REPO "https://github.com/oneapi-src/level-zero.git") + set(LEVEL_ZERO_LOADER_TAG v1.11.0) + + # Disable due to a bug https://github.com/oneapi-src/level-zero/issues/104 + set(CMAKE_INCLUDE_CURRENT_DIR OFF) + # Prevent L0 loader from exporting extra symbols + set(CMAKE_WINDOWS_EXPORT_ALL_SYMBOLS OFF) + + message(STATUS "Will fetch Level Zero Loader from ${LEVEL_ZERO_LOADER_REPO}") + include(FetchContent) + FetchContent_Declare(level-zero-loader + GIT_REPOSITORY ${LEVEL_ZERO_LOADER_REPO} + GIT_TAG ${LEVEL_ZERO_LOADER_TAG} + ) + set(CMAKE_CXX_FLAGS_BAK "${CMAKE_CXX_FLAGS}") + if(MSVC) + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /WX-") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /WX-") + # FIXME: Unified runtime build fails with /DUNICODE + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /UUNICODE") + set(CMAKE_C_FLAGS "${CMAKE_C_FLAGS} /UUNICODE") + # USE_Z7 forces use of /Z7 instead of /Zi which is broken with sccache + set(USE_Z7 ON) + endif() + FetchContent_MakeAvailable(level-zero-loader) + FetchContent_GetProperties(level-zero-loader) + + set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS_BAK}") + + set(LEVEL_ZERO_LIBRARY ze_loader) + set(LEVEL_ZERO_INCLUDE_DIR + ${level-zero-loader_SOURCE_DIR}/include CACHE PATH "Path to Level Zero Headers") +endif() + +add_library (LevelZeroLoader INTERFACE) +# The MSVC linker does not like / at the start of a path, so to work around this +# we split it into a link library and a library path, where the path is allowed +# to have leading /. +get_filename_component(LEVEL_ZERO_LIBRARY_SRC "${LEVEL_ZERO_LIBRARY}" DIRECTORY) +get_filename_component(LEVEL_ZERO_LIB_NAME "${LEVEL_ZERO_LIBRARY}" NAME) +target_link_directories(LevelZeroLoader + INTERFACE "${LEVEL_ZERO_LIBRARY_SRC}" +) +target_link_libraries(LevelZeroLoader + INTERFACE "${LEVEL_ZERO_LIB_NAME}" +) + +if (NOT MSVC) + target_compile_options(${LEVEL_ZERO_LIB_NAME} PUBLIC + -Wno-unused-but-set-variable + -Wno-pedantic + -Wno-unused-parameter + -Wno-error + ) +endif() + +add_library (LevelZeroLoader-Headers INTERFACE) +target_include_directories(LevelZeroLoader-Headers + INTERFACE "${LEVEL_ZERO_INCLUDE_DIR}" +) + +add_ur_adapter(${TARGET_NAME} + SHARED + ${L0_DIR}/ur_interface_loader.cpp + ${L0_DIR}/adapter.hpp + ${L0_DIR}/adapter.cpp + ${L0_DIR}/command_buffer.hpp + ${L0_DIR}/command_buffer.cpp + ${L0_DIR}/common.hpp + ${L0_DIR}/context.hpp + ${L0_DIR}/device.hpp + ${L0_DIR}/event.hpp + ${L0_DIR}/usm.hpp + ${L0_DIR}/memory.hpp + ${L0_DIR}/kernel.hpp + ${L0_DIR}/platform.hpp + ${L0_DIR}/program.hpp + ${L0_DIR}/queue.hpp + ${L0_DIR}/sampler.hpp + ${L0_DIR}/ur_level_zero.cpp + ${L0_DIR}/common.cpp + ${L0_DIR}/context.cpp + ${L0_DIR}/device.cpp + ${L0_DIR}/event.cpp + ${L0_DIR}/usm.cpp + ${L0_DIR}/usm_p2p.cpp + ${L0_DIR}/memory.cpp + ${L0_DIR}/kernel.cpp + ${L0_DIR}/platform.cpp + ${L0_DIR}/program.cpp + ${L0_DIR}/queue.cpp + ${L0_DIR}/sampler.cpp + ${L0_DIR}/../../ur.cpp +) + +set_target_properties(${TARGET_NAME} PROPERTIES + VERSION "${PROJECT_VERSION_MAJOR}.${PROJECT_VERSION_MINOR}.${PROJECT_VERSION_PATCH}" + SOVERSION "${PROJECT_VERSION_MAJOR}" +) + +target_link_libraries(${TARGET_NAME} PRIVATE + ${PROJECT_NAME}::headers + ${PROJECT_NAME}::common + ${PROJECT_NAME}::unified_malloc_framework + LevelZeroLoader + LevelZeroLoader-Headers +) + +target_include_directories(${TARGET_NAME} PRIVATE + ${L0_DIR}/../../../ + LevelZeroLoader-Headers +) diff --git a/source/adapters/null/CMakeLists.txt b/source/adapters/null/CMakeLists.txt index 9cd093a9aa..0d4aa13e01 100644 --- a/source/adapters/null/CMakeLists.txt +++ b/source/adapters/null/CMakeLists.txt @@ -5,7 +5,7 @@ set(TARGET_NAME ur_adapter_null) -add_ur_library(${TARGET_NAME} +add_ur_adapter(${TARGET_NAME} SHARED ${CMAKE_CURRENT_SOURCE_DIR}/ur_null.hpp ${CMAKE_CURRENT_SOURCE_DIR}/ur_null.cpp @@ -21,8 +21,3 @@ target_link_libraries(${TARGET_NAME} PRIVATE ${PROJECT_NAME}::headers ${PROJECT_NAME}::common ) - -if(UNIX) - set(GCC_COVERAGE_COMPILE_FLAGS "-fvisibility=hidden -fvisibility-inlines-hidden -fno-strict-aliasing") - set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${GCC_COVERAGE_COMPILE_FLAGS}") -endif() diff --git a/source/adapters/null/ur_null.cpp b/source/adapters/null/ur_null.cpp index 18c8d89ef5..5a62761b67 100644 --- a/source/adapters/null/ur_null.cpp +++ b/source/adapters/null/ur_null.cpp @@ -163,5 +163,68 @@ context_t::context_t() { } return UR_RESULT_SUCCESS; }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.USM.pfnHostAlloc = + [](ur_context_handle_t hContext, const ur_usm_desc_t *pUSMDesc, + ur_usm_pool_handle_t pool, size_t size, void **ppMem) { + if (size == 0) { + *ppMem = nullptr; + return UR_RESULT_ERROR_UNSUPPORTED_SIZE; + } + *ppMem = malloc(size); + if (ppMem == nullptr) { + return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + return UR_RESULT_SUCCESS; + }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.USM.pfnDeviceAlloc = + [](ur_context_handle_t hContext, ur_device_handle_t hDevice, + const ur_usm_desc_t *pUSMDesc, ur_usm_pool_handle_t pool, + size_t size, void **ppMem) { + if (size == 0) { + *ppMem = nullptr; + return UR_RESULT_ERROR_UNSUPPORTED_SIZE; + } + *ppMem = malloc(size); + if (ppMem == nullptr) { + return UR_RESULT_ERROR_OUT_OF_HOST_MEMORY; + } + return UR_RESULT_SUCCESS; + }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.USM.pfnFree = [](ur_context_handle_t hContext, void *pMem) { + free(pMem); + return UR_RESULT_SUCCESS; + }; + + ////////////////////////////////////////////////////////////////////////// + urDdiTable.USM.pfnGetMemAllocInfo = + [](ur_context_handle_t hContext, const void *pMem, + ur_usm_alloc_info_t propName, size_t propSize, void *pPropValue, + size_t *pPropSizeRet) { + switch (propName) { + case UR_USM_ALLOC_INFO_TYPE: + *reinterpret_cast(pPropValue) = + pMem ? UR_USM_TYPE_DEVICE : UR_USM_TYPE_UNKNOWN; + if (pPropSizeRet != nullptr) { + *pPropSizeRet = sizeof(ur_usm_type_t); + } + break; + case UR_USM_ALLOC_INFO_SIZE: + *reinterpret_cast(pPropValue) = pMem ? SIZE_MAX : 0; + if (pPropSizeRet != nullptr) { + *pPropSizeRet = sizeof(size_t); + } + break; + default: + pPropValue = nullptr; + break; + } + return UR_RESULT_SUCCESS; + }; } } // namespace driver diff --git a/source/common/unified_malloc_framework/src/memory_provider_get_last_failed.cpp b/source/common/unified_malloc_framework/src/memory_provider_get_last_failed.cpp index c439213a26..f9af93206a 100644 --- a/source/common/unified_malloc_framework/src/memory_provider_get_last_failed.cpp +++ b/source/common/unified_malloc_framework/src/memory_provider_get_last_failed.cpp @@ -14,7 +14,7 @@ extern "C" { static thread_local umf_memory_provider_handle_t lastFailedProvider = nullptr; -umf_memory_provider_handle_t *umfGetLastFailedMemoryProviderPtr() { +umf_memory_provider_handle_t *umfGetLastFailedMemoryProviderPtr(void) { return &lastFailedProvider; } } diff --git a/source/common/unified_malloc_framework/src/memory_provider_internal.h b/source/common/unified_malloc_framework/src/memory_provider_internal.h index 07befd4b4e..2bad161706 100644 --- a/source/common/unified_malloc_framework/src/memory_provider_internal.h +++ b/source/common/unified_malloc_framework/src/memory_provider_internal.h @@ -18,7 +18,7 @@ extern "C" { #endif void *umfMemoryProviderGetPriv(umf_memory_provider_handle_t hProvider); -umf_memory_provider_handle_t *umfGetLastFailedMemoryProviderPtr(); +umf_memory_provider_handle_t *umfGetLastFailedMemoryProviderPtr(void); #ifdef __cplusplus } diff --git a/test/CMakeLists.txt b/test/CMakeLists.txt index 79ca48236c..72564667ed 100644 --- a/test/CMakeLists.txt +++ b/test/CMakeLists.txt @@ -24,3 +24,6 @@ add_subdirectory(unit) if(UR_BUILD_TOOLS) add_subdirectory(tools) endif() +if(CMAKE_CXX_COMPILER_ID STREQUAL "Clang") + add_subdirectory(fuzz) +endif() diff --git a/test/conformance/CMakeLists.txt b/test/conformance/CMakeLists.txt index 8506afaa16..eec9f37215 100644 --- a/test/conformance/CMakeLists.txt +++ b/test/conformance/CMakeLists.txt @@ -45,6 +45,7 @@ function(add_conformance_test_with_platform_environment name) endfunction() add_subdirectory(testing) +add_subdirectory(adapters) add_subdirectory(runtime) add_subdirectory(platform) @@ -61,7 +62,7 @@ if(DEFINED UR_DPCXX) add_custom_target(generate_device_binaries) set(UR_CONFORMANCE_DEVICE_BINARIES_DIR - "${CMAKE_CURRENT_BINARY_DIR}/device_binaries/") + "${CMAKE_CURRENT_BINARY_DIR}/device_binaries" CACHE INTERNAL UR_CONFORMANCE_DEVICE_BINARIES_DIR) file(MAKE_DIRECTORY ${UR_CONFORMANCE_DEVICE_BINARIES_DIR}) if(DEFINED UR_CONFORMANCE_TARGET_TRIPLES) diff --git a/test/conformance/adapters/CMakeLists.txt b/test/conformance/adapters/CMakeLists.txt new file mode 100644 index 0000000000..7b9324d5c5 --- /dev/null +++ b/test/conformance/adapters/CMakeLists.txt @@ -0,0 +1,8 @@ +# Copyright (C) 2023 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +if(UR_BUILD_ADAPTER_CUDA) + add_subdirectory(cuda) +endif() diff --git a/test/conformance/adapters/cuda/CMakeLists.txt b/test/conformance/adapters/cuda/CMakeLists.txt new file mode 100644 index 0000000000..241eb87a8c --- /dev/null +++ b/test/conformance/adapters/cuda/CMakeLists.txt @@ -0,0 +1,19 @@ +# Copyright (C) 2023 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +add_conformance_test_with_devices_environment(adapter-cuda + cuda_fixtures.h + cuda_urContextGetNativeHandle.cpp + cuda_urDeviceGetNativeHandle.cpp + cuda_urDeviceCreateWithNativeHandle.cpp + cuda_urEventGetNativeHandle.cpp + cuda_urEventCreateWithNativeHandle.cpp +) +target_link_libraries(test-adapter-cuda PRIVATE cudadrv) + +set_tests_properties(adapter-cuda PROPERTIES + LABELS "conformance:cuda" + ENVIRONMENT "UR_ADAPTERS_FORCE_LOAD=\"$\"" + ) diff --git a/test/conformance/adapters/cuda/cuda_fixtures.h b/test/conformance/adapters/cuda/cuda_fixtures.h new file mode 100644 index 0000000000..e367a4aa2c --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_fixtures.h @@ -0,0 +1,43 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#ifndef UR_TEST_CONFORMANCE_ADAPTERS_CUDA_FIXTURES_H_INCLUDED +#define UR_TEST_CONFORMANCE_ADAPTERS_CUDA_FIXTURES_H_INCLUDED +#include +#include + +namespace uur { +struct ResultCuda { + + constexpr ResultCuda(CUresult result) noexcept : value(result) {} + + inline bool operator==(const ResultCuda &rhs) const noexcept { + return rhs.value == value; + } + + CUresult value; +}; +} // namespace uur + +#ifndef ASSERT_EQ_RESULT_CUDA +#define ASSERT_EQ_RESULT_CUDA(EXPECTED, ACTUAL) \ + ASSERT_EQ(uur::ResultCuda(EXPECTED), uur::ResultCuda(ACTUAL)) +#endif // ASSERT_EQ_RESULT_CUDA + +#ifndef ASSERT_SUCCESS_CUDA +#define ASSERT_SUCCESS_CUDA(ACTUAL) ASSERT_EQ_RESULT_CUDA(CUDA_SUCCESS, ACTUAL) +#endif // ASSERT_SUCCESS_CUDA + +#ifndef EXPECT_EQ_RESULT_CUDA +#define EXPECT_EQ_RESULT_CUDA(EXPECTED, ACTUAL) \ + EXPECT_EQ_RESULT_CUDA(uur::ResultCuda(EXPECTED), uur::ResultCuda(ACTUAL)) +#endif // EXPECT_EQ_RESULT_CUDA + +#ifndef EXPECT_SUCCESS_CUDA +#define EXPECT_SUCCESS_CUDA(ACTUAL) \ + EXPECT_EQ_RESULT_CUDA(UR_RESULT_SUCCESS, ACTUAL) +#endif // EXPECT_EQ_RESULT_CUDA + +#endif // UR_TEST_CONFORMANCE_ADAPTERS_CUDA_FIXTURES_H_INCLUDED diff --git a/test/conformance/adapters/cuda/cuda_urContextGetNativeHandle.cpp b/test/conformance/adapters/cuda/cuda_urContextGetNativeHandle.cpp new file mode 100644 index 0000000000..0a2c855360 --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_urContextGetNativeHandle.cpp @@ -0,0 +1,18 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "cuda_fixtures.h" + +using urCudaContextGetNativeHandle = uur::urContextTest; +UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urCudaContextGetNativeHandle); + +TEST_P(urCudaContextGetNativeHandle, Success) { + ur_native_handle_t native_context = nullptr; + ASSERT_SUCCESS(urContextGetNativeHandle(context, &native_context)); + CUcontext cuda_context = reinterpret_cast(native_context); + + unsigned int cudaVersion; + ASSERT_SUCCESS_CUDA(cuCtxGetApiVersion(cuda_context, &cudaVersion)); +} diff --git a/test/conformance/adapters/cuda/cuda_urDeviceCreateWithNativeHandle.cpp b/test/conformance/adapters/cuda/cuda_urDeviceCreateWithNativeHandle.cpp new file mode 100644 index 0000000000..b116c9a5c9 --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_urDeviceCreateWithNativeHandle.cpp @@ -0,0 +1,23 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "cuda_fixtures.h" + +using urCudaDeviceCreateWithNativeHandle = uur::urPlatformTest; + +TEST_F(urCudaDeviceCreateWithNativeHandle, Success) { + // get a device from cuda + int nCudaDevices; + ASSERT_SUCCESS_CUDA(cuDeviceGetCount(&nCudaDevices)); + ASSERT_GT(nCudaDevices, 0); + CUdevice cudaDevice; + ASSERT_SUCCESS_CUDA(cuDeviceGet(&cudaDevice, 0)); + + ur_native_handle_t nativeCuda = + reinterpret_cast(cudaDevice); + ur_device_handle_t urDevice; + ASSERT_SUCCESS(urDeviceCreateWithNativeHandle(nativeCuda, platform, nullptr, + &urDevice)); +} diff --git a/test/conformance/adapters/cuda/cuda_urDeviceGetNativeHandle.cpp b/test/conformance/adapters/cuda/cuda_urDeviceGetNativeHandle.cpp new file mode 100644 index 0000000000..3d2cfd33b7 --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_urDeviceGetNativeHandle.cpp @@ -0,0 +1,20 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "cuda_fixtures.h" + +using urCudaGetDeviceNativeHandle = uur::urDeviceTest; +UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urCudaGetDeviceNativeHandle); + +TEST_P(urCudaGetDeviceNativeHandle, Success) { + ur_native_handle_t native_handle; + ASSERT_SUCCESS(urDeviceGetNativeHandle(device, &native_handle)); + + CUdevice cuda_device = *reinterpret_cast(&native_handle); + + char cuda_device_name[256]; + ASSERT_SUCCESS_CUDA(cuDeviceGetName(cuda_device_name, + sizeof(cuda_device_name), cuda_device)); +} diff --git a/test/conformance/adapters/cuda/cuda_urEventCreateWithNativeHandle.cpp b/test/conformance/adapters/cuda/cuda_urEventCreateWithNativeHandle.cpp new file mode 100644 index 0000000000..94ae9ad80b --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_urEventCreateWithNativeHandle.cpp @@ -0,0 +1,24 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "cuda_fixtures.h" + +using urCudaEventCreateWithNativeHandleTest = uur::urQueueTest; +UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urCudaEventCreateWithNativeHandleTest); + +TEST_P(urCudaEventCreateWithNativeHandleTest, Success) { + + CUevent cuda_event; + ASSERT_SUCCESS_CUDA(cuEventCreate(&cuda_event, CU_EVENT_DEFAULT)); + + ur_native_handle_t native_event = + reinterpret_cast(cuda_event); + + ur_event_handle_t event = nullptr; + ASSERT_SUCCESS( + urEventCreateWithNativeHandle(native_event, context, nullptr, &event)); + + ASSERT_SUCCESS(urEventRelease(event)); +} diff --git a/test/conformance/adapters/cuda/cuda_urEventGetNativeHandle.cpp b/test/conformance/adapters/cuda/cuda_urEventGetNativeHandle.cpp new file mode 100644 index 0000000000..a6185868fb --- /dev/null +++ b/test/conformance/adapters/cuda/cuda_urEventGetNativeHandle.cpp @@ -0,0 +1,30 @@ +// Copyright (C) 2022-2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "cuda_fixtures.h" + +using urCudaEventGetNativeHandleTest = uur::urQueueTest; +UUR_INSTANTIATE_DEVICE_TEST_SUITE_P(urCudaEventGetNativeHandleTest); + +TEST_P(urCudaEventGetNativeHandleTest, Success) { + constexpr size_t buffer_size = 1024; + ur_mem_handle_t mem = nullptr; + ASSERT_SUCCESS(urMemBufferCreate(context, UR_MEM_FLAG_READ_WRITE, + buffer_size, nullptr, &mem)); + + ur_event_handle_t event = nullptr; + uint8_t pattern = 6; + ASSERT_SUCCESS(urEnqueueMemBufferFill(queue, mem, &pattern, sizeof(pattern), + 0, buffer_size, 0, nullptr, &event)); + + ur_native_handle_t native_event = nullptr; + ASSERT_SUCCESS(urEventGetNativeHandle(event, &native_event)); + CUevent cuda_event = reinterpret_cast(native_event); + + ASSERT_SUCCESS_CUDA(cuEventSynchronize(cuda_event)); + + ASSERT_SUCCESS(urEventRelease(event)); + ASSERT_SUCCESS(urMemRelease(mem)); +} diff --git a/test/fuzz/CMakeLists.txt b/test/fuzz/CMakeLists.txt new file mode 100644 index 0000000000..8444e67c64 --- /dev/null +++ b/test/fuzz/CMakeLists.txt @@ -0,0 +1,35 @@ +# Copyright (C) 2023 Intel Corporation +# Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +# See LICENSE.TXT +# SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +function(add_fuzz_test name) + set(TEST_TARGET_NAME fuzztest-${name}) + add_ur_executable(${TEST_TARGET_NAME} + ${ARGN}) + target_link_libraries(${TEST_TARGET_NAME} + PRIVATE + ${PROJECT_NAME}::loader + ${PROJECT_NAME}::headers + ${PROJECT_NAME}::common + -fsanitize=fuzzer -fprofile-instr-generate -fcoverage-mapping) + add_test(NAME ${TEST_TARGET_NAME} + COMMAND ${TEST_TARGET_NAME} -max_total_time=600 -seed=1 -shrink=1 -verbosity=1 + WORKING_DIRECTORY ${CMAKE_CURRENT_BINARY_DIR}) + set_tests_properties(${TEST_TARGET_NAME} PROPERTIES + LABELS "fuzz" + ENVIRONMENT + "XPTI_TRACE_ENABLE=1" + "XPTI_FRAMEWORK_DISPATCHER=$" + "XPTI_SUBSCRIBERS=$" + "UR_ENABLE_LAYERS=UR_LAYER_TRACING" + "UR_ADAPTERS_FORCE_LOAD=\"$\"") + target_compile_options(${TEST_TARGET_NAME} PRIVATE -g -fsanitize=fuzzer -fprofile-instr-generate -fcoverage-mapping) + target_compile_definitions(${TEST_TARGET_NAME} PRIVATE -DKERNEL_IL_PATH="${UR_CONFORMANCE_DEVICE_BINARIES_DIR}/bar/sycl_spir641.spv") + target_include_directories(${TEST_TARGET_NAME} PRIVATE ${UR_CONFORMANCE_DEVICE_BINARIES_DIR}) + + add_dependencies(${TEST_TARGET_NAME} generate_device_binaries) +endfunction() + +add_fuzz_test(base + urFuzz.cpp) diff --git a/test/fuzz/urFuzz.cpp b/test/fuzz/urFuzz.cpp new file mode 100644 index 0000000000..f88b496051 --- /dev/null +++ b/test/fuzz/urFuzz.cpp @@ -0,0 +1,397 @@ +// Copyright (C) 2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include "kernel_entry_points.h" +#include "ur_api.h" +#include "utils.hpp" + +namespace fuzz { + +int ur_platform_get(TestState &state) { + ur_result_t res = urPlatformGet( + state.adapters.data(), state.adapters.size(), state.num_entries, + state.platforms.data(), &state.num_platforms); + if (res != UR_RESULT_SUCCESS) { + return -1; + } + if (state.platforms.size() != state.num_platforms) { + state.platforms.resize(state.num_platforms); + } + + return 0; +} + +int ur_device_get(TestState &state) { + if (state.platforms.empty() || + state.platform_num >= state.platforms.size() || + state.platforms[0] == nullptr) { + return -1; + } + + ur_result_t res = urDeviceGet(state.platforms[state.platform_num], + state.device_type, state.num_entries, + state.devices.data(), &state.num_devices); + if (res != UR_RESULT_SUCCESS) { + return -1; + } + if (state.devices.size() != state.num_devices) { + state.devices.resize(state.num_devices); + } + + return 0; +} + +int ur_device_release(TestState &state) { + if (state.devices.empty()) { + return -1; + } + + ur_result_t res = urDeviceRelease(state.devices.back()); + if (res == UR_RESULT_SUCCESS) { + state.devices.pop_back(); + } + + return 0; +} + +int ur_context_create(TestState &state) { + if (!check_device_exists(&state)) { + return -1; + } + + ur_context_handle_t context; + ur_result_t res = urContextCreate(state.devices.size(), + state.devices.data(), nullptr, &context); + if (res == UR_RESULT_SUCCESS) { + state.contexts.push_back(context); + } + + return 0; +} + +int ur_context_release(TestState &state) { + if (!check_context_exists(&state) || + state.contexts[state.context_num] == state.contexts.back()) { + return -1; + } + + ur_result_t res = urContextRelease(state.contexts.back()); + if (res == UR_RESULT_SUCCESS) { + state.contexts.pop_back(); + } + + return 0; +} + +int pool_create( + TestState &state, + std::map> &pool_allocs) { + if (!check_context_exists(&state)) { + return -1; + } + + ur_usm_pool_handle_t pool; + ur_usm_pool_desc_t pool_desc{UR_STRUCTURE_TYPE_USM_POOL_DESC, nullptr, + UR_USM_POOL_FLAG_ZERO_INITIALIZE_BLOCK}; + ur_result_t res = + urUSMPoolCreate(state.contexts[state.context_num], &pool_desc, &pool); + if (res == UR_RESULT_SUCCESS) { + pool_allocs[pool] = {}; + } + + return 0; +} + +int ur_usm_pool_create_host(TestState &state) { + return pool_create(state, state.pool_host_allocs); +} + +int ur_usm_pool_create_device(TestState &state) { + return pool_create(state, state.pool_device_allocs); +} + +int pool_release( + TestState &state, + std::map> &pool_allocs) { + if (!check_context_exists(&state)) { + return -1; + } + + uint8_t pool_num; + if (get_next_input_data(&state.input, &pool_num) != 0) { + return -1; + } + if (!check_pool_exists(&pool_allocs, pool_num)) { + return -1; + } + + auto &[pool, allocs] = *get_map_item(&pool_allocs, pool_num); + if (allocs.empty()) { + return -1; + } + + ur_result_t res = urUSMPoolRelease(pool); + if (res == UR_RESULT_SUCCESS) { + pool_allocs.erase(pool); + } + + return 0; +} + +int ur_usm_pool_release_host(TestState &state) { + return pool_release(state, state.pool_host_allocs); +} + +int ur_usm_pool_release_device(TestState &state) { + return pool_release(state, state.pool_device_allocs); +} + +int alloc_setup(TestState &state, uint16_t &alloc_size) { + if (!check_context_exists(&state)) { + return -1; + } + + if (get_next_input_data(&state.input, &alloc_size) != 0) { + return -1; + } + + return 0; +} + +int host_alloc(TestState &state, ur_usm_pool_handle_t pool, + std::vector &allocs) { + void *ptr; + uint16_t alloc_size; + ur_result_t res = UR_RESULT_SUCCESS; + + int ret = alloc_setup(state, alloc_size); + if (ret != 0) { + return -1; + } + + auto &context = state.contexts[state.context_num]; + res = urUSMHostAlloc(context, nullptr, pool, alloc_size, &ptr); + if (res == UR_RESULT_SUCCESS) { + allocs.push_back(ptr); + } + + return 0; +} + +int get_alloc_pool( + TestState &state, + std::map> &pool_map, + ur_usm_pool_handle_t pool, std::vector &allocs) { + uint8_t pool_num; + + if (get_next_input_data(&state.input, &pool_num) != 0) { + return -1; + } + if (!check_pool_exists(&pool_map, pool_num)) { + return -1; + } + + auto &[pool_tmp, allocs_tmp] = *get_map_item(&pool_map, pool_num); + pool = pool_tmp; + allocs = allocs_tmp; + + return 0; +} + +int ur_usm_host_alloc_pool(TestState &state) { + ur_usm_pool_handle_t pool = nullptr; + std::vector allocs; + + get_alloc_pool(state, state.pool_host_allocs, pool, allocs); + return host_alloc(state, pool, allocs); +} + +int ur_usm_host_alloc_no_pool(TestState &state) { + return host_alloc(state, nullptr, state.no_pool_host_allocs); +} + +int device_alloc(TestState &state, ur_usm_pool_handle_t pool, + std::vector &allocs) { + void *ptr; + uint16_t alloc_size; + ur_result_t res = UR_RESULT_SUCCESS; + + int ret = alloc_setup(state, alloc_size); + if (ret != 0) { + return -1; + } + + if (!check_device_exists(&state)) { + return -1; + } + + auto &context = state.contexts[state.context_num]; + auto &device = state.devices[state.device_num]; + res = urUSMDeviceAlloc(context, device, nullptr, pool, alloc_size, &ptr); + if (res == UR_RESULT_SUCCESS) { + allocs.push_back(ptr); + } + + return 0; +} + +int ur_usm_device_alloc_pool(TestState &state) { + ur_usm_pool_handle_t pool = nullptr; + std::vector allocs; + + get_alloc_pool(state, state.pool_device_allocs, pool, allocs); + return device_alloc(state, pool, allocs); +} + +int ur_usm_device_alloc_no_pool(TestState &state) { + return device_alloc(state, nullptr, state.no_pool_device_allocs); +} + +int free_pool(TestState &state, + std::map> &pool_map) { + if (pool_map.empty()) { + return -1; + } + + ur_usm_pool_handle_t pool = nullptr; + std::vector allocs; + + int ret = get_alloc_pool(state, pool_map, pool, allocs); + if (ret != 0 || allocs.empty()) { + return -1; + } + + urUSMFree(state.contexts[state.context_num], allocs.back()); + allocs.pop_back(); + + return 0; +} + +int ur_usm_free_host_pool(TestState &state) { + return free_pool(state, state.pool_host_allocs); +} + +int ur_usm_free_device_pool(TestState &state) { + return free_pool(state, state.pool_device_allocs); +} + +int free_no_pool(TestState &state, std::vector allocs) { + if (allocs.empty()) { + return -1; + } + + urUSMFree(state.contexts[state.context_num], allocs.back()); + allocs.pop_back(); + + return 0; +} + +int ur_usm_free_host_no_pool(TestState &state) { + return free_no_pool(state, state.no_pool_host_allocs); +} + +int ur_usm_free_device_no_pool(TestState &state) { + return free_no_pool(state, state.no_pool_device_allocs); +} + +// TODO: Extract API calls to separate functions +int ur_program_create_with_il(TestState &state) { + if (!check_context_exists(&state) || !check_device_exists(&state)) { + return -1; + } + + std::vector il_bin; + ur_program_handle_t program = nullptr; + ur_kernel_handle_t kernel = nullptr; + ur_queue_handle_t queue = nullptr; + ur_event_handle_t event = nullptr; + auto &context = state.contexts[state.context_num]; + auto &device = state.devices[state.device_num]; + std::string kernel_name = + uur::device_binaries::program_kernel_map["bar"][0]; + + load_kernel_source(il_bin); + urProgramCreateWithIL(context, il_bin.data(), il_bin.size(), nullptr, + &program); + urProgramBuild(context, program, nullptr); + urKernelCreate(program, kernel_name.data(), &kernel); + urQueueCreate(context, device, nullptr, &queue); + + const uint32_t nDim = 3; + const size_t gWorkOffset[] = {0, 0, 0}; + const size_t gWorkSize[] = {128, 128, 128}; + + urEnqueueKernelLaunch(queue, kernel, nDim, gWorkOffset, gWorkSize, nullptr, + 0, nullptr, &event); + + urEventWait(1, &event); + urEventRelease(event); + urQueueFinish(queue); + urQueueRelease(queue); + urKernelRelease(kernel); + urProgramRelease(program); + + return 0; +} + +extern "C" int LLVMFuzzerTestOneInput(uint8_t *data, size_t size) { + int next_api_call; + TestState test_state; + int ret = -1; + + int (*api_wrappers[])(TestState &) = { + ur_platform_get, + ur_device_get, + ur_device_release, + ur_context_create, + ur_context_release, + ur_usm_pool_create_host, + ur_usm_pool_create_device, + ur_usm_pool_release_host, + ur_usm_pool_release_device, + ur_usm_host_alloc_pool, + ur_usm_host_alloc_no_pool, + ur_usm_device_alloc_pool, + ur_usm_device_alloc_no_pool, + ur_usm_free_host_pool, + ur_usm_free_host_no_pool, + ur_usm_free_device_pool, + ur_usm_free_device_no_pool, + ur_program_create_with_il, + }; + + test_state.input = {data, size}; + + ret = init_random_data(&test_state); + if (ret == -1) { + return ret; + } + + urLoaderConfigCreate(&test_state.config); + urLoaderConfigEnableLayer(test_state.config, "UR_LAYER_FULL_VALIDATION"); + ur_result_t res = urInit(0, test_state.config); + if (res != UR_RESULT_SUCCESS) { + return -1; + } + + test_state.adapters.resize(test_state.num_entries); + res = urAdapterGet(test_state.num_entries, test_state.adapters.data(), + &test_state.num_adapters); + if (res != UR_RESULT_SUCCESS || test_state.num_adapters == 0) { + return -1; + } + + while ((next_api_call = get_next_api_call(&test_state.input)) != -1) { + ret = api_wrappers[next_api_call](test_state); + if (ret) { + cleanup(&test_state); + return -1; + } + } + + cleanup(&test_state); + return 0; +} +} // namespace fuzz diff --git a/test/fuzz/utils.hpp b/test/fuzz/utils.hpp new file mode 100644 index 0000000000..330473a4b4 --- /dev/null +++ b/test/fuzz/utils.hpp @@ -0,0 +1,199 @@ +// Copyright (C) 2023 Intel Corporation +// Part of the Unified-Runtime Project, under the Apache License v2.0 with LLVM Exceptions. +// See LICENSE.TXT +// SPDX-License-Identifier: Apache-2.0 WITH LLVM-exception + +#include +#include +#include +#include +#include + +namespace fuzz { + +enum FuzzerAPICall { + UR_PLATFORM_GET, + UR_DEVICE_GET, + UR_DEVICE_RELEASE, + UR_CONTEXT_CREATE, + UR_CONTEXT_RELEASE, + UR_USM_POOL_CREATE_HOST, + UR_USM_POOL_CREATE_DEVICE, + UR_USM_POOL_RELEASE_HOST, + UR_USM_POOL_RELEASE_DEVICE, + UR_USM_HOST_ALLOC_POOL, + UR_USM_HOST_ALLOC_NO_POOL, + UR_USM_DEVICE_ALLOC_POOL, + UR_USM_DEVICE_ALLOC_NO_POOL, + UR_USM_FREE_HOST_POOL, + UR_USM_FREE_HOST_NO_POOL, + UR_USM_FREE_DEVICE_POOL, + UR_USM_FREE_DEVICE_NO_POOL, + UR_PROGRAM_CREATE_WITH_IL, + UR_MAX_FUZZER_API_CALL, +}; + +typedef struct FuzzerInput { + uint8_t *data_ptr; + size_t data_size; +} FuzzerInput; + +typedef struct TestState { + static constexpr uint32_t num_entries = 1; + + FuzzerInput input; + ur_loader_config_handle_t config; + + std::vector adapters; + std::vector platforms; + std::vector devices; + std::vector contexts; + std::map> pool_host_allocs; + std::map> pool_device_allocs; + std::vector no_pool_host_allocs; + std::vector no_pool_device_allocs; + ur_device_type_t device_type = UR_DEVICE_TYPE_ALL; + + uint32_t num_adapters; + uint32_t num_platforms; + uint32_t num_devices; + + uint8_t platform_num; + uint8_t device_num; + uint8_t context_num; + uint8_t device_type_fuzz; +} TestState; + +////////////////////////////////////////////////////////////////////////////// +template int get_next_input_data(FuzzerInput *input, T *out_data) { + size_t out_data_size = sizeof(out_data); + if (input->data_size == 0 || input->data_size < out_data_size) { + return -1; + } + *out_data = *input->data_ptr; + input->data_ptr += out_data_size; + input->data_size -= out_data_size; + + return 0; +} + +int init_random_data(TestState *state) { + if (state->input.data_size < 5) { + return -1; + } + get_next_input_data(&state->input, &state->platform_num); + get_next_input_data(&state->input, &state->device_num); + get_next_input_data(&state->input, &state->context_num); + get_next_input_data(&state->input, &state->device_type_fuzz); + if (state->device_type_fuzz < 1 || state->device_type_fuzz > 7) { + return -1; + } + state->device_type = static_cast(state->device_type_fuzz); + + return 0; +} + +int get_next_api_call(FuzzerInput *input) { + uint8_t next_api_call; + if (get_next_input_data(input, &next_api_call) != 0) { + return -1; + } + return next_api_call % UR_MAX_FUZZER_API_CALL; +} + +bool check_device_exists(const TestState *state) { + if (state->devices.empty() || state->device_num >= state->devices.size() || + state->devices[0] == nullptr) { + return false; + } + + return true; +} + +bool check_context_exists(const TestState *state) { + if (state->contexts.empty() || + state->context_num >= state->contexts.size() || + state->contexts[0] == nullptr) { + return false; + } + + return true; +} + +bool check_pool_exists( + const std::map> *map, + const uint8_t pool_num) { + if (pool_num >= map->size()) { + return false; + } + + return true; +} + +auto get_map_item(std::map> *map, + const uint8_t item_index) { + auto map_it = map->begin(); + std::advance(map_it, item_index); + + return map_it; +} + +int load_kernel_source(std::vector &binary_out) { + std::string source_path = KERNEL_IL_PATH; + + std::ifstream source_file; + source_file.open(source_path, + std::ios::binary | std::ios::in | std::ios::ate); + if (!source_file.is_open()) { + std::cerr << "Failed to open a kernel source file: " << source_path + << std::endl; + return -1; + } + + size_t source_size = static_cast(source_file.tellg()); + source_file.seekg(0, std::ios::beg); + + std::vector device_binary(source_size); + source_file.read(device_binary.data(), source_size); + if (!source_file) { + source_file.close(); + std::cerr << "failed reading kernel source data from file: " + << source_path << std::endl; + return -1; + } + source_file.close(); + + binary_out = std::vector(std::move(device_binary)); + + return 0; +} + +void cleanup(TestState *state) { + urLoaderConfigRelease(state->config); + + for (auto &[pool, allocs] : state->pool_host_allocs) { + for (auto &alloc : allocs) { + urUSMFree(state->contexts[state->context_num], alloc); + } + urUSMPoolRelease(pool); + } + for (auto &[pool, allocs] : state->pool_device_allocs) { + for (auto &alloc : allocs) { + urUSMFree(state->contexts[state->context_num], alloc); + } + urUSMPoolRelease(pool); + } + for (auto &alloc : state->no_pool_host_allocs) { + urUSMFree(state->contexts[state->context_num], alloc); + } + for (auto &alloc : state->no_pool_device_allocs) { + urUSMFree(state->contexts[state->context_num], alloc); + } + for (auto &context : state->contexts) { + urContextRelease(context); + } + for (auto &device : state->devices) { + urDeviceRelease(device); + } +} +} // namespace fuzz diff --git a/test/loader/platforms/CMakeLists.txt b/test/loader/platforms/CMakeLists.txt index 7c1e7315ec..86f8eea085 100644 --- a/test/loader/platforms/CMakeLists.txt +++ b/test/loader/platforms/CMakeLists.txt @@ -33,5 +33,5 @@ function(add_loader_platform_test name ENV) ) endfunction() -add_loader_platform_test(no_platforms "") +add_loader_platform_test(no_platforms "UR_ADAPTERS_FORCE_LOAD=\"\"") add_loader_platform_test(null_platform "UR_ADAPTERS_FORCE_LOAD=\"$\"") diff --git a/test/loader/platforms/platforms.cpp b/test/loader/platforms/platforms.cpp index 2a665fe8d6..bb4f8fb79d 100644 --- a/test/loader/platforms/platforms.cpp +++ b/test/loader/platforms/platforms.cpp @@ -19,17 +19,17 @@ using namespace logger; ////////////////////////////////////////////////////////////////////////// int main(int argc, char *argv[]) { - logger::init("TEST"); + auto out = create_logger("TEST"); ur_result_t status; // Initialize the platform status = urInit(0, nullptr); if (status != UR_RESULT_SUCCESS) { - error("urInit failed with return code: {}", status); + out.error("urInit failed with return code: {}", status); return 1; } - info("urInit succeeded."); + out.info("urInit succeeded."); uint32_t adapterCount = 0; std::vector adapters; @@ -52,16 +52,16 @@ int main(int argc, char *argv[]) { status = urPlatformGet(adapters.data(), adapterCount, 1, nullptr, &platformCount); if (status != UR_RESULT_SUCCESS) { - error("urPlatformGet failed with return code: {}", status); + out.error("urPlatformGet failed with return code: {}", status); goto out; } - info("urPlatformGet found {} platforms", platformCount); + out.info("urPlatformGet found {} platforms", platformCount); platforms.resize(platformCount); status = urPlatformGet(adapters.data(), adapterCount, platformCount, platforms.data(), nullptr); if (status != UR_RESULT_SUCCESS) { - error("urPlatformGet failed with return code: {}", status); + out.error("urPlatformGet failed with return code: {}", status); goto out; } @@ -70,7 +70,7 @@ int main(int argc, char *argv[]) { status = urPlatformGetInfo(p, UR_PLATFORM_INFO_NAME, 0, nullptr, &name_len); if (status != UR_RESULT_SUCCESS) { - error("urPlatformGetInfo failed with return code: {}", status); + out.error("urPlatformGetInfo failed with return code: {}", status); goto out; } @@ -80,11 +80,11 @@ int main(int argc, char *argv[]) { status = urPlatformGetInfo(p, UR_PLATFORM_INFO_NAME, name_len, name, nullptr); if (status != UR_RESULT_SUCCESS) { - error("urPlatformGetInfo failed with return code: {}", status); + out.error("urPlatformGetInfo failed with return code: {}", status); free(name); goto out; } - info("Found {} ", name); + out.info("Found {} ", name); free(name); }