From 21668359b79bd4a44a1f34e479a7bd8072ecdc69 Mon Sep 17 00:00:00 2001 From: Sergey Sharybin Date: Wed, 3 Jul 2019 15:15:11 +0200 Subject: Fix T66234: Issue on switching material mode between Object and Data The root of the issue comes to the fact that part of dependency graph is being removed, without doing any further remapping. This was happening because only materials used by objects were pulled in, so when material mode is changed some material became unused and removed from the dependency graph and freed, causing object or its data to point to a freed memory in its materials array. Simplest and safest way to solve this is to pull materials referenced by both object and object data. This causes somewhat higher memory usage but keeps evaluated state of scene in an always consistent state, without any need to tag/update object's data on material mode change. Don't think it is a problem in practice. Reviewers: brecht, fclem Reviewed By: brecht, fclem Differential Revision: https://developer.blender.org/D5172 --- .../depsgraph/intern/builder/deg_builder_nodes.cc | 25 +++++++++++++++------- .../depsgraph/intern/builder/deg_builder_nodes.h | 1 + .../intern/builder/deg_builder_relations.cc | 25 +++++++++++++++------- .../intern/builder/deg_builder_relations.h | 1 + 4 files changed, 36 insertions(+), 16 deletions(-) diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc index 9b02f231be4..46a1ea17041 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.cc @@ -697,6 +697,12 @@ void DepsgraphNodeBuilder::build_object_data(Object *object, bool is_object_visi break; } } + /* Materials. */ + Material ***materials_ptr = give_matarar(object); + if (materials_ptr != NULL) { + short *num_materials_ptr = give_totcolp(object); + build_materials(*materials_ptr, *num_materials_ptr); + } } void DepsgraphNodeBuilder::build_object_data_camera(Object *object) @@ -1195,14 +1201,7 @@ void DepsgraphNodeBuilder::build_object_data_geometry(Object *object, bool is_ob function_bind(BKE_object_eval_uber_data, _1, scene_cow, object_cow)); op_node->set_as_exit(); /* Materials. */ - if (object->totcol != 0) { - for (int a = 1; a <= object->totcol; a++) { - Material *ma = give_current_material(object, a); - if (ma != NULL) { - build_material(ma); - } - } - } + build_materials(object->mat, object->totcol); /* Point caches. */ build_object_pointcache(object); /* Geometry. */ @@ -1434,6 +1433,16 @@ void DepsgraphNodeBuilder::build_material(Material *material) build_nodetree(material->nodetree); } +void DepsgraphNodeBuilder::build_materials(Material **materials, int num_materials) +{ + for (int i = 0; i < num_materials; ++i) { + if (materials[i] == NULL) { + continue; + } + build_material(materials[i]); + } +} + /* Recursively build graph for texture */ void DepsgraphNodeBuilder::build_texture(Tex *texture) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h index 9983b346355..de9f0e4d6cd 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_nodes.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_nodes.h @@ -202,6 +202,7 @@ class DepsgraphNodeBuilder : public DepsgraphBuilder { void build_light(Light *lamp); void build_nodetree(bNodeTree *ntree); void build_material(Material *ma); + void build_materials(Material **materials, int num_materials); void build_texture(Tex *tex); void build_image(Image *image); void build_world(World *world); diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc index c2216e068fc..d2f06136b7e 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.cc +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.cc @@ -751,6 +751,12 @@ void DepsgraphRelationBuilder::build_object_data(Object *object) add_relation(key_key, geometry_key, "Shapekeys"); build_nested_shapekey(&object->id, key); } + /* Materials. */ + Material ***materials_ptr = give_matarar(object); + if (materials_ptr != NULL) { + short *num_materials_ptr = give_totcolp(object); + build_materials(*materials_ptr, *num_materials_ptr); + } } void DepsgraphRelationBuilder::build_object_data_camera(Object *object) @@ -1934,14 +1940,7 @@ void DepsgraphRelationBuilder::build_object_data_geometry(Object *object) } } /* Materials. */ - if (object->totcol) { - for (int a = 1; a <= object->totcol; a++) { - Material *ma = give_current_material(object, a); - if (ma != NULL) { - build_material(ma); - } - } - } + build_materials(object->mat, object->totcol); /* Geometry collision. */ if (ELEM(object->type, OB_MESH, OB_CURVE, OB_LATTICE)) { // add geometry collider relations @@ -2236,6 +2235,16 @@ void DepsgraphRelationBuilder::build_material(Material *material) } } +void DepsgraphRelationBuilder::build_materials(Material **materials, int num_materials) +{ + for (int i = 0; i < num_materials; ++i) { + if (materials[i] == NULL) { + continue; + } + build_material(materials[i]); + } +} + /* Recursively build graph for texture */ void DepsgraphRelationBuilder::build_texture(Tex *texture) { diff --git a/source/blender/depsgraph/intern/builder/deg_builder_relations.h b/source/blender/depsgraph/intern/builder/deg_builder_relations.h index 257cae7d127..0e15818622f 100644 --- a/source/blender/depsgraph/intern/builder/deg_builder_relations.h +++ b/source/blender/depsgraph/intern/builder/deg_builder_relations.h @@ -264,6 +264,7 @@ class DepsgraphRelationBuilder : public DepsgraphBuilder { void build_light(Light *lamp); void build_nodetree(bNodeTree *ntree); void build_material(Material *ma); + void build_materials(Material **materials, int num_materials); void build_texture(Tex *tex); void build_image(Image *image); void build_gpencil(bGPdata *gpd); -- cgit v1.2.3