瀏覽代碼

Guard against drawable updates being inserted during threaded drawable update. Add these to separate container and process later. Inspired by PR work submitted by guijun.

Lasse Öörni 9 年之前
父節點
當前提交
32904aefec
共有 2 個文件被更改,包括 29 次插入1 次删除
  1. 27 1
      Source/Urho3D/Graphics/Octree.cpp
  2. 2 0
      Source/Urho3D/Graphics/Octree.h

+ 27 - 1
Source/Urho3D/Graphics/Octree.cpp

@@ -374,6 +374,12 @@ void Octree::SetSize(const BoundingBox& box, unsigned numLevels)
 
 void Octree::Update(const FrameInfo& frame)
 {
+    if (!Thread::IsMainThread())
+    {
+        URHO3D_LOGERROR("Octree::Update() can not be called from worker threads");
+        return;
+    }
+
     // Let drawables update themselves before reinsertion. This can be used for animation
     if (!drawableUpdates_.Empty())
     {
@@ -412,6 +418,24 @@ void Octree::Update(const FrameInfo& frame)
         scene->EndThreadedUpdate();
     }
 
+    // If any drawables were inserted during threaded update, update them now from the main thread
+    if (!threadedDrawableUpdates_.Empty())
+    {
+        URHO3D_PROFILE(UpdateDrawablesQueuedDuringUpdate);
+
+        for (PODVector<Drawable*>::ConstIterator i = threadedDrawableUpdates_.Begin(); i != threadedDrawableUpdates_.End(); ++i)
+        {
+            Drawable* drawable = *i;
+            if (drawable)
+            {
+                drawable->Update(frame);
+                drawableUpdates_.Push(drawable);
+            }
+        }
+
+        threadedDrawableUpdates_.Clear();
+    }
+
     // Notify drawable update being finished. Custom animation (eg. IK) can be done at this point
     Scene* scene = GetScene();
     if (scene)
@@ -540,7 +564,7 @@ void Octree::QueueUpdate(Drawable* drawable)
     if (scene && scene->IsThreadedUpdate())
     {
         MutexLock lock(octreeMutex_);
-        drawableUpdates_.Push(drawable);
+        threadedDrawableUpdates_.Push(drawable);
     }
     else
         drawableUpdates_.Push(drawable);
@@ -550,6 +574,8 @@ void Octree::QueueUpdate(Drawable* drawable)
 
 void Octree::CancelUpdate(Drawable* drawable)
 {
+    // This doesn't have to take into account scene being in threaded update, because it is called only
+    // when removing a drawable from octree, which should only ever happen from the main thread.
     drawableUpdates_.Remove(drawable);
     drawable->updateQueued_ = false;
 }

+ 2 - 0
Source/Urho3D/Graphics/Octree.h

@@ -208,6 +208,8 @@ private:
 
     /// Drawable objects that require update.
     PODVector<Drawable*> drawableUpdates_;
+    /// Drawable objects that were inserted during threaded update phase.
+    PODVector<Drawable*> threadedDrawableUpdates_;
     /// Mutex for octree reinsertions.
     Mutex octreeMutex_;
     /// Ray query temporary list of drawables.