Summary:
Made objects update happening from multiple threads. It is a task-based
scheduling system which uses current dependency graph for spawning new
tasks. This means threading happens on object level, but the system is
flexible enough for higher granularity.
Technical details:
- Uses task scheduler which was recently committed to trunk
(that one which Brecht ported from Cycles).
- Added two utility functions to dependency graph:
* DAG_threaded_update_begin, which is called to initialize threaded
objects update. It will also schedule root DAG node to the queue,
hence starting evaluation process.
Initialization will calculate how much parents are to be evaluation
before current DAG node can be scheduled. This value is used by task
threads for faster detecting which nodes might be scheduled.
* DAG_threaded_update_handle_node_updated which is called from task
thread function when node was fully handled.
This function decreases num_pending_parents of node children and
schedules children with zero valency.
As it might have become clear, task thread receives DAG nodes and
decides which callback to call for it.
Currently only BKE_object_handle_update is called for object nodes.
In the future it'll call node->callback() from Ali's new DAG.
- This required adding some workarounds to the render pipeline.
Mainly to stop using get_object_dm() from modifiers' apply callback.
Such a call was only a workaround for dependency graph glitch when
rendering scene with, say, boolean modifiers before displaying
this scene.
Such change moves workaround from one place to another, so overall
hackentropy remains the same.
- Added paradigm of EvaluaitonContext. Currently it's more like just a
more reliable replacement for G.is_rendering which fails in some
circumstances.
Future idea of this context is to also store all the local data needed
for objects evaluation such as local time, Copy-on-Write data and so.
There're two types of EvaluationContext:
* Context used for viewport updated and owned by Main. In the future
this context might be easily moved to Window or Screen to allo
per-window/per-screen local time.
* Context used by render engines to evaluate objects for render purposes.
Render engine is an owner of this context.
This context is passed to all object update routines.
Reviewers: brecht, campbellbarton
Reviewed By: brecht
CC: lukastoenne
Differential Revision: https://developer.blender.org/D94
152 lines
4.6 KiB
C++
152 lines
4.6 KiB
C++
/*
|
|
* ***** BEGIN GPL LICENSE BLOCK *****
|
|
*
|
|
* 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) 2004 Blender Foundation.
|
|
* All rights reserved.
|
|
*
|
|
* Contributor(s): none yet.
|
|
*
|
|
* ***** END GPL LICENSE BLOCK *****
|
|
*/
|
|
|
|
/** \file blender/blenkernel/depsgraph_private.h
|
|
* \ingroup bke
|
|
*/
|
|
|
|
#ifndef __DEPSGRAPH_PRIVATE_H__
|
|
#define __DEPSGRAPH_PRIVATE_H__
|
|
|
|
#include "BKE_depsgraph.h"
|
|
#include "DNA_constraint_types.h"
|
|
#include "BKE_constraint.h"
|
|
|
|
/* **** DAG relation types *** */
|
|
|
|
/* scene link to object */
|
|
#define DAG_RL_SCENE (1 << 0)
|
|
/* object link to data */
|
|
#define DAG_RL_DATA (1 << 1)
|
|
|
|
/* object changes object (parent, track, constraints) */
|
|
#define DAG_RL_OB_OB (1 << 2)
|
|
/* object changes obdata (hooks, constraints) */
|
|
#define DAG_RL_OB_DATA (1 << 3)
|
|
/* data changes object (vertex parent) */
|
|
#define DAG_RL_DATA_OB (1 << 4)
|
|
/* data changes data (deformers) */
|
|
#define DAG_RL_DATA_DATA (1 << 5)
|
|
|
|
#define DAG_NO_RELATION (1 << 6)
|
|
|
|
#define DAG_RL_ALL_BUT_DATA (DAG_RL_SCENE | DAG_RL_OB_OB | DAG_RL_OB_DATA | DAG_RL_DATA_OB | DAG_RL_DATA_DATA)
|
|
#define DAG_RL_ALL (DAG_RL_ALL_BUT_DATA | DAG_RL_DATA)
|
|
|
|
|
|
#define DAGQUEUEALLOC 50
|
|
|
|
enum {
|
|
DAG_WHITE = 0,
|
|
DAG_GRAY = 1,
|
|
DAG_BLACK = 2
|
|
};
|
|
|
|
typedef struct DagAdjList {
|
|
struct DagNode *node;
|
|
short type;
|
|
int count; /* number of identical arcs */
|
|
unsigned int lay; // for flushing redraw/rebuild events
|
|
const char *name;
|
|
struct DagAdjList *next;
|
|
} DagAdjList;
|
|
|
|
|
|
typedef struct DagNode {
|
|
int color;
|
|
short type;
|
|
float x, y, k;
|
|
void *ob;
|
|
void *first_ancestor;
|
|
int ancestor_count;
|
|
unsigned int lay; /* accumulated layers of its relations + itself */
|
|
unsigned int scelay; /* layers due to being in scene */
|
|
uint64_t customdata_mask; /* customdata mask */
|
|
int lasttime; /* if lasttime != DagForest->time, this node was not evaluated yet for flushing */
|
|
int BFS_dist; /* BFS distance */
|
|
int DFS_dist; /* DFS distance */
|
|
int DFS_dvtm; /* DFS discovery time */
|
|
int DFS_fntm; /* DFS Finishing time */
|
|
struct DagAdjList *child;
|
|
struct DagAdjList *parent;
|
|
struct DagNode *next;
|
|
|
|
/* Threaded evaluation routines */
|
|
uint32_t num_pending_parents; /* number of parents which are not updated yet
|
|
* this node has got.
|
|
* Used by threaded update for faster detect whether node could be
|
|
* updated aready.
|
|
*/
|
|
bool tag, scheduled;
|
|
} DagNode;
|
|
|
|
typedef struct DagNodeQueueElem {
|
|
struct DagNode *node;
|
|
struct DagNodeQueueElem *next;
|
|
} DagNodeQueueElem;
|
|
|
|
typedef struct DagNodeQueue {
|
|
DagNodeQueueElem *first;
|
|
DagNodeQueueElem *last;
|
|
int count;
|
|
int maxlevel;
|
|
struct DagNodeQueue *freenodes;
|
|
} DagNodeQueue;
|
|
|
|
// forest as we may have more than one DAG unnconected
|
|
typedef struct DagForest {
|
|
ListBase DagNode;
|
|
struct GHash *nodeHash;
|
|
int numNodes;
|
|
int is_acyclic;
|
|
int time; /* for flushing/tagging, compare with node->lasttime */
|
|
} DagForest;
|
|
|
|
|
|
// queue operations
|
|
DagNodeQueue *queue_create(int slots);
|
|
void queue_raz(DagNodeQueue *queue);
|
|
void push_queue(DagNodeQueue *queue, DagNode *node);
|
|
void push_stack(DagNodeQueue *queue, DagNode *node);
|
|
DagNode *pop_queue(DagNodeQueue *queue);
|
|
DagNode *get_top_node_queue(DagNodeQueue *queue);
|
|
void queue_delete(DagNodeQueue *queue);
|
|
|
|
// Dag management
|
|
DagForest *dag_init(void);
|
|
DagForest *build_dag(struct Main *bmain, struct Scene *sce, short mask);
|
|
void free_forest(struct DagForest *Dag);
|
|
DagNode *dag_find_node(DagForest *forest, void *fob);
|
|
DagNode *dag_add_node(DagForest *forest, void *fob);
|
|
DagNode *dag_get_node(DagForest *forest, void *fob);
|
|
DagNode *dag_get_sub_node(DagForest *forest, void *fob);
|
|
void dag_add_relation(DagForest *forest, DagNode *fob1, DagNode *fob2, short rel, const char *name);
|
|
|
|
void graph_print_queue(DagNodeQueue *nqueue);
|
|
void graph_print_queue_dist(DagNodeQueue *nqueue);
|
|
void graph_print_adj_list(DagForest *dag);
|
|
|
|
#endif /* __DEPSGRAPH_PRIVATE_H__ */
|