## Copyright 2009-2021 Intel Corporation
## SPDX-License-Identifier: Apache-2.0

cmake_minimum_required(VERSION 3.1.0)

project(ze_raytracing)

SET(ZE_RAYTRACING_VERSION_MAJOR 1)
SET(ZE_RAYTRACING_VERSION_MINOR 2)
SET(ZE_RAYTRACING_VERSION_PATCH 3)
SET(ZE_RAYTRACING_VERSION ${ZE_RAYTRACING_VERSION_MAJOR}.${ZE_RAYTRACING_VERSION_MINOR}.${ZE_RAYTRACING_VERSION_PATCH})
IF (ZE_RAYTRACING_VERSION_BUILD)
  SET(ZE_RAYTRACING_VERSION ${ZE_RAYTRACING_VERSION}.${ZE_RAYTRACING_VERSION_BUILD})
ENDIF()

IF(COMMAND cmake_policy)
  if(POLICY CMP0135)
    message("set policy CMP0135 to NEW")
    cmake_policy(SET CMP0135 NEW)
  endif()
ENDIF()

SET(CMAKE_CXX_STANDARD 17)
SET(EMBREE_CMAKEEXPORT_DIR "cmake")

SET(CMAKE_RUNTIME_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_ARCHIVE_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_LIBRARY_OUTPUT_DIRECTORY "${CMAKE_CURRENT_BINARY_DIR}")
SET(CMAKE_MODULE_PATH "${CMAKE_CURRENT_SOURCE_DIR}/cmake" ${CMAKE_MODULE_PATH})

# Build configurations to use
SET(CMAKE_BUILD_TYPE "ReleaseInternal" CACHE STRING "Specifies the build type.")
SET_PROPERTY(CACHE CMAKE_BUILD_TYPE PROPERTY STRINGS Debug Release ReleaseInternal)
SET(CMAKE_CONFIGURATION_TYPES "Debug;Release;ReleaseInternal" CACHE STRING "List of generated configurations." FORCE)

# Debug build configuration
IF (WIN32) # Link runtime statically under Windows
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS_DEBUG "${CMAKE_C_FLAGS_DEBUG}")
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_DEBUG "${CMAKE_CXX_FLAGS_DEBUG}")
ENDIF()
MESSAGE("CMAKE_CXX_FLAGS_DEBUG = ${CMAKE_CXX_FLAGS_DEBUG}")
MESSAGE("CMAKE_C_FLAGS_DEBUG = ${CMAKE_C_FLAGS_DEBUG}")
MESSAGE("CMAKE_SHARED_LINKER_FLAGS_DEBUG = ${CMAKE_SHARED_LINKER_FLAGS_DEBUG}")
MESSAGE("CMAKE_EXE_LINKER_FLAGS_DEBUG = ${CMAKE_EXE_LINKER_FLAGS_DEBUG}")

# Release build configuration
SET(CMAKE_CXX_FLAGS_RELEASE ${CMAKE_CXX_FLAGS_RELWITHDEBINFO})
SET(CMAKE_C_FLAGS_RELEASE ${CMAKE_C_FLAGS_RELWITHDEBINFO})
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO})
SET(CMAKE_EXE_LINKER_FLAGS_RELEASE ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
IF (WIN32) # Link runtime statically under Windows
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE}")
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE}")
ENDIF()
IF (WIN32) # enable dynamic control flow guard mitigation under windows
  SET(CMAKE_CXX_FLAGS_RELEASE "${CMAKE_CXX_FLAGS_RELEASE} /guard:cf")
  SET(CMAKE_C_FLAGS_RELEASE "${CMAKE_C_FLAGS_RELEASE} /guard:cf")
  SET(CMAKE_SHARED_LINKER_FLAGS_RELEASE "${CMAKE_SHARED_LINKER_FLAGS_RELEASE} /DynamicBase /guard:cf")
  SET(CMAKE_EXE_LINKER_FLAGS_RELEASE "${CMAKE_EXE_LINKER_FLAGS_RELEASE} /DynamicBase /guard:cf")
ENDIF()
MESSAGE("CMAKE_CXX_FLAGS_RELEASE = ${CMAKE_CXX_FLAGS_RELEASE}")
MESSAGE("CMAKE_C_FLAGS_RELEASE = ${CMAKE_C_FLAGS_RELEASE}")
MESSAGE("CMAKE_SHARED_LINKER_FLAGS_RELEASE = ${CMAKE_SHARED_LINKER_FLAGS_RELEASE}")
MESSAGE("CMAKE_EXE_LINKER_FLAGS_RELEASE = ${CMAKE_EXE_LINKER_FLAGS_RELEASE}")

# ReleaseInternal build configuration
string(REPLACE "DNDEBUG" "DDEBUG" CMAKE_CXX_FLAGS_RELEASEINTERNAL "${CMAKE_CXX_FLAGS_RELWITHDEBINFO}")
string(REPLACE "DNDEBUG" "DDEBUG" CMAKE_C_FLAGS_RELEASEINTERNAL   "${CMAKE_C_FLAGS_RELWITHDEBINFO}")
SET(CMAKE_SHARED_LINKER_FLAGS_RELEASEINTERNAL ${CMAKE_SHARED_LINKER_FLAGS_RELWITHDEBINFO})
SET(CMAKE_EXE_LINKER_FLAGS_RELEASEINTERNAL ${CMAKE_EXE_LINKER_FLAGS_RELWITHDEBINFO})
IF (WIN32) # Link runtime statically under Windows
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_C_FLAGS_RELEASEINTERNAL "${CMAKE_C_FLAGS_RELEASEINTERNAL}")
  STRING(REGEX REPLACE "/MD" "/MT" CMAKE_CXX_FLAGS_RELEASEINTERNAL "${CMAKE_CXX_FLAGS_RELEASEINTERNAL}")
ENDIF()
MESSAGE("CMAKE_CXX_FLAGS_RELEASEINTERNAL = ${CMAKE_CXX_FLAGS_RELEASEINTERNAL}")
MESSAGE("CMAKE_C_FLAGS_RELEASEINTERNAL = ${CMAKE_C_FLAGS_RELEASEINTERNAL}")
MESSAGE("CMAKE_SHARED_LINKER_FLAGS_RELEASEINTERNAL = ${CMAKE_SHARED_LINKER_FLAGS_RELEASEINTERNAL}")
MESSAGE("CMAKE_EXE_LINKER_FLAGS_RELEASEINTERNAL = ${CMAKE_EXE_LINKER_FLAGS_RELEASEINTERNAL}")

# configure resource file file
CONFIGURE_FILE(
  "${PROJECT_SOURCE_DIR}/level_zero_raytracing.rc.in"
  "${PROJECT_SOURCE_DIR}/level_zero_raytracing.rc"
)

# default TBB mode
SET(ZE_RAYTRACING_TBB_DEFAULT "build_static")

# still support ZE_RAYTRACING_TBB_STATIC if defined
IF (DEFINED ZE_RAYTRACING_TBB_STATIC)
  IF(ZE_RAYTRACING_TBB_STATIC)
    SET(ZE_RAYTRACING_TBB_DEFAULT "build_static")
  ELSE()
    SET(ZE_RAYTRACING_TBB_DEFAULT "normal")
  ENDIF()
ENDIF()

# TBB mode configuration
SET(ZE_RAYTRACING_TBB ${ZE_RAYTRACING_TBB_DEFAULT} CACHE
  STRING "Configures how to use TBB: build_static builds specified TBB version and links statically, inject_headers uses headers of specified TBB version, and normal links against system provided TBB)")
SET_PROPERTY(CACHE ZE_RAYTRACING_TBB PROPERTY STRINGS "build_static" "inject_header" "normal")
SET(ZE_RAYTRACING_DEFAULT_TBB_VERSION v2022.3.0)

IF (ZE_RAYTRACING_TBB STREQUAL "build_static")
  SET(TBB_STATIC ON)
  SET(TBB_HEADER OFF)
ELSEIF (ZE_RAYTRACING_TBB STREQUAL "inject_headers")
  SET(TBB_STATIC OFF)
  SET(TBB_HEADER ON)
  SET(ZE_RAYTRACING_DEFAULT_TBB_VERSION v2021.6.0)  # headers of that version are included
ELSEIF (ZE_RAYTRACING_TBB STREQUAL "normal")
  SET(TBB_STATIC OFF)
  SET(TBB_HEADER OFF)
ELSE()
  MESSAGE(FATAL_ERROR "Unknown TBB mode ${ZE_RAYTRACING_TBB}")
ENDIF()

SET(ZE_RAYTRACING_TBB_VERSION ${ZE_RAYTRACING_DEFAULT_TBB_VERSION} CACHE STRING "TBB version to use.") 

IF (TBB_STATIC OR TBB_HEADER)
  INCLUDE(fetchtbb)
ENDIF()
IF (NOT TBB_STATIC)
  FIND_PACKAGE(TBB)
  
  IF (NOT TBB_FOUND)
    find_package(PkgConfig REQUIRED)
    pkg_check_modules(TBB REQUIRED tbb)
    IF(NOT TARGET TBB::tbb)
        add_library(TBB::tbb INTERFACE IMPORTED)
        target_link_libraries(TBB::tbb INTERFACE ${TBB_LIBRARIES})
        target_include_directories(TBB::tbb INTERFACE ${TBB_INCLUDE_DIRS})
        set(TBB_VERSION ${TBB_VERSION})
    ENDIF()
ENDIF()

message(STATUS "Found TBB version: ${TBB_VERSION}")

ENDIF()
ADD_DEFINITIONS(-DTASKING_TBB)

# add path to TBB headers to use for compilation
IF (ZE_RAYTRACING_TBB_HEADER_DIR)
  INCLUDE_DIRECTORIES(${ZE_RAYTRACING_TBB_HEADER_DIR})
  IF (NOT EXISTS "${ZE_RAYTRACING_TBB_HEADER_DIR}/tbb/tbb.h")
    MESSAGE(FATAL_ERROR "TBB headers not found at ${ZE_RAYTRACING_TBB_HEADER_DIR}")
  ENDIF()
  MESSAGE(STATUS "Using TBB headers ${ZE_RAYTRACING_TBB_HEADER_DIR}")
ENDIF()

OPTION(ZE_RAYTRACING_RT_SIMULATION "Using hardware simulation" OFF)
IF (ZE_RAYTRACING_RT_SIMULATION AND (NOT ZE_RAYTRACING_RT_VALIDATION_API OR ZE_RAYTRACING_IMPLICIT_DISPATCH_GLOBALS))
  MESSAGE(FATAL_ERROR "Using ZE_RAYTRACING_RT_SIMULATION requires ZE_RAYTRACING_RT_VALIDATION_API=ON and ZE_RAYTRACING_IMPLICIT_DISPATCH_GLOBALS=OFF")
ENDIF()

IF (ZE_RAYTRACING_RT_SIMULATION)
  FIND_PACKAGE(rtcore)
  ADD_DEFINITIONS("-DEMBREE_SYCL_RT_SIMULATION")
ENDIF()

OPTION(ZE_RAYTRACING_RT_VALIDATION_API "Use rt_validation API instead of IGC provided rt_production API" OFF)
IF (ZE_RAYTRACING_RT_VALIDATION_API)
  ADD_DEFINITIONS("-DEMBREE_SYCL_RT_VALIDATION_API")
ENDIF()

SET(ZE_RAYTRACING_DEVICE -1 CACHE STRING "Forces Xe device to use.")
ADD_DEFINITIONS("-DZE_RAYTRACING_DEVICE=${ZE_RAYTRACING_DEVICE}")

OPTION(ZE_RAYTRACING_IMPLICIT_DISPATCH_GLOBALS "Using L0 allocated Dispatch Globals" ON)
IF (NOT ZE_RAYTRACING_IMPLICIT_DISPATCH_GLOBALS)
  ADD_DEFINITIONS("-DEMBREE_SYCL_ALLOC_DISPATCH_GLOBALS")
ENDIF()

SET(ZE_RAYTRACING_SYCL_TESTS "OFF" CACHE STRING "Enable SYCL tests.")
SET_PROPERTY(CACHE ZE_RAYTRACING_SYCL_TESTS PROPERTY STRINGS OFF INTERNAL_RTAS_BUILDER LEVEL_ZERO_RTAS_BUILDER)

STRING(TOLOWER "${CMAKE_CXX_COMPILER_ID}" LOWER_CXX_COMPILER_ID)
include(${LOWER_CXX_COMPILER_ID})

INCLUDE(CTest)
include(package)
INCLUDE(CPack)

IF (ZE_RAYTRACING_RT_VALIDATION_API)
  ADD_SUBDIRECTORY(rttrace)
  SET(EMBREE_RTHWIF_SYCL embree_rthwif_sycl)
ENDIF()

ADD_SUBDIRECTORY(rtbuild/sys)
ADD_SUBDIRECTORY(rtbuild/simd)
ADD_SUBDIRECTORY(level_zero)

IF (NOT ZE_RAYTRACING_SYCL_TESTS STREQUAL "LEVEL_ZERO_RTAS_BUILDER") # do not build RTAS builder when building LEVEL_ZERO test
  ADD_SUBDIRECTORY(rtbuild)
ENDIF()

IF (NOT ZE_RAYTRACING_SYCL_TESTS STREQUAL "OFF")
  ADD_SUBDIRECTORY(testing)
ENDIF()

