feat: add particle static CPU fast path
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
Some checks failed
validate-scripts / validate-scripts (push) Has been cancelled
This commit is contained in:
@@ -1,4 +1,5 @@
|
||||
#include <mbgl/renderer/retained_underlay_cache.hpp>
|
||||
#include <mbgl/renderer/particle_fast_path.hpp>
|
||||
|
||||
#include <gtest/gtest.h>
|
||||
|
||||
@@ -31,6 +32,34 @@ RetainedUnderlayRevisionState revisionState(Size size = {640, 480}, int32_t boun
|
||||
result.cameraMatrix = key(size, boundary).cameraMatrix;
|
||||
return result;
|
||||
}
|
||||
|
||||
ParticleFastPathGateInput fastPathInput() {
|
||||
return {
|
||||
.hasPreparedTree = true,
|
||||
.retainedEnabled = true,
|
||||
.cacheValid = true,
|
||||
.revisionMatches = true,
|
||||
.contentRevisionMatches = true,
|
||||
.cameraMatches = true,
|
||||
.viewportMatches = true,
|
||||
.updateParametersMatch = true,
|
||||
.styleLoaded = true,
|
||||
.boundaryMatches = true,
|
||||
.topologyMatches = true,
|
||||
.staticStable = true,
|
||||
.hasPlacementTransition = false,
|
||||
.hasPendingChanges = false,
|
||||
.hasNonParticleTransition = false,
|
||||
.hasNonParticleRepaint = false,
|
||||
.hasFadingTiles = false,
|
||||
.particleNeedsRepaint = true,
|
||||
.stillImageRequest = false,
|
||||
.continuousMode = true,
|
||||
.debugDisabled = true,
|
||||
.supportedScene = true,
|
||||
.annotationMutation = false,
|
||||
};
|
||||
}
|
||||
} // namespace
|
||||
|
||||
TEST(RetainedDynamicBoundary, SelectsFirstCandidate) {
|
||||
@@ -310,3 +339,125 @@ TEST(RetainedUnderlayCache, RuntimeControlDisablesAndReenablesMapScopedCache) {
|
||||
EXPECT_EQ(cache.evaluate(key(), 1, true), RetainedUnderlayDecision::Build);
|
||||
EXPECT_TRUE(state->snapshot().enabled);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, ParticleOnlyStableRevisionIsCandidate) {
|
||||
const auto decision = evaluateParticleFastPath(fastPathInput());
|
||||
EXPECT_TRUE(decision.candidate);
|
||||
EXPECT_EQ(decision.reason, ParticleFastPathMissReason::None);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, RevisionCameraAndViewportMismatchReject) {
|
||||
auto input = fastPathInput();
|
||||
input.revisionMatches = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::RevisionMismatch);
|
||||
|
||||
input = fastPathInput();
|
||||
input.cameraMatches = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::CameraChanged);
|
||||
|
||||
input = fastPathInput();
|
||||
input.viewportMatches = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::ViewportChanged);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, NonParticleTransitionAndRepaintReject) {
|
||||
auto input = fastPathInput();
|
||||
input.hasNonParticleTransition = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::NonParticleTransition);
|
||||
|
||||
input = fastPathInput();
|
||||
input.hasNonParticleRepaint = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::NonParticleRepaint);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, SettledCurrentPlacementAllowsCandidateAfterPlacementFullFrame) {
|
||||
// A full frame may have run placement and captured placementChanged=true.
|
||||
// That previous-frame event is deliberately not a fast-path gate input;
|
||||
// only the controller's current transition state is authoritative.
|
||||
auto input = fastPathInput();
|
||||
input.hasPlacementTransition = false;
|
||||
EXPECT_TRUE(evaluateParticleFastPath(input).candidate);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, ActivePlacementFadeAndFadingTilesReject) {
|
||||
auto input = fastPathInput();
|
||||
input.hasPlacementTransition = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::PlacementOrFade);
|
||||
|
||||
input = fastPathInput();
|
||||
input.hasFadingTiles = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::FadingTiles);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, CacheDisabledAndSemanticMutationReject) {
|
||||
auto input = fastPathInput();
|
||||
input.retainedEnabled = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::RetainedDisabled);
|
||||
|
||||
input = fastPathInput();
|
||||
input.cacheValid = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::CacheInvalid);
|
||||
|
||||
input = fastPathInput();
|
||||
input.contentRevisionMatches = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::ContentMutation);
|
||||
|
||||
input = fastPathInput();
|
||||
input.updateParametersMatch = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::UpdateParametersChanged);
|
||||
|
||||
input = fastPathInput();
|
||||
input.topologyMatches = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::TopologyChanged);
|
||||
|
||||
input = fastPathInput();
|
||||
input.styleLoaded = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::StyleNotLoaded);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, PendingStillAndUnsupportedPathsReject) {
|
||||
auto input = fastPathInput();
|
||||
input.hasPendingChanges = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::PendingChanges);
|
||||
|
||||
input = fastPathInput();
|
||||
input.stillImageRequest = true;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::StillImageRequest);
|
||||
|
||||
input = fastPathInput();
|
||||
input.supportedScene = false;
|
||||
EXPECT_EQ(evaluateParticleFastPath(input).reason, ParticleFastPathMissReason::UnsupportedScene);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, FullFrameCanRestabilizeCandidate) {
|
||||
auto input = fastPathInput();
|
||||
input.contentRevisionMatches = false;
|
||||
EXPECT_FALSE(evaluateParticleFastPath(input).candidate);
|
||||
|
||||
input.contentRevisionMatches = true;
|
||||
input.revisionMatches = true;
|
||||
input.cacheValid = true;
|
||||
input.staticStable = true;
|
||||
EXPECT_TRUE(evaluateParticleFastPath(input).candidate);
|
||||
}
|
||||
|
||||
TEST(ParticleFastPath, PreparedTreeReplacementOwnsLifetime) {
|
||||
struct TrackedTree {
|
||||
TrackedTree(int value_, int& destroyed_)
|
||||
: value(value_), destroyed(destroyed_) {}
|
||||
~TrackedTree() { ++destroyed; }
|
||||
int value;
|
||||
int& destroyed;
|
||||
};
|
||||
|
||||
int destroyed = 0;
|
||||
ParticleFastPathPreparedTree<TrackedTree> slot;
|
||||
slot.replace(std::make_unique<TrackedTree>(1, destroyed));
|
||||
EXPECT_EQ(slot.get()->value, 1);
|
||||
slot.replace(std::make_unique<TrackedTree>(2, destroyed));
|
||||
EXPECT_EQ(destroyed, 1);
|
||||
EXPECT_EQ(slot.get()->value, 2);
|
||||
slot.reset();
|
||||
EXPECT_EQ(destroyed, 2);
|
||||
EXPECT_TRUE(slot.empty());
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user