mirror of
https://github.com/OpenMW/openmw.git
synced 2025-06-20 02:11:32 +00:00
refactors hashed std::map (#3199)
We currently apply a strange algorithm to `LightManager::mStateSetCache`. For some reason this algorithm inserts hashed keys into `std::map` in a way that fails to handle hash collisions and exhibits worse lookup complexity than `std::unordered_map`. With this PR we just use `std::unordered_map` here.
This commit is contained in:
parent
3042c000c6
commit
1979ee1491
2 changed files with 33 additions and 17 deletions
|
@ -1,6 +1,8 @@
|
||||||
#include "lightmanager.hpp"
|
#include "lightmanager.hpp"
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <algorithm>
|
||||||
|
#include <iterator>
|
||||||
|
|
||||||
#include <osg/BufferObject>
|
#include <osg/BufferObject>
|
||||||
#include <osg/BufferIndexBinding>
|
#include <osg/BufferIndexBinding>
|
||||||
|
@ -1158,29 +1160,39 @@ namespace SceneUtil
|
||||||
return mSun;
|
return mSun;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
size_t LightManager::HashLightIdList::operator()(const LightIdList& lightIdList) const
|
||||||
|
{
|
||||||
|
size_t hash = 0;
|
||||||
|
for (size_t i = 0; i < lightIdList.size(); ++i)
|
||||||
|
Misc::hashCombine(hash, lightIdList[i]);
|
||||||
|
return hash;
|
||||||
|
}
|
||||||
|
|
||||||
osg::ref_ptr<osg::StateSet> LightManager::getLightListStateSet(const LightList& lightList, size_t frameNum, const osg::RefMatrix* viewMatrix)
|
osg::ref_ptr<osg::StateSet> LightManager::getLightListStateSet(const LightList& lightList, size_t frameNum, const osg::RefMatrix* viewMatrix)
|
||||||
{
|
{
|
||||||
// possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists)
|
// possible optimization: return a StateSet containing all requested lights plus some extra lights (if a suitable one exists)
|
||||||
size_t hash = 0;
|
|
||||||
|
if (getLightingMethod() == LightingMethod::SingleUBO)
|
||||||
|
{
|
||||||
for (size_t i = 0; i < lightList.size(); ++i)
|
for (size_t i = 0; i < lightList.size(); ++i)
|
||||||
{
|
{
|
||||||
auto id = lightList[i]->mLightSource->getId();
|
auto id = lightList[i]->mLightSource->getId();
|
||||||
Misc::hashCombine(hash, id);
|
|
||||||
|
|
||||||
if (getLightingMethod() != LightingMethod::SingleUBO)
|
|
||||||
continue;
|
|
||||||
|
|
||||||
if (getLightIndexMap(frameNum).find(id) != getLightIndexMap(frameNum).end())
|
if (getLightIndexMap(frameNum).find(id) != getLightIndexMap(frameNum).end())
|
||||||
continue;
|
continue;
|
||||||
|
|
||||||
int index = getLightIndexMap(frameNum).size() + 1;
|
int index = getLightIndexMap(frameNum).size() + 1;
|
||||||
updateGPUPointLight(index, lightList[i]->mLightSource, frameNum, viewMatrix);
|
updateGPUPointLight(index, lightList[i]->mLightSource, frameNum, viewMatrix);
|
||||||
getLightIndexMap(frameNum).emplace(lightList[i]->mLightSource->getId(), index);
|
getLightIndexMap(frameNum).emplace(id, index);
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
auto& stateSetCache = mStateSetCache[frameNum%2];
|
auto& stateSetCache = mStateSetCache[frameNum%2];
|
||||||
|
|
||||||
auto found = stateSetCache.find(hash);
|
LightIdList lightIdList;
|
||||||
|
lightIdList.reserve(lightList.size());
|
||||||
|
std::transform(lightList.begin(), lightList.end(), std::back_inserter(lightIdList), [] (const LightSourceViewBound* l) { return l->mLightSource->getId(); });
|
||||||
|
|
||||||
|
auto found = stateSetCache.find(lightIdList);
|
||||||
if (found != stateSetCache.end())
|
if (found != stateSetCache.end())
|
||||||
{
|
{
|
||||||
mStateSetGenerator->update(found->second, lightList, frameNum);
|
mStateSetGenerator->update(found->second, lightList, frameNum);
|
||||||
|
@ -1188,7 +1200,7 @@ namespace SceneUtil
|
||||||
}
|
}
|
||||||
|
|
||||||
auto stateset = mStateSetGenerator->generate(lightList, frameNum);
|
auto stateset = mStateSetGenerator->generate(lightList, frameNum);
|
||||||
stateSetCache.emplace(hash, stateset);
|
stateSetCache.emplace(lightIdList, stateset);
|
||||||
return stateset;
|
return stateset;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -207,8 +207,12 @@ namespace SceneUtil
|
||||||
using LightSourceViewBoundCollection = std::vector<LightSourceViewBound>;
|
using LightSourceViewBoundCollection = std::vector<LightSourceViewBound>;
|
||||||
std::map<osg::observer_ptr<osg::Camera>, LightSourceViewBoundCollection> mLightsInViewSpace;
|
std::map<osg::observer_ptr<osg::Camera>, LightSourceViewBoundCollection> mLightsInViewSpace;
|
||||||
|
|
||||||
// < Light list hash , StateSet >
|
using LightIdList = std::vector<int>;
|
||||||
using LightStateSetMap = std::map<size_t, osg::ref_ptr<osg::StateSet>>;
|
struct HashLightIdList
|
||||||
|
{
|
||||||
|
size_t operator()(const LightIdList&) const;
|
||||||
|
};
|
||||||
|
using LightStateSetMap = std::unordered_map<LightIdList, osg::ref_ptr<osg::StateSet>, HashLightIdList>;
|
||||||
LightStateSetMap mStateSetCache[2];
|
LightStateSetMap mStateSetCache[2];
|
||||||
|
|
||||||
std::vector<osg::ref_ptr<osg::StateAttribute>> mDummies;
|
std::vector<osg::ref_ptr<osg::StateAttribute>> mDummies;
|
||||||
|
|
Loading…
Reference in a new issue