Depsgraph: Move RNA lookup to an own query class

Currently should have no functional changes, but allows to
implement runction optimizations more localized and easily.
This commit is contained in:
Sergey Sharybin 2019-02-15 12:45:56 +01:00
parent 373b8e311d
commit 0ecd587991
7 changed files with 340 additions and 257 deletions

View File

@ -47,6 +47,7 @@ set(SRC
intern/builder/deg_builder_relations_keys.cc
intern/builder/deg_builder_relations_rig.cc
intern/builder/deg_builder_relations_view_layer.cc
intern/builder/deg_builder_rna.cc
intern/builder/deg_builder_transitive.cc
intern/debug/deg_debug.cc
intern/debug/deg_debug_relations_graphviz.cc
@ -87,6 +88,7 @@ set(SRC
intern/builder/deg_builder_pchanmap.h
intern/builder/deg_builder_relations.h
intern/builder/deg_builder_relations_impl.h
intern/builder/deg_builder_rna.h
intern/builder/deg_builder_transitive.h
intern/debug/deg_debug.h
intern/eval/deg_eval.h

View File

@ -177,10 +177,10 @@ static bool check_id_has_anim_component(ID *id)
}
static OperationCode bone_target_opcode(ID *target,
const char *subtarget,
ID *id,
const char *component_subdata,
RootPChanMap *root_map)
const char *subtarget,
ID *id,
const char *component_subdata,
RootPChanMap *root_map)
{
/* Same armature. */
if (target == id) {
@ -212,7 +212,8 @@ DepsgraphRelationBuilder::DepsgraphRelationBuilder(Main *bmain,
Depsgraph *graph)
: bmain_(bmain),
graph_(graph),
scene_(NULL)
scene_(NULL),
rna_node_query_(graph)
{
}
@ -253,9 +254,9 @@ OperationNode *DepsgraphRelationBuilder::get_node(
return op_node;
}
Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key) const
Node *DepsgraphRelationBuilder::get_node(const RNAPathKey &key)
{
return graph_->find_node_from_pointer(&key.ptr, key.prop, key.source);
return rna_node_query_.find_node(&key.ptr, key.prop, key.source);
}
OperationNode *DepsgraphRelationBuilder::find_node(
@ -1260,7 +1261,7 @@ void DepsgraphRelationBuilder::build_animdata_curves_targets(
{
continue;
}
Node *node_to = graph_->find_node_from_pointer(
Node *node_to = rna_node_query_.find_node(
&ptr, prop, RNAPointerSource::ENTRY);
if (node_to == NULL) {
continue;

View File

@ -36,6 +36,7 @@
#include "BLI_string.h"
#include "intern/builder/deg_builder_map.h"
#include "intern/builder/deg_builder_rna.h"
#include "intern/depsgraph.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_component.h"
@ -298,7 +299,7 @@ protected:
TimeSourceNode *get_node(const TimeSourceKey &key) const;
ComponentNode *get_node(const ComponentKey &key) const;
OperationNode *get_node(const OperationKey &key) const;
Node *get_node(const RNAPathKey &key) const;
Node *get_node(const RNAPathKey &key);
OperationNode *find_node(const OperationKey &key) const;
bool has_node(const OperationKey &key) const;
@ -355,6 +356,7 @@ private:
Scene *scene_;
BuilderMap built_map_;
RNANodeQuery rna_node_query_;
};
struct DepsNodeHandle

View File

@ -0,0 +1,262 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file \ingroup depsgraph
*/
#include "intern/builder/deg_builder_rna.h"
#include <cstring>
#include "BLI_utildefines.h"
#include "BLI_listbase.h"
extern "C" {
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_sequence_types.h"
}
#include "BKE_constraint.h"
#include "RNA_access.h"
#include "intern/depsgraph.h"
#include "intern/node/deg_node.h"
#include "intern/node/deg_node_component.h"
#include "intern/node/deg_node_id.h"
#include "intern/node/deg_node_operation.h"
namespace DEG {
namespace {
bool pointer_to_component_node_criteria(
const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource /*source*/,
ID **id,
NodeType *type,
const char **component_name,
OperationCode *operation_code,
const char **operation_name,
int *operation_name_tag)
{
if (ptr->type == NULL) {
return false;
}
/* Set default values for returns. */
*id = (ID *)ptr->id.data;
*component_name = "";
*operation_code = OperationCode::OPERATION;
*operation_name = "";
*operation_name_tag = -1;
/* Handling of commonly known scenarios. */
if (ptr->type == &RNA_PoseBone) {
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
if (prop != NULL && RNA_property_is_idprop(prop)) {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::ID_PROPERTY;
*operation_name = RNA_property_identifier((PropertyRNA *)prop);
*operation_name_tag = -1;
}
else {
/* Bone - generally, we just want the bone component. */
*type = NodeType::BONE;
*component_name = pchan->name;
/* But B-Bone properties should connect to the actual operation. */
if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 &&
STRPREFIX(RNA_property_identifier(prop), "bbone_"))
{
*operation_code = OperationCode::BONE_SEGMENTS;
}
}
return true;
}
else if (ptr->type == &RNA_Bone) {
Bone *bone = (Bone *)ptr->data;
/* armature-level bone, but it ends up going to bone component anyway */
// NOTE: the ID in this case will end up being bArmature.
*type = NodeType::BONE;
*component_name = bone->name;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
Object *object = (Object *)ptr->id.data;
bConstraint *con = (bConstraint *)ptr->data;
/* Check whether is object or bone constraint. */
/* NOTE: Currently none of the area can address transform of an object
* at a given constraint, but for rigging one might use constraint
* influence to be used to drive some corrective shape keys or so. */
if (BLI_findindex(&object->constraints, con) != -1) {
*type = NodeType::TRANSFORM;
*operation_code = OperationCode::TRANSFORM_LOCAL;
return true;
}
else if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
*type = NodeType::BONE;
*operation_code = OperationCode::BONE_LOCAL;
*component_name = pchan->name;
return true;
}
}
}
}
else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) {
Object *object = (Object *)ptr->id.data;
bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
/* Check whether is object or bone constraint. */
bPoseChannel *pchan = NULL;
bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan);
if (con != NULL) {
if (pchan != NULL) {
*type = NodeType::BONE;
*operation_code = OperationCode::BONE_LOCAL;
*component_name = pchan->name;
}
else {
*type = NodeType::TRANSFORM;
*operation_code = OperationCode::TRANSFORM_LOCAL;
}
return true;
}
}
else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
*type = NodeType::GEOMETRY;
return true;
}
else if (ptr->type == &RNA_Object) {
/* Transforms props? */
if (prop != NULL) {
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
/* TODO(sergey): How to optimize this? */
if (strstr(prop_identifier, "location") ||
strstr(prop_identifier, "rotation") ||
strstr(prop_identifier, "scale") ||
strstr(prop_identifier, "matrix_"))
{
*type = NodeType::TRANSFORM;
return true;
}
else if (strstr(prop_identifier, "data")) {
/* We access object.data, most likely a geometry.
* Might be a bone tho. */
*type = NodeType::GEOMETRY;
return true;
}
}
}
else if (ptr->type == &RNA_ShapeKey) {
KeyBlock *key_block = (KeyBlock *)ptr->data;
*id = (ID *)ptr->id.data;
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::PARAMETERS_EVAL;
*operation_name = key_block->name;
return true;
}
else if (ptr->type == &RNA_Key) {
*id = (ID *)ptr->id.data;
*type = NodeType::GEOMETRY;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
Sequence *seq = (Sequence *)ptr->data;
/* Sequencer strip */
*type = NodeType::SEQUENCER;
*component_name = seq->name;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
*type = NodeType::SHADING;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
*type = NodeType::SHADING;
return true;
}
else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) {
*id = (ID *)ptr->id.data;
*type = NodeType::GEOMETRY;
return true;
}
if (prop != NULL) {
/* All unknown data effectively falls under "parameter evaluation". */
if (RNA_property_is_idprop(prop)) {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::ID_PROPERTY;
*operation_name = RNA_property_identifier((PropertyRNA *)prop);
*operation_name_tag = -1;
}
else {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::PARAMETERS_EVAL;
*operation_name = "";
*operation_name_tag = -1;
}
return true;
}
return false;
}
} // namespace
RNANodeQuery::RNANodeQuery(Depsgraph *depsgraph)
: depsgraph_(depsgraph)
{
}
Node *RNANodeQuery::find_node(const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource source)
{
ID *id;
NodeType node_type;
const char *component_name, *operation_name;
OperationCode operation_code;
int operation_name_tag;
if (pointer_to_component_node_criteria(
ptr, prop, source,
&id, &node_type, &component_name,
&operation_code, &operation_name, &operation_name_tag))
{
IDNode *id_node = depsgraph_->find_id_node(id);
if (id_node == NULL) {
return NULL;
}
ComponentNode *comp_node =
id_node->find_component(node_type, component_name);
if (comp_node == NULL) {
return NULL;
}
if (operation_code == OperationCode::OPERATION) {
return comp_node;
}
return comp_node->find_operation(operation_code,
operation_name,
operation_name_tag);
}
return NULL;
}
} // namespace DEG

View File

@ -0,0 +1,61 @@
/*
* This program is free software; you can redistribute it and/or
* modify it under the terms of the GNU General Public License
* as published by the Free Software Foundation; either version 2
* of the License, or (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software Foundation,
* Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
* The Original Code is Copyright (C) 2019 Blender Foundation.
* All rights reserved.
*/
/** \file \ingroup depsgraph
*/
#pragma once
struct PointerRNA;
struct PropertyRNA;
namespace DEG {
struct Depsgraph;
struct Node;
/* For queries which gives operation node or key defines whether we are
* interested in a result of the given property or whether we are linking some
* dependency to that property. */
enum class RNAPointerSource {
/* Query will return pointer to an entry operation of component which is
* responsible for evaluation of the given property. */
ENTRY,
/* Query will return pointer to an exit operation of component which is
* responsible for evaluation of the given property.
* More precisely, it will return operation at which the property is known
* to be evaluated. */
EXIT,
};
/* Helper class which performs optimized lookups of a node within a given
* dependency graph which satisfies given RNA pointer or RAN path. */
class RNANodeQuery {
public:
RNANodeQuery(Depsgraph *depsgraph);
Node *find_node(const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource source);
protected:
Depsgraph *depsgraph_;
};
} // namespace DEG

View File

@ -24,32 +24,21 @@
#include "intern/depsgraph.h" /* own include */
#include <algorithm>
#include <cstring>
#include "MEM_guardedalloc.h"
#include "BLI_utildefines.h"
#include "BLI_console.h"
#include "BLI_hash.h"
#include "BLI_ghash.h"
#include "BLI_listbase.h"
extern "C" {
#include "DNA_action_types.h"
#include "DNA_armature_types.h"
#include "DNA_constraint_types.h"
#include "DNA_key_types.h"
#include "DNA_object_types.h"
#include "DNA_sequence_types.h"
#include "RNA_access.h"
#include "BKE_scene.h"
#include "BKE_constraint.h"
#include "BKE_global.h"
}
#include <algorithm>
#include <cstring>
#include "DEG_depsgraph.h"
#include "DEG_depsgraph_debug.h"
@ -108,211 +97,6 @@ Depsgraph::~Depsgraph()
BLI_spin_end(&lock);
}
/* Query Conditions from RNA ----------------------- */
static bool pointer_to_component_node_criteria(
const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource /*source*/,
ID **id,
NodeType *type,
const char **component_name,
OperationCode *operation_code,
const char **operation_name,
int *operation_name_tag)
{
if (ptr->type == NULL) {
return false;
}
/* Set default values for returns. */
*id = (ID *)ptr->id.data;
*component_name = "";
*operation_code = OperationCode::OPERATION;
*operation_name = "";
*operation_name_tag = -1;
/* Handling of commonly known scenarios. */
if (ptr->type == &RNA_PoseBone) {
bPoseChannel *pchan = (bPoseChannel *)ptr->data;
if (prop != NULL && RNA_property_is_idprop(prop)) {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::ID_PROPERTY;
*operation_name = RNA_property_identifier((PropertyRNA *)prop);
*operation_name_tag = -1;
}
else {
/* Bone - generally, we just want the bone component. */
*type = NodeType::BONE;
*component_name = pchan->name;
/* But B-Bone properties should connect to the actual operation. */
if (!ELEM(NULL, pchan->bone, prop) && pchan->bone->segments > 1 &&
STRPREFIX(RNA_property_identifier(prop), "bbone_"))
{
*operation_code = OperationCode::BONE_SEGMENTS;
}
}
return true;
}
else if (ptr->type == &RNA_Bone) {
Bone *bone = (Bone *)ptr->data;
/* armature-level bone, but it ends up going to bone component anyway */
// NOTE: the ID in this case will end up being bArmature.
*type = NodeType::BONE;
*component_name = bone->name;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Constraint)) {
Object *object = (Object *)ptr->id.data;
bConstraint *con = (bConstraint *)ptr->data;
/* Check whether is object or bone constraint. */
/* NOTE: Currently none of the area can address transform of an object
* at a given constraint, but for rigging one might use constraint
* influence to be used to drive some corrective shape keys or so. */
if (BLI_findindex(&object->constraints, con) != -1) {
*type = NodeType::TRANSFORM;
*operation_code = OperationCode::TRANSFORM_LOCAL;
return true;
}
else if (object->pose != NULL) {
LISTBASE_FOREACH (bPoseChannel *, pchan, &object->pose->chanbase) {
if (BLI_findindex(&pchan->constraints, con) != -1) {
*type = NodeType::BONE;
*operation_code = OperationCode::BONE_LOCAL;
*component_name = pchan->name;
return true;
}
}
}
}
else if (ELEM(ptr->type, &RNA_ConstraintTarget, &RNA_ConstraintTargetBone)) {
Object *object = (Object *)ptr->id.data;
bConstraintTarget *tgt = (bConstraintTarget *)ptr->data;
/* Check whether is object or bone constraint. */
bPoseChannel *pchan = NULL;
bConstraint *con = BKE_constraint_find_from_target(object, tgt, &pchan);
if (con != NULL) {
if (pchan != NULL) {
*type = NodeType::BONE;
*operation_code = OperationCode::BONE_LOCAL;
*component_name = pchan->name;
}
else {
*type = NodeType::TRANSFORM;
*operation_code = OperationCode::TRANSFORM_LOCAL;
}
return true;
}
}
else if (RNA_struct_is_a(ptr->type, &RNA_Modifier)) {
*type = NodeType::GEOMETRY;
return true;
}
else if (ptr->type == &RNA_Object) {
/* Transforms props? */
if (prop != NULL) {
const char *prop_identifier = RNA_property_identifier((PropertyRNA *)prop);
/* TODO(sergey): How to optimize this? */
if (strstr(prop_identifier, "location") ||
strstr(prop_identifier, "rotation") ||
strstr(prop_identifier, "scale") ||
strstr(prop_identifier, "matrix_"))
{
*type = NodeType::TRANSFORM;
return true;
}
else if (strstr(prop_identifier, "data")) {
/* We access object.data, most likely a geometry.
* Might be a bone tho. */
*type = NodeType::GEOMETRY;
return true;
}
}
}
else if (ptr->type == &RNA_ShapeKey) {
KeyBlock *key_block = (KeyBlock *)ptr->data;
*id = (ID *)ptr->id.data;
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::PARAMETERS_EVAL;
*operation_name = key_block->name;
return true;
}
else if (ptr->type == &RNA_Key) {
*id = (ID *)ptr->id.data;
*type = NodeType::GEOMETRY;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_Sequence)) {
Sequence *seq = (Sequence *)ptr->data;
/* Sequencer strip */
*type = NodeType::SEQUENCER;
*component_name = seq->name;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_NodeSocket)) {
*type = NodeType::SHADING;
return true;
}
else if (RNA_struct_is_a(ptr->type, &RNA_ShaderNode)) {
*type = NodeType::SHADING;
return true;
}
else if (ELEM(ptr->type, &RNA_Curve, &RNA_TextCurve)) {
*id = (ID *)ptr->id.data;
*type = NodeType::GEOMETRY;
return true;
}
if (prop != NULL) {
/* All unknown data effectively falls under "parameter evaluation". */
if (RNA_property_is_idprop(prop)) {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::ID_PROPERTY;
*operation_name = RNA_property_identifier((PropertyRNA *)prop);
*operation_name_tag = -1;
}
else {
*type = NodeType::PARAMETERS;
*operation_code = OperationCode::PARAMETERS_EVAL;
*operation_name = "";
*operation_name_tag = -1;
}
return true;
}
return false;
}
/* Convenience wrapper to find node given just pointer + property. */
Node *Depsgraph::find_node_from_pointer(const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource source) const
{
ID *id;
NodeType node_type;
const char *component_name, *operation_name;
OperationCode operation_code;
int operation_name_tag;
if (pointer_to_component_node_criteria(
ptr, prop, source,
&id, &node_type, &component_name,
&operation_code, &operation_name, &operation_name_tag))
{
IDNode *id_node = find_id_node(id);
if (id_node == NULL) {
return NULL;
}
ComponentNode *comp_node =
id_node->find_component(node_type, component_name);
if (comp_node == NULL) {
return NULL;
}
if (operation_code == OperationCode::OPERATION) {
return comp_node;
}
return comp_node->find_operation(operation_code,
operation_name,
operation_name_tag);
}
return NULL;
}
/* Node Management ---------------------------- */
TimeSourceNode *Depsgraph::add_time_source()

View File

@ -45,8 +45,6 @@ struct GHash;
struct GSet;
struct ID;
struct Main;
struct PointerRNA;
struct PropertyRNA;
struct Scene;
struct ViewLayer;
@ -94,20 +92,6 @@ struct Relation {
int flag; /* Bitmask of RelationFlag) */
};
/* For queries which gives operation node or key defines whether we are
* interested in a result of the given property or whether we are linking some
* dependency to that property. */
enum class RNAPointerSource {
/* Query will return pointer to an entry operation of component which is
* responsible for evaluation of the given property. */
ENTRY,
/* Query will return pointer to an exit operation of component which is
* responsible for evaluation of the given property.
* More precisely, it will return operation at which the property is known
* to be evaluated. */
EXIT,
};
/* ********* */
/* Depsgraph */
@ -122,19 +106,6 @@ struct Depsgraph {
eEvaluationMode mode);
~Depsgraph();
/**
* Convenience wrapper to find node given just pointer + property.
*
* \param ptr: pointer to the data that node will represent
* \param prop: optional property affected - providing this effectively
* results in inner nodes being returned
*
* \return A node matching the required characteristics if it exists
* or NULL if no such node exists in the graph */
Node *find_node_from_pointer(const PointerRNA *ptr,
const PropertyRNA *prop,
RNAPointerSource source) const;
TimeSourceNode *add_time_source();
TimeSourceNode *find_time_source() const;