From c8f9fdc0c87b5875fa0dda8bcd586da28c9e9d9c Mon Sep 17 00:00:00 2001 From: Brecht Van Lommel Date: Fri, 11 Apr 2025 19:14:14 +0200 Subject: [PATCH] Fix: Cycles CUDA errors after recent changes for scene update Broken by 86b67a20d675afa3774. Delay upload of shader data to GPU until after kernels have been loaded. Pull Request: https://projects.blender.org/blender/blender/pulls/137349 --- intern/cycles/device/optix/device_impl.cpp | 3 +- intern/cycles/scene/osl.cpp | 37 +++++++++++---------- intern/cycles/scene/osl.h | 5 ++- intern/cycles/scene/scene.cpp | 14 ++++++-- intern/cycles/scene/shader.cpp | 21 ++++++++---- intern/cycles/scene/shader.h | 38 ++++++++++++---------- intern/cycles/scene/svm.cpp | 2 -- 7 files changed, 70 insertions(+), 50 deletions(-) diff --git a/intern/cycles/device/optix/device_impl.cpp b/intern/cycles/device/optix/device_impl.cpp index 182d2e447ce..6ef7e4cebc7 100644 --- a/intern/cycles/device/optix/device_impl.cpp +++ b/intern/cycles/device/optix/device_impl.cpp @@ -613,8 +613,7 @@ bool OptiXDevice::load_kernels(const uint kernel_features) # endif if (use_osl) { - /* Re-create OSL pipeline in case kernels are reloaded after it has been created before. */ - load_osl_kernels(); + /* OSL kernels will be (re)created on by OSL manager. */ } else if (kernel_features & (KERNEL_FEATURE_NODE_RAYTRACE | KERNEL_FEATURE_MNEE)) { /* Create shader ray-tracing and MNEE pipeline. */ diff --git a/intern/cycles/scene/osl.cpp b/intern/cycles/scene/osl.cpp index 2c6366258b3..f5a9691a7cd 100644 --- a/intern/cycles/scene/osl.cpp +++ b/intern/cycles/scene/osl.cpp @@ -143,13 +143,12 @@ void OSLManager::device_update_pre(Device *device, Scene *scene) } } -void OSLManager::device_update_post(Device *device, Scene *scene, Progress &progress) +void OSLManager::device_update_post(Device *device, + Scene *scene, + Progress &progress, + const bool reload_kernels) { - if (!need_update()) { - return; - } - - { + if (need_update()) { scoped_callback_timer timer([scene](double time) { if (scene->update_stats) { scene->update_stats->osl.times.add_entry({"jit", time}); @@ -181,21 +180,23 @@ void OSLManager::device_update_post(Device *device, Scene *scene, Progress &prog OSLRenderServices::image_manager = nullptr; } - /* setup shader engine */ - foreach_osl_device(device, [this, &progress](Device *sub_device, OSLGlobals *og) { - if (og->use) { - OSL::ShadingSystem *ss = get_shading_system(sub_device); + /* Load OSL kernels on changes to shaders, or when main kernels got reloaded. */ + if (need_update() || reload_kernels) { + foreach_osl_device(device, [this, &progress](Device *sub_device, OSLGlobals *og) { + if (og->use) { + OSL::ShadingSystem *ss = get_shading_system(sub_device); - og->ss = ss; - og->ts = get_texture_system(); - og->services = static_cast(ss->renderer()); + og->ss = ss; + og->ts = get_texture_system(); + og->services = static_cast(ss->renderer()); - /* load kernels */ - if (!sub_device->load_osl_kernels()) { - progress.set_error(sub_device->error_message()); + /* load kernels */ + if (!sub_device->load_osl_kernels()) { + progress.set_error(sub_device->error_message()); + } } - } - }); + }); + } need_update_ = false; } diff --git a/intern/cycles/scene/osl.h b/intern/cycles/scene/osl.h index 750c91226ea..5eaf377b6ae 100644 --- a/intern/cycles/scene/osl.h +++ b/intern/cycles/scene/osl.h @@ -62,7 +62,10 @@ class OSLManager { void reset(Scene *scene); void device_update_pre(Device *device, Scene *scene); - void device_update_post(Device *device, Scene *scene, Progress &progress); + void device_update_post(Device *device, + Scene *scene, + Progress &progress, + const bool reload_kernels); void device_free(Device *device, DeviceScene *dscene, Scene *scene); #ifdef WITH_OSL diff --git a/intern/cycles/scene/scene.cpp b/intern/cycles/scene/scene.cpp index aa1750af44d..c03925167af 100644 --- a/intern/cycles/scene/scene.cpp +++ b/intern/cycles/scene/scene.cpp @@ -199,10 +199,10 @@ void Scene::device_update(Device *device_, Progress &progress) integrator->tag_modified(); } + /* Compile shaders and get information about features they used. */ progress.set_status("Updating Shaders"); osl_manager->device_update_pre(device, this); - shader_manager->device_update(device, &dscene, this, progress); - osl_manager->device_update_post(device, this, progress); + shader_manager->device_update_pre(device, &dscene, this, progress); if (progress.get_cancel() || device->have_error()) { return; @@ -221,13 +221,21 @@ void Scene::device_update(Device *device_, Progress &progress) * compilation) does not depend on the scene and some other functionality (like display * driver) might be waiting on the scene mutex to synchronize display pass. */ mutex.unlock(); - load_kernels(progress); + const bool kernels_reloaded = load_kernels(progress); mutex.lock(); if (progress.get_cancel() || device->have_error()) { return; } + /* Upload shaders to GPU and compile OSL kernels, after kernels have been loaded. */ + shader_manager->device_update_post(device, &dscene, this, progress); + osl_manager->device_update_post(device, this, progress, kernels_reloaded); + + if (progress.get_cancel() || device->have_error()) { + return; + } + procedural_manager->update(this, progress); if (progress.get_cancel()) { diff --git a/intern/cycles/scene/shader.cpp b/intern/cycles/scene/shader.cpp index 620fa9bcb3b..363d4011505 100644 --- a/intern/cycles/scene/shader.cpp +++ b/intern/cycles/scene/shader.cpp @@ -480,11 +480,12 @@ int ShaderManager::get_shader_id(Shader *shader, bool smooth) return id; } -void ShaderManager::device_update(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress) +void ShaderManager::device_update_pre(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) { + /* This runs before kernels have been loaded, so can't copy to device yet. */ if (!need_update()) { return; } @@ -504,6 +505,16 @@ void ShaderManager::device_update(Device *device, device_update_specific(device, dscene, scene, progress); } +void ShaderManager::device_update_post(Device * /*device*/, + DeviceScene *dscene, + Scene * /*scene*/, + Progress & /*progress*/) +{ + /* This runs after kernels have been loaded, so can copy to device. */ + dscene->shaders.copy_to_device_if_modified(); + dscene->svm_nodes.copy_to_device_if_modified(); +} + void ShaderManager::device_update_common(Device * /*device*/, DeviceScene *dscene, Scene *scene, @@ -604,8 +615,6 @@ void ShaderManager::device_update_common(Device * /*device*/, has_transparent_shadow |= (flag & SD_HAS_TRANSPARENT_SHADOW) != 0; } - dscene->shaders.copy_to_device(); - /* lookup tables */ KernelTables *ktables = &dscene->data.tables; ktables->ggx_E = ensure_bsdf_table(dscene, scene, table_ggx_E); diff --git a/intern/cycles/scene/shader.h b/intern/cycles/scene/shader.h index 10303e70315..e69a3fac30c 100644 --- a/intern/cycles/scene/shader.h +++ b/intern/cycles/scene/shader.h @@ -185,16 +185,10 @@ class ShaderManager { } /* device update */ - void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - virtual void device_update_specific(Device *device, - DeviceScene *dscene, - Scene *scene, - Progress &progress) = 0; + void device_update_pre(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); + void device_update_post(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); virtual void device_free(Device *device, DeviceScene *dscene, Scene *scene) = 0; - void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); - void device_free_common(Device *device, DeviceScene *dscene, Scene *scene); - /* get globally unique id for a type of attribute */ virtual uint64_t get_attribute_id(ustring name); virtual uint64_t get_attribute_id(AttributeStandard std); @@ -232,6 +226,18 @@ class ShaderManager { unordered_map bsdf_tables; + thread_spin_lock attribute_lock_; + + float3 xyz_to_r; + float3 xyz_to_g; + float3 xyz_to_b; + float3 rgb_to_y; + float3 white_xyz; + float3 rec709_to_r; + float3 rec709_to_g; + float3 rec709_to_b; + bool is_rec709; + template size_t ensure_bsdf_table(DeviceScene *dscene, Scene *scene, const float (&table)[n]) { @@ -244,17 +250,13 @@ class ShaderManager { uint get_graph_kernel_features(ShaderGraph *graph); - thread_spin_lock attribute_lock_; + virtual void device_update_specific(Device *device, + DeviceScene *dscene, + Scene *scene, + Progress &progress) = 0; - float3 xyz_to_r; - float3 xyz_to_g; - float3 xyz_to_b; - float3 rgb_to_y; - float3 white_xyz; - float3 rec709_to_r; - float3 rec709_to_g; - float3 rec709_to_b; - bool is_rec709; + void device_update_common(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress); + void device_free_common(Device *device, DeviceScene *dscene, Scene *scene); }; CCL_NAMESPACE_END diff --git a/intern/cycles/scene/svm.cpp b/intern/cycles/scene/svm.cpp index 5073ab1e4a2..aa1acfbfacc 100644 --- a/intern/cycles/scene/svm.cpp +++ b/intern/cycles/scene/svm.cpp @@ -132,8 +132,6 @@ void SVMShaderManager::device_update_specific(Device *device, return; } - dscene->svm_nodes.copy_to_device(); - device_update_common(device, dscene, scene, progress); update_flags = UPDATE_NONE;