Browse Source

Queue octree updates & reinsertions in a PODVector instead of a HashSet.

Lasse Öörni 14 years ago
parent
commit
f9d04676f8

+ 1 - 1
Engine/Graphics/AnimatedModel.h

@@ -56,7 +56,7 @@ public:
     virtual void UpdateDistance(const FrameInfo& frame);
     virtual void UpdateDistance(const FrameInfo& frame);
     /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
     /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
     virtual void UpdateGeometry(const FrameInfo& frame);
     virtual void UpdateGeometry(const FrameInfo& frame);
-    /// Return whether a geometry update is necessary, and if it should happen threaded.
+    /// Return whether a geometry update is necessary, and if it should happen in a worker thread.
     virtual UpdateGeometryType GetUpdateGeometryType();
     virtual UpdateGeometryType GetUpdateGeometryType();
     /// Fill rendering batch with distance, geometry, material and world transform.
     /// Fill rendering batch with distance, geometry, material and world transform.
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);

+ 1 - 1
Engine/Graphics/BillboardSet.h

@@ -69,7 +69,7 @@ public:
     virtual bool GetUpdateOnGPU() { return true; }
     virtual bool GetUpdateOnGPU() { return true; }
     /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
     /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
     virtual void UpdateGeometry(const FrameInfo& frame);
     virtual void UpdateGeometry(const FrameInfo& frame);
-    /// Return whether a geometry update is necessary, and if it should happen threaded.
+    /// Return whether a geometry update is necessary, and if it should happen in a worker thread.
     virtual UpdateGeometryType GetUpdateGeometryType();
     virtual UpdateGeometryType GetUpdateGeometryType();
     /// Return number of batches.
     /// Return number of batches.
     virtual unsigned GetNumBatches();
     virtual unsigned GetNumBatches();

+ 3 - 1
Engine/Graphics/Drawable.cpp

@@ -59,7 +59,9 @@ Drawable::Drawable(Context* context) :
     visible_(true),
     visible_(true),
     castShadows_(false),
     castShadows_(false),
     occluder_(false),
     occluder_(false),
-    worldBoundingBoxDirty_(true)
+    worldBoundingBoxDirty_(true),
+    updateQueued_(false),
+    reinsertionQueued_(false)
 {
 {
 }
 }
 
 

+ 8 - 2
Engine/Graphics/Drawable.h

@@ -73,7 +73,9 @@ class Drawable : public Component
 {
 {
     OBJECT(Drawable);
     OBJECT(Drawable);
     
     
+    friend class DrawableUpdate;
     friend class Octant;
     friend class Octant;
+    friend class Octree;
     
     
 public:
 public:
     /// Construct.
     /// Construct.
@@ -91,14 +93,14 @@ public:
     virtual void UpdateDistance(const FrameInfo& frame);
     virtual void UpdateDistance(const FrameInfo& frame);
     /// Prepare geometry for rendering.
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame) {}
     virtual void UpdateGeometry(const FrameInfo& frame) {}
+    /// Return whether a geometry update is necessary, and if it should happen in a worker thread.
+    virtual UpdateGeometryType GetUpdateGeometryType() { return UPDATE_NONE; }
     /// Return number of rendering batches.
     /// Return number of rendering batches.
     virtual unsigned GetNumBatches() { return 0; }
     virtual unsigned GetNumBatches() { return 0; }
     /// Fill rendering batch with distance, geometry, material and world transform.
     /// Fill rendering batch with distance, geometry, material and world transform.
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex) {}
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex) {}
     /// Return number of occlusion geometry triangles.
     /// Return number of occlusion geometry triangles.
     virtual unsigned GetNumOccluderTriangles() { return 0; }
     virtual unsigned GetNumOccluderTriangles() { return 0; }
-    /// Return whether a geometry update is necessary, and if it should happen threaded.
-    virtual UpdateGeometryType GetUpdateGeometryType() { return UPDATE_NONE; }
     /// Draw to occlusion buffer.
     /// Draw to occlusion buffer.
     virtual bool DrawOcclusion(OcclusionBuffer* buffer) { return true; }
     virtual bool DrawOcclusion(OcclusionBuffer* buffer) { return true; }
     /// Draw debug geometry.
     /// Draw debug geometry.
@@ -253,6 +255,10 @@ protected:
     bool occluder_;
     bool occluder_;
     /// Bounding box dirty flag.
     /// Bounding box dirty flag.
     bool worldBoundingBoxDirty_;
     bool worldBoundingBoxDirty_;
+    /// Octree update queued flag.
+    bool updateQueued_;
+    /// Octree reinsertion queued flag.
+    bool reinsertionQueued_;
 };
 };
 
 
 inline bool CompareDrawables(Drawable* lhs, Drawable* rhs)
 inline bool CompareDrawables(Drawable* lhs, Drawable* rhs)

+ 34 - 14
Engine/Graphics/Octree.cpp

@@ -390,29 +390,47 @@ void Octree::GetUnculledDrawables(PODVector<Drawable*>& dest, unsigned char draw
 
 
 void Octree::QueueUpdate(Drawable* drawable)
 void Octree::QueueUpdate(Drawable* drawable)
 {
 {
-    drawableUpdates_.Insert(drawable);
+    if (!drawable->updateQueued_)
+    {
+        drawableUpdates_.Push(drawable);
+        drawable->updateQueued_ = true;
+    }
 }
 }
 
 
 void Octree::QueueReinsertion(Drawable* drawable)
 void Octree::QueueReinsertion(Drawable* drawable)
 {
 {
-    if (scene_ && scene_->IsThreadedUpdate())
+    if (!drawable->reinsertionQueued_)
     {
     {
-        reinsertionLock_.Acquire();
-        drawableReinsertions_.Insert(drawable);
-        reinsertionLock_.Release();
+        if (scene_ && scene_->IsThreadedUpdate())
+        {
+            reinsertionLock_.Acquire();
+            drawableReinsertions_.Push(drawable);
+            reinsertionLock_.Release();
+        }
+        else
+            drawableReinsertions_.Push(drawable);
+        drawable->reinsertionQueued_ = true;
     }
     }
-    else
-        drawableReinsertions_.Insert(drawable);
 }
 }
 
 
 void Octree::CancelUpdate(Drawable* drawable)
 void Octree::CancelUpdate(Drawable* drawable)
 {
 {
-    drawableUpdates_.Erase(drawable);
+    PODVector<Drawable*>::Iterator i = drawableUpdates_.Find(drawable);
+    if (i != drawableUpdates_.End())
+    {
+        (*i)->updateQueued_ = false;
+        drawableUpdates_.Erase(i);
+    }
 }
 }
 
 
 void Octree::CancelReinsertion(Drawable* drawable)
 void Octree::CancelReinsertion(Drawable* drawable)
 {
 {
-    drawableReinsertions_.Erase(drawable);
+    PODVector<Drawable*>::Iterator i = drawableReinsertions_.Find(drawable);
+    if (i != drawableReinsertions_.End())
+    {
+        (*i)->reinsertionQueued_ = false;
+        drawableReinsertions_.Erase(i);
+    }
 }
 }
 
 
 void Octree::DrawDebugGeometry(bool depthTest)
 void Octree::DrawDebugGeometry(bool depthTest)
@@ -437,14 +455,14 @@ void Octree::UpdateDrawables(const FrameInfo& frame)
     if (drawableUpdates_.Empty())
     if (drawableUpdates_.Empty())
         return;
         return;
     
     
-    PROFILE(UpdateDrawables);
+    PROFILE_MULTIPLE(UpdateDrawable, drawableUpdates_.Size());
     
     
     Scene* scene = node_->GetScene();
     Scene* scene = node_->GetScene();
     scene->BeginThreadedUpdate();
     scene->BeginThreadedUpdate();
     
     
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     List<DrawableUpdate>::Iterator item = drawableUpdateItems_.Begin();
     List<DrawableUpdate>::Iterator item = drawableUpdateItems_.Begin();
-    HashSet<Drawable*>::Iterator start = drawableUpdates_.Begin();
+    PODVector<Drawable*>::Iterator start = drawableUpdates_.Begin();
     
     
     while (start != drawableUpdates_.End())
     while (start != drawableUpdates_.End())
     {
     {
@@ -455,7 +473,7 @@ void Octree::UpdateDrawables(const FrameInfo& frame)
             item = --drawableUpdateItems_.End();
             item = --drawableUpdateItems_.End();
         }
         }
         
         
-        HashSet<Drawable*>::Iterator end = start;
+        PODVector<Drawable*>::Iterator end = start;
         int count = 0;
         int count = 0;
         while (count < DRAWABLES_PER_WORKITEM && end != drawableUpdates_.End())
         while (count < DRAWABLES_PER_WORKITEM && end != drawableUpdates_.End())
         {
         {
@@ -491,10 +509,10 @@ void Octree::ReinsertDrawables(const FrameInfo& frame)
     if (drawableReinsertions_.Empty())
     if (drawableReinsertions_.Empty())
         return;
         return;
     
     
-    PROFILE(ReinsertDrawables);
+    PROFILE_MULTIPLE(ReinsertDrawable, drawableReinsertions_.Size());
     
     
     // Reinsert drawables into the octree
     // Reinsert drawables into the octree
-    for (HashSet<Drawable*>::Iterator i = drawableReinsertions_.Begin(); i != drawableReinsertions_.End(); ++i)
+    for (PODVector<Drawable*>::Iterator i = drawableReinsertions_.Begin(); i != drawableReinsertions_.End(); ++i)
     {
     {
         Drawable* drawable = *i;
         Drawable* drawable = *i;
         Octant* octant = drawable->GetOctant();
         Octant* octant = drawable->GetOctant();
@@ -522,6 +540,8 @@ void Octree::ReinsertDrawables(const FrameInfo& frame)
         }
         }
         else
         else
             InsertDrawable(drawable);
             InsertDrawable(drawable);
+        
+        drawable->reinsertionQueued_ = false;
     }
     }
     
     
     drawableReinsertions_.Clear();
     drawableReinsertions_.Clear();

+ 10 - 8
Engine/Graphics/Octree.h

@@ -24,7 +24,6 @@
 #pragma once
 #pragma once
 
 
 #include "Drawable.h"
 #include "Drawable.h"
-#include "HashSet.h"
 #include "List.h"
 #include "List.h"
 #include "SpinLock.h"
 #include "SpinLock.h"
 #include "WorkItem.h"
 #include "WorkItem.h"
@@ -43,16 +42,19 @@ public:
     /// Do the work.
     /// Do the work.
     virtual void Process(unsigned threadIndex)
     virtual void Process(unsigned threadIndex)
     {
     {
-        for (HashSet<Drawable*>::Iterator i = start_; i != end_; ++i)
+        for (PODVector<Drawable*>::Iterator i = start_; i != end_; ++i)
+        {
             (*i)->Update(*frame_);
             (*i)->Update(*frame_);
+            (*i)->updateQueued_ = false;
+        }
     }
     }
     
     
     /// Frame info.
     /// Frame info.
     const FrameInfo* frame_;
     const FrameInfo* frame_;
     /// Start iterator.
     /// Start iterator.
-    HashSet<Drawable*>::Iterator start_;
+    PODVector<Drawable*>::Iterator start_;
     /// End iterator.
     /// End iterator.
-    HashSet<Drawable*>::Iterator end_;
+    PODVector<Drawable*>::Iterator end_;
 };
 };
 
 
 /// %Octree octant
 /// %Octree octant
@@ -221,10 +223,10 @@ private:
     
     
     /// Scene.
     /// Scene.
     Scene* scene_;
     Scene* scene_;
-    /// %Set of drawable objects that require update.
-    HashSet<Drawable*> drawableUpdates_;
-    /// %Set of drawable objects that require reinsertion.
-    HashSet<Drawable*> drawableReinsertions_;
+    /// Drawable objects that require update.
+    PODVector<Drawable*> drawableUpdates_;
+    /// Drawable objects that require reinsertion.
+    PODVector<Drawable*> drawableReinsertions_;
     /// Pool for drawable update work items.
     /// Pool for drawable update work items.
     List<DrawableUpdate> drawableUpdateItems_;
     List<DrawableUpdate> drawableUpdateItems_;
     /// Lock for octree reinsertions.
     /// Lock for octree reinsertions.

+ 3 - 3
Engine/Graphics/View.cpp

@@ -591,12 +591,10 @@ void View::GetBatches()
 
 
 void View::UpdateGeometries()
 void View::UpdateGeometries()
 {
 {
-    PROFILE(UpdateGeometries);
-    
     // Split into threaded and non-threaded geometries.
     // Split into threaded and non-threaded geometries.
     nonThreadedGeometries_.Clear();
     nonThreadedGeometries_.Clear();
     threadedGeometries_.Clear();
     threadedGeometries_.Clear();
-    for (PODVector<Drawable*>::ConstIterator i = allGeometries_.Begin(); i != allGeometries_.End(); ++i)
+    for (PODVector<Drawable*>::Iterator i = allGeometries_.Begin(); i != allGeometries_.End(); ++i)
     {
     {
         UpdateGeometryType type = (*i)->GetUpdateGeometryType();
         UpdateGeometryType type = (*i)->GetUpdateGeometryType();
         if (type == UPDATE_MAIN_THREAD)
         if (type == UPDATE_MAIN_THREAD)
@@ -605,6 +603,8 @@ void View::UpdateGeometries()
             threadedGeometries_.Push(*i);
             threadedGeometries_.Push(*i);
     }
     }
     
     
+    PROFILE_MULTIPLE(UpdateGeometry, nonThreadedGeometries_.Size() + threadedGeometries_.Size());
+    
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     WorkQueue* queue = GetSubsystem<WorkQueue>();
     
     
     if (threadedGeometries_.Size())
     if (threadedGeometries_.Size())