cmake_minimum_required(VERSION 3.24)
project(bray LANGUAGES C CXX CUDA)

set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)

# ---------------------------------------------------------------------------
# Compile-time template parameters (override via cmake -D or pip --config-settings)
# ---------------------------------------------------------------------------
set(BRAY_CAM_WIDTH  128  CACHE STRING "Per-camera width  (pixels)")
set(BRAY_CAM_HEIGHT 128  CACHE STRING "Per-camera height (pixels)")
set(BRAY_NUM_CAMERAS 4096 CACHE STRING "Maximum number of cameras")
set(BRAY_NUM_PROBES  0    CACHE STRING "Collision probes per camera (0 = disable)")

# ---------------------------------------------------------------------------
# Dependencies
# ---------------------------------------------------------------------------
include(FetchContent)

# OWL (OptiX Wrapper Library)
FetchContent_Declare(
    OWL
    GIT_REPOSITORY https://github.com/NVIDIA/OWL.git
    GIT_TAG        main
    EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(OWL)

# STB (header-only image I/O, used by rl-tools raytracer)
FetchContent_Declare(
    STB
    GIT_REPOSITORY https://github.com/nothings/stb.git
    GIT_TAG        master
    EXCLUDE_FROM_ALL
)
FetchContent_MakeAvailable(STB)

find_package(assimp REQUIRED)
find_package(pybind11 REQUIRED)

# ---------------------------------------------------------------------------
# rl_tools_core – interface library with just the include path
# ---------------------------------------------------------------------------
add_library(rl_tools_core INTERFACE)
target_include_directories(rl_tools_core INTERFACE
    ${CMAKE_CURRENT_SOURCE_DIR}/bray/rl-tools/include
)
target_compile_definitions(rl_tools_core INTERFACE
    RL_TOOLS_RENDERING_ENABLE_RAYTRACING
)

# ---------------------------------------------------------------------------
# PTX generation for OptiX device programs
# ---------------------------------------------------------------------------
embed_ptx(
    OUTPUT_TARGET bray_device_ptx
    PTX_LINK_LIBRARIES owl::owl rl_tools_core
    SOURCES ${CMAKE_CURRENT_SOURCE_DIR}/bray/src/device.cu
)

# ---------------------------------------------------------------------------
# bray_impl – static CUDA library (the only TU touching OWL/rl-tools)
# ---------------------------------------------------------------------------
add_library(bray_impl STATIC
    bray/src/bray_impl.cu
)
target_include_directories(bray_impl PUBLIC
    ${CMAKE_CURRENT_SOURCE_DIR}/bray/src
    ${stb_SOURCE_DIR}
)
target_link_libraries(bray_impl PUBLIC
    rl_tools_core
    owl::owl
    assimp::assimp
    bray_device_ptx
)
target_compile_definitions(bray_impl PRIVATE
    BRAY_CAM_WIDTH=${BRAY_CAM_WIDTH}
    BRAY_CAM_HEIGHT=${BRAY_CAM_HEIGHT}
    BRAY_NUM_CAMERAS=${BRAY_NUM_CAMERAS}
    BRAY_NUM_PROBES=${BRAY_NUM_PROBES}
)
set_target_properties(bray_impl PROPERTIES
    CUDA_RESOLVE_DEVICE_SYMBOLS ON
    POSITION_INDEPENDENT_CODE ON
)

# ---------------------------------------------------------------------------
# _bray_core – pybind11 extension module (plain C++, no CUDA)
# ---------------------------------------------------------------------------
pybind11_add_module(_bray_core
    bray/src/bindings.cpp
)
target_include_directories(_bray_core PRIVATE
    ${CMAKE_CURRENT_SOURCE_DIR}/bray/src
)
target_link_libraries(_bray_core PRIVATE
    bray_impl
)
target_compile_definitions(_bray_core PRIVATE
    BRAY_CAM_WIDTH=${BRAY_CAM_WIDTH}
    BRAY_CAM_HEIGHT=${BRAY_CAM_HEIGHT}
    BRAY_NUM_CAMERAS=${BRAY_NUM_CAMERAS}
    BRAY_NUM_PROBES=${BRAY_NUM_PROBES}
)

# Set RPATH so the extension module finds libowl.so next to it
set_target_properties(_bray_core PROPERTIES
    INSTALL_RPATH "$ORIGIN"
)

install(TARGETS _bray_core DESTINATION bray)
install(TARGETS owl DESTINATION bray LIBRARY NAMELINK_SKIP)
