31TEST(MultiGpuFrameGate, a_connected_secondary_with_an_episode_waits_for_the_primary) {
32 EXPECT_EQ(DecideBeginFrame(Steady()), BeginFrameAction::Wait);
35TEST(MultiGpuFrameGate, a_disconnected_secondary_runs_on_its_own_clock_whatever_else_holds) {
38 EXPECT_EQ(DecideBeginFrame(state), BeginFrameAction::OwnClock);
41 EXPECT_EQ(DecideBeginFrame(state), BeginFrameAction::OwnClock);
44TEST(MultiGpuFrameGate, never_waits_while_the_primary_waits_for_this_server) {
49 EXPECT_EQ(DecideBeginFrame(travel), BeginFrameAction::DontWait);
53 EXPECT_EQ(DecideBeginFrame(load_map), BeginFrameAction::DontWait);
57 EXPECT_EQ(DecideBeginFrame(no_episode), BeginFrameAction::DontWait);
61 EXPECT_EQ(DecideBeginFrame(exiting), BeginFrameAction::DontWait);
64TEST(MultiGpuFrameGate, a_pending_load_map_takes_precedence_over_a_prepared_frame) {
65 EXPECT_EQ(DecidePreTick(
true,
true,
true,
true), PreTickAction::OpenLevel);
67 EXPECT_EQ(DecidePreTick(
true,
false,
false,
false), PreTickAction::Skip);
70TEST(MultiGpuFrameGate, only_a_prepared_frame_on_the_episode_world_is_played) {
71 EXPECT_EQ(DecidePreTick(
false,
true,
true,
true), PreTickAction::Play);
72 EXPECT_EQ(DecidePreTick(
false,
true,
false,
true), PreTickAction::Skip);
73 EXPECT_EQ(DecidePreTick(
false,
true,
true,
false), PreTickAction::Skip);
74 EXPECT_EQ(DecidePreTick(
false,
false,
true,
true), PreTickAction::Skip);
77TEST(MultiGpuFrameGate, consecutive_frames) {
78 EXPECT_TRUE(IsConsecutive(41u, 42u));
79 EXPECT_FALSE(IsConsecutive(41u, 41u));
80 EXPECT_FALSE(IsConsecutive(41u, 43u));
81 EXPECT_FALSE(IsConsecutive(std::nullopt, 42u));
84TEST(MultiGpuFrameGate, a_gap_asks_for_a_resync_unless_the_frame_is_one) {
85 EXPECT_TRUE(NeedsResync(41u, 43u,
false));
86 EXPECT_FALSE(NeedsResync(41u, 43u,
true));
87 EXPECT_FALSE(NeedsResync(41u, 42u,
false));
89 EXPECT_FALSE(NeedsResync(std::nullopt, 42u,
false));
92TEST(MultiGpuFrameGate, only_finite_non_negative_deltas_become_the_time_step) {
93 EXPECT_TRUE(IsUsableDelta(0.05f));
94 EXPECT_TRUE(IsUsableDelta(0.0f));
95 EXPECT_FALSE(IsUsableDelta(-0.05f));
96 EXPECT_FALSE(IsUsableDelta(std::numeric_limits<float>::infinity()));
97 EXPECT_FALSE(IsUsableDelta(std::numeric_limits<float>::quiet_NaN()));
bool IsConsecutive(std::optional< uint64_t > last_played, uint64_t frame)
Whether frame directly follows the last frame this secondary played.
bool IsUsableDelta(float delta_seconds)
Whether a primary's delta can be this engine frame's time step.
BeginFrameAction DecideBeginFrame(const BeginFrameState &state)
PreTickAction DecidePreTick(bool load_map_pending, bool has_episode, bool frame_prepared, bool episode_world)
BeginFrameAction
What a secondary does at the start of an engine frame, before the engine computes the frame's time st...
bool NeedsResync(std::optional< uint64_t > last_played, uint64_t frame, bool full_resync)
Whether playing frame shows that this secondary missed primary state (a frame went missing) that only...
PreTickAction
What a secondary does when its world starts ticking.
TEST(MultiGpuFrameGate, a_connected_secondary_with_an_episode_waits_for_the_primary)