From 8e1c514a9c5c289d9c5059f58ce912b709ff0104 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 11:51:53 -0800 Subject: [PATCH 1/7] Replace scene buckets with nonspatial set --- libraries/render/src/render/Item.h | 7 +- libraries/render/src/render/Scene.cpp | 112 +++++++------------------- libraries/render/src/render/Scene.h | 41 +++------- 3 files changed, 46 insertions(+), 114 deletions(-) diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 8aaaf07300..53e1f3f0df 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -112,6 +112,7 @@ public: bool isPickable() const { return _flags[PICKABLE]; } bool isLayered() const { return _flags[LAYERED]; } + bool isSpatial() const { return !isLayered(); } // Probably not public, flags used by the scene bool isSmall() const { return _flags[SMALLER]; } @@ -315,8 +316,10 @@ public: // Main scene / item managment interface Reset/Update/Kill void resetPayload(const PayloadPointer& payload); void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); } - void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); } // Communicate update to the payload - void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Kill means forget the payload and key and cell + // Communicate the update to the payload + void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); _key = _payload->getKey(); } + // Forget the payload, key, and cell + void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // Check heuristic key const ItemKey& getKey() const { return _key; } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 58b1e61046..624f639d79 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -15,59 +15,11 @@ using namespace render; -void ItemBucketMap::insert(const ItemID& id, const ItemKey& key) { - // Insert the itemID in every bucket where it filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(key)) { - bucket.second.insert(id); - } - } -} -void ItemBucketMap::erase(const ItemID& id, const ItemKey& key) { - // Remove the itemID in every bucket where it filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(key)) { - bucket.second.erase(id); - } - } -} - -void ItemBucketMap::reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey) { - // Reset the itemID in every bucket, - // Remove from the buckets where oldKey filters true AND newKey filters false - // Insert into the buckets where newKey filters true - for (auto& bucket : (*this)) { - if (bucket.first.test(oldKey)) { - if (!bucket.first.test(newKey)) { - bucket.second.erase(id); - } - } else if (bucket.first.test(newKey)) { - bucket.second.insert(id); - } - } -} - -void ItemBucketMap::allocateStandardOpaqueTranparentBuckets() { - (*this)[ItemFilter::Builder::opaqueShape().withoutLayered()]; - (*this)[ItemFilter::Builder::transparentShape().withoutLayered()]; - (*this)[ItemFilter::Builder::light()]; - (*this)[ItemFilter::Builder::background()]; - (*this)[ItemFilter::Builder::opaqueShape().withLayered()]; - (*this)[ItemFilter::Builder::transparentShape().withLayered()]; -} - - void PendingChanges::resetItem(ItemID id, const PayloadPointer& payload) { _resetItems.push_back(id); _resetPayloads.push_back(payload); } -void PendingChanges::resortItem(ItemID id, ItemKey oldKey, ItemKey newKey) { - _resortItems.push_back(id); - _resortOldKeys.push_back(oldKey); - _resortNewKeys.push_back(newKey); -} - void PendingChanges::removeItem(ItemID id) { _removedItems.push_back(id); } @@ -80,9 +32,6 @@ void PendingChanges::updateItem(ItemID id, const UpdateFunctorPointer& functor) void PendingChanges::merge(PendingChanges& changes) { _resetItems.insert(_resetItems.end(), changes._resetItems.begin(), changes._resetItems.end()); _resetPayloads.insert(_resetPayloads.end(), changes._resetPayloads.begin(), changes._resetPayloads.end()); - _resortItems.insert(_resortItems.end(), changes._resortItems.begin(), changes._resortItems.end()); - _resortOldKeys.insert(_resortOldKeys.end(), changes._resortOldKeys.begin(), changes._resortOldKeys.end()); - _resortNewKeys.insert(_resortNewKeys.end(), changes._resortNewKeys.begin(), changes._resortNewKeys.end()); _removedItems.insert(_removedItems.end(), changes._removedItems.begin(), changes._removedItems.end()); _updatedItems.insert(_updatedItems.end(), changes._updatedItems.begin(), changes._updatedItems.end()); _updateFunctors.insert(_updateFunctors.end(), changes._updateFunctors.begin(), changes._updateFunctors.end()); @@ -92,7 +41,6 @@ Scene::Scene(glm::vec3 origin, float size) : _masterSpatialTree(origin, size) { _items.push_back(Item()); // add the itemID #0 to nothing - _masterBucketMap.allocateStandardOpaqueTranparentBuckets(); } ItemID Scene::allocateID() { @@ -133,7 +81,6 @@ void Scene::processPendingChangesQueue() { // capture anything coming from the pendingChanges resetItems(consolidatedPendingChanges._resetItems, consolidatedPendingChanges._resetPayloads); updateItems(consolidatedPendingChanges._updatedItems, consolidatedPendingChanges._updateFunctors); - resortItems(consolidatedPendingChanges._resortItems, consolidatedPendingChanges._resortOldKeys, consolidatedPendingChanges._resortNewKeys); removeItems(consolidatedPendingChanges._removedItems); // ready to go back to rendering activities @@ -141,7 +88,6 @@ void Scene::processPendingChangesQueue() { } void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { - auto resetPayload = payloads.begin(); for (auto resetID : ids) { // Access the true item @@ -153,28 +99,18 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { item.resetPayload(*resetPayload); auto newKey = item.getKey(); - - // Reset the item in the Bucket map - _masterBucketMap.reset(resetID, oldKey, newKey); - - // Reset the item in the spatial tree - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); - item.resetCell(newCell, newKey.isSmall()); + // Update the item's container + assert((oldKey.isSpatial() == newKey.isSpatial()) || oldKey._flags.none()); + if (newKey.isSpatial()) { + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } // next loop resetPayload++; } } -void Scene::resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys) { - auto resortID = ids.begin(); - auto oldKey = oldKeys.begin(); - auto newKey = newKeys.begin(); - for (; resortID != ids.end(); resortID++, oldKey++, newKey++) { - _masterBucketMap.reset(*resortID, *oldKey, *newKey); - } -} - void Scene::removeItems(const ItemIDs& ids) { for (auto removedID :ids) { // Access the true item @@ -182,11 +118,12 @@ void Scene::removeItems(const ItemIDs& ids) { auto oldCell = item.getCell(); auto oldKey = item.getKey(); - // Remove from Bucket map - _masterBucketMap.erase(removedID, item.getKey()); - - // Remove from spatial tree - _masterSpatialTree.removeItem(oldCell, oldKey, removedID); + // Remove the item + if (oldKey.isSpatial()) { + _masterSpatialTree.removeItem(oldCell, oldKey, removedID); + } else { + _masterNonspatialSet.erase(removedID); + } // Kill it item.kill(); @@ -202,14 +139,27 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { auto oldCell = item.getCell(); auto oldKey = item.getKey(); - // Update it - _items[updateID].update((*updateFunctor)); - + // Update the item + item.update((*updateFunctor)); auto newKey = item.getKey(); - // Update the citem in the spatial tree if needed - auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); - item.resetCell(newCell, newKey.isSmall()); + // Update the item's container + if (oldKey.isSpatial() == newKey.isSpatial()) { + if (newKey.isSpatial()) { + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } + } else { + if (newKey.isSpatial()) { + _masterNonspatialSet.erase(updateID); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); + item.resetCell(newCell, newKey.isSmall()); + } else { + _masterSpatialTree.removeItem(oldCell, oldKey, updateID); + _masterNonspatialSet.insert(updateID); + } + } + // next loop updateFunctor++; diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 63aa2ba831..8516c234dd 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -17,21 +17,6 @@ namespace render { -// A map of ItemIDSets allowing to create bucket lists of items which are filtered according to their key -class ItemBucketMap : public std::map { -public: - - ItemBucketMap() {} - - void insert(const ItemID& id, const ItemKey& key); - void erase(const ItemID& id, const ItemKey& key); - void reset(const ItemID& id, const ItemKey& oldKey, const ItemKey& newKey); - - // standard builders allocating the main buckets - void allocateStandardOpaqueTranparentBuckets(); - -}; - class Engine; class PendingChanges { @@ -40,7 +25,6 @@ public: ~PendingChanges() {} void resetItem(ItemID id, const PayloadPointer& payload); - void resortItem(ItemID id, ItemKey oldKey, ItemKey newKey); void removeItem(ItemID id); template void updateItem(ItemID id, std::function func) { @@ -53,9 +37,6 @@ public: ItemIDs _resetItems; Payloads _resetPayloads; - ItemIDs _resortItems; - ItemKeys _resortOldKeys; - ItemKeys _resortNewKeys; ItemIDs _removedItems; ItemIDs _updatedItems; UpdateFunctors _updateFunctors; @@ -75,27 +56,27 @@ public: Scene(glm::vec3 origin, float size); ~Scene() {} - /// This call is thread safe, can be called from anywhere to allocate a new ID + // This call is thread safe, can be called from anywhere to allocate a new ID ItemID allocateID(); - /// Enqueue change batch to the scene + // Enqueue change batch to the scene void enqueuePendingChanges(const PendingChanges& pendingChanges); // Process the penging changes equeued void processPendingChangesQueue(); - /// Access a particular item form its ID - /// WARNING, There is No check on the validity of the ID, so this could return a bad Item + // Access a particular item form its ID + // WARNING, There is No check on the validity of the ID, so this could return a bad Item const Item& getItem(const ItemID& id) const { return _items[id]; } size_t getNumItems() const { return _items.size(); } - /// Access the main bucketmap of items - const ItemBucketMap& getMasterBucket() const { return _masterBucketMap; } - - /// Access the item spatial tree + // Access the spatialized items const ItemSpatialTree& getSpatialTree() const { return _masterSpatialTree; } - + + // Access non-spatialized items (overlays, backgrounds) + const ItemIDSet& getNonspatialSet() const { return _masterNonspatialSet; } + protected: // Thread safe elements that can be accessed from anywhere std::atomic _IDAllocator{ 1 }; // first valid itemID will be One @@ -106,12 +87,10 @@ protected: // database of items is protected for editing by a mutex std::mutex _itemsMutex; Item::Vector _items; - ItemBucketMap _masterBucketMap; ItemSpatialTree _masterSpatialTree; - + ItemIDSet _masterNonspatialSet; void resetItems(const ItemIDs& ids, Payloads& payloads); - void resortItems(const ItemIDs& ids, ItemKeys& oldKeys, ItemKeys& newKeys); void removeItems(const ItemIDs& ids); void updateItems(const ItemIDs& ids, UpdateFunctors& functors); From 6c3dd027a70adfcc1ba2b9a5ef8cd8a63198a231 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 11:58:21 -0800 Subject: [PATCH 2/7] Use spatial tree for shadow fetch --- .../render-utils/src/RenderShadowTask.cpp | 20 +++++++++---------- 1 file changed, 9 insertions(+), 11 deletions(-) diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index f8057c164b..c5ae5f0f6a 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -104,19 +104,17 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha skinProgram, state); } - // CPU: Fetch shadow-casting opaques - const auto fetchedItems = addJob("FetchShadowMap"); + // CPU jobs: + // Fetch and cull the items from the scene + auto shadowFilter = ItemFilter::Builder::visibleWorldItems().withTypeShape().withOpaque().withoutLayered(); + const auto shadowSelection = addJob("FetchShadowSelection", shadowFilter); + const auto culledShadowSelection = addJob("CullShadowSelection", shadowSelection, cullFunctor, RenderDetails::SHADOW, shadowFilter); - // CPU: Cull against KeyLight frustum (nearby viewing camera) - const auto culledItems = addJob>("CullShadowMap", fetchedItems, cullFunctor); + // Sort + const auto sortedShapes = addJob("PipelineSortShadowSort", culledShadowSelection); + const auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); - // CPU: Sort by pipeline - const auto sortedShapes = addJob("PipelineSortShadowSort", culledItems); - - // CPU: Sort front to back - const auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); - - // GPU: Render to shadow map + // GPU jobs: Render to shadow map addJob("RenderShadowMap", shadowShapes, shapePlumber); } From 2cd6706a6a39a4f3d946f1095604ade16ba7004a Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 12:10:20 -0800 Subject: [PATCH 3/7] Update fetch to use nonspatialSet --- .../render-utils/src/RenderDeferredTask.cpp | 54 +++++++++---------- .../render-utils/src/RenderDeferredTask.h | 4 +- libraries/render/src/render/CullTask.cpp | 23 +++----- libraries/render/src/render/CullTask.h | 45 ++-------------- libraries/render/src/render/DrawTask.cpp | 15 ------ libraries/render/src/render/DrawTask.h | 10 ---- 6 files changed, 38 insertions(+), 113 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 31f40f5285..d2209ae321 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -54,34 +54,42 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // CPU jobs: // Fetch and cull the items from the scene - auto sceneFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); - const auto sceneSelection = addJob("FetchSceneSelection", sceneFilter); - const auto culledSceneSelection = addJob("CullSceneSelection", sceneSelection, cullFunctor, RenderDetails::ITEM, sceneFilter); + auto spatialFilter = ItemFilter::Builder::visibleWorldItems().withoutLayered(); + const auto spatialSelection = addJob("FetchSceneSelection", spatialFilter); + const auto culledSpatialSelection = addJob("CullSceneSelection", spatialSelection, cullFunctor, RenderDetails::ITEM, spatialFilter); + + // Overlays are not culled + const auto nonspatialSelection = addJob("FetchOverlaySelection"); // Multi filter visible items into different buckets const int NUM_FILTERS = 3; const int OPAQUE_SHAPE_BUCKET = 0; const int TRANSPARENT_SHAPE_BUCKET = 1; const int LIGHT_BUCKET = 2; - MultiFilterItem::ItemFilterArray triageFilters = { { + const int BACKGROUND_BUCKET = 2; + MultiFilterItem::ItemFilterArray spatialFilters = { { ItemFilter::Builder::opaqueShape(), ItemFilter::Builder::transparentShape(), ItemFilter::Builder::light() } }; - const auto filteredItemsBuckets = addJob>("FilterSceneSelection", culledSceneSelection, triageFilters).get::ItemBoundsArray>(); + MultiFilterItem::ItemFilterArray nonspatialFilters = { { + ItemFilter::Builder::opaqueShape(), + ItemFilter::Builder::transparentShape(), + ItemFilter::Builder::background() + } }; + const auto filteredSpatialBuckets = addJob>("FilterSceneSelection", culledSpatialSelection, spatialFilters).get::ItemBoundsArray>(); + const auto filteredNonspatialBuckets = addJob>("FilterOverlaySelection", nonspatialSelection, nonspatialFilters).get::ItemBoundsArray>(); // Extract / Sort opaques / Transparents / Lights / Overlays - const auto opaques = addJob("DepthSortOpaque", filteredItemsBuckets[OPAQUE_SHAPE_BUCKET]); - const auto transparents = addJob("DepthSortTransparent", filteredItemsBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); - const auto lights = filteredItemsBuckets[LIGHT_BUCKET]; + const auto opaques = addJob("DepthSortOpaque", filteredSpatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto transparents = addJob("DepthSortTransparent", filteredSpatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto lights = filteredSpatialBuckets[LIGHT_BUCKET]; - // Overlays are not culled because we want to make sure they are seen - // Could be considered a bug in the current cullfunctor - const auto overlayOpaques = addJob("FetchOverlayOpaque", ItemFilter::Builder::opaqueShapeLayered()); - const auto fetchedOverlayOpaques = addJob("FetchOverlayTransparents", ItemFilter::Builder::transparentShapeLayered()); - const auto overlayTransparents = addJob("DepthSortTransparentOverlay", fetchedOverlayOpaques, DepthSortItems(false)); + const auto overlayOpaques = addJob("DepthSortOverlayOpaque", filteredNonspatialBuckets[OPAQUE_SHAPE_BUCKET]); + const auto overlayTransparents = addJob("DepthSortOverlayTransparent", filteredNonspatialBuckets[TRANSPARENT_SHAPE_BUCKET], DepthSortItems(false)); + const auto background = filteredNonspatialBuckets[BACKGROUND_BUCKET]; - // GPU Jobs: Start preparing the deferred and lighting buffer + // GPU jobs: Start preparing the deferred and lighting buffer addJob("PrepareDeferred"); // Render opaque objects in DeferredBuffer @@ -91,7 +99,7 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { addJob("DrawOpaqueStencil"); // Use Stencil and start drawing background in Lighting buffer - addJob("DrawBackgroundDeferred"); + addJob("DrawBackgroundDeferred", background); // AO job addJob("AmbientOcclusion"); @@ -123,8 +131,8 @@ RenderDeferredTask::RenderDeferredTask(CullFunctor cullFunctor) { // Scene Octree Debuging job { - addJob("DrawSceneOctree", sceneSelection); - addJob("DrawItemSelection", sceneSelection); + addJob("DrawSceneOctree", spatialSelection); + addJob("DrawItemSelection", spatialSelection); } // Status icon rendering job @@ -276,20 +284,10 @@ void DrawStencilDeferred::run(const SceneContextPointer& sceneContext, const Ren args->_batch = nullptr; } -void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext) { +void DrawBackgroundDeferred::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); - // render backgrounds - auto& scene = sceneContext->_scene; - auto& items = scene->getMasterBucket().at(ItemFilter::Builder::background()); - - - ItemBounds inItems; - inItems.reserve(items.size()); - for (auto id : items) { - inItems.emplace_back(id); - } RenderArgs* args = renderContext->args; doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index 5591edce7c..f8837f5b24 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -85,9 +85,9 @@ protected: class DrawBackgroundDeferred { public: - void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext); + void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, const render::ItemBounds& inItems); - using JobModel = render::Job::Model; + using JobModel = render::Job::ModelI; }; class DrawOverlay3DConfig : public render::Job::Config { diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 7824514649..7c5f5184da 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -129,32 +129,21 @@ void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderCo depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); } - -void FetchItems::configure(const Config& config) { -} - -void FetchItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) { +void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); auto& scene = sceneContext->_scene; outItems.clear(); - const auto& bucket = scene->getMasterBucket(); - const auto& items = bucket.find(_filter); - if (items != bucket.end()) { - outItems.reserve(items->second.size()); - for (auto& id : items->second) { - auto& item = scene->getItem(id); - outItems.emplace_back(ItemBound(id, item.getBound())); - } + const auto& items = scene->getNonspatialSet(); + outItems.reserve(items.size()); + for (auto& id : items) { + auto& item = scene->getItem(id); + outItems.emplace_back(ItemBound(id, item.getBound())); } - - std::static_pointer_cast(renderContext->jobConfig)->numItems = (int)outItems.size(); } - - void FetchSpatialTree::configure(const Config& config) { _justFrozeFrustum = _justFrozeFrustum || (config.freezeFrustum && !_freezeFrustum); _freezeFrustum = config.freezeFrustum; diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 734d683ad7..1306640891 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -23,50 +23,12 @@ namespace render { const ItemBounds& inItems, ItemBounds& outItems); void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems); - class FetchItemsConfig : public Job::Config { - Q_OBJECT - Q_PROPERTY(int numItems READ getNumItems) + class FetchNonspatialItems { public: - int getNumItems() { return numItems; } - - int numItems{ 0 }; - }; - - class FetchItems { - public: - using Config = FetchItemsConfig; - using JobModel = Job::ModelO; - - FetchItems() {} - FetchItems(const ItemFilter& filter) : _filter(filter) {} - - ItemFilter _filter{ ItemFilter::Builder::opaqueShape().withoutLayered() }; - - void configure(const Config& config); + using JobModel = Job::ModelO; void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems); }; - - template - class CullItems { - public: - using JobModel = Job::ModelIO, ItemBounds, ItemBounds>; - - CullItems(CullFunctor cullFunctor) : _cullFunctor{ cullFunctor } {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { - const auto& args = renderContext->args; - auto& details = args->_details.edit(T); - outItems.clear(); - outItems.reserve(inItems.size()); - render::cullItems(renderContext, _cullFunctor, details, inItems, outItems); - } - - protected: - CullFunctor _cullFunctor; - }; - - class FetchSpatialTreeConfig : public Job::Config { Q_OBJECT Q_PROPERTY(int numItems READ getNumItems) @@ -209,13 +171,14 @@ namespace render { outItems[i].template edit().clear(); } - // For each item, filter it into the buckets + // For each item, filter it into one bucket for (auto itemBound : inItems) { auto& item = scene->getItem(itemBound.id); auto itemKey = item.getKey(); for (size_t i = 0; i < NUM_FILTERS; i++) { if (_filters[i].test(itemKey)) { outItems[i].template edit().emplace_back(itemBound); + break; } } } diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 5ad6ca0547..85bb01a378 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -93,18 +93,3 @@ void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const Rend items.second.shrink_to_fit(); } } - -void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes) { - outShapes.clear(); - outShapes.reserve(inShapes.size()); - - for (auto& pipeline : inShapes) { - auto& inItems = pipeline.second; - auto outItems = outShapes.find(pipeline.first); - if (outItems == outShapes.end()) { - outItems = outShapes.insert(std::make_pair(pipeline.first, ItemBounds{})).first; - } - - depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems->second); - } -} diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index a52bd3192f..29543dfb3e 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -37,16 +37,6 @@ public: void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapesIDsBounds& outShapes); }; -class DepthSortShapes { -public: - using JobModel = Job::ModelIO; - - bool _frontToBack; - DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapesIDsBounds& inShapes, ShapesIDsBounds& outShapes); -}; - } #endif // hifi_render_DrawTask_h From 5995c3717f44a26d6a2caf7999d47d0ada64b338 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 14:42:00 -0800 Subject: [PATCH 4/7] Continue updating overlay key on edit --- interface/src/ui/overlays/Overlays.cpp | 20 ++++++++------------ libraries/render/src/render/Item.cpp | 7 +++++++ libraries/render/src/render/Item.h | 8 +++----- libraries/render/src/render/Scene.h | 1 + 4 files changed, 19 insertions(+), 17 deletions(-) diff --git a/interface/src/ui/overlays/Overlays.cpp b/interface/src/ui/overlays/Overlays.cpp index 2bc1286419..5a2d05815b 100644 --- a/interface/src/ui/overlays/Overlays.cpp +++ b/interface/src/ui/overlays/Overlays.cpp @@ -233,23 +233,19 @@ bool Overlays::editOverlay(unsigned int id, const QScriptValue& properties) { Overlay::Pointer thisOverlay = getOverlay(id); if (thisOverlay) { + thisOverlay->setProperties(properties); + if (thisOverlay->is3D()) { - render::ItemKey oldItemKey = render::payloadGetKey(thisOverlay); - - thisOverlay->setProperties(properties); - - render::ItemKey itemKey = render::payloadGetKey(thisOverlay); - if (itemKey != oldItemKey) { - auto itemID = thisOverlay->getRenderItemID(); - if (render::Item::isValidID(itemID)) { - render::ScenePointer scene = qApp->getMain3DScene(); + auto itemID = thisOverlay->getRenderItemID(); + if (render::Item::isValidID(itemID)) { + render::ScenePointer scene = qApp->getMain3DScene(); + const render::Item& item = scene->getItem(itemID); + if (item.getKey() != render::payloadGetKey(thisOverlay)) { render::PendingChanges pendingChanges; - pendingChanges.resortItem(itemID, oldItemKey, itemKey); + pendingChanges.updateItem(itemID); scene->enqueuePendingChanges(pendingChanges); } } - } else { - thisOverlay->setProperties(properties); } return true; diff --git a/libraries/render/src/render/Item.cpp b/libraries/render/src/render/Item.cpp index e5356c2b0c..f80563bf73 100644 --- a/libraries/render/src/render/Item.cpp +++ b/libraries/render/src/render/Item.cpp @@ -63,6 +63,13 @@ void Item::PayloadInterface::addStatusGetters(const Status::Getters& getters) { } } +void Item::update(const UpdateFunctorPointer& updateFunctor) { + if (updateFunctor) { + _payload->update(updateFunctor); + } + _key = _payload->getKey(); +} + void Item::resetPayload(const PayloadPointer& payload) { if (!payload) { kill(); diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index 53e1f3f0df..ddc5a92c9d 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -313,13 +313,11 @@ public: Item() {} ~Item() {} - // Main scene / item managment interface Reset/Update/Kill + // Main scene / item managment interface reset/update/kill void resetPayload(const PayloadPointer& payload); void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); } - // Communicate the update to the payload - void update(const UpdateFunctorPointer& updateFunctor) { _payload->update(updateFunctor); _key = _payload->getKey(); } - // Forget the payload, key, and cell - void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } + void update(const UpdateFunctorPointer& updateFunctor); // communicate update to payload + void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // forget the payload, key, cell // Check heuristic key const ItemKey& getKey() const { return _key; } diff --git a/libraries/render/src/render/Scene.h b/libraries/render/src/render/Scene.h index 8516c234dd..40c0baca60 100644 --- a/libraries/render/src/render/Scene.h +++ b/libraries/render/src/render/Scene.h @@ -32,6 +32,7 @@ public: } void updateItem(ItemID id, const UpdateFunctorPointer& functor); + void updateItem(ItemID id) { updateItem(id, nullptr); } void merge(PendingChanges& changes); From 56aac35348b9e9aa08be09eddbcb6534086cb8b3 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 15:24:37 -0800 Subject: [PATCH 5/7] Fix drawInFront bugs --- libraries/render/src/render/Item.h | 4 ++-- libraries/render/src/render/Scene.cpp | 5 +++++ 2 files changed, 7 insertions(+), 2 deletions(-) diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index ddc5a92c9d..c075b281f3 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -315,9 +315,9 @@ public: // Main scene / item managment interface reset/update/kill void resetPayload(const PayloadPointer& payload); - void resetCell(ItemCell cell, bool _small) { _cell = cell; _key.setSmaller(_small); } + void resetCell(ItemCell cell = INVALID_CELL, bool _small = false) { _cell = cell; _key.setSmaller(_small); } void update(const UpdateFunctorPointer& updateFunctor); // communicate update to payload - void kill() { _payload.reset(); _key._flags.reset(); _cell = INVALID_CELL; } // forget the payload, key, cell + void kill() { _payload.reset(); resetCell(); _key._flags.reset(); } // forget the payload, key, cell // Check heuristic key const ItemKey& getKey() const { return _key; } diff --git a/libraries/render/src/render/Scene.cpp b/libraries/render/src/render/Scene.cpp index 624f639d79..0cdd736fee 100644 --- a/libraries/render/src/render/Scene.cpp +++ b/libraries/render/src/render/Scene.cpp @@ -104,6 +104,8 @@ void Scene::resetItems(const ItemIDs& ids, Payloads& payloads) { if (newKey.isSpatial()) { auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), resetID, newKey); item.resetCell(newCell, newKey.isSmall()); + } else { + _masterNonspatialSet.insert(resetID); } // next loop @@ -152,10 +154,13 @@ void Scene::updateItems(const ItemIDs& ids, UpdateFunctors& functors) { } else { if (newKey.isSpatial()) { _masterNonspatialSet.erase(updateID); + auto newCell = _masterSpatialTree.resetItem(oldCell, oldKey, item.getBound(), updateID, newKey); item.resetCell(newCell, newKey.isSmall()); } else { _masterSpatialTree.removeItem(oldCell, oldKey, updateID); + item.resetCell(); + _masterNonspatialSet.insert(updateID); } } From 30fbd99d1130de92a67fd11d851d3ab8026dc809 Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 16:04:15 -0800 Subject: [PATCH 6/7] Factor out SortTask to fix shadows --- .../render-utils/src/RenderDeferredTask.cpp | 13 +- .../render-utils/src/RenderDeferredTask.h | 5 +- .../render-utils/src/RenderShadowTask.cpp | 18 ++- libraries/render-utils/src/RenderShadowTask.h | 6 +- libraries/render/src/render/CullTask.cpp | 67 ---------- libraries/render/src/render/CullTask.h | 11 -- libraries/render/src/render/DrawTask.cpp | 20 --- libraries/render/src/render/DrawTask.h | 10 -- libraries/render/src/render/Item.h | 2 +- libraries/render/src/render/SortTask.cpp | 120 ++++++++++++++++++ libraries/render/src/render/SortTask.h | 47 +++++++ 11 files changed, 192 insertions(+), 127 deletions(-) create mode 100644 libraries/render/src/render/SortTask.cpp create mode 100644 libraries/render/src/render/SortTask.h diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index d2209ae321..27316007b7 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -10,27 +10,30 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RenderDeferredTask.h" + #include #include #include #include #include +#include +#include +#include +#include +#include + #include "DebugDeferredBuffer.h" #include "DeferredLightingEffect.h" #include "FramebufferCache.h" #include "HitEffect.h" #include "TextureCache.h" -#include "render/DrawTask.h" -#include "render/DrawStatus.h" -#include "render/DrawSceneOctree.h" #include "AmbientOcclusionEffect.h" #include "AntialiasingEffect.h" #include "ToneMappingEffect.h" -#include "RenderDeferredTask.h" - using namespace render; extern void initStencilPipeline(gpu::PipelinePointer& pipeline); diff --git a/libraries/render-utils/src/RenderDeferredTask.h b/libraries/render-utils/src/RenderDeferredTask.h index f8837f5b24..bbcaec34f3 100755 --- a/libraries/render-utils/src/RenderDeferredTask.h +++ b/libraries/render-utils/src/RenderDeferredTask.h @@ -12,9 +12,8 @@ #ifndef hifi_RenderDeferredTask_h #define hifi_RenderDeferredTask_h -#include "gpu/Pipeline.h" - -#include "render/DrawTask.h" +#include +#include class SetupDeferred { public: diff --git a/libraries/render-utils/src/RenderShadowTask.cpp b/libraries/render-utils/src/RenderShadowTask.cpp index c5ae5f0f6a..d9e0c06a90 100644 --- a/libraries/render-utils/src/RenderShadowTask.cpp +++ b/libraries/render-utils/src/RenderShadowTask.cpp @@ -9,16 +9,20 @@ // See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html // +#include "RenderShadowTask.h" + #include #include -#include "render/Context.h" +#include +#include +#include +#include + #include "DeferredLightingEffect.h" #include "FramebufferCache.h" -#include "RenderShadowTask.h" - #include "model_shadow_vert.h" #include "skin_model_shadow_vert.h" @@ -28,7 +32,7 @@ using namespace render; void RenderShadowMap::run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, - const render::ShapesIDsBounds& inShapes) { + const render::ShapeBounds& inShapes) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); @@ -111,11 +115,11 @@ RenderShadowTask::RenderShadowTask(CullFunctor cullFunctor) : Task(std::make_sha const auto culledShadowSelection = addJob("CullShadowSelection", shadowSelection, cullFunctor, RenderDetails::SHADOW, shadowFilter); // Sort - const auto sortedShapes = addJob("PipelineSortShadowSort", culledShadowSelection); - const auto shadowShapes = addJob("DepthSortShadowMap", sortedShapes); + const auto sortedPipelines = addJob("PipelineSortShadowSort", culledShadowSelection); + const auto sortedShapes = addJob("DepthSortShadowMap", sortedPipelines); // GPU jobs: Render to shadow map - addJob("RenderShadowMap", shadowShapes, shapePlumber); + addJob("RenderShadowMap", sortedShapes, shapePlumber); } void RenderShadowTask::configure(const Config& configuration) { diff --git a/libraries/render-utils/src/RenderShadowTask.h b/libraries/render-utils/src/RenderShadowTask.h index 679302b69f..4a6ff1b0e9 100644 --- a/libraries/render-utils/src/RenderShadowTask.h +++ b/libraries/render-utils/src/RenderShadowTask.h @@ -15,17 +15,17 @@ #include #include -#include +#include class ViewFrustum; class RenderShadowMap { public: - using JobModel = render::Job::ModelI; + using JobModel = render::Job::ModelI; RenderShadowMap(render::ShapePlumberPointer shapePlumber) : _shapePlumber{ shapePlumber } {} void run(const render::SceneContextPointer& sceneContext, const render::RenderContextPointer& renderContext, - const render::ShapesIDsBounds& inShapes); + const render::ShapeBounds& inShapes); protected: render::ShapePlumberPointer _shapePlumber; diff --git a/libraries/render/src/render/CullTask.cpp b/libraries/render/src/render/CullTask.cpp index 7c5f5184da..484f049944 100644 --- a/libraries/render/src/render/CullTask.cpp +++ b/libraries/render/src/render/CullTask.cpp @@ -62,73 +62,6 @@ void render::cullItems(const RenderContextPointer& renderContext, const CullFunc details._rendered += (int)outItems.size(); } -struct ItemBoundSort { - float _centerDepth = 0.0f; - float _nearDepth = 0.0f; - float _farDepth = 0.0f; - ItemID _id = 0; - AABox _bounds; - - ItemBoundSort() {} - ItemBoundSort(float centerDepth, float nearDepth, float farDepth, ItemID id, const AABox& bounds) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id), _bounds(bounds) {} -}; - -struct FrontToBackSort { - bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) { - return (left._centerDepth < right._centerDepth); - } -}; - -struct BackToFrontSort { - bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) { - return (left._centerDepth > right._centerDepth); - } -}; - -void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { - assert(renderContext->args); - assert(renderContext->args->_viewFrustum); - - auto& scene = sceneContext->_scene; - RenderArgs* args = renderContext->args; - - - // Allocate and simply copy - outItems.clear(); - outItems.reserve(inItems.size()); - - - // Make a local dataset of the center distance and closest point distance - std::vector itemBoundSorts; - itemBoundSorts.reserve(outItems.size()); - - for (auto itemDetails : inItems) { - auto item = scene->getItem(itemDetails.id); - auto bound = itemDetails.bound; // item.getBound(); - float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); - - itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound)); - } - - // sort against Z - if (frontToBack) { - FrontToBackSort frontToBackSort; - std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), frontToBackSort); - } else { - BackToFrontSort backToFrontSort; - std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), backToFrontSort); - } - - // FInally once sorted result to a list of itemID - for (auto& item : itemBoundSorts) { - outItems.emplace_back(ItemBound(item._id, item._bounds)); - } -} - -void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { - depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); -} - void FetchNonspatialItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, ItemBounds& outItems) { assert(renderContext->args); assert(renderContext->args->_viewFrustum); diff --git a/libraries/render/src/render/CullTask.h b/libraries/render/src/render/CullTask.h index 1306640891..a6a32e4561 100644 --- a/libraries/render/src/render/CullTask.h +++ b/libraries/render/src/render/CullTask.h @@ -21,7 +21,6 @@ namespace render { void cullItems(const RenderContextPointer& renderContext, const CullFunctor& cullFunctor, RenderDetails::Item& details, const ItemBounds& inItems, ItemBounds& outItems); - void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems); class FetchNonspatialItems { public: @@ -184,16 +183,6 @@ namespace render { } } }; - - class DepthSortItems { - public: - using JobModel = Job::ModelIO; - - bool _frontToBack; - DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {} - - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); - }; } #endif // hifi_render_CullTask_h; \ No newline at end of file diff --git a/libraries/render/src/render/DrawTask.cpp b/libraries/render/src/render/DrawTask.cpp index 85bb01a378..733f7d9e9c 100755 --- a/libraries/render/src/render/DrawTask.cpp +++ b/libraries/render/src/render/DrawTask.cpp @@ -73,23 +73,3 @@ void DrawLight::run(const SceneContextPointer& sceneContext, const RenderContext args->_batch = nullptr; }); } - -void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapesIDsBounds& outShapes) { - auto& scene = sceneContext->_scene; - outShapes.clear(); - - for (const auto& item : inItems) { - auto key = scene->getItem(item.id).getShapeKey(); - auto outItems = outShapes.find(key); - if (outItems == outShapes.end()) { - outItems = outShapes.insert(std::make_pair(key, ItemBounds{})).first; - outItems->second.reserve(inItems.size()); - } - - outItems->second.push_back(item); - } - - for (auto& items : outShapes) { - items.second.shrink_to_fit(); - } -} diff --git a/libraries/render/src/render/DrawTask.h b/libraries/render/src/render/DrawTask.h index 29543dfb3e..fc2ab9682f 100755 --- a/libraries/render/src/render/DrawTask.h +++ b/libraries/render/src/render/DrawTask.h @@ -13,10 +13,6 @@ #define hifi_render_DrawTask_h #include "Engine.h" -#include "CullTask.h" -#include "ShapePipeline.h" -#include "gpu/Batch.h" - namespace render { @@ -31,12 +27,6 @@ public: protected: }; -class PipelineSortShapes { -public: - using JobModel = Job::ModelIO; - void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapesIDsBounds& outShapes); -}; - } #endif // hifi_render_DrawTask_h diff --git a/libraries/render/src/render/Item.h b/libraries/render/src/render/Item.h index c075b281f3..fb5534e3ab 100644 --- a/libraries/render/src/render/Item.h +++ b/libraries/render/src/render/Item.h @@ -465,7 +465,7 @@ public: using ItemBounds = std::vector; // A map of items by ShapeKey to optimize rendering pipeline assignments -using ShapesIDsBounds = std::unordered_map; +using ShapeBounds = std::unordered_map; } diff --git a/libraries/render/src/render/SortTask.cpp b/libraries/render/src/render/SortTask.cpp new file mode 100644 index 0000000000..d2fda542b1 --- /dev/null +++ b/libraries/render/src/render/SortTask.cpp @@ -0,0 +1,120 @@ +// +// CullTask.cpp +// render/src/render +// +// Created by Sam Gateau on 2/2/16. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#include "SortTask.h" +#include "ShapePipeline.h" + +#include +#include + +using namespace render; + +struct ItemBoundSort { + float _centerDepth = 0.0f; + float _nearDepth = 0.0f; + float _farDepth = 0.0f; + ItemID _id = 0; + AABox _bounds; + + ItemBoundSort() {} + ItemBoundSort(float centerDepth, float nearDepth, float farDepth, ItemID id, const AABox& bounds) : _centerDepth(centerDepth), _nearDepth(nearDepth), _farDepth(farDepth), _id(id), _bounds(bounds) {} +}; + +struct FrontToBackSort { + bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) { + return (left._centerDepth < right._centerDepth); + } +}; + +struct BackToFrontSort { + bool operator() (const ItemBoundSort& left, const ItemBoundSort& right) { + return (left._centerDepth > right._centerDepth); + } +}; + +void render::depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems) { + assert(renderContext->args); + assert(renderContext->args->_viewFrustum); + + auto& scene = sceneContext->_scene; + RenderArgs* args = renderContext->args; + + + // Allocate and simply copy + outItems.clear(); + outItems.reserve(inItems.size()); + + + // Make a local dataset of the center distance and closest point distance + std::vector itemBoundSorts; + itemBoundSorts.reserve(outItems.size()); + + for (auto itemDetails : inItems) { + auto item = scene->getItem(itemDetails.id); + auto bound = itemDetails.bound; // item.getBound(); + float distance = args->_viewFrustum->distanceToCamera(bound.calcCenter()); + + itemBoundSorts.emplace_back(ItemBoundSort(distance, distance, distance, itemDetails.id, bound)); + } + + // sort against Z + if (frontToBack) { + FrontToBackSort frontToBackSort; + std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), frontToBackSort); + } else { + BackToFrontSort backToFrontSort; + std::sort(itemBoundSorts.begin(), itemBoundSorts.end(), backToFrontSort); + } + + // Finally once sorted result to a list of itemID + for (auto& item : itemBoundSorts) { + outItems.emplace_back(ItemBound(item._id, item._bounds)); + } +} + +void PipelineSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapeBounds& outShapes) { + auto& scene = sceneContext->_scene; + outShapes.clear(); + + for (const auto& item : inItems) { + auto key = scene->getItem(item.id).getShapeKey(); + auto outItems = outShapes.find(key); + if (outItems == outShapes.end()) { + outItems = outShapes.insert(std::make_pair(key, ItemBounds{})).first; + outItems->second.reserve(inItems.size()); + } + + outItems->second.push_back(item); + } + + for (auto& items : outShapes) { + items.second.shrink_to_fit(); + } +} + +void DepthSortShapes::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapeBounds& inShapes, ShapeBounds& outShapes) { + outShapes.clear(); + outShapes.reserve(inShapes.size()); + + for (auto& pipeline : inShapes) { + auto& inItems = pipeline.second; + auto outItems = outShapes.find(pipeline.first); + if (outItems == outShapes.end()) { + outItems = outShapes.insert(std::make_pair(pipeline.first, ItemBounds{})).first; + } + + depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems->second); + } +} + +void DepthSortItems::run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems) { + depthSortItems(sceneContext, renderContext, _frontToBack, inItems, outItems); +} diff --git a/libraries/render/src/render/SortTask.h b/libraries/render/src/render/SortTask.h new file mode 100644 index 0000000000..eb341192aa --- /dev/null +++ b/libraries/render/src/render/SortTask.h @@ -0,0 +1,47 @@ +// +// SortTask.h +// render/src/render +// +// Created by Zach Pomerantz on 2/26/2016. +// Copyright 2016 High Fidelity, Inc. +// +// Distributed under the Apache License, Version 2.0. +// See the accompanying file LICENSE or http://www.apache.org/licenses/LICENSE-2.0.html +// + +#ifndef hifi_render_SortTask_h +#define hifi_render_SortTask_h + +#include "Engine.h" + +namespace render { + void depthSortItems(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, bool frontToBack, const ItemBounds& inItems, ItemBounds& outItems); + + class PipelineSortShapes { + public: + using JobModel = Job::ModelIO; + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ShapeBounds& outShapes); + }; + + class DepthSortShapes { + public: + using JobModel = Job::ModelIO; + + bool _frontToBack; + DepthSortShapes(bool frontToBack = true) : _frontToBack(frontToBack) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ShapeBounds& inShapes, ShapeBounds& outShapes); + }; + + class DepthSortItems { + public: + using JobModel = Job::ModelIO; + + bool _frontToBack; + DepthSortItems(bool frontToBack = true) : _frontToBack(frontToBack) {} + + void run(const SceneContextPointer& sceneContext, const RenderContextPointer& renderContext, const ItemBounds& inItems, ItemBounds& outItems); + }; +} + +#endif // hifi_render_SortTask_h; \ No newline at end of file From 32807012e8124ede2e94549cb6ec01933d8c3aff Mon Sep 17 00:00:00 2001 From: Zach Pomerantz Date: Fri, 26 Feb 2016 16:26:16 -0800 Subject: [PATCH 7/7] Rm redundant texture reset in overlay draw --- libraries/render-utils/src/RenderDeferredTask.cpp | 11 ++++------- 1 file changed, 4 insertions(+), 7 deletions(-) diff --git a/libraries/render-utils/src/RenderDeferredTask.cpp b/libraries/render-utils/src/RenderDeferredTask.cpp index 27316007b7..f87ca26df1 100755 --- a/libraries/render-utils/src/RenderDeferredTask.cpp +++ b/libraries/render-utils/src/RenderDeferredTask.cpp @@ -181,9 +181,9 @@ void DrawDeferred::run(const SceneContextPointer& sceneContext, const RenderCont RenderArgs* args = renderContext->args; gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { + args->_batch = &batch; batch.setViewportTransform(args->_viewport); batch.setStateScissorRect(args->_viewport); - args->_batch = &batch; config->setNumDrawn((int)inItems.size()); emit config->numDrawnChanged(); @@ -233,7 +233,8 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon // Render the items gpu::doInBatch(args->_context, [&](gpu::Batch& batch) { args->_batch = &batch; - args->_whiteTexture = DependencyManager::get()->getWhiteTexture(); + batch.setViewportTransform(args->_viewport); + batch.setStateScissorRect(args->_viewport); glm::mat4 projMat; Transform viewMat; @@ -242,14 +243,10 @@ void DrawOverlay3D::run(const SceneContextPointer& sceneContext, const RenderCon batch.setProjectionTransform(projMat); batch.setViewTransform(viewMat); - batch.setViewportTransform(args->_viewport); - batch.setStateScissorRect(args->_viewport); - batch.setResourceTexture(0, args->_whiteTexture); renderShapes(sceneContext, renderContext, _shapePlumber, inItems, _maxDrawn); + args->_batch = nullptr; }); - args->_batch = nullptr; - args->_whiteTexture.reset(); } }