Fix #139986: Cycles crash on some scene updates, after Embree upgrade

Device::const_copy_to is sometimes called when the Embree BVH has been freed
and not replaced yet. Previously this was a simpler pointer copy, now there is
a function call. Make sure it's just a function copy.

Thanks to Nikita Sirgienko for figuring this out.

Pull Request: https://projects.blender.org/blender/blender/pulls/140457
This commit is contained in:
Brecht Van Lommel
2025-06-16 11:23:03 +02:00
parent f7ffcfe652
commit e84fad92ea
4 changed files with 29 additions and 21 deletions

View File

@@ -187,15 +187,11 @@ void CPUDevice::const_copy_to(const char *name, void *host, const size_t size)
if (strcmp(name, "data") == 0) {
assert(size <= sizeof(KernelData));
// Update scene handle (since it is different for each device on multi devices)
/* Update scene handle (since it is different for each device on multi devices).
* This must be a raw pointer copy since at some points during scene update this
* pointer may be invalid. */
KernelData *const data = (KernelData *)host;
data->device_bvh =
# if RTC_VERSION >= 40400
rtcGetSceneTraversable(embree_scene)
# else
embree_scene
# endif
;
data->device_bvh = embree_traversable;
}
#endif
kernel_const_copy(&kernel_globals, name, host, size);
@@ -272,7 +268,11 @@ void CPUDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
}
if (bvh->params.top_level) {
embree_scene = bvh_embree->scene;
# if RTC_VERSION >= 40400
embree_traversable = rtcGetSceneTraversable(bvh_embree->scene);
# else
embree_traversable = bvh_embree->scene;
# endif
}
}
else

View File

@@ -45,7 +45,11 @@ class CPUDevice : public Device {
OSLGlobals osl_globals;
#endif
#ifdef WITH_EMBREE
RTCScene embree_scene = nullptr;
# if RTC_VERSION >= 40400
RTCTraversable embree_traversable = nullptr;
# else
RTCScene embree_traversable = nullptr;
# endif
RTCDevice embree_device;
#endif
#ifdef WITH_PATH_GUIDING

View File

@@ -181,7 +181,11 @@ void OneapiDevice::build_bvh(BVH *bvh, Progress &progress, bool refit)
# endif
if (bvh->params.top_level) {
embree_scene = bvh_embree->scene;
# if RTC_VERSION >= 40400
embree_traversable = rtcGetSceneTraversable(bvh_embree->scene);
# else
embree_traversable = bvh_embree->scene;
# endif
# if RTC_VERSION >= 40302
RTCError error_code = bvh_embree->offload_scenes_to_gpu(all_embree_scenes);
if (error_code != RTC_ERROR_NONE) {
@@ -585,18 +589,14 @@ void OneapiDevice::const_copy_to(const char *name, void *host, const size_t size
<< string_human_readable_size(size) << ")";
# ifdef WITH_EMBREE_GPU
if (embree_scene != nullptr && strcmp(name, "data") == 0) {
if (embree_traversable != nullptr && strcmp(name, "data") == 0) {
assert(size <= sizeof(KernelData));
/* Update scene handle(since it is different for each device on multi devices) */
/* Update scene handle(since it is different for each device on multi devices).
* This must be a raw pointer copy since at some points during scene update this
* pointer may be invalid. */
KernelData *const data = (KernelData *)host;
data->device_bvh =
# if RTC_VERSION >= 40400
rtcGetSceneTraversable(embree_scene)
# else
embree_scene
# endif
;
data->device_bvh = embree_traversable;
/* We need this number later for proper local memory allocation. */
scene_max_shaders_ = data->max_shaders;

View File

@@ -23,7 +23,11 @@ class OneapiDevice : public GPUDevice {
SyclQueue *device_queue_ = nullptr;
# ifdef WITH_EMBREE_GPU
RTCDevice embree_device = nullptr;
RTCScene embree_scene = nullptr;
# if RTC_VERSION >= 40400
RTCTraversable embree_traversable = nullptr;
# else
RTCScene embree_traversable = nullptr;
# endif
# if RTC_VERSION >= 40302
thread_mutex scene_data_mutex;
vector<RTCScene> all_embree_scenes;