Hello everyone,
I am pretty new to CUDA and OPTIX, so please excuse if there is an quite obvious fix. I installed CUDA and OPTIX-SDK via the installers. Now I tried to build a more performant raytracing method as I used my own before, however I keep getting the following error:
identifier "optixProgramGroupGetStackSize" is undefined
I checked the installations and it seems OPTIX-SDK comes only with headers and dynamically loads the necessary libraries on runtime. OPTIX should be correctly installed as the SDK examples compile with no problem. Also CUDA by itself compiles, however in the following example I keep getting the same error. It seems to be connected to the voxelizationUtil.cu, namely this line: OPTIX_CHECK(optixUtilAccumulateStackSizes(pg, &stackSizes, optixPipeline));
voxelizationUtil.cu:
#ifndef OPTIX_FUNCTION_TABLE_DEFINITION
#define OPTIX_FUNCTION_TABLE_DEFINITION
#endif
#ifndef OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO
#define OPTIX_COMPILE_DEBUG_LEVEL_LINEINFO 3
#endif
#include <string>
#include <sstream>
#include <iostream>
#include <stdexcept>
#include <fstream>
#include <optix.h>
#include <optix_function_table_definition.h>
#include <optix_stack_size.h>
#include <optix_stubs.h>
#include <cuda_runtime.h>
#include <vector_types.h>
#include "cudaUtil.hpp"
// OptiX context and module variables
static OptixDeviceContext optixContext = nullptr;
static OptixModule optixModule = nullptr;
static OptixPipeline optixPipeline = nullptr;
static OptixProgramGroup raygenPG = nullptr;
static OptixProgramGroup missPG = nullptr;
static OptixProgramGroup hitgroupPG = nullptr;
// CUDA error checking macro
#define CUDA_CHECK( call ) \
do { \
cudaError_t error = call; \
if( error != cudaSuccess ) { \
std::stringstream ss; \
ss << "CUDA call (" << #call << " ) failed with error: '" \
<< cudaGetErrorString( error ) \
<< "' (" __FILE__ << ":" << __LINE__ << ")\n"; \
std::cerr << ss.str() << std::endl; \
exit( 1 ); \
} \
} while( 0 )
// OptiX error checking macro
#define OPTIX_CHECK( call ) \
do { \
OptixResult res = call; \
if( res != OPTIX_SUCCESS ) { \
std::stringstream ss; \
ss << "Optix call (" << #call << " ) failed: " \
<< optixGetErrorName( res ) << " (" __FILE__ << ":" \
<< __LINE__ << ")\n"; \
std::cerr << ss.str() << std::endl; \
exit( 1 ); \
} \
} while( 0 )
std::string loadPTXSource(const std::string& filename) {
std::ifstream file(filename);
if (!file.is_open()) {
throw std::runtime_error("Unable to open PTX file: " + filename);
}
std::stringstream ss;
ss << file.rdbuf();
return ss.str();
}
void initializeOptix()
{
// Initialize CUDA
CUDA_CHECK(cudaFree(0));
// Initialize OptiX
OPTIX_CHECK(optixInit());
// Create OptiX context
cudaStream_t stream;
CUDA_CHECK(cudaStreamCreate(&stream));
OptixDeviceContextOptions contextOptions = {};
OPTIX_CHECK(optixDeviceContextCreate(0, &contextOptions, &optixContext));
OPTIX_CHECK(optixDeviceContextSetLogCallback(optixContext, nullptr, nullptr, 4));
// Create OptiX module
OptixModuleCompileOptions moduleCompileOptions = {};
moduleCompileOptions.maxRegisterCount = OPTIX_COMPILE_DEFAULT_MAX_REGISTER_COUNT;
moduleCompileOptions.optLevel = OPTIX_COMPILE_OPTIMIZATION_DEFAULT;
moduleCompileOptions.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_DEFAULT;
OptixPipelineCompileOptions pipelineCompileOptions = {};
pipelineCompileOptions.usesMotionBlur = false;
pipelineCompileOptions.traversableGraphFlags = OPTIX_TRAVERSABLE_GRAPH_FLAG_ALLOW_SINGLE_LEVEL_INSTANCING;
pipelineCompileOptions.numPayloadValues = 2;
pipelineCompileOptions.numAttributeValues = 2;
pipelineCompileOptions.exceptionFlags = OPTIX_EXCEPTION_FLAG_NONE;
pipelineCompileOptions.pipelineLaunchParamsVariableName = "params";
const std::string ptxCode = loadPTXSource("optixPrograms.ptx");
char log[2048];
size_t sizeof_log = sizeof(log);
OPTIX_CHECK(optixModuleCreate(
optixContext,
&moduleCompileOptions,
&pipelineCompileOptions,
ptxCode.c_str(),
ptxCode.size(),
log,
&sizeof_log,
&optixModule
));
// Create OptiX program groups
OptixProgramGroupOptions pgOptions = {};
OptixProgramGroupDesc pgDesc = {};
pgDesc.kind = OPTIX_PROGRAM_GROUP_KIND_RAYGEN;
pgDesc.raygen.module = optixModule;
pgDesc.raygen.entryFunctionName = "__raygen__rg";
OPTIX_CHECK(optixProgramGroupCreate(
optixContext,
&pgDesc,
1,
&pgOptions,
log,
&sizeof_log,
&raygenPG
));
memset(&pgDesc, 0, sizeof(OptixProgramGroupDesc));
pgDesc.kind = OPTIX_PROGRAM_GROUP_KIND_MISS;
pgDesc.miss.module = optixModule;
pgDesc.miss.entryFunctionName = "__miss__ms";
OPTIX_CHECK(optixProgramGroupCreate(
optixContext,
&pgDesc,
1,
&pgOptions,
log,
&sizeof_log,
&missPG
));
memset(&pgDesc, 0, sizeof(OptixProgramGroupDesc));
pgDesc.kind = OPTIX_PROGRAM_GROUP_KIND_HITGROUP;
pgDesc.hitgroup.moduleCH = optixModule;
pgDesc.hitgroup.entryFunctionNameCH = "__closesthit__ch";
OPTIX_CHECK(optixProgramGroupCreate(
optixContext,
&pgDesc,
1,
&pgOptions,
log,
&sizeof_log,
&hitgroupPG
));
// Create OptiX pipeline
OptixProgramGroup programGroups[] = { raygenPG, missPG, hitgroupPG };
OptixPipelineLinkOptions pipelineLinkOptions = {};
pipelineLinkOptions.maxTraceDepth = 1;
OPTIX_CHECK(optixPipelineCreate(
optixContext,
&pipelineCompileOptions,
&pipelineLinkOptions,
programGroups,
sizeof(programGroups) / sizeof(programGroups[0]),
log,
&sizeof_log,
&optixPipeline
));
OptixStackSizes stackSizes = {};
for (auto& pg : programGroups)
{
OPTIX_CHECK(optixUtilAccumulateStackSizes(pg, &stackSizes, optixPipeline));
}
uint32_t directCallableStackSizeFromTraversal;
uint32_t directCallableStackSizeFromState;
uint32_t continuationStackSize;
OPTIX_CHECK(optixUtilComputeStackSizes(
&stackSizes,
1,
0,
0,
&directCallableStackSizeFromTraversal,
&directCallableStackSizeFromState,
&continuationStackSize
));
OPTIX_CHECK(optixPipelineSetStackSize(
optixPipeline,
directCallableStackSizeFromTraversal,
directCallableStackSizeFromState,
continuationStackSize,
1
));
}
extern "C" void launchOptixRayTracing(float* densities, float3* voxel_centers, OptixTraversableHandle handle,
unsigned int width, unsigned int height, unsigned int depth)
{
Params params;
params.densities = densities;
params.voxel_centers = voxel_centers;
params.handle = handle;
params.width = width;
params.height = height;
params.depth = depth;
CUdeviceptr d_param;
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&d_param), sizeof(Params)));
CUDA_CHECK(cudaMemcpy(
reinterpret_cast<void*>(d_param),
¶ms,
sizeof(params),
cudaMemcpyHostToDevice
));
OptixShaderBindingTable sbt = {};
CUdeviceptr raygen_record;
CUdeviceptr miss_record;
CUdeviceptr hitgroup_record;
size_t raygen_record_size = sizeof(RayGenSbtRecord);
size_t miss_record_size = sizeof(MissSbtRecord);
size_t hitgroup_record_size = sizeof(HitGroupSbtRecord);
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&raygen_record), raygen_record_size));
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&miss_record), miss_record_size));
CUDA_CHECK(cudaMalloc(reinterpret_cast<void**>(&hitgroup_record), hitgroup_record_size));
RayGenSbtRecord rg_sbt;
OPTIX_CHECK(optixSbtRecordPackHeader(raygenPG, &rg_sbt));
CUDA_CHECK(cudaMemcpy(
reinterpret_cast<void*>(raygen_record),
&rg_sbt,
raygen_record_size,
cudaMemcpyHostToDevice
));
MissSbtRecord ms_sbt;
OPTIX_CHECK(optixSbtRecordPackHeader(missPG, &ms_sbt));
CUDA_CHECK(cudaMemcpy(
reinterpret_cast<void*>(miss_record),
&ms_sbt,
miss_record_size,
cudaMemcpyHostToDevice
));
HitGroupSbtRecord hg_sbt;
OPTIX_CHECK(optixSbtRecordPackHeader(hitgroupPG, &hg_sbt));
CUDA_CHECK(cudaMemcpy(
reinterpret_cast<void*>(hitgroup_record),
&hg_sbt,
hitgroup_record_size,
cudaMemcpyHostToDevice
));
sbt.raygenRecord = raygen_record;
sbt.missRecordBase = miss_record;
sbt.missRecordStrideInBytes = sizeof(MissSbtRecord);
sbt.missRecordCount = 1;
sbt.hitgroupRecordBase = hitgroup_record;
sbt.hitgroupRecordStrideInBytes = sizeof(HitGroupSbtRecord);
sbt.hitgroupRecordCount = 1;
OPTIX_CHECK(optixLaunch(optixPipeline, 0, d_param, sizeof(Params), &sbt, width, height, depth));
CUDA_CHECK(cudaDeviceSynchronize());
CUDA_CHECK(cudaFree(reinterpret_cast<void*>(d_param)));
CUDA_CHECK(cudaFree(reinterpret_cast<void*>(raygen_record)));
CUDA_CHECK(cudaFree(reinterpret_cast<void*>(miss_record)));
CUDA_CHECK(cudaFree(reinterpret_cast<void*>(hitgroup_record)));
}
__global__ void initializeDensitiesKernelVoxelization(float* densities, int total_voxels) {
int idx = blockIdx.x * blockDim.x + threadIdx.x;
if (idx < total_voxels) {
densities[idx] = 0.0f;
}
}
extern "C" void launchInitializeDensities(float* densities, int total_voxels) {
dim3 block(256);
dim3 grid((total_voxels + block.x - 1) / block.x);
initializeDensitiesKernelVoxelization<<<grid, block>>>(densities, total_voxels);
cudaDeviceSynchronize();
}
optixUtil.cu:
#include <optix.h>
#include <cuda_runtime.h>
#include <vector_types.h>
#include <vector_functions.h>
#include "cudaUtil.hpp"
extern "C" {
__constant__ Params params;
}
// Helper function for vector subtraction
__device__ float3 subtract(float3 a, float3 b) {
return make_float3(a.x - b.x, a.y - b.y, a.z - b.z);
}
// Helper function for vector length
__device__ float length(float3 v) {
return sqrtf(v.x * v.x + v.y * v.y + v.z * v.z);
}
extern "C" __global__ void __raygen__rg()
{
const uint3 idx = optixGetLaunchIndex();
const uint3 dim = optixGetLaunchDimensions();
const float3 voxel_center = params.voxel_centers[idx.x + idx.y * dim.x + idx.z * dim.x * dim.y];
float3 ray_origin = voxel_center;
float3 ray_direction = make_float3(1.0f, 0.0f, 0.0f); // Ray direction along x-axis
unsigned int p0, p1;
optixTrace(
params.handle,
ray_origin,
ray_direction,
0.0f, // tmin
1e16f, // tmax
0.0f, // rayTime
OptixVisibilityMask(1),
OPTIX_RAY_FLAG_NONE,
0, // SBT offset
1, // SBT stride
0, // missSBTIndex
p0, p1);
float density = __uint_as_float(p0);
params.densities[idx.x + idx.y * dim.x + idx.z * dim.x * dim.y] = density;
}
extern "C" __global__ void __miss__ms()
{
optixSetPayload_0(0); // Set density to 0 for miss
}
extern "C" __global__ void __closesthit__ch()
{
float3 world_ray_direction = optixGetWorldRayDirection();
float3 world_ray_origin = optixGetWorldRayOrigin();
float ray_tmax = optixGetRayTmax();
// Calculate the intersection point
float3 hit_point;
hit_point.x = world_ray_origin.x + ray_tmax * world_ray_direction.x;
hit_point.y = world_ray_origin.y + ray_tmax * world_ray_direction.y;
hit_point.z = world_ray_origin.z + ray_tmax * world_ray_direction.z;
// Calculate distance from voxel center to hit point
float3 voxel_center = *(float3*)optixGetSbtDataPointer();
float distance = length(subtract(hit_point, voxel_center));
// Calculate density based on distance (you can adjust this formula as needed)
float density = 1.0f / (1.0f + distance);
// Set the density as the payload
optixSetPayload_0(__float_as_uint(density));
}
cudaUtil.hpp:
#pragma once
#ifndef CUDAUTIL_H
#define CUDAUTIL_H
#include <cuda_runtime.h>
#include <optix.h>
#include <vector_types.h>
struct Params {
float3* voxel_centers;
float* densities;
OptixTraversableHandle handle;
unsigned int width;
unsigned int height;
unsigned int depth;
};
struct RayGenSbtRecord {
__align__(OPTIX_SBT_RECORD_ALIGNMENT) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
};
struct MissSbtRecord {
__align__(OPTIX_SBT_RECORD_ALIGNMENT) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
};
struct HitGroupSbtRecord {
__align__(OPTIX_SBT_RECORD_ALIGNMENT) char header[OPTIX_SBT_RECORD_HEADER_SIZE];
float3 voxel_center;
};
#ifdef __cplusplus
extern "C" {
#endif
void initializeOptix();
void launchOptixRayTracing(float* densities, float3* voxel_centers, OptixTraversableHandle handle,
unsigned int width, unsigned int height, unsigned int depth);
void launchInitializeDensities(float* densities, int total_voxels);
#ifdef __cplusplus
}
#endif
#endif // CUDAUTIL_H
And for good measure my CMakeLists:
cmake_minimum_required(VERSION 3.12)
project(CadUtilityLibrary LANGUAGES CXX CUDA)
################################## Set C++ standard ##################################
set(CMAKE_CXX_STANDARD 17)
set(CMAKE_CXX_STANDARD_REQUIRED ON)
cmake_policy(SET CMP0144 NEW)
cmake_policy(SET CMP0167 NEW)
################################## Set CUDA flags ##################################
set(CMAKE_CUDA_STANDARD 17)
set(CMAKE_CUDA_STANDARD_REQUIRED ON)
################################## Set up Vcpkg ##################################
if(DEFINED ENV{VCPKG_ROOT} AND NOT DEFINED CMAKE_TOOLCHAIN_FILE)
set(CMAKE_TOOLCHAIN_FILE "$ENV{VCPKG_ROOT}/scripts/buildsystems/vcpkg.cmake"
CACHE STRING "")
endif()
if(DEFINED ENV{VCPKG_DEFAULT_TRIPLET} AND NOT DEFINED VCPKG_TARGET_TRIPLET)
set(VCPKG_TARGET_TRIPLET "$ENV{VCPKG_DEFAULT_TRIPLET}" CACHE STRING "")
endif()
################################## Setting build type ##################################
set(CMAKE_BUILD_TYPE Release)
################################## Set compiler flags ##################################
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /W4")
else()
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} -Wall -Wextra -Wpedantic")
endif()
################################## OpenMp ##################################
if(MSVC)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} /openmp:experimental /openmp:llvm")
message(STATUS "Enabling OpenMP experimental features and LLVM runtime for MSVC")
add_definitions(-DUSE_OPENMP)
else()
find_package(OpenMP)
if(OpenMP_CXX_FOUND)
set(CMAKE_CXX_FLAGS "${CMAKE_CXX_FLAGS} ${OpenMP_CXX_FLAGS}")
add_definitions(-DUSE_OPENMP)
add_compile_definitions(_OPENMP)
else()
message(WARNING "OpenMP not found. Multithreading will be disabled.")
endif()
endif()
################################## TBB ##################################
# Add this to include the TBB header files
include_directories("C:/Program Files (x86)/Intel/oneAPI/tbb/2021.13/include")
# Alternatively, if you're using the find_package command for TBB
find_package(TBB REQUIRED)
if(TBB_FOUND)
include_directories(${TBB_INCLUDE_DIRS})
else()
message(FATAL_ERROR "TBB not found")
endif()
################################## Boost ##################################
set(CMAKE_PREFIX_PATH "${CMAKE_PREFIX_PATH};C:/vcpkg/installed/x64-windows")
set(Boost_NO_SYSTEM_PATHS ON)
set(Boost_USE_STATIC_LIBS OFF)
set(Boost_USE_MULTITHREADED ON)
set(Boost_USE_STATIC_RUNTIME OFF)
find_package(Boost REQUIRED COMPONENTS system thread serialization iostreams)
if(NOT Boost_FOUND)
message(FATAL_ERROR "Boost not found. Please check your Boost installation.")
endif()
################################## GMP and MPFR ##################################
set(GMP_ROOT "C:/Lib/GMP_MPFR")
set(GMP_INCLUDE_DIR "${GMP_ROOT}/include")
set(GMP_LIBRARY_DIR "${GMP_ROOT}/lib")
# Find GMP library
find_library(GMP_LIBRARIES
NAMES gmp libgmp libgmp-10
PATHS ${GMP_LIBRARY_DIR}
NO_DEFAULT_PATH
)
if(NOT GMP_LIBRARIES)
message(FATAL_ERROR "GMP library not found. Please check GMP_ROOT.")
endif()
# Find MPFR library
set(MPFR_INCLUDE_DIR "${GMP_ROOT}/include")
set(MPFR_LIBRARY_DIR "${GMP_ROOT}/lib")
find_library(MPFR_LIBRARIES
NAMES mpfr libmpfr libmpfr-4
PATHS ${MPFR_LIBRARY_DIR}
NO_DEFAULT_PATH
)
if(NOT MPFR_LIBRARIES)
message(FATAL_ERROR "MPFR library not found. Please check GMP_ROOT.")
endif()
set(GMP_INCLUDE_DIRS ${GMP_INCLUDE_DIR})
set(MPFR_INCLUDE_DIRS ${MPFR_INCLUDE_DIR})
################################## VTK ##################################
set(VTK_DIR "C:/Lib/VTK/VTK-9.3.1-install/lib/cmake/vtk-9.3")
if(NOT EXISTS "${VTK_DIR}/vtk-config.cmake")
message(FATAL_ERROR "VTK configuration file not found. Please check VTK_DIR.")
endif()
set(CMAKE_FIND_PACKAGE_NAME VTK)
include("${VTK_DIR}/vtk-config.cmake")
if(NOT DEFINED VTK_VERSION)
message(FATAL_ERROR "VTK_VERSION not defined after including vtk-config.cmake")
endif()
set(VTK_FOUND TRUE)
if(NOT VTK_FOUND)
message(FATAL_ERROR "VTK not found. Please install VTK or set the correct VTK_DIR.")
endif()
include_directories(${VTK_INCLUDE_DIRS})
set(REQUIRED_VTK_MODULES
CommonCore
IOImage
InteractionStyle
RenderingOpenGL2
)
foreach(MODULE ${REQUIRED_VTK_MODULES})
if(NOT TARGET VTK::${MODULE})
message(FATAL_ERROR "Required VTK module ${MODULE} is missing.")
endif()
endforeach()
################################## Eigen ##################################
set(EIGEN3_INCLUDE_DIR "C:/Lib/Eigen/eigen-3.4.0")
################################## OCC ##################################
set(OpenCASCADE_DIR "C:/Lib/OCCT/OCCT-7_8_0_binary")
set(OpenCASCADE_INCLUDE_DIR "${OpenCASCADE_DIR}/inc")
set(OpenCASCADE_LIBRARY_DIR "${OpenCASCADE_DIR}/win64/vc14/lib")
find_path(OpenCASCADE_INCLUDE_DIR Standard.hxx
PATHS ${OpenCASCADE_INCLUDE_DIR}
NO_DEFAULT_PATH
)
file(GLOB OpenCASCADE_LIBRARIES "${OpenCASCADE_LIBRARY_DIR}/*.lib")
if(OpenCASCADE_INCLUDE_DIR AND OpenCASCADE_LIBRARIES)
include_directories(${OpenCASCADE_INCLUDE_DIR})
set(OpenCASCADE_FOUND TRUE)
else()
set(OpenCASCADE_FOUND FALSE)
message(FATAL_ERROR "OpenCASCADE not found. Please check OpenCASCADE_DIR.")
endif()
################################## FFTW ##################################
set(FFTW_ROOT "C:/Lib/FFTW/fftw-3.3.10")
set(FFTW_INCLUDE_DIR "${FFTW_ROOT}/include")
set(FFTW_LIBRARY_DIR "${FFTW_ROOT}")
find_path(FFTW_INCLUDES
NAMES "fftw3.h"
PATHS ${FFTW_INCLUDE_DIR}
NO_DEFAULT_PATH
)
find_file(FFTW_LIB_DOUBLE
NAMES "libfftw3-3.lib"
PATHS ${FFTW_LIBRARY_DIR}
NO_DEFAULT_PATH
)
find_file(FFTW_LIB_FLOAT
NAMES "libfftw3f-3.lib"
PATHS ${FFTW_LIBRARY_DIR}
NO_DEFAULT_PATH
)
find_file(FFTW_LIB_LONG_DOUBLE
NAMES "libfftw3l-3.lib"
PATHS ${FFTW_LIBRARY_DIR}
NO_DEFAULT_PATH
)
if(NOT FFTW_INCLUDES)
message(FATAL_ERROR "FFTW3 headers not found. Please check FFTW_INCLUDE_DIR.")
endif()
if(NOT FFTW_LIB_DOUBLE OR NOT FFTW_LIB_FLOAT OR NOT FFTW_LIB_LONG_DOUBLE)
message(FATAL_ERROR "FFTW3 import libraries not found. Please check FFTW_LIBRARY_DIR.")
endif()
# Add the found libraries to FFTW_LIBRARIES
set(FFTW_LIBRARIES ${FFTW_LIB_DOUBLE} ${FFTW_LIB_FLOAT} ${FFTW_LIB_LONG_DOUBLE})
################################## GLFW3 ##################################
set(GLFW3_ROOT "C:/Lib/GLFW/glfw-3.4")
set(GLFW3_INCLUDE_DIR "${GLFW3_ROOT}/include")
find_path(GLFW3_INCLUDES
NAMES "GLFW/glfw3.h"
PATHS ${GLFW3_INCLUDE_DIR}
NO_DEFAULT_PATH
)
if(NOT GLFW3_INCLUDES)
message(FATAL_ERROR "GLFW3 headers not found. Please check GLFW3_INCLUDE_DIR.")
endif()
# Since GLFW3 is not installed, we'll add it as a subdirectory
add_subdirectory(${GLFW3_ROOT} ${CMAKE_BINARY_DIR}/glfw3)
################################## FreeImage ##################################
set(FREEIMAGE_ROOT "C:/Lib/FreeImage/FreeImage-3-18-0")
set(FREEIMAGE_INCLUDE_DIR "${FREEIMAGE_ROOT}/include")
set(FREEIMAGE_LIBRARY_DIR "${FREEIMAGE_ROOT}/Dist/x64")
find_path(FREEIMAGE_INCLUDE_DIR
NAMES "FreeImage.h"
PATHS ${FREEIMAGE_INCLUDE_DIR}
NO_DEFAULT_PATH
)
find_library(FREEIMAGE_LIBRARY
NAMES "FreeImage"
PATHS ${FREEIMAGE_LIBRARY_DIR}
NO_DEFAULT_PATH
)
if(NOT FREEIMAGE_INCLUDE_DIR)
message(FATAL_ERROR "FreeImage header not found. Please check FREEIMAGE_INCLUDE_DIR.")
endif()
if(NOT FREEIMAGE_LIBRARY)
message(FATAL_ERROR "FreeImage library not found. Please check FREEIMAGE_LIBRARY_DIR.")
endif()
################################## CGAL ##################################
set(CGAL_DIR "C:/Lib/CGAL/CGAL-5.6.1")
set(CGAL_INCLUDE_DIR "${CGAL_DIR}/include")
set(CMAKE_PREFIX_PATH ${CMAKE_PREFIX_PATH} "${CGAL_DIR}")
find_package(CGAL REQUIRED)
if(NOT EXISTS ${CGAL_INCLUDE_DIR})
message(FATAL_ERROR "CGAL include directory not found.")
endif()
# Add CGAL flags
add_definitions(${CGAL_DEFINITIONS})
include(${CGAL_USE_FILE})
################################## NVIDIA CUDA ##################################
set(CMAKE_CUDA_ARCHITECTURES 89)
set(CMAKE_CUDA_SEPARABLE_COMPILATION ON)
set(CMAKE_CUDA_RESOLVE_DEVICE_SYMBOLS ON)
find_package(CUDAToolkit REQUIRED)
################################## NVIDIA OptiX ##################################
set(OptiX_INCLUDE_DIRS "C:/ProgramData/NVIDIA Corporation/OptiX SDK 8.0.0/include")
add_definitions(-DOPTIX_DYNAMIC_LOADING)
################################## OPTIX file compilation ##################################
function(compile_optix_cuda TARGET_NAME)
foreach(CUDA_FILE ${ARGN})
get_filename_component(CUDA_FILE_NAME ${CUDA_FILE} NAME_WE)
set(GENERATED_PTX_FILE "${CMAKE_CURRENT_BINARY_DIR}/${CUDA_FILE_NAME}.ptx")
# Debugging: Print the file being processed and the generated output
message(STATUS "Processing CUDA file: ${CUDA_FILE}")
message(STATUS "Generating PTX: ${GENERATED_PTX_FILE}")
# Print the full NVCC command for debugging
message(STATUS "Running NVCC Command:")
message(STATUS "${CMAKE_CUDA_COMPILER} -ptx -o ${GENERATED_PTX_FILE} ${CUDA_FILE}")
# Custom command to compile the PTX file
add_custom_command(
OUTPUT ${GENERATED_PTX_FILE}
COMMAND ${CMAKE_CUDA_COMPILER}
-ptx
-o "${GENERATED_PTX_FILE}"
"${CUDA_FILE}"
-I "${CMAKE_CURRENT_SOURCE_DIR}/include"
-I "${CMAKE_SOURCE_DIR}/src"
-I "${OpenCASCADE_INCLUDE_DIR}"
-I "${EIGEN3_INCLUDE_DIR}"
-I "${GMP_INCLUDE_DIR}"
-I "${MPFR_INCLUDE_DIR}"
-I "${CGAL_INCLUDE_DIRS}"
-I "${VTK_INCLUDE_DIRS}"
-I "${Boost_INCLUDE_DIRS}"
-I "${Python3_INCLUDE_DIRS}"
-I "${pybind11_INCLUDE_DIRS}"
-I "${FFTW_INCLUDES}"
-I "${TBB_INCLUDE_DIRS}"
-I "${CUDAToolkit_INCLUDE_DIRS}"
-I "${OptiX_INCLUDE_DIRS}"
-D__CUDACC__
DEPENDS "${CUDA_FILE}"
COMMENT "Compiling ${CUDA_FILE} to PTX"
VERBATIM # Ensures proper handling of arguments
)
# Adding the generated PTX file to the target sources
target_sources(${TARGET_NAME} PRIVATE ${GENERATED_PTX_FILE})
endforeach()
endfunction()
# Example usage: compile_optix_cuda(YourTargetName your_cuda_file1.cu your_cuda_file2.cu)
################################## Python and pybind11 ##################################
set(Python3_ROOT_DIR "C:/Python312")
set(Python3_EXECUTABLE "${Python3_ROOT_DIR}/python.exe")
set(Python3_INCLUDE_DIR "${Python3_ROOT_DIR}/include")
set(Python3_LIBRARY "${Python3_ROOT_DIR}/libs/python312.lib")
find_package(Python3 REQUIRED COMPONENTS Interpreter Development)
find_package(pybind11 CONFIG REQUIRED)
################################## Include directories ##################################
include_directories(${CMAKE_CURRENT_SOURCE_DIR}/include)
include_directories(${CMAKE_SOURCE_DIR}/src)
include_directories(${EIGEN3_INCLUDE_DIR})
include_directories(${GMP_INCLUDE_DIR})
include_directories(${MPFR_INCLUDE_DIR})
include_directories(${CGAL_INCLUDE_DIR})
include_directories(${VTK_INCLUDE_DIRS})
include_directories(${OpenCASCADE_INCLUDE_DIR})
include_directories(${Boost_INCLUDE_DIRS})
include_directories(${Python3_INCLUDE_DIRS})
include_directories(${pybind11_INCLUDE_DIRS})
include_directories(${FFTW_INCLUDES})
include_directories(${TBB_INCLUDE_DIRS})
include_directories(${CUDAToolkit_INCLUDE_DIRS})
include_directories(${OptiX_INCLUDE_DIRS})
include_directories(${CGAL_INCLUDE_DIRS})
################################## Add definitions for CGAL ##################################
add_definitions(-DCGAL_USE_BASIC_VIEWER)
################################## Find all source files ##################################
# Add C++ files
file(GLOB_RECURSE SOURCES "${CMAKE_SOURCE_DIR}/src/*.cpp")
# Add CUDA files
file(GLOB CUDA_SOURCES "${CMAKE_SOURCE_DIR}/src/cuda/*.cu")
################################## Create executable ##################################
add_executable(CadUtilityLibrary ${SOURCES} ${CUDA_SOURCES})
target_compile_features(CadUtilityLibrary PUBLIC cxx_std_17)
set_target_properties(CadUtilityLibrary PROPERTIES CUDA_STANDARD 17)
if(MSVC)
# Apply the MSVC-specific flags only to C++ compilation, not CUDA
target_compile_options(CadUtilityLibrary PRIVATE
"$<$<COMPILE_LANGUAGE:CXX>:/external:W0>"
"$<$<COMPILE_LANGUAGE:CXX>:/external:anglebrackets>"
)
message(STATUS "Disabling external Library warnings for MSVC")
endif()
################################## VTK module auto initialization ##################################
vtk_module_autoinit(TARGETS CadUtilityLibrary MODULES ${VTK_LIBRARIES})
################################## Link libraries ##################################
target_sources(CadUtilityLibrary PRIVATE ${CUDA_SOURCES})
target_include_directories(CadUtilityLibrary PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
${OpenCASCADE_INCLUDE_DIR}
)
target_link_libraries(CadUtilityLibrary PRIVATE
${OpenCASCADE_LIBRARIES}
CGAL::CGAL
${VTK_LIBRARIES}
${Boost_LIBRARIES}
TBB::tbb
TBB::tbbmalloc
${FFTW_LIBRARIES}
${Python3_LIBRARIES}
pybind11::pybind11
${GMP_LIBRARIES}
${MPFR_LIBRARIES}
${CUDA_LIBRARIES}
${CUDAToolkit_LIBRARIES}
)
################################## Create Python module ##################################
pybind11_add_module(voxelizationUtil ${SOURCES} ${CUDA_SOURCES})
target_compile_features(voxelizationUtil PUBLIC cxx_std_17)
set_target_properties(voxelizationUtil PROPERTIES CUDA_STANDARD 17)
################################## Link Python module ##################################
target_sources(voxelizationUtil PRIVATE ${CUDA_SOURCES})
target_include_directories(voxelizationUtil PRIVATE
${CMAKE_CURRENT_SOURCE_DIR}/include
${CMAKE_SOURCE_DIR}/src
${OpenCASCADE_INCLUDE_DIR}
)
target_link_libraries(voxelizationUtil PRIVATE
${OpenCASCADE_LIBRARIES}
CGAL::CGAL
${VTK_LIBRARIES}
${Boost_LIBRARIES}
TBB::tbb
TBB::tbbmalloc
${FFTW_LIBRARIES}
${Python3_LIBRARIES}
pybind11::pybind11
${GMP_LIBRARIES}
${MPFR_LIBRARIES}
${CUDA_LIBRARIES}
${CUDAToolkit_LIBRARIES}
)
################################## Set CUDA-specific flags ##################################
set_target_properties(CadUtilityLibrary PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(voxelizationUtil PROPERTIES POSITION_INDEPENDENT_CODE ON)
set_target_properties(CadUtilityLibrary voxelizationUtil PROPERTIES CUDA_SEPARABLE_COMPILATION ON)
################################## Compile OPTIX Files ##################################
compile_optix_cuda(CadUtilityLibrary ${CUDA_SOURCES})
compile_optix_cuda(voxelizationUtil ${CUDA_SOURCES})
################################## Set MSVC-specific flags ##################################
if (MSVC)
# Apply these only to C++ compilation, not CUDA
target_compile_options(CadUtilityLibrary PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/external:W0>" "$<$<COMPILE_LANGUAGE:CXX>:/external:anglebrackets>")
target_link_options(CadUtilityLibrary PRIVATE /NODEFAULTLIB:LIBCMT)
target_compile_options(voxelizationUtil PRIVATE "$<$<COMPILE_LANGUAGE:CXX>:/external:W0>" "$<$<COMPILE_LANGUAGE:CXX>:/external:anglebrackets>")
target_link_options(voxelizationUtil PRIVATE /NODEFAULTLIB:LIBCMT)
endif()
################################## Install the Python module ##################################
install(TARGETS voxelizationUtil LIBRARY DESTINATION ${Python3_SITEARCH})
install(TARGETS CadUtilityLibrary RUNTIME DESTINATION bin)
install(FILES ${OpenCASCADE_LIBRARY_DIR}/TKBRep.dll
${OpenCASCADE_LIBRARY_DIR}/TKDEIGES.dll
${OpenCASCADE_LIBRARY_DIR}/TKDESTEP.dll
DESTINATION bin)
Any help is greatly appreciated.