From a8cb7cf327d05d5afbf1d2704713f30f4fa77faf Mon Sep 17 00:00:00 2001
From: Jorge Ortega <jorge-ortega@outlook.com>
Date: Wed, 19 Mar 2025 18:45:28 -0700
Subject: [PATCH 1/3] Rework optix_stubs.c

The stubs were a copy of optix_stubs.h, but without `inline` so they end up in the binary when compiling them. This change instead includes optix_stubs.h and uses the preprocessor to erase `inline` in the header.
---
 crates/optix/build.rs      |   1 +
 crates/optix/optix_stubs.c | 603 +------------------------------------
 2 files changed, 13 insertions(+), 591 deletions(-)

diff --git a/crates/optix/build.rs b/crates/optix/build.rs
index c1783718..b52e0f0c 100644
--- a/crates/optix/build.rs
+++ b/crates/optix/build.rs
@@ -23,6 +23,7 @@ fn main() {
 
     bindgen_optix(&optix_include, &cuda_include);
 
+    println!("cargo:rerun-if-changed=optix_stubs.c");
     cc::Build::new()
         .file("./optix_stubs.c")
         .include(optix_include)
diff --git a/crates/optix/optix_stubs.c b/crates/optix/optix_stubs.c
index 3325d867..af44d0e2 100644
--- a/crates/optix/optix_stubs.c
+++ b/crates/optix/optix_stubs.c
@@ -1,37 +1,9 @@
-/*
- * Copyright (c) 2021 NVIDIA Corporation.  All rights reserved.
- *
- * Redistribution and use in source and binary forms, with or without
- * modification, are permitted provided that the following conditions
- * are met:
- *  * Redistributions of source code must retain the above copyright
- *    notice, this list of conditions and the following disclaimer.
- *  * Redistributions in binary form must reproduce the above copyright
- *    notice, this list of conditions and the following disclaimer in the
- *    documentation and/or other materials provided with the distribution.
- *  * Neither the name of NVIDIA CORPORATION nor the names of its
- *    contributors may be used to endorse or promote products derived
- *    from this software without specific prior written permission.
- *
- * THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS ``AS IS'' AND ANY
- * EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
- * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR
- * PURPOSE ARE DISCLAIMED.  IN NO EVENT SHALL THE COPYRIGHT OWNER OR
- * CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL,
- * EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO,
- * PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR
- * PROFITS; OR BUSINESS INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY
- * OF LIABILITY, WHETHER IN CONTRACT, STRICT LIABILITY, OR TORT
- * (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY OUT OF THE USE
- * OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF SUCH DAMAGE.
- */
-
-/// @file
-/// @author NVIDIA Corporation
-/// @brief  OptiX public API header
-
-#include "optix_function_table.h"
+// Optix uses a function table approach to load its api at runtime. The table is defined
+// by including optix_function_table_definition.h here.
+#include "optix_function_table_definition.h"
 
+// These are copied from optix_stubs.h so they do not get affected by the redefinition
+// of inline. See below.
 #ifdef _WIN32
 #ifndef WIN32_LEAN_AND_MEAN
 #define WIN32_LEAN_AND_MEAN 1
@@ -46,561 +18,10 @@
 #include <dlfcn.h>
 #endif
 
-#ifdef __cplusplus
-extern "C"
-{
-#endif
-
-// The function table needs to be defined in exactly one translation unit. This can be
-// achieved by including optix_function_table_definition.h in that translation unit.
-// extern OptixFunctionTable g_optixFunctionTable;
-#include "optix_function_table_definition.h"
-
-#ifdef _WIN32
-  static void *optixLoadWindowsDllFromName(const char *optixDllName)
-  {
-    void *handle = NULL;
-
-    // Get the size of the path first, then allocate
-    unsigned int size = GetSystemDirectoryA(NULL, 0);
-    if (size == 0)
-    {
-      // Couldn't get the system path size, so bail
-      return NULL;
-    }
-    size_t pathSize = size + 1 + strlen(optixDllName);
-    char *systemPath = (char *)malloc(pathSize);
-    if (systemPath == NULL)
-      return NULL;
-    if (GetSystemDirectoryA(systemPath, size) != size - 1)
-    {
-      // Something went wrong
-      free(systemPath);
-      return NULL;
-    }
-    strcat(systemPath, "\\");
-    strcat(systemPath, optixDllName);
-    handle = LoadLibraryA(systemPath);
-    free(systemPath);
-    if (handle)
-      return handle;
-
-    // If we didn't find it, go looking in the register store.  Since nvoptix.dll doesn't
-    // have its own registry entry, we are going to look for the opengl driver which lives
-    // next to nvoptix.dll.  0 (null) will be returned if any errors occured.
-
-    static const char *deviceInstanceIdentifiersGUID = "{4d36e968-e325-11ce-bfc1-08002be10318}";
-    const ULONG flags = CM_GETIDLIST_FILTER_CLASS | CM_GETIDLIST_FILTER_PRESENT;
-    ULONG deviceListSize = 0;
-    if (CM_Get_Device_ID_List_SizeA(&deviceListSize, deviceInstanceIdentifiersGUID, flags) != CR_SUCCESS)
-    {
-      return NULL;
-    }
-    char *deviceNames = (char *)malloc(deviceListSize);
-    if (deviceNames == NULL)
-      return NULL;
-    if (CM_Get_Device_ID_ListA(deviceInstanceIdentifiersGUID, deviceNames, deviceListSize, flags))
-    {
-      free(deviceNames);
-      return NULL;
-    }
-    DEVINST devID = 0;
-    char *dllPath = NULL;
-
-    // Continue to the next device if errors are encountered.
-    for (char *deviceName = deviceNames; *deviceName; deviceName += strlen(deviceName) + 1)
-    {
-      if (CM_Locate_DevNodeA(&devID, deviceName, CM_LOCATE_DEVNODE_NORMAL) != CR_SUCCESS)
-      {
-        continue;
-      }
-      HKEY regKey = 0;
-      if (CM_Open_DevNode_Key(devID, KEY_QUERY_VALUE, 0, RegDisposition_OpenExisting, &regKey, CM_REGISTRY_SOFTWARE) != CR_SUCCESS)
-      {
-        continue;
-      }
-      const char *valueName = "OpenGLDriverName";
-      DWORD valueSize = 0;
-      LSTATUS ret = RegQueryValueExA(regKey, valueName, NULL, NULL, NULL, &valueSize);
-      if (ret != ERROR_SUCCESS)
-      {
-        RegCloseKey(regKey);
-        continue;
-      }
-      char *regValue = (char *)malloc(valueSize);
-      if (regValue == NULL)
-      {
-        RegCloseKey(regKey);
-        continue;
-      }
-      ret = RegQueryValueExA(regKey, valueName, NULL, NULL, (LPBYTE)regValue, &valueSize);
-      if (ret != ERROR_SUCCESS)
-      {
-        free(regValue);
-        RegCloseKey(regKey);
-        continue;
-      }
-      // Strip the opengl driver dll name from the string then create a new string with
-      // the path and the nvoptix.dll name
-      for (int i = (int)valueSize - 1; i >= 0 && regValue[i] != '\\'; --i)
-        regValue[i] = '\0';
-      size_t newPathSize = strlen(regValue) + strlen(optixDllName) + 1;
-      dllPath = (char *)malloc(newPathSize);
-      if (dllPath == NULL)
-      {
-        free(regValue);
-        RegCloseKey(regKey);
-        continue;
-      }
-      strcpy(dllPath, regValue);
-      strcat(dllPath, optixDllName);
-      free(regValue);
-      RegCloseKey(regKey);
-      handle = LoadLibraryA((LPCSTR)dllPath);
-      free(dllPath);
-      if (handle)
-        break;
-    }
-    free(deviceNames);
-    return handle;
-  }
-
-  static void *optixLoadWindowsDll()
-  {
-    return optixLoadWindowsDllFromName("nvoptix.dll");
-  }
-#endif
-
-  /// \defgroup optix_utilities Utilities
-  /// \brief OptiX Utilities
-
-  /** \addtogroup optix_utilities
-@{
-*/
-
-  /// Loads the OptiX library and initializes the function table used by the stubs below.
-  ///
-  /// If handlePtr is not nullptr, an OS-specific handle to the library will be returned in *handlePtr.
-  ///
-  /// \see #optixUninitWithHandle
-  OptixResult optixInitWithHandle(void **handlePtr)
-  {
-    // Make sure these functions get initialized to zero in case the DLL and function
-    // table can't be loaded
-    g_optixFunctionTable.optixGetErrorName = 0;
-    g_optixFunctionTable.optixGetErrorString = 0;
-
-    if (!handlePtr)
-      return OPTIX_ERROR_INVALID_VALUE;
-
-#ifdef _WIN32
-    *handlePtr = optixLoadWindowsDll();
-    if (!*handlePtr)
-      return OPTIX_ERROR_LIBRARY_NOT_FOUND;
-
-    void *symbol = GetProcAddress((HMODULE)*handlePtr, "optixQueryFunctionTable");
-    if (!symbol)
-      return OPTIX_ERROR_ENTRY_SYMBOL_NOT_FOUND;
-#else
-  *handlePtr = dlopen("libnvoptix.so.1", RTLD_NOW);
-  if (!*handlePtr)
-    return OPTIX_ERROR_LIBRARY_NOT_FOUND;
-
-  void *symbol = dlsym(*handlePtr, "optixQueryFunctionTable");
-  if (!symbol)
-    return OPTIX_ERROR_ENTRY_SYMBOL_NOT_FOUND;
-#endif
-
-    OptixQueryFunctionTable_t *optixQueryFunctionTable = (OptixQueryFunctionTable_t *)symbol;
-
-    return optixQueryFunctionTable(OPTIX_ABI_VERSION, 0, 0, 0, &g_optixFunctionTable, sizeof(g_optixFunctionTable));
-  }
-
-  /// Loads the OptiX library and initializes the function table used by the stubs below.
-  ///
-  /// A variant of #optixInitWithHandle() that does not make the handle to the loaded library available.
-  OptixResult optixInit(void)
-  {
-    void *handle;
-    return optixInitWithHandle(&handle);
-  }
-
-  /// Unloads the OptiX library and zeros the function table used by the stubs below.  Takes the
-  /// handle returned by optixInitWithHandle.  All OptixDeviceContext objects must be destroyed
-  /// before calling this function, or the behavior is undefined.
-  ///
-  /// \see #optixInitWithHandle
-  OptixResult optixUninitWithHandle(void *handle)
-  {
-    if (!handle)
-      return OPTIX_ERROR_INVALID_VALUE;
-#ifdef _WIN32
-    if (!FreeLibrary((HMODULE)handle))
-      return OPTIX_ERROR_LIBRARY_UNLOAD_FAILURE;
-#else
-  if (dlclose(handle))
-    return OPTIX_ERROR_LIBRARY_UNLOAD_FAILURE;
-#endif
-    OptixFunctionTable empty = {0};
-    g_optixFunctionTable = empty;
-    return OPTIX_SUCCESS;
-  }
-
-  /*@}*/ // end group optix_utilities
-
-  // Stub functions that forward calls to the corresponding function pointer in the function table.
-
-  const char *optixGetErrorName(OptixResult result)
-  {
-    if (g_optixFunctionTable.optixGetErrorName)
-      return g_optixFunctionTable.optixGetErrorName(result);
-
-    // If the DLL and symbol table couldn't be loaded, provide a set of error strings
-    // suitable for processing errors related to the DLL loading.
-    switch (result)
-    {
-    case OPTIX_SUCCESS:
-      return "OPTIX_SUCCESS";
-    case OPTIX_ERROR_INVALID_VALUE:
-      return "OPTIX_ERROR_INVALID_VALUE";
-    case OPTIX_ERROR_UNSUPPORTED_ABI_VERSION:
-      return "OPTIX_ERROR_UNSUPPORTED_ABI_VERSION";
-    case OPTIX_ERROR_FUNCTION_TABLE_SIZE_MISMATCH:
-      return "OPTIX_ERROR_FUNCTION_TABLE_SIZE_MISMATCH";
-    case OPTIX_ERROR_INVALID_ENTRY_FUNCTION_OPTIONS:
-      return "OPTIX_ERROR_INVALID_ENTRY_FUNCTION_OPTIONS";
-    case OPTIX_ERROR_LIBRARY_NOT_FOUND:
-      return "OPTIX_ERROR_LIBRARY_NOT_FOUND";
-    case OPTIX_ERROR_ENTRY_SYMBOL_NOT_FOUND:
-      return "OPTIX_ERROR_ENTRY_SYMBOL_NOT_FOUND";
-    case OPTIX_ERROR_LIBRARY_UNLOAD_FAILURE:
-      return "OPTIX_ERROR_LIBRARY_UNLOAD_FAILURE";
-    default:
-      return "Unknown OptixResult code";
-    }
-  }
-
-  const char *optixGetErrorString(OptixResult result)
-  {
-    if (g_optixFunctionTable.optixGetErrorString)
-      return g_optixFunctionTable.optixGetErrorString(result);
-
-    // If the DLL and symbol table couldn't be loaded, provide a set of error strings
-    // suitable for processing errors related to the DLL loading.
-    switch (result)
-    {
-    case OPTIX_SUCCESS:
-      return "Success";
-    case OPTIX_ERROR_INVALID_VALUE:
-      return "Invalid value";
-    case OPTIX_ERROR_UNSUPPORTED_ABI_VERSION:
-      return "Unsupported ABI version";
-    case OPTIX_ERROR_FUNCTION_TABLE_SIZE_MISMATCH:
-      return "Function table size mismatch";
-    case OPTIX_ERROR_INVALID_ENTRY_FUNCTION_OPTIONS:
-      return "Invalid options to entry function";
-    case OPTIX_ERROR_LIBRARY_NOT_FOUND:
-      return "Library not found";
-    case OPTIX_ERROR_ENTRY_SYMBOL_NOT_FOUND:
-      return "Entry symbol not found";
-    case OPTIX_ERROR_LIBRARY_UNLOAD_FAILURE:
-      return "Library could not be unloaded";
-    default:
-      return "Unknown OptixResult code";
-    }
-  }
-
-  OptixResult optixDeviceContextCreate(CUcontext fromContext, const OptixDeviceContextOptions *options, OptixDeviceContext *context)
-  {
-    return g_optixFunctionTable.optixDeviceContextCreate(fromContext, options, context);
-  }
-
-  OptixResult optixDeviceContextDestroy(OptixDeviceContext context)
-  {
-    return g_optixFunctionTable.optixDeviceContextDestroy(context);
-  }
-
-  OptixResult optixDeviceContextGetProperty(OptixDeviceContext context, OptixDeviceProperty property, void *value, size_t sizeInBytes)
-  {
-    return g_optixFunctionTable.optixDeviceContextGetProperty(context, property, value, sizeInBytes);
-  }
-
-  OptixResult optixDeviceContextSetLogCallback(OptixDeviceContext context,
-                                               OptixLogCallback callbackFunction,
-                                               void *callbackData,
-                                               unsigned int callbackLevel)
-  {
-    return g_optixFunctionTable.optixDeviceContextSetLogCallback(context, callbackFunction, callbackData, callbackLevel);
-  }
-
-  OptixResult optixDeviceContextSetCacheEnabled(OptixDeviceContext context, int enabled)
-  {
-    return g_optixFunctionTable.optixDeviceContextSetCacheEnabled(context, enabled);
-  }
-
-  OptixResult optixDeviceContextSetCacheLocation(OptixDeviceContext context, const char *location)
-  {
-    return g_optixFunctionTable.optixDeviceContextSetCacheLocation(context, location);
-  }
-
-  OptixResult optixDeviceContextSetCacheDatabaseSizes(OptixDeviceContext context, size_t lowWaterMark, size_t highWaterMark)
-  {
-    return g_optixFunctionTable.optixDeviceContextSetCacheDatabaseSizes(context, lowWaterMark, highWaterMark);
-  }
-
-  OptixResult optixDeviceContextGetCacheEnabled(OptixDeviceContext context, int *enabled)
-  {
-    return g_optixFunctionTable.optixDeviceContextGetCacheEnabled(context, enabled);
-  }
-
-  OptixResult optixDeviceContextGetCacheLocation(OptixDeviceContext context, char *location, size_t locationSize)
-  {
-    return g_optixFunctionTable.optixDeviceContextGetCacheLocation(context, location, locationSize);
-  }
-
-  OptixResult optixDeviceContextGetCacheDatabaseSizes(OptixDeviceContext context, size_t *lowWaterMark, size_t *highWaterMark)
-  {
-    return g_optixFunctionTable.optixDeviceContextGetCacheDatabaseSizes(context, lowWaterMark, highWaterMark);
-  }
-
-  OptixResult optixModuleCreateFromPTX(OptixDeviceContext context,
-                                       const OptixModuleCompileOptions *moduleCompileOptions,
-                                       const OptixPipelineCompileOptions *pipelineCompileOptions,
-                                       const char *PTX,
-                                       size_t PTXsize,
-                                       char *logString,
-                                       size_t *logStringSize,
-                                       OptixModule *module)
-  {
-    return g_optixFunctionTable.optixModuleCreateFromPTX(context, moduleCompileOptions, pipelineCompileOptions, PTX,
-                                                         PTXsize, logString, logStringSize, module);
-  }
-
-  OptixResult optixModuleDestroy(OptixModule module)
-  {
-    return g_optixFunctionTable.optixModuleDestroy(module);
-  }
-
-  OptixResult optixBuiltinISModuleGet(OptixDeviceContext context,
-                                      const OptixModuleCompileOptions *moduleCompileOptions,
-                                      const OptixPipelineCompileOptions *pipelineCompileOptions,
-                                      const OptixBuiltinISOptions *builtinISOptions,
-                                      OptixModule *builtinModule)
-  {
-    return g_optixFunctionTable.optixBuiltinISModuleGet(context, moduleCompileOptions, pipelineCompileOptions,
-                                                        builtinISOptions, builtinModule);
-  }
-
-  OptixResult optixProgramGroupCreate(OptixDeviceContext context,
-                                      const OptixProgramGroupDesc *programDescriptions,
-                                      unsigned int numProgramGroups,
-                                      const OptixProgramGroupOptions *options,
-                                      char *logString,
-                                      size_t *logStringSize,
-                                      OptixProgramGroup *programGroups)
-  {
-    return g_optixFunctionTable.optixProgramGroupCreate(context, programDescriptions, numProgramGroups, options,
-                                                        logString, logStringSize, programGroups);
-  }
-
-  OptixResult optixProgramGroupDestroy(OptixProgramGroup programGroup)
-  {
-    return g_optixFunctionTable.optixProgramGroupDestroy(programGroup);
-  }
-
-  OptixResult optixProgramGroupGetStackSize(OptixProgramGroup programGroup, OptixStackSizes *stackSizes)
-  {
-    return g_optixFunctionTable.optixProgramGroupGetStackSize(programGroup, stackSizes);
-  }
-
-  OptixResult optixPipelineCreate(OptixDeviceContext context,
-                                  const OptixPipelineCompileOptions *pipelineCompileOptions,
-                                  const OptixPipelineLinkOptions *pipelineLinkOptions,
-                                  const OptixProgramGroup *programGroups,
-                                  unsigned int numProgramGroups,
-                                  char *logString,
-                                  size_t *logStringSize,
-                                  OptixPipeline *pipeline)
-  {
-    return g_optixFunctionTable.optixPipelineCreate(context, pipelineCompileOptions, pipelineLinkOptions, programGroups,
-                                                    numProgramGroups, logString, logStringSize, pipeline);
-  }
-
-  OptixResult optixPipelineDestroy(OptixPipeline pipeline)
-  {
-    return g_optixFunctionTable.optixPipelineDestroy(pipeline);
-  }
-
-  OptixResult optixPipelineSetStackSize(OptixPipeline pipeline,
-                                        unsigned int directCallableStackSizeFromTraversal,
-                                        unsigned int directCallableStackSizeFromState,
-                                        unsigned int continuationStackSize,
-                                        unsigned int maxTraversableGraphDepth)
-  {
-    return g_optixFunctionTable.optixPipelineSetStackSize(pipeline, directCallableStackSizeFromTraversal, directCallableStackSizeFromState,
-                                                          continuationStackSize, maxTraversableGraphDepth);
-  }
-
-  OptixResult optixAccelComputeMemoryUsage(OptixDeviceContext context,
-                                           const OptixAccelBuildOptions *accelOptions,
-                                           const OptixBuildInput *buildInputs,
-                                           unsigned int numBuildInputs,
-                                           OptixAccelBufferSizes *bufferSizes)
-  {
-    return g_optixFunctionTable.optixAccelComputeMemoryUsage(context, accelOptions, buildInputs, numBuildInputs, bufferSizes);
-  }
-
-  OptixResult optixAccelBuild(OptixDeviceContext context,
-                              CUstream stream,
-                              const OptixAccelBuildOptions *accelOptions,
-                              const OptixBuildInput *buildInputs,
-                              unsigned int numBuildInputs,
-                              CUdeviceptr tempBuffer,
-                              size_t tempBufferSizeInBytes,
-                              CUdeviceptr outputBuffer,
-                              size_t outputBufferSizeInBytes,
-                              OptixTraversableHandle *outputHandle,
-                              const OptixAccelEmitDesc *emittedProperties,
-                              unsigned int numEmittedProperties)
-  {
-    return g_optixFunctionTable.optixAccelBuild(context, stream, accelOptions, buildInputs, numBuildInputs, tempBuffer,
-                                                tempBufferSizeInBytes, outputBuffer, outputBufferSizeInBytes,
-                                                outputHandle, emittedProperties, numEmittedProperties);
-  }
-
-  OptixResult optixAccelGetRelocationInfo(OptixDeviceContext context, OptixTraversableHandle handle, OptixAccelRelocationInfo *info)
-  {
-    return g_optixFunctionTable.optixAccelGetRelocationInfo(context, handle, info);
-  }
-
-  OptixResult optixAccelCheckRelocationCompatibility(OptixDeviceContext context, const OptixAccelRelocationInfo *info, int *compatible)
-  {
-    return g_optixFunctionTable.optixAccelCheckRelocationCompatibility(context, info, compatible);
-  }
-
-  OptixResult optixAccelRelocate(OptixDeviceContext context,
-                                 CUstream stream,
-                                 const OptixAccelRelocationInfo *info,
-                                 CUdeviceptr instanceTraversableHandles,
-                                 size_t numInstanceTraversableHandles,
-                                 CUdeviceptr targetAccel,
-                                 size_t targetAccelSizeInBytes,
-                                 OptixTraversableHandle *targetHandle)
-  {
-    return g_optixFunctionTable.optixAccelRelocate(context, stream, info, instanceTraversableHandles, numInstanceTraversableHandles,
-                                                   targetAccel, targetAccelSizeInBytes, targetHandle);
-  }
-
-  OptixResult optixAccelCompact(OptixDeviceContext context,
-                                CUstream stream,
-                                OptixTraversableHandle inputHandle,
-                                CUdeviceptr outputBuffer,
-                                size_t outputBufferSizeInBytes,
-                                OptixTraversableHandle *outputHandle)
-  {
-    return g_optixFunctionTable.optixAccelCompact(context, stream, inputHandle, outputBuffer, outputBufferSizeInBytes, outputHandle);
-  }
-
-  OptixResult optixConvertPointerToTraversableHandle(OptixDeviceContext onDevice,
-                                                     CUdeviceptr pointer,
-                                                     OptixTraversableType traversableType,
-                                                     OptixTraversableHandle *traversableHandle)
-  {
-    return g_optixFunctionTable.optixConvertPointerToTraversableHandle(onDevice, pointer, traversableType, traversableHandle);
-  }
-
-  OptixResult optixSbtRecordPackHeader(OptixProgramGroup programGroup, void *sbtRecordHeaderHostPointer)
-  {
-    return g_optixFunctionTable.optixSbtRecordPackHeader(programGroup, sbtRecordHeaderHostPointer);
-  }
-
-  OptixResult optixLaunch(OptixPipeline pipeline,
-                          CUstream stream,
-                          CUdeviceptr pipelineParams,
-                          size_t pipelineParamsSize,
-                          const OptixShaderBindingTable *sbt,
-                          unsigned int width,
-                          unsigned int height,
-                          unsigned int depth)
-  {
-    return g_optixFunctionTable.optixLaunch(pipeline, stream, pipelineParams, pipelineParamsSize, sbt, width, height, depth);
-  }
-
-  OptixResult optixDenoiserCreate(OptixDeviceContext context, OptixDenoiserModelKind modelKind, const OptixDenoiserOptions *options, OptixDenoiser *returnHandle)
-  {
-    return g_optixFunctionTable.optixDenoiserCreate(context, modelKind, options, returnHandle);
-  }
-
-  OptixResult optixDenoiserCreateWithUserModel(OptixDeviceContext context, const void *data, size_t dataSizeInBytes, OptixDenoiser *returnHandle)
-  {
-    return g_optixFunctionTable.optixDenoiserCreateWithUserModel(context, data, dataSizeInBytes, returnHandle);
-  }
-
-  OptixResult optixDenoiserDestroy(OptixDenoiser handle)
-  {
-    return g_optixFunctionTable.optixDenoiserDestroy(handle);
-  }
-
-  OptixResult optixDenoiserComputeMemoryResources(const OptixDenoiser handle,
-                                                  unsigned int maximumInputWidth,
-                                                  unsigned int maximumInputHeight,
-                                                  OptixDenoiserSizes *returnSizes)
-  {
-    return g_optixFunctionTable.optixDenoiserComputeMemoryResources(handle, maximumInputWidth, maximumInputHeight, returnSizes);
-  }
-
-  OptixResult optixDenoiserSetup(OptixDenoiser denoiser,
-                                 CUstream stream,
-                                 unsigned int inputWidth,
-                                 unsigned int inputHeight,
-                                 CUdeviceptr denoiserState,
-                                 size_t denoiserStateSizeInBytes,
-                                 CUdeviceptr scratch,
-                                 size_t scratchSizeInBytes)
-  {
-    return g_optixFunctionTable.optixDenoiserSetup(denoiser, stream, inputWidth, inputHeight, denoiserState,
-                                                   denoiserStateSizeInBytes, scratch, scratchSizeInBytes);
-  }
-
-  OptixResult optixDenoiserInvoke(OptixDenoiser handle,
-                                  CUstream stream,
-                                  const OptixDenoiserParams *params,
-                                  CUdeviceptr denoiserData,
-                                  size_t denoiserDataSize,
-                                  const OptixDenoiserGuideLayer *guideLayer,
-                                  const OptixDenoiserLayer *layers,
-                                  unsigned int numLayers,
-                                  unsigned int inputOffsetX,
-                                  unsigned int inputOffsetY,
-                                  CUdeviceptr scratch,
-                                  size_t scratchSizeInBytes)
-  {
-    return g_optixFunctionTable.optixDenoiserInvoke(handle, stream, params, denoiserData, denoiserDataSize,
-                                                    guideLayer, layers, numLayers,
-                                                    inputOffsetX, inputOffsetY, scratch, scratchSizeInBytes);
-  }
-
-  OptixResult optixDenoiserComputeIntensity(OptixDenoiser handle,
-                                            CUstream stream,
-                                            const OptixImage2D *inputImage,
-                                            CUdeviceptr outputIntensity,
-                                            CUdeviceptr scratch,
-                                            size_t scratchSizeInBytes)
-  {
-    return g_optixFunctionTable.optixDenoiserComputeIntensity(handle, stream, inputImage, outputIntensity, scratch, scratchSizeInBytes);
-  }
-
-  OptixResult optixDenoiserComputeAverageColor(OptixDenoiser handle,
-                                               CUstream stream,
-                                               const OptixImage2D *inputImage,
-                                               CUdeviceptr outputAverageColor,
-                                               CUdeviceptr scratch,
-                                               size_t scratchSizeInBytes)
-  {
-    return g_optixFunctionTable.optixDenoiserComputeAverageColor(handle, stream, inputImage, outputAverageColor, scratch, scratchSizeInBytes);
-  }
-
-#ifdef __cplusplus
-}
-#endif
-
+// optix_stubs.h contains the functions needed to load the library and provides stubs
+// to call the functions in the function table. However, the stubs are defined as
+// `inline`, and won't be included in the final binary as is. We work around this by
+// redefining `inline` to do nothing before including the header.
+#define inline
+#include "optix_stubs.h"
+#undef inline

From a9206084289ecbd5d82f52351afb61890611c22f Mon Sep 17 00:00:00 2001
From: Jorge Ortega <jorge-ortega@outlook.com>
Date: Wed, 19 Mar 2025 22:29:04 -0700
Subject: [PATCH 2/3] Remove redundant cargo instructions.

`cc` already sets rustc-link-search and rustc-link-lib after compiling. Since other rerun-if-changed instructions are emitted, specifying build.rs is redudant.
---
 crates/optix/build.rs | 9 ---------
 1 file changed, 9 deletions(-)

diff --git a/crates/optix/build.rs b/crates/optix/build.rs
index b52e0f0c..15772112 100644
--- a/crates/optix/build.rs
+++ b/crates/optix/build.rs
@@ -1,5 +1,4 @@
 use find_cuda_helper::{find_cuda_root, find_optix_root};
-use std::env;
 use std::path::{Path, PathBuf};
 
 // OptiX is a bit exotic in how it provides its functions. It uses a function table
@@ -8,7 +7,6 @@ use std::path::{Path, PathBuf};
 // OptiX provides this logic inside optix_stubs.h in the include dir, so we need to compile that
 // to a lib and link it in so that we have the initialization and C function logic.
 fn main() {
-    let out_dir = env::var("OUT_DIR").unwrap();
     let mut optix_include = find_optix_root().expect(
         "Unable to find the OptiX SDK, make sure you installed it and
     that OPTIX_ROOT or OPTIX_ROOT_DIR are set",
@@ -30,9 +28,6 @@ fn main() {
         .include(cuda_include)
         .cpp(false)
         .compile("optix_stubs");
-
-    println!("cargo:rustc-link-search=native={}", out_dir);
-    println!("cargo:rustc-link-lib=static=optix_stubs");
 }
 
 fn bindgen_optix(optix_include: &Path, cuda_include: &Path) {
@@ -42,11 +37,7 @@ fn bindgen_optix(optix_include: &Path, cuda_include: &Path) {
         .join("src")
         .join("optix_wrapper.h");
 
-    let this_path =
-        std::path::PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap()).join("build.rs");
-
     println!("cargo:rerun-if-changed={}", header_path.display());
-    println!("cargo:rerun-if-changed={}", this_path.display());
 
     let bindings = bindgen::Builder::default()
         .header("src/optix_wrapper.h")

From f02a17c0ad69472ffe2c5c6c40a1ab22377695bf Mon Sep 17 00:00:00 2001
From: Jorge Ortega <jorge-ortega@outlook.com>
Date: Wed, 19 Mar 2025 23:56:17 -0700
Subject: [PATCH 3/3] Use `bindgen::CargoCallback` to rerun when included
 header files change.

---
 crates/optix/build.rs | 7 +------
 1 file changed, 1 insertion(+), 6 deletions(-)

diff --git a/crates/optix/build.rs b/crates/optix/build.rs
index 15772112..feb65716 100644
--- a/crates/optix/build.rs
+++ b/crates/optix/build.rs
@@ -33,14 +33,9 @@ fn main() {
 fn bindgen_optix(optix_include: &Path, cuda_include: &Path) {
     let out_path = PathBuf::from(std::env::var("OUT_DIR").unwrap()).join("optix_wrapper.rs");
 
-    let header_path = PathBuf::from(std::env::var("CARGO_MANIFEST_DIR").unwrap())
-        .join("src")
-        .join("optix_wrapper.h");
-
-    println!("cargo:rerun-if-changed={}", header_path.display());
-
     let bindings = bindgen::Builder::default()
         .header("src/optix_wrapper.h")
+        .parse_callbacks(Box::new(bindgen::CargoCallbacks::new()))
         .clang_arg(format!("-I{}", optix_include.display()))
         .clang_arg(format!("-I{}", cuda_include.display()))
         .allowlist_recursively(false)