## Copyright 2009 Intel Corporation ## SPDX-License-Identifier: Apache-2.0 include(CMakeFindDependencyMacro) ## Macro for printing CMake variables ## macro(print var) message("${var} = ${${var}}") endmacro() ## Get a list of subdirectories (single level) under a given directory macro(get_subdirectories result curdir) file(GLOB children RELATIVE ${curdir} ${curdir}/*) set(dirlist "") foreach(child ${children}) if(IS_DIRECTORY ${curdir}/${child}) list(APPEND dirlist ${child}) endif() endforeach() set(${result} ${dirlist}) endmacro() ## Get all subdirectories and call add_subdirectory() if it has a CMakeLists.txt macro(add_all_subdirectories_except except) set(e ${except}) file(GLOB dirs RELATIVE ${CMAKE_CURRENT_SOURCE_DIR}/ *) foreach(dir ${dirs}) if (NOT "${dir}X" STREQUAL "${except}X" AND EXISTS ${CMAKE_CURRENT_SOURCE_DIR}/${dir}/CMakeLists.txt) add_subdirectory(${dir}) endif() endforeach() endmacro() macro(add_all_subdirectories) add_all_subdirectories_except("") endmacro() ## Setup CMAKE_BUILD_TYPE to have a default + cycle between options in UI macro(ospray_configure_build_type) set(CONFIGURATION_TYPES "Debug;Release;RelWithDebInfo") if(NOT CMAKE_BUILD_TYPE) set(CMAKE_BUILD_TYPE "Release" CACHE STRING "Choose the build type." FORCE) endif() if (WIN32) if (NOT OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET) set(CMAKE_CONFIGURATION_TYPES "${CONFIGURATION_TYPES}" CACHE STRING "List of generated configurations." FORCE) set(OSPRAY_DEFAULT_CMAKE_CONFIGURATION_TYPES_SET ON CACHE INTERNAL "Default CMake configuration types set.") endif() else() set_property(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS ${CONFIGURATION_TYPES}) endif() if (${CMAKE_BUILD_TYPE} STREQUAL "Release") set(OSPRAY_BUILD_RELEASE TRUE ) set(OSPRAY_BUILD_DEBUG FALSE) set(OSPRAY_BUILD_RELWITHDEBINFO FALSE) elseif (${CMAKE_BUILD_TYPE} STREQUAL "Debug") set(OSPRAY_BUILD_RELEASE FALSE) set(OSPRAY_BUILD_DEBUG TRUE ) set(OSPRAY_BUILD_RELWITHDEBINFO FALSE) else() set(OSPRAY_BUILD_RELEASE FALSE) set(OSPRAY_BUILD_DEBUG FALSE) set(OSPRAY_BUILD_RELWITHDEBINFO TRUE ) endif() endmacro() # workaround link issues to Embree ISPC exports # ISPC only adds the ISA suffix during name mangling (and dynamic dispatch # code) when compiling for multiple targets. Thus, when only one OSPRay ISA is # selected, but Embree was compiled for multiple ISAs, we need to add a # second, different, supported dummy target. macro(ospray_fix_ispc_target_list) list(LENGTH OSPRAY_ISPC_TARGET_LIST NUM_TARGETS) if (NUM_TARGETS EQUAL 1 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x4" AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x8") if (EMBREE_ISA_SSE42 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "sse4") list(APPEND OSPRAY_ISPC_TARGET_LIST sse4) elseif (EMBREE_ISA_AVX AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx") list(APPEND OSPRAY_ISPC_TARGET_LIST avx) elseif (EMBREE_ISA_AVX2 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx2") list(APPEND OSPRAY_ISPC_TARGET_LIST avx2) elseif (EMBREE_ISA_AVX512 AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "avx512skx-i32x16") list(APPEND OSPRAY_ISPC_TARGET_LIST avx512skx-i32x16) elseif (EMBREE_ISA_NEON AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x4") list(APPEND OSPRAY_ISPC_TARGET_LIST neon-i32x4) elseif (EMBREE_ISA_NEON2X AND NOT OSPRAY_ISPC_TARGET_LIST STREQUAL "neon-i32x8") list(APPEND OSPRAY_ISPC_TARGET_LIST neon-i32x8) endif() endif() endmacro() ## Macro configure ISA targets for ispc ## macro(ospray_configure_ispc_isa) set(OSPRAY_BUILD_ISA "ALL" CACHE STRING "Target ISA (SSE4, AVX, AVX2, AVX512SKX, NEON, NEON2X, or ALL)") string(TOUPPER ${OSPRAY_BUILD_ISA} OSPRAY_BUILD_ISA) if(EMBREE_ISA_SSE42 AND OPENVKL_ISA_SSE4) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} SSE4) endif() if(EMBREE_ISA_AVX AND OPENVKL_ISA_AVX) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX) endif() if(EMBREE_ISA_AVX2 AND OPENVKL_ISA_AVX2) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX2) endif() if(EMBREE_ISA_AVX512 AND OPENVKL_ISA_AVX512SKX) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} AVX512SKX) endif() if(EMBREE_ISA_NEON AND OPENVKL_ISA_NEON) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} NEON) endif() if(EMBREE_ISA_NEON2X AND OPENVKL_ISA_NEON2X) set(OSPRAY_SUPPORTED_ISAS ${OSPRAY_SUPPORTED_ISAS} NEON2X) endif() set_property(CACHE OSPRAY_BUILD_ISA PROPERTY STRINGS ALL ${OSPRAY_SUPPORTED_ISAS}) unset(OSPRAY_ISPC_TARGET_LIST) if (OSPRAY_BUILD_ISA STREQUAL "ALL") if(EMBREE_ISA_SSE42 AND OPENVKL_ISA_SSE4) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} sse4) message(STATUS "OSPRay SSE4 ISA target enabled.") endif() if(EMBREE_ISA_AVX AND OPENVKL_ISA_AVX) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx) message(STATUS "OSPRay AVX ISA target enabled.") endif() if(EMBREE_ISA_AVX2 AND OPENVKL_ISA_AVX2) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx2) message(STATUS "OSPRay AVX2 ISA target enabled.") endif() if(EMBREE_ISA_AVX512 AND OPENVKL_ISA_AVX512SKX) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} avx512skx-i32x16) message(STATUS "OSPRay AVX512SKX ISA target enabled.") endif() if(EMBREE_ISA_NEON AND OPENVKL_ISA_NEON) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} neon-i32x4) message(STATUS "OSPRay NEON ISA target enabled.") endif() if(EMBREE_ISA_NEON2X AND OPENVKL_ISA_NEON2X) set(OSPRAY_ISPC_TARGET_LIST ${OSPRAY_ISPC_TARGET_LIST} neon-i32x8) message(STATUS "OSPRay NEON2X ISA target enabled.") endif() elseif (OSPRAY_BUILD_ISA STREQUAL "AVX512SKX") if(NOT EMBREE_ISA_AVX512) message(FATAL_ERROR "Your Embree build does not support AVX512SKX!") endif() if(NOT OPENVKL_ISA_AVX512SKX) message(FATAL_ERROR "Your Open VKL build does not support AVX512SKX!") endif() set(OSPRAY_ISPC_TARGET_LIST avx512skx-i32x16) elseif (OSPRAY_BUILD_ISA STREQUAL "AVX2") if(NOT EMBREE_ISA_AVX2) message(FATAL_ERROR "Your Embree build does not support AVX2!") endif() if(NOT OPENVKL_ISA_AVX2) message(FATAL_ERROR "Your Open VKL build does not support AVX2!") endif() set(OSPRAY_ISPC_TARGET_LIST avx2) elseif (OSPRAY_BUILD_ISA STREQUAL "AVX") if(NOT EMBREE_ISA_AVX) message(FATAL_ERROR "Your Embree build does not support AVX!") endif() if(NOT OPENVKL_ISA_AVX) message(FATAL_ERROR "Your Open VKL build does not support AVX!") endif() set(OSPRAY_ISPC_TARGET_LIST avx) elseif (OSPRAY_BUILD_ISA STREQUAL "SSE4") if(NOT EMBREE_ISA_SSE42) message(FATAL_ERROR "Your Embree build does not support SSE4!") endif() if(NOT OPENVKL_ISA_SSE4) message(FATAL_ERROR "Your Open VKL build does not support SSE4!") endif() set(OSPRAY_ISPC_TARGET_LIST sse4) elseif (OSPRAY_BUILD_ISA STREQUAL "NEON") if (NOT EMBREE_ISA_NEON) message(FATAL_ERROR "Your Embree build does not support NEON!") endif() if (NOT OPENVKL_ISA_NEON) message(FATAL_ERROR "Your OpenVKL build does not support NEON!") endif() set(OSPRAY_ISPC_TARGET_LIST neon-i32x4) elseif (OSPRAY_BUILD_ISA STREQUAL "NEON2X") if (NOT EMBREE_ISA_NEON2X) message(FATAL_ERROR "Your Embree build does not support NEON2X!") endif() if (NOT OPENVKL_ISA_NEON2X) message(FATAL_ERROR "Your OpenVKL build does not support NEON2X!") endif() set(OSPRAY_ISPC_TARGET_LIST neon-i32x8) else() message(FATAL_ERROR "Invalid OSPRAY_BUILD_ISA value. " "Please select one of ${OSPRAY_SUPPORTED_ISAS}, or ALL.") endif() ospray_fix_ispc_target_list() endmacro() macro(ospray_add_sycl_target target) target_compile_features(${target} PUBLIC cxx_std_17) target_compile_options(${target} PUBLIC ${OSPRAY_CXX_FLAGS_SYCL}) target_link_options(${target} PUBLIC ${OSPRAY_LINKER_FLAGS_SYCL}) endmacro() ## Target creation macros ## macro(ospray_sign_target name) if (OSPRAY_SIGN_FILE AND NOT APPLE) add_custom_command(TARGET ${name} POST_BUILD COMMAND ${OSPRAY_SIGN_FILE} -q $ COMMENT "Signing target" VERBATIM ) endif() endmacro() macro(ospray_install_library name component) set_target_properties(${name} PROPERTIES VERSION ${OSPRAY_VERSION} SOVERSION ${OSPRAY_SOVERSION}) ospray_install_target(${name} ${component}) ospray_sign_target(${name}) if (${ARGN}) # Install the namelink in the devel component. This command also includes the # RUNTIME and ARCHIVE components a second time to prevent an "install TARGETS # given no ARCHIVE DESTINATION for static library target" error. Installing # these components twice doesn't hurt anything. install(TARGETS ${name} LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel NAMELINK_ONLY RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${component} ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ) endif() endmacro() macro(ospray_install_target name component) install(TARGETS ${name} EXPORT ospray_Exports LIBRARY DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT ${component} NAMELINK_SKIP # on Windows put the dlls into bin RUNTIME DESTINATION ${CMAKE_INSTALL_BINDIR} COMPONENT ${component} # ... and the import lib into the devel package ARCHIVE DESTINATION ${CMAKE_INSTALL_LIBDIR} COMPONENT devel ) install(EXPORT ospray_Exports DESTINATION ${OSPRAY_CMAKECONFIG_DIR} NAMESPACE ospray:: COMPONENT devel ) endmacro() ## Compiler configuration macros ## macro(ospray_configure_compiler) # unhide compiler to make it easier for users to see what they are using mark_as_advanced(CLEAR CMAKE_CXX_COMPILER) option(OSPRAY_STRICT_BUILD "Build with additional warning flags" ON) mark_as_advanced(OSPRAY_STRICT_BUILD) option(OSPRAY_WARN_AS_ERRORS "Treat warnings as errors" OFF) mark_as_advanced(OSPRAY_WARN_AS_ERRORS) set(OSPRAY_COMPILER_ICC FALSE) set(OSPRAY_COMPILER_GCC FALSE) set(OSPRAY_COMPILER_CLANG FALSE) set(OSPRAY_COMPILER_MSVC FALSE) set(OSPRAY_COMPILER_DPCPP FALSE) if ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "IntelLLVM" OR OSPRAY_MODULE_GPU) set(OSPRAY_COMPILER_DPCPP TRUE) include(dpcpp) if(WIN32) set(CMAKE_NINJA_CMCLDEPS_RC OFF) # workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/18311 endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Intel") set(OSPRAY_COMPILER_ICC TRUE) if(WIN32) set(CMAKE_NINJA_CMCLDEPS_RC OFF) # workaround for https://gitlab.kitware.com/cmake/cmake/-/issues/18311 include(msvc) # icc on Windows behaves like msvc else() include(icc) endif() elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "GNU") set(OSPRAY_COMPILER_GCC TRUE) include(gcc) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "Clang" OR "${CMAKE_CXX_COMPILER_ID}" STREQUAL "AppleClang") set(OSPRAY_COMPILER_CLANG TRUE) include(clang) elseif ("${CMAKE_CXX_COMPILER_ID}" STREQUAL "MSVC") set(OSPRAY_COMPILER_MSVC TRUE) include(msvc) else() message(FATAL_ERROR "Unsupported compiler specified: '${CMAKE_CXX_COMPILER_ID}'") endif() set(CMAKE_CXX_FLAGS_DEBUG "-DDEBUG ${CMAKE_CXX_FLAGS_DEBUG}") if (WIN32) # increase stack to 8MB (the default size of 1MB is too small for our apps) if (CMAKE_CXX_COMPILER_FRONTEND_VARIANT STREQUAL "GNU") set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} -Xlinker") endif() set(CMAKE_EXE_LINKER_FLAGS "${CMAKE_EXE_LINKER_FLAGS} /STACK:8388608") endif() endmacro() macro(ospray_disable_compiler_warnings) if (NOT OSPRAY_COMPILER_MSVC) set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -w") endif() endmacro() ## Embree functions/macros ## function(ospray_check_embree_feature FEATURE VALUE DESC) set(FEATURE EMBREE_${FEATURE}) if (${ARGN}) if (${FEATURE} STREQUAL ${VALUE}) return() endif() else() if ((${VALUE} AND ${FEATURE}) OR (NOT ${VALUE} AND NOT ${FEATURE})) return() endif() endif() message(FATAL_ERROR "OSPRay requires Embree to ${DESC} (compiled with ${FEATURE}=${VALUE}).") endfunction() function(ospray_verify_embree_features) ospray_check_embree_feature(ISPC_SUPPORT ON "support ISPC") ospray_check_embree_feature(FILTER_FUNCTION ON "support intersection filter") ospray_check_embree_feature(GEOMETRY_TRIANGLE ON "support triangle geometries") ospray_check_embree_feature(GEOMETRY_CURVE ON "support spline curve geometries") ospray_check_embree_feature(GEOMETRY_USER ON "support user geometries") ospray_check_embree_feature(RAY_PACKETS ON "support ray packets") ospray_check_embree_feature(BACKFACE_CULLING OFF "have backface culling disabled") ospray_check_embree_feature(GEOMETRY_INSTANCE ON "support instances") ospray_check_embree_feature(MAX_INSTANCE_LEVEL_COUNT 1 "only support single-level instancing" ON) if (OSPRAY_MODULE_GPU) ospray_check_embree_feature(SYCL_SUPPORT ON "support DPC++/SYCL") endif() endfunction() macro(ospray_find_embree EMBREE_VERSION_REQUIRED FIND_AS_DEPENDENCY) if (${FIND_AS_DEPENDENCY}) find_dependency(embree ${EMBREE_VERSION_REQUIRED}) else() find_package(embree ${EMBREE_VERSION_REQUIRED}) endif() if (NOT embree_FOUND) message(FATAL_ERROR "We did not find Embree installed on your system. OSPRay requires" " an Embree installation >= v${EMBREE_VERSION_REQUIRED}, please" " download and extract Embree (or compile Embree from source), then" " set the 'embree_DIR' variable to the installation (or build)" " directory.") endif() # Get Embree CPU info get_target_property(EMBREE_INCLUDE_DIRS embree INTERFACE_INCLUDE_DIRECTORIES) get_target_property(CONFIGURATIONS embree IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(EMBREE_LIBRARY embree IMPORTED_LOCATION_${CONFIGURATION}) # Get Embree SYCL info if DPCPP was enabled if (EMBREE_SYCL_SUPPORT) get_target_property(CONFIGURATIONS embree_sycl IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(EMBREE_SYCL_LIBRARY embree_sycl IMPORTED_LOCATION_${CONFIGURATION}) endif() message(STATUS "Found Embree v${embree_VERSION}: ${EMBREE_LIBRARY}") endmacro() macro(ospray_find_openvkl OPENVKL_VERSION_REQUIRED FIND_AS_DEPENDENCY) if (${FIND_AS_DEPENDENCY}) find_dependency(openvkl ${OPENVKL_VERSION_REQUIRED}) else() find_package(openvkl ${OPENVKL_VERSION_REQUIRED}) endif() if (openvkl_FOUND) get_target_property(OPENVKL_INCLUDE_DIRS openvkl::openvkl INTERFACE_INCLUDE_DIRECTORIES) get_target_property(OPENVKL_CPU_DEVICE_INCLUDE_DIRS openvkl::openvkl_module_cpu_device INTERFACE_INCLUDE_DIRECTORIES) get_target_property(CONFIGURATIONS openvkl::openvkl IMPORTED_CONFIGURATIONS) list(GET CONFIGURATIONS 0 CONFIGURATION) get_target_property(OPENVKL_LIBRARY openvkl::openvkl IMPORTED_LOCATION_${CONFIGURATION}) message(STATUS "Found Open VKL v${openvkl_VERSION}: ${OPENVKL_LIBRARY}") endif() endmacro()