diff --git a/.gitignore b/.gitignore index 7862593..47c9b81 100644 --- a/.gitignore +++ b/.gitignore @@ -17,4 +17,4 @@ hiprt/cache/KernelArgs.h PUBLIC_OUT/ hiprt/impl/bvh_build_array.h scripts/bitcodes/__pycache__/ -test/common/meshes/lfs +test/common/meshes/lfs \ No newline at end of file diff --git a/CMakeLists.txt b/CMakeLists.txt index 625ea77..55b8b7e 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -591,6 +591,9 @@ if(WIN32) target_link_libraries(${HIPRT_NAME} version) endif() +if(WIN32 AND cuda_path) + target_link_libraries(${HIPRT_NAME} "${cuda_path}/lib/x64/cuda.lib" "${cuda_path}/lib/x64/cudart.lib") +endif() target_include_directories(${HIPRT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}) target_include_directories(${HIPRT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/contrib/Orochi) @@ -720,3 +723,16 @@ if(HIPRTEW) target_compile_definitions(hiprtewtest PRIVATE GTEST_HAS_TR1_TUPLE=0) endif() + + + +# Fix hiprt03001 to find embree +target_include_directories(${HIPRT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/contrib/embree/include) +target_compile_definitions(${HIPRT_NAME} PRIVATE HIPEW_DO_NOT_CHECK_VERSION) +if(WIN32) + target_link_directories(${HIPRT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/contrib/embree/win) + target_link_libraries(${HIPRT_NAME} ${CMAKE_CURRENT_SOURCE_DIR}/contrib/embree/win/embree4.lib) +elseif(UNIX) + target_link_directories(${HIPRT_NAME} PRIVATE ${CMAKE_CURRENT_SOURCE_DIR}/contrib/embree/linux) + target_link_libraries(${HIPRT_NAME} embree4 tbb) +endif() diff --git a/cache/2b5ffda9-721887d1.v.NVIDIA GeForce GTX 1650 Ti.13020_64.bin.check b/cache/2b5ffda9-721887d1.v.NVIDIA GeForce GTX 1650 Ti.13020_64.bin.check new file mode 100644 index 0000000..6823b7c Binary files /dev/null and b/cache/2b5ffda9-721887d1.v.NVIDIA GeForce GTX 1650 Ti.13020_64.bin.check differ diff --git a/contrib/Orochi/Orochi/Orochi.cpp b/contrib/Orochi/Orochi/Orochi.cpp index a987d31..6ea3573 100644 --- a/contrib/Orochi/Orochi/Orochi.cpp +++ b/contrib/Orochi/Orochi/Orochi.cpp @@ -23,6 +23,7 @@ #include +#include #include #include #include @@ -844,6 +845,9 @@ int oroInitialize( oroApi api, oroU32 flags, int e = 0; s_loadedApis = 0; + if( api == ORO_API_AUTOMATIC ) + api = (oroApi)(ORO_API_CUDA | ORO_API_HIP); + if( api & ORO_API_CUDA ) { #ifdef OROCHI_ENABLE_CUEW @@ -1154,7 +1158,11 @@ oroError OROAPI oroCtxCreate(oroCtx* pctx, unsigned int flags, oroDevice dev) if( s_api & ORO_API_CUDADRIVER ) { #ifdef OROCHI_ENABLE_CUEW + #if CUDA_VERSION >= 13000 + CU4ORO::CUresult e = CU4ORO::cuCtxCreate( oroCtx2cu( pctx ), nullptr, flags, d.getDevice() ); + #else CU4ORO::CUresult e = CU4ORO::cuCtxCreate( oroCtx2cu( pctx ), flags, d.getDevice() ); + #endif if ( e != CU4ORO::CUDA_SUCCESS ) return cu2oro(e); #endif diff --git a/contrib/Orochi/Orochi/enable_cuew.cmake b/contrib/Orochi/Orochi/enable_cuew.cmake index d251abe..2a59e35 100644 --- a/contrib/Orochi/Orochi/enable_cuew.cmake +++ b/contrib/Orochi/Orochi/enable_cuew.cmake @@ -41,10 +41,10 @@ endfunction() # Region generated by Orochi Summoner #REGION_PREMAKE_START CudaPath -set(BEST_CUDA_VERSION_NAME "12.2") -set(BEST_CUDA_ENVVAR "CUDA_PATH_V12_2") -set(BEST_CUDA_PATH_LINUX "/usr/local/cuda-12.2") -set(BEST_CUDA_PATH_WINDOWS "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v12.2") +set(BEST_CUDA_VERSION_NAME "13.0") +set(BEST_CUDA_ENVVAR "CUDA_PATH_V13_0") +set(BEST_CUDA_PATH_LINUX "/usr/local/cuda-13.0") +set(BEST_CUDA_PATH_WINDOWS "C:/Program Files/NVIDIA GPU Computing Toolkit/CUDA/v13.0") set(BACKUP_CUDA_ENVVAR "CUDA_PATH") set(BACKUP_CUDA_PATH_LINUX "/usr/local/cuda") diff --git a/contrib/Orochi/Orochi/nvidia_hip_runtime_api_oro.h b/contrib/Orochi/Orochi/nvidia_hip_runtime_api_oro.h index 5953008..a209862 100644 --- a/contrib/Orochi/Orochi/nvidia_hip_runtime_api_oro.h +++ b/contrib/Orochi/Orochi/nvidia_hip_runtime_api_oro.h @@ -2250,14 +2250,20 @@ inline static hipError_t hipChooseDeviceR0600_cu4oro(int* device, const hipDevic cdprop.regsPerBlock = prop->regsPerBlock; cdprop.warpSize = prop->warpSize; cdprop.maxThreadsPerBlock = prop->maxThreadsPerBlock; +#if CUDA_VERSION < 13000 cdprop.clockRate = prop->clockRate; +#endif cdprop.totalConstMem = prop->totalConstMem; cdprop.multiProcessorCount = prop->multiProcessorCount; cdprop.l2CacheSize = prop->l2CacheSize; cdprop.maxThreadsPerMultiProcessor = prop->maxThreadsPerMultiProcessor; +#if CUDA_VERSION < 13000 cdprop.computeMode = prop->computeMode; +#endif cdprop.canMapHostMemory = prop->canMapHostMemory; +#if CUDA_VERSION < 13000 cdprop.memoryClockRate = prop->memoryClockRate; +#endif cdprop.memoryBusWidth = prop->memoryBusWidth; return hipCUDAErrorTohipError(cudaChooseDevice(device, &cdprop)); } @@ -2635,21 +2641,31 @@ inline static hipError_t hipGetDevicePropertiesR0600_cu4oro(hipDeviceProp_t* p_p p_prop->maxGridSize[0] = cdprop.maxGridSize[0]; p_prop->maxGridSize[1] = cdprop.maxGridSize[1]; p_prop->maxGridSize[2] = cdprop.maxGridSize[2]; +#if CUDA_VERSION < 13000 p_prop->clockRate = cdprop.clockRate; +#endif p_prop->totalConstMem = cdprop.totalConstMem; p_prop->major = cdprop.major; p_prop->minor = cdprop.minor; p_prop->textureAlignment = cdprop.textureAlignment; p_prop->texturePitchAlignment = cdprop.texturePitchAlignment; +#if CUDA_VERSION < 13000 p_prop->deviceOverlap = cdprop.deviceOverlap; +#endif p_prop->multiProcessorCount = cdprop.multiProcessorCount; +#if CUDA_VERSION < 13000 p_prop->kernelExecTimeoutEnabled = cdprop.kernelExecTimeoutEnabled; +#endif p_prop->integrated = cdprop.integrated; p_prop->canMapHostMemory = cdprop.canMapHostMemory; +#if CUDA_VERSION < 13000 p_prop->computeMode = cdprop.computeMode; +#endif p_prop->maxTexture1D = cdprop.maxTexture1D; p_prop->maxTexture1DMipmap = cdprop.maxTexture1DMipmap; +#if CUDA_VERSION < 13000 p_prop->maxTexture1DLinear = cdprop.maxTexture1DLinear; +#endif p_prop->maxTexture2D[0] = cdprop.maxTexture2D[0]; p_prop->maxTexture2D[1] = cdprop.maxTexture2D[1]; p_prop->maxTexture2DMipmap[0] = cdprop.maxTexture2DMipmap[0]; @@ -2696,7 +2712,9 @@ inline static hipError_t hipGetDevicePropertiesR0600_cu4oro(hipDeviceProp_t* p_p p_prop->tccDriver = cdprop.tccDriver; p_prop->asyncEngineCount = cdprop.asyncEngineCount; p_prop->unifiedAddressing = cdprop.unifiedAddressing; +#if CUDA_VERSION < 13000 p_prop->memoryClockRate = cdprop.memoryClockRate; +#endif p_prop->memoryBusWidth = cdprop.memoryBusWidth; p_prop->l2CacheSize = cdprop.l2CacheSize; p_prop->maxThreadsPerMultiProcessor = cdprop.maxThreadsPerMultiProcessor; @@ -2709,13 +2727,17 @@ inline static hipError_t hipGetDevicePropertiesR0600_cu4oro(hipDeviceProp_t* p_p p_prop->isMultiGpuBoard = cdprop.isMultiGpuBoard; p_prop->multiGpuBoardGroupID = cdprop.multiGpuBoardGroupID; p_prop->hostNativeAtomicSupported = cdprop.hostNativeAtomicSupported; +#if CUDA_VERSION < 13000 p_prop->singleToDoublePrecisionPerfRatio = cdprop.singleToDoublePrecisionPerfRatio; +#endif p_prop->pageableMemoryAccess = cdprop.pageableMemoryAccess; p_prop->concurrentManagedAccess = cdprop.concurrentManagedAccess; p_prop->computePreemptionSupported = cdprop.computePreemptionSupported; p_prop->canUseHostPointerForRegisteredMem = cdprop.canUseHostPointerForRegisteredMem; p_prop->cooperativeLaunch = cdprop.cooperativeLaunch; +#if CUDA_VERSION < 13000 p_prop->cooperativeMultiDeviceLaunch = cdprop.cooperativeMultiDeviceLaunch; +#endif p_prop->sharedMemPerBlockOptin = cdprop.sharedMemPerBlockOptin; p_prop->pageableMemoryAccessUsesHostPageTables = cdprop.pageableMemoryAccessUsesHostPageTables; p_prop->directManagedMemAccessFromHost = cdprop.directManagedMemAccessFromHost; @@ -2871,7 +2893,11 @@ inline static hipError_t hipDeviceGetAttribute_cu4oro(int* pi, hipDeviceAttribut cdattr = cudaDevAttrCooperativeLaunch; break; case hipDeviceAttributeCooperativeMultiDeviceLaunch: +#if CUDA_VERSION < 13000 cdattr = cudaDevAttrCooperativeMultiDeviceLaunch; +#else + cdattr = cudaDevAttrCooperativeLaunch; +#endif break; case hipDeviceAttributeHostRegisterSupported: cdattr = cudaDevAttrHostRegisterSupported; @@ -3331,7 +3357,11 @@ inline static hipError_t hipEventQuery_cu4oro(hipEvent_t event) { } inline static hipError_t hipCtxCreate_cu4oro(hipCtx_t* ctx, unsigned int flags, hipDevice_t device) { +#if CUDA_VERSION >= 13000 + return hipCUResultTohipError(cuCtxCreate(ctx, nullptr, flags, device)); +#else return hipCUResultTohipError(cuCtxCreate(ctx, flags, device)); +#endif } inline static hipError_t hipCtxDestroy_cu4oro(hipCtx_t ctx) { diff --git a/contrib/Orochi/contrib/cuew/src/cuew.cpp b/contrib/Orochi/contrib/cuew/src/cuew.cpp index 7120a3e..106c0d9 100644 --- a/contrib/Orochi/contrib/cuew/src/cuew.cpp +++ b/contrib/Orochi/contrib/cuew/src/cuew.cpp @@ -99,8 +99,8 @@ static DynamicLibrary nvrtc_lib = NULL; // It's recommanded to use similar versions in the #include of CUDA SDK. // If this assert is wrong, it's advised either to install a CUDA SDK closed to version 12020 or search on the Orochi github a branch matching the CUDA SDK you are using. // checking the major-version number only: -static_assert( ((int)CUDA_VERSION / (int)1000) == ((int)12020/ (int)1000) ); -static_assert( ((int)CUDART_VERSION / (int)1000) == ((int)12020/ (int)1000) ); +static_assert( ((int)CUDA_VERSION / (int)1000) == ((int)12020/ (int)1000) || ((int)CUDA_VERSION / (int)1000) == ((int)13000/ (int)1000) ); +static_assert( ((int)CUDART_VERSION / (int)1000) == ((int)12020/ (int)1000) || ((int)CUDART_VERSION / (int)1000) == ((int)13000/ (int)1000) ); #endif @@ -862,7 +862,7 @@ static int cuewCudaInit(const char** customPaths_Cuda, const char** customPaths_ #ifdef _WIN32 // Expected in c:/windows/system or similar, no path needed. const char *cuda_paths[] = {"nvcuda.dll", NULL}; - const char *cudart_paths[] = {"cudart64_12.dll", NULL}; + const char *cudart_paths[] = {"cudart64_13.dll", "cudart64_12.dll", NULL}; #elif defined(__APPLE__) // Default installation path. const char *cuda_paths[] = {"/usr/local/cuda/lib/libcuda.dylib", NULL}; @@ -1629,7 +1629,8 @@ static int cuewNvrtcInit(const char** customPaths_NvRTC) /* Library paths. */ #ifdef _WIN32 /* Expected in c:/windows/system or similar, no path needed. */ - const char* nvrtc_paths[] = {"nvrtc64_120_0.dll", + const char* nvrtc_paths[] = {"nvrtc64_130_0.dll", + "nvrtc64_120_0.dll", "nvrtc64_112_0.dll", "nvrtc64_101_0.dll", "nvrtc64_100_0.dll", diff --git a/hiprt/hiprt_cpu.h b/hiprt/hiprt_cpu.h new file mode 100644 index 0000000..997f3ba --- /dev/null +++ b/hiprt/hiprt_cpu.h @@ -0,0 +1,343 @@ +#pragma once + +#include +#include +#include +#include + +namespace hiprt +{ + +class hiprtGeomTraversalClosestCPU +{ + public: + static void traceBatch( + hiprtContext ctx, + hiprtGeometry geom, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuGeometryData* cpuGeom = contextBase->getCpuGeom(geom); + if (!cpuGeom || !cpuGeom->rtcScene) return; + + RTCIntersectArguments args; + rtcInitIntersectArguments(&args); + + for (uint32_t i = 0; i < count; ++i) + { + RTCRayHit rayhit; + rayhit.ray.org_x = rays[i].origin.x; + rayhit.ray.org_y = rays[i].origin.y; + rayhit.ray.org_z = rays[i].origin.z; + rayhit.ray.dir_x = rays[i].direction.x; + rayhit.ray.dir_y = rays[i].direction.y; + rayhit.ray.dir_z = rays[i].direction.z; + rayhit.ray.tnear = rays[i].minT; + rayhit.ray.tfar = rays[i].maxT; + rayhit.ray.mask = -1; + rayhit.ray.id = i; + rayhit.ray.flags = 0; + + rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID; + rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; + + rtcIntersect1(cpuGeom->rtcScene, &rayhit, &args); + + if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) + { + hits[i].primID = rayhit.hit.primID; + hits[i].instanceID = hiprtInvalidValue; + hits[i].uv.x = rayhit.hit.u; + hits[i].uv.y = rayhit.hit.v; + hits[i].normal.x = rayhit.hit.Ng_x; + hits[i].normal.y = rayhit.hit.Ng_y; + hits[i].normal.z = rayhit.hit.Ng_z; + hits[i].t = rayhit.ray.tfar; + } + else + { + hits[i].primID = hiprtInvalidValue; + } + } + } + + static void traceBatchAVX( + hiprtContext ctx, + hiprtGeometry geom, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuGeometryData* cpuGeom = contextBase->getCpuGeom(geom); + if (!cpuGeom || !cpuGeom->rtcScene) return; + + RTCIntersectArguments args; + rtcInitIntersectArguments(&args); + + for (uint32_t i = 0; i < count; i += 8) + { + RTCRayHit8 rayhit8; + int valid[8] = {0}; + + uint32_t batchSize = std::min(count - i, 8u); + + for (uint32_t j = 0; j < batchSize; ++j) + { + valid[j] = -1; + rayhit8.ray.org_x[j] = rays[i + j].origin.x; + rayhit8.ray.org_y[j] = rays[i + j].origin.y; + rayhit8.ray.org_z[j] = rays[i + j].origin.z; + rayhit8.ray.dir_x[j] = rays[i + j].direction.x; + rayhit8.ray.dir_y[j] = rays[i + j].direction.y; + rayhit8.ray.dir_z[j] = rays[i + j].direction.z; + rayhit8.ray.tnear[j] = rays[i + j].minT; + rayhit8.ray.tfar[j] = rays[i + j].maxT; + rayhit8.ray.mask[j] = -1; + rayhit8.ray.id[j] = i + j; + rayhit8.ray.flags[j] = 0; + + rayhit8.hit.geomID[j] = RTC_INVALID_GEOMETRY_ID; + rayhit8.hit.instID[0][j] = RTC_INVALID_GEOMETRY_ID; + } + + for (uint32_t j = batchSize; j < 8; ++j) { + valid[j] = 0; + } + + rtcIntersect8(valid, cpuGeom->rtcScene, &rayhit8, &args); + + for (uint32_t j = 0; j < batchSize; ++j) + { + if (rayhit8.hit.geomID[j] != RTC_INVALID_GEOMETRY_ID) + { + hits[i + j].primID = rayhit8.hit.primID[j]; + hits[i + j].instanceID = hiprtInvalidValue; + hits[i + j].uv.x = rayhit8.hit.u[j]; + hits[i + j].uv.y = rayhit8.hit.v[j]; + hits[i + j].normal.x = rayhit8.hit.Ng_x[j]; + hits[i + j].normal.y = rayhit8.hit.Ng_y[j]; + hits[i + j].normal.z = rayhit8.hit.Ng_z[j]; + hits[i + j].t = rayhit8.ray.tfar[j]; + } + else + { + hits[i + j].primID = hiprtInvalidValue; + } + } + } + } + + static void traceBatchAVX( + hiprtContext ctx, + hiprtScene scene, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuSceneData* cpuScene = contextBase->getCpuScene(scene); + if (!cpuScene || !cpuScene->rtcScene) return; + + RTCIntersectArguments args; + rtcInitIntersectArguments(&args); + + for (uint32_t i = 0; i < count; i += 8) + { + RTCRayHit8 rayhit8; + int valid[8] = {0}; + + uint32_t batchSize = std::min(count - i, 8u); + + for (uint32_t j = 0; j < batchSize; ++j) + { + valid[j] = -1; + rayhit8.ray.org_x[j] = rays[i + j].origin.x; + rayhit8.ray.org_y[j] = rays[i + j].origin.y; + rayhit8.ray.org_z[j] = rays[i + j].origin.z; + rayhit8.ray.dir_x[j] = rays[i + j].direction.x; + rayhit8.ray.dir_y[j] = rays[i + j].direction.y; + rayhit8.ray.dir_z[j] = rays[i + j].direction.z; + rayhit8.ray.tnear[j] = rays[i + j].minT; + rayhit8.ray.tfar[j] = rays[i + j].maxT; + rayhit8.ray.mask[j] = -1; + rayhit8.ray.id[j] = i + j; + rayhit8.ray.flags[j] = 0; + + rayhit8.hit.geomID[j] = RTC_INVALID_GEOMETRY_ID; + rayhit8.hit.instID[0][j] = RTC_INVALID_GEOMETRY_ID; + } + + for (uint32_t j = batchSize; j < 8; ++j) { + valid[j] = 0; + } + + rtcIntersect8(valid, cpuScene->rtcScene, &rayhit8, &args); + + for (uint32_t j = 0; j < batchSize; ++j) + { + if (rayhit8.hit.geomID[j] != RTC_INVALID_GEOMETRY_ID) + { + hits[i + j].primID = rayhit8.hit.primID[j]; + hits[i + j].instanceID = rayhit8.hit.instID[0][j]; + hits[i + j].uv.x = rayhit8.hit.u[j]; + hits[i + j].uv.y = rayhit8.hit.v[j]; + hits[i + j].normal.x = rayhit8.hit.Ng_x[j]; + hits[i + j].normal.y = rayhit8.hit.Ng_y[j]; + hits[i + j].normal.z = rayhit8.hit.Ng_z[j]; + hits[i + j].t = rayhit8.ray.tfar[j]; + } + else + { + hits[i + j].primID = hiprtInvalidValue; + } + } + } + } + + static void traceBatch( + hiprtContext ctx, + hiprtScene scene, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuSceneData* cpuScene = contextBase->getCpuScene(scene); + if (!cpuScene || !cpuScene->rtcScene) return; + + RTCIntersectArguments args; + rtcInitIntersectArguments(&args); + + for (uint32_t i = 0; i < count; ++i) + { + RTCRayHit rayhit; + rayhit.ray.org_x = rays[i].origin.x; + rayhit.ray.org_y = rays[i].origin.y; + rayhit.ray.org_z = rays[i].origin.z; + rayhit.ray.dir_x = rays[i].direction.x; + rayhit.ray.dir_y = rays[i].direction.y; + rayhit.ray.dir_z = rays[i].direction.z; + rayhit.ray.tnear = rays[i].minT; + rayhit.ray.tfar = rays[i].maxT; + rayhit.ray.mask = -1; + rayhit.ray.id = i; + rayhit.ray.flags = 0; + + rayhit.hit.geomID = RTC_INVALID_GEOMETRY_ID; + rayhit.hit.instID[0] = RTC_INVALID_GEOMETRY_ID; + + rtcIntersect1(cpuScene->rtcScene, &rayhit, &args); + + if (rayhit.hit.geomID != RTC_INVALID_GEOMETRY_ID) + { + hits[i].primID = rayhit.hit.primID; + hits[i].instanceID = rayhit.hit.instID[0]; + hits[i].uv.x = rayhit.hit.u; + hits[i].uv.y = rayhit.hit.v; + hits[i].normal.x = rayhit.hit.Ng_x; + hits[i].normal.y = rayhit.hit.Ng_y; + hits[i].normal.z = rayhit.hit.Ng_z; + hits[i].t = rayhit.ray.tfar; + } + else + { + hits[i].primID = hiprtInvalidValue; + } + } + } +}; + +class hiprtGeomTraversalAnyHitCPU +{ + public: + static void traceBatch( + hiprtContext ctx, + hiprtGeometry geom, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuGeometryData* cpuGeom = contextBase->getCpuGeom(geom); + if (!cpuGeom || !cpuGeom->rtcScene) return; + + RTCOccludedArguments args; + rtcInitOccludedArguments(&args); + + for (uint32_t i = 0; i < count; ++i) + { + RTCRay ray; + ray.org_x = rays[i].origin.x; + ray.org_y = rays[i].origin.y; + ray.org_z = rays[i].origin.z; + ray.dir_x = rays[i].direction.x; + ray.dir_y = rays[i].direction.y; + ray.dir_z = rays[i].direction.z; + ray.tnear = rays[i].minT; + ray.tfar = rays[i].maxT; + ray.mask = -1; + ray.id = i; + ray.flags = 0; + + rtcOccluded1(cpuGeom->rtcScene, &ray, &args); + + if (ray.tfar < 0.0f) // hit + { + hits[i].primID = 0; // Just some valid value to indicate hit + hits[i].t = 0.0f; + } + else + { + hits[i].primID = hiprtInvalidValue; + } + } + } + + static void traceBatch( + hiprtContext ctx, + hiprtScene scene, + const hiprtRay* rays, + hiprtHit* hits, + uint32_t count ) + { + auto* contextBase = reinterpret_cast(ctx); + CpuSceneData* cpuScene = contextBase->getCpuScene(scene); + if (!cpuScene || !cpuScene->rtcScene) return; + + RTCOccludedArguments args; + rtcInitOccludedArguments(&args); + + for (uint32_t i = 0; i < count; ++i) + { + RTCRay ray; + ray.org_x = rays[i].origin.x; + ray.org_y = rays[i].origin.y; + ray.org_z = rays[i].origin.z; + ray.dir_x = rays[i].direction.x; + ray.dir_y = rays[i].direction.y; + ray.dir_z = rays[i].direction.z; + ray.tnear = rays[i].minT; + ray.tfar = rays[i].maxT; + ray.mask = -1; + ray.id = i; + ray.flags = 0; + + rtcOccluded1(cpuScene->rtcScene, &ray, &args); + + if (ray.tfar < 0.0f) // hit + { + hits[i].primID = 0; // Just some valid value to indicate hit + hits[i].t = 0.0f; + } + else + { + hits[i].primID = hiprtInvalidValue; + } + } + } +}; + +} // namespace hiprt diff --git a/hiprt/hiprt_hybrid.h b/hiprt/hiprt_hybrid.h new file mode 100644 index 0000000..fc96362 --- /dev/null +++ b/hiprt/hiprt_hybrid.h @@ -0,0 +1,72 @@ +#pragma once + +#include +#include +#include +#include +#include +#include +#include + +namespace hiprt +{ + +struct hiprtHybridTraceConfig +{ + float gpuFraction = 0.8f; + uint32_t minCpuBatch = 1024; +}; + +inline void hiprtTraceHybridClosest( + hiprtContext context, + hiprtScene scene, + const hiprtHybridTraceConfig& config, + hiprtRay* raysGpuVisible, + hiprtHit* hitsGpuVisible, + uint32_t rayCount, + hiprtApiStream stream, + std::function gpuLaunchCallback ) +{ + const uint32_t gpuCount = static_cast( rayCount * config.gpuFraction ); + const uint32_t cpuStart = gpuCount; + + // 1. Launch GPU kernel for rays [0 .. gpuCount) + if (gpuCount > 0 && gpuLaunchCallback) + { + gpuLaunchCallback(0, gpuCount); + } + + // 2. Launch CPU traceBatch for rays [gpuCount .. rayCount) + if (rayCount > cpuStart) + { + uint32_t cpuCount = rayCount - cpuStart; + const uint32_t chunkSize = 16384; + uint32_t numChunks = (cpuCount + chunkSize - 1) / chunkSize; + std::vector> futures; + + for (uint32_t i = 0; i < numChunks; ++i) { + uint32_t offset = i * chunkSize; + uint32_t size = std::min(chunkSize, cpuCount - offset); + futures.push_back(std::async(std::launch::async, [=]() { + hiprtGeomTraversalClosestCPU::traceBatch( + context, + scene, + raysGpuVisible + cpuStart + offset, + hitsGpuVisible + cpuStart + offset, + size ); + })); + } + + for (auto& f : futures) { + f.wait(); + } + } + + // 3. Synchronize stream (the caller can do this, but if we have Orochi, we can't easily include it here without Orochi headers) + if (gpuCount > 0 && stream) + { + oroStreamSynchronize(reinterpret_cast(stream)); + } +} + +} // namespace hiprt diff --git a/hiprt/hiprt_types.h b/hiprt/hiprt_types.h index 2e631c3..cb7305b 100644 --- a/hiprt/hiprt_types.h +++ b/hiprt/hiprt_types.h @@ -309,12 +309,14 @@ struct hiprtFuncNameSet /** \brief Device type. * */ -enum hiprtDeviceType +enum hiprtDeviceType : uint32_t { /*!< AMD device */ - hiprtDeviceAMD, + hiprtDeviceAMD = 1 << 0, /*!< Nvidia device */ - hiprtDeviceNVIDIA, + hiprtDeviceNVIDIA = 1 << 1, + /*!< CPU device */ + hiprtDeviceCPU = 1 << 2, }; /** \brief Context creation input. @@ -328,6 +330,8 @@ struct hiprtContextCreationInput hiprtApiDevice device; /*!< HIPRT API device type */ hiprtDeviceType deviceType; + /*!< Number of CPU threads (0 = use all available hardware threads) */ + uint32_t numCpuThreads = 0; }; /** \brief Various flags controlling scene/geometry build process. diff --git a/hiprt/impl/Context.h b/hiprt/impl/Context.h index c078dbd..5cbc684 100644 --- a/hiprt/impl/Context.h +++ b/hiprt/impl/Context.h @@ -30,9 +30,11 @@ #include #include +#include + namespace hiprt { -class Context +class Context : public ContextBase { public: Context( const hiprtContextCreationInput& input ); @@ -99,8 +101,8 @@ class Context void saveScene( hiprtScene inScene, const std::string& filename ); hiprtScene loadScene( const std::string& filename ); - void exportGeometryAabb( hiprtGeometry inGeometry, float3& outAabbMin, float3& outAabbMax ); - void exportSceneAabb( hiprtScene inScene, float3& outAabbMin, float3& outAabbMax ); + virtual void exportGeometryAabb( hiprtGeometry inGeometry, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override; + virtual void exportSceneAabb( hiprtScene inScene, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override; void buildKernels( const std::vector& funcNames, @@ -148,6 +150,11 @@ class Context m_logger.print( hiprtLogLevelError, args... ); } + virtual void logError( const char* msg ) const override + { + m_logger.print( hiprtLogLevelError, msg ); + } + uint32_t getSMCount() const; uint32_t getMaxBlockSize() const; uint32_t getMaxGridSize() const; @@ -166,6 +173,9 @@ class Context size_t getBoxNodeSize() const; size_t getInstanceNodeSize() const; + virtual CpuGeometryData* getCpuGeom( hiprtGeometry geom ) override { return nullptr; } + virtual CpuSceneData* getCpuScene( hiprtScene scene ) override { return nullptr; } + private: oroDevice m_device; oroCtx m_ctxt; diff --git a/hiprt/impl/ContextBase.h b/hiprt/impl/ContextBase.h new file mode 100644 index 0000000..a6fe502 --- /dev/null +++ b/hiprt/impl/ContextBase.h @@ -0,0 +1,116 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace hiprt +{ + +struct CpuGeometryData; +struct CpuSceneData; + +class ContextBase +{ + public: + virtual ~ContextBase() = default; + + virtual std::vector createGeometries( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) = 0; + virtual void destroyGeometries( const std::vector& geometries ) = 0; + + virtual void buildGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) = 0; + + virtual void updateGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) = 0; + + virtual size_t getGeometriesBuildTempBufferSize( + const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) = 0; + + virtual std::vector compactGeometries( const std::vector& geometries, oroStream stream ) = 0; + + virtual std::vector createScenes( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) = 0; + virtual void destroyScenes( const std::vector& scenes ) = 0; + + virtual void buildScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) = 0; + + virtual void updateScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) = 0; + + virtual size_t getScenesBuildTempBufferSize( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) = 0; + + virtual std::vector compactScenes( const std::vector& scenes, oroStream stream ) = 0; + + virtual hiprtFuncTable createFuncTable( uint32_t numGeomTypes, uint32_t numRayTypes ) = 0; + virtual void setFuncTable( hiprtFuncTable funcTable, uint32_t geomType, uint32_t rayType, hiprtFuncDataSet set ) = 0; + virtual void destroyFuncTable( hiprtFuncTable funcTable ) = 0; + + virtual void createGlobalStackBuffer( const hiprtGlobalStackBufferInput& input, hiprtGlobalStackBuffer& stackBufferOut ) = 0; + virtual void destroyGlobalStackBuffer( hiprtGlobalStackBuffer stackBuffer ) = 0; + + virtual void saveGeometry( hiprtGeometry inGeometry, const std::string& filename ) = 0; + virtual hiprtGeometry loadGeometry( const std::string& filename ) = 0; + + virtual void saveScene( hiprtScene inScene, const std::string& filename ) = 0; + virtual hiprtScene loadScene( const std::string& filename ) = 0; + virtual void exportGeometryAabb( hiprtGeometry inGeometry, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) = 0; + virtual void exportSceneAabb( hiprtScene inScene, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) = 0; + + virtual void buildKernels( + const std::vector& funcNames, + const std::string& src, + const std::filesystem::path& moduleName, + std::vector& headers, + std::vector& includeNames, + std::vector& options, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + oroModule& module, + bool cache ) = 0; + + virtual void buildKernelsFromBitcode( + const std::vector& funcNames, + const std::filesystem::path& moduleName, + const std::string_view bitcodeBinary, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + bool cache ) = 0; + + virtual void setCacheDir( const std::filesystem::path& path ) = 0; + virtual void setLogLevel( hiprtLogLevel level ) = 0; + + virtual void logError( const char* msg ) const + { + fprintf( stderr, "HIPRT Error: %s\n", msg ); + } + + // CPU-specific getters (needed for Hybrid and Host Traversal) + virtual CpuGeometryData* getCpuGeom( hiprtGeometry geom ) = 0; + virtual CpuSceneData* getCpuScene( hiprtScene scene ) = 0; +}; + +} // namespace hiprt diff --git a/hiprt/impl/CpuContext.h b/hiprt/impl/CpuContext.h new file mode 100644 index 0000000..99c5aa4 --- /dev/null +++ b/hiprt/impl/CpuContext.h @@ -0,0 +1,413 @@ +#pragma once + +#include +#include +#include +#include +#include + +namespace hiprt +{ + +inline void aabbBoundsFunc(const struct RTCBoundsFunctionArguments* args) { + const hiprtAABBListPrimitive* list = (const hiprtAABBListPrimitive*)args->geometryUserPtr; + const char* ptr = (const char*)list->aabbs + args->primID * list->aabbStride; + const float* minP = (const float*)ptr; + const float* maxP = (const float*)(ptr + (list->aabbStride / 2)); + args->bounds_o->lower_x = minP[0]; + args->bounds_o->lower_y = minP[1]; + args->bounds_o->lower_z = minP[2]; + args->bounds_o->upper_x = maxP[0]; + args->bounds_o->upper_y = maxP[1]; + args->bounds_o->upper_z = maxP[2]; +} + +inline void aabbIntersectFunc(const struct RTCIntersectFunctionNArguments* args) { + int* valid = args->valid; + if (!valid[0]) return; + + const hiprtAABBListPrimitive* list = (const hiprtAABBListPrimitive*)args->geometryUserPtr; + const char* ptr = (const char*)list->aabbs + args->primID * list->aabbStride; + const float* minP = (const float*)ptr; + const float* maxP = (const float*)(ptr + (list->aabbStride / 2)); + + RTCRayHit* rayhit = (RTCRayHit*)args->rayhit; + RTCRay* ray = &rayhit->ray; + + float tmin = (minP[0] - ray->org_x) / ray->dir_x; + float tmax = (maxP[0] - ray->org_x) / ray->dir_x; + if (tmin > tmax) std::swap(tmin, tmax); + + float tymin = (minP[1] - ray->org_y) / ray->dir_y; + float tymax = (maxP[1] - ray->org_y) / ray->dir_y; + if (tymin > tymax) std::swap(tymin, tymax); + + if ((tmin > tymax) || (tymin > tmax)) return; + if (tymin > tmin) tmin = tymin; + if (tymax < tmax) tmax = tymax; + + float tzmin = (minP[2] - ray->org_z) / ray->dir_z; + float tzmax = (maxP[2] - ray->org_z) / ray->dir_z; + if (tzmin > tzmax) std::swap(tzmin, tzmax); + + if ((tmin > tzmax) || (tzmin > tmax)) return; + if (tzmin > tmin) tmin = tzmin; + if (tzmax < tmax) tmax = tzmax; + + if (tmin >= ray->tnear && tmin <= ray->tfar) { + ray->tfar = tmin; + rayhit->hit.geomID = args->geomID; + rayhit->hit.primID = args->primID; + rayhit->hit.Ng_x = 1.0f; rayhit->hit.Ng_y = 0.0f; rayhit->hit.Ng_z = 0.0f; + } +} + +struct CpuGeometryData +{ + RTCDevice rtcDevice; + RTCScene rtcScene; + hiprtAABBListPrimitive* aabbListCopy = nullptr; +}; + +struct CpuSceneData +{ + RTCDevice rtcDevice; + RTCScene rtcScene; +}; + +class CpuContext : public ContextBase +{ + private: + RTCDevice m_rtcDevice; + + public: + CpuContext( const hiprtContextCreationInput& input ) + { + std::string config = ""; + if (input.numCpuThreads > 0) { + config += "threads=" + std::to_string(input.numCpuThreads); + } + m_rtcDevice = rtcNewDevice(config.c_str()); + if (!m_rtcDevice) + { + throw std::runtime_error("Failed to initialize Embree device"); + } + } + + virtual ~CpuContext() + { + if (m_rtcDevice) { + rtcReleaseDevice(m_rtcDevice); + } + } + + virtual std::vector createGeometries( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + std::vector out; + out.reserve( buildInputs.size() ); + + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = new CpuGeometryData(); + data->rtcDevice = m_rtcDevice; + data->rtcScene = rtcNewScene( m_rtcDevice ); + out.push_back( reinterpret_cast( data ) ); + } + + return out; + } + + virtual void destroyGeometries( const std::vector& geometries ) override + { + for ( auto geom : geometries ) + { + auto* data = reinterpret_cast( geom ); + if (data) { + if (data->rtcScene) rtcReleaseScene(data->rtcScene); + if (data->aabbListCopy) delete data->aabbListCopy; + delete data; + } + } + } + + virtual void buildGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = reinterpret_cast( buffers[i] ); + const auto& input = buildInputs[i]; + + if ( input.type == hiprtPrimitiveTypeTriangleMesh ) + { + const auto& mesh = input.primitive.triangleMesh; + + RTCGeometry geom = rtcNewGeometry( m_rtcDevice, RTC_GEOMETRY_TYPE_TRIANGLE ); + rtcSetSharedGeometryBuffer( + geom, + RTC_BUFFER_TYPE_VERTEX, + 0, + RTC_FORMAT_FLOAT3, + mesh.vertices, + 0, + mesh.vertexStride, + mesh.vertexCount ); + + if (mesh.triangleIndices) { + rtcSetSharedGeometryBuffer( + geom, + RTC_BUFFER_TYPE_INDEX, + 0, + RTC_FORMAT_UINT3, + mesh.triangleIndices, + 0, + mesh.triangleStride, + mesh.triangleCount ); + } + + rtcCommitGeometry( geom ); + rtcAttachGeometry( data->rtcScene, geom ); + rtcReleaseGeometry( geom ); + } + else if ( input.type == hiprtPrimitiveTypeAABBList ) + { + const auto& aabbList = input.primitive.aabbList; + data->aabbListCopy = new hiprtAABBListPrimitive(aabbList); + + RTCGeometry geom = rtcNewGeometry( m_rtcDevice, RTC_GEOMETRY_TYPE_USER ); + rtcSetGeometryUserPrimitiveCount(geom, aabbList.aabbCount); + rtcSetGeometryUserData(geom, data->aabbListCopy); + rtcSetGeometryBoundsFunction(geom, aabbBoundsFunc, nullptr); + rtcSetGeometryIntersectFunction(geom, aabbIntersectFunc); + + rtcCommitGeometry(geom); + rtcAttachGeometry(data->rtcScene, geom); + rtcReleaseGeometry(geom); + } + + rtcCommitScene( data->rtcScene ); + } + } + + virtual void updateGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = reinterpret_cast( buffers[i] ); + if (data) { + if (data->rtcScene) { + rtcReleaseScene(data->rtcScene); + data->rtcScene = rtcNewScene(m_rtcDevice); + } + if (data->aabbListCopy) { + delete data->aabbListCopy; + data->aabbListCopy = nullptr; + } + } + } + buildGeometries(buildInputs, buildOptions, temporaryBuffer, stream, buffers); + } + + virtual size_t getGeometriesBuildTempBufferSize( + const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + return 0; + } + + virtual std::vector compactGeometries( const std::vector& geometries, oroStream stream ) override + { + return geometries; + } + + virtual std::vector createScenes( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + std::vector out; + out.reserve( buildInputs.size() ); + + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = new CpuSceneData(); + data->rtcDevice = m_rtcDevice; + data->rtcScene = rtcNewScene( m_rtcDevice ); + out.push_back( reinterpret_cast( data ) ); + } + + return out; + } + + virtual void destroyScenes( const std::vector& scenes ) override + { + for ( auto scene : scenes ) + { + auto* data = reinterpret_cast( scene ); + if (data) { + if (data->rtcScene) rtcReleaseScene(data->rtcScene); + delete data; + } + } + } + + virtual void buildScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = reinterpret_cast( buffers[i] ); + const auto& input = buildInputs[i]; + + if (input.instances != nullptr) { + hiprtInstance* instances = reinterpret_cast(input.instances); + for (uint32_t j = 0; j < input.instanceCount; ++j) { + if (instances[j].type == hiprtInstanceTypeGeometry) { + CpuGeometryData* geomData = reinterpret_cast(instances[j].geometry); + if (geomData) { + RTCGeometry instance = rtcNewGeometry(m_rtcDevice, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(instance, geomData->rtcScene); + rtcCommitGeometry(instance); + rtcAttachGeometry(data->rtcScene, instance); + rtcReleaseGeometry(instance); + } + } else if (instances[j].type == hiprtInstanceTypeScene) { + CpuSceneData* sceneData = reinterpret_cast(instances[j].scene); + if (sceneData) { + RTCGeometry instance = rtcNewGeometry(m_rtcDevice, RTC_GEOMETRY_TYPE_INSTANCE); + rtcSetGeometryInstancedScene(instance, sceneData->rtcScene); + rtcCommitGeometry(instance); + rtcAttachGeometry(data->rtcScene, instance); + rtcReleaseGeometry(instance); + } + } + } + } + + rtcCommitScene( data->rtcScene ); + } + } + + virtual void updateScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + for ( size_t i = 0; i < buildInputs.size(); ++i ) + { + auto* data = reinterpret_cast( buffers[i] ); + if (data) { + if (data->rtcScene) { + rtcReleaseScene(data->rtcScene); + data->rtcScene = rtcNewScene(m_rtcDevice); + } + } + } + buildScenes(buildInputs, buildOptions, temporaryBuffer, stream, buffers); + } + + virtual size_t getScenesBuildTempBufferSize( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + return 0; + } + + virtual std::vector compactScenes( const std::vector& scenes, oroStream stream ) override + { + return scenes; + } + + virtual hiprtFuncTable createFuncTable( uint32_t numGeomTypes, uint32_t numRayTypes ) override { return nullptr; } + virtual void setFuncTable( hiprtFuncTable funcTable, uint32_t geomType, uint32_t rayType, hiprtFuncDataSet set ) override {} + virtual void destroyFuncTable( hiprtFuncTable funcTable ) override {} + virtual void createGlobalStackBuffer( const hiprtGlobalStackBufferInput& input, hiprtGlobalStackBuffer& stackBufferOut ) override {} + virtual void destroyGlobalStackBuffer( hiprtGlobalStackBuffer stackBuffer ) override {} + virtual void saveGeometry( hiprtGeometry inGeometry, const std::string& filename ) override { + throw std::runtime_error("CpuContext::saveGeometry not implemented"); + } + virtual hiprtGeometry loadGeometry( const std::string& filename ) override { + throw std::runtime_error("CpuContext::loadGeometry not implemented"); + return nullptr; + } + virtual void saveScene( hiprtScene inScene, const std::string& filename ) override { + throw std::runtime_error("CpuContext::saveScene not implemented"); + } + virtual hiprtScene loadScene( const std::string& filename ) override { + throw std::runtime_error("CpuContext::loadScene not implemented"); + return nullptr; + } + virtual void exportGeometryAabb( hiprtGeometry inGeometry, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override + { + CpuGeometryData* data = reinterpret_cast(inGeometry); + if (data && data->rtcScene) { + RTCBounds bounds; + rtcGetSceneBounds(data->rtcScene, &bounds); + outAabbMin = {bounds.lower_x, bounds.lower_y, bounds.lower_z}; + outAabbMax = {bounds.upper_x, bounds.upper_y, bounds.upper_z}; + } else { + throw std::runtime_error("Invalid CPU geometry for AABB export"); + } + } + + virtual void exportSceneAabb( hiprtScene inScene, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override + { + CpuSceneData* data = reinterpret_cast(inScene); + if (data && data->rtcScene) { + RTCBounds bounds; + rtcGetSceneBounds(data->rtcScene, &bounds); + outAabbMin = {bounds.lower_x, bounds.lower_y, bounds.lower_z}; + outAabbMax = {bounds.upper_x, bounds.upper_y, bounds.upper_z}; + } else { + throw std::runtime_error("Invalid CPU scene for AABB export"); + } + } + + virtual void buildKernels( + const std::vector& funcNames, + const std::string& src, + const std::filesystem::path& moduleName, + std::vector& headers, + std::vector& includeNames, + std::vector& options, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + oroModule& module, + bool cache ) override {} + + virtual void buildKernelsFromBitcode( + const std::vector& funcNames, + const std::filesystem::path& moduleName, + const std::string_view bitcodeBinary, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + bool cache ) override {} + + virtual void setCacheDir( const std::filesystem::path& path ) override {} + virtual void setLogLevel( hiprtLogLevel level ) override {} + + virtual CpuGeometryData* getCpuGeom( hiprtGeometry geom ) override + { + return reinterpret_cast(geom); + } + + virtual CpuSceneData* getCpuScene( hiprtScene scene ) override + { + return reinterpret_cast(scene); + } +}; + +} // namespace hiprt diff --git a/hiprt/impl/HybridContext.h b/hiprt/impl/HybridContext.h new file mode 100644 index 0000000..48c4634 --- /dev/null +++ b/hiprt/impl/HybridContext.h @@ -0,0 +1,293 @@ +#pragma once + +#include +#include +#include +#include +#include +#include + +namespace hiprt +{ + +class HybridContext : public ContextBase +{ + public: + Context* m_gpu = nullptr; + CpuContext* m_cpu = nullptr; + + std::unordered_map m_cpuGeomMap; + std::unordered_map m_cpuSceneMap; + + public: + HybridContext( const hiprtContextCreationInput& input ) + { + hiprtContextCreationInput gpuInput = input; + if (input.deviceType & hiprtDeviceAMD) gpuInput.deviceType = hiprtDeviceAMD; + else if (input.deviceType & hiprtDeviceNVIDIA) gpuInput.deviceType = hiprtDeviceNVIDIA; + + m_gpu = new Context(gpuInput); + try { + m_cpu = new CpuContext(input); + } catch (...) { + delete m_gpu; + throw; + } + } + + virtual ~HybridContext() + { + delete m_gpu; + delete m_cpu; + } + + virtual std::vector createGeometries( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + auto gpuGeoms = m_gpu->createGeometries( buildInputs, buildOptions ); + auto cpuGeoms = m_cpu->createGeometries( buildInputs, buildOptions ); + + for ( size_t i = 0; i < gpuGeoms.size(); ++i ) + { + m_cpuGeomMap[reinterpret_cast( gpuGeoms[i] )] = reinterpret_cast( cpuGeoms[i] ); + } + + return gpuGeoms; + } + + virtual void destroyGeometries( const std::vector& geometries ) override + { + std::vector cpuGeometries; + for (auto g : geometries) { + cpuGeometries.push_back(reinterpret_cast(m_cpuGeomMap[reinterpret_cast(g)])); + m_cpuGeomMap.erase(reinterpret_cast(g)); + } + + m_gpu->destroyGeometries( geometries ); + m_cpu->destroyGeometries( cpuGeometries ); + } + + virtual void buildGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + std::vector cpuBuffers; + for (auto b : buffers) { + cpuBuffers.push_back(reinterpret_cast(m_cpuGeomMap[reinterpret_cast(b)])); + } + + auto cpuFuture = std::async(std::launch::async, [this, &buildInputs, buildOptions, &cpuBuffers]() { + m_cpu->buildGeometries( buildInputs, buildOptions, nullptr, nullptr, cpuBuffers ); + }); + + m_gpu->buildGeometries( buildInputs, buildOptions, temporaryBuffer, stream, buffers ); + cpuFuture.wait(); + } + + virtual void updateGeometries( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + std::vector cpuBuffers; + for (auto b : buffers) { + cpuBuffers.push_back(reinterpret_cast(m_cpuGeomMap[reinterpret_cast(b)])); + } + + auto cpuFuture = std::async(std::launch::async, [this, &buildInputs, buildOptions, &cpuBuffers]() { + m_cpu->updateGeometries( buildInputs, buildOptions, nullptr, nullptr, cpuBuffers ); + }); + + m_gpu->updateGeometries( buildInputs, buildOptions, temporaryBuffer, stream, buffers ); + cpuFuture.wait(); + } + + virtual size_t getGeometriesBuildTempBufferSize( + const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + return m_gpu->getGeometriesBuildTempBufferSize(buildInputs, buildOptions); + } + + virtual std::vector compactGeometries( const std::vector& geometries, oroStream stream ) override + { + throw std::runtime_error("HybridContext::compactGeometries not implemented"); + } + + virtual std::vector createScenes( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + auto gpuScenes = m_gpu->createScenes( buildInputs, buildOptions ); + auto cpuScenes = m_cpu->createScenes( buildInputs, buildOptions ); + + for ( size_t i = 0; i < gpuScenes.size(); ++i ) + { + m_cpuSceneMap[reinterpret_cast( gpuScenes[i] )] = reinterpret_cast( cpuScenes[i] ); + } + + return gpuScenes; + } + + virtual void destroyScenes( const std::vector& scenes ) override + { + std::vector cpuScenes; + for (auto s : scenes) { + cpuScenes.push_back(reinterpret_cast(m_cpuSceneMap[reinterpret_cast(s)])); + m_cpuSceneMap.erase(reinterpret_cast(s)); + } + + m_gpu->destroyScenes( scenes ); + m_cpu->destroyScenes( cpuScenes ); + } + + virtual void buildScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + std::vector cpuBuffers; + for (auto b : buffers) { + cpuBuffers.push_back(reinterpret_cast(m_cpuSceneMap[reinterpret_cast(b)])); + } + + std::vector cpuBuildInputs = buildInputs; + std::vector> cpuInstancesArray(buildInputs.size()); + + for (size_t i = 0; i < buildInputs.size(); ++i) { + if (buildInputs[i].instances != nullptr) { + cpuInstancesArray[i].resize(buildInputs[i].instanceCount); + oroMemcpyDtoH(cpuInstancesArray[i].data(), reinterpret_cast(buildInputs[i].instances), buildInputs[i].instanceCount * sizeof(hiprtInstance)); + for (uint32_t j = 0; j < buildInputs[i].instanceCount; ++j) { + if (cpuInstancesArray[i][j].type == hiprtInstanceTypeGeometry) { + cpuInstancesArray[i][j].geometry = reinterpret_cast(m_cpuGeomMap[reinterpret_cast(cpuInstancesArray[i][j].geometry)]); + } else if (cpuInstancesArray[i][j].type == hiprtInstanceTypeScene) { + cpuInstancesArray[i][j].scene = reinterpret_cast(m_cpuSceneMap[reinterpret_cast(cpuInstancesArray[i][j].scene)]); + } + } + cpuBuildInputs[i].instances = reinterpret_cast(cpuInstancesArray[i].data()); + } + } + + auto cpuFuture = std::async( std::launch::async, [&]() { + m_cpu->buildScenes( cpuBuildInputs, buildOptions, nullptr, nullptr, cpuBuffers ); + }); + + m_gpu->buildScenes( buildInputs, buildOptions, temporaryBuffer, stream, buffers ); + cpuFuture.wait(); + } + + virtual void updateScenes( + const std::vector& buildInputs, + const hiprtBuildOptions buildOptions, + hiprtDevicePtr temporaryBuffer, + oroStream stream, + std::vector& buffers ) override + { + std::vector cpuBuffers; + for (auto b : buffers) { + cpuBuffers.push_back(reinterpret_cast(m_cpuSceneMap[reinterpret_cast(b)])); + } + + std::vector cpuBuildInputs = buildInputs; + std::vector> cpuInstancesArray(buildInputs.size()); + + for (size_t i = 0; i < buildInputs.size(); ++i) { + if (buildInputs[i].instances != nullptr) { + cpuInstancesArray[i].resize(buildInputs[i].instanceCount); + oroMemcpyDtoH(cpuInstancesArray[i].data(), reinterpret_cast(buildInputs[i].instances), buildInputs[i].instanceCount * sizeof(hiprtInstance)); + for (uint32_t j = 0; j < buildInputs[i].instanceCount; ++j) { + if (cpuInstancesArray[i][j].type == hiprtInstanceTypeGeometry) { + cpuInstancesArray[i][j].geometry = reinterpret_cast(m_cpuGeomMap[reinterpret_cast(cpuInstancesArray[i][j].geometry)]); + } else if (cpuInstancesArray[i][j].type == hiprtInstanceTypeScene) { + cpuInstancesArray[i][j].scene = reinterpret_cast(m_cpuSceneMap[reinterpret_cast(cpuInstancesArray[i][j].scene)]); + } + } + cpuBuildInputs[i].instances = reinterpret_cast(cpuInstancesArray[i].data()); + } + } + + auto cpuFuture = std::async(std::launch::async, [&]() { + m_cpu->updateScenes( cpuBuildInputs, buildOptions, nullptr, nullptr, cpuBuffers ); + }); + + m_gpu->updateScenes( buildInputs, buildOptions, temporaryBuffer, stream, buffers ); + cpuFuture.wait(); + } + + virtual size_t getScenesBuildTempBufferSize( const std::vector& buildInputs, const hiprtBuildOptions buildOptions ) override + { + return m_gpu->getScenesBuildTempBufferSize(buildInputs, buildOptions); + } + + virtual std::vector compactScenes( const std::vector& scenes, oroStream stream ) override + { + throw std::runtime_error("HybridContext::compactScenes not implemented"); + } + + virtual hiprtFuncTable createFuncTable( uint32_t numGeomTypes, uint32_t numRayTypes ) override { return m_gpu->createFuncTable(numGeomTypes, numRayTypes); } + virtual void setFuncTable( hiprtFuncTable funcTable, uint32_t geomType, uint32_t rayType, hiprtFuncDataSet set ) override { m_gpu->setFuncTable(funcTable, geomType, rayType, set); } + virtual void destroyFuncTable( hiprtFuncTable funcTable ) override { m_gpu->destroyFuncTable(funcTable); } + virtual void createGlobalStackBuffer( const hiprtGlobalStackBufferInput& input, hiprtGlobalStackBuffer& stackBufferOut ) override { m_gpu->createGlobalStackBuffer(input, stackBufferOut); } + virtual void destroyGlobalStackBuffer( hiprtGlobalStackBuffer stackBuffer ) override { m_gpu->destroyGlobalStackBuffer(stackBuffer); } + + virtual void saveGeometry( hiprtGeometry inGeometry, const std::string& filename ) override { throw std::runtime_error("HybridContext::saveGeometry not implemented"); } + virtual hiprtGeometry loadGeometry( const std::string& filename ) override { throw std::runtime_error("HybridContext::loadGeometry not implemented"); return nullptr; } + virtual void saveScene( hiprtScene inScene, const std::string& filename ) override { throw std::runtime_error("HybridContext::saveScene not implemented"); } + virtual hiprtScene loadScene( const std::string& filename ) override { throw std::runtime_error("HybridContext::loadScene not implemented"); return nullptr; } + + virtual void exportGeometryAabb( hiprtGeometry inGeometry, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override { m_gpu->exportGeometryAabb(inGeometry, outAabbMin, outAabbMax); } + virtual void exportSceneAabb( hiprtScene inScene, hiprtFloat3& outAabbMin, hiprtFloat3& outAabbMax ) override { m_gpu->exportSceneAabb(inScene, outAabbMin, outAabbMax); } + + virtual void buildKernels( + const std::vector& funcNames, + const std::string& src, + const std::filesystem::path& moduleName, + std::vector& headers, + std::vector& includeNames, + std::vector& options, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + oroModule& module, + bool cache ) override + { + m_gpu->buildKernels(funcNames, src, moduleName, headers, includeNames, options, numGeomTypes, numRayTypes, funcNameSets, functions, module, cache); + } + + virtual void buildKernelsFromBitcode( + const std::vector& funcNames, + const std::filesystem::path& moduleName, + const std::string_view bitcodeBinary, + uint32_t numGeomTypes, + uint32_t numRayTypes, + const std::vector& funcNameSets, + std::vector& functions, + bool cache ) override + { + m_gpu->buildKernelsFromBitcode(funcNames, moduleName, bitcodeBinary, numGeomTypes, numRayTypes, funcNameSets, functions, cache); + } + + virtual void setCacheDir( const std::filesystem::path& path ) override { m_gpu->setCacheDir(path); } + virtual void setLogLevel( hiprtLogLevel level ) override { m_gpu->setLogLevel(level); } + + virtual CpuGeometryData* getCpuGeom( hiprtGeometry geom ) override + { + auto it = m_cpuGeomMap.find(reinterpret_cast(geom)); + if (it != m_cpuGeomMap.end()) return it->second; + return nullptr; + } + + virtual CpuSceneData* getCpuScene( hiprtScene scene ) override + { + auto it = m_cpuSceneMap.find(reinterpret_cast(scene)); + if (it != m_cpuSceneMap.end()) return it->second; + return nullptr; + } +}; + +} // namespace hiprt diff --git a/hiprt/impl/hiprt.cpp b/hiprt/impl/hiprt.cpp index 7059b41..3fc1c78 100644 --- a/hiprt/impl/hiprt.cpp +++ b/hiprt/impl/hiprt.cpp @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -33,13 +35,41 @@ using namespace hiprt; hiprtError hiprtCreateContext( uint32_t hiprtApiVersion, const hiprtContextCreationInput& input, hiprtContext& contextOut ) { - oroInitialize( ( input.deviceType == hiprtDeviceAMD ) ? ORO_API_HIP : ORO_API_CUDA, 0, g_hip_paths, g_hiprtc_paths ); if ( hiprtApiVersion != HIPRT_API_VERSION ) return hiprtErrorInvalidApiVersion; try { - Context* ctxt = new Context( input ); - contextOut = reinterpret_cast( ctxt ); + ContextBase* ctxt = nullptr; + + if ( input.deviceType == hiprtDeviceCPU ) + { + ctxt = new CpuContext( input ); + } + else if ( input.deviceType & hiprtDeviceCPU ) + { + int err = oroInitialize( ( input.deviceType & hiprtDeviceAMD ) ? ORO_API_HIP : ORO_API_CUDA, 0, g_hip_paths, g_hiprtc_paths ); + if (err == 0 && oroInit(0) == oroSuccess) { // oroSuccess + try { + ctxt = new HybridContext( input ); + } catch (const std::exception& e) { + std::cerr << "GPU initialization failed during HybridContext creation (" << e.what() << "), falling back to CPU." << std::endl; + ctxt = new CpuContext( input ); + } + } else { + ctxt = new CpuContext( input ); + } + } + else + { + int err = oroInitialize( ( input.deviceType == hiprtDeviceAMD ) ? ORO_API_HIP : ORO_API_CUDA, 0, g_hip_paths, g_hiprtc_paths ); + if (err == 0 && oroInit(0) == oroSuccess) { + ctxt = new Context( input ); + } else { + throw std::runtime_error("GPU initialization failed and no CPU fallback requested."); + } + } + + contextOut = reinterpret_cast( ctxt ); } catch ( std::exception& e ) { @@ -53,7 +83,7 @@ hiprtError hiprtCreateContext( uint32_t hiprtApiVersion, const hiprtContextCreat hiprtError hiprtDestroyContext( hiprtContext context ) { if ( !context ) return hiprtErrorInvalidParameter; - delete reinterpret_cast( context ); + delete reinterpret_cast( context ); return hiprtSuccess; } @@ -88,13 +118,13 @@ hiprtError hiprtCreateGeometries( try { std::vector geometries = - reinterpret_cast( context )->createGeometries( buildInputs, buildOptions ); + reinterpret_cast( context )->createGeometries( buildInputs, buildOptions ); for ( uint32_t i = 0; i < numGeometries; ++i ) *geometriesOut[i] = geometries[i]; } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -119,11 +149,11 @@ hiprtError hiprtDestroyGeometries( hiprtContext context, uint32_t numGeometries, try { - reinterpret_cast( context )->destroyGeometries( geometries ); + reinterpret_cast( context )->destroyGeometries( geometries ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -169,12 +199,12 @@ hiprtError hiprtBuildGeometries( switch ( buildOperation ) { case hiprtBuildOperationBuild: { - reinterpret_cast( context )->buildGeometries( + reinterpret_cast( context )->buildGeometries( buildInputs, buildOptions, temporaryBuffer, reinterpret_cast( stream ), buffers ); break; } case hiprtBuildOperationUpdate: { - reinterpret_cast( context )->updateGeometries( + reinterpret_cast( context )->updateGeometries( buildInputs, buildOptions, temporaryBuffer, reinterpret_cast( stream ), buffers ); break; } @@ -182,7 +212,7 @@ hiprtError hiprtBuildGeometries( } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -211,11 +241,11 @@ hiprtError hiprtGetGeometriesBuildTemporaryBufferSize( try { - sizeOut = reinterpret_cast( context )->getGeometriesBuildTempBufferSize( buildInputs, buildOptions ); + sizeOut = reinterpret_cast( context )->getGeometriesBuildTempBufferSize( buildInputs, buildOptions ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -250,13 +280,13 @@ hiprtError hiprtCompactGeometries( try { std::vector compactedGeometries = - reinterpret_cast( context )->compactGeometries( geometries, reinterpret_cast( stream ) ); + reinterpret_cast( context )->compactGeometries( geometries, reinterpret_cast( stream ) ); for ( uint32_t i = 0; i < numGeometries; ++i ) *geometriesOut[i] = compactedGeometries[i]; } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -288,13 +318,13 @@ hiprtError hiprtCreateScenes( try { - std::vector scenes = reinterpret_cast( context )->createScenes( buildInputs, buildOptions ); + std::vector scenes = reinterpret_cast( context )->createScenes( buildInputs, buildOptions ); for ( uint32_t i = 0; i < numScenes; ++i ) *scenesOut[i] = scenes[i]; } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -316,11 +346,11 @@ hiprtError hiprtDestroyScenes( hiprtContext context, uint32_t numScenes, hiprtSc try { - reinterpret_cast( context )->destroyScenes( scenes ); + reinterpret_cast( context )->destroyScenes( scenes ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -365,12 +395,12 @@ hiprtError hiprtBuildScenes( switch ( buildOperation ) { case hiprtBuildOperationBuild: { - reinterpret_cast( context )->buildScenes( + reinterpret_cast( context )->buildScenes( buildInputs, buildOptions, temporaryBuffer, reinterpret_cast( stream ), buffers ); break; } case hiprtBuildOperationUpdate: { - reinterpret_cast( context )->updateScenes( + reinterpret_cast( context )->updateScenes( buildInputs, buildOptions, temporaryBuffer, reinterpret_cast( stream ), buffers ); break; } @@ -378,7 +408,7 @@ hiprtError hiprtBuildScenes( } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -407,11 +437,11 @@ hiprtError hiprtGetScenesBuildTemporaryBufferSize( try { - sizeOut = reinterpret_cast( context )->getScenesBuildTempBufferSize( buildInputs, buildOptions ); + sizeOut = reinterpret_cast( context )->getScenesBuildTempBufferSize( buildInputs, buildOptions ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -440,13 +470,13 @@ hiprtError hiprtCompactScenes( try { std::vector compactedScenes = - reinterpret_cast( context )->compactScenes( scenes, reinterpret_cast( stream ) ); + reinterpret_cast( context )->compactScenes( scenes, reinterpret_cast( stream ) ); for ( uint32_t i = 0; i < numScenes; ++i ) *scenesOut[i] = compactedScenes[i]; } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -458,11 +488,11 @@ hiprtCreateFuncTable( hiprtContext context, uint32_t numGeomTypes, uint32_t numR if ( !context ) return hiprtErrorInvalidParameter; try { - funcTableOut = reinterpret_cast( context )->createFuncTable( numGeomTypes, numRayTypes ); + funcTableOut = reinterpret_cast( context )->createFuncTable( numGeomTypes, numRayTypes ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -474,11 +504,11 @@ hiprtSetFuncTable( hiprtContext context, hiprtFuncTable funcTable, uint32_t geom if ( !context || !funcTable ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->setFuncTable( funcTable, geomType, rayType, set ); + reinterpret_cast( context )->setFuncTable( funcTable, geomType, rayType, set ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -489,11 +519,11 @@ hiprtError hiprtDestroyFuncTable( hiprtContext context, hiprtFuncTable funcTable if ( !context || !funcTable ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->destroyFuncTable( funcTable ); + reinterpret_cast( context )->destroyFuncTable( funcTable ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -505,11 +535,11 @@ hiprtError hiprtCreateGlobalStackBuffer( if ( !context ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->createGlobalStackBuffer( input, stackBufferOut ); + reinterpret_cast( context )->createGlobalStackBuffer( input, stackBufferOut ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -520,11 +550,11 @@ hiprtError hiprtDestroyGlobalStackBuffer( hiprtContext context, hiprtGlobalStack if ( !context ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->destroyGlobalStackBuffer( stackBuffer ); + reinterpret_cast( context )->destroyGlobalStackBuffer( stackBuffer ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -535,11 +565,11 @@ hiprtError hiprtSaveGeometry( hiprtContext context, hiprtGeometry geometry, cons if ( !context || !geometry || !filename ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->saveGeometry( geometry, filename ); + reinterpret_cast( context )->saveGeometry( geometry, filename ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -550,11 +580,11 @@ hiprtError hiprtLoadGeometry( hiprtContext context, hiprtGeometry& geometryOut, if ( !context || !filename ) return hiprtErrorInvalidParameter; try { - geometryOut = reinterpret_cast( context )->loadGeometry( filename ); + geometryOut = reinterpret_cast( context )->loadGeometry( filename ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -565,11 +595,11 @@ hiprtError hiprtSaveScene( hiprtContext context, hiprtScene scene, const char* f if ( !context || !scene || !filename ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->saveScene( scene, filename ); + reinterpret_cast( context )->saveScene( scene, filename ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -580,11 +610,11 @@ hiprtError hiprtLoadScene( hiprtContext context, hiprtScene& sceneOut, const cha if ( !context || !sceneOut || !filename ) return hiprtErrorInvalidParameter; try { - sceneOut = reinterpret_cast( context )->loadScene( filename ); + sceneOut = reinterpret_cast( context )->loadScene( filename ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -595,11 +625,11 @@ hiprtError hiprtExportGeometryAabb( hiprtContext context, hiprtGeometry geometry if ( !context || !geometry ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->exportGeometryAabb( geometry, aabbMinOut, aabbMaxOut ); + reinterpret_cast( context )->exportGeometryAabb( geometry, aabbMinOut, aabbMaxOut ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -610,11 +640,11 @@ hiprtError hiprtExportSceneAabb( hiprtContext context, hiprtScene scene, float3& if ( !context || !scene ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->exportSceneAabb( scene, aabbMinOut, aabbMaxOut ); + reinterpret_cast( context )->exportSceneAabb( scene, aabbMinOut, aabbMaxOut ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -670,7 +700,7 @@ hiprtError hiprtBuildTraceKernels( std::vector functions; oroModule module = nullptr; - reinterpret_cast( context )->buildKernels( + reinterpret_cast( context )->buildKernels( funcNames, src, moduleName, @@ -691,7 +721,7 @@ hiprtError hiprtBuildTraceKernels( } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -730,7 +760,7 @@ hiprtError hiprtBuildTraceKernelsFromBitcode( } std::string_view binary( bitcodeBinary, bitcodeBinarySize ); std::vector functions; - reinterpret_cast( context )->buildKernelsFromBitcode( + reinterpret_cast( context )->buildKernelsFromBitcode( funcNames, moduleName, binary, numGeomTypes, numRayTypes, funcNameSets, functions, cache ); for ( uint32_t i = 0; i < numFunctions; ++i ) @@ -738,7 +768,7 @@ hiprtError hiprtBuildTraceKernelsFromBitcode( } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } @@ -750,11 +780,11 @@ hiprtError hiprtSetCacheDirPath( hiprtContext context, const char* path ) if ( !context ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->setCacheDir( path ); + reinterpret_cast( context )->setCacheDir( path ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; @@ -765,11 +795,11 @@ hiprtError hiprtSetLogLevel( hiprtContext context, hiprtLogLevel level ) if ( !context ) return hiprtErrorInvalidParameter; try { - reinterpret_cast( context )->setLogLevel( level ); + reinterpret_cast( context )->setLogLevel( level ); } catch ( std::exception& e ) { - reinterpret_cast( context )->logError( e.what() ); + reinterpret_cast( context )->logError( e.what() ); return hiprtErrorInternal; } return hiprtSuccess; diff --git a/scripts/test_version.py b/scripts/test_version.py new file mode 100644 index 0000000..bde1728 Binary files /dev/null and b/scripts/test_version.py differ diff --git a/test/test_dlopen.cpp b/test/test_dlopen.cpp new file mode 100644 index 0000000..58b242f Binary files /dev/null and b/test/test_dlopen.cpp differ diff --git a/test/test_orochi.cpp b/test/test_orochi.cpp new file mode 100644 index 0000000..b2b83ec --- /dev/null +++ b/test/test_orochi.cpp @@ -0,0 +1,8 @@ +#include "contrib/Orochi/Orochi/Orochi.h" +#include + +int main() { + int oroErr = oroInitialize(ORO_API_AUTOMATIC, 0); + std::cout << "Orochi init: " << oroErr << std::endl; + return 0; +}