Browse Source

Sort batch groups front to back according to the distance of the first batch to reduce overdraw.

Lasse Öörni 14 years ago
parent
commit
f26ff1c2f6
4 changed files with 57 additions and 25 deletions
  1. 30 0
      Engine/Graphics/Batch.cpp
  2. 8 4
      Engine/Graphics/Batch.h
  3. 16 18
      Engine/Graphics/View.cpp
  4. 3 3
      Engine/UI/UIElement.cpp

+ 30 - 0
Engine/Graphics/Batch.cpp

@@ -59,6 +59,11 @@ inline bool CompareInstancesFrontToBack(const InstanceData& lhs, const InstanceD
     return lhs.distance_ < rhs.distance_;
 }
 
+inline bool CompareBatchGroupsFrontToBack(BatchGroup* lhs, BatchGroup* rhs)
+{
+    return lhs->instances_[0].distance_ < rhs->instances_[0].distance_;
+}
+
 void Batch::CalculateSortKey()
 {
     unsigned lightQueue = (*((unsigned*)&lightQueue_) / sizeof(LightBatchQueue)) & 0x7fff;
@@ -562,6 +567,17 @@ void BatchQueue::SortBackToFront()
         sortedBatches_[i] = &batches_[i];
     
     Sort(sortedBatches_.Begin(), sortedBatches_.End(), CompareBatchesBackToFront);
+    
+    // Do not actually sort batch groups, just list them
+    sortedPriorityBatchGroups_.Resize(priorityBatchGroups_.Size());
+    sortedBatchGroups_.Resize(batchGroups_.Size());
+    
+    unsigned index = 0;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
+        sortedPriorityBatchGroups_[index++] = &i->second_;
+    index = 0;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
+        sortedBatchGroups_[index++] = &i->second_;
 }
 
 void BatchQueue::SortFrontToBack()
@@ -587,6 +603,20 @@ void BatchQueue::SortFrontToBack()
         Sort(i->second_.instances_.Begin(), i->second_.instances_.End(), CompareInstancesFrontToBack);
     for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
         Sort(i->second_.instances_.Begin(), i->second_.instances_.End(), CompareInstancesFrontToBack);
+    
+    // Now sort batch groups by the distance of the first batch
+    sortedPriorityBatchGroups_.Resize(priorityBatchGroups_.Size());
+    sortedBatchGroups_.Resize(batchGroups_.Size());
+    
+    unsigned index = 0;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = priorityBatchGroups_.Begin(); i != priorityBatchGroups_.End(); ++i)
+        sortedPriorityBatchGroups_[index++] = &i->second_;
+    index = 0;
+    for (Map<BatchGroupKey, BatchGroup>::Iterator i = batchGroups_.Begin(); i != batchGroups_.End(); ++i)
+        sortedBatchGroups_[index++] = &i->second_;
+    
+    Sort(sortedPriorityBatchGroups_.Begin(), sortedPriorityBatchGroups_.End(), CompareBatchGroupsFrontToBack);
+    Sort(sortedBatchGroups_.Begin(), sortedBatchGroups_.End(), CompareBatchGroupsFrontToBack);
 }
 
 void BatchQueue::SetTransforms(Renderer* renderer, void* lockedData, unsigned& freeIndex)

+ 8 - 4
Engine/Graphics/Batch.h

@@ -239,14 +239,18 @@ public:
     bool IsEmpty() const { return batches_.Empty() && priorityBatchGroups_.Empty() && batchGroups_.Empty(); }
     /// Unsorted non-instanced draw calls.
     PODVector<Batch> batches_;
-    /// Sorted non-instanced draw calls with priority flag.
-    PODVector<Batch*> sortedPriorityBatches_;
-    /// Sorted non-instanced draw calls.
-    PODVector<Batch*> sortedBatches_;
     /// Instanced draw calls with priority flag.
     Map<BatchGroupKey, BatchGroup> priorityBatchGroups_;
     /// Instanced draw calls.
     Map<BatchGroupKey, BatchGroup> batchGroups_;
+    /// Sorted non-instanced draw calls with priority flag.
+    PODVector<Batch*> sortedPriorityBatches_;
+    /// Sorted non-instanced draw calls.
+    PODVector<Batch*> sortedBatches_;
+    /// Sorted instanced draw calls with priority flag.
+    PODVector<BatchGroup*> sortedPriorityBatchGroups_;
+    /// Sorted instanced draw calls.
+    PODVector<BatchGroup*> sortedBatchGroups_;
 };
 
 /// Queue for shadow map draw calls

+ 16 - 18
Engine/Graphics/View.cpp

@@ -1545,11 +1545,11 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
     graphics_->SetStencilTest(false);
     
     // Priority instanced
-    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = queue.priorityBatchGroups_.Begin(); i !=
-        queue.priorityBatchGroups_.End(); ++i)
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedPriorityBatchGroups_.Begin(); i !=
+        queue.sortedPriorityBatchGroups_.End(); ++i)
     {
-        const BatchGroup& group = i->second_;
-        group.Draw(graphics_, renderer_, shaderParameters_);
+        BatchGroup* group = *i;
+        group->Draw(graphics_, renderer_, shaderParameters_);
     }
     // Priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
@@ -1559,13 +1559,12 @@ void View::RenderBatchQueue(const BatchQueue& queue, bool useScissor)
     }
     
     // Non-priority instanced
-    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = queue.batchGroups_.Begin(); i !=
-        queue.batchGroups_.End(); ++i)
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     {
-        const BatchGroup& group = i->second_;
-        if (useScissor && group.lightQueue_)
-            OptimizeLightByScissor(group.lightQueue_->light_);
-        group.Draw(graphics_, renderer_, shaderParameters_);
+        BatchGroup* group = *i;
+        if (useScissor && group->lightQueue_)
+            OptimizeLightByScissor(group->lightQueue_->light_);
+        group->Draw(graphics_, renderer_, shaderParameters_);
     }
     // Non-priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)
@@ -1589,11 +1588,11 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
     graphics_->SetStencilTest(false);
     
     // Priority instanced
-    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = queue.priorityBatchGroups_.Begin(); i !=
-        queue.priorityBatchGroups_.End(); ++i)
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedPriorityBatchGroups_.Begin(); i !=
+        queue.sortedPriorityBatchGroups_.End(); ++i)
     {
-        const BatchGroup& group = i->second_;
-        group.Draw(graphics_, renderer_, shaderParameters_);
+        BatchGroup* group = *i;
+        group->Draw(graphics_, renderer_, shaderParameters_);
     }
     // Priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedPriorityBatches_.Begin(); i != queue.sortedPriorityBatches_.End(); ++i)
@@ -1607,11 +1606,10 @@ void View::RenderLightBatchQueue(const BatchQueue& queue, Light* light)
     OptimizeLightByScissor(light);
     
     // Non-priority instanced
-    for (Map<BatchGroupKey, BatchGroup>::ConstIterator i = queue.batchGroups_.Begin(); i !=
-        queue.batchGroups_.End(); ++i)
+    for (PODVector<BatchGroup*>::ConstIterator i = queue.sortedBatchGroups_.Begin(); i != queue.sortedBatchGroups_.End(); ++i)
     {
-        const BatchGroup& group = i->second_;
-        group.Draw(graphics_, renderer_, shaderParameters_);
+        BatchGroup* group = *i;
+        group->Draw(graphics_, renderer_, shaderParameters_);
     }
     // Non-priority non-instanced
     for (PODVector<Batch*>::ConstIterator i = queue.sortedBatches_.Begin(); i != queue.sortedBatches_.End(); ++i)

+ 3 - 3
Engine/UI/UIElement.cpp

@@ -1195,8 +1195,8 @@ void UIElement::CalculateLayout(PODVector<int>& positions, PODVector<int>& sizes
         
         for (int i = 0; i < numResizable; ++i)
         {
-            unsigned idx = resizable[i];
-            int targetSize = sizes[idx] + errorPerChild;
+            unsigned index = resizable[i];
+            int targetSize = sizes[index] + errorPerChild;
             if (remainder)
             {
                 acc += add;
@@ -1208,7 +1208,7 @@ void UIElement::CalculateLayout(PODVector<int>& positions, PODVector<int>& sizes
                 }
             }
             
-            sizes[idx] = Clamp(targetSize, minSizes[idx], maxSizes[idx]);
+            sizes[index] = Clamp(targetSize, minSizes[index], maxSizes[index]);
         }
     }