Added support for a priority lane for entity spawning

It's now possible to have high and normal priority calls on the spawnable entities manager. This allows for events like (de)spawning and retrieving information to be executed before already queued requests, though requests cannot be reordered on the same ticket. High priority calls are executed twice per frame, while normal priority calls are called only once.
This commit is contained in:
AMZN-koppersr
2021-05-26 09:23:53 -07:00
parent 37b53c0680
commit 76827ff95e
7 changed files with 266 additions and 111 deletions
@@ -55,7 +55,11 @@ namespace UnitTest
delete m_ticket;
m_ticket = nullptr;
// One more tick on the spawnable entities manager in order to delete the ticket fully.
m_manager->ProcessQueue();
while (m_manager->ProcessQueue(
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::High |
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular) !=
AzFramework::SpawnableEntitiesManager::CommandQueueStatus::NoCommandsLeft)
;
delete m_spawnableAsset;
m_spawnableAsset = nullptr;
@@ -96,8 +100,8 @@ namespace UnitTest
{
spawnedEntitiesCount += entities.size();
};
m_manager->SpawnAllEntities(*m_ticket, {}, AZStd::move(callback));
m_manager->ProcessQueue();
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_Default, {}, AZStd::move(callback));
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
EXPECT_EQ(NumEntities, spawnedEntitiesCount);
}
@@ -119,9 +123,9 @@ namespace UnitTest
spawnedEntitiesCount += entities.size();
};
m_manager->SpawnAllEntities(*m_ticket);
m_manager->ListEntities(*m_ticket, AZStd::move(callback));
m_manager->ProcessQueue();
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_Default);
m_manager->ListEntities(*m_ticket, AzFramework::SpawnablePriorty_Default, AZStd::move(callback));
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
EXPECT_TRUE(allValidEntityIds);
EXPECT_EQ(NumEntities, spawnedEntitiesCount);
@@ -148,11 +152,73 @@ namespace UnitTest
}
};
m_manager->SpawnAllEntities(*m_ticket);
m_manager->ListIndicesAndEntities(*m_ticket, AZStd::move(callback));
m_manager->ProcessQueue();
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_Default);
m_manager->ListIndicesAndEntities(*m_ticket, AzFramework::SpawnablePriorty_Default, AZStd::move(callback));
m_manager->ProcessQueue(AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
EXPECT_TRUE(allValidEntityIds);
EXPECT_EQ(NumEntities, spawnedEntitiesCount);
}
TEST_F(SpawnableEntitiesManagerTest, Priority_HighBeforeDefault_HigherPriorityCallHappensBeforeDefaultPriorityEvenWhenQueuedLater)
{
static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities);
AzFramework::EntitySpawnTicket highPriorityTicket(*m_spawnableAsset);
size_t callCounter = 1;
size_t highPriorityCallId = 0;
size_t defaultPriorityCallId = 0;
auto highCallback = [&callCounter, &highPriorityCallId]
(AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView)
{
highPriorityCallId = callCounter++;
};
auto defaultCallback = [&callCounter, &defaultPriorityCallId]
(AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView)
{
defaultPriorityCallId = callCounter++;
};
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_Default, {}, AZStd::move(defaultCallback));
m_manager->SpawnAllEntities(highPriorityTicket, AzFramework::SpawnablePriorty_High, {}, AZStd::move(highCallback));
m_manager->ProcessQueue(
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::High |
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
EXPECT_LT(highPriorityCallId, defaultPriorityCallId);
}
TEST_F(SpawnableEntitiesManagerTest, Priority_SameTicket_DefaultPriorityCallHappensBeforeHighPriority)
{
static constexpr size_t NumEntities = 4;
FillSpawnable(NumEntities);
size_t callCounter = 1;
size_t highPriorityCallId = 0;
size_t defaultPriorityCallId = 0;
auto highCallback =
[&callCounter, &highPriorityCallId](AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView)
{
highPriorityCallId = callCounter++;
};
auto defaultCallback =
[&callCounter, &defaultPriorityCallId](AzFramework::EntitySpawnTicket&, AzFramework::SpawnableConstEntityContainerView)
{
defaultPriorityCallId = callCounter++;
};
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_Default, {}, AZStd::move(defaultCallback));
m_manager->SpawnAllEntities(*m_ticket, AzFramework::SpawnablePriorty_High, {}, AZStd::move(highCallback));
m_manager->ProcessQueue(
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::High |
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
// Run a second time as the high priority task will be pending at this point.
m_manager->ProcessQueue(
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::High |
AzFramework::SpawnableEntitiesManager::CommandQueuePriority::Regular);
EXPECT_LT(defaultPriorityCallId, highPriorityCallId);
}
} // namespace UnitTest