Skip to content

Commit 919cfae

Browse files
committed
improve ShadowMapManager slightly
don't use FixedCapacityVector to store pointers to active shadowmaps, that's just not needed. They're all stored un a static array already and directional and spot shadows are partitioned. This saves a couple heap allocations as well a an pointer dereference.
1 parent 0b93894 commit 919cfae

File tree

3 files changed

+70
-61
lines changed

3 files changed

+70
-61
lines changed

filament/src/ShadowMapManager.cpp

Lines changed: 39 additions & 40 deletions
Original file line numberDiff line numberDiff line change
@@ -90,40 +90,39 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::update(FEngine& engine, FVie
9090
}
9191

9292
void ShadowMapManager::reset() noexcept {
93-
mCascadeShadowMaps.clear();
94-
mSpotShadowMaps.clear();
93+
mDirectionalShadowMapCount = 0;
94+
mSpotShadowMapCount = 0;
9595
}
9696

9797
void ShadowMapManager::setDirectionalShadowMap(size_t lightIndex,
9898
LightManager::ShadowOptions const* options) noexcept {
9999
assert_invariant(options->shadowCascades <= CONFIG_MAX_SHADOW_CASCADES);
100+
101+
// this updates getCascadedShadowMap()
102+
mDirectionalShadowMapCount = options->shadowCascades;
103+
utils::Slice<ShadowMap> cascadedShadowMap = getCascadedShadowMap();
100104
for (size_t c = 0; c < options->shadowCascades; c++) {
101-
const size_t i = c;
102-
assert_invariant(i < CONFIG_MAX_SHADOW_CASCADES);
103-
auto* pShadowMap = getShadowMap(i);
104-
pShadowMap->initialize(lightIndex, ShadowType::DIRECTIONAL, i, 0, options);
105-
mCascadeShadowMaps.push_back(pShadowMap);
105+
ShadowMap& shadowMap = cascadedShadowMap[c];
106+
shadowMap.initialize(lightIndex, ShadowType::DIRECTIONAL, c, 0, options);
106107
}
107108
}
108109

109110
void ShadowMapManager::addShadowMap(size_t lightIndex, bool spotlight,
110111
LightManager::ShadowOptions const* options) noexcept {
111112
if (spotlight) {
112-
const size_t c = mSpotShadowMaps.size();
113+
const size_t c = mSpotShadowMapCount++;
113114
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
114115
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
115-
auto* pShadowMap = getShadowMap(i);
116-
pShadowMap->initialize(lightIndex, ShadowType::SPOT, i, 0, options);
117-
mSpotShadowMaps.push_back(pShadowMap);
116+
auto& shadowMap = getShadowMap(i);
117+
shadowMap.initialize(lightIndex, ShadowType::SPOT, i, 0, options);
118118
} else {
119119
// point-light, generate 6 independent shadowmaps
120120
for (size_t face = 0; face < 6; face++) {
121-
const size_t c = mSpotShadowMaps.size();
121+
const size_t c = mSpotShadowMapCount++;
122122
const size_t i = c + CONFIG_MAX_SHADOW_CASCADES;
123123
assert_invariant(i < CONFIG_MAX_SHADOWMAPS);
124-
auto* pShadowMap = getShadowMap(i);
125-
pShadowMap->initialize(lightIndex, ShadowType::POINT, i, face, options);
126-
mSpotShadowMaps.push_back(pShadowMap);
124+
auto& shadowMap = getShadowMap(i);
125+
shadowMap.initialize(lightIndex, ShadowType::POINT, i, face, options);
127126
}
128127
}
129128
}
@@ -179,11 +178,11 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
179178
// Directional, cascaded shadow maps
180179
auto const directionalShadowCastersRange = view.getVisibleDirectionalShadowCasters();
181180
if (!directionalShadowCastersRange.empty()) {
182-
for (auto* pShadowMap : mCascadeShadowMaps) {
181+
for (auto& shadowMap : getCascadedShadowMap()) {
183182
// for the directional light, we already know if it has visible shadows.
184-
if (pShadowMap->hasVisibleShadows()) {
183+
if (shadowMap.hasVisibleShadows()) {
185184
passList.push_back({
186-
{}, pShadowMap, directionalShadowCastersRange,
185+
{}, &shadowMap, directionalShadowCastersRange,
187186
VISIBLE_DIR_SHADOW_RENDERABLE });
188187
}
189188
}
@@ -192,10 +191,10 @@ FrameGraphId<FrameGraphTexture> ShadowMapManager::render(FEngine& engine, FrameG
192191
// Point lights and Spotlight shadow maps
193192
auto const spotShadowCastersRange = view.getVisibleSpotShadowCasters();
194193
if (!spotShadowCastersRange.empty()) {
195-
for (auto* pShadowMap : mSpotShadowMaps) {
196-
assert_invariant(!pShadowMap->isDirectionalShadow());
194+
for (auto& shadowMap : getSpotShadowMaps()) {
195+
assert_invariant(!shadowMap.isDirectionalShadow());
197196
passList.push_back({
198-
{}, pShadowMap, spotShadowCastersRange,
197+
{}, &shadowMap, spotShadowCastersRange,
199198
VISIBLE_DYN_SHADOW_RENDERABLE });
200199
}
201200
}
@@ -517,10 +516,11 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
517516
};
518517

519518
bool hasVisibleShadows = false;
520-
if (!mCascadeShadowMaps.empty()) {
519+
utils::Slice<ShadowMap> cascadedShadowMaps = getCascadedShadowMap();
520+
if (!cascadedShadowMaps.empty()) {
521521
// Even if we have more than one cascade, we cull directional shadow casters against the
522522
// entire camera frustum, as if we only had a single cascade.
523-
ShadowMap& shadowMap = *mCascadeShadowMaps[0];
523+
ShadowMap& shadowMap = cascadedShadowMaps[0];
524524

525525
const auto direction = options.transform * lightData.elementAt<FScene::DIRECTION>(0);
526526

@@ -558,7 +558,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
558558
vsFar = std::max(vsFar, sceneInfo.vsNearFar.y);
559559
}
560560

561-
const size_t cascadeCount = mCascadeShadowMaps.size();
561+
const size_t cascadeCount = cascadedShadowMaps.size();
562562

563563
// We divide the camera frustum into N cascades. This gives us N + 1 split positions.
564564
// The first split position is the near plane; the last split position is the far plane.
@@ -592,11 +592,9 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
592592
// note: normalBias is set to zero for VSM
593593
const float normalBias = shadowMapInfo.vsm ? 0.0f : 0.5f * lcm.getShadowNormalBias(0);
594594

595-
for (size_t i = 0, c = mCascadeShadowMaps.size(); i < c; i++) {
596-
assert_invariant(mCascadeShadowMaps[i]);
597-
595+
for (size_t i = 0, c = cascadedShadowMaps.size(); i < c; i++) {
598596
// Compute the frustum for the directional light.
599-
ShadowMap& shadowMap = *mCascadeShadowMaps[i];
597+
ShadowMap& shadowMap = cascadedShadowMaps[i];
600598
assert_invariant(shadowMap.getLightIndex() == 0);
601599

602600
sceneInfo.csNearFar = { csSplitPosition[i], csSplitPosition[i + 1] };
@@ -643,7 +641,7 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateCascadeShadowMaps(FEng
643641
}
644642

645643
uint32_t cascades = 0;
646-
cascades |= uint32_t(mCascadeShadowMaps.size());
644+
cascades |= uint32_t(cascadedShadowMaps.size());
647645
cascades |= cascadeHasVisibleShadows << 8u;
648646

649647
mShadowMappingUniforms.directionalShadows = directionalShadowsMask;
@@ -852,16 +850,17 @@ ShadowMapManager::ShadowTechnique ShadowMapManager::updateSpotShadowMaps(FEngine
852850
lightData.data<FScene::SHADOW_INFO>());
853851

854852
ShadowTechnique shadowTechnique{};
855-
if (!mSpotShadowMaps.empty()) {
853+
utils::Slice<ShadowMap> const spotShadowMaps = getSpotShadowMaps();
854+
if (!spotShadowMaps.empty()) {
856855
shadowTechnique |= ShadowTechnique::SHADOW_MAP;
857-
for (auto const* pShadowMap : mSpotShadowMaps) {
858-
const size_t lightIndex = pShadowMap->getLightIndex();
856+
for (ShadowMap const& shadowMap : spotShadowMaps) {
857+
const size_t lightIndex = shadowMap.getLightIndex();
859858
// gather the per-light (not per shadow map) information. For point lights we will
860859
// "see" 6 shadowmaps (one per face), we must use the first face one, the shader
861860
// knows how to find the entry for other faces (they're guaranteed to be sequential).
862-
if (pShadowMap->getFace() == 0) {
861+
if (shadowMap.getFace() == 0) {
863862
shadowInfo[lightIndex].castsShadows = true; // FIXME: is that set correctly?
864-
shadowInfo[lightIndex].index = pShadowMap->getShadowIndex();
863+
shadowInfo[lightIndex].index = shadowMap.getShadowIndex();
865864
}
866865
}
867866
}
@@ -891,18 +890,18 @@ void ShadowMapManager::calculateTextureRequirements(FEngine& engine, FView& view
891890
uint8_t layer = 0;
892891
uint32_t maxDimension = 0;
893892
bool elvsm = false;
894-
for (auto* pShadowMap : mCascadeShadowMaps) {
893+
for (ShadowMap& shadowMap : getCascadedShadowMap()) {
895894
// Shadow map size should be the same for all cascades.
896-
auto const& options = pShadowMap->getShadowOptions();
895+
auto const& options = shadowMap.getShadowOptions();
897896
maxDimension = std::max(maxDimension, options->mapSize);
898897
elvsm = elvsm || options->vsm.elvsm;
899-
pShadowMap->setLayer(layer++);
898+
shadowMap.setLayer(layer++);
900899
}
901-
for (auto& pShadowMap : mSpotShadowMaps) {
902-
auto const& options = pShadowMap->getShadowOptions();
900+
for (ShadowMap& shadowMap : getSpotShadowMaps()) {
901+
auto const& options = shadowMap.getShadowOptions();
903902
maxDimension = std::max(maxDimension, options->mapSize);
904903
elvsm = elvsm || options->vsm.elvsm;
905-
pShadowMap->setLayer(layer++);
904+
shadowMap.setLayer(layer++);
906905
}
907906

908907
const uint8_t layersNeeded = layer;

filament/src/ShadowMapManager.h

Lines changed: 30 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -31,7 +31,7 @@
3131
#include <backend/DriverEnums.h>
3232
#include <backend/Handle.h>
3333

34-
#include <utils/FixedCapacityVector.h>
34+
#include <utils/Slice.h>
3535

3636
#include <math/vec3.h>
3737

@@ -89,23 +89,19 @@ class ShadowMapManager {
8989
FrameGraphId<FrameGraphTexture> render(FEngine& engine, FrameGraph& fg, RenderPass const& pass,
9090
FView& view, CameraInfo const& mainCameraInfo, math::float4 const& userTime) noexcept;
9191

92-
ShadowMap* getShadowMap(size_t index) noexcept {
93-
assert_invariant(index < CONFIG_MAX_SHADOWMAPS);
94-
return std::launder(reinterpret_cast<ShadowMap*>(&mShadowMapCache[index]));
95-
}
96-
97-
ShadowMap const* getShadowMap(size_t index) const noexcept {
98-
return const_cast<ShadowMapManager*>(this)->getShadowMap(index);
99-
}
100-
10192
// valid after calling update() above
10293
ShadowMappingUniforms getShadowMappingUniforms() const noexcept {
10394
return mShadowMappingUniforms;
10495
}
10596

10697
auto& getShadowUniformsHandle() const { return mShadowUbh; }
10798

108-
bool hasSpotShadows() const { return !mSpotShadowMaps.empty(); }
99+
bool hasSpotShadows() const { return !mSpotShadowMapCount; }
100+
101+
// for debugging only
102+
FCamera const* getDirectionalLightCamera() const noexcept {
103+
return &getShadowMap(0).getDebugCamera();
104+
}
109105

110106
private:
111107
ShadowMapManager::ShadowTechnique updateCascadeShadowMaps(FEngine& engine,
@@ -184,19 +180,33 @@ class ShadowMapManager {
184180

185181
ShadowMap::SceneInfo mSceneInfo;
186182

187-
utils::FixedCapacityVector<ShadowMap*> mCascadeShadowMaps{
188-
utils::FixedCapacityVector<ShadowMap*>::with_capacity(
189-
CONFIG_MAX_SHADOW_CASCADES) };
190-
191-
utils::FixedCapacityVector<ShadowMap*> mSpotShadowMaps{
192-
utils::FixedCapacityVector<ShadowMap*>::with_capacity(
193-
CONFIG_MAX_SHADOWMAPS - CONFIG_MAX_SHADOW_CASCADES) };
194-
195183
// Inline storage for all our ShadowMap objects, we can't easily use a std::array<> directly.
196184
// Because ShadowMap doesn't have a default ctor, and we avoid out-of-line allocations.
197185
// Each ShadowMap is currently 40 bytes (total of 2.5KB for 64 shadow maps)
198186
using ShadowMapStorage = std::aligned_storage<sizeof(ShadowMap), alignof(ShadowMap)>::type;
199-
std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS> mShadowMapCache;
187+
using ShadowMapCacheContainer = std::array<ShadowMapStorage, CONFIG_MAX_SHADOWMAPS>;
188+
ShadowMapCacheContainer mShadowMapCache;
189+
uint32_t mDirectionalShadowMapCount = 0;
190+
uint32_t mSpotShadowMapCount = 0;
191+
192+
ShadowMap& getShadowMap(size_t index) noexcept {
193+
assert_invariant(index < CONFIG_MAX_SHADOWMAPS);
194+
return *std::launder(reinterpret_cast<ShadowMap*>(&mShadowMapCache[index]));
195+
}
196+
197+
ShadowMap const& getShadowMap(size_t index) const noexcept {
198+
return const_cast<ShadowMapManager*>(this)->getShadowMap(index);
199+
}
200+
201+
utils::Slice<ShadowMap> getCascadedShadowMap() noexcept {
202+
ShadowMap* const p = &getShadowMap(0);
203+
return { p, mDirectionalShadowMapCount };
204+
}
205+
206+
utils::Slice<ShadowMap> getSpotShadowMaps() noexcept {
207+
ShadowMap* const p = &getShadowMap(CONFIG_MAX_SHADOW_CASCADES);
208+
return { p, mSpotShadowMapCount };
209+
}
200210
};
201211

202212
} // namespace filament

filament/src/details/View.h

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -195,7 +195,7 @@ class FView : public View {
195195
void setStereoscopicOptions(StereoscopicOptions const& options);
196196

197197
FCamera const* getDirectionalLightCamera() const noexcept {
198-
return &mShadowMapManager.getShadowMap(0)->getDebugCamera();
198+
return mShadowMapManager.getDirectionalLightCamera();
199199
}
200200

201201
void setRenderTarget(FRenderTarget* renderTarget) noexcept {

0 commit comments

Comments
 (0)