From 807043b995264f166e333bca54c4e0b281bd8669 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Ricardo=20Lu=C3=ADs=20Vaz=20Silva?= Date: Wed, 6 Aug 2025 23:35:34 -0300 Subject: [PATCH] dynlight optimize attempt --- src/common/utility/tarray.h | 57 ++---------- src/g_levellocals.h | 4 +- src/playsim/a_dynlight.cpp | 93 +++++++------------ src/playsim/a_dynlight.h | 4 +- src/r_data/r_sections.h | 2 + src/rendering/hwrenderer/scene/hw_flats.cpp | 6 +- .../hwrenderer/scene/hw_renderhacks.cpp | 6 +- .../hwrenderer/scene/hw_spritelight.cpp | 12 +-- src/rendering/hwrenderer/scene/hw_walls.cpp | 12 +-- src/rendering/swrenderer/line/r_walldraw.cpp | 6 +- .../swrenderer/plane/r_visibleplane.cpp | 6 +- src/rendering/swrenderer/things/r_sprite.cpp | 6 +- 12 files changed, 67 insertions(+), 147 deletions(-) diff --git a/src/common/utility/tarray.h b/src/common/utility/tarray.h index 5db743f1f..696a22364 100644 --- a/src/common/utility/tarray.h +++ b/src/common/utility/tarray.h @@ -405,36 +405,14 @@ public: // exact = false returns the closest match, to be used for, ex., insertions, exact = true returns Size() when no match, like Find does unsigned int SortedFind(const T& item, bool exact = true) const { - if(Count == 0) return 0; - if(Count == 1) return (item < Array[0]) ? 0 : 1; - - unsigned int lo = 0; - unsigned int hi = Count - 1; - - while(lo <= hi) - { - int mid = lo + ((hi - lo) / 2); - - if(Array[mid] < item) - { - lo = mid + 1; - } - else if(item < Array[mid]) - { - hi = mid - 1; - } - else - { - return mid; - } - } + unsigned int index = (std::lower_bound(begin(), end(), item) - begin()); if(exact) { - return Count; + return (index < Count && Array[index] == item) ? index : Count; } else { - return (lo == Count || (item < Array[lo])) ? lo : lo + 1; + return index; } } @@ -444,37 +422,14 @@ public: template unsigned int SortedFind(const T& item, Func &<, bool exact = true) const { - if(Count == 0) return 0; - if(Count == 1) return lt(item, Array[0]) ? 0 : 1; - - unsigned int lo = 0; - unsigned int hi = Count - 1; - - while(lo <= hi) - { - int mid = lo + ((hi - lo) / 2); - - if(std::invoke(lt, Array[mid], item)) - { - lo = mid + 1; - } - else if(std::invoke(lt, item, Array[mid])) - { - if(mid == 0) break; // prevent negative overflow due to unsigned numbers - hi = mid - 1; - } - else - { - return mid; - } - } + unsigned int index = (std::lower_bound(begin(), end(), item, lt) - begin()); if(exact) { - return Count; + return (index < Count && !std::invoke(lt, Array[index], item) && !std::invoke(lt, item, Array[index])) ? index : Count; } else { - return (lo == Count || std::invoke(lt, item, Array[lo])) ? lo : lo + 1; + return index; } } diff --git a/src/g_levellocals.h b/src/g_levellocals.h index a10d53219..70f71f1f1 100644 --- a/src/g_levellocals.h +++ b/src/g_levellocals.h @@ -61,8 +61,8 @@ struct FGlobalDLightLists { - TMap>> flat_dlist; - TMap>> wall_dlist; + TArray>> flat_dlist; + TArray>> wall_dlist; }; //============================================================================ diff --git a/src/playsim/a_dynlight.cpp b/src/playsim/a_dynlight.cpp index 4025abfb7..e37c14baa 100644 --- a/src/playsim/a_dynlight.cpp +++ b/src/playsim/a_dynlight.cpp @@ -426,69 +426,50 @@ void FDynamicLight::UpdateLocation() // //============================================================================= + +int FSection::Index() const +{ + return int(this - §or->Level->sections.allSections[0]); +} + void FDynamicLight::AddLightNode(FSection *section, side_t *sidedef) { - auto updateFlatTList = [&](FSection *sec) - { - touchlists.flat_tlist.TryEmplace(sec, sec); - }; - auto updateWallTList = [&](side_t *sidedef) - { - touchlists.wall_tlist.TryEmplace(sidedef, sidedef); - }; - if (section) { - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(section); - if (flatLightList) + if(Level->lightlists.flat_dlist.SSize() <= section->Index()) { - if (!flatLightList->CheckKey(this)) - { - FLightNode * node = new FLightNode; - node->lightsource = this; - node->targ = section; - - flatLightList->TryEmplace(this, node); - updateFlatTList(section); - } + Level->lightlists.flat_dlist.Resize(section->Index() + 1); } - else + + auto &flatLightList = Level->lightlists.flat_dlist[section->Index()]; + + if (!flatLightList.CheckKey(this)) { FLightNode * node = new FLightNode; node->lightsource = this; node->targ = section; - TMap> u; - u.TryEmplace(this, node); - Level->lightlists.flat_dlist.TryEmplace(section, std::move(u)); - updateFlatTList(section); + flatLightList.TryEmplace(this, node); + touchlists.flat_tlist.SortedAddUnique(section); } } else if (sidedef) { - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(sidedef); - if (wallLightList) + if(Level->lightlists.wall_dlist.SSize() <= sidedef->Index()) { - if (!wallLightList->CheckKey(this)) - { - FLightNode * node = new FLightNode; - node->lightsource = this; - node->targ = sidedef; - - wallLightList->TryEmplace(this, node); - updateWallTList(sidedef); - } + Level->lightlists.wall_dlist.Resize(sidedef->Index() + 1); } - else + + auto &wallLightList = Level->lightlists.wall_dlist[sidedef->Index()]; + + if (!wallLightList.CheckKey(this)) { FLightNode * node = new FLightNode; node->lightsource = this; node->targ = sidedef; - TMap> u; - u.TryEmplace(this, node); - Level->lightlists.wall_dlist.TryEmplace(sidedef, std::move(u)); - updateWallTList(sidedef); + wallLightList.TryEmplace(this, node); + touchlists.wall_tlist.SortedAddUnique(sidedef); } } } @@ -686,32 +667,24 @@ void FDynamicLight::LinkLight() void FDynamicLight::UnlinkLight () { - TMap::Iterator wit(touchlists.wall_tlist); - TMap::Pair *wpair; - while (wit.NextPair(wpair)) + for(int i = 0; i < touchlists.wall_tlist.SSize(); i++) { - auto sidedef = wpair->Value; + auto sidedef = touchlists.wall_tlist[i]; if (!sidedef) continue; - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(sidedef); - if (wallLightList) - { - wallLightList->Remove(this); - } + assert(Level->lightlists.wall_dlist.SSize() < sidedef->Index()); + + Level->lightlists.wall_dlist[sidedef->Index()].Remove(this); } - TMap::Iterator fit(touchlists.flat_tlist); - TMap::Pair *fpair; - while (fit.NextPair(fpair)) + for(int i = 0; i < touchlists.flat_tlist.SSize(); i++) { - auto sec = fpair->Value; + auto sec = touchlists.flat_tlist[i]; if (!sec) continue; - - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - if (flatLightList) - { - flatLightList->Remove(this); - } + + assert(Level->lightlists.flat_dlist.SSize() < sec->Index()); + + Level->lightlists.flat_dlist[sec->Index()].Remove(this); } touchlists.flat_tlist.Clear(); diff --git a/src/playsim/a_dynlight.h b/src/playsim/a_dynlight.h index 2f8bea462..92e6d3626 100644 --- a/src/playsim/a_dynlight.h +++ b/src/playsim/a_dynlight.h @@ -199,8 +199,8 @@ struct FLightNode struct FDynamicLightTouchLists { - TMap flat_tlist; - TMap wall_tlist; + TArray flat_tlist; + TArray wall_tlist; }; struct FDynamicLight diff --git a/src/r_data/r_sections.h b/src/r_data/r_sections.h index d844d2d18..9de145615 100644 --- a/src/r_data/r_sections.h +++ b/src/r_data/r_sections.h @@ -120,6 +120,8 @@ struct FSection short mapsection; char hacked; // 1: is part of a render hack char flags; + + int Index() const; }; class FSectionContainer diff --git a/src/rendering/hwrenderer/scene/hw_flats.cpp b/src/rendering/hwrenderer/scene/hw_flats.cpp index 178c6872f..509a63321 100644 --- a/src/rendering/hwrenderer/scene/hw_flats.cpp +++ b/src/rendering/hwrenderer/scene/hw_flats.cpp @@ -159,11 +159,9 @@ void HWFlat::SetupLights(HWDrawInfo *di, FDynLightData &lightdata, int portalgro return; // no lights on additively blended surfaces. } - auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(section); - - if (flatLightList) + if (di->Level->lightlists.flat_dlist.SSize() > section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(di->Level->lightlists.flat_dlist[section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp index 8aa077294..7318d6e58 100644 --- a/src/rendering/hwrenderer/scene/hw_renderhacks.cpp +++ b/src/rendering/hwrenderer/scene/hw_renderhacks.cpp @@ -117,11 +117,9 @@ int HWDrawInfo::SetupLightsForOtherPlane(subsector_t * sub, FDynLightData &light lightdata.Clear(); - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sub->section); - - if (flatLightList) + if (Level->lightlists.flat_dlist.SSize() > sub->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[sub->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/hwrenderer/scene/hw_spritelight.cpp b/src/rendering/hwrenderer/scene/hw_spritelight.cpp index d3b164ba0..55a952198 100644 --- a/src/rendering/hwrenderer/scene/hw_spritelight.cpp +++ b/src/rendering/hwrenderer/scene/hw_spritelight.cpp @@ -124,11 +124,9 @@ void HWDrawInfo::GetDynSpriteLight(AActor *self, float x, float y, float z, FSec } // Go through both light lists - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - - if (flatLightList) + if (Level->lightlists.flat_dlist.SSize() > sec->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[sec->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { @@ -255,10 +253,10 @@ void hw_GetDynModelLight(AActor *self, FDynLightData &modellightdata) { auto section = subsector->section; if (section->validcount == dl_validcount) return; // already done from a previous subsector. - auto flatLightList = self->Level->lightlists.flat_dlist.CheckKey(subsector->section); - if (flatLightList) + + if (self->Level->lightlists.flat_dlist.SSize() > subsector->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(self->Level->lightlists.flat_dlist[subsector->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { // check all lights touching a subsector diff --git a/src/rendering/hwrenderer/scene/hw_walls.cpp b/src/rendering/hwrenderer/scene/hw_walls.cpp index 7ff0fa7d8..3495bc9e1 100644 --- a/src/rendering/hwrenderer/scene/hw_walls.cpp +++ b/src/rendering/hwrenderer/scene/hw_walls.cpp @@ -427,11 +427,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata) if ((seg->sidedef->Flags & WALLF_POLYOBJ) && sub) { // Polobject segs cannot be checked per sidedef so use the subsector instead. - auto flatLightList = di->Level->lightlists.flat_dlist.CheckKey(sub->section); - - if (flatLightList) + if (di->Level->lightlists.flat_dlist.SSize() > sub->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(di->Level->lightlists.flat_dlist[sub->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { @@ -492,11 +490,9 @@ void HWWall::SetupLights(HWDrawInfo*di, FDynLightData &lightdata) } else { - auto wallLightList = di->Level->lightlists.wall_dlist.CheckKey(seg->sidedef); - - if (wallLightList) + if (di->Level->lightlists.wall_dlist.SSize() > seg->sidedef->Index()) { - TMap>::Iterator it(*wallLightList); + TMap>::Iterator it(di->Level->lightlists.wall_dlist[seg->sidedef->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/swrenderer/line/r_walldraw.cpp b/src/rendering/swrenderer/line/r_walldraw.cpp index 6f12b13fb..d7feb8f9c 100644 --- a/src/rendering/swrenderer/line/r_walldraw.cpp +++ b/src/rendering/swrenderer/line/r_walldraw.cpp @@ -224,10 +224,10 @@ namespace swrenderer else if (curline && curline->sidedef) { auto Level = curline->Subsector->sector->Level; - auto wallLightList = Level->lightlists.wall_dlist.CheckKey(curline->sidedef); - if (wallLightList) + + if (Level->lightlists.wall_dlist.SSize() > curline->sidedef->Index()) { - TMap>::Iterator it(*wallLightList); + TMap>::Iterator it(Level->lightlists.wall_dlist[curline->sidedef->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/swrenderer/plane/r_visibleplane.cpp b/src/rendering/swrenderer/plane/r_visibleplane.cpp index c7d327191..3b20236ca 100644 --- a/src/rendering/swrenderer/plane/r_visibleplane.cpp +++ b/src/rendering/swrenderer/plane/r_visibleplane.cpp @@ -76,10 +76,10 @@ namespace swrenderer return; // [SP] no dynlights if invul or lightamp auto Level = sec->sector->Level; - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(sec); - if (flatLightList) + + if (Level->lightlists.flat_dlist.SSize() > sec->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[sec->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) { diff --git a/src/rendering/swrenderer/things/r_sprite.cpp b/src/rendering/swrenderer/things/r_sprite.cpp index 102dc429e..2e1df8899 100644 --- a/src/rendering/swrenderer/things/r_sprite.cpp +++ b/src/rendering/swrenderer/things/r_sprite.cpp @@ -209,10 +209,10 @@ namespace swrenderer float lit_green = 0; float lit_blue = 0; auto Level = vis->sector->Level; - auto flatLightList = Level->lightlists.flat_dlist.CheckKey(vis->section); - if (flatLightList) + + if (Level->lightlists.flat_dlist.SSize() > vis->section->Index()) { - TMap>::Iterator it(*flatLightList); + TMap>::Iterator it(Level->lightlists.flat_dlist[vis->section->Index()]); TMap>::Pair *pair; while (it.NextPair(pair)) {