Cycles: More accurate volume stack size calculation
The idea is to allow having a lot of non-intersecting volumes without allocating volume stack to its full size. With the F11285472 file the memory usage goes from 1400 MiB to 1000 on the RTX6000 card. The fix makes it so the integrator work memory is allocated after scene update which has downside of possible less efficient update when some textures don't fit GPU memory, but has an advantage of making proper decision and having a clear and consistent internal API. Fixes memory part of T92014. Differential Revision: https://developer.blender.org/D12966
This commit is contained in:
@@ -360,6 +360,8 @@ void Scene::device_update(Device *device_, Progress &progress)
|
||||
return;
|
||||
|
||||
if (device->have_error() == false) {
|
||||
dscene.data.volume_stack_size = get_volume_stack_size();
|
||||
|
||||
progress.set_status("Updating Device", "Writing constant memory");
|
||||
device->const_copy_to("__data", &dscene.data, sizeof(dscene.data));
|
||||
}
|
||||
@@ -527,8 +529,6 @@ void Scene::update_kernel_features()
|
||||
const uint max_closures = (params.background) ? get_max_closure_count() : MAX_CLOSURE;
|
||||
dscene.data.max_closures = max_closures;
|
||||
dscene.data.max_shaders = shaders.size();
|
||||
|
||||
dscene.data.volume_stack_size = get_volume_stack_size();
|
||||
}
|
||||
|
||||
bool Scene::update(Progress &progress)
|
||||
@@ -586,6 +586,8 @@ bool Scene::load_kernels(Progress &progress, bool lock_scene)
|
||||
scene_lock = thread_scoped_lock(mutex);
|
||||
}
|
||||
|
||||
update_kernel_features();
|
||||
|
||||
const uint kernel_features = dscene.data.kernel_features;
|
||||
|
||||
if (!kernels_loaded || loaded_kernel_features != kernel_features) {
|
||||
@@ -656,10 +658,25 @@ int Scene::get_volume_stack_size() const
|
||||
|
||||
/* Quick non-expensive check. Can over-estimate maximum possible nested level, but does not
|
||||
* require expensive calculation during pre-processing. */
|
||||
bool has_volume_object = false;
|
||||
for (const Object *object : objects) {
|
||||
if (object->check_is_volume()) {
|
||||
if (!object->get_geometry()->has_volume) {
|
||||
continue;
|
||||
}
|
||||
|
||||
if (object->intersects_volume) {
|
||||
/* Object intersects another volume, assume it's possible to go deeper in the stack. */
|
||||
/* TODO(sergey): This might count nesting twice (A intersects B and B intersects A), but
|
||||
* can't think of a computantially cheap algorithm. Dividing my 2 doesn't work because of
|
||||
* Venn diagram example with 3 circles. */
|
||||
++volume_stack_size;
|
||||
}
|
||||
else if (!has_volume_object) {
|
||||
/* Allocate space for at least one volume object. */
|
||||
++volume_stack_size;
|
||||
}
|
||||
|
||||
has_volume_object = true;
|
||||
|
||||
if (volume_stack_size == MAX_VOLUME_STACK_SIZE) {
|
||||
break;
|
||||
@@ -668,6 +685,8 @@ int Scene::get_volume_stack_size() const
|
||||
|
||||
volume_stack_size = min(volume_stack_size, MAX_VOLUME_STACK_SIZE);
|
||||
|
||||
VLOG(3) << "Detected required volume stack size " << volume_stack_size;
|
||||
|
||||
return volume_stack_size;
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user