Fix T63588: Cycles unnecessarily updates background importance sampling map

With modifications by Brecht to solve T77273, crash enabling portal lights.
This commit is contained in:
Tautvydas Andrikys 2020-05-14 17:41:37 +02:00 committed by Brecht Van Lommel
parent 0465086223
commit ffb3365fb2
3 changed files with 46 additions and 15 deletions

@ -182,7 +182,10 @@ bool Light::has_contribution(Scene *scene)
LightManager::LightManager()
{
need_update = true;
need_update_background = true;
use_light_visibility = false;
last_background_enabled = false;
last_background_resolution = 0;
}
LightManager::~LightManager()
@ -202,7 +205,7 @@ bool LightManager::has_background_light(Scene *scene)
return false;
}
void LightManager::disable_ineffective_light(Scene *scene)
void LightManager::test_enabled_lights(Scene *scene)
{
/* Make all lights enabled by default, and perform some preliminary checks
* needed for finer-tuning of settings (for example, check whether we've
@ -215,6 +218,9 @@ void LightManager::disable_ineffective_light(Scene *scene)
has_background |= light->type == LIGHT_BACKGROUND;
}
bool background_enabled = false;
int background_resolution = 0;
if (has_background) {
/* Ignore background light if:
* - If unsupported on a device
@ -226,9 +232,18 @@ void LightManager::disable_ineffective_light(Scene *scene)
foreach (Light *light, scene->lights) {
if (light->type == LIGHT_BACKGROUND) {
light->is_enabled = !disable_mis;
background_enabled = !disable_mis;
background_resolution = light->map_resolution;
}
}
}
if (last_background_enabled != background_enabled ||
last_background_resolution != background_resolution) {
last_background_enabled = background_enabled;
last_background_resolution = background_resolution;
need_update_background = true;
}
}
bool LightManager::object_usable_as_light(Object *object)
@ -902,12 +917,13 @@ void LightManager::device_update(Device *device,
VLOG(1) << "Total " << scene->lights.size() << " lights.";
device_free(device, dscene);
/* Detect which lights are enabled, also determins if we need to update the background. */
test_enabled_lights(scene);
device_free(device, dscene, need_update_background);
use_light_visibility = false;
disable_ineffective_light(scene);
device_update_points(device, dscene, scene);
if (progress.get_cancel())
return;
@ -916,9 +932,11 @@ void LightManager::device_update(Device *device,
if (progress.get_cancel())
return;
device_update_background(device, dscene, scene, progress);
if (progress.get_cancel())
return;
if (need_update_background) {
device_update_background(device, dscene, scene, progress);
if (progress.get_cancel())
return;
}
device_update_ies(dscene);
if (progress.get_cancel())
@ -930,14 +948,17 @@ void LightManager::device_update(Device *device,
}
need_update = false;
need_update_background = false;
}
void LightManager::device_free(Device *, DeviceScene *dscene)
void LightManager::device_free(Device *, DeviceScene *dscene, const bool free_background)
{
dscene->light_distribution.free();
dscene->lights.free();
dscene->light_background_marginal_cdf.free();
dscene->light_background_conditional_cdf.free();
if (free_background) {
dscene->light_background_marginal_cdf.free();
dscene->light_background_conditional_cdf.free();
}
dscene->ies_lights.free();
}
@ -990,6 +1011,7 @@ int LightManager::add_ies(const string &content)
ies_slots[slot]->hash = hash;
need_update = true;
need_update_background = true;
return slot;
}
@ -1008,6 +1030,7 @@ void LightManager::remove_ies(int slot)
/* If the slot has no more users, update the device to remove it. */
need_update |= (ies_slots[slot]->users == 0);
need_update_background |= need_update;
}
void LightManager::device_update_ies(DeviceScene *dscene)

@ -88,6 +88,9 @@ class LightManager {
bool use_light_visibility;
bool need_update;
/* Need to update background (including multiple importance map) */
bool need_update_background;
LightManager();
~LightManager();
@ -97,7 +100,7 @@ class LightManager {
void remove_ies(int slot);
void device_update(Device *device, DeviceScene *dscene, Scene *scene, Progress &progress);
void device_free(Device *device, DeviceScene *dscene);
void device_free(Device *device, DeviceScene *dscene, const bool free_background = true);
void tag_update(Scene *scene);
@ -109,7 +112,7 @@ class LightManager {
* which doesn't contribute to the scene or which is only used for MIS
* and scene doesn't need MIS.
*/
void disable_ineffective_light(Scene *scene);
void test_enabled_lights(Scene *scene);
void device_update_points(Device *device, DeviceScene *dscene, Scene *scene);
void device_update_distribution(Device *device,
@ -133,6 +136,9 @@ class LightManager {
vector<IESSlot *> ies_slots;
thread_mutex ies_mutex;
bool last_background_enabled;
int last_background_resolution;
};
CCL_NAMESPACE_END

@ -318,9 +318,11 @@ void Shader::tag_update(Scene *scene)
* has use_mis set to false. We are quite close to release now, so
* better to be safe.
*/
if (this == scene->background->get_shader(scene) &&
scene->light_manager->has_background_light(scene)) {
scene->light_manager->need_update = true;
if (this == scene->background->get_shader(scene)) {
scene->light_manager->need_update_background = true;
if (scene->light_manager->has_background_light(scene)) {
scene->light_manager->need_update = true;
}
}
/* quick detection of which kind of shaders we have to avoid loading