Fix: Cycles CUDA errors after recent changes for scene update

Broken by 86b67a20d6. Delay upload of shader data to GPU until
after kernels have been loaded.

Pull Request: https://projects.blender.org/blender/blender/pulls/137349
This commit is contained in:
Brecht Van Lommel
2025-04-11 19:14:14 +02:00
committed by Brecht Van Lommel
parent bb52754652
commit c8f9fdc0c8
7 changed files with 70 additions and 50 deletions

View File

@@ -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. */

View File

@@ -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<OSLRenderServices *>(ss->renderer());
og->ss = ss;
og->ts = get_texture_system();
og->services = static_cast<OSLRenderServices *>(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;
}

View File

@@ -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

View File

@@ -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()) {

View File

@@ -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);

View File

@@ -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<const float *, size_t> 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<std::size_t n>
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

View File

@@ -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;