Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion .cirun.yml
Original file line number Diff line number Diff line change
Expand Up @@ -17,7 +17,7 @@ runners:
# Add a label to match runs-on param in Github Actions yml files
labels:
- gpu

- name: notebook-gpu-runner
# Cloud Provider: Amazon Web Services
cloud: aws
Expand Down
11 changes: 11 additions & 0 deletions .gersemi.config
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
## Gersemi configuration for ITKVkFFTBackend (no CMake/stubs)
# yaml-language-server: $schema=https://raw.githubusercontent.com/BlankSpruce/gersemi/0.19.3/gersemi/configuration.schema.json

disable_formatting: false
extensions: []
# use ITK preferred 2 space indent
indent: 2
line_length: 80
list_expansion: favour-expansion
unsafe: false
warn_about_unknown_commands: false
42 changes: 42 additions & 0 deletions .pre-commit-config.yaml
Original file line number Diff line number Diff line change
@@ -0,0 +1,42 @@
# .pre-commit-config.yaml
# for details see https://pre-commit.com
# Hook versions are pinned to match the upstream ITK toolchain so that
# formatting stays byte-identical with ITK CI (gersemi in particular is
# not forward/backward compatible across releases).
fail_fast: true
repos:
- repo: https://github.com/pre-commit/pre-commit-hooks
rev: v6.0.0
hooks:
- id: check-added-large-files
args: ['--maxkb=200']
- id: check-merge-conflict
args: ['--assume-in-merge']
- id: end-of-file-fixer
- id: trailing-whitespace

- repo: https://github.com/pre-commit/mirrors-clang-format
rev: v19.1.7
hooks:
- id: clang-format
args: ['--style=file']
files: '\.(c|cc|h|cxx|hxx|cu)$'

- repo: https://github.com/psf/black
rev: 24.2.0
hooks:
- id: black
args: ['--target-version', 'py310']

- repo: https://github.com/asottile/pyupgrade
rev: v3.21.2
hooks:
- id: pyupgrade
args: ['--py310-plus']

- repo: https://github.com/BlankSpruce/gersemi
rev: 0.19.3
hooks:
- id: gersemi
args: ['--config', '.gersemi.config', '-i']
files: '\.(cmake|wrap)$|CMakeLists.txt'
208 changes: 160 additions & 48 deletions CMakeLists.txt
Original file line number Diff line number Diff line change
Expand Up @@ -15,59 +15,105 @@ include(FetchContent)

#### Set up VkFFT flags ####

set(VKFFT_BACKEND 3 CACHE STRING "0 - Vulkan, 1 - CUDA, 2 - HIP, 3 - OpenCL, 4 - Level Zero, 5 - Metal")
# itk-module-init.cmake normally establishes VKFFT_BACKEND (with auto-detection);
# this is the fallback default when that file was not included first.
if(NOT DEFINED VKFFT_BACKEND)
set(
VKFFT_BACKEND
3
CACHE STRING
"0 - Vulkan, 1 - CUDA, 2 - HIP, 3 - OpenCL, 4 - Level Zero, 5 - Metal"
)
endif()
add_compile_definitions(VKFFT_BACKEND=${VKFFT_BACKEND})

if(VKFFT_BACKEND EQUAL 1)
find_package(CUDAToolkit REQUIRED)
list(APPEND VkFFTBackend_SYSTEM_INCLUDE_DIRS ${CUDAToolkit_INCLUDE_DIRS})
elseif(VKFFT_BACKEND EQUAL 3)
set(CL_TARGET_OPENCL_VERSION 300 CACHE STRING "OpenCL API version to target (e.g. 120, 300)")
set(
CL_TARGET_OPENCL_VERSION
300
CACHE STRING
"OpenCL API version to target (e.g. 120, 300)"
)
add_compile_definitions(CL_TARGET_OPENCL_VERSION=${CL_TARGET_OPENCL_VERSION})

## When this module is loaded by an app, load OpenCL too.
set(VkFFTBackend_EXPORT_CODE_INSTALL "
set(
VkFFTBackend_EXPORT_CODE_INSTALL
"
set(OpenCL_DIR \"${OpenCL_DIR}\")
find_package(OpenCL REQUIRED)
")
set(VkFFTBackend_EXPORT_CODE_BUILD "
"
)
set(
VkFFTBackend_EXPORT_CODE_BUILD
"
if(NOT ITK_BINARY_DIR)
set(OpenCL_DIR \"${OpenCL_DIR}\")
find_package(OpenCL REQUIRED)
endif()
")
"
)
list(APPEND VkFFTBackend_SYSTEM_INCLUDE_DIRS ${OpenCL_INCLUDE_DIRS})
get_filename_component(OpenCL_LIB_DIR ${OpenCL_LIBRARY} DIRECTORY)
set(VkFFTBackend_SYSTEM_LIBRARY_DIRS ${OpenCL_LIB_DIR})
elseif(VKFFT_BACKEND EQUAL 4)
# oneAPI Level Zero loader (libze_loader) + headers (<level_zero/ze_api.h>).
# Installed by Intel's "level-zero" package on Linux/Windows; also shipped
# with the oneAPI Base Toolkit.
find_path(LevelZero_INCLUDE_DIR
NAMES level_zero/ze_api.h
HINTS ENV LEVEL_ZERO_ROOT ENV CMPLR_ROOT
PATH_SUFFIXES include)
find_library(LevelZero_LIBRARY
NAMES ze_loader
HINTS ENV LEVEL_ZERO_ROOT ENV CMPLR_ROOT
PATH_SUFFIXES lib lib64 lib/x64)
find_path(
LevelZero_INCLUDE_DIR
NAMES
level_zero/ze_api.h
HINTS
ENV LEVEL_ZERO_ROOT
ENV CMPLR_ROOT
PATH_SUFFIXES
include
)
find_library(
LevelZero_LIBRARY
NAMES
ze_loader
HINTS
ENV LEVEL_ZERO_ROOT
ENV CMPLR_ROOT
PATH_SUFFIXES
lib
lib64
lib/x64
)
if(NOT LevelZero_INCLUDE_DIR OR NOT LevelZero_LIBRARY)
message(FATAL_ERROR "VKFFT_BACKEND=4 (Level Zero) requires the oneAPI Level Zero loader (ze_loader) and headers (level_zero/ze_api.h). Install the 'level-zero' package or set LEVEL_ZERO_ROOT.")
message(
FATAL_ERROR
"VKFFT_BACKEND=4 (Level Zero) requires the oneAPI Level Zero loader (ze_loader) and headers (level_zero/ze_api.h). Install the 'level-zero' package or set LEVEL_ZERO_ROOT."
)
endif()
# VkFFT includes <ze_api.h> bare; this module uses <level_zero/ze_api.h> — both dirs needed.
list(APPEND VkFFTBackend_SYSTEM_INCLUDE_DIRS
list(
APPEND
VkFFTBackend_SYSTEM_INCLUDE_DIRS
${LevelZero_INCLUDE_DIR}
${LevelZero_INCLUDE_DIR}/level_zero)
${LevelZero_INCLUDE_DIR}/level_zero
)
list(APPEND VkFFTBackend_SYSTEM_LIBRARIES ${LevelZero_LIBRARY})

set(VkFFTBackend_EXPORT_CODE_INSTALL "
set(
VkFFTBackend_EXPORT_CODE_INSTALL
"
find_path(LevelZero_INCLUDE_DIR NAMES level_zero/ze_api.h)
find_library(LevelZero_LIBRARY NAMES ze_loader)
")
"
)
set(VkFFTBackend_EXPORT_CODE_BUILD "${VkFFTBackend_EXPORT_CODE_INSTALL}")
elseif(VKFFT_BACKEND EQUAL 5)
if(NOT APPLE)
message(FATAL_ERROR "VKFFT_BACKEND=5 (Metal) requires Apple platforms (macOS/iOS).")
message(
FATAL_ERROR
"VKFFT_BACKEND=5 (Metal) requires Apple platforms (macOS/iOS)."
)
endif()

# metal-cpp requires C++17.
Expand All @@ -90,20 +136,39 @@ elseif(VKFFT_BACKEND EQUAL 5)
find_library(METAL_FRAMEWORK Metal REQUIRED)
find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
find_library(QUARTZCORE_FRAMEWORK QuartzCore REQUIRED)
list(APPEND VkFFTBackend_SYSTEM_LIBRARIES
${METAL_FRAMEWORK} ${FOUNDATION_FRAMEWORK} ${QUARTZCORE_FRAMEWORK})
list(
APPEND
VkFFTBackend_SYSTEM_LIBRARIES
${METAL_FRAMEWORK}
${FOUNDATION_FRAMEWORK}
${QUARTZCORE_FRAMEWORK}
)

set(VkFFTBackend_EXPORT_CODE_INSTALL "
set(
VkFFTBackend_EXPORT_CODE_INSTALL
"
find_library(METAL_FRAMEWORK Metal REQUIRED)
find_library(FOUNDATION_FRAMEWORK Foundation REQUIRED)
find_library(QUARTZCORE_FRAMEWORK QuartzCore REQUIRED)
")
"
)
set(VkFFTBackend_EXPORT_CODE_BUILD "${VkFFTBackend_EXPORT_CODE_INSTALL}")
else()
message(WARNING "ITKVkFFTBackend currently supports only CUDA, OpenCL, Level Zero, or Metal backends.")
message(
WARNING
"ITKVkFFTBackend currently supports only CUDA, OpenCL, Level Zero, or Metal backends."
)
endif()

if (CMAKE_CXX_COMPILER_ID STREQUAL "Clang" OR CMAKE_CXX_COMPILER_ID STREQUAL "GNU")
if(
CMAKE_CXX_COMPILER_ID
STREQUAL
"Clang"
OR
CMAKE_CXX_COMPILER_ID
STREQUAL
"GNU"
)
# Remove this list of disabled warnings when VkFFT has been updated
message("Adding compile options: -Wno-format-overflow")
add_compile_options(-Wno-format-overflow)
Expand All @@ -113,7 +178,11 @@ elseif(CMAKE_CXX_COMPILER_ID STREQUAL "MSVC")
# C4146: unary minus operator applied to unsigned type, result still unsigned
# C4244: 'argument': conversion from 'double' to 'uint64_t', possible loss of data
# C4996: 'sprintf': This function or variable may be unsafe. Consider using sprintf_s instead.
add_compile_options(/wd4146 /wd4244 /wd4996)
add_compile_options(
/wd4146
/wd4244
/wd4996
)
endif()

#### Populate VkFFT dependency ###
Expand All @@ -125,22 +194,33 @@ endif()

set(VkFFT_GIT_TAG "v1.3.4")
set(VkFFT_GIT_REPOSITORY "https://github.com/DTolm/VkFFT")
set(VkFFT_HEADER_URL "https://raw.githubusercontent.com/DTolm/VkFFT/${VkFFT_GIT_TAG}/vkFFT/vkFFT.h")
set(
VkFFT_HEADER_URL
"https://raw.githubusercontent.com/DTolm/VkFFT/${VkFFT_GIT_TAG}/vkFFT/vkFFT.h"
)

# v1.3.x split vkFFT.h into a multi-file tree, so the single-header URL
# fetch no longer suffices; force the full-repo path when not overridden.
option(BUILD_VKFFT "Fetch the full VkFFT repo (required for v1.3+ multi-file layout)" ON)
option(
BUILD_VKFFT
"Fetch the full VkFFT repo (required for v1.3+ multi-file layout)"
ON
)
if(BUILD_VKFFT)
# Fetch the full VkFFT repo with the header-only library and build targets
FetchContent_Declare(
vkfft_lib
GIT_REPOSITORY ${VkFFT_GIT_REPOSITORY}
GIT_TAG ${VkFFT_GIT_TAG}
)
)
FetchContent_GetProperties(vkfft_lib)
if(NOT vkfft_lib_POPULATED)
FetchContent_Populate(vkfft_lib)
add_subdirectory(${vkfft_lib_SOURCE_DIR} ${vkfft_lib_BINARY_DIR} EXCLUDE_FROM_ALL)
add_subdirectory(
${vkfft_lib_SOURCE_DIR}
${vkfft_lib_BINARY_DIR}
EXCLUDE_FROM_ALL
)
endif()

set(vkfft_INCLUDE_DIR "${vkfft_lib_SOURCE_DIR}/vkFFT")
Expand All @@ -149,7 +229,8 @@ else()
set(vkfft_INCLUDE_DIR "${CMAKE_CURRENT_BINARY_DIR}/_deps/include")
FetchContent_Declare(
vkfft_header_only
URL ${VkFFT_HEADER_URL}
URL
${VkFFT_HEADER_URL}
DOWNLOAD_DIR "${vkfft_INCLUDE_DIR}"
DOWNLOAD_NO_EXTRACT TRUE
)
Expand All @@ -170,7 +251,12 @@ endif()

if(VKFFT_BACKEND EQUAL 4)
target_link_libraries(VkFFTBackend PUBLIC ${LevelZero_LIBRARY})
target_include_directories(VkFFTBackend SYSTEM PUBLIC ${LevelZero_INCLUDE_DIR})
target_include_directories(
VkFFTBackend
SYSTEM
PUBLIC
${LevelZero_INCLUDE_DIR}
)

# Probe at configure time whether a Level Zero driver implementation is
# actually present on this host (the loader can be installed without any
Expand All @@ -180,34 +266,60 @@ if(VKFFT_BACKEND EQUAL 4)
# stays clean.
if(BUILD_TESTING)
set(_probe_src "${CMAKE_CURRENT_BINARY_DIR}/level_zero_probe.cxx")
file(WRITE "${_probe_src}" [=[
file(
WRITE
"${_probe_src}"
[=[
#include <level_zero/ze_api.h>
int main(){
if (zeInit(0) != ZE_RESULT_SUCCESS) return 1;
uint32_t n = 0;
if (zeDriverGet(&n, nullptr) != ZE_RESULT_SUCCESS) return 1;
return n > 0 ? 0 : 1;
}
]=])
try_run(VkFFTBackend_LEVEL_ZERO_RUNTIME_RUN
VkFFTBackend_LEVEL_ZERO_RUNTIME_COMPILE
"${CMAKE_CURRENT_BINARY_DIR}/level_zero_probe"
SOURCES "${_probe_src}"
CMAKE_FLAGS "-DINCLUDE_DIRECTORIES=${LevelZero_INCLUDE_DIR};${LevelZero_INCLUDE_DIR}/level_zero"
LINK_LIBRARIES ${LevelZero_LIBRARY})
if(NOT VkFFTBackend_LEVEL_ZERO_RUNTIME_COMPILE OR NOT VkFFTBackend_LEVEL_ZERO_RUNTIME_RUN EQUAL 0)
message(STATUS "VkFFTBackend: no working Level Zero driver detected (zeInit/zeDriverGet probe failed); FFT tests will be DISABLED.")
]=]
)
try_run(
VkFFTBackend_LEVEL_ZERO_RUNTIME_RUN
VkFFTBackend_LEVEL_ZERO_RUNTIME_COMPILE
"${CMAKE_CURRENT_BINARY_DIR}/level_zero_probe"
SOURCES
"${_probe_src}"
CMAKE_FLAGS
"-DINCLUDE_DIRECTORIES=${LevelZero_INCLUDE_DIR};${LevelZero_INCLUDE_DIR}/level_zero"
LINK_LIBRARIES
${LevelZero_LIBRARY}
)
if(
NOT
VkFFTBackend_LEVEL_ZERO_RUNTIME_COMPILE
OR
NOT
VkFFTBackend_LEVEL_ZERO_RUNTIME_RUN
EQUAL
0
)
message(
STATUS
"VkFFTBackend: no working Level Zero driver detected (zeInit/zeDriverGet probe failed); FFT tests will be DISABLED."
)
set(VkFFTBackend_LEVEL_ZERO_RUNTIME_AVAILABLE FALSE CACHE INTERNAL "")
else()
message(STATUS "VkFFTBackend: Level Zero runtime probe found at least one driver.")
message(
STATUS
"VkFFTBackend: Level Zero runtime probe found at least one driver."
)
set(VkFFTBackend_LEVEL_ZERO_RUNTIME_AVAILABLE TRUE CACHE INTERNAL "")
endif()
endif()
endif()


if(VKFFT_BACKEND EQUAL 5)
target_link_libraries(VkFFTBackend PUBLIC
${METAL_FRAMEWORK} ${FOUNDATION_FRAMEWORK} ${QUARTZCORE_FRAMEWORK})
target_link_libraries(
VkFFTBackend
PUBLIC
${METAL_FRAMEWORK}
${FOUNDATION_FRAMEWORK}
${QUARTZCORE_FRAMEWORK}
)
endif()

2 changes: 1 addition & 1 deletion example/AcceleratedForwardFFT.ipynb
Original file line number Diff line number Diff line change
Expand Up @@ -289,4 +289,4 @@
},
"nbformat": 4,
"nbformat_minor": 5
}
}
Loading
Loading