From 53a36deaacb6329e6e7fc6f0a4c135813ba383e4 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Jaakko=20Kera=CC=88nen?= Date: Wed, 2 Nov 2016 22:09:02 +0200 Subject: [PATCH] Performance|Client: Minor optimizations These optimizations are mostly related to avoiding repeated Surface -> MaterialAnimator lookups. --- doomsday/apps/client/include/render/store.h | 1 - doomsday/apps/client/include/world/bspleaf.h | 4 +-- .../apps/client/include/world/subsector.h | 3 +-- doomsday/apps/client/include/world/surface.h | 11 +++++++- .../client/src/client/clientsubsector.cpp | 6 ++--- doomsday/apps/client/src/render/rend_main.cpp | 27 +++++++++++++++++++ .../apps/client/src/render/shadowedge.cpp | 15 ++++++----- .../apps/client/src/world/base/bspleaf.cpp | 14 ++-------- .../apps/client/src/world/base/maputil.cpp | 27 ++++++++++--------- doomsday/apps/client/src/world/base/plane.cpp | 13 ++++----- .../apps/client/src/world/base/subsector.cpp | 9 +++++-- .../apps/client/src/world/base/surface.cpp | 24 ++++++++++++++++- .../apps/client/src/world/contactspreader.cpp | 4 +-- .../sdk/libcore/include/de/data/binarytree.h | 4 +-- 14 files changed, 108 insertions(+), 54 deletions(-) diff --git a/doomsday/apps/client/include/render/store.h b/doomsday/apps/client/include/render/store.h index 3cecffbc0a..aa4649fd3b 100644 --- a/doomsday/apps/client/include/render/store.h +++ b/doomsday/apps/client/include/render/store.h @@ -47,4 +47,3 @@ struct Store }; #endif // DENG_CLIENT_RENDER_STORE_H - diff --git a/doomsday/apps/client/include/world/bspleaf.h b/doomsday/apps/client/include/world/bspleaf.h index ea85123961..bd64e1f555 100644 --- a/doomsday/apps/client/include/world/bspleaf.h +++ b/doomsday/apps/client/include/world/bspleaf.h @@ -87,8 +87,8 @@ class BspLeaf : public BspElement * intended for legacy compatibility logics which don't care if a subspace exists at * the leaf, or not. */ - Sector *sectorPtr(); - Sector const *sectorPtr() const; + inline Sector *sectorPtr() { return _sector; } + inline Sector const *sectorPtr() const { return _sector; } /** * Attribute this BSP leaf to the given world @a sector. diff --git a/doomsday/apps/client/include/world/subsector.h b/doomsday/apps/client/include/world/subsector.h index b76273c0c0..79186c1f32 100644 --- a/doomsday/apps/client/include/world/subsector.h +++ b/doomsday/apps/client/include/world/subsector.h @@ -226,8 +226,7 @@ class SubsectorCirculator /// Returns the current half-edge of a non-empty sequence. de::HEdge &operator * () const { - if (!_current) - { + if (!_current) { /// @throw NullError Attempted to dereference a "null" circulator. throw NullError("SubsectorCirculator::operator *", "Circulator references an empty sequence"); } diff --git a/doomsday/apps/client/include/world/surface.h b/doomsday/apps/client/include/world/surface.h index 799c07ebbb..fec752ea69 100644 --- a/doomsday/apps/client/include/world/surface.h +++ b/doomsday/apps/client/include/world/surface.h @@ -33,6 +33,7 @@ #ifdef __CLIENT__ class Decoration; +class MaterialAnimator; #endif /** @@ -205,6 +206,14 @@ class Surface : public world::MapElement de::Uri composeMaterialUri() const; #ifdef __CLIENT__ + + MaterialAnimator *materialAnimator() const; + + /** + * Resets all lookups that are used for accelerating common operations. + */ + void resetLookups(); + //- Origin smoothing -------------------------------------------------------------------- /// Notified when the @em sharp material origin changes. @@ -270,4 +279,4 @@ class Surface : public world::MapElement DENG2_PRIVATE(d) }; -#endif // DENG_WORLD_SURFACE_H \ No newline at end of file +#endif // DENG_WORLD_SURFACE_H diff --git a/doomsday/apps/client/src/client/clientsubsector.cpp b/doomsday/apps/client/src/client/clientsubsector.cpp index 5ce2c15526..2fd49005c4 100644 --- a/doomsday/apps/client/src/client/clientsubsector.cpp +++ b/doomsday/apps/client/src/client/clientsubsector.cpp @@ -1011,9 +1011,9 @@ DENG2_PIMPL(ClientSubsector) Vector3d bottomRight, topLeft; if (prepareGeometry(surface, topLeft, bottomRight, materialOrigin)) { - MaterialAnimator &animator = - surface.material().as() - .getAnimator(Rend_MapSurfaceMaterialSpec()); + MaterialAnimator &animator = *surface.materialAnimator(); + //surface.material().as() +// .getAnimator(Rend_MapSurfaceMaterialSpec()); projectDecorations(surface, animator, materialOrigin, topLeft, bottomRight); } diff --git a/doomsday/apps/client/src/render/rend_main.cpp b/doomsday/apps/client/src/render/rend_main.cpp index d1c3bb6082..3f23a19e1d 100644 --- a/doomsday/apps/client/src/render/rend_main.cpp +++ b/doomsday/apps/client/src/render/rend_main.cpp @@ -323,6 +323,33 @@ void Rend_ResetLookups() { lookupMapSurfaceMaterialSpec = nullptr; lookupSpriteMaterialAnimators.clear(); + + if (ClientApp::world().hasMap()) + { + auto &map = ClientApp::world().map(); + + map.forAllSectors([] (Sector §or) + { + sector.forAllPlanes([] (Plane &plane) + { + plane.surface().resetLookups(); + return LoopContinue; + }); + return LoopContinue; + }); + + map.forAllLines([] (Line &line) + { + auto resetFunc = [] (Surface &surface) { + surface.resetLookups(); + return LoopContinue; + }; + + line.front().forAllSurfaces(resetFunc); + line.back() .forAllSurfaces(resetFunc); + return LoopContinue; + }); + } } static void reportWallDrawn(Line &line) diff --git a/doomsday/apps/client/src/render/shadowedge.cpp b/doomsday/apps/client/src/render/shadowedge.cpp index db6f8b6653..796b480c25 100644 --- a/doomsday/apps/client/src/render/shadowedge.cpp +++ b/doomsday/apps/client/src/render/shadowedge.cpp @@ -93,16 +93,19 @@ static bool middleMaterialCoversOpening(LineSide const &side) if (!side.hasSector()) return false; // Never. if (!side.hasSections()) return false; - if (!side.middle().hasMaterial()) return false; + //if (!side.middle().hasMaterial()) return false; - MaterialAnimator &matAnimator = side.middle().material().as() - .getAnimator(Rend_MapSurfaceMaterialSpec()); + MaterialAnimator *matAnimator = side.middle().materialAnimator(); + /* material().as() + .getAnimator(Rend_MapSurfaceMaterialSpec());*/ + + if (!matAnimator) return false; // Ensure we have up to date info about the material. - matAnimator.prepare(); + matAnimator->prepare(); // Might the material cover the opening? - if (matAnimator.isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1) + if (matAnimator->isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1) { // Stretched middles always cover the opening. if (side.isFlagged(SDF_MIDDLE_STRETCH)) @@ -132,7 +135,7 @@ static bool middleMaterialCoversOpening(LineSide const &side) openTop = frontSec.ceiling().heightSmoothed(); } - if (matAnimator.dimensions().y >= openTop - openBottom) + if (matAnimator->dimensions().y >= openTop - openBottom) { // Possibly; check the placement. if(side.leftHEdge()) // possibility of degenerate BSP leaf diff --git a/doomsday/apps/client/src/world/base/bspleaf.cpp b/doomsday/apps/client/src/world/base/bspleaf.cpp index d4f5e32d39..d23778a39c 100644 --- a/doomsday/apps/client/src/world/base/bspleaf.cpp +++ b/doomsday/apps/client/src/world/base/bspleaf.cpp @@ -38,14 +38,14 @@ bool BspLeaf::hasSubspace() const ConvexSubspace &BspLeaf::subspace() const { - if(hasSubspace()) return *_subspace; + if (hasSubspace()) return *_subspace; /// @throw MissingSubspaceError Attempted with no subspace attributed. throw MissingSubspaceError("BspLeaf::subspace", "No subspace is attributed"); } ConvexSubspace *BspLeaf::subspacePtr() const { - return hasSubspace() ? &subspace() : nullptr; + return _subspace; } void BspLeaf::setSubspace(ConvexSubspace *newSubspace) @@ -65,16 +65,6 @@ void BspLeaf::setSubspace(ConvexSubspace *newSubspace) } } -Sector *BspLeaf::sectorPtr() -{ - return _sector; -} - -Sector const *BspLeaf::sectorPtr() const -{ - return _sector; -} - void BspLeaf::setSector(Sector *newSector) { _sector = newSector; diff --git a/doomsday/apps/client/src/world/base/maputil.cpp b/doomsday/apps/client/src/world/base/maputil.cpp index af5a957beb..5a65a715ea 100644 --- a/doomsday/apps/client/src/world/base/maputil.cpp +++ b/doomsday/apps/client/src/world/base/maputil.cpp @@ -153,15 +153,17 @@ bool R_SideBackClosed(LineSide const &side, bool ignoreOpacity) if(backSec.floor().heightSmoothed() >= frontSec.ceiling().heightSmoothed()) return true; // Perhaps a middle material completely covers the opening? - if(side.middle().hasMaterial()) + //if(side.middle().hasMaterial()) + + if (MaterialAnimator *matAnimator = side.middle().materialAnimator()) { - MaterialAnimator &matAnimator = static_cast(side.middle().material()) - .getAnimator(Rend_MapSurfaceMaterialSpec()); + //MaterialAnimator &matAnimator = static_cast(side.middle().material()) + // .getAnimator(Rend_MapSurfaceMaterialSpec()); // Ensure we have up to date info about the material. - matAnimator.prepare(); + matAnimator->prepare(); - if(ignoreOpacity || (matAnimator.isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1)) + if(ignoreOpacity || (matAnimator->isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1)) { // Stretched middles always cover the opening. if(side.isFlagged(SDF_MIDDLE_STRETCH)) @@ -171,7 +173,7 @@ bool R_SideBackClosed(LineSide const &side, bool ignoreOpacity) { coord_t openRange, openBottom, openTop; openRange = visOpenRange(side, &openBottom, &openTop); - if(matAnimator.dimensions().y >= openRange) + if(matAnimator->dimensions().y >= openRange) { // Possibly; check the placement. WallEdge edge(WallSpec::fromMapSide(side, LineSide::Middle), @@ -233,25 +235,26 @@ static bool middleMaterialCoversOpening(LineSide const &side) if(!side.hasSector()) return false; // Never. if(!side.hasSections()) return false; - if(!side.middle().hasMaterial()) return false; + //if(!side.middle().hasMaterial()) return false; // Stretched middles always cover the opening. if(side.isFlagged(SDF_MIDDLE_STRETCH)) return true; - MaterialAnimator &matAnimator = side.middle().material() - .as().getAnimator(Rend_MapSurfaceMaterialSpec()); + MaterialAnimator *matAnimator = side.middle().materialAnimator(); + //.as().getAnimator(Rend_MapSurfaceMaterialSpec()); + if (!matAnimator) return false; // Ensure we have up to date info about the material. - matAnimator.prepare(); + matAnimator->prepare(); - if(matAnimator.isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1) + if(matAnimator->isOpaque() && !side.middle().blendMode() && side.middle().opacity() >= 1) { if(side.leftHEdge()) // possibility of degenerate BSP leaf. { coord_t openRange, openBottom, openTop; openRange = visOpenRange(side, &openBottom, &openTop); - if(matAnimator.dimensions().y >= openRange) + if(matAnimator->dimensions().y >= openRange) { // Possibly; check the placement. WallEdge edge(WallSpec::fromMapSide(side, LineSide::Middle), *side.leftHEdge(), Line::From); diff --git a/doomsday/apps/client/src/world/base/plane.cpp b/doomsday/apps/client/src/world/base/plane.cpp index a8f81416a9..5db141fe7b 100644 --- a/doomsday/apps/client/src/world/base/plane.cpp +++ b/doomsday/apps/client/src/world/base/plane.cpp @@ -424,18 +424,15 @@ void Plane::removeMover(ClPlaneMover &mover) bool Plane::castsShadow() const { - if(surface().hasMaterial()) + if (auto *matAnim = d->surface.materialAnimator()) { - MaterialAnimator &matAnimator = surface().material().as() - .getAnimator(Rend_MapSurfaceMaterialSpec()); - // Ensure we have up to date info about the material. - matAnimator.prepare(); + matAnim->prepare(); - if(!matAnimator.material().isDrawable()) return false; - if(matAnimator.material().isSkyMasked()) return false; + if (!matAnim->material().isDrawable()) return false; + if (matAnim->material().isSkyMasked()) return false; - return de::fequal(matAnimator.glowStrength(), 0); + return de::fequal(matAnim->glowStrength(), 0); } return false; } diff --git a/doomsday/apps/client/src/world/base/subsector.cpp b/doomsday/apps/client/src/world/base/subsector.cpp index dd27cef544..11e8c9ed62 100644 --- a/doomsday/apps/client/src/world/base/subsector.cpp +++ b/doomsday/apps/client/src/world/base/subsector.cpp @@ -115,7 +115,12 @@ Sector &Subsector::sector() Sector const &Subsector::sector() const { - return const_cast(this)->sector(); + if (!d->sector) + { + d->sector = firstSubspace().bspLeaf().sectorPtr(); + DENG2_ASSERT(d->sector); + } + return *d->sector; } dint Subsector::subspaceCount() const @@ -126,7 +131,7 @@ dint Subsector::subspaceCount() const ConvexSubspace &Subsector::firstSubspace() const { DENG2_ASSERT(!d->subspaces.isEmpty()); - return *d->subspaces.first(); + return *d->subspaces.constFirst(); } LoopResult Subsector::forAllSubspaces(std::function func) const diff --git a/doomsday/apps/client/src/world/base/surface.cpp b/doomsday/apps/client/src/world/base/surface.cpp index a318c5ae2d..2e254094fe 100644 --- a/doomsday/apps/client/src/world/base/surface.cpp +++ b/doomsday/apps/client/src/world/base/surface.cpp @@ -80,6 +80,7 @@ DENG2_PIMPL(Surface) Vector2f oldOrigin[2]; ///< Old @em sharp surface space material origins, for smoothing. Vector2f originSmoothed; ///< @em smoothed surface space material origin. Vector2f originSmoothedDelta; ///< Delta between @em sharp and @em smoothed. + MaterialAnimator *matAnimator = nullptr; #endif Impl(Public *i) : Base(i) @@ -261,6 +262,10 @@ Surface &Surface::setMaterial(Material *newMaterial, bool isMissingFix) } } +#ifdef __CLIENT__ + d->matAnimator = nullptr; +#endif + // Notify interested parties. DENG2_FOR_AUDIENCE2(MaterialChange, i) i->surfaceMaterialChanged(*this); @@ -563,6 +568,23 @@ dint Surface::setProperty(DmuArgs const &args) #ifdef __CLIENT__ +MaterialAnimator *Surface::materialAnimator() const +{ + if (!d->material) return nullptr; + + if (!d->matAnimator) + { + d->matAnimator = &d->material->as() + .getAnimator(Rend_MapSurfaceMaterialSpec()); + } + return d->matAnimator; +} + +void Surface::resetLookups() +{ + d->matAnimator = nullptr; +} + Vector2f const &Surface::originSmoothed() const { return d->originSmoothed; @@ -620,7 +642,7 @@ dfloat Surface::glow(Vector3f &color) const return 0; } - MaterialAnimator &matAnimator = material().as().getAnimator(Rend_MapSurfaceMaterialSpec()); + MaterialAnimator &matAnimator = *materialAnimator(); //material().as().getAnimator(Rend_MapSurfaceMaterialSpec()); // Ensure we've up to date info about the material. matAnimator.prepare(); diff --git a/doomsday/apps/client/src/world/contactspreader.cpp b/doomsday/apps/client/src/world/contactspreader.cpp index 6867ba0a58..f14277c003 100644 --- a/doomsday/apps/client/src/world/contactspreader.cpp +++ b/doomsday/apps/client/src/world/contactspreader.cpp @@ -222,8 +222,8 @@ struct ContactSpreader openTop = fromSubsec.visCeiling().heightSmoothed(); } - MaterialAnimator &matAnimator = facingLineSide.middle().material() - .as().getAnimator(Rend_MapSurfaceMaterialSpec()); + MaterialAnimator &matAnimator = *facingLineSide.middle().materialAnimator(); + //.as().getAnimator(Rend_MapSurfaceMaterialSpec()); // Ensure we have up to date info about the material. matAnimator.prepare(); diff --git a/doomsday/sdk/libcore/include/de/data/binarytree.h b/doomsday/sdk/libcore/include/de/data/binarytree.h index 33b544ee33..dccdde1577 100644 --- a/doomsday/sdk/libcore/include/de/data/binarytree.h +++ b/doomsday/sdk/libcore/include/de/data/binarytree.h @@ -144,7 +144,7 @@ class BinaryTree */ inline BinaryTree *parentPtr() const { - return hasParent()? &parent() : 0; + return _parent; } /** @@ -284,7 +284,7 @@ class BinaryTree */ inline BinaryTree *childPtr(ChildId which) const { - return hasChild(which)? &child(which) : 0; + return which == Left? _leftChild : _rightChild; } /**