Browse Source

Split GetBatches() into sub-functions to aid in profiling. Minor optimization of View::GetTechnique() when using the default material.

Lasse Öörni 10 years ago
parent
commit
6c3b8078f6
2 changed files with 108 additions and 97 deletions
  1. 102 97
      Source/Urho3D/Graphics/View.cpp
  2. 6 0
      Source/Urho3D/Graphics/View.h

+ 102 - 97
Source/Urho3D/Graphics/View.cpp

@@ -916,32 +916,40 @@ void View::GetBatches()
     nonThreadedGeometries_.Clear();
     threadedGeometries_.Clear();
     
-    WorkQueue* queue = GetSubsystem<WorkQueue>();
-    BatchQueue* alphaQueue = batchQueues_.Contains(alphaPassIndex_) ? &batchQueues_[alphaPassIndex_] : (BatchQueue*)0;
-    
+    ProcessLights();
+    GetLightBatches();
+    GetBaseBatches();
+}
+
+void View::ProcessLights()
+{
     // Process lit geometries and shadow casters for each light
+    PROFILE(ProcessLights);
+
+    WorkQueue* queue = GetSubsystem<WorkQueue>();
+    lightQueryResults_.Resize(lights_.Size());
+
+    for (unsigned i = 0; i < lightQueryResults_.Size(); ++i)
     {
-        PROFILE(ProcessLights);
-        
-        lightQueryResults_.Resize(lights_.Size());
-        
-        for (unsigned i = 0; i < lightQueryResults_.Size(); ++i)
-        {
-            SharedPtr<WorkItem> item = queue->GetFreeItem();
-            item->priority_ = M_MAX_UNSIGNED;
-            item->workFunction_ = ProcessLightWork;
-            item->aux_ = this;
+        SharedPtr<WorkItem> item = queue->GetFreeItem();
+        item->priority_ = M_MAX_UNSIGNED;
+        item->workFunction_ = ProcessLightWork;
+        item->aux_ = this;
 
-            LightQueryResult& query = lightQueryResults_[i];
-            query.light_ = lights_[i];
-            
-            item->start_ = &query;
-            queue->AddWorkItem(item);
-        }
-        
-        // Ensure all lights have been processed before proceeding
-        queue->Complete(M_MAX_UNSIGNED);
+        LightQueryResult& query = lightQueryResults_[i];
+        query.light_ = lights_[i];
+
+        item->start_ = &query;
+        queue->AddWorkItem(item);
     }
+
+    // Ensure all lights have been processed before proceeding
+    queue->Complete(M_MAX_UNSIGNED);
+}
+
+void View::GetLightBatches()
+{
+    BatchQueue* alphaQueue = batchQueues_.Contains(alphaPassIndex_) ? &batchQueues_[alphaPassIndex_] : (BatchQueue*)0;
     
     // Build light queues and lit batches
     {
@@ -1119,92 +1127,92 @@ void View::GetBatches()
             }
         }
     }
+}
+
+void View::GetBaseBatches()
+{
+    PROFILE(GetBaseBatches);
     
-    // Build base pass batches and find out the geometry update queue (threaded or nonthreaded) drawables should end up to
+    for (PODVector<Drawable*>::ConstIterator i = geometries_.Begin(); i != geometries_.End(); ++i)
     {
-        PROFILE(GetBaseBatches);
+        Drawable* drawable = *i;
+        UpdateGeometryType type = drawable->GetUpdateGeometryType();
+        if (type == UPDATE_MAIN_THREAD)
+            nonThreadedGeometries_.Push(drawable);
+        else if (type == UPDATE_WORKER_THREAD)
+            threadedGeometries_.Push(drawable);
         
-        for (PODVector<Drawable*>::ConstIterator i = geometries_.Begin(); i != geometries_.End(); ++i)
+        const Vector<SourceBatch>& batches = drawable->GetBatches();
+        bool vertexLightsProcessed = false;
+
+        for (unsigned j = 0; j < batches.Size(); ++j)
         {
-            Drawable* drawable = *i;
-            UpdateGeometryType type = drawable->GetUpdateGeometryType();
-            if (type == UPDATE_MAIN_THREAD)
-                nonThreadedGeometries_.Push(drawable);
-            else if (type == UPDATE_WORKER_THREAD)
-                threadedGeometries_.Push(drawable);
+            const SourceBatch& srcBatch = batches[j];
             
-            const Vector<SourceBatch>& batches = drawable->GetBatches();
-            bool vertexLightsProcessed = false;
-
-            for (unsigned j = 0; j < batches.Size(); ++j)
+            // Check here if the material refers to a rendertarget texture with camera(s) attached
+            // Only check this for backbuffer views (null rendertarget)
+            if (srcBatch.material_ && srcBatch.material_->GetAuxViewFrameNumber() != frame_.frameNumber_ && !renderTarget_)
+                CheckMaterialForAuxView(srcBatch.material_);
+            
+            Technique* tech = GetTechnique(drawable, srcBatch.material_);
+            if (!srcBatch.geometry_ || !srcBatch.numWorldTransforms_ || !tech)
+                continue;
+            
+            // Check each of the scene passes
+            for (unsigned k = 0; k < scenePasses_.Size(); ++k)
             {
-                const SourceBatch& srcBatch = batches[j];
-                
-                // Check here if the material refers to a rendertarget texture with camera(s) attached
-                // Only check this for backbuffer views (null rendertarget)
-                if (srcBatch.material_ && srcBatch.material_->GetAuxViewFrameNumber() != frame_.frameNumber_ && !renderTarget_)
-                    CheckMaterialForAuxView(srcBatch.material_);
-                
-                Technique* tech = GetTechnique(drawable, srcBatch.material_);
-                if (!srcBatch.geometry_ || !srcBatch.numWorldTransforms_ || !tech)
+                ScenePassInfo& info = scenePasses_[k];
+                // Skip forward base pass if the corresponding litbase pass already exists
+                if (info.passIndex_ == basePassIndex_ && j < 32 && drawable->HasBasePass(j))
+                    continue;
+
+                Pass* pass = tech->GetSupportedPass(info.passIndex_);
+                if (!pass)
                     continue;
                 
-                // Check each of the scene passes
-                for (unsigned k = 0; k < scenePasses_.Size(); ++k)
+                Batch destBatch(srcBatch);
+                destBatch.pass_ = pass;
+                destBatch.camera_ = camera_;
+                destBatch.zone_ = GetZone(drawable);
+                destBatch.isBase_ = true;
+                destBatch.lightMask_ = GetLightMask(drawable);
+
+                if (info.vertexLights_)
                 {
-                    ScenePassInfo& info = scenePasses_[k];
-                    // Skip forward base pass if the corresponding litbase pass already exists
-                    if (info.passIndex_ == basePassIndex_ && j < 32 && drawable->HasBasePass(j))
-                        continue;
-
-                    Pass* pass = tech->GetSupportedPass(info.passIndex_);
-                    if (!pass)
-                        continue;
-                    
-                    Batch destBatch(srcBatch);
-                    destBatch.pass_ = pass;
-                    destBatch.camera_ = camera_;
-                    destBatch.zone_ = GetZone(drawable);
-                    destBatch.isBase_ = true;
-                    destBatch.lightMask_ = GetLightMask(drawable);
-
-                    if (info.vertexLights_)
+                    const PODVector<Light*>& drawableVertexLights = drawable->GetVertexLights();
+                    if (drawableVertexLights.Size() && !vertexLightsProcessed)
                     {
-                        const PODVector<Light*>& drawableVertexLights = drawable->GetVertexLights();
-                        if (drawableVertexLights.Size() && !vertexLightsProcessed)
-                        {
-                            // Limit vertex lights. If this is a deferred opaque batch, remove converted per-pixel lights,
-                            // as they will be rendered as light volumes in any case, and drawing them also as vertex lights
-                            // would result in double lighting
-                            drawable->LimitVertexLights(deferred_ && destBatch.pass_->GetBlendMode() == BLEND_REPLACE);
-                            vertexLightsProcessed = true;
-                        }
+                        // Limit vertex lights. If this is a deferred opaque batch, remove converted per-pixel lights,
+                        // as they will be rendered as light volumes in any case, and drawing them also as vertex lights
+                        // would result in double lighting
+                        drawable->LimitVertexLights(deferred_ && destBatch.pass_->GetBlendMode() == BLEND_REPLACE);
+                        vertexLightsProcessed = true;
+                    }
 
-                        if (drawableVertexLights.Size())
+                    if (drawableVertexLights.Size())
+                    {
+                        // Find a vertex light queue. If not found, create new
+                        unsigned long long hash = GetVertexLightQueueHash(drawableVertexLights);
+                        HashMap<unsigned long long, LightBatchQueue>::Iterator i = vertexLightQueues_.Find(hash);
+                        if (i == vertexLightQueues_.End())
                         {
-                            // Find a vertex light queue. If not found, create new
-                            unsigned long long hash = GetVertexLightQueueHash(drawableVertexLights);
-                            HashMap<unsigned long long, LightBatchQueue>::Iterator i = vertexLightQueues_.Find(hash);
-                            if (i == vertexLightQueues_.End())
-                            {
-                                i = vertexLightQueues_.Insert(MakePair(hash, LightBatchQueue()));
-                                i->second_.light_ = 0;
-                                i->second_.shadowMap_ = 0;
-                                i->second_.vertexLights_ = drawableVertexLights;
-                            }
-                            
-                            destBatch.lightQueue_ = &(i->second_);
+                            i = vertexLightQueues_.Insert(MakePair(hash, LightBatchQueue()));
+                            i->second_.light_ = 0;
+                            i->second_.shadowMap_ = 0;
+                            i->second_.vertexLights_ = drawableVertexLights;
                         }
+                        
+                        destBatch.lightQueue_ = &(i->second_);
                     }
-                    else
-                        destBatch.lightQueue_ = 0;
-                    
-                    bool allowInstancing = info.allowInstancing_;
-                    if (allowInstancing && info.markToStencil_ && destBatch.lightMask_ != (destBatch.zone_->GetLightMask() & 0xff))
-                        allowInstancing = false;
-                    
-                    AddBatchToQueue(*info.batchQueue_, destBatch, tech, allowInstancing);
                 }
+                else
+                    destBatch.lightQueue_ = 0;
+                
+                bool allowInstancing = info.allowInstancing_;
+                if (allowInstancing && info.markToStencil_ && destBatch.lightMask_ != (destBatch.zone_->GetLightMask() & 0xff))
+                    allowInstancing = false;
+                
+                AddBatchToQueue(*info.batchQueue_, destBatch, tech, allowInstancing);
             }
         }
     }
@@ -2674,10 +2682,7 @@ void View::FindZone(Drawable* drawable)
 Technique* View::GetTechnique(Drawable* drawable, Material* material)
 {
     if (!material)
-    {
-        const Vector<TechniqueEntry>& techniques = renderer_->GetDefaultMaterial()->GetTechniques();
-        return techniques.Size() ? techniques[0].technique_ : (Technique*)0;
-    }
+        return renderer_->GetDefaultMaterial()->GetTechniques()[0].technique_;
     
     const Vector<TechniqueEntry>& techniques = material->GetTechniques();
     // If only one technique, no choice

+ 6 - 0
Source/Urho3D/Graphics/View.h

@@ -164,6 +164,12 @@ private:
     void GetDrawables();
     /// Construct batches from the drawable objects.
     void GetBatches();
+    /// Get lit geometries and shadowcasters for visible lights.
+    void ProcessLights();
+    /// Get batches from lit geometries and shadowcasters.
+    void GetLightBatches();
+    /// Get unlit batches.
+    void GetBaseBatches();
     /// Update geometries and sort batches.
     void UpdateGeometries();
     /// Get pixel lit batches for a certain light and drawable.