Getting vfont data wasn't safe for threading, because it
was modifying font data which is in bmain and could be
shared by multiple objects.
For now made it so getting vfont uses critical section,
meaning vfont->data is initializing from inside a locked
mutex.
Object update used to free object-data level bounding box to trigger
it's re-calculation in the future. Such a freeing performed from
object update isn't thread-safe because mesh could be shared between
multiple objects.
Rather than freeing bounding box, tag it's as invalid, this is safe
from threading point of view and also prevents unnecessary memory
re-allocation.
Object-level bounding box is still reallocating, but think we could
change this easily in the future as well.
Curve-type objects now always does have object'level
bounding box, meaning cu->bb wouldn't evenr used in
BKE_object_minmax.
So zapping this confusing check for whether ob->bb
exists, which is always truth. Makes it easier to
follow what cu->bb is for and what ob->bb is for.
Issue was caused by size influence affecting on object's matrix, which
is nice by it's own. But mball code was using ob->size to check whether
it's zero-sized object or not, but then was using ob->obmat to scale
the meta elements.
This lead to situation when zero-sized elements were trying to tessellate,
which is for sure a really bad idea.
There's one thing we didn't foresee from the beginning,
which is apparently TLS is only available in OSX starting
from version 10.7, and we still do support of 10.6.
After recent Brecht's changes about locked viewport
while initializing BI render this TLS is not needed
in trunk anymore. So reverting this chunk of base
iteration to use static variable. But leaving all the
other static variables warped into context still, it
should help a bit in the future refactor.
Real fix would be to have some kind of graph context
evaluation structure which would be passing to update
routines (which will solve threaded mballs update) and
making depsgraph responsible for getting a motherball.
But this is all for GSoC project.
This time issue was caused by static variables used in
BKE_scene_base_iter_next function.
Change is not so much ultimate actually, but didn't
find more clear solution for now. So the changes are:
- Wrap almost all the static variables into own context-
like structure, which is owned by the callee function
and getting passed to the iteration function.
- Recursion detection wasn't possible with such approach,
so recursion detection still uses static in_next_object
variable, but which is now stored in thread local
storage (TLS, or thread variable if this names are more
clear for you).
This makes code thread-safe, but for sure final solution
shall be completely different. Ideally, dependency graph
shall be possible to answer on question "which object is
a motherball for this metaball". This will avoid iterating
via all the bases, objects and duplis just to get needed
motherball.
Further, metaball evaluation ideally will use the same
kind of depsgraph filtering, which will get result for
question like "which objects belongs to this group of
metaballs".
But this ideal things are to be solved in Joshua's and
mind GSoC projects.
Tested on linux (gcc and clang) and windows (msvc2008),
hopefully no compilation error will happen.
Thanks to Brecht for reviewing the change and getting
feedback for other possible ways we've dicussed!
the way Curve.len is used at the moment is really stupid, calculate string size on save for now, but should really store the length in bytes and total number of characters.
Some objects from scene could have dupligroup with objects
which are not in the scene. This case wasn't checked by
workaround for threaded display object free routines.
We really need to have threading issues with display
objects solved.
This is not the nicest behaviour but trying to keep both bullet and
blender side objects in sync breaks in this case.
There might be a better soluion but this avoids crashes for now.
Fixes: [#35995] Delete crash on specific scene (Physics)
Now modifier stack wouldn't modify original curve's nurbs
and will operate on a copy of nurbs.
This makes it possible to process curve object update with
shared curve datablocks from multiple threads. There's no
big overhead for creating a copy of nurbs comparing to old
behavior which was allocating original vertex array and
apply coordinates on curve after all modifier are applied.
The only remained issue with curves is curve's bounding box
and texture space. It's not thread-safe, but it wouldn't
lead to crashes -- it just could lead to either memory
leak or wrong texture coordinates due to difference in
modifiers stacks of objects which shares the same curve.
DAG node already has got type field, so we could just check whether
type is ID_OB to distinguish whether object_handle_update need to
be called for node->ob.
This saves iterating via scene's bases when preparing threaded
update. This also will very much likely update objects which are
not in the scene base are used in dupli groups.
So now objects form dupli_groups are likely already properly updated
white traversing the DAG with threaded update and special hacks
are needed from main thread to update objects from dupli_groups
which was added in previous commit.
However, kept this hack for a while, need some more thoughts
and investigation.
Dupli-groups used to have special case for updating
which is BKE_group_handle_recalc_and_update. This
function calls BKE_object_handle_update for every
object in the group.
This isn't thread-safe, because object could be
updating in separate thread already. And what's
worse dependencies are not known for objects inside
the group, which makes it impossible to schedule
objects from the group in a safe way.
It's even impossible to schedule groups as different
tasks, because groups could share the same objects.
For now used simple but robust solution which is
updating dupli-groups in main thread, handling
groups one-by-one and updating objects from the
group one-by-one as well.
Will work on a proper solution for this later.
I know this is not so much nice to have this guys hanging
around in a general Object datablock and ideally they better
be wrapped around into a structure like DerivedMesh or
something like this. But this is pure runtime only stuff and
we could re-wrap them around later.
Main purpose of this is making curves more thread safe,
so no separate threads will ever start freeing the same path
or the same bevel list.
It also makes sense because path and bevel shall include
deformation coming from modifiers which are applying on
pre-tesselation point and different objects could have
different set of modifiers. This used to be really confusing
in the past and now dtaa which depends on object is stored
in an object, making things clear for understanding even.
This doesn't make curve code fully thread-safe due to
pre-tesselation modifiers still modifies actual nurbs and
lock is still needed in makeDispListsCurveTypes, but this
change makes usage of paths safe for threading.
Once modifiers will stop modifying actual nurbs, curves
will be fully safe for threading.
Issue was caused by worker threads updating nodes valency
at the same time while we're filling the queue with "root"
nodes (leaf nodes which don't depend on others).
The tihng here is: curve is getting modified by modifier stack
and then it's coordinates are restored. To be really safe we
need to do all this locked.
Added threading lock around unsafe part of do_makeDispListCurveTypes
(parts which touches Curve->bev and Curve->path). Namely it means
pre-tesselation modifiers, bevel, path and non-modified display
list will be calculated inside a locked thread.
Post-tessellation modifiers will eb calculated outside of locked
thread, which means heavy constructive or deformation modifiers
applying on tesselated spline will be nicely threaded.
This makes it possible to use threaded object update by default
in the branch, so everyone could start testing it.
This display list was only used for texture space calculation,
and even there this display list was only used for bounding
box calulation.
Since we alreayd do have boundgind box in a curve datablock
there's no reason to duplicate non-modified display list
just to calculate bounding box later, let's just calculate
boundding box at the first point.
This makes code a little be more thread-safe but curves are
still not safe for threads at all because of bevel list and
path. That would be solved later.
It's not so much happening inside the lock and using spin
lock instead of mutex lock will give some speedup due to
smaller latency of resuming the thread when mutex was locked.