Cycles: Bump OptiX minimum and release version to 8.0.0

This requires a minimum driver version of 535, however most devices
were already requiring 570 due to the CUDA toolkit version.

The update is required to be able to use an API function for correct
stack size calculation.

Code for older API versions has been removed.

Fix #138185: OSL custom camera errors with OptiX

Pull Request: https://projects.blender.org/blender/blender/pulls/139801
This commit is contained in:
Brecht Van Lommel
2025-06-04 19:24:21 +02:00
committed by Brecht Van Lommel
parent 3a47bd7e5a
commit 0add3f31a2
4 changed files with 12 additions and 136 deletions

View File

@@ -26,14 +26,6 @@ set(_optix_SEARCH_DIRS
${OPTIX_ROOT_DIR}
)
# TODO: Which environment uses this?
if(DEFINED ENV{PROGRAMDATA})
list(APPEND _optix_SEARCH_DIRS
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.4.0"
"$ENV{PROGRAMDATA}/NVIDIA Corporation/OptiX SDK 7.3.0"
)
endif()
find_path(OPTIX_INCLUDE_DIR
NAMES
optix.h

View File

@@ -18,7 +18,7 @@ buildbot:
linux:
version: '6.4.0'
optix:
version: '7.4.0'
version: '8.0.0'
ocloc:
version: '101.6557'
cmake:

View File

@@ -265,7 +265,7 @@ if(WITH_CYCLES_DEVICE_HIP)
endif()
if(WITH_CYCLES_DEVICE_OPTIX)
find_package(OptiX 7.3.0)
find_package(OptiX 8.0.0)
if(OPTIX_FOUND)
add_definitions(-DWITH_OPTIX)

View File

@@ -28,7 +28,6 @@
CCL_NAMESPACE_BEGIN
# if OPTIX_ABI_VERSION >= 55
static void execute_optix_task(TaskPool &pool, OptixTask task, OptixResult &failure_reason)
{
OptixTask additional_tasks[16];
@@ -46,7 +45,6 @@ static void execute_optix_task(TaskPool &pool, OptixTask task, OptixResult &fail
failure_reason = result;
}
}
# endif
OptiXDevice::OptiXDevice(const DeviceInfo &info, Stats &stats, Profiler &profiler, bool headless)
: CUDADevice(info, stats, profiler, headless),
@@ -203,7 +201,6 @@ void OptiXDevice::create_optix_module(TaskPool &pool,
OptixModule &module,
OptixResult &result)
{
# if OPTIX_ABI_VERSION >= 84
OptixTask task = nullptr;
result = optixModuleCreateWithTasks(context,
&module_options,
@@ -217,31 +214,6 @@ void OptiXDevice::create_optix_module(TaskPool &pool,
if (result == OPTIX_SUCCESS) {
execute_optix_task(pool, task, result);
}
# elif OPTIX_ABI_VERSION >= 55
OptixTask task = nullptr;
result = optixModuleCreateFromPTXWithTasks(context,
&module_options,
&pipeline_options,
ptx_data.data(),
ptx_data.size(),
nullptr,
nullptr,
&module,
&task);
if (result == OPTIX_SUCCESS) {
execute_optix_task(pool, task, result);
}
# else
(void)pool;
result = optixModuleCreateFromPTX(context,
&module_options,
&pipeline_options,
ptx_data.data(),
ptx_data.size(),
nullptr,
nullptr,
&module);
# endif
}
bool OptiXDevice::load_kernels(const uint kernel_features)
@@ -364,10 +336,8 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
module_options.boundValues = nullptr;
module_options.numBoundValues = 0;
# if OPTIX_ABI_VERSION >= 55
module_options.payloadTypes = nullptr;
module_options.numPayloadTypes = 0;
# endif
/* Default to no motion blur and two-level graph, since it is the fastest option. */
pipeline_options.usesMotionBlur = false;
@@ -381,11 +351,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
pipeline_options.usesPrimitiveTypeFlags = OPTIX_PRIMITIVE_TYPE_FLAGS_TRIANGLE;
if (kernel_features & KERNEL_FEATURE_HAIR) {
if (kernel_features & KERNEL_FEATURE_HAIR_THICK) {
# if OPTIX_ABI_VERSION >= 55
pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CATMULLROM;
# else
pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_ROUND_CUBIC_BSPLINE;
# endif
}
else {
pipeline_options.usesPrimitiveTypeFlags |= OPTIX_PRIMITIVE_TYPE_FLAGS_CUSTOM;
@@ -472,15 +438,11 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
if (kernel_features & KERNEL_FEATURE_HAIR_THICK) {
/* Built-in thick curve intersection. */
OptixBuiltinISOptions builtin_options = {};
# if OPTIX_ABI_VERSION >= 55
builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM;
builtin_options.buildFlags = OPTIX_BUILD_FLAG_PREFER_FAST_TRACE |
OPTIX_BUILD_FLAG_ALLOW_COMPACTION |
OPTIX_BUILD_FLAG_ALLOW_UPDATE;
builtin_options.curveEndcapFlags = OPTIX_CURVE_ENDCAP_DEFAULT; /* Disable end-caps. */
# else
builtin_options.builtinISModuleType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
# endif
builtin_options.usesMotionBlur = false;
optix_assert(optixBuiltinISModuleGet(
@@ -636,11 +598,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
memset(sbt_data.host_pointer, 0, sizeof(SbtRecord) * NUM_PROGRAM_GROUPS);
for (int i = 0; i < NUM_PROGRAM_GROUPS; ++i) {
optix_assert(optixSbtRecordPackHeader(groups[i], &sbt_data[i]));
# if OPTIX_ABI_VERSION >= 84
optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i], nullptr));
# else
optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i]));
# endif
}
sbt_data.copy_to_device(); /* Upload SBT to device. */
@@ -662,9 +620,6 @@ bool OptiXDevice::load_kernels(const uint kernel_features)
OptixPipelineLinkOptions link_options = {};
link_options.maxTraceDepth = 1;
# if OPTIX_ABI_VERSION < 84
link_options.debugLevel = module_options.debugLevel;
# endif
if (use_osl_shading || use_osl_camera) {
/* OSL kernels will be (re)created on by OSL manager. */
@@ -976,9 +931,6 @@ bool OptiXDevice::load_osl_kernels()
OptixPipelineLinkOptions link_options = {};
link_options.maxTraceDepth = 0;
# if OPTIX_ABI_VERSION < 84
link_options.debugLevel = OPTIX_COMPILE_DEBUG_LEVEL_NONE;
# endif
{
vector<OptixProgramGroup> pipeline_groups;
@@ -1018,20 +970,12 @@ bool OptiXDevice::load_osl_kernels()
vector<OptixStackSizes> osl_stack_size(osl_groups.size());
for (int i = 0; i < NUM_PROGRAM_GROUPS; ++i) {
# if OPTIX_ABI_VERSION >= 84
optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i], nullptr));
# else
optix_assert(optixProgramGroupGetStackSize(groups[i], &stack_size[i]));
# endif
}
for (size_t i = 0; i < osl_groups.size(); ++i) {
if (osl_groups[i] != nullptr) {
# if OPTIX_ABI_VERSION >= 84
optix_assert(optixProgramGroupGetStackSize(
osl_groups[i], &osl_stack_size[i], pipelines[PIP_SHADE]));
# else
optix_assert(optixProgramGroupGetStackSize(osl_groups[i], &osl_stack_size[i]));
# endif
}
}
@@ -1278,9 +1222,7 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
/* Four control points for each curve segment. */
size_t num_vertices = num_segments * 4;
if (hair->curve_shape == CURVE_THICK) {
# if OPTIX_ABI_VERSION >= 55
num_vertices = hair->num_keys() + 2 * hair->num_curves();
# endif
index_data.alloc(num_segments);
vertex_data.alloc(num_vertices * num_motion_steps);
}
@@ -1299,7 +1241,6 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
keys = motion_keys->data_float3() + attr_offset * hair->get_curve_keys().size();
}
# if OPTIX_ABI_VERSION >= 55
if (hair->curve_shape == CURVE_THICK) {
for (size_t curve_index = 0, segment_index = 0, vertex_index = step * num_vertices;
curve_index < hair->num_curves();
@@ -1339,60 +1280,21 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
}
}
}
else
# endif
{
else {
for (size_t curve_index = 0, i = 0; curve_index < hair->num_curves(); ++curve_index) {
const Hair::Curve curve = hair->get_curve(curve_index);
for (int segment = 0; segment < curve.num_segments(); ++segment, ++i) {
# if OPTIX_ABI_VERSION < 55
if (hair->curve_shape == CURVE_THICK) {
const array<float> &curve_radius = hair->get_curve_radius();
BoundBox bounds = BoundBox::empty;
curve.bounds_grow(segment, keys, hair->get_curve_radius().data(), bounds);
int k0 = curve.first_key + segment;
int k1 = k0 + 1;
int ka = max(k0 - 1, curve.first_key);
int kb = min(k1 + 1, curve.first_key + curve.num_keys - 1);
index_data[i] = i * 4;
float4 *const v = vertex_data.data() + step * num_vertices + index_data[i];
const float4 px = make_float4(keys[ka].x, keys[k0].x, keys[k1].x, keys[kb].x);
const float4 py = make_float4(keys[ka].y, keys[k0].y, keys[k1].y, keys[kb].y);
const float4 pz = make_float4(keys[ka].z, keys[k0].z, keys[k1].z, keys[kb].z);
const float4 pw = make_float4(
curve_radius[ka], curve_radius[k0], curve_radius[k1], curve_radius[kb]);
/* Convert Catmull-Rom data to B-spline. */
static const float4 cr2bsp0 = make_float4(+7, -4, +5, -2) / 6.f;
static const float4 cr2bsp1 = make_float4(-2, 11, -4, +1) / 6.f;
static const float4 cr2bsp2 = make_float4(+1, -4, 11, -2) / 6.f;
static const float4 cr2bsp3 = make_float4(-2, +5, -4, +7) / 6.f;
v[0] = make_float4(
dot(cr2bsp0, px), dot(cr2bsp0, py), dot(cr2bsp0, pz), dot(cr2bsp0, pw));
v[1] = make_float4(
dot(cr2bsp1, px), dot(cr2bsp1, py), dot(cr2bsp1, pz), dot(cr2bsp1, pw));
v[2] = make_float4(
dot(cr2bsp2, px), dot(cr2bsp2, py), dot(cr2bsp2, pz), dot(cr2bsp2, pw));
v[3] = make_float4(
dot(cr2bsp3, px), dot(cr2bsp3, py), dot(cr2bsp3, pz), dot(cr2bsp3, pw));
}
else
# endif
{
BoundBox bounds = BoundBox::empty;
curve.bounds_grow(segment, keys, hair->get_curve_radius().data(), bounds);
const size_t index = step * num_segments + i;
aabb_data[index].minX = bounds.min.x;
aabb_data[index].minY = bounds.min.y;
aabb_data[index].minZ = bounds.min.z;
aabb_data[index].maxX = bounds.max.x;
aabb_data[index].maxY = bounds.max.y;
aabb_data[index].maxZ = bounds.max.z;
}
const size_t index = step * num_segments + i;
aabb_data[index].minX = bounds.min.x;
aabb_data[index].minY = bounds.min.y;
aabb_data[index].minZ = bounds.min.z;
aabb_data[index].maxX = bounds.max.x;
aabb_data[index].maxY = bounds.max.y;
aabb_data[index].maxZ = bounds.max.z;
}
}
}
@@ -1422,11 +1324,7 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
OptixBuildInput build_input = {};
if (hair->curve_shape == CURVE_THICK) {
build_input.type = OPTIX_BUILD_INPUT_TYPE_CURVES;
# if OPTIX_ABI_VERSION >= 55
build_input.curveArray.curveType = OPTIX_PRIMITIVE_TYPE_ROUND_CATMULLROM;
# else
build_input.curveArray.curveType = OPTIX_PRIMITIVE_TYPE_ROUND_CUBIC_BSPLINE;
# endif
build_input.curveArray.numPrimitives = num_segments;
build_input.curveArray.vertexBuffers = (CUdeviceptr *)vertex_ptrs.data();
build_input.curveArray.numVertices = num_vertices;
@@ -1600,21 +1498,12 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
OPTIX_GEOMETRY_FLAG_REQUIRE_SINGLE_ANYHIT_CALL;
OptixBuildInput build_input = {};
build_input.type = OPTIX_BUILD_INPUT_TYPE_CUSTOM_PRIMITIVES;
# if OPTIX_ABI_VERSION < 23
build_input.aabbArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
build_input.aabbArray.numPrimitives = num_points;
build_input.aabbArray.strideInBytes = sizeof(OptixAabb);
build_input.aabbArray.flags = &build_flags;
build_input.aabbArray.numSbtRecords = 1;
build_input.aabbArray.primitiveIndexOffset = pointcloud->prim_offset;
# else
build_input.customPrimitiveArray.aabbBuffers = (CUdeviceptr *)aabb_ptrs.data();
build_input.customPrimitiveArray.numPrimitives = num_points;
build_input.customPrimitiveArray.strideInBytes = sizeof(OptixAabb);
build_input.customPrimitiveArray.flags = &build_flags;
build_input.customPrimitiveArray.numSbtRecords = 1;
build_input.customPrimitiveArray.primitiveIndexOffset = pointcloud->prim_offset;
# endif
if (!build_optix_bvh(bvh_optix, operation, build_input, num_motion_steps)) {
progress.set_error("Failed to build OptiX acceleration structure");
@@ -1714,11 +1603,6 @@ void OptiXDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
/* Also skip point clouds in local trace calls. */
instance.visibilityMask |= 4;
}
# if OPTIX_ABI_VERSION < 55
/* Cannot disable any-hit program for thick curves, since it needs to filter out end-caps. */
else
# endif
{
/* Can disable __anyhit__kernel_optix_visibility_test by default (except for thick curves,
* since it needs to filter out end-caps there).