Forráskód Böngészése

Divide geometry updates explicitly into main thread, worker threads, and none.

Lasse Öörni 14 éve
szülő
commit
721885ba4a

+ 2 - 2
Bin/Data/Scripts/TestSceneOld.as

@@ -1,10 +1,10 @@
 // GraphicsTest rewrite from Urho3D 1.0
 
-const uint NUM_OBJECTS = 250;
+const uint NUM_OBJECTS = 2500;
 const uint NUM_LIGHTS = 20;
 const uint NUM_INSTANCENODES = 20;
 const uint NUM_INSTANCES = 50;
-const uint NUM_BILLBOARDNODES = 20;
+const uint NUM_BILLBOARDNODES = 0;
 const uint NUM_BILLBOARDS = 15;
 
 Scene@ testScene;

+ 11 - 6
Engine/Graphics/AnimatedModel.cpp

@@ -231,20 +231,25 @@ void AnimatedModel::UpdateDistance(const FrameInfo& frame)
     }
 }
 
-bool AnimatedModel::GetUpdateOnGPU()
-{
-    return morphsDirty_ && morphs_.Size();
-}
-
 void AnimatedModel::UpdateGeometry(const FrameInfo& frame)
 {
-    if (morphsDirty_ && morphs_.Size())
+    if (morphsDirty_)
         UpdateMorphs();
     
     if (skinningDirty_)
         UpdateSkinning();
 }
 
+UpdateGeometryType AnimatedModel::GetUpdateGeometryType()
+{
+    if (morphsDirty_)
+        return UPDATE_MAIN_THREAD;
+    else if (skinningDirty_)
+        return UPDATE_WORKER_THREAD;
+    else
+        return UPDATE_NONE;
+}
+
 void AnimatedModel::GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex)
 {
     batch.distance_ = geometryDistances_[batchIndex];

+ 2 - 2
Engine/Graphics/AnimatedModel.h

@@ -54,10 +54,10 @@ public:
     virtual void Update(const FrameInfo& frame);
     /// Calculate distance and LOD level for rendering.
     virtual void UpdateDistance(const FrameInfo& frame);
-    /// Return whether the next geometry update will touch actual GPU resources.
-    virtual bool GetUpdateOnGPU();
     /// Prepare geometry for rendering. Called from a worker thread if possible (no GPU update.)
     virtual void UpdateGeometry(const FrameInfo& frame);
+    /// Return whether a geometry update is necessary, and if it should happen threaded.
+    virtual UpdateGeometryType GetUpdateGeometryType();
     /// Fill rendering batch with distance, geometry, material and world transform.
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex);
     /// Add debug geometry to the debug graphics.

+ 10 - 1
Engine/Graphics/BillboardSet.cpp

@@ -131,13 +131,22 @@ void BillboardSet::UpdateGeometry(const FrameInfo& frame)
     if (vertexBuffer_->IsDataLost())
     {
         vertexBuffer_->ClearDataLost();
+        bufferDirty_ = true;
         forceUpdate_ = true;
     }
     
-    if (bufferDirty_ || forceUpdate_)
+    if (bufferDirty_)
         UpdateVertexBuffer(frame);
 }
 
+UpdateGeometryType BillboardSet::GetUpdateGeometryType()
+{
+    if (bufferDirty_ || bufferSizeDirty_ || (vertexBuffer_ && vertexBuffer_->IsDataLost()))
+        return UPDATE_MAIN_THREAD;
+    else
+        return UPDATE_NONE;
+}
+
 unsigned BillboardSet::GetNumBatches()
 {
     return 1;

+ 2 - 0
Engine/Graphics/BillboardSet.h

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

+ 10 - 2
Engine/Graphics/Drawable.h

@@ -47,6 +47,14 @@ class Octant;
 class RayOctreeQuery;
 class Zone;
 
+/// Geometry update type.
+enum UpdateGeometryType
+{
+    UPDATE_NONE = 0,
+    UPDATE_MAIN_THREAD,
+    UPDATE_WORKER_THREAD
+};
+
 /// Rendering frame update parameters.
 struct FrameInfo
 {
@@ -81,8 +89,6 @@ public:
     virtual void Update(const FrameInfo& frame) {}
     /// Calculate distance and LOD level for rendering.
     virtual void UpdateDistance(const FrameInfo& frame);
-    /// Return whether the next geometry update will touch actual GPU resources. If not, it can be threaded.
-    virtual bool GetUpdateOnGPU() { return true; }
     /// Prepare geometry for rendering.
     virtual void UpdateGeometry(const FrameInfo& frame) {}
     /// Return number of rendering batches.
@@ -91,6 +97,8 @@ public:
     virtual void GetBatch(Batch& batch, const FrameInfo& frame, unsigned batchIndex) {}
     /// Return number of occlusion geometry triangles.
     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.
     virtual bool DrawOcclusion(OcclusionBuffer* buffer) { return true; }
     /// Draw debug geometry.

+ 1 - 1
Engine/Graphics/Octree.cpp

@@ -39,7 +39,7 @@
 
 static const float DEFAULT_OCTREE_SIZE = 1000.0f;
 static const int DEFAULT_OCTREE_LEVELS = 8;
-static const int DRAWABLES_PER_WORKITEM = 4;
+static const int DRAWABLES_PER_WORKITEM = 8;
 
 inline bool CompareRayQueryResults(const RayQueryResult& lhs, const RayQueryResult& rhs)
 {

+ 8 - 7
Engine/Graphics/View.cpp

@@ -57,7 +57,7 @@ static const Vector3 directions[] =
     Vector3(0.0f, 0.0f, -1.0f)
 };
 
-static const int DRAWABLES_PER_WORKITEM = 4;
+static const int DRAWABLES_PER_WORKITEM = 8;
 
 OBJECTTYPESTATIC(View);
 
@@ -594,10 +594,14 @@ void View::UpdateGeometries()
     PROFILE(UpdateGeometries);
     
     // Split into threaded and non-threaded geometries.
+    nonThreadedGeometries_.Clear();
     threadedGeometries_.Clear();
     for (PODVector<Drawable*>::ConstIterator i = allGeometries_.Begin(); i != allGeometries_.End(); ++i)
     {
-        if (!(*i)->GetUpdateOnGPU())
+        UpdateGeometryType type = (*i)->GetUpdateGeometryType();
+        if (type == UPDATE_MAIN_THREAD)
+            nonThreadedGeometries_.Push(*i);
+        else if (type == UPDATE_WORKER_THREAD)
             threadedGeometries_.Push(*i);
     }
     
@@ -638,11 +642,8 @@ void View::UpdateGeometries()
     }
     
     // While the work queue is processed, update non-threaded geometries
-    for (PODVector<Drawable*>::ConstIterator i = allGeometries_.Begin(); i != allGeometries_.End(); ++i)
-    {
-        if ((*i)->GetUpdateOnGPU())
-            (*i)->UpdateGeometry(frame_);
-    }
+    for (PODVector<Drawable*>::ConstIterator i = nonThreadedGeometries_.Begin(); i != nonThreadedGeometries_.End(); ++i)
+        (*i)->UpdateGeometry(frame_);
     
     queue->FinishAndStop();
 }

+ 2 - 0
Engine/Graphics/View.h

@@ -230,6 +230,8 @@ private:
     PODVector<Drawable*> geometries_;
     /// All geometry objects, including shadow casters not visible in the main view.
     PODVector<Drawable*> allGeometries_;
+    /// Geometry objects that will be updated in the main thread.
+    PODVector<Drawable*> nonThreadedGeometries_;
     /// Geometry objects that will be updated in worker threads.
     PODVector<Drawable*> threadedGeometries_;
     /// Occluder objects.