Browse Source

Merge remote-tracking branch 'remotes/alexparlett/feature/work-item-refactor'

Lasse Öörni 12 years ago
parent
commit
ae626c861e

+ 15 - 12
Source/Engine/Core/WorkQueue.cpp

@@ -99,13 +99,16 @@ void WorkQueue::CreateThreads(unsigned numThreads)
     }
 }
 
-void WorkQueue::AddWorkItem(const WorkItem& item)
+void WorkQueue::AddWorkItem(SharedPtr<WorkItem> item)
 {
+    // Check for duplicate items.
+    if (workItems_.Contains(item))
+        return;
+
     // Push to the main thread list to keep item alive
     // Clear completed flag in case item is reused
     workItems_.Push(item);
-    WorkItem* itemPtr = &workItems_.Back();
-    itemPtr->completed_ = false;
+    item->completed_ = false;
     
     // Make sure worker threads' list is safe to modify
     if (threads_.Size() && !paused_)
@@ -113,14 +116,14 @@ void WorkQueue::AddWorkItem(const WorkItem& item)
     
     // Find position for new item
     if (queue_.Empty())
-        queue_.Push(itemPtr);
+        queue_.Push(item);
     else
     {
         for (List<WorkItem*>::Iterator i = queue_.Begin(); i != queue_.End(); ++i)
         {
-            if ((*i)->priority_ <= itemPtr->priority_)
+            if ((*i)->priority_ <= item->priority_)
             {
-                queue_.Insert(i, itemPtr);
+                queue_.Insert(i, item);
                 break;
             }
         }
@@ -207,9 +210,9 @@ void WorkQueue::Complete(unsigned priority)
 
 bool WorkQueue::IsCompleted(unsigned priority) const
 {
-    for (List<WorkItem>::ConstIterator i = workItems_.Begin(); i != workItems_.End(); ++i)
+    for (List<SharedPtr<WorkItem> >::ConstIterator i = workItems_.Begin(); i != workItems_.End(); ++i)
     {
-        if (i->priority_ >= priority && !i->completed_)
+        if ((*i)->priority_ >= priority && !(*i)->completed_)
             return false;
     }
     
@@ -258,13 +261,13 @@ void WorkQueue::PurgeCompleted()
     VariantMap& eventData = GetEventDataMap();
     
     // Purge completed work items and send completion events.
-    for (List<WorkItem>::Iterator i = workItems_.Begin(); i != workItems_.End();)
+    for (List<SharedPtr<WorkItem> >::Iterator i = workItems_.Begin(); i != workItems_.End();)
     {
-        if (i->completed_)
+        if ((*i)->completed_)
         {
-            if (i->sendEvent_)
+            if ((*i)->sendEvent_)
             {
-                eventData[P_ITEM] = (void*)(&(*i));
+                eventData[P_ITEM] = static_cast<void*>(i->Get());
                 SendEvent(E_WORKITEMCOMPLETED, eventData);
             }
             

+ 3 - 3
Source/Engine/Core/WorkQueue.h

@@ -38,7 +38,7 @@ EVENT(E_WORKITEMCOMPLETED, WorkItemCompleted)
 class WorkerThread;
 
 /// Work queue item.
-struct WorkItem
+struct WorkItem : public RefCounted
 {
     // Construct
     WorkItem() :
@@ -80,7 +80,7 @@ public:
     /// Create worker threads. Can only be called once.
     void CreateThreads(unsigned numThreads);
     /// Add a work item and resume worker threads.
-    void AddWorkItem(const WorkItem& item);
+    void AddWorkItem(SharedPtr<WorkItem> item);
     /// Pause worker threads.
     void Pause();
     /// Resume worker threads.
@@ -104,7 +104,7 @@ private:
     /// Worker threads.
     Vector<SharedPtr<WorkerThread> > threads_;
     /// Work item collection. Accessed only by the main thread.
-    List<WorkItem> workItems_;
+    List<SharedPtr<WorkItem> > workItems_;
     /// Work item prioritized queue for worker threads. Pointers are guaranteed to be valid (point to workItems.)
     List<WorkItem*> queue_;
     /// Worker queue mutex.

+ 12 - 12
Source/Engine/Graphics/Octree.cpp

@@ -406,20 +406,20 @@ void Octree::Update(const FrameInfo& frame)
         int numWorkItems = queue->GetNumThreads() + 1; // Worker threads + main thread
         int drawablesPerItem = drawableUpdates_.Size() / numWorkItems;
         
-        WorkItem item;
-        item.workFunction_ = UpdateDrawablesWork;
-        item.aux_ = const_cast<FrameInfo*>(&frame);
-
         PODVector<Drawable*>::Iterator start = drawableUpdates_.Begin();
         // Create a work item for each thread
         for (int i = 0; i < numWorkItems; ++i)
         {
+            SharedPtr<WorkItem> item(new WorkItem());
+            item->workFunction_ = UpdateDrawablesWork;
+            item->aux_ = const_cast<FrameInfo*>(&frame);
+
             PODVector<Drawable*>::Iterator end = drawableUpdates_.End();
             if (i < numWorkItems - 1 && end - start > drawablesPerItem)
                 end = start + drawablesPerItem;
 
-            item.start_ = &(*start);
-            item.end_ = &(*end);
+            item->start_ = &(*start);
+            item->end_ = &(*end);
             queue->AddWorkItem(item);
 
             start = end;
@@ -526,19 +526,19 @@ void Octree::Raycast(RayOctreeQuery& query) const
             for (unsigned i = 0; i < rayQueryResults_.Size(); ++i)
                 rayQueryResults_[i].Clear();
 
-            WorkItem item;
-            item.workFunction_ = RaycastDrawablesWork;
-            item.aux_ = const_cast<Octree*>(this);
-
             PODVector<Drawable*>::Iterator start = rayQueryDrawables_.Begin();
             while (start != rayQueryDrawables_.End())
             {
+                SharedPtr<WorkItem> item(new WorkItem());
+                item->workFunction_ = RaycastDrawablesWork;
+                item->aux_ = const_cast<Octree*>(this);
+
                 PODVector<Drawable*>::Iterator end = rayQueryDrawables_.End();
                 if (end - start > RAYCASTS_PER_WORK_ITEM)
                     end = start + RAYCASTS_PER_WORK_ITEM;
 
-                item.start_ = &(*start);
-                item.end_ = &(*end);
+                item->start_ = &(*start);
+                item->end_ = &(*end);
                 queue->AddWorkItem(item);
 
                 start = end;

+ 29 - 27
Source/Engine/Graphics/View.cpp

@@ -687,20 +687,20 @@ void View::GetDrawables()
         int numWorkItems = queue->GetNumThreads() + 1; // Worker threads + main thread
         int drawablesPerItem = tempDrawables.Size() / numWorkItems;
         
-        WorkItem item;
-        item.workFunction_ = CheckVisibilityWork;
-        item.aux_ = this;
-        
         PODVector<Drawable*>::Iterator start = tempDrawables.Begin();
         // Create a work item for each thread
         for (int i = 0; i < numWorkItems; ++i)
         {
+            SharedPtr<WorkItem> item(new WorkItem());
+            item->workFunction_ = CheckVisibilityWork;
+            item->aux_ = this;
+
             PODVector<Drawable*>::Iterator end = tempDrawables.End();
             if (i < numWorkItems - 1 && end - start > drawablesPerItem)
                 end = start + drawablesPerItem;
             
-            item.start_ = &(*start);
-            item.end_ = &(*end);
+            item->start_ = &(*start);
+            item->end_ = &(*end);
             queue->AddWorkItem(item);
             
             start = end;
@@ -762,16 +762,16 @@ void View::GetBatches()
         
         lightQueryResults_.Resize(lights_.Size());
         
-        WorkItem item;
-        item.workFunction_ = ProcessLightWork;
-        item.aux_ = this;
-        
         for (unsigned i = 0; i < lightQueryResults_.Size(); ++i)
         {
+            SharedPtr<WorkItem> item(new WorkItem());
+            item->workFunction_ = ProcessLightWork;
+            item->aux_ = this;
+
             LightQueryResult& query = lightQueryResults_[i];
             query.light_ = lights_[i];
             
-            item.start_ = &query;
+            item->start_ = &query;
             queue->AddWorkItem(item);
         }
         
@@ -1048,8 +1048,7 @@ void View::UpdateGeometries()
     
     // Sort batches
     {
-        WorkItem item;
-        
+     
         for (unsigned i = 0; i < renderPath_->commands_.Size(); ++i)
         {
             const RenderPathCommand& command = renderPath_->commands_[i];
@@ -1060,22 +1059,26 @@ void View::UpdateGeometries()
             {
                 BatchQueue* passQueue = &batchQueues_[command.pass_];
                 
-                item.workFunction_ = command.sortMode_ == SORT_FRONTTOBACK ? SortBatchQueueFrontToBackWork :
-                    SortBatchQueueBackToFrontWork;
-                item.start_ = &batchQueues_[command.pass_];
+                SharedPtr<WorkItem> item(new WorkItem());
+                item->workFunction_ = command.sortMode_ == SORT_FRONTTOBACK ? SortBatchQueueFrontToBackWork : SortBatchQueueBackToFrontWork;
+                item->start_ = &batchQueues_[command.pass_];
                 queue->AddWorkItem(item);
             }
         }
         
         for (Vector<LightBatchQueue>::Iterator i = lightQueues_.Begin(); i != lightQueues_.End(); ++i)
         {
-            item.workFunction_ = SortLightQueueWork;
-            item.start_ = &(*i);
-            queue->AddWorkItem(item);
+            SharedPtr<WorkItem> lightItem(new WorkItem());
+            lightItem->workFunction_ = SortLightQueueWork;
+            lightItem->start_ = &(*i);
+            queue->AddWorkItem(lightItem);
+
             if (i->shadowSplits_.Size())
             {
-                item.workFunction_ = SortShadowQueueWork;
-                queue->AddWorkItem(item);
+                SharedPtr<WorkItem> shadowItem(new WorkItem());
+                shadowItem->workFunction_ = SortShadowQueueWork;
+                shadowItem->start_ = &(*i);
+                queue->AddWorkItem(shadowItem);
             }
         }
     }
@@ -1107,10 +1110,6 @@ void View::UpdateGeometries()
             int numWorkItems = queue->GetNumThreads() + 1; // Worker threads + main thread
             int drawablesPerItem = threadedGeometries_.Size() / numWorkItems;
             
-            WorkItem item;
-            item.workFunction_ = UpdateDrawableGeometriesWork;
-            item.aux_ = const_cast<FrameInfo*>(&frame_);
-            
             PODVector<Drawable*>::Iterator start = threadedGeometries_.Begin();
             for (int i = 0; i < numWorkItems; ++i)
             {
@@ -1118,8 +1117,11 @@ void View::UpdateGeometries()
                 if (i < numWorkItems - 1 && end - start > drawablesPerItem)
                     end = start + drawablesPerItem;
                 
-                item.start_ = &(*start);
-                item.end_ = &(*end);
+                SharedPtr<WorkItem> item(new WorkItem());
+                item->workFunction_ = UpdateDrawableGeometriesWork;
+                item->aux_ = const_cast<FrameInfo*>(&frame_);
+                item->start_ = &(*start);
+                item->end_ = &(*end);
                 queue->AddWorkItem(item);
                 
                 start = end;