Depsgraph: Bind base by it's index
For the performance we convert object bases list to an array during view layer evaluation. This makes it possible to have very cheap index-based base lookup. The goal of this change is to get rid of base used for function binding, and avoid scene datablock expansion at the depsgraph construction time.
This commit is contained in:
@@ -247,7 +247,7 @@ void BKE_object_data_select_update(
|
||||
|
||||
void BKE_object_eval_flush_base_flags(
|
||||
const struct EvaluationContext *eval_ctx,
|
||||
struct Object *object, struct Base *base,
|
||||
struct Object *object, int base_index,
|
||||
const bool is_from_set);
|
||||
|
||||
void BKE_object_handle_data_update(
|
||||
|
||||
@@ -216,6 +216,8 @@ void BKE_view_layer_free_ex(ViewLayer *view_layer, const bool do_id_user)
|
||||
MEM_freeN(view_layer->id_properties);
|
||||
}
|
||||
|
||||
MEM_SAFE_FREE(view_layer->object_bases_array);
|
||||
|
||||
MEM_freeN(view_layer);
|
||||
}
|
||||
|
||||
@@ -503,6 +505,8 @@ void BKE_view_layer_copy_data(
|
||||
view_layer_dst->basact = base_dst;
|
||||
}
|
||||
}
|
||||
|
||||
view_layer_dst->object_bases_array = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -2358,11 +2362,19 @@ static void layer_eval_layer_collection(const EvaluationContext *eval_ctx,
|
||||
static void layer_eval_layer_collection_post(ViewLayer *view_layer)
|
||||
{
|
||||
DEG_debug_print_eval(__func__, view_layer->name, view_layer);
|
||||
/* if base is not selectabled, clear select */
|
||||
/* Create array of bases, for fast index-based lookup. */
|
||||
const int num_object_bases = BLI_listbase_count(&view_layer->object_bases);
|
||||
MEM_SAFE_FREE(view_layer->object_bases_array);
|
||||
view_layer->object_bases_array = MEM_malloc_arrayN(
|
||||
num_object_bases, sizeof(Base *), "view_layer->object_bases_array");
|
||||
int base_index = 0;
|
||||
for (Base *base = view_layer->object_bases.first; base; base = base->next) {
|
||||
/* if base is not selectabled, clear select. */
|
||||
if ((base->flag & BASE_SELECTABLED) == 0) {
|
||||
base->flag &= ~BASE_SELECTED;
|
||||
}
|
||||
/* Store base in the array. */
|
||||
view_layer->object_bases_array[base_index++] = base;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
@@ -433,9 +433,16 @@ void BKE_object_data_select_update(const EvaluationContext *UNUSED(eval_ctx),
|
||||
}
|
||||
}
|
||||
|
||||
void BKE_object_eval_flush_base_flags(const EvaluationContext *UNUSED(eval_ctx),
|
||||
Object *object, Base *base, bool is_from_set)
|
||||
void BKE_object_eval_flush_base_flags(const EvaluationContext *eval_ctx,
|
||||
Object *object, int base_index, bool is_from_set)
|
||||
{
|
||||
ViewLayer *view_layer = eval_ctx->view_layer;
|
||||
BLI_assert(view_layer->object_bases_array != NULL);
|
||||
BLI_assert(base_index >= 0);
|
||||
BLI_assert(base_index < MEM_allocN_len(view_layer->object_bases_array) / sizeof(Base *));
|
||||
Base *base = view_layer->object_bases_array[base_index];
|
||||
BLI_assert(base->object == object);
|
||||
|
||||
DEG_debug_print_eval(__func__, object->id.name, object);
|
||||
|
||||
/* Make sure we have the base collection settings is already populated.
|
||||
|
||||
@@ -6217,6 +6217,7 @@ static void direct_link_view_layer(FileData *fd, ViewLayer *view_layer)
|
||||
view_layer->properties_evaluated = NULL;
|
||||
|
||||
BLI_listbase_clear(&view_layer->drawdata);
|
||||
view_layer->object_bases_array = NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@@ -136,6 +136,7 @@ DepsgraphNodeBuilder::DepsgraphNodeBuilder(Main *bmain, Depsgraph *graph)
|
||||
: bmain_(bmain),
|
||||
graph_(graph),
|
||||
scene_(NULL),
|
||||
view_layer_(NULL),
|
||||
cow_id_hash_(NULL)
|
||||
{
|
||||
}
|
||||
@@ -399,7 +400,7 @@ void DepsgraphNodeBuilder::build_group(Group *group)
|
||||
}
|
||||
/* Build group objects. */
|
||||
LISTBASE_FOREACH (Base *, base, &group->view_layer->object_bases) {
|
||||
build_object(NULL, base->object, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, base->object, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
/* Operation to evaluate the whole view layer.
|
||||
*
|
||||
@@ -417,7 +418,7 @@ void DepsgraphNodeBuilder::build_group(Group *group)
|
||||
DEG_OPCODE_VIEW_LAYER_EVAL);
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_object(Base *base,
|
||||
void DepsgraphNodeBuilder::build_object(int base_index,
|
||||
Object *object,
|
||||
eDepsNode_LinkedState_Type linked_state)
|
||||
{
|
||||
@@ -429,7 +430,7 @@ void DepsgraphNodeBuilder::build_object(Base *base,
|
||||
* directly.
|
||||
*/
|
||||
if (id_node->linked_state == DEG_ID_LINKED_INDIRECTLY) {
|
||||
build_object_flags(base, object, linked_state);
|
||||
build_object_flags(base_index, object, linked_state);
|
||||
}
|
||||
id_node->linked_state = max(id_node->linked_state, linked_state);
|
||||
return;
|
||||
@@ -439,12 +440,12 @@ void DepsgraphNodeBuilder::build_object(Base *base,
|
||||
id_node->linked_state = linked_state;
|
||||
object->customdata_mask = 0;
|
||||
/* Various flags, flushing from bases/collections. */
|
||||
build_object_flags(base, object, linked_state);
|
||||
build_object_flags(base_index, object, linked_state);
|
||||
/* Transform. */
|
||||
build_object_transform(object);
|
||||
/* Parent. */
|
||||
if (object->parent != NULL) {
|
||||
build_object(NULL, object->parent, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, object->parent, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
/* Modifiers. */
|
||||
if (object->modifiers.first != NULL) {
|
||||
@@ -483,7 +484,7 @@ void DepsgraphNodeBuilder::build_object(Base *base,
|
||||
/* Object that this is a proxy for. */
|
||||
if (object->proxy) {
|
||||
object->proxy->proxy_from = object;
|
||||
build_object(NULL, object->proxy, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, object->proxy, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
/* Object dupligroup. */
|
||||
if (object->dup_group != NULL) {
|
||||
@@ -492,11 +493,11 @@ void DepsgraphNodeBuilder::build_object(Base *base,
|
||||
}
|
||||
|
||||
void DepsgraphNodeBuilder::build_object_flags(
|
||||
Base *base,
|
||||
int base_index,
|
||||
Object *object,
|
||||
eDepsNode_LinkedState_Type linked_state)
|
||||
{
|
||||
if (base == NULL) {
|
||||
if (base_index == -1) {
|
||||
return;
|
||||
}
|
||||
/* TODO(sergey): Is this really best component to be used? */
|
||||
@@ -505,7 +506,9 @@ void DepsgraphNodeBuilder::build_object_flags(
|
||||
add_operation_node(&object->id,
|
||||
DEG_NODE_TYPE_LAYER_COLLECTIONS,
|
||||
function_bind(BKE_object_eval_flush_base_flags,
|
||||
_1, object_cow, base, is_from_set),
|
||||
_1,
|
||||
object_cow, base_index,
|
||||
is_from_set),
|
||||
DEG_OPCODE_OBJECT_BASE_FLAGS);
|
||||
}
|
||||
|
||||
@@ -877,7 +880,7 @@ void DepsgraphNodeBuilder::build_particles(Object *object)
|
||||
switch (part->ren_as) {
|
||||
case PART_DRAW_OB:
|
||||
if (part->dup_ob != NULL) {
|
||||
build_object(NULL,
|
||||
build_object(-1,
|
||||
part->dup_ob,
|
||||
DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
@@ -1083,13 +1086,13 @@ void DepsgraphNodeBuilder::build_obdata_geom(Object *object)
|
||||
*/
|
||||
Curve *cu = (Curve *)obdata;
|
||||
if (cu->bevobj != NULL) {
|
||||
build_object(NULL, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, cu->bevobj, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
if (cu->taperobj != NULL) {
|
||||
build_object(NULL, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, cu->taperobj, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
if (object->type == OB_FONT && cu->textoncurve != NULL) {
|
||||
build_object(NULL, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, cu->textoncurve, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
break;
|
||||
}
|
||||
@@ -1208,7 +1211,7 @@ void DepsgraphNodeBuilder::build_nodetree(bNodeTree *ntree)
|
||||
build_image((Image *)id);
|
||||
}
|
||||
else if (id_type == ID_OB) {
|
||||
build_object(NULL, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, (Object *)id, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
else if (id_type == ID_SCE) {
|
||||
/* Scenes are used by compositor trees, and handled by render
|
||||
@@ -1405,7 +1408,7 @@ void DepsgraphNodeBuilder::modifier_walk(void *user_data,
|
||||
}
|
||||
switch (GS(id->name)) {
|
||||
case ID_OB:
|
||||
data->builder->build_object(NULL,
|
||||
data->builder->build_object(-1,
|
||||
(Object *)id,
|
||||
DEG_ID_LINKED_INDIRECTLY);
|
||||
break;
|
||||
@@ -1430,7 +1433,7 @@ void DepsgraphNodeBuilder::constraint_walk(bConstraint * /*con*/,
|
||||
}
|
||||
switch (GS(id->name)) {
|
||||
case ID_OB:
|
||||
data->builder->build_object(NULL,
|
||||
data->builder->build_object(-1,
|
||||
(Object *)id,
|
||||
DEG_ID_LINKED_INDIRECTLY);
|
||||
break;
|
||||
|
||||
@@ -171,10 +171,10 @@ struct DepsgraphNodeBuilder {
|
||||
ViewLayer *view_layer,
|
||||
eDepsNode_LinkedState_Type linked_state);
|
||||
void build_group(Group *group);
|
||||
void build_object(Base *base,
|
||||
void build_object(int base_index,
|
||||
Object *object,
|
||||
eDepsNode_LinkedState_Type linked_state);
|
||||
void build_object_flags(Base *base,
|
||||
void build_object_flags(int base_index,
|
||||
Object *object,
|
||||
eDepsNode_LinkedState_Type linked_state);
|
||||
void build_object_data(Object *object);
|
||||
@@ -242,6 +242,7 @@ protected:
|
||||
|
||||
/* State which demotes currently built entities. */
|
||||
Scene *scene_;
|
||||
ViewLayer *view_layer_;
|
||||
|
||||
GHash *cow_id_hash_;
|
||||
BuilderMap built_map_;
|
||||
|
||||
@@ -313,7 +313,7 @@ void DepsgraphNodeBuilder::build_rig(Object *object)
|
||||
|
||||
/* Custom shape. */
|
||||
if (pchan->custom != NULL) {
|
||||
build_object(NULL, pchan->custom, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, pchan->custom, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
|
||||
pchan_index++;
|
||||
|
||||
@@ -76,6 +76,7 @@ void DepsgraphNodeBuilder::build_view_layer(
|
||||
add_time_source();
|
||||
/* Setup currently building context. */
|
||||
scene_ = scene;
|
||||
view_layer_ = view_layer;
|
||||
/* Expand Scene Cow datablock to get proper pointers to bases. */
|
||||
Scene *scene_cow;
|
||||
ViewLayer *view_layer_cow;
|
||||
@@ -112,17 +113,19 @@ void DepsgraphNodeBuilder::build_view_layer(
|
||||
* but object is expected to be an original one. Hence we go into some
|
||||
* tricks here iterating over the view layer.
|
||||
*/
|
||||
int base_index = 0;
|
||||
for (Base *base_orig = (Base *)view_layer->object_bases.first,
|
||||
*base_cow = (Base *)view_layer_cow->object_bases.first;
|
||||
base_orig != NULL;
|
||||
base_orig = base_orig->next, base_cow = base_cow->next)
|
||||
{
|
||||
/* object itself */
|
||||
build_object(base_cow, base_orig->object, linked_state);
|
||||
build_object(base_index, base_orig->object, linked_state);
|
||||
base_orig->object->select_color = select_color++;
|
||||
++base_index;
|
||||
}
|
||||
if (scene->camera != NULL) {
|
||||
build_object(NULL, scene->camera, DEG_ID_LINKED_INDIRECTLY);
|
||||
build_object(-1, scene->camera, DEG_ID_LINKED_INDIRECTLY);
|
||||
}
|
||||
/* Rigidbody. */
|
||||
if (scene->rigidbody_world != NULL) {
|
||||
|
||||
@@ -97,6 +97,7 @@ typedef struct ViewLayer {
|
||||
|
||||
/* Runtime data */
|
||||
ListBase drawdata; /* ViewLayerEngineData */
|
||||
struct Base **object_bases_array;
|
||||
} ViewLayer;
|
||||
|
||||
typedef struct SceneCollection {
|
||||
|
||||
Reference in New Issue
Block a user