From 371e81c6ff924b97d1cbbe02686401c6e454ba83 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 09:48:54 -0600 Subject: [PATCH 01/95] Add new functional test stub Derived from FLoadAllMapsInEditorTest in EditorAutomationTests.cpp --- .../Private/Tests/CesiumLoadTest.cpp | 88 +++++++++++++++++++ 1 file changed, 88 insertions(+) create mode 100644 Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp new file mode 100644 index 000000000..c8c2ae488 --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -0,0 +1,88 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "Misc/AutomationTest.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" +#include "Interfaces/IAnalyticsProvider.h" +#include "EngineAnalytics.h" + +#include "Editor.h" +#include "Engine/World.h" +#include "EngineUtils.h" +#include "CesiumRuntime.h" + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumLoadTest, + "Cesium.LoadTest", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + + +bool FCesiumLoadTest::RunTest(const FString& Parameters) { + FString MapName = "MyMap"; + double MapLoadStartTime = 0; + + // Test event for analytics. This should fire anytime this automation + // procedure is started. + + if (FEngineAnalytics::IsAvailable()) { + FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.TestEvent")); + UE_LOG( + LogCesium, + Log, + TEXT( + "AnayticsTest: Load All Maps automation triggered and Editor.Usage.TestEvent analytic event has been fired.")); + } + + { + // Find the main editor window + TArray> AllWindows; + FSlateApplication::Get().GetAllVisibleWindowsOrdered(AllWindows); + if (AllWindows.Num() == 0) { + UE_LOG( + LogCesium, + Error, + TEXT("ERROR: Could not find the main editor window.")); + return false; + } + WindowScreenshotParameters WindowParameters; + WindowParameters.CurrentWindow = AllWindows[0]; + + // Disable Eye Adaptation + static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable( + TEXT("r.EyeAdaptationQuality")); + CVar->Set(0); + + // Create a screen shot filename and path + const FString LoadAllMapsTestName = FString::Printf( + TEXT("LoadAllMaps_Editor/%s"), + *FPaths::GetBaseFilename(MapName)); + WindowParameters.ScreenshotName = + AutomationCommon::GetScreenshotName(LoadAllMapsTestName); + + // Get the current number of seconds. This will be used to track how long + // it took to load the map. + MapLoadStartTime = FPlatformTime::Seconds(); + // Load the map + FAutomationEditorCommonUtils::LoadMap(MapName); + // Log how long it took to launch the map. + UE_LOG( + LogEditorAutomationTests, + Display, + TEXT("Map '%s' took %.3f to load"), + *MapName, + FPlatformTime::Seconds() - MapLoadStartTime); + + // If we don't have NoTextureStreaming enabled, give the textures some time + // to load. + if (!FParse::Param(FCommandLine::Get(), TEXT("NoTextureStreaming"))) { + // Give the contents some time to load + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.5f)); + } + } + + return true; +} + +#endif From b9fb0f358c5f1340f825e41c3d9f7e116e487eaf Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 10:33:08 -0600 Subject: [PATCH 02/95] Run clang format --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index c8c2ae488..52efd2940 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -2,23 +2,22 @@ #if WITH_EDITOR +#include "EngineAnalytics.h" +#include "Interfaces/IAnalyticsProvider.h" #include "Misc/AutomationTest.h" #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" -#include "Interfaces/IAnalyticsProvider.h" -#include "EngineAnalytics.h" +#include "CesiumRuntime.h" #include "Editor.h" #include "Engine/World.h" #include "EngineUtils.h" -#include "CesiumRuntime.h" IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, "Cesium.LoadTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) - bool FCesiumLoadTest::RunTest(const FString& Parameters) { FString MapName = "MyMap"; double MapLoadStartTime = 0; From ccbf5b03960e74055290c3dca141de4a28673ee7 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 10:34:01 -0600 Subject: [PATCH 03/95] Fix non-unity build errors --- .../CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp | 1 + Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h | 3 ++- 2 files changed, 3 insertions(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp b/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp index 5e2955b33..ed83985c3 100644 --- a/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp +++ b/Source/CesiumRuntime/Private/CesiumSubLevelSwitcherComponent.cpp @@ -1,4 +1,5 @@ #include "CesiumSubLevelSwitcherComponent.h" +#include "CesiumRuntime.h" #include "CesiumSubLevelComponent.h" #include "Engine/LevelStreaming.h" #include "Engine/World.h" diff --git a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h index ebbc79b0b..02becf9bb 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h @@ -2,6 +2,7 @@ #pragma once +#include "CesiumRuntime.h" #include "EngineUtils.h" #include "Kismet/GameplayStatics.h" #include "Misc/AutomationTest.h" @@ -15,7 +16,7 @@ class UWorld; namespace CesiumTestHelpers { -static UWorld* getGlobalWorldContext(); +UWorld* getGlobalWorldContext(); template void waitForImpl( From 4db30315ebf83fb1958e9642763243bbb75fdd63 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 13:48:20 -0600 Subject: [PATCH 04/95] Set up programmatic scene with typical Cesium objects --- .../Private/Tests/CesiumLoadTest.cpp | 111 ++++++++---------- 1 file changed, 47 insertions(+), 64 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 52efd2940..92ff3a2d4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -2,84 +2,67 @@ #if WITH_EDITOR -#include "EngineAnalytics.h" -#include "Interfaces/IAnalyticsProvider.h" #include "Misc/AutomationTest.h" #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" -#include "CesiumRuntime.h" #include "Editor.h" #include "Engine/World.h" #include "EngineUtils.h" +#include "Cesium3DTileset.h" +#include "CesiumCameraManager.h" +#include "CesiumGeoreference.h" +#include "CesiumRuntime.h" +#include "CesiumSunSky.h" +#include "CesiumTestHelpers.h" +#include "GlobeAwareDefaultPawn.h" + IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, "Cesium.LoadTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) bool FCesiumLoadTest::RunTest(const FString& Parameters) { - FString MapName = "MyMap"; - double MapLoadStartTime = 0; - - // Test event for analytics. This should fire anytime this automation - // procedure is started. - - if (FEngineAnalytics::IsAvailable()) { - FEngineAnalytics::GetProvider().RecordEvent(TEXT("Editor.Usage.TestEvent")); - UE_LOG( - LogCesium, - Log, - TEXT( - "AnayticsTest: Load All Maps automation triggered and Editor.Usage.TestEvent analytic event has been fired.")); - } - - { - // Find the main editor window - TArray> AllWindows; - FSlateApplication::Get().GetAllVisibleWindowsOrdered(AllWindows); - if (AllWindows.Num() == 0) { - UE_LOG( - LogCesium, - Error, - TEXT("ERROR: Could not find the main editor window.")); - return false; - } - WindowScreenshotParameters WindowParameters; - WindowParameters.CurrentWindow = AllWindows[0]; - - // Disable Eye Adaptation - static IConsoleVariable* CVar = IConsoleManager::Get().FindConsoleVariable( - TEXT("r.EyeAdaptationQuality")); - CVar->Set(0); - - // Create a screen shot filename and path - const FString LoadAllMapsTestName = FString::Printf( - TEXT("LoadAllMaps_Editor/%s"), - *FPaths::GetBaseFilename(MapName)); - WindowParameters.ScreenshotName = - AutomationCommon::GetScreenshotName(LoadAllMapsTestName); - - // Get the current number of seconds. This will be used to track how long - // it took to load the map. - MapLoadStartTime = FPlatformTime::Seconds(); - // Load the map - FAutomationEditorCommonUtils::LoadMap(MapName); - // Log how long it took to launch the map. - UE_LOG( - LogEditorAutomationTests, - Display, - TEXT("Map '%s' took %.3f to load"), - *MapName, - FPlatformTime::Seconds() - MapLoadStartTime); - - // If we don't have NoTextureStreaming enabled, give the textures some time - // to load. - if (!FParse::Param(FCommandLine::Get(), TEXT("NoTextureStreaming"))) { - // Give the contents some time to load - ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.5f)); - } - } + + // + // Programmatically set up the world + // + + UWorld* world = CesiumTestHelpers::getGlobalWorldContext(); + ULevel* level = world->GetCurrentLevel(); + + // Create a camera + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + TestNotNull("Camera manager pointer is valid", cameraManager); + + // Create world objects + ACesiumGeoreference* georeference = + ACesiumGeoreference::GetDefaultGeoreference(world); + ACesiumSunSky* sunSkyActor = world->SpawnActor(); + ACesium3DTileset* tilesetActor = world->SpawnActor(); + + FSoftObjectPath objectPath( + TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); + TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); + AGlobeAwareDefaultPawn* pawnActor = world->SpawnActor( + Cast(DynamicPawn.LoadSynchronous())); + + TestNotNull("Georeference pointer is valid", georeference); + TestNotNull("SunSky actor pointer is valid", sunSkyActor); + TestNotNull("Tileset actor pointer is valid", tilesetActor); + TestNotNull("Dynamic pawn actor pointer is valid", pawnActor); + + // Configure similar to Google Tiles sample + FVector targetOrigin(-122.083969, 37.424492, 142.859116); + FString targetUrl( + "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); + + georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); + tilesetActor->SetUrl(targetUrl); + tilesetActor->SetTilesetSource(ETilesetSource::FromUrl); + pawnActor->SetActorRotation(FRotator(-25, 95, 0)); return true; } From e4d636c9b35bede8ae8a4f684264438903f16acd Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 15:31:38 -0600 Subject: [PATCH 05/95] Fix camera not looking at correct place when entering PIE mode --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 92ff3a2d4..384ea32e3 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -9,6 +9,7 @@ #include "Editor.h" #include "Engine/World.h" #include "EngineUtils.h" +#include "GameFramework/PlayerStart.h" #include "Cesium3DTileset.h" #include "CesiumCameraManager.h" @@ -42,6 +43,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { ACesiumGeoreference::GetDefaultGeoreference(world); ACesiumSunSky* sunSkyActor = world->SpawnActor(); ACesium3DTileset* tilesetActor = world->SpawnActor(); + APlayerStart* playerStartActor = world->SpawnActor(); FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); @@ -52,6 +54,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { TestNotNull("Georeference pointer is valid", georeference); TestNotNull("SunSky actor pointer is valid", sunSkyActor); TestNotNull("Tileset actor pointer is valid", tilesetActor); + TestNotNull("PlayerStart actor pointer is valid", playerStartActor); TestNotNull("Dynamic pawn actor pointer is valid", pawnActor); // Configure similar to Google Tiles sample @@ -62,7 +65,9 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); tilesetActor->SetUrl(targetUrl); tilesetActor->SetTilesetSource(ETilesetSource::FromUrl); + pawnActor->SetActorLocation(FVector(0, 0, 0)); pawnActor->SetActorRotation(FRotator(-25, 95, 0)); + pawnActor->AutoPossessPlayer = EAutoReceiveInput::Player0; return true; } From 7cad8693cb7e65d91dbb324d41c108f3a659c383 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:05:36 -0600 Subject: [PATCH 06/95] Add option to create test in editor or in standalone world --- .../Private/Tests/CesiumLoadTest.cpp | 40 ++++++++++++++----- 1 file changed, 29 insertions(+), 11 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 384ea32e3..f8c95900b 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -19,6 +19,13 @@ #include "CesiumTestHelpers.h" #include "GlobeAwareDefaultPawn.h" +// +// For debugging, it may help to create the scene in the editor +// After the test is run, you can play with their settings and even run PIE +// +#define CREATE_TEST_IN_EDITOR_WORLD 0 + + IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, "Cesium.LoadTest", @@ -30,15 +37,18 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Programmatically set up the world // - UWorld* world = CesiumTestHelpers::getGlobalWorldContext(); - ULevel* level = world->GetCurrentLevel(); +#if CREATE_TEST_IN_EDITOR_WORLD + UWorld* world = FAutomationEditorCommonUtils::CreateNewMap(); +#else + UWorld* world = UWorld::CreateWorld(EWorldType::Game, false); + FWorldContext& context = GEngine->CreateNewWorldContext(EWorldType::Game); + context.SetCurrentWorld(world); +#endif + TestNotNull("world is valid", world); - // Create a camera + // Create world objects ACesiumCameraManager* cameraManager = ACesiumCameraManager::GetDefaultCameraManager(world); - TestNotNull("Camera manager pointer is valid", cameraManager); - - // Create world objects ACesiumGeoreference* georeference = ACesiumGeoreference::GetDefaultGeoreference(world); ACesiumSunSky* sunSkyActor = world->SpawnActor(); @@ -51,11 +61,12 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { AGlobeAwareDefaultPawn* pawnActor = world->SpawnActor( Cast(DynamicPawn.LoadSynchronous())); - TestNotNull("Georeference pointer is valid", georeference); - TestNotNull("SunSky actor pointer is valid", sunSkyActor); - TestNotNull("Tileset actor pointer is valid", tilesetActor); - TestNotNull("PlayerStart actor pointer is valid", playerStartActor); - TestNotNull("Dynamic pawn actor pointer is valid", pawnActor); + TestNotNull("cameraManager is valid", cameraManager); + TestNotNull("georeference is valid", georeference); + TestNotNull("sunSkyActor is valid", sunSkyActor); + TestNotNull("tilesetActor is valid", tilesetActor); + TestNotNull("playerStartActor is valid", playerStartActor); + TestNotNull("pawnActor is valid", pawnActor); // Configure similar to Google Tiles sample FVector targetOrigin(-122.083969, 37.424492, 142.859116); @@ -69,6 +80,13 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { pawnActor->SetActorRotation(FRotator(-25, 95, 0)); pawnActor->AutoPossessPlayer = EAutoReceiveInput::Player0; +#if CREATE_TEST_IN_EDITOR_WORLD + // Let all objects persist +#else + GEngine->DestroyWorldContext(world); + world->DestroyWorld(false); +#endif + return true; } From 6ec8d79e303254105365288afda7c16efaabe1a3 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 23 Aug 2023 16:06:26 -0600 Subject: [PATCH 07/95] Fix formatting --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index f8c95900b..0d8ab790b 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -25,7 +25,6 @@ // #define CREATE_TEST_IN_EDITOR_WORLD 0 - IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, "Cesium.LoadTest", From a89e5a95088dd73dd3f576c5e91cf879e209f27a Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 24 Aug 2023 15:54:00 -0600 Subject: [PATCH 08/95] Setup denver (ion) example. Steps towards ticking world after objects created. --- .../Private/Tests/CesiumLoadTest.cpp | 132 ++++++++++++++---- 1 file changed, 101 insertions(+), 31 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 0d8ab790b..1231f97c2 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -23,62 +23,132 @@ // For debugging, it may help to create the scene in the editor // After the test is run, you can play with their settings and even run PIE // -#define CREATE_TEST_IN_EDITOR_WORLD 0 +#define CREATE_TEST_IN_EDITOR_WORLD 1 IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, "Cesium.LoadTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -bool FCesiumLoadTest::RunTest(const FString& Parameters) { +void tickWorld(UWorld* world, double time) { + const double minStepTime = 0.001; // Don't loop faster than 100 fps - // - // Programmatically set up the world - // + const double testStartMark = FPlatformTime::Seconds(); + const double testEndMark = testStartMark + time; + double lastTimeMark = testStartMark; -#if CREATE_TEST_IN_EDITOR_WORLD - UWorld* world = FAutomationEditorCommonUtils::CreateNewMap(); -#else - UWorld* world = UWorld::CreateWorld(EWorldType::Game, false); - FWorldContext& context = GEngine->CreateNewWorldContext(EWorldType::Game); - context.SetCurrentWorld(world); -#endif - TestNotNull("world is valid", world); + while (1) { + double frameTimeMark = FPlatformTime::Seconds(); + + if (frameTimeMark > testEndMark) + break; + + double frameElapsedTime = frameTimeMark - lastTimeMark; + + if (frameElapsedTime < minStepTime) { + double sleepTarget = minStepTime - frameElapsedTime; + FPlatformProcess::Sleep(sleepTarget); + continue; + } - // Create world objects + // Let world tick at same rate as this loop + world->Tick(ELevelTick::LEVELTICK_All, frameElapsedTime); + + // Derived from TimerManagerTests.cpp, TimerTest_TickWorld + GFrameCounter++; + + lastTimeMark = frameTimeMark; + }; +} + +void setupForGoogleTiles(UWorld* world) { ACesiumCameraManager* cameraManager = ACesiumCameraManager::GetDefaultCameraManager(world); ACesiumGeoreference* georeference = ACesiumGeoreference::GetDefaultGeoreference(world); - ACesiumSunSky* sunSkyActor = world->SpawnActor(); - ACesium3DTileset* tilesetActor = world->SpawnActor(); - APlayerStart* playerStartActor = world->SpawnActor(); + ACesiumSunSky* sunSky = world->SpawnActor(); + ACesium3DTileset* tileset = world->SpawnActor(); + APlayerStart* playerStart = world->SpawnActor(); FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); - AGlobeAwareDefaultPawn* pawnActor = world->SpawnActor( + AGlobeAwareDefaultPawn* pawn = world->SpawnActor( Cast(DynamicPawn.LoadSynchronous())); + pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; - TestNotNull("cameraManager is valid", cameraManager); - TestNotNull("georeference is valid", georeference); - TestNotNull("sunSkyActor is valid", sunSkyActor); - TestNotNull("tilesetActor is valid", tilesetActor); - TestNotNull("playerStartActor is valid", playerStartActor); - TestNotNull("pawnActor is valid", pawnActor); - - // Configure similar to Google Tiles sample FVector targetOrigin(-122.083969, 37.424492, 142.859116); FString targetUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); - tilesetActor->SetUrl(targetUrl); - tilesetActor->SetTilesetSource(ETilesetSource::FromUrl); - pawnActor->SetActorLocation(FVector(0, 0, 0)); - pawnActor->SetActorRotation(FRotator(-25, 95, 0)); - pawnActor->AutoPossessPlayer = EAutoReceiveInput::Player0; + tileset->SetUrl(targetUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + pawn->SetActorLocation(FVector(0, 0, 0)); + pawn->SetActorRotation(FRotator(-25, 95, 0)); +} + +void setupForDenver(UWorld* world) { + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + ACesiumGeoreference* georeference = + ACesiumGeoreference::GetDefaultGeoreference(world); + ACesiumSunSky* sunSky = world->SpawnActor(); + ACesium3DTileset* worldTileset = world->SpawnActor(); + ACesium3DTileset* denverTileset = world->SpawnActor(); + APlayerStart* playerStart = world->SpawnActor(); + + FSoftObjectPath objectPath( + TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); + TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); + AGlobeAwareDefaultPawn* pawn = world->SpawnActor( + Cast(DynamicPawn.LoadSynchronous())); + pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; + + FVector targetOrigin(-104.988892, 39.743462, 1798.679443); + FString ionToken( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); + + georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); + worldTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTileset->SetIonAssetID(1); + worldTileset->SetIonAccessToken(ionToken); + + denverTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + denverTileset->SetIonAssetID(354307); + denverTileset->SetIonAccessToken(ionToken); + denverTileset->SetMaximumScreenSpaceError(2.0); + + pawn->SetActorLocation(FVector(0, 0, 0)); + pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); +} + +bool FCesiumLoadTest::RunTest(const FString& Parameters) { + + // + // Programmatically set up the world + // + +#if CREATE_TEST_IN_EDITOR_WORLD + UWorld* world = FAutomationEditorCommonUtils::CreateNewMap(); +#else + UWorld* world = UWorld::CreateWorld(EWorldType::Game, false); + FWorldContext& context = GEngine->CreateNewWorldContext(EWorldType::Game); + context.SetCurrentWorld(world); +#endif + TestNotNull("world is valid", world); + + // Configure similar to Google Tiles sample + // setupForGoogleTiles(world); + setupForDenver(world); + + world->BeginPlay(); + + // Spin for 5 seconds, letting our game objects tick + const double testMaxTime = 5.0; + tickWorld(world, testMaxTime); + // Cleanup #if CREATE_TEST_IN_EDITOR_WORLD // Let all objects persist #else From 459ef0e497a57e906bcd9e751fd9e70e58628a3d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 25 Aug 2023 11:52:06 -0600 Subject: [PATCH 09/95] Fixup issues with Denver test Fix raster imagery not showing. Name actors for convenience --- .../Private/Tests/CesiumLoadTest.cpp | 38 +++++++++++++------ 1 file changed, 27 insertions(+), 11 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 1231f97c2..fea3913da 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -14,6 +14,7 @@ #include "Cesium3DTileset.h" #include "CesiumCameraManager.h" #include "CesiumGeoreference.h" +#include "CesiumIonRasterOverlay.h" #include "CesiumRuntime.h" #include "CesiumSunSky.h" #include "CesiumTestHelpers.h" @@ -94,10 +95,7 @@ void setupForDenver(UWorld* world) { ACesiumGeoreference* georeference = ACesiumGeoreference::GetDefaultGeoreference(world); ACesiumSunSky* sunSky = world->SpawnActor(); - ACesium3DTileset* worldTileset = world->SpawnActor(); - ACesium3DTileset* denverTileset = world->SpawnActor(); APlayerStart* playerStart = world->SpawnActor(); - FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); @@ -110,17 +108,35 @@ void setupForDenver(UWorld* world) { "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); - worldTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - worldTileset->SetIonAssetID(1); - worldTileset->SetIonAccessToken(ionToken); - - denverTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - denverTileset->SetIonAssetID(354307); - denverTileset->SetIonAccessToken(ionToken); - denverTileset->SetMaximumScreenSpaceError(2.0); pawn->SetActorLocation(FVector(0, 0, 0)); pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(ionToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + + // Bing Maps Aerial overlay + UCesiumIonRasterOverlay* pOverlay = NewObject( + worldTerrainTileset, + FName("Bing Maps Aerial"), + RF_Transactional); + pOverlay->MaterialLayerKey = TEXT("Overlay0"); + pOverlay->IonAssetID = 2; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + worldTerrainTileset->AddInstanceComponent(pOverlay); + + // Aerometrex Denver + ACesium3DTileset* aerometrexTileset = world->SpawnActor(); + aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + aerometrexTileset->SetIonAssetID(354307); + aerometrexTileset->SetIonAccessToken(ionToken); + aerometrexTileset->SetMaximumScreenSpaceError(2.0); + aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); } bool FCesiumLoadTest::RunTest(const FString& Parameters) { From 9db4b939a2daef16aa9759ee0e8f15c52796dbd4 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 25 Aug 2023 13:53:37 -0600 Subject: [PATCH 10/95] Refactor and add logic to stop reset tilesets before loop start --- .../Private/Tests/CesiumLoadTest.cpp | 96 ++++++++++++------- 1 file changed, 62 insertions(+), 34 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index fea3913da..4826252d5 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -62,46 +62,34 @@ void tickWorld(UWorld* world, double time) { }; } -void setupForGoogleTiles(UWorld* world) { - ACesiumCameraManager* cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(world); - ACesiumGeoreference* georeference = - ACesiumGeoreference::GetDefaultGeoreference(world); - ACesiumSunSky* sunSky = world->SpawnActor(); - ACesium3DTileset* tileset = world->SpawnActor(); - APlayerStart* playerStart = world->SpawnActor(); - - FSoftObjectPath objectPath( - TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); - TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); - AGlobeAwareDefaultPawn* pawn = world->SpawnActor( - Cast(DynamicPawn.LoadSynchronous())); - pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; +void setupForGoogleTiles( + UWorld* world, + ACesiumGeoreference* georeference, + AGlobeAwareDefaultPawn* pawn, + std::vector& createdTilesets) { FVector targetOrigin(-122.083969, 37.424492, 142.859116); FString targetUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); - tileset->SetUrl(targetUrl); - tileset->SetTilesetSource(ETilesetSource::FromUrl); + pawn->SetActorLocation(FVector(0, 0, 0)); pawn->SetActorRotation(FRotator(-25, 95, 0)); + + ACesium3DTileset* tileset = world->SpawnActor(); + tileset->SetUrl(targetUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); + + createdTilesets.push_back(tileset); } -void setupForDenver(UWorld* world) { - ACesiumCameraManager* cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(world); - ACesiumGeoreference* georeference = - ACesiumGeoreference::GetDefaultGeoreference(world); - ACesiumSunSky* sunSky = world->SpawnActor(); - APlayerStart* playerStart = world->SpawnActor(); - FSoftObjectPath objectPath( - TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); - TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); - AGlobeAwareDefaultPawn* pawn = world->SpawnActor( - Cast(DynamicPawn.LoadSynchronous())); - pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; +void setupForDenver( + UWorld* world, + ACesiumGeoreference* georeference, + AGlobeAwareDefaultPawn* pawn, + std::vector& createdTilesets) { FVector targetOrigin(-104.988892, 39.743462, 1798.679443); FString ionToken( @@ -137,6 +125,9 @@ void setupForDenver(UWorld* world) { aerometrexTileset->SetIonAccessToken(ionToken); aerometrexTileset->SetMaximumScreenSpaceError(2.0); aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); + + createdTilesets.push_back(worldTerrainTileset); + createdTilesets.push_back(aerometrexTileset); } bool FCesiumLoadTest::RunTest(const FString& Parameters) { @@ -154,11 +145,48 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { #endif TestNotNull("world is valid", world); - // Configure similar to Google Tiles sample - // setupForGoogleTiles(world); - setupForDenver(world); + // Create common objects across all locations + ACesiumCameraManager* cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(world); + ACesiumGeoreference* georeference = + ACesiumGeoreference::GetDefaultGeoreference(world); + ACesiumSunSky* sunSky = world->SpawnActor(); + APlayerStart* playerStart = world->SpawnActor(); + + FSoftObjectPath objectPath( + TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); + TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); + AGlobeAwareDefaultPawn* pawn = world->SpawnActor( + Cast(DynamicPawn.LoadSynchronous())); + pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; - world->BeginPlay(); + // Configure location specific objects + std::vector tilesets; + const size_t locationIndex = 1; + switch (locationIndex) { + case 0: + setupForGoogleTiles(world, georeference, pawn, tilesets); + break; + case 1: + setupForDenver(world, georeference, pawn, tilesets); + break; + default: + break; + } + + // Halt tileset updates and reset them + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + tileset->SuspendUpdate = true; + tileset->RefreshTileset(); + } + + // Turn updates back on + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + tileset->SuspendUpdate = false; + } // Spin for 5 seconds, letting our game objects tick const double testMaxTime = 5.0; From e0deda6d0296d0f48a73728c439e8df4cdde3954 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 25 Aug 2023 15:32:23 -0600 Subject: [PATCH 11/95] Refactor common vars into context class. Add structure to loop until tiles loaded (still WIP) --- .../Private/Tests/CesiumLoadTest.cpp | 149 +++++++++++------- 1 file changed, 95 insertions(+), 54 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 4826252d5..c8a6d6c1f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -8,6 +8,7 @@ #include "Editor.h" #include "Engine/World.h" +#include "EngineAnalytics.h" #include "EngineUtils.h" #include "GameFramework/PlayerStart.h" @@ -31,7 +32,29 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.LoadTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -void tickWorld(UWorld* world, double time) { +struct LoadTestContext { + UWorld* world; + ACesiumGeoreference* georeference; + AGlobeAwareDefaultPawn* pawn; + std::vector tilesets; +}; + +bool neverBreak(LoadTestContext& context) { return false; } + +bool breakWhenTilesetsLoaded(LoadTestContext& context) { + std::vector::const_iterator it; + for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + if (tileset->GetLoadProgress() != 100) + return false; + } + return true; +} + +bool tickWorldUntil( + LoadTestContext& context, + double time, + std::function breakFunction) { const double minStepTime = 0.001; // Don't loop faster than 100 fps const double testStartMark = FPlatformTime::Seconds(); @@ -42,7 +65,10 @@ void tickWorld(UWorld* world, double time) { double frameTimeMark = FPlatformTime::Seconds(); if (frameTimeMark > testEndMark) - break; + return true; + + if (breakFunction(context)) + return false; double frameElapsedTime = frameTimeMark - lastTimeMark; @@ -53,7 +79,7 @@ void tickWorld(UWorld* world, double time) { } // Let world tick at same rate as this loop - world->Tick(ELevelTick::LEVELTICK_All, frameElapsedTime); + context.world->Tick(ELevelTick::LEVELTICK_All, frameElapsedTime); // Derived from TimerManagerTests.cpp, TimerTest_TickWorld GFrameCounter++; @@ -62,46 +88,41 @@ void tickWorld(UWorld* world, double time) { }; } -void setupForGoogleTiles( - UWorld* world, - ACesiumGeoreference* georeference, - AGlobeAwareDefaultPawn* pawn, - std::vector& createdTilesets) { +void setupForGoogleTiles(LoadTestContext& context) { FVector targetOrigin(-122.083969, 37.424492, 142.859116); FString targetUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); - georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); - pawn->SetActorLocation(FVector(0, 0, 0)); - pawn->SetActorRotation(FRotator(-25, 95, 0)); + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-25, 95, 0)); - ACesium3DTileset* tileset = world->SpawnActor(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(targetUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); - createdTilesets.push_back(tileset); + context.tilesets.push_back(tileset); } -void setupForDenver( - UWorld* world, - ACesiumGeoreference* georeference, - AGlobeAwareDefaultPawn* pawn, - std::vector& createdTilesets) { +void setupForDenver(LoadTestContext& context) { FVector targetOrigin(-104.988892, 39.743462, 1798.679443); FString ionToken( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); - georeference->SetGeoreferenceOriginLongitudeLatitudeHeight(targetOrigin); + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); - pawn->SetActorLocation(FVector(0, 0, 0)); - pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); // Add Cesium World Terrain - ACesium3DTileset* worldTerrainTileset = world->SpawnActor(); + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); worldTerrainTileset->SetIonAssetID(1); worldTerrainTileset->SetIonAccessToken(ionToken); @@ -119,56 +140,62 @@ void setupForDenver( worldTerrainTileset->AddInstanceComponent(pOverlay); // Aerometrex Denver - ACesium3DTileset* aerometrexTileset = world->SpawnActor(); + ACesium3DTileset* aerometrexTileset = + context.world->SpawnActor(); aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); aerometrexTileset->SetIonAssetID(354307); aerometrexTileset->SetIonAccessToken(ionToken); aerometrexTileset->SetMaximumScreenSpaceError(2.0); aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); - createdTilesets.push_back(worldTerrainTileset); - createdTilesets.push_back(aerometrexTileset); + context.tilesets.push_back(worldTerrainTileset); + context.tilesets.push_back(aerometrexTileset); } -bool FCesiumLoadTest::RunTest(const FString& Parameters) { - - // - // Programmatically set up the world - // +void createCommonWorldObjects(LoadTestContext& context) { #if CREATE_TEST_IN_EDITOR_WORLD - UWorld* world = FAutomationEditorCommonUtils::CreateNewMap(); + context.world = FAutomationEditorCommonUtils::CreateNewMap(); #else - UWorld* world = UWorld::CreateWorld(EWorldType::Game, false); - FWorldContext& context = GEngine->CreateNewWorldContext(EWorldType::Game); - context.SetCurrentWorld(world); + context.world = UWorld::CreateWorld(EWorldType::Game, false); + FWorldContext& worldContext = + GEngine->CreateNewWorldContext(EWorldType::Game); + worldContext.SetCurrentWorld(context.world); #endif - TestNotNull("world is valid", world); - // Create common objects across all locations ACesiumCameraManager* cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(world); - ACesiumGeoreference* georeference = - ACesiumGeoreference::GetDefaultGeoreference(world); - ACesiumSunSky* sunSky = world->SpawnActor(); - APlayerStart* playerStart = world->SpawnActor(); + ACesiumCameraManager::GetDefaultCameraManager(context.world); + ACesiumSunSky* sunSky = context.world->SpawnActor(); + APlayerStart* playerStart = context.world->SpawnActor(); FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); - AGlobeAwareDefaultPawn* pawn = world->SpawnActor( + + context.georeference = + ACesiumGeoreference::GetDefaultGeoreference(context.world); + context.pawn = context.world->SpawnActor( Cast(DynamicPawn.LoadSynchronous())); - pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; + + context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; +} + +bool FCesiumLoadTest::RunTest(const FString& Parameters) { + + // + // Programmatically set up the world + // + LoadTestContext context; + createCommonWorldObjects(context); // Configure location specific objects - std::vector tilesets; const size_t locationIndex = 1; switch (locationIndex) { case 0: - setupForGoogleTiles(world, georeference, pawn, tilesets); + setupForGoogleTiles(context); break; case 1: - setupForDenver(world, georeference, pawn, tilesets); + setupForDenver(context); break; default: break; @@ -176,31 +203,45 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Halt tileset updates and reset them std::vector::iterator it; - for (it = tilesets.begin(); it != tilesets.end(); ++it) { + for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; tileset->SuspendUpdate = true; tileset->RefreshTileset(); } + // Let world settle for 1 second + tickWorldUntil(context, 1.0, neverBreak); + // Turn updates back on - for (it = tilesets.begin(); it != tilesets.end(); ++it) { + for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; tileset->SuspendUpdate = false; } - // Spin for 5 seconds, letting our game objects tick - const double testMaxTime = 5.0; - tickWorld(world, testMaxTime); + // Spin for a maximum of 5 seconds, or until tilesets finish loading + bool timedOut = tickWorldUntil(context, 5.0, breakWhenTilesetsLoaded); + + if (FEngineAnalytics::IsAvailable()) { + if (timedOut) { + FEngineAnalytics::GetProvider().RecordEvent( + TEXT("LoadTest.TimeoutEvent")); + UE_LOG(LogCesium, Error, TEXT("Test timed out")); + } else { + FEngineAnalytics::GetProvider().RecordEvent( + TEXT("LoadTest.CompletionEvent")); + UE_LOG(LogCesium, Display, TEXT("Test completed")); + } + } // Cleanup #if CREATE_TEST_IN_EDITOR_WORLD // Let all objects persist #else - GEngine->DestroyWorldContext(world); - world->DestroyWorld(false); + GEngine->DestroyWorldContext(context.world); + context.world->DestroyWorld(false); #endif - return true; + return !timedOut; } #endif From e647f086bc4a3bb9085b13d9b1a78d4860cae7f7 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 25 Aug 2023 16:48:58 -0600 Subject: [PATCH 12/95] Add additional camera manager for updates. Add debug logging --- .../Private/Tests/CesiumLoadTest.cpp | 51 +++++++++++++------ 1 file changed, 36 insertions(+), 15 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index c8a6d6c1f..9b73b5e5a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -8,7 +8,6 @@ #include "Editor.h" #include "Engine/World.h" -#include "EngineAnalytics.h" #include "EngineUtils.h" #include "GameFramework/PlayerStart.h" @@ -35,6 +34,7 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( struct LoadTestContext { UWorld* world; ACesiumGeoreference* georeference; + ACesiumCameraManager* cameraManager; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; }; @@ -45,7 +45,10 @@ bool breakWhenTilesetsLoaded(LoadTestContext& context) { std::vector::const_iterator it; for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; - if (tileset->GetLoadProgress() != 100) + + int progress = (int)tileset->GetLoadProgress(); + UE_LOG(LogCesium, Display, TEXT("Load Progress: %d"), progress); + if (progress != 100) return false; } return true; @@ -55,7 +58,7 @@ bool tickWorldUntil( LoadTestContext& context, double time, std::function breakFunction) { - const double minStepTime = 0.001; // Don't loop faster than 100 fps + const double minStepTime = 0.050; // Don't loop faster than 20 fps const double testStartMark = FPlatformTime::Seconds(); const double testEndMark = testStartMark + time; @@ -79,6 +82,12 @@ bool tickWorldUntil( } // Let world tick at same rate as this loop + UE_LOG( + LogCesium, + Display, + TEXT("Ticking world: Frame delta: %d ms"), + int(frameElapsedTime * 1000.0)); + context.world->Tick(ELevelTick::LEVELTICK_All, frameElapsedTime); // Derived from TimerManagerTests.cpp, TimerTest_TickWorld @@ -120,6 +129,21 @@ void setupForDenver(LoadTestContext& context) { context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-5.2, -149.4, 0); + camera.FieldOfViewDegrees = 90; + + // Take over first camera, or add if it doesn't exist + const TMap cameras = + context.cameraManager->GetCameras(); + if (cameras.IsEmpty()) { + context.cameraManager->AddCamera(camera); + } else { + context.cameraManager->UpdateCamera(0, camera); + } + // Add Cesium World Terrain ACesium3DTileset* worldTerrainTileset = context.world->SpawnActor(); @@ -163,11 +187,12 @@ void createCommonWorldObjects(LoadTestContext& context) { worldContext.SetCurrentWorld(context.world); #endif - ACesiumCameraManager* cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(context.world); ACesiumSunSky* sunSky = context.world->SpawnActor(); APlayerStart* playerStart = context.world->SpawnActor(); + context.cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(context.world); + FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); @@ -210,6 +235,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { } // Let world settle for 1 second + UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); tickWorldUntil(context, 1.0, neverBreak); // Turn updates back on @@ -219,18 +245,13 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { } // Spin for a maximum of 5 seconds, or until tilesets finish loading + UE_LOG(LogCesium, Display, TEXT("\nSpinning until tilesets load...\n")); bool timedOut = tickWorldUntil(context, 5.0, breakWhenTilesetsLoaded); - if (FEngineAnalytics::IsAvailable()) { - if (timedOut) { - FEngineAnalytics::GetProvider().RecordEvent( - TEXT("LoadTest.TimeoutEvent")); - UE_LOG(LogCesium, Error, TEXT("Test timed out")); - } else { - FEngineAnalytics::GetProvider().RecordEvent( - TEXT("LoadTest.CompletionEvent")); - UE_LOG(LogCesium, Display, TEXT("Test completed")); - } + if (timedOut) { + UE_LOG(LogCesium, Error, TEXT("Test timed out")); + } else { + UE_LOG(LogCesium, Display, TEXT("Test completed")); } // Cleanup From 24d211db69afb5f25852216b1401c1cfed081651 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:28:00 -0600 Subject: [PATCH 13/95] First iteration of working test that ticks correctly --- .../Private/Tests/CesiumLoadTest.cpp | 110 ++++++++++++------ 1 file changed, 75 insertions(+), 35 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 9b73b5e5a..694577bdc 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -37,6 +37,16 @@ struct LoadTestContext { ACesiumCameraManager* cameraManager; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; + + void setCamera(const FCesiumCamera& camera) { + // Take over first camera, or add if it doesn't exist + const TMap cameras = cameraManager->GetCameras(); + if (cameras.IsEmpty()) { + cameraManager->AddCamera(camera); + } else { + cameraManager->UpdateCamera(0, camera); + } + } }; bool neverBreak(LoadTestContext& context) { return false; } @@ -47,7 +57,7 @@ bool breakWhenTilesetsLoaded(LoadTestContext& context) { ACesium3DTileset* tileset = *it; int progress = (int)tileset->GetLoadProgress(); - UE_LOG(LogCesium, Display, TEXT("Load Progress: %d"), progress); + // UE_LOG(LogCesium, Display, TEXT("Load Progress: %d"), progress); if (progress != 100) return false; } @@ -56,12 +66,12 @@ bool breakWhenTilesetsLoaded(LoadTestContext& context) { bool tickWorldUntil( LoadTestContext& context, - double time, + size_t timeoutSecs, std::function breakFunction) { const double minStepTime = 0.050; // Don't loop faster than 20 fps const double testStartMark = FPlatformTime::Seconds(); - const double testEndMark = testStartMark + time; + const double testEndMark = testStartMark + (double)timeoutSecs; double lastTimeMark = testStartMark; while (1) { @@ -70,9 +80,6 @@ bool tickWorldUntil( if (frameTimeMark > testEndMark) return true; - if (breakFunction(context)) - return false; - double frameElapsedTime = frameTimeMark - lastTimeMark; if (frameElapsedTime < minStepTime) { @@ -81,17 +88,24 @@ bool tickWorldUntil( continue; } + // + // Force a tick. Derived from various examples in this code base + // Search for FTSTicker::GetCoreTicker().Tick + // + + // Increment global frame counter once for each app tick. + GFrameCounter++; + // Let world tick at same rate as this loop - UE_LOG( - LogCesium, - Display, - TEXT("Ticking world: Frame delta: %d ms"), - int(frameElapsedTime * 1000.0)); + context.world->Tick(ELevelTick::LEVELTICK_ViewportsOnly, frameElapsedTime); - context.world->Tick(ELevelTick::LEVELTICK_All, frameElapsedTime); + // Application tick + FTaskGraphInterface::Get().ProcessThreadUntilIdle( + ENamedThreads::GameThread); + FTSTicker::GetCoreTicker().Tick(frameElapsedTime); - // Derived from TimerManagerTests.cpp, TimerTest_TickWorld - GFrameCounter++; + if (breakFunction(context)) + return false; lastTimeMark = frameTimeMark; }; @@ -103,6 +117,13 @@ void setupForGoogleTiles(LoadTestContext& context) { FString targetUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-25, 95, 0); + camera.FieldOfViewDegrees = 90; + context.setCamera(camera); + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( targetOrigin); @@ -123,26 +144,18 @@ void setupForDenver(LoadTestContext& context) { FString ionToken( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); - - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); - FCesiumCamera camera; camera.ViewportSize = FVector2D(1024, 768); camera.Location = FVector(0, 0, 0); camera.Rotation = FRotator(-5.2, -149.4, 0); camera.FieldOfViewDegrees = 90; + context.setCamera(camera); - // Take over first camera, or add if it doesn't exist - const TMap cameras = - context.cameraManager->GetCameras(); - if (cameras.IsEmpty()) { - context.cameraManager->AddCamera(camera); - } else { - context.cameraManager->UpdateCamera(0, camera); - } + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); + + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); // Add Cesium World Terrain ACesium3DTileset* worldTerrainTileset = @@ -228,6 +241,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Halt tileset updates and reset them std::vector::iterator it; + for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; tileset->SuspendUpdate = true; @@ -236,27 +250,53 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Let world settle for 1 second UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); - tickWorldUntil(context, 1.0, neverBreak); + tickWorldUntil(context, 1, neverBreak); + + // Start test mark, turn updates back on + double loadStartMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); - // Turn updates back on for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; tileset->SuspendUpdate = false; } - // Spin for a maximum of 5 seconds, or until tilesets finish loading + // Spin for a maximum of 20 seconds, or until tilesets finish loading + const size_t testTimeout = 20; UE_LOG(LogCesium, Display, TEXT("\nSpinning until tilesets load...\n")); - bool timedOut = tickWorldUntil(context, 5.0, breakWhenTilesetsLoaded); + bool timedOut = tickWorldUntil(context, testTimeout, breakWhenTilesetsLoaded); if (timedOut) { - UE_LOG(LogCesium, Error, TEXT("Test timed out")); + UE_LOG( + LogCesium, + Error, + TEXT("TIMED OUT: Loading exceeded %d seconds"), + testTimeout); } else { - UE_LOG(LogCesium, Display, TEXT("Test completed")); + double loadEndMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); + + double loadElapsedTime = loadEndMark - loadStartMark; + UE_LOG( + LogCesium, + Display, + TEXT("Tileset load completed in %.2f seconds"), + loadElapsedTime); } // Cleanup #if CREATE_TEST_IN_EDITOR_WORLD - // Let all objects persist + // Let all objects persist and be available for viewing after test + + // Let world settle for 1 second + UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); + tickWorldUntil(context, 1, neverBreak); + + // Turn updates back off + for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + tileset->SuspendUpdate = true; + } #else GEngine->DestroyWorldContext(context.world); context.world->DestroyWorld(false); From e48572dd7981cb7013547a14811c1b54db2a21f2 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 28 Aug 2023 16:35:46 -0600 Subject: [PATCH 14/95] Refactor suspend update calls (remove duplication) --- .../Private/Tests/CesiumLoadTest.cpp | 36 +++++++++---------- 1 file changed, 18 insertions(+), 18 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 694577bdc..a48824852 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -47,6 +47,18 @@ struct LoadTestContext { cameraManager->UpdateCamera(0, camera); } } + + void refreshTilesets() { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->RefreshTileset(); + } + + void setSuspendUpdate(bool suspend) { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->SuspendUpdate = suspend; + } }; bool neverBreak(LoadTestContext& context) { return false; } @@ -240,13 +252,8 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { } // Halt tileset updates and reset them - std::vector::iterator it; - - for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { - ACesium3DTileset* tileset = *it; - tileset->SuspendUpdate = true; - tileset->RefreshTileset(); - } + context.setSuspendUpdate(true); + context.refreshTilesets(); // Let world settle for 1 second UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); @@ -255,11 +262,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Start test mark, turn updates back on double loadStartMark = FPlatformTime::Seconds(); UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); - - for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { - ACesium3DTileset* tileset = *it; - tileset->SuspendUpdate = false; - } + context.setSuspendUpdate(false); // Spin for a maximum of 20 seconds, or until tilesets finish loading const size_t testTimeout = 20; @@ -286,17 +289,14 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Cleanup #if CREATE_TEST_IN_EDITOR_WORLD - // Let all objects persist and be available for viewing after test + // Let all objects be available for viewing after test // Let world settle for 1 second UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); tickWorldUntil(context, 1, neverBreak); - // Turn updates back off - for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { - ACesium3DTileset* tileset = *it; - tileset->SuspendUpdate = true; - } + // Freeze updates + context.setSuspendUpdate(true); #else GEngine->DestroyWorldContext(context.world); context.world->DestroyWorld(false); From c89f0cac8e61851f36232880855195ecd83e2877 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 29 Aug 2023 10:39:38 -0600 Subject: [PATCH 15/95] Separate tests into separate namespaces (unit, performance) And don't run performance tests on CI --- .github/workflows/testWindows.yml | 2 +- Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 2 +- Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp | 2 +- .../CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp | 2 +- 6 files changed, 6 insertions(+), 6 deletions(-) diff --git a/.github/workflows/testWindows.yml b/.github/workflows/testWindows.yml index 7ed9ad681..32f2513fe 100644 --- a/.github/workflows/testWindows.yml +++ b/.github/workflows/testWindows.yml @@ -65,7 +65,7 @@ jobs: timeout-minutes: 30 run: | cd "${{ inputs.unreal-binaries-path }}" - ./UnrealEditor-Cmd.exe "$env:TESTS_PROJECT_ROOT/TestsProject.uproject" -execcmds="Automation RunTests Cesium.;quit" -nullrhi -unattended -nosplash -ReportExportPath="$env:TESTS_PROJECT_LOGS" + ./UnrealEditor-Cmd.exe "$env:TESTS_PROJECT_ROOT/TestsProject.uproject" -execcmds="Automation RunTests Cesium.Unit.;quit" -nullrhi -unattended -nosplash -ReportExportPath="$env:TESTS_PROJECT_LOGS" - name: Display tests log run: | cd "$env:TESTS_PROJECT_LOGS" diff --git a/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp index a8b5ba961..a00b81f1a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumCameraManager.spec.cpp @@ -7,7 +7,7 @@ BEGIN_DEFINE_SPEC( FCesiumCameraManagerSpec, - "Cesium.CameraManager", + "Cesium.Unit.CameraManager", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FCesiumCameraManagerSpec) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index a48824852..f679e1124 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -28,7 +28,7 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTest, - "Cesium.LoadTest", + "Cesium.Performance.LoadTest", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) struct LoadTestContext { diff --git a/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp b/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp index dde3e5d33..d83bcd84b 100644 --- a/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/GeoTransforms.spec.cpp @@ -10,7 +10,7 @@ using namespace CesiumUtility; BEGIN_DEFINE_SPEC( FGeoTransformsSpec, - "Cesium.GeoTransforms", + "Cesium.Unit.GeoTransforms", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FGeoTransformsSpec) diff --git a/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp b/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp index 267c70486..31cb119e6 100644 --- a/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/GlobeAwareDefaultPawn.spec.cpp @@ -13,7 +13,7 @@ BEGIN_DEFINE_SPEC( FGlobeAwareDefaultPawnSpec, - "Cesium.GlobeAwareDefaultPawn", + "Cesium.Unit.GlobeAwareDefaultPawn", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) diff --git a/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp b/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp index 87d3ed90b..4166daedd 100644 --- a/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/SubLevels.spec.cpp @@ -14,7 +14,7 @@ BEGIN_DEFINE_SPEC( FSubLevelsSpec, - "Cesium.SubLevels", + "Cesium.Unit.SubLevels", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) From 20c81ee9c999f54136f68532ce10bbe982d11733 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:12:13 -0600 Subject: [PATCH 16/95] Refine logging messages for clarity --- .../Private/Tests/CesiumLoadTest.cpp | 46 +++++++++++-------- 1 file changed, 26 insertions(+), 20 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index f679e1124..7e9f8e038 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -235,6 +235,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // // Programmatically set up the world // + UE_LOG(LogCesium, Display, TEXT("Creating world objects...")); LoadTestContext context; createCommonWorldObjects(context); @@ -256,7 +257,7 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { context.refreshTilesets(); // Let world settle for 1 second - UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); + UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); tickWorldUntil(context, 1, neverBreak); // Start test mark, turn updates back on @@ -266,33 +267,22 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { // Spin for a maximum of 20 seconds, or until tilesets finish loading const size_t testTimeout = 20; - UE_LOG(LogCesium, Display, TEXT("\nSpinning until tilesets load...\n")); + UE_LOG( + LogCesium, + Display, + TEXT("Tick world until tilesets load, or %d seconds elapse..."), + testTimeout); bool timedOut = tickWorldUntil(context, testTimeout, breakWhenTilesetsLoaded); - if (timedOut) { - UE_LOG( - LogCesium, - Error, - TEXT("TIMED OUT: Loading exceeded %d seconds"), - testTimeout); - } else { - double loadEndMark = FPlatformTime::Seconds(); - UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); - - double loadElapsedTime = loadEndMark - loadStartMark; - UE_LOG( - LogCesium, - Display, - TEXT("Tileset load completed in %.2f seconds"), - loadElapsedTime); - } + double loadEndMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); // Cleanup #if CREATE_TEST_IN_EDITOR_WORLD // Let all objects be available for viewing after test // Let world settle for 1 second - UE_LOG(LogCesium, Display, TEXT("\nLetting world settle...\n")); + UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); tickWorldUntil(context, 1, neverBreak); // Freeze updates @@ -302,6 +292,22 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { context.world->DestroyWorld(false); #endif + double loadElapsedTime = loadEndMark - loadStartMark; + + if (timedOut) { + UE_LOG( + LogCesium, + Error, + TEXT("TIMED OUT: Loading stopped after %.2f seconds"), + loadElapsedTime); + } else { + UE_LOG( + LogCesium, + Display, + TEXT("Tileset load completed in %.2f seconds"), + loadElapsedTime); + } + return !timedOut; } From 43cf2577b8a5ae73bd9ae6c450931cc09a5c6eb1 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:19:59 -0600 Subject: [PATCH 17/95] Implement two tests for demonstration (Denver, Googleplex) --- .../Private/Tests/CesiumLoadTest.cpp | 20 +++++++++++++++---- 1 file changed, 16 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 7e9f8e038..f4f0d709e 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -27,8 +27,13 @@ #define CREATE_TEST_IN_EDITOR_WORLD 1 IMPLEMENT_SIMPLE_AUTOMATION_TEST( - FCesiumLoadTest, - "Cesium.Performance.LoadTest", + FCesiumLoadTestDenver, + "Cesium.Performance.LoadTestDenver", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumLoadTestGoogleplex, + "Cesium.Performance.LoadTestGoogleplex", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) struct LoadTestContext { @@ -230,7 +235,7 @@ void createCommonWorldObjects(LoadTestContext& context) { context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; } -bool FCesiumLoadTest::RunTest(const FString& Parameters) { +bool RunLoadTest(const size_t locationIndex) { // // Programmatically set up the world @@ -240,7 +245,6 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { createCommonWorldObjects(context); // Configure location specific objects - const size_t locationIndex = 1; switch (locationIndex) { case 0: setupForGoogleTiles(context); @@ -311,4 +315,12 @@ bool FCesiumLoadTest::RunTest(const FString& Parameters) { return !timedOut; } +bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { + return RunLoadTest(1); +} + +bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { + return RunLoadTest(0); +} + #endif From 12b9c6d6156b3b58c294d72587f5bdb13468342e Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 29 Aug 2023 13:24:41 -0600 Subject: [PATCH 18/95] Remove debug and test code --- .../Private/Tests/CesiumLoadTest.cpp | 25 +++---------------- 1 file changed, 3 insertions(+), 22 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index f4f0d709e..cc4da39fe 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -20,12 +20,6 @@ #include "CesiumTestHelpers.h" #include "GlobeAwareDefaultPawn.h" -// -// For debugging, it may help to create the scene in the editor -// After the test is run, you can play with their settings and even run PIE -// -#define CREATE_TEST_IN_EDITOR_WORLD 1 - IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTestDenver, "Cesium.Performance.LoadTestDenver", @@ -74,7 +68,6 @@ bool breakWhenTilesetsLoaded(LoadTestContext& context) { ACesium3DTileset* tileset = *it; int progress = (int)tileset->GetLoadProgress(); - // UE_LOG(LogCesium, Display, TEXT("Load Progress: %d"), progress); if (progress != 100) return false; } @@ -208,14 +201,7 @@ void setupForDenver(LoadTestContext& context) { void createCommonWorldObjects(LoadTestContext& context) { -#if CREATE_TEST_IN_EDITOR_WORLD context.world = FAutomationEditorCommonUtils::CreateNewMap(); -#else - context.world = UWorld::CreateWorld(EWorldType::Game, false); - FWorldContext& worldContext = - GEngine->CreateNewWorldContext(EWorldType::Game); - worldContext.SetCurrentWorld(context.world); -#endif ACesiumSunSky* sunSky = context.world->SpawnActor(); APlayerStart* playerStart = context.world->SpawnActor(); @@ -281,20 +267,15 @@ bool RunLoadTest(const size_t locationIndex) { double loadEndMark = FPlatformTime::Seconds(); UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); - // Cleanup -#if CREATE_TEST_IN_EDITOR_WORLD - // Let all objects be available for viewing after test - + // + // Skip object cleanup. Let all objects be available for viewing after test + // // Let world settle for 1 second UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); tickWorldUntil(context, 1, neverBreak); // Freeze updates context.setSuspendUpdate(true); -#else - GEngine->DestroyWorldContext(context.world); - context.world->DestroyWorld(false); -#endif double loadElapsedTime = loadEndMark - loadStartMark; From fd2da6022e802cab7e19c6a1574e08953aaf2258 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 29 Aug 2023 14:46:39 -0600 Subject: [PATCH 19/95] Add code to let UI tick when running tests --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index cc4da39fe..fb8ce9a56 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -114,6 +114,12 @@ bool tickWorldUntil( ENamedThreads::GameThread); FTSTicker::GetCoreTicker().Tick(frameElapsedTime); + // Let UI update + // Not absolutely necessary, but convenient when running the tests + // from inside the editor, so the UI doesn't appear frozen + FSlateApplication::Get().PumpMessages(); + FSlateApplication::Get().Tick(); + if (breakFunction(context)) return false; From bbd61c074e134dfaffc84bbf731b4dcabb984de9 Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Thu, 31 Aug 2023 15:55:08 +1000 Subject: [PATCH 20/95] Tweaks to performance testing framework. --- Source/CesiumRuntime/CesiumRuntime.Build.cs | 2 + .../CesiumRuntime/Private/Cesium3DTileset.cpp | 9 +- .../Private/Tests/CesiumLoadTest.cpp | 103 +++++++++++++++--- extern/cesium-native | 2 +- 4 files changed, 101 insertions(+), 15 deletions(-) diff --git a/Source/CesiumRuntime/CesiumRuntime.Build.cs b/Source/CesiumRuntime/CesiumRuntime.Build.cs index 9cbd2b379..d2b708b65 100644 --- a/Source/CesiumRuntime/CesiumRuntime.Build.cs +++ b/Source/CesiumRuntime/CesiumRuntime.Build.cs @@ -81,6 +81,8 @@ public CesiumRuntime(ReadOnlyTargetRules Target) : base(Target) string[] libs = new string[] { "async++", + "Cesium3DTiles", + "Cesium3DTilesReader", "Cesium3DTilesSelection", "CesiumAsync", "CesiumGeometry", diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index dd2077153..cf845984e 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -890,6 +890,12 @@ void ACesium3DTileset::UpdateLoadStatus() { this->LoadProgress = this->_pTileset->computeLoadProgress(); + // If we have tiles to hide next frame, we haven't completely finished loading + // yet. We need to tick once more + if (!this->_tilesToHideNextFrame.empty()) { + this->LoadProgress = glm::min(this->LoadProgress, 99.9999f); + } + if (this->LoadProgress < 100 || this->_lastTilesWaitingForOcclusionResults > 0) { this->_activeLoading = true; @@ -2031,7 +2037,6 @@ void ACesium3DTileset::Tick(float DeltaTime) { ? this->_pTileset->updateViewOffline(frustums) : this->_pTileset->updateView(frustums, DeltaTime); updateLastViewUpdateResultState(result); - this->UpdateLoadStatus(); removeCollisionForTiles(result.tilesFadingOut); @@ -2064,6 +2069,8 @@ void ACesium3DTileset::Tick(float DeltaTime) { updateTileFade(pTile, false); } } + + this->UpdateLoadStatus(); } void ACesium3DTileset::EndPlay(const EEndPlayReason::Type EndPlayReason) { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index fb8ce9a56..182abb4d1 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -14,6 +14,7 @@ #include "Cesium3DTileset.h" #include "CesiumCameraManager.h" #include "CesiumGeoreference.h" +#include "CesiumGltfComponent.h" #include "CesiumIonRasterOverlay.h" #include "CesiumRuntime.h" #include "CesiumSunSky.h" @@ -30,6 +31,11 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.LoadTestGoogleplex", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumLoadTestMontrealPointCloud, + "Cesium.Performance.LoadTestMontrealPointCloud", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + struct LoadTestContext { UWorld* world; ACesiumGeoreference* georeference; @@ -227,7 +233,9 @@ void createCommonWorldObjects(LoadTestContext& context) { context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; } -bool RunLoadTest(const size_t locationIndex) { +bool RunLoadTest( + std::function locationSetup, + std::function afterTest = {}) { // // Programmatically set up the world @@ -237,16 +245,7 @@ bool RunLoadTest(const size_t locationIndex) { createCommonWorldObjects(context); // Configure location specific objects - switch (locationIndex) { - case 0: - setupForGoogleTiles(context); - break; - case 1: - setupForDenver(context); - break; - default: - break; - } + locationSetup(context); // Halt tileset updates and reset them context.setSuspendUpdate(true); @@ -299,15 +298,93 @@ bool RunLoadTest(const size_t locationIndex) { loadElapsedTime); } + if (afterTest) { + afterTest(context); + } + return !timedOut; } bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { - return RunLoadTest(1); + return RunLoadTest(setupForDenver); } bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { - return RunLoadTest(0); + return RunLoadTest(setupForGoogleTiles); +} + +bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { + auto setup = [this](LoadTestContext& context) { + FVector targetOrigin(-73.616526, 45.57335, 95.048859); + FString ionToken( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); + + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-90.0, 0.0, 0.0); + camera.FieldOfViewDegrees = 90; + context.setCamera(camera); + + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); + + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-90.0, 0.0, 0.0)); + + // Montreal Point Cloud + ACesium3DTileset* montrealTileset = + context.world->SpawnActor(); + montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + montrealTileset->SetIonAssetID(28945); + montrealTileset->SetIonAccessToken(ionToken); + montrealTileset->SetMaximumScreenSpaceError(16.0); + montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); + + context.tilesets.push_back(montrealTileset); + }; + + auto after = [this](LoadTestContext& context) { + // Zoom way out + FCesiumCamera zoomedOut; + zoomedOut.ViewportSize = FVector2D(1024, 768); + zoomedOut.Location = FVector(0, 0, 7240000.0); + zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); + zoomedOut.FieldOfViewDegrees = 90; + context.setCamera(zoomedOut); + + context.pawn->SetActorLocation(zoomedOut.Location); + + context.setSuspendUpdate(false); + tickWorldUntil(context, 10, breakWhenTilesetsLoaded); + context.setSuspendUpdate(true); + + Cesium3DTilesSelection::Tileset* pTileset = + context.tilesets[0]->GetTileset(); + if (TestNotNull("Tileset", pTileset)) { + int visibleTiles = 0; + pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { + if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) + return; + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + ++visibleTiles; + } + }); + + TestEqual("visibleTiles", visibleTiles, 1); + } + }; + + return RunLoadTest(setup, after); } #endif diff --git a/extern/cesium-native b/extern/cesium-native index 172ac5ddc..da901d260 160000 --- a/extern/cesium-native +++ b/extern/cesium-native @@ -1 +1 @@ -Subproject commit 172ac5ddcce602c8b268ad342639554dea2f6004 +Subproject commit da901d260eae9b0a802a396d11185a9fc24a711e From 7614bb3ad098992f515459b84508130a94aabf28 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 31 Aug 2023 13:00:10 -0600 Subject: [PATCH 21/95] Add logic to start / end play session --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 182abb4d1..87ecdd3e9 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -251,6 +251,12 @@ bool RunLoadTest( context.setSuspendUpdate(true); context.refreshTilesets(); + // Immediately start a requested play session + UE_LOG(LogCesium, Display, TEXT("Requesting play session...")); + FRequestPlaySessionParams params{}; + GEditor->RequestPlaySession(params); + GEditor->StartQueuedPlaySessionRequest(); + // Let world settle for 1 second UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); tickWorldUntil(context, 1, neverBreak); @@ -282,6 +288,9 @@ bool RunLoadTest( // Freeze updates context.setSuspendUpdate(true); + UE_LOG(LogCesium, Display, TEXT("Ending play session...")); + GEditor->RequestEndPlayMap(); + double loadElapsedTime = loadEndMark - loadStartMark; if (timedOut) { From 4dd0060f55e8f774e954e9e01ac7d6b1308ddc5f Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 31 Aug 2023 13:24:38 -0600 Subject: [PATCH 22/95] Unfreeze updates when test ends, so we can see something When PIE ends, it seems to clear all tiles. Before we froze the state of what the test loaded, which was useful. But it's not all that useful to just see nothing when the test ends. Let it stream it all back in. Also, move play session param to context so it can be configured if needed --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 7 ++----- 1 file changed, 2 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 87ecdd3e9..3fe663fae 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -42,6 +42,7 @@ struct LoadTestContext { ACesiumCameraManager* cameraManager; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; + FRequestPlaySessionParams playSessionParams; void setCamera(const FCesiumCamera& camera) { // Take over first camera, or add if it doesn't exist @@ -253,8 +254,7 @@ bool RunLoadTest( // Immediately start a requested play session UE_LOG(LogCesium, Display, TEXT("Requesting play session...")); - FRequestPlaySessionParams params{}; - GEditor->RequestPlaySession(params); + GEditor->RequestPlaySession(context.playSessionParams); GEditor->StartQueuedPlaySessionRequest(); // Let world settle for 1 second @@ -285,9 +285,6 @@ bool RunLoadTest( UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); tickWorldUntil(context, 1, neverBreak); - // Freeze updates - context.setSuspendUpdate(true); - UE_LOG(LogCesium, Display, TEXT("Ending play session...")); GEditor->RequestEndPlayMap(); From b9f594fe5909608f9e0749f38d00eebe60c5c351 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 1 Sep 2023 14:33:12 -0600 Subject: [PATCH 23/95] Update ion token for test (sync with default in samples project) --- .../CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 13 ++++++------- 1 file changed, 6 insertions(+), 7 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 3fe663fae..65aa16f9a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -21,6 +21,9 @@ #include "CesiumTestHelpers.h" #include "GlobeAwareDefaultPawn.h" +FString testIonToken( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); + IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTestDenver, "Cesium.Performance.LoadTestDenver", @@ -164,8 +167,6 @@ void setupForGoogleTiles(LoadTestContext& context) { void setupForDenver(LoadTestContext& context) { FVector targetOrigin(-104.988892, 39.743462, 1798.679443); - FString ionToken( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); FCesiumCamera camera; camera.ViewportSize = FVector2D(1024, 768); @@ -185,7 +186,7 @@ void setupForDenver(LoadTestContext& context) { context.world->SpawnActor(); worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); worldTerrainTileset->SetIonAssetID(1); - worldTerrainTileset->SetIonAccessToken(ionToken); + worldTerrainTileset->SetIonAccessToken(testIonToken); worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); // Bing Maps Aerial overlay @@ -204,7 +205,7 @@ void setupForDenver(LoadTestContext& context) { context.world->SpawnActor(); aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); aerometrexTileset->SetIonAssetID(354307); - aerometrexTileset->SetIonAccessToken(ionToken); + aerometrexTileset->SetIonAccessToken(testIonToken); aerometrexTileset->SetMaximumScreenSpaceError(2.0); aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); @@ -322,8 +323,6 @@ bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { auto setup = [this](LoadTestContext& context) { FVector targetOrigin(-73.616526, 45.57335, 95.048859); - FString ionToken( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI2NmZhZTk4NS01MDFmLTRjODgtOTlkYy04NjIwODhiZWExOGYiLCJpZCI6MjU5LCJpYXQiOjE2ODg1MTI4ODd9.haoe5hsJyfHk1dQAHVK6N8dW_kfmtdbyuhlGwFdEHbM"); FCesiumCamera camera; camera.ViewportSize = FVector2D(1024, 768); @@ -343,7 +342,7 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { context.world->SpawnActor(); montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); montrealTileset->SetIonAssetID(28945); - montrealTileset->SetIonAccessToken(ionToken); + montrealTileset->SetIonAccessToken(testIonToken); montrealTileset->SetMaximumScreenSpaceError(16.0); montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); From 9c9ef245772e9fe02fc06c395f4f25d154bff975 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 1 Sep 2023 15:17:21 -0600 Subject: [PATCH 24/95] Refactor scene setup code into separate files --- .../Private/Tests/CesiumLoadTest.cpp | 192 ++---------------- .../Private/Tests/CesiumSceneGeneration.cpp | 169 +++++++++++++++ .../Private/Tests/CesiumSceneGeneration.h | 40 ++++ 3 files changed, 222 insertions(+), 179 deletions(-) create mode 100644 Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp create mode 100644 Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 65aa16f9a..c033b2d7f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -6,23 +6,13 @@ #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" -#include "Editor.h" -#include "Engine/World.h" -#include "EngineUtils.h" -#include "GameFramework/PlayerStart.h" - -#include "Cesium3DTileset.h" -#include "CesiumCameraManager.h" -#include "CesiumGeoreference.h" +#include "CesiumTestHelpers.h" +#include "CesiumSceneGeneration.h" #include "CesiumGltfComponent.h" -#include "CesiumIonRasterOverlay.h" #include "CesiumRuntime.h" -#include "CesiumSunSky.h" -#include "CesiumTestHelpers.h" #include "GlobeAwareDefaultPawn.h" -FString testIonToken( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); +using namespace Cesium; IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumLoadTestDenver, @@ -39,40 +29,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.LoadTestMontrealPointCloud", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -struct LoadTestContext { - UWorld* world; - ACesiumGeoreference* georeference; - ACesiumCameraManager* cameraManager; - AGlobeAwareDefaultPawn* pawn; - std::vector tilesets; - FRequestPlaySessionParams playSessionParams; - - void setCamera(const FCesiumCamera& camera) { - // Take over first camera, or add if it doesn't exist - const TMap cameras = cameraManager->GetCameras(); - if (cameras.IsEmpty()) { - cameraManager->AddCamera(camera); - } else { - cameraManager->UpdateCamera(0, camera); - } - } - - void refreshTilesets() { - std::vector::iterator it; - for (it = tilesets.begin(); it != tilesets.end(); ++it) - (*it)->RefreshTileset(); - } - - void setSuspendUpdate(bool suspend) { - std::vector::iterator it; - for (it = tilesets.begin(); it != tilesets.end(); ++it) - (*it)->SuspendUpdate = suspend; - } -}; - -bool neverBreak(LoadTestContext& context) { return false; } +bool neverBreak(SceneGenerationContext& context) { return false; } -bool breakWhenTilesetsLoaded(LoadTestContext& context) { +bool breakWhenTilesetsLoaded(SceneGenerationContext& context) { std::vector::const_iterator it; for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { ACesium3DTileset* tileset = *it; @@ -85,9 +44,9 @@ bool breakWhenTilesetsLoaded(LoadTestContext& context) { } bool tickWorldUntil( - LoadTestContext& context, + SceneGenerationContext& context, size_t timeoutSecs, - std::function breakFunction) { + std::function breakFunction) { const double minStepTime = 0.050; // Don't loop faster than 20 fps const double testStartMark = FPlatformTime::Seconds(); @@ -137,114 +96,16 @@ bool tickWorldUntil( }; } -void setupForGoogleTiles(LoadTestContext& context) { - - FVector targetOrigin(-122.083969, 37.424492, 142.859116); - FString targetUrl( - "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); - - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-25, 95, 0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); - - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); - - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-25, 95, 0)); - - ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(targetUrl); - tileset->SetTilesetSource(ETilesetSource::FromUrl); - tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); - - context.tilesets.push_back(tileset); -} - -void setupForDenver(LoadTestContext& context) { - - FVector targetOrigin(-104.988892, 39.743462, 1798.679443); - - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-5.2, -149.4, 0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); - - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); - - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); - - // Add Cesium World Terrain - ACesium3DTileset* worldTerrainTileset = - context.world->SpawnActor(); - worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - worldTerrainTileset->SetIonAssetID(1); - worldTerrainTileset->SetIonAccessToken(testIonToken); - worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); - - // Bing Maps Aerial overlay - UCesiumIonRasterOverlay* pOverlay = NewObject( - worldTerrainTileset, - FName("Bing Maps Aerial"), - RF_Transactional); - pOverlay->MaterialLayerKey = TEXT("Overlay0"); - pOverlay->IonAssetID = 2; - pOverlay->SetActive(true); - pOverlay->OnComponentCreated(); - worldTerrainTileset->AddInstanceComponent(pOverlay); - - // Aerometrex Denver - ACesium3DTileset* aerometrexTileset = - context.world->SpawnActor(); - aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - aerometrexTileset->SetIonAssetID(354307); - aerometrexTileset->SetIonAccessToken(testIonToken); - aerometrexTileset->SetMaximumScreenSpaceError(2.0); - aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); - - context.tilesets.push_back(worldTerrainTileset); - context.tilesets.push_back(aerometrexTileset); -} - -void createCommonWorldObjects(LoadTestContext& context) { - - context.world = FAutomationEditorCommonUtils::CreateNewMap(); - - ACesiumSunSky* sunSky = context.world->SpawnActor(); - APlayerStart* playerStart = context.world->SpawnActor(); - - context.cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(context.world); - - FSoftObjectPath objectPath( - TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); - TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); - - context.georeference = - ACesiumGeoreference::GetDefaultGeoreference(context.world); - context.pawn = context.world->SpawnActor( - Cast(DynamicPawn.LoadSynchronous())); - - context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; -} - bool RunLoadTest( - std::function locationSetup, - std::function afterTest = {}) { + std::function locationSetup, + std::function afterTest = {}) { // // Programmatically set up the world // UE_LOG(LogCesium, Display, TEXT("Creating world objects...")); - LoadTestContext context; - createCommonWorldObjects(context); + Cesium::SceneGenerationContext context; + Cesium::createCommonWorldObjects(context); // Configure location specific objects locationSetup(context); @@ -321,35 +182,8 @@ bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { } bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { - auto setup = [this](LoadTestContext& context) { - FVector targetOrigin(-73.616526, 45.57335, 95.048859); - - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-90.0, 0.0, 0.0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); - - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); - - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-90.0, 0.0, 0.0)); - - // Montreal Point Cloud - ACesium3DTileset* montrealTileset = - context.world->SpawnActor(); - montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - montrealTileset->SetIonAssetID(28945); - montrealTileset->SetIonAccessToken(testIonToken); - montrealTileset->SetMaximumScreenSpaceError(16.0); - montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); - - context.tilesets.push_back(montrealTileset); - }; - auto after = [this](LoadTestContext& context) { + auto after = [this](SceneGenerationContext& context) { // Zoom way out FCesiumCamera zoomedOut; zoomedOut.ViewportSize = FVector2D(1024, 768); @@ -389,7 +223,7 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { } }; - return RunLoadTest(setup, after); + return RunLoadTest(setupForMelbourne, after); } #endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp new file mode 100644 index 000000000..dd8603357 --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -0,0 +1,169 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#include "CesiumSceneGeneration.h" + +#include "Tests/AutomationEditorCommon.h" + +#include "GameFramework/PlayerStart.h" + +#include "Cesium3DTileset.h" +#include "CesiumCameraManager.h" +#include "CesiumGeoreference.h" +#include "CesiumIonRasterOverlay.h" +#include "CesiumSunSky.h" +#include "GlobeAwareDefaultPawn.h" + +namespace Cesium { + +FString SceneGenerationContext::testIonToken( + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); + +void SceneGenerationContext::setCamera(const FCesiumCamera& camera) { + // Take over first camera, or add if it doesn't exist + const TMap cameras = cameraManager->GetCameras(); + if (cameras.IsEmpty()) { + cameraManager->AddCamera(camera); + } else { + cameraManager->UpdateCamera(0, camera); + } +} + +void SceneGenerationContext::refreshTilesets() { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->RefreshTileset(); +} + +void SceneGenerationContext::setSuspendUpdate(bool suspend) { + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) + (*it)->SuspendUpdate = suspend; +} + +void createCommonWorldObjects(SceneGenerationContext& context) { + + context.world = FAutomationEditorCommonUtils::CreateNewMap(); + + ACesiumSunSky* sunSky = context.world->SpawnActor(); + APlayerStart* playerStart = context.world->SpawnActor(); + + context.cameraManager = + ACesiumCameraManager::GetDefaultCameraManager(context.world); + + FSoftObjectPath objectPath( + TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); + TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); + + context.georeference = + ACesiumGeoreference::GetDefaultGeoreference(context.world); + context.pawn = context.world->SpawnActor( + Cast(DynamicPawn.LoadSynchronous())); + + context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; +} + +void setupForGoogleTiles(SceneGenerationContext& context) { + + FVector targetOrigin(-122.083969, 37.424492, 142.859116); + FString targetUrl( + "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); + + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-25, 95, 0); + camera.FieldOfViewDegrees = 90; + context.setCamera(camera); + + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); + + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-25, 95, 0)); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(targetUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); + + context.tilesets.push_back(tileset); +} + +void setupForDenver(SceneGenerationContext& context) { + + FVector targetOrigin(-104.988892, 39.743462, 1798.679443); + + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-5.2, -149.4, 0); + camera.FieldOfViewDegrees = 90; + context.setCamera(camera); + + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); + + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + + // Bing Maps Aerial overlay + UCesiumIonRasterOverlay* pOverlay = NewObject( + worldTerrainTileset, + FName("Bing Maps Aerial"), + RF_Transactional); + pOverlay->MaterialLayerKey = TEXT("Overlay0"); + pOverlay->IonAssetID = 2; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + worldTerrainTileset->AddInstanceComponent(pOverlay); + + // Aerometrex Denver + ACesium3DTileset* aerometrexTileset = + context.world->SpawnActor(); + aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + aerometrexTileset->SetIonAssetID(354307); + aerometrexTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + aerometrexTileset->SetMaximumScreenSpaceError(2.0); + aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); + + context.tilesets.push_back(worldTerrainTileset); + context.tilesets.push_back(aerometrexTileset); +} + +void setupForMelbourne(SceneGenerationContext& context) { + FVector targetOrigin(-73.616526, 45.57335, 95.048859); + + FCesiumCamera camera; + camera.ViewportSize = FVector2D(1024, 768); + camera.Location = FVector(0, 0, 0); + camera.Rotation = FRotator(-90.0, 0.0, 0.0); + camera.FieldOfViewDegrees = 90; + context.setCamera(camera); + + context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + targetOrigin); + + context.pawn->SetActorLocation(FVector(0, 0, 0)); + context.pawn->SetActorRotation(FRotator(-90.0, 0.0, 0.0)); + + // Montreal Point Cloud + ACesium3DTileset* montrealTileset = + context.world->SpawnActor(); + montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + montrealTileset->SetIonAssetID(28945); + montrealTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + montrealTileset->SetMaximumScreenSpaceError(16.0); + montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); + + context.tilesets.push_back(montrealTileset); +} + +} // namespace Cesium diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h new file mode 100644 index 000000000..54a2fc4be --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -0,0 +1,40 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#pragma once + +#if WITH_EDITOR + +#include "CesiumCameraManager.h" +#include "Editor.h" + +class UWorld; +class ACesiumGeoreference; +class AGlobeAwareDefaultPawn; +class ACesium3DTileset; + +namespace Cesium { + +struct SceneGenerationContext { + UWorld* world; + ACesiumGeoreference* georeference; + ACesiumCameraManager* cameraManager; + AGlobeAwareDefaultPawn* pawn; + std::vector tilesets; + FRequestPlaySessionParams playSessionParams; + + void setCamera(const FCesiumCamera& camera); + void refreshTilesets(); + void setSuspendUpdate(bool suspend); + + static FString testIonToken; +}; + +void createCommonWorldObjects(SceneGenerationContext& context); + +void setupForDenver(SceneGenerationContext& context); +void setupForGoogleTiles(SceneGenerationContext& context); +void setupForMelbourne(SceneGenerationContext& context); + +}; // namespace Cesium + +#endif // #if WITH_EDITOR From b642e17ea9b2f22cbe9e90605254a3ee3bc70897 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:30:40 -0600 Subject: [PATCH 25/95] Add missing control path --- Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h index 02becf9bb..ec54a5d5d 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumTestHelpers.h @@ -157,6 +157,8 @@ template T* findInPlay(T* pEditorObject) { return nullptr; return getComponentWithTag(pPlayOwner, getUniqueTag(pEditorObject)); } + + return nullptr; } /// From 291ac14830b89e7496e9b94253f38f960e452b5c Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 5 Sep 2023 11:32:50 -0600 Subject: [PATCH 26/95] Rework tick logic to use latent commands Melbourne 'after' test is temporarily commented out --- .../Private/Tests/CesiumLoadTest.cpp | 268 ++++++++---------- .../Private/Tests/CesiumSceneGeneration.cpp | 49 ++++ .../Private/Tests/CesiumSceneGeneration.h | 5 +- 3 files changed, 176 insertions(+), 146 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index c033b2d7f..8ece64ead 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -6,10 +6,10 @@ #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" -#include "CesiumTestHelpers.h" -#include "CesiumSceneGeneration.h" #include "CesiumGltfComponent.h" #include "CesiumRuntime.h" +#include "CesiumSceneGeneration.h" +#include "CesiumTestHelpers.h" #include "GlobeAwareDefaultPawn.h" using namespace Cesium; @@ -29,71 +29,81 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.LoadTestMontrealPointCloud", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -bool neverBreak(SceneGenerationContext& context) { return false; } +struct LoadTestContext { + SceneGenerationContext creationContext; + SceneGenerationContext playContext; -bool breakWhenTilesetsLoaded(SceneGenerationContext& context) { - std::vector::const_iterator it; - for (it = context.tilesets.begin(); it != context.tilesets.end(); ++it) { - ACesium3DTileset* tileset = *it; + bool testStarted; + double startMark; + double endMark; - int progress = (int)tileset->GetLoadProgress(); - if (progress != 100) - return false; + void reset() { + creationContext = playContext = SceneGenerationContext(); + testStarted = false; + startMark = endMark = 0; } - return true; -} +}; -bool tickWorldUntil( - SceneGenerationContext& context, - size_t timeoutSecs, - std::function breakFunction) { - const double minStepTime = 0.050; // Don't loop faster than 20 fps +LoadTestContext gLoadTestContext; - const double testStartMark = FPlatformTime::Seconds(); - const double testEndMark = testStartMark + (double)timeoutSecs; - double lastTimeMark = testStartMark; +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( + TimeLoadingCommand, + LoadTestContext&, + context); +bool TimeLoadingCommand::Update() { - while (1) { - double frameTimeMark = FPlatformTime::Seconds(); + if (!context.testStarted) { - if (frameTimeMark > testEndMark) - return true; + // Bind all play in editor pointers + context.playContext.initForPlay(context.creationContext); - double frameElapsedTime = frameTimeMark - lastTimeMark; + // Start test mark, turn updates back on + context.startMark = FPlatformTime::Seconds(); + UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); - if (frameElapsedTime < minStepTime) { - double sleepTarget = minStepTime - frameElapsedTime; - FPlatformProcess::Sleep(sleepTarget); - continue; - } - - // - // Force a tick. Derived from various examples in this code base - // Search for FTSTicker::GetCoreTicker().Tick - // + context.playContext.setSuspendUpdate(false); - // Increment global frame counter once for each app tick. - GFrameCounter++; + context.testStarted = true; + // Return, let world tick + return false; + } - // Let world tick at same rate as this loop - context.world->Tick(ELevelTick::LEVELTICK_ViewportsOnly, frameElapsedTime); + double timeMark = FPlatformTime::Seconds(); + double testElapsedTime = timeMark - context.startMark; - // Application tick - FTaskGraphInterface::Get().ProcessThreadUntilIdle( - ENamedThreads::GameThread); - FTSTicker::GetCoreTicker().Tick(frameElapsedTime); + // The command is over if tilesets are loaded, or timed out + // Wait for a maximum of 20 seconds + const size_t testTimeout = 20; + bool tilesetsloaded = context.playContext.areTilesetsDoneLoading(); + bool timedOut = testElapsedTime >= testTimeout; + + if (tilesetsloaded || timedOut) { + context.endMark = timeMark; + UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); + + if (timedOut) { + UE_LOG( + LogCesium, + Error, + TEXT("TIMED OUT: Loading stopped after %.2f seconds"), + testElapsedTime); + } else { + UE_LOG( + LogCesium, + Display, + TEXT("Tileset load completed in %.2f seconds"), + testElapsedTime); + } - // Let UI update - // Not absolutely necessary, but convenient when running the tests - // from inside the editor, so the UI doesn't appear frozen - FSlateApplication::Get().PumpMessages(); - FSlateApplication::Get().Tick(); + // Turn on the editor tileset updates so we can see what we loaded + gLoadTestContext.creationContext.setSuspendUpdate(false); - if (breakFunction(context)) - return false; + // Command is done + return true; + } - lastTimeMark = frameTimeMark; - }; + // Let world tick, we'll come back to this command + return false; } bool RunLoadTest( @@ -103,74 +113,41 @@ bool RunLoadTest( // // Programmatically set up the world // + gLoadTestContext.reset(); UE_LOG(LogCesium, Display, TEXT("Creating world objects...")); - Cesium::SceneGenerationContext context; - Cesium::createCommonWorldObjects(context); + createCommonWorldObjects(gLoadTestContext.creationContext); // Configure location specific objects - locationSetup(context); + locationSetup(gLoadTestContext.creationContext); + gLoadTestContext.creationContext.trackForPlay(); // Halt tileset updates and reset them - context.setSuspendUpdate(true); - context.refreshTilesets(); - - // Immediately start a requested play session - UE_LOG(LogCesium, Display, TEXT("Requesting play session...")); - GEditor->RequestPlaySession(context.playSessionParams); - GEditor->StartQueuedPlaySessionRequest(); + gLoadTestContext.creationContext.setSuspendUpdate(true); + gLoadTestContext.creationContext.refreshTilesets(); - // Let world settle for 1 second - UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); - tickWorldUntil(context, 1, neverBreak); + // + // Start async commands + // - // Start test mark, turn updates back on - double loadStartMark = FPlatformTime::Seconds(); - UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); - context.setSuspendUpdate(false); + // Start play in editor (don't sim in editor) + ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(false)); - // Spin for a maximum of 20 seconds, or until tilesets finish loading - const size_t testTimeout = 20; - UE_LOG( - LogCesium, - Display, - TEXT("Tick world until tilesets load, or %d seconds elapse..."), - testTimeout); - bool timedOut = tickWorldUntil(context, testTimeout, breakWhenTilesetsLoaded); + // Wait a bit + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); - double loadEndMark = FPlatformTime::Seconds(); - UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); + // Do our timing capture + ADD_LATENT_AUTOMATION_COMMAND(TimeLoadingCommand(gLoadTestContext)); - // - // Skip object cleanup. Let all objects be available for viewing after test - // - // Let world settle for 1 second - UE_LOG(LogCesium, Display, TEXT("Letting world settle for 1 second...")); - tickWorldUntil(context, 1, neverBreak); - - UE_LOG(LogCesium, Display, TEXT("Ending play session...")); - GEditor->RequestEndPlayMap(); - - double loadElapsedTime = loadEndMark - loadStartMark; - - if (timedOut) { - UE_LOG( - LogCesium, - Error, - TEXT("TIMED OUT: Loading stopped after %.2f seconds"), - loadElapsedTime); - } else { - UE_LOG( - LogCesium, - Display, - TEXT("Tileset load completed in %.2f seconds"), - loadElapsedTime); - } + // End play in editor + ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); - if (afterTest) { - afterTest(context); - } + /* + if (afterTest) { + afterTest(context); + } + */ - return !timedOut; + return true; } bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { @@ -184,43 +161,44 @@ bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { auto after = [this](SceneGenerationContext& context) { - // Zoom way out - FCesiumCamera zoomedOut; - zoomedOut.ViewportSize = FVector2D(1024, 768); - zoomedOut.Location = FVector(0, 0, 7240000.0); - zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); - zoomedOut.FieldOfViewDegrees = 90; - context.setCamera(zoomedOut); - - context.pawn->SetActorLocation(zoomedOut.Location); - - context.setSuspendUpdate(false); - tickWorldUntil(context, 10, breakWhenTilesetsLoaded); - context.setSuspendUpdate(true); - - Cesium3DTilesSelection::Tileset* pTileset = - context.tilesets[0]->GetTileset(); - if (TestNotNull("Tileset", pTileset)) { - int visibleTiles = 0; - pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { - if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) - return; - const Cesium3DTilesSelection::TileContent& content = tile.getContent(); - const Cesium3DTilesSelection::TileRenderContent* pRenderContent = - content.getRenderContent(); - if (!pRenderContent) { - return; - } - - UCesiumGltfComponent* Gltf = static_cast( - pRenderContent->getRenderResources()); - if (Gltf && Gltf->IsVisible()) { - ++visibleTiles; - } - }); - - TestEqual("visibleTiles", visibleTiles, 1); - } + /* + // Zoom way out + FCesiumCamera zoomedOut; + zoomedOut.ViewportSize = FVector2D(1024, 768); + zoomedOut.Location = FVector(0, 0, 7240000.0); + zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); + zoomedOut.FieldOfViewDegrees = 90; + context.setCamera(zoomedOut); + + context.pawn->SetActorLocation(zoomedOut.Location); + + context.setSuspendUpdate(false); + tickWorldUntil(context, 10, breakWhenTilesetsLoaded); + context.setSuspendUpdate(true); + + Cesium3DTilesSelection::Tileset* pTileset = + context.tilesets[0]->GetTileset(); + if (TestNotNull("Tileset", pTileset)) { + int visibleTiles = 0; + pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { + if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) + return; + const Cesium3DTilesSelection::TileContent& content = + tile.getContent(); const Cesium3DTilesSelection::TileRenderContent* + pRenderContent = content.getRenderContent(); if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + ++visibleTiles; + } + }); + + TestEqual("visibleTiles", visibleTiles, 1); + } + */ }; return RunLoadTest(setupForMelbourne, after); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index dd8603357..d04834750 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -13,6 +13,8 @@ #include "CesiumSunSky.h" #include "GlobeAwareDefaultPawn.h" +#include "CesiumTestHelpers.h" + namespace Cesium { FString SceneGenerationContext::testIonToken( @@ -40,6 +42,53 @@ void SceneGenerationContext::setSuspendUpdate(bool suspend) { (*it)->SuspendUpdate = suspend; } +bool SceneGenerationContext::areTilesetsDoneLoading() { + if (tilesets.empty()) + return false; + + std::vector::const_iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + + int progress = (int)tileset->GetLoadProgress(); + if (progress != 100) { + // We aren't done + return false; + } + } + return true; +} + +void SceneGenerationContext::trackForPlay() { + CesiumTestHelpers::trackForPlay(georeference); + CesiumTestHelpers::trackForPlay(cameraManager); + CesiumTestHelpers::trackForPlay(pawn); + + std::vector::iterator it; + for (it = tilesets.begin(); it != tilesets.end(); ++it) { + ACesium3DTileset* tileset = *it; + CesiumTestHelpers::trackForPlay(tileset); + } +} + +void SceneGenerationContext::initForPlay( + SceneGenerationContext& creationContext) { + world = GEditor->PlayWorld; + georeference = CesiumTestHelpers::findInPlay(creationContext.georeference); + cameraManager = CesiumTestHelpers::findInPlay(creationContext.cameraManager); + pawn = CesiumTestHelpers::findInPlay(creationContext.pawn); + + tilesets.clear(); + + std::vector& creationTilesets = creationContext.tilesets; + std::vector::iterator it; + for (it = creationTilesets.begin(); it != creationTilesets.end(); ++it) { + ACesium3DTileset* creationTileset = *it; + ACesium3DTileset* tileset = CesiumTestHelpers::findInPlay(creationTileset); + tilesets.push_back(tileset); + } +} + void createCommonWorldObjects(SceneGenerationContext& context) { context.world = FAutomationEditorCommonUtils::CreateNewMap(); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 54a2fc4be..1bfcd1713 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -20,11 +20,14 @@ struct SceneGenerationContext { ACesiumCameraManager* cameraManager; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; - FRequestPlaySessionParams playSessionParams; void setCamera(const FCesiumCamera& camera); void refreshTilesets(); void setSuspendUpdate(bool suspend); + bool areTilesetsDoneLoading(); + + void trackForPlay(); + void initForPlay(SceneGenerationContext& creationContext); static FString testIonToken; }; From 2fff0b4c879b61684aabf3e6d3c8a6a022509ae0 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 5 Sep 2023 13:29:54 -0600 Subject: [PATCH 27/95] Let tests define separable passes for setup / verification --- .../Private/Tests/CesiumLoadTest.cpp | 148 +++++++++++------- .../Private/Tests/CesiumSceneGeneration.cpp | 2 +- .../Private/Tests/CesiumSceneGeneration.h | 2 +- 3 files changed, 90 insertions(+), 62 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 8ece64ead..29e4a7518 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -33,37 +33,45 @@ struct LoadTestContext { SceneGenerationContext creationContext; SceneGenerationContext playContext; - bool testStarted; + bool testInProgress; double startMark; double endMark; void reset() { creationContext = playContext = SceneGenerationContext(); - testStarted = false; + testInProgress = false; startMark = endMark = 0; } }; LoadTestContext gLoadTestContext; -DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( +DEFINE_LATENT_AUTOMATION_COMMAND_THREE_PARAMETER( TimeLoadingCommand, LoadTestContext&, - context); + context, + std::function, + setupStep, + std::function, + verifyStep); bool TimeLoadingCommand::Update() { - if (!context.testStarted) { + if (!context.testInProgress) { // Bind all play in editor pointers context.playContext.initForPlay(context.creationContext); + if (setupStep) + setupStep(context.playContext); + // Start test mark, turn updates back on context.startMark = FPlatformTime::Seconds(); UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); context.playContext.setSuspendUpdate(false); - context.testStarted = true; + context.testInProgress = true; + // Return, let world tick return false; } @@ -95,9 +103,14 @@ bool TimeLoadingCommand::Update() { testElapsedTime); } + if (verifyStep) + verifyStep(context.playContext); + // Turn on the editor tileset updates so we can see what we loaded gLoadTestContext.creationContext.setSuspendUpdate(false); + context.testInProgress = false; + // Command is done return true; } @@ -106,14 +119,20 @@ bool TimeLoadingCommand::Update() { return false; } +struct TestPass { + std::function setupStep; + std::function verifyStep; +}; + bool RunLoadTest( std::function locationSetup, - std::function afterTest = {}) { + const std::vector& testPasses) { + + gLoadTestContext.reset(); // // Programmatically set up the world // - gLoadTestContext.reset(); UE_LOG(LogCesium, Display, TEXT("Creating world objects...")); createCommonWorldObjects(gLoadTestContext.creationContext); @@ -132,76 +151,85 @@ bool RunLoadTest( // Start play in editor (don't sim in editor) ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(false)); - // Wait a bit - ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + std::vector::const_iterator it; + for (it = testPasses.begin(); it != testPasses.end(); ++it) { + const TestPass& pass = *it; - // Do our timing capture - ADD_LATENT_AUTOMATION_COMMAND(TimeLoadingCommand(gLoadTestContext)); + // Wait a bit + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + + // Do our timing capture + ADD_LATENT_AUTOMATION_COMMAND( + TimeLoadingCommand(gLoadTestContext, pass.setupStep, pass.verifyStep)); + } // End play in editor ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); - /* - if (afterTest) { - afterTest(context); - } - */ - return true; } bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { - return RunLoadTest(setupForDenver); + + std::vector testPasses; + testPasses.push_back(TestPass{nullptr, nullptr}); + + return RunLoadTest(setupForDenver, testPasses); } bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { - return RunLoadTest(setupForGoogleTiles); + + std::vector testPasses; + testPasses.push_back(TestPass{nullptr, nullptr}); + + return RunLoadTest(setupForGoogleTiles, testPasses); } bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { - auto after = [this](SceneGenerationContext& context) { - /* - // Zoom way out - FCesiumCamera zoomedOut; - zoomedOut.ViewportSize = FVector2D(1024, 768); - zoomedOut.Location = FVector(0, 0, 7240000.0); - zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); - zoomedOut.FieldOfViewDegrees = 90; - context.setCamera(zoomedOut); - - context.pawn->SetActorLocation(zoomedOut.Location); - - context.setSuspendUpdate(false); - tickWorldUntil(context, 10, breakWhenTilesetsLoaded); - context.setSuspendUpdate(true); - - Cesium3DTilesSelection::Tileset* pTileset = - context.tilesets[0]->GetTileset(); - if (TestNotNull("Tileset", pTileset)) { - int visibleTiles = 0; - pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { - if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) - return; - const Cesium3DTilesSelection::TileContent& content = - tile.getContent(); const Cesium3DTilesSelection::TileRenderContent* - pRenderContent = content.getRenderContent(); if (!pRenderContent) { - return; - } - - UCesiumGltfComponent* Gltf = static_cast( - pRenderContent->getRenderResources()); - if (Gltf && Gltf->IsVisible()) { - ++visibleTiles; - } - }); - - TestEqual("visibleTiles", visibleTiles, 1); - } - */ + auto adjustCamera = [this](SceneGenerationContext& context) { + // Zoom way out + FCesiumCamera zoomedOut; + zoomedOut.ViewportSize = FVector2D(1024, 768); + zoomedOut.Location = FVector(0, 0, 7240000.0); + zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); + zoomedOut.FieldOfViewDegrees = 90; + context.setCamera(zoomedOut); + + context.pawn->SetActorLocation(zoomedOut.Location); }; - return RunLoadTest(setupForMelbourne, after); + auto verifyVisibleTiles = [this](SceneGenerationContext& context) { + Cesium3DTilesSelection::Tileset* pTileset = + context.tilesets[0]->GetTileset(); + if (TestNotNull("Tileset", pTileset)) { + int visibleTiles = 0; + pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { + if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) + return; + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + ++visibleTiles; + } + }); + + TestEqual("visibleTiles", visibleTiles, 1); + } + }; + + std::vector testPasses; + testPasses.push_back(TestPass{nullptr, nullptr}); + testPasses.push_back(TestPass{adjustCamera, verifyVisibleTiles}); + + return RunLoadTest(setupForMontrealPointCloud, testPasses); } #endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index d04834750..c7ae15c20 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -187,7 +187,7 @@ void setupForDenver(SceneGenerationContext& context) { context.tilesets.push_back(aerometrexTileset); } -void setupForMelbourne(SceneGenerationContext& context) { +void setupForMontrealPointCloud(SceneGenerationContext& context) { FVector targetOrigin(-73.616526, 45.57335, 95.048859); FCesiumCamera camera; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 1bfcd1713..85ff0cd1b 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -36,7 +36,7 @@ void createCommonWorldObjects(SceneGenerationContext& context); void setupForDenver(SceneGenerationContext& context); void setupForGoogleTiles(SceneGenerationContext& context); -void setupForMelbourne(SceneGenerationContext& context); +void setupForMontrealPointCloud(SceneGenerationContext& context); }; // namespace Cesium From 9942babfdb73952d9953fbf1c943b788a927aa4e Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 5 Sep 2023 14:00:23 -0600 Subject: [PATCH 28/95] Remove extraneous include --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index c7ae15c20..0dba7458f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -2,8 +2,6 @@ #include "CesiumSceneGeneration.h" -#include "Tests/AutomationEditorCommon.h" - #include "GameFramework/PlayerStart.h" #include "Cesium3DTileset.h" From 7562b490eaf52cad0a009a5764f32b1cbb1c0c3b Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Tue, 5 Sep 2023 16:00:24 -0600 Subject: [PATCH 29/95] Add missing ifdef to fix non-Windows50 builds --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 0dba7458f..17fceb83e 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -2,6 +2,8 @@ #include "CesiumSceneGeneration.h" +#if WITH_EDITOR + #include "GameFramework/PlayerStart.h" #include "Cesium3DTileset.h" @@ -214,3 +216,5 @@ void setupForMontrealPointCloud(SceneGenerationContext& context) { } } // namespace Cesium + +#endif // #if WITH_EDITOR From 014ff800ac855f8fc242334f292e3cb8810b5caa Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 6 Sep 2023 09:54:21 -0600 Subject: [PATCH 30/95] Create performance-profiling.md --- Documentation/performance-profiling.md | 1 + 1 file changed, 1 insertion(+) create mode 100644 Documentation/performance-profiling.md diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling.md new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Documentation/performance-profiling.md @@ -0,0 +1 @@ + From 0cc5214eb0225dce1295fb98760569afadd94f1c Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 6 Sep 2023 10:40:48 -0600 Subject: [PATCH 31/95] Update performance-profiling.md Add outline and setup sections --- Documentation/performance-profiling.md | 43 ++++++++++++++++++++++++++ 1 file changed, 43 insertions(+) diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling.md index 8b1378917..426590155 100644 --- a/Documentation/performance-profiling.md +++ b/Documentation/performance-profiling.md @@ -1 +1,44 @@ +Is your app running slowly? Here is a guide to help find performance problems in your code. + +This guide profiles C++ code, running on Windows, using the Visual Studio CPU usage diagonostic tool ([link](https://learn.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling?view=vs-2022)). + +## Set up a repeatable test + +We need an area of code to execute repeatedly, with as many variables locked down as possible. + +In this example, we will use our Cesium performance tests. + +#### Setup Unreal +1) Open Unreal Editor (UnrealEditor.exe) +2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) +3) Go to Edit->Plugins +4) Search for "Functional Testing plugin". Check it to enable it +![smaller](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a3bc9de-cdaf-4d9d-842d-104719426663) +5) Save all +6) Set this map as the 'Editor Startup Map' so it loads when starting from Visual Studio +![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) + + +#### Setup your code + +We need to make sure all our C++ code is building in release mode. Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. + +> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). + +1) If building the cesium-native library, make sure you are using a Release build +2) Open your project's Visual Studio solution (.sln). In this example we will use the solution generated from https://github.com/CesiumGS/cesium-unreal-samples +3) Choose "Development Editor" + +![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) + +4) From the menu, choose Build -> Build Solution + + +## Capture timing data + +TODO + +## Interpret the report + +TODO From 6589f08a0f63b494ea436a490731c902176b0486 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 6 Sep 2023 11:21:26 -0600 Subject: [PATCH 32/95] Update performance-profiling.md Add timing capture section --- Documentation/performance-profiling.md | 42 +++++++++++++++++++++----- 1 file changed, 35 insertions(+), 7 deletions(-) diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling.md index 426590155..941e1c05d 100644 --- a/Documentation/performance-profiling.md +++ b/Documentation/performance-profiling.md @@ -20,14 +20,14 @@ In this example, we will use our Cesium performance tests. ![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) -#### Setup your code +#### Build Release Code -We need to make sure all our C++ code is building in release mode. Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. +We need to make sure all our C++ code is building in release mode. -> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). +> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. -1) If building the cesium-native library, make sure you are using a Release build -2) Open your project's Visual Studio solution (.sln). In this example we will use the solution generated from https://github.com/CesiumGS/cesium-unreal-samples +1) If building the cesium-native library, make sure you are using a Release configuration +2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from https://github.com/CesiumGS/cesium-unreal-samples 3) Choose "Development Editor" ![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) @@ -35,10 +35,38 @@ We need to make sure all our C++ code is building in release mode. Although you 4) From the menu, choose Build -> Build Solution -## Capture timing data +## Setup Visual Studio for capture -TODO +1) Open your project's Visual Studio solution (.sln). This example uses the solution generated from https://github.com/CesiumGS/cesium-unreal-samples +2) From the menu, choose Debug->Windows->Show Diagnostic Tools +3) Configure it. Uncheck 'Memory Usage'. Under Settings, Uncheck "Enable CPU Profiling", we'll turn this back on later. + +DiagSetup + +4) Optionally, find two places in your code to set breakpoints. In our example, performance tests already log at their timing marks. Let's set a breakpoint at the start and end. + +![Breakpoint Set small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a793b9c-fd68-42ed-96ae-6ec884c38951) + +> We don't have to do this. We could profile the entire debugging session if we needed to. But it's generally good practice to reduce your timing capture as much as possible. This can improve responsiveness when using profiling tools, especially when dealing with intensive operations like memory heap tracking. + +## Run the timing capture session + +1) Start your debugging session (Debug->Start Debugging, F5) +2) Find the performance tests in Unreal. Tools->Test Automation +![Automation Window small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/d27e7d67-3658-4cb2-ab10-777498cba0da) + +3) Check "LoadTestDenver" +4) Click "Start Tests" +5) Your first break point should hit in Visual Studio +6) Go back to the Diagnostic Tools window, click on "Record CPU Profile". It should turn red +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/ce0c7e86-c1ef-4a01-97fd-c97275b6f62b) + +7) Continue the debugging session (Debug->Continue, F5) +8) Your second break point should hit +9) Go back to the Diagnostic Tools window, you should now see a report ## Interpret the report +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/b83c63e0-06c4-47ff-afab-17a9923fa646) + TODO From d16df299b0f1aea9d4f623aee59c26d1b8ac16b7 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 6 Sep 2023 13:57:42 -0600 Subject: [PATCH 33/95] Add more to interpretation section --- Documentation/performance-profiling.md | 28 +++++++++++++++++++------- 1 file changed, 21 insertions(+), 7 deletions(-) diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling.md index 941e1c05d..f498bb56d 100644 --- a/Documentation/performance-profiling.md +++ b/Documentation/performance-profiling.md @@ -1,7 +1,12 @@ -Is your app running slowly? Here is a guide to help find performance problems in your code. +Want to find out how to make your Unreal app using Cesium run faster? + +This guide will help you find performance problems in your C++ code using the CPU Usage tool included in Visual Studio's Diagonostic tools window. +[link](https://learn.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling?view=vs-2022) + +The CPU Usage tool is easy to set up with minimal effect on how your app is built or how it runs. If you use Visual Studio often, you may even have this running already. This is a sampling-based profiler, with pros and cons detailed [here](https://learn.microsoft.com/en-us/visualstudio/profiling/understanding-performance-collection-methods-perf-profiler?view=vs-2022) + -This guide profiles C++ code, running on Windows, using the Visual Studio CPU usage diagonostic tool ([link](https://learn.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling?view=vs-2022)). ## Set up a repeatable test @@ -27,7 +32,7 @@ We need to make sure all our C++ code is building in release mode. > This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. 1) If building the cesium-native library, make sure you are using a Release configuration -2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from https://github.com/CesiumGS/cesium-unreal-samples +2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) 3) Choose "Development Editor" ![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) @@ -37,7 +42,7 @@ We need to make sure all our C++ code is building in release mode. ## Setup Visual Studio for capture -1) Open your project's Visual Studio solution (.sln). This example uses the solution generated from https://github.com/CesiumGS/cesium-unreal-samples +1) Open your project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) 2) From the menu, choose Debug->Windows->Show Diagnostic Tools 3) Configure it. Uncheck 'Memory Usage'. Under Settings, Uncheck "Enable CPU Profiling", we'll turn this back on later. @@ -47,7 +52,7 @@ We need to make sure all our C++ code is building in release mode. ![Breakpoint Set small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a793b9c-fd68-42ed-96ae-6ec884c38951) -> We don't have to do this. We could profile the entire debugging session if we needed to. But it's generally good practice to reduce your timing capture as much as possible. This can improve responsiveness when using profiling tools, especially when dealing with intensive operations like memory heap tracking. +>We could profile the entire debugging session if we needed to. But it's generally good practice to reduce your timing capture as much as possible. This can improve responsiveness when using resource intensive profiling tools, like memory heap tracking. ## Run the timing capture session @@ -67,6 +72,15 @@ We need to make sure all our C++ code is building in release mode. ## Interpret the report -![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/b83c63e0-06c4-47ff-afab-17a9923fa646) +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/afe09c83-6904-48ea-8002-3d7237b8d188) + +This can be a bit daunting at first, but most profiling tools have a similar workflow. + + +#### Start at the timeline +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/c97fd664-7951-46cb-bb60-20e8eaa35e88) + +Note the highlighted area to the right where the CPU usage spikes. This corresponds to the breakpoints that we set. All data from the report will reflect this selection only + + -TODO From 8479aa1af44f0634a21285ce24cbc04c8f84b986 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 6 Sep 2023 16:45:33 -0600 Subject: [PATCH 34/95] Finish up conclusions section. Misc revisions --- Documentation/performance-profiling.md | 63 ++++++++++++++++++-------- 1 file changed, 44 insertions(+), 19 deletions(-) diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling.md index f498bb56d..ea54e9d73 100644 --- a/Documentation/performance-profiling.md +++ b/Documentation/performance-profiling.md @@ -1,20 +1,17 @@ -Want to find out how to make your Unreal app using Cesium run faster? +This guide will help you find performance problems in your C++ code using the [CPU Usage tool](https://learn.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling?view=vs-2022) included in Visual Studio's Diagnostic tools window. -This guide will help you find performance problems in your C++ code using the CPU Usage tool included in Visual Studio's Diagonostic tools window. -[link](https://learn.microsoft.com/en-us/visualstudio/profiling/beginners-guide-to-performance-profiling?view=vs-2022) +The CPU Usage tool is easy to set up with minimal impact on how your app is built or how it runs. If you use Visual Studio often, you may have this running already. This is a sampling-based profiler, with pros and cons detailed [here](https://learn.microsoft.com/en-us/visualstudio/profiling/understanding-performance-collection-methods-perf-profiler?view=vs-2022). -The CPU Usage tool is easy to set up with minimal effect on how your app is built or how it runs. If you use Visual Studio often, you may even have this running already. This is a sampling-based profiler, with pros and cons detailed [here](https://learn.microsoft.com/en-us/visualstudio/profiling/understanding-performance-collection-methods-perf-profiler?view=vs-2022) - -## Set up a repeatable test +# Set up a repeatable test We need an area of code to execute repeatedly, with as many variables locked down as possible. In this example, we will use our Cesium performance tests. -#### Setup Unreal +### Set up Unreal 1) Open Unreal Editor (UnrealEditor.exe) 2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) 3) Go to Edit->Plugins @@ -25,7 +22,7 @@ In this example, we will use our Cesium performance tests. ![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) -#### Build Release Code +### Build Release Code We need to make sure all our C++ code is building in release mode. @@ -40,7 +37,7 @@ We need to make sure all our C++ code is building in release mode. 4) From the menu, choose Build -> Build Solution -## Setup Visual Studio for capture +# Setup Visual Studio for capture 1) Open your project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) 2) From the menu, choose Debug->Windows->Show Diagnostic Tools @@ -48,39 +45,67 @@ We need to make sure all our C++ code is building in release mode. DiagSetup -4) Optionally, find two places in your code to set breakpoints. In our example, performance tests already log at their timing marks. Let's set a breakpoint at the start and end. +4) Optionally, find two places in your code to set breakpoints. In our example, performance test start / end marks are perfect. ![Breakpoint Set small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a793b9c-fd68-42ed-96ae-6ec884c38951) ->We could profile the entire debugging session if we needed to. But it's generally good practice to reduce your timing capture as much as possible. This can improve responsiveness when using resource intensive profiling tools, like memory heap tracking. +>We could profile the entire debugging session if we needed to. But it's generally good practice to reduce your timing capture as much as possible. This can improve responsiveness when using resource intensive profiling tools, like memory tracking. -## Run the timing capture session +# Run the timing capture session -1) Start your debugging session (Debug->Start Debugging, F5) +1) From Visual Studio, start your debugging session (Debug->Start Debugging, F5) 2) Find the performance tests in Unreal. Tools->Test Automation ![Automation Window small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/d27e7d67-3658-4cb2-ab10-777498cba0da) 3) Check "LoadTestDenver" 4) Click "Start Tests" 5) Your first break point should hit in Visual Studio -6) Go back to the Diagnostic Tools window, click on "Record CPU Profile". It should turn red +6) Go back to the Diagnostic Tools window, click on "Record CPU Profile". It should turn red. + ![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/ce0c7e86-c1ef-4a01-97fd-c97275b6f62b) 7) Continue the debugging session (Debug->Continue, F5) 8) Your second break point should hit 9) Go back to the Diagnostic Tools window, you should now see a report -## Interpret the report +# Interpret the report -![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/afe09c83-6904-48ea-8002-3d7237b8d188) +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/a9fb3e0b-86f5-4239-b4ab-c7f9b1dba4a5) This can be a bit daunting at first, but most profiling tools have a similar workflow. +### Start at the timeline + +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/da733adc-6cae-4c89-8a6c-01a367667a0d) + +Note the highlighted area to the right where the CPU usage spikes. This corresponds to the breakpoints that we set. + +All data from the report will reflect this selection only. + +### Trace calls with high usage + +From the main window, click on "Open Details" +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/f34b5ee3-15b7-485a-a90a-8f71310b1b44) + +The CPU Usage window will appear. Set "Current View" to "Functions", then find the 'Self CPU' column and sort descending (down arrow). + +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/20836178-8337-4d53-be58-f388db905f9f) + +This window now shows the functions that have the highest time spent within themselves only. Useful for finding individual functions that are called often or need to be optimized. + +In this example, `stbir_resample_horizontal_downsample` is of particular interest because it's in the code base we built. Entries with `[External]` or originate from an unfamiliar module are generally ignored, although it is useful to know we are calling into them. + +Right click on the `stbir_resample_horizontal_downsample` row, select "View in Call Tree". -#### Start at the timeline -![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/c97fd664-7951-46cb-bb60-20e8eaa35e88) +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/e5a88c06-5b76-4a07-83be-db5147a961b2) -Note the highlighted area to the right where the CPU usage spikes. This corresponds to the breakpoints that we set. All data from the report will reflect this selection only +# Draw conclusions +The window above is starting to show some actionable information: +- 20% of the sampled CPU time was spent in `CesiumTextureUtility::loadTextureAnyThreadPart`. Basically, we're loading textures +- There are a variety of `stbir_XXX functions` that are taking the bulk of the time, and might be candidates for optimization +- The highest cost single function is `stbir_resample_horizontal_downsample`, but keep in mind the limits of a sampling profiler. We don't know how many times it was called, just that it was being executed ~6% of the time. +Are these functions worth investigating and potentially optimizing? Maybe. Again, know this is a sampling profiler. Even if you optimize the highest cost function to 0.001%, you are only improving CPU efficiency. +If your goal is to reach absolute numbers, like specific loading times, or frames per second, you may need another type of profiling tool. From 89d808140616e2894549ac8483fc27580fdf274a Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:33:50 -0600 Subject: [PATCH 35/95] Rename performance-profiling.md to performance-profiling-with-cpu-usage.md --- ...mance-profiling.md => performance-profiling-with-cpu-usage.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/{performance-profiling.md => performance-profiling-with-cpu-usage.md} (100%) diff --git a/Documentation/performance-profiling.md b/Documentation/performance-profiling-with-cpu-usage.md similarity index 100% rename from Documentation/performance-profiling.md rename to Documentation/performance-profiling-with-cpu-usage.md From 9b8292b6ff82f7c469845f9cb3fadc9474f14fdb Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:34:50 -0600 Subject: [PATCH 36/95] Create performance-profiling-with-unreal-insights --- Documentation/performance-profiling-with-unreal-insights | 1 + 1 file changed, 1 insertion(+) create mode 100644 Documentation/performance-profiling-with-unreal-insights diff --git a/Documentation/performance-profiling-with-unreal-insights b/Documentation/performance-profiling-with-unreal-insights new file mode 100644 index 000000000..8b1378917 --- /dev/null +++ b/Documentation/performance-profiling-with-unreal-insights @@ -0,0 +1 @@ + From 1db33097920231ea5a4d618af3aed39e584c0a34 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:37:36 -0600 Subject: [PATCH 37/95] Rename performance-profiling-with-unreal-insights to performance-profiling-with-unreal-insights.md --- ...eal-insights => performance-profiling-with-unreal-insights.md} | 0 1 file changed, 0 insertions(+), 0 deletions(-) rename Documentation/{performance-profiling-with-unreal-insights => performance-profiling-with-unreal-insights.md} (100%) diff --git a/Documentation/performance-profiling-with-unreal-insights b/Documentation/performance-profiling-with-unreal-insights.md similarity index 100% rename from Documentation/performance-profiling-with-unreal-insights rename to Documentation/performance-profiling-with-unreal-insights.md From 9fa60191c535f6b46c9c8880f941e517f0e65fbd Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Thu, 7 Sep 2023 15:56:17 -0600 Subject: [PATCH 38/95] Stub out major sections --- ...formance-profiling-with-unreal-insights.md | 59 +++++++++++++++++++ 1 file changed, 59 insertions(+) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index 8b1378917..24c5d89d7 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -1 +1,60 @@ +This guide will help you find performance problems in your C++ code using [Unreal Insights](https://docs.unrealengine.com/5.0/en-US/unreal-insights-in-unreal-engine/), included with Unreal Engine. +Unreal Insights can display the scope of timing events as well as activity across threads. There is minimal impact to app execution, and you can set up your own custom events. It provides more functionality than an exclusive [CPU sampling-based profiler](https://learn.microsoft.com/en-us/visualstudio/profiling/understanding-performance-collection-methods-perf-profiler?view=vs-2022), although both tools can complement each other. + +# Set up a repeatable test + +We need an area of code to execute repeatedly, with as many variables locked down as possible. + +In this example, we will use our Cesium performance tests. + +### Set up Unreal +1) Open Unreal Editor (UnrealEditor.exe) +2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) +3) Go to Edit->Plugins +4) Search for "Functional Testing plugin". Check it to enable it +![smaller](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a3bc9de-cdaf-4d9d-842d-104719426663) +5) Save all +6) Set this map as the 'Editor Startup Map' so it loads when starting from Visual Studio +![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) + + +### Build Release Code + +We need to make sure all our C++ code is building in release mode. + +> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. + +1) If building the cesium-native library, make sure you are using a Release configuration +2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) +3) Choose "Development Editor" + +![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) + +4) From the menu, choose Build -> Build Solution + + +# Setup Unreal Editor + Unreal Insights for capture + +TODO + +# Run the timing capture session + +TODO + + +# Interpret the report + +TODO + +### Start at the timeline + +TODO + +### Examine low use areas + +TODO + +# Draw conclusions + +TODO From 6a8a2ba170e746039d94889ab303211f603d57b5 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Thu, 7 Sep 2023 16:09:41 -0600 Subject: [PATCH 39/95] Flesh out prepare for capture section --- ...formance-profiling-with-unreal-insights.md | 20 ++++++++++++++++--- 1 file changed, 17 insertions(+), 3 deletions(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index 24c5d89d7..31adbbbf3 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -33,15 +33,29 @@ We need to make sure all our C++ code is building in release mode. 4) From the menu, choose Build -> Build Solution +# Prepare for capture -# Setup Unreal Editor + Unreal Insights for capture +### Unreal Editor +1) Start debugging from VS +2) In Unreal, click Tools->Test Automation +3) Check the Cesium.Performance.LoadTestDenver row (don't start the test yet) +4) Click Tools->Run Unreal Insights +> You can also find UnrealInsights.exe in UE_5.X\Engine\Binaries\Win64 -TODO +### Unreal Insights +1) From the session browser, click Connection tab +2) Click Connect +3) Go back to the Trace Store tab, notice your live session # Run the timing capture session -TODO +1) In Unreal, click Tools->Test Automation +2) Click Start (you should already have the test selected) +3) When the test ends, close UnrealEditor +4) In Unreal Insights, select the trace that was just created +5) Click on Open Trace +> Trace files are saved in C:/Users/your username/AppData/Local/UnrealEngine/Common/UnrealTrace/Store/001 # Interpret the report From 4fc27ac3bdc021a48ae0428459faf2479eef5239 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 13:28:29 -0600 Subject: [PATCH 40/95] Flesh out timing capture sections (add pics) --- ...formance-profiling-with-unreal-insights.md | 25 +++++++++++-------- 1 file changed, 14 insertions(+), 11 deletions(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index 31adbbbf3..9c4cad84f 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -36,29 +36,32 @@ We need to make sure all our C++ code is building in release mode. # Prepare for capture ### Unreal Editor -1) Start debugging from VS +1) In Visual Studio, click Debug -> Start Debugging (F5) 2) In Unreal, click Tools->Test Automation 3) Check the Cesium.Performance.LoadTestDenver row (don't start the test yet) +![Automation Window small](https://github.com/CesiumGS/cesium-unreal/assets/130494071/d27e7d67-3658-4cb2-ab10-777498cba0da) 4) Click Tools->Run Unreal Insights +5) In Unreal Insights, click on the "Connection" tab (don't connect yet) + > You can also find UnrealInsights.exe in UE_5.X\Engine\Binaries\Win64 -### Unreal Insights -1) From the session browser, click Connection tab -2) Click Connect -3) Go back to the Trace Store tab, notice your live session +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/eadd4013-ca10-4b61-bb7d-0ab233440a39) # Run the timing capture session +1) In Unreal Insights, click "Connect" +2) In Unreal Editor, click "Start Tests" (you should already have the Test Automation window open) +3) When the test ends, close Unreal Editor. We don't need it anymore. +4) In Unreal Insights, click the Trace Store tab, notice the trace that was just created +5) Click on it, then click on the 'Open Trace' button -1) In Unreal, click Tools->Test Automation -2) Click Start (you should already have the test selected) -3) When the test ends, close UnrealEditor -4) In Unreal Insights, select the trace that was just created -5) Click on Open Trace +> On the right side, there's a "Explore Trace Store Directory" button. You can click on this to delete or organize your traces -> Trace files are saved in C:/Users/your username/AppData/Local/UnrealEngine/Common/UnrealTrace/Store/001 +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/f1e34fbc-35cd-4bc3-b935-5e322f5d9ba6) # Interpret the report +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/9cab7cf1-ab6d-4b58-a362-fc21ccff0334) + TODO ### Start at the timeline From 637504eff7db055593f5d8626fd3a1ebf2be277d Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 14:42:50 -0600 Subject: [PATCH 41/95] Add first part of Interpret section --- ...formance-profiling-with-unreal-insights.md | 37 +++++++++++++++++-- 1 file changed, 34 insertions(+), 3 deletions(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index 9c4cad84f..5f444d58d 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -62,11 +62,42 @@ We need to make sure all our C++ code is building in release mode. ![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/9cab7cf1-ab6d-4b58-a362-fc21ccff0334) -TODO +By default, the Timings Insights Tab is shown. More detail can be found [here](https://docs.unrealengine.com/5.0/en-US/timing-insights-in-unreal-engine-5/). -### Start at the timeline +For this session, there are several sections of interest for us: +- The Frames panel (top, a timeline view) +- The Timings panel (middle, mostly empty because nothing is selected) +- The Log Panel (bottom) +- The Timers tab (right) + +### Isolate your area of interest + +1) In the Log Panel, search for "mark". This will show the logging of our timing marks for our test. Select the start mark, then hold shift and down arrow to select the end mark too +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/7cccc075-edf7-4b8e-b704-b9efc9de1a3c) + +2) Notice that the Timings panel is now displaying timing data, with a specific time region highlighted +3) In the Timings panel, select View Mode -> Compact Mode to see more of a bird's eye view +4) Select All Tracks and uncheck the following threads that don't have much activity for our test: ```RenderThread 3-7, BackgroundThreadPool #1, ForegroundWorker #0-#1, DDC IO ThreadPool #0-#2, Reserve Worker #0-#13, AudioMixerXXX``` +5) Use the mouse wheel to zoom in to selected region. Right click and drag to pan left and right. + +The view should be a lot cleaner now +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/aca0680e-3dc3-4d23-9838-8f598f384089) + + +### Examine high traffic timers + +Let's look at the Timers tab. + +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/823fc4d4-25d3-40dc-9b41-1cffee560454) + +Every row is a timing event. Some events come from the engine, some are custom timers in the Cesium for Unreal plugin code. You'll notice that Incl is sorting descending, showing the events with the highest inclusive time. + +You may feel the need to jump right in to `Cesium::CreateRHITexture2D`. It seems to have one of the highest exclusive times (Excl) of any of the events in the list, 1 second. After all, our selection is only 1.2 seconds long, so this must be the performance bottleneck right? Hold on. The total sampled time at the top (CPU) is 19.8s, indicating we are sampling across threads. + +Given that the highest sampled calls are actually somewhat small compared to the total sampled CPU time, our bottleneck is most likely outside of our timed events. + +This brings us to... -TODO ### Examine low use areas From 1079c0c98c3d245e8f014b0c23af939b40ea5048 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:00:02 -0600 Subject: [PATCH 42/95] Flesh out Examine low use areas section --- ...erformance-profiling-with-unreal-insights.md | 17 ++++++++++++++++- 1 file changed, 16 insertions(+), 1 deletion(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index 5f444d58d..a61a0c4ac 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -94,13 +94,28 @@ Every row is a timing event. Some events come from the engine, some are custom t You may feel the need to jump right in to `Cesium::CreateRHITexture2D`. It seems to have one of the highest exclusive times (Excl) of any of the events in the list, 1 second. After all, our selection is only 1.2 seconds long, so this must be the performance bottleneck right? Hold on. The total sampled time at the top (CPU) is 19.8s, indicating we are sampling across threads. -Given that the highest sampled calls are actually somewhat small compared to the total sampled CPU time, our bottleneck is most likely outside of our timed events. +Given that the sampled time of the highest cost calls are actually somewhat small compared to the total sampled CPU time, our bottleneck is most likely outside of our timed events. This brings us to... ### Examine low use areas +1) Go back to the Timings panel. +2) In All Tracks, check Game Frames +2) Turn off compact mode by unchecking "View Mode->Compact Mode". +3) In View Mode, set "Depth Limit" to "4 lanes" +4) Zoom and pan to an area of the selection where the background workers haven't started loading yet + +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/caa47e66-b088-46d8-9aa0-1916a65777de) + +The selected area is the first phase of the loading test. This is a region between when the start mark was logged until when background workers start loading models. + +It lasts about 8 game frames, or 388 ms, and does not seem to be making use of background threads at all. Could be something to investigate. + + +### Examine fragmented use areas + TODO # Draw conclusions From e544bb33e96e1b032093ec35fd788d6bb4618134 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:46:45 -0600 Subject: [PATCH 43/95] Finish the last sections --- ...rformance-profiling-with-unreal-insights.md | 18 +++++++++++++++--- 1 file changed, 15 insertions(+), 3 deletions(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index a61a0c4ac..fff003457 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -92,7 +92,7 @@ Let's look at the Timers tab. Every row is a timing event. Some events come from the engine, some are custom timers in the Cesium for Unreal plugin code. You'll notice that Incl is sorting descending, showing the events with the highest inclusive time. -You may feel the need to jump right in to `Cesium::CreateRHITexture2D`. It seems to have one of the highest exclusive times (Excl) of any of the events in the list, 1 second. After all, our selection is only 1.2 seconds long, so this must be the performance bottleneck right? Hold on. The total sampled time at the top (CPU) is 19.8s, indicating we are sampling across threads. +> You may feel the need to jump right in to `Cesium::CreateRHITexture2D`. It seems to have one of the highest exclusive times (Excl) of any of the events in the list, 1 second. After all, our selection is only 1.2 seconds long, so this must be the performance bottleneck right? Hold on. The total sampled time at the top (CPU) is 19.8s, indicating the times are the total sampled times across threads, not absolute session duration. Given that the sampled time of the highest cost calls are actually somewhat small compared to the total sampled CPU time, our bottleneck is most likely outside of our timed events. @@ -116,8 +116,20 @@ It lasts about 8 game frames, or 388 ms, and does not seem to be making use of b ### Examine fragmented use areas -TODO +1) Find the Timings panel +2) In View Mode, set "Depth Limit" to "Unlimited" +3) Zoom a bit into an area where our background workers are very busy + +![image](https://github.com/CesiumGS/cesium-unreal/assets/130494071/29d7c3a2-3710-4a2b-a4f1-09050bdb9287) + +This selected area is zoomed in enough to see that the background workers are all calling the same functions. They finish their work, then wait for more work to be available. Some of this work seems to take longer than others, especially at the beginning. + +Note the gaps between the work. In general, there seems to be more inactivity than activity during this timeframe. Ideally, we would like to see all work squished together, with no waits in between. Improvements like this should bring the total execution duration lower. In this case, total load time. # Draw conclusions -TODO +We've identified some actionable information so far, even if it only leads to investigation: +* There is a 388 ms low use area at the beginning of the test (~30%). What is happening here? Can it be faster? +* During high use areas, background threads seems to inactive more than they are active. Why? Can this be optimized so they are always active? + +It's very common for profiling to be an iterative process. The result of a profiling session could easily be just adding more event timers, or digging deeper into how something works. Before we can expect that code change that results in a heroic 10x speedup, we need to be able to see clearly what is going on. From 5586afa7275cea4df777387aa8656dcce18c5dbe Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:49:25 -0600 Subject: [PATCH 44/95] Create performance-profiling-setup-test.md --- .../performance-profiling-setup-test.md | 30 +++++++++++++++++++ 1 file changed, 30 insertions(+) create mode 100644 Documentation/performance-profiling-setup-test.md diff --git a/Documentation/performance-profiling-setup-test.md b/Documentation/performance-profiling-setup-test.md new file mode 100644 index 000000000..2a9b3e9c4 --- /dev/null +++ b/Documentation/performance-profiling-setup-test.md @@ -0,0 +1,30 @@ +# Set up a repeatable test + +We need an area of code to execute repeatedly, with as many variables locked down as possible. + +In this example, we will use our Cesium performance tests. + +### Set up Unreal +1) Open Unreal Editor (UnrealEditor.exe) +2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) +3) Go to Edit->Plugins +4) Search for "Functional Testing plugin". Check it to enable it +![smaller](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a3bc9de-cdaf-4d9d-842d-104719426663) +5) Save all +6) Set this map as the 'Editor Startup Map' so it loads when starting from Visual Studio +![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) + + +### Build Release Code + +We need to make sure all our C++ code is building in release mode. + +> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. + +1) If building the cesium-native library, make sure you are using a Release configuration +2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) +3) Choose "Development Editor" + +![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) + +4) From the menu, choose Build -> Build Solution From 1240f52a40f8733479fa2554cb3670a35c497700 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:51:33 -0600 Subject: [PATCH 45/95] Link to separate setup page --- ...formance-profiling-with-unreal-insights.md | 29 +------------------ 1 file changed, 1 insertion(+), 28 deletions(-) diff --git a/Documentation/performance-profiling-with-unreal-insights.md b/Documentation/performance-profiling-with-unreal-insights.md index fff003457..4a4e947f9 100644 --- a/Documentation/performance-profiling-with-unreal-insights.md +++ b/Documentation/performance-profiling-with-unreal-insights.md @@ -4,34 +4,7 @@ Unreal Insights can display the scope of timing events as well as activity acros # Set up a repeatable test -We need an area of code to execute repeatedly, with as many variables locked down as possible. - -In this example, we will use our Cesium performance tests. - -### Set up Unreal -1) Open Unreal Editor (UnrealEditor.exe) -2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) -3) Go to Edit->Plugins -4) Search for "Functional Testing plugin". Check it to enable it -![smaller](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a3bc9de-cdaf-4d9d-842d-104719426663) -5) Save all -6) Set this map as the 'Editor Startup Map' so it loads when starting from Visual Studio -![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) - - -### Build Release Code - -We need to make sure all our C++ code is building in release mode. - -> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. - -1) If building the cesium-native library, make sure you are using a Release configuration -2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) -3) Choose "Development Editor" - -![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) - -4) From the menu, choose Build -> Build Solution +In this example, we will use our Cesium performance tests. Follow the steps outlined [here](https://github.com/CesiumGS/cesium-unreal/blob/profiling-documentation/Documentation/performance-profiling-setup-test.md). # Prepare for capture From 46b8fcca820391698a24cbd79277d60ac67ed8cf Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:53:48 -0600 Subject: [PATCH 46/95] Link to separate setup page --- .../performance-profiling-with-cpu-usage.md | 34 ++----------------- 1 file changed, 3 insertions(+), 31 deletions(-) diff --git a/Documentation/performance-profiling-with-cpu-usage.md b/Documentation/performance-profiling-with-cpu-usage.md index ea54e9d73..b68844728 100644 --- a/Documentation/performance-profiling-with-cpu-usage.md +++ b/Documentation/performance-profiling-with-cpu-usage.md @@ -3,41 +3,13 @@ This guide will help you find performance problems in your C++ code using the [C The CPU Usage tool is easy to set up with minimal impact on how your app is built or how it runs. If you use Visual Studio often, you may have this running already. This is a sampling-based profiler, with pros and cons detailed [here](https://learn.microsoft.com/en-us/visualstudio/profiling/understanding-performance-collection-methods-perf-profiler?view=vs-2022). - - # Set up a repeatable test -We need an area of code to execute repeatedly, with as many variables locked down as possible. - -In this example, we will use our Cesium performance tests. - -### Set up Unreal -1) Open Unreal Editor (UnrealEditor.exe) -2) Create a blank map (project doesn't matter. Choose an existing one or create a new one) -3) Go to Edit->Plugins -4) Search for "Functional Testing plugin". Check it to enable it -![smaller](https://github.com/CesiumGS/cesium-unreal/assets/130494071/5a3bc9de-cdaf-4d9d-842d-104719426663) -5) Save all -6) Set this map as the 'Editor Startup Map' so it loads when starting from Visual Studio -![smaller 2](https://github.com/CesiumGS/cesium-unreal/assets/130494071/8ba5c6c2-8c97-4048-afe2-db74770d85cc) - - -### Build Release Code - -We need to make sure all our C++ code is building in release mode. - -> This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. - -1) If building the cesium-native library, make sure you are using a Release configuration -2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) -3) Choose "Development Editor" - -![smaller 3](https://github.com/CesiumGS/cesium-unreal/assets/130494071/0e70065f-c717-466b-a92b-cab1dcfdd29b) - -4) From the menu, choose Build -> Build Solution +In this example, we will use our Cesium performance tests. Follow the steps outlined [here](https://github.com/CesiumGS/cesium-unreal/blob/profiling-documentation/Documentation/performance-profiling-setup-test.md). +# Prepare for capture -# Setup Visual Studio for capture +### Visual Studio 1) Open your project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) 2) From the menu, choose Debug->Windows->Show Diagnostic Tools From 264fbe638b82e86ddd2349ec9e26073b995663c8 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 8 Sep 2023 15:55:06 -0600 Subject: [PATCH 47/95] Remove duplicate wording --- Documentation/performance-profiling-setup-test.md | 1 - 1 file changed, 1 deletion(-) diff --git a/Documentation/performance-profiling-setup-test.md b/Documentation/performance-profiling-setup-test.md index 2a9b3e9c4..544e552af 100644 --- a/Documentation/performance-profiling-setup-test.md +++ b/Documentation/performance-profiling-setup-test.md @@ -2,7 +2,6 @@ We need an area of code to execute repeatedly, with as many variables locked down as possible. -In this example, we will use our Cesium performance tests. ### Set up Unreal 1) Open Unreal Editor (UnrealEditor.exe) From d92e84f8c0d6ede88dbd5098b944c26329a7ae7b Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:07:02 -0600 Subject: [PATCH 48/95] Fix non-unity build (broke this again, oops) --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 17fceb83e..71af4ace9 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -4,6 +4,8 @@ #if WITH_EDITOR +#include "Tests/AutomationEditorCommon.h" + #include "GameFramework/PlayerStart.h" #include "Cesium3DTileset.h" From 61feff1d68c03f161800f193d4f0fde2b7962e36 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 11 Sep 2023 11:17:44 -0600 Subject: [PATCH 49/95] Add cold / warm cache tests + test names to logging marks --- .../Private/Tests/CesiumLoadTest.cpp | 43 +++++++++++++------ 1 file changed, 31 insertions(+), 12 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 29e4a7518..4bf36d687 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -46,8 +46,10 @@ struct LoadTestContext { LoadTestContext gLoadTestContext; -DEFINE_LATENT_AUTOMATION_COMMAND_THREE_PARAMETER( +DEFINE_LATENT_AUTOMATION_COMMAND_FOUR_PARAMETER( TimeLoadingCommand, + FString, + loggingName, LoadTestContext&, context, std::function, @@ -66,7 +68,7 @@ bool TimeLoadingCommand::Update() { // Start test mark, turn updates back on context.startMark = FPlatformTime::Seconds(); - UE_LOG(LogCesium, Display, TEXT("-- Load start mark --")); + UE_LOG(LogCesium, Display, TEXT("-- Load start mark -- %s"), *loggingName); context.playContext.setSuspendUpdate(false); @@ -87,7 +89,7 @@ bool TimeLoadingCommand::Update() { if (tilesetsloaded || timedOut) { context.endMark = timeMark; - UE_LOG(LogCesium, Display, TEXT("-- Load end mark --")); + UE_LOG(LogCesium, Display, TEXT("-- Load end mark -- %s"), *loggingName); if (timedOut) { UE_LOG( @@ -120,11 +122,13 @@ bool TimeLoadingCommand::Update() { } struct TestPass { + FString name; std::function setupStep; std::function verifyStep; }; bool RunLoadTest( + const FString& testName, std::function locationSetup, const std::vector& testPasses) { @@ -159,8 +163,13 @@ bool RunLoadTest( ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); // Do our timing capture - ADD_LATENT_AUTOMATION_COMMAND( - TimeLoadingCommand(gLoadTestContext, pass.setupStep, pass.verifyStep)); + FString loggingName = testName + ":" + pass.name; + + ADD_LATENT_AUTOMATION_COMMAND(TimeLoadingCommand( + loggingName, + gLoadTestContext, + pass.setupStep, + pass.verifyStep)); } // End play in editor @@ -169,20 +178,30 @@ bool RunLoadTest( return true; } +void clearDiskCache(SceneGenerationContext& context) { + // TODO +} + +void refreshTilesets(SceneGenerationContext& context) { + gLoadTestContext.playContext.refreshTilesets(); +} + bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{nullptr, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(setupForDenver, testPasses); + return RunLoadTest(GetTestName(), setupForDenver, testPasses); } bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{nullptr, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(setupForGoogleTiles, testPasses); + return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); } bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { @@ -226,10 +245,10 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { }; std::vector testPasses; - testPasses.push_back(TestPass{nullptr, nullptr}); - testPasses.push_back(TestPass{adjustCamera, verifyVisibleTiles}); + testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); - return RunLoadTest(setupForMontrealPointCloud, testPasses); + return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); } #endif From a6a353b5082c1b3d8fbafa5f817f113fc9d29392 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 11 Sep 2023 13:42:26 -0600 Subject: [PATCH 50/95] Add runtime access to cache database. Let load tests reset cache for cold / warm testing --- .../CesiumRuntime/Private/CesiumRuntime.cpp | 20 +++++++++++++------ .../Private/Tests/CesiumLoadTest.cpp | 13 +++++++----- Source/CesiumRuntime/Public/CesiumRuntime.h | 4 ++++ 3 files changed, 26 insertions(+), 11 deletions(-) diff --git a/Source/CesiumRuntime/Private/CesiumRuntime.cpp b/Source/CesiumRuntime/Private/CesiumRuntime.cpp index d0289b183..a46aeada0 100644 --- a/Source/CesiumRuntime/Private/CesiumRuntime.cpp +++ b/Source/CesiumRuntime/Private/CesiumRuntime.cpp @@ -100,20 +100,28 @@ std::string getCacheDatabaseName() { } // namespace +std::shared_ptr& getCacheDatabase() { + static int MaxCacheItems = + GetDefault()->MaxCacheItems; + + static std::shared_ptr pCacheDatabase = + std::make_shared( + spdlog::default_logger(), + getCacheDatabaseName(), + MaxCacheItems); + + return pCacheDatabase; +} + const std::shared_ptr& getAssetAccessor() { static int RequestsPerCachePrune = GetDefault()->RequestsPerCachePrune; - static int MaxCacheItems = - GetDefault()->MaxCacheItems; static std::shared_ptr pAssetAccessor = std::make_shared( std::make_shared( spdlog::default_logger(), std::make_shared(), - std::make_shared( - spdlog::default_logger(), - getCacheDatabaseName(), - MaxCacheItems), + getCacheDatabase(), RequestsPerCachePrune)); return pAssetAccessor; } diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 4bf36d687..c1b576f93 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -6,6 +6,7 @@ #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" +#include "CesiumAsync/ICacheDatabase.h" #include "CesiumGltfComponent.h" #include "CesiumRuntime.h" #include "CesiumSceneGeneration.h" @@ -178,8 +179,10 @@ bool RunLoadTest( return true; } -void clearDiskCache(SceneGenerationContext& context) { - // TODO +void clearCacheDb(SceneGenerationContext& context) { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); } void refreshTilesets(SceneGenerationContext& context) { @@ -189,7 +192,7 @@ void refreshTilesets(SceneGenerationContext& context) { bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); return RunLoadTest(GetTestName(), setupForDenver, testPasses); @@ -198,7 +201,7 @@ bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); @@ -245,7 +248,7 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { }; std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearDiskCache, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); diff --git a/Source/CesiumRuntime/Public/CesiumRuntime.h b/Source/CesiumRuntime/Public/CesiumRuntime.h index f383d15c7..5c4252b48 100644 --- a/Source/CesiumRuntime/Public/CesiumRuntime.h +++ b/Source/CesiumRuntime/Public/CesiumRuntime.h @@ -12,6 +12,7 @@ class UCesiumRasterOverlay; namespace CesiumAsync { class AsyncSystem; class IAssetAccessor; +class ICacheDatabase; } // namespace CesiumAsync DECLARE_LOG_CATEGORY_EXTERN(LogCesium, Log, All); @@ -48,3 +49,6 @@ CESIUMRUNTIME_API extern FCesiumRasterOverlayIonTroubleshooting CESIUMRUNTIME_API CesiumAsync::AsyncSystem& getAsyncSystem() noexcept; CESIUMRUNTIME_API const std::shared_ptr& getAssetAccessor(); + +CESIUMRUNTIME_API std::shared_ptr& +getCacheDatabase(); From b1f22d84476a9084f56e3d4df01e4f9669e8509f Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 11 Sep 2023 15:20:11 -0600 Subject: [PATCH 51/95] Move clear db cache step to initial test setup Seems to yield more consistent test times --- .../Private/Tests/CesiumLoadTest.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index c1b576f93..2a0252574 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -128,6 +128,12 @@ struct TestPass { std::function verifyStep; }; +void clearCacheDb() { + std::shared_ptr pCacheDatabase = + getCacheDatabase(); + pCacheDatabase->clearAll(); +} + bool RunLoadTest( const FString& testName, std::function locationSetup, @@ -148,6 +154,7 @@ bool RunLoadTest( // Halt tileset updates and reset them gLoadTestContext.creationContext.setSuspendUpdate(true); gLoadTestContext.creationContext.refreshTilesets(); + clearCacheDb (); // // Start async commands @@ -161,7 +168,7 @@ bool RunLoadTest( const TestPass& pass = *it; // Wait a bit - ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); // Do our timing capture FString loggingName = testName + ":" + pass.name; @@ -179,12 +186,6 @@ bool RunLoadTest( return true; } -void clearCacheDb(SceneGenerationContext& context) { - std::shared_ptr pCacheDatabase = - getCacheDatabase(); - pCacheDatabase->clearAll(); -} - void refreshTilesets(SceneGenerationContext& context) { gLoadTestContext.playContext.refreshTilesets(); } @@ -192,7 +193,7 @@ void refreshTilesets(SceneGenerationContext& context) { bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); return RunLoadTest(GetTestName(), setupForDenver, testPasses); @@ -201,7 +202,7 @@ bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); @@ -248,7 +249,7 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { }; std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", clearCacheDb, nullptr}); + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); From 7a8b725dff30cca2184bba963da165082fbaec88 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 12 Sep 2023 09:19:28 -0600 Subject: [PATCH 52/95] Fix formatting --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 2a0252574..5ccf9dc2f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -154,7 +154,7 @@ bool RunLoadTest( // Halt tileset updates and reset them gLoadTestContext.creationContext.setSuspendUpdate(true); gLoadTestContext.creationContext.refreshTilesets(); - clearCacheDb (); + clearCacheDb(); // // Start async commands From e73fee9e433757a85c71ba7ad11d9ff24374a89d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:50:13 -0600 Subject: [PATCH 53/95] Add trace events before calling updateView, updateViewOffline --- Source/CesiumRuntime/Private/Cesium3DTileset.cpp | 12 ++++++++---- 1 file changed, 8 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index cf845984e..02a1c0bc4 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2032,10 +2032,14 @@ void ACesium3DTileset::Tick(float DeltaTime) { CreateViewStateFromViewParameters(camera, unrealWorldToTileset)); } - const Cesium3DTilesSelection::ViewUpdateResult& result = - this->_captureMovieMode - ? this->_pTileset->updateViewOffline(frustums) - : this->_pTileset->updateView(frustums, DeltaTime); + Cesium3DTilesSelection::ViewUpdateResult result; + if (this->_captureMovieMode) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) + result = this->_pTileset->updateViewOffline(frustums); + } else { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) + result = this->_pTileset->updateView(frustums, DeltaTime); + } updateLastViewUpdateResultState(result); removeCollisionForTiles(result.tilesFadingOut); From fb130b18437429ca97f1c68989a3abc3033f9868 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 18 Sep 2023 12:50:55 -0600 Subject: [PATCH 54/95] Add wait before exiting play mode Helps see cases where work is still being done passed the end mark (which might be a bug) --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 3 +++ 1 file changed, 3 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 5ccf9dc2f..8935c6eed 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -180,6 +180,9 @@ bool RunLoadTest( pass.verifyStep)); } + // Wait a bit + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); + // End play in editor ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); From 26a9b7f0ea4e729086c8b2d76c22a3cd9e7a160a Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:13:36 -0600 Subject: [PATCH 55/95] Fix for non-unity build --- Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp b/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp index f9c94425a..6a5c46298 100644 --- a/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp +++ b/Source/CesiumEditor/Private/CesiumEditorSubLevelMutex.cpp @@ -6,6 +6,7 @@ #include "CesiumSubLevelComponent.h" #include "CesiumSubLevelSwitcherComponent.h" #include "Components/ActorComponent.h" +#include "Engine/World.h" #include "LevelInstance/LevelInstanceActor.h" CesiumEditorSubLevelMutex::CesiumEditorSubLevelMutex() { From 1f6ecc7ebade491dc79b078903a39cf1d5b106f3 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:13:58 -0600 Subject: [PATCH 56/95] Update to renamed georeference functions --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index fb8ce9a56..1891f9649 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -140,7 +140,7 @@ void setupForGoogleTiles(LoadTestContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + context.georeference->SetOriginLongitudeLatitudeHeight( targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); @@ -167,7 +167,7 @@ void setupForDenver(LoadTestContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( + context.georeference->SetOriginLongitudeLatitudeHeight( targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); From 7c93ae0be09a20d5e8772ae8d985e786ab9f9662 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:26:41 -0600 Subject: [PATCH 57/95] Update to renamed georeference functions --- .../Private/Tests/CesiumSceneGeneration.cpp | 9 +++------ 1 file changed, 3 insertions(+), 6 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 71af4ace9..46551fac4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -126,8 +126,7 @@ void setupForGoogleTiles(SceneGenerationContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); + context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-25, 95, 0)); @@ -151,8 +150,7 @@ void setupForDenver(SceneGenerationContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); + context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); @@ -199,8 +197,7 @@ void setupForMontrealPointCloud(SceneGenerationContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetGeoreferenceOriginLongitudeLatitudeHeight( - targetOrigin); + context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-90.0, 0.0, 0.0)); From a3fd233532aa3daad04590bf9e9eefbe0192c521 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 19 Sep 2023 11:27:00 -0600 Subject: [PATCH 58/95] Update test to Cesium.Unit.X namespace --- Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp index 571a69fb0..ac35d51c0 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumGeoreference.spec.cpp @@ -12,7 +12,7 @@ using namespace CesiumUtility; BEGIN_DEFINE_SPEC( FCesiumGeoreferenceSpec, - "Cesium.Georeference", + "Cesium.Unit.Georeference", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) From 7af3191447208aa6a5da8b809b2b09a5b1bc5141 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:19:11 -0600 Subject: [PATCH 59/95] Add note about building Release and RelWithDebInfo configs --- Documentation/developer-setup-windows.md | 1 + 1 file changed, 1 insertion(+) diff --git a/Documentation/developer-setup-windows.md b/Documentation/developer-setup-windows.md index b99ec69c1..3b4567904 100644 --- a/Documentation/developer-setup-windows.md +++ b/Documentation/developer-setup-windows.md @@ -74,6 +74,7 @@ To build a "Release" build of cesium-native, - Add a new configuration by clicking the `+` and choose `x64-Release`. - Select the new "x64-Release" from the Solution Configuration dropdown. - Right-click on `CMakeLists.txt` again and choose "Install". +> In Visual Studio, this defaults to the "RelWithDebInfo" configuration type. You can change this at any time ## Visual Studio Code From bcb30e71eb6deb1796a268bca8e99eb1e7c8be2f Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Wed, 20 Sep 2023 11:21:55 -0600 Subject: [PATCH 60/95] Add note about building release with debug symbols --- Documentation/performance-profiling-setup-test.md | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Documentation/performance-profiling-setup-test.md b/Documentation/performance-profiling-setup-test.md index 544e552af..b22469215 100644 --- a/Documentation/performance-profiling-setup-test.md +++ b/Documentation/performance-profiling-setup-test.md @@ -16,11 +16,11 @@ We need an area of code to execute repeatedly, with as many variables locked dow ### Build Release Code -We need to make sure all our C++ code is building in release mode. +We need to make sure all our C++ code is building in release mode, preferably with debug symbols. > This assumes that you have already built your code successfully and are familiar with the concepts from our [developer setup guide](https://github.com/CesiumGS/cesium-unreal/blob/ue5-main/Documentation/developer-setup-windows.md). Although you could profile a debug build, it is typically more useful to build in release, since this is how a game is usually packaged. -1) If building the cesium-native library, make sure you are using a Release configuration +1) If building the cesium-native library, make sure you are using a release configuration derived from "RelWithDebInfo" 2) Open your Unreal project's Visual Studio solution (.sln). This example uses the solution generated from [cesium-unreal-samples](https://github.com/CesiumGS/cesium-unreal-samples) 3) Choose "Development Editor" From 748e19acd0f46848f86d9812be62454e7e5cc49a Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 21 Sep 2023 16:09:46 -0600 Subject: [PATCH 61/95] Disable world bounds checks for test world This silences our ACesium3DTileset warning about this during tests. --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 46551fac4..e18bf30b8 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -111,6 +111,10 @@ void createCommonWorldObjects(SceneGenerationContext& context) { Cast(DynamicPawn.LoadSynchronous())); context.pawn->AutoPossessPlayer = EAutoReceiveInput::Player0; + + AWorldSettings* pWorldSettings = context.world->GetWorldSettings(); + if (pWorldSettings) + pWorldSettings->bEnableWorldBoundsChecks = false; } void setupForGoogleTiles(SceneGenerationContext& context) { From 56ed67753fa70f0bee769b5988a2763f813b4e68 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Mon, 25 Sep 2023 10:56:31 -0600 Subject: [PATCH 62/95] Add missing include header Should fix build error on CI --- Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp | 7 +++---- 1 file changed, 3 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 1891f9649..682b7bdd9 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -2,6 +2,7 @@ #if WITH_EDITOR +#include "Framework/Application/SlateApplication.h" #include "Misc/AutomationTest.h" #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" @@ -140,8 +141,7 @@ void setupForGoogleTiles(LoadTestContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetOriginLongitudeLatitudeHeight( - targetOrigin); + context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-25, 95, 0)); @@ -167,8 +167,7 @@ void setupForDenver(LoadTestContext& context) { camera.FieldOfViewDegrees = 90; context.setCamera(camera); - context.georeference->SetOriginLongitudeLatitudeHeight( - targetOrigin); + context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); context.pawn->SetActorLocation(FVector(0, 0, 0)); context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); From a075071aa132bfd70ae6192363828fab7b373e84 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 25 Sep 2023 17:01:56 -0600 Subject: [PATCH 63/95] Tweak LoadProgress - Don't let it reach 100 if there is still occlusion work to do - Reset to 0 when a tileset is first created (LoadTileset) - Remove unneeded _activeLoading flag --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 48 +++++++++++-------- Source/CesiumRuntime/Public/Cesium3DTileset.h | 1 - 2 files changed, 29 insertions(+), 20 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index a6b30a4ec..456705caf 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -881,33 +881,41 @@ class UnrealResourcePreparer void ACesium3DTileset::UpdateLoadStatus() { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateLoadStatus) - this->LoadProgress = this->_pTileset->computeLoadProgress(); + float nativeLoadProgress = this->_pTileset->computeLoadProgress(); + + // If native tileset still loading, just copy its progress + if (nativeLoadProgress < 100) { + this->LoadProgress = nativeLoadProgress; + return; + } + + // Native tileset is 100% loaded, but there might be a few frames where + // nothing needs to be loaded as we are waiting for occlusion results to come + // back, which means we are not done with loading all the tiles in the tileset + // yet. Interpret this as 99% (almost) done + if (this->_lastTilesWaitingForOcclusionResults > 0) { + this->LoadProgress = 99; + return; + } // If we have tiles to hide next frame, we haven't completely finished loading - // yet. We need to tick once more + // yet. We need to tick once more. We're really close to done. if (!this->_tilesToHideNextFrame.empty()) { this->LoadProgress = glm::min(this->LoadProgress, 99.9999f); + return; } - if (this->LoadProgress < 100 || - this->_lastTilesWaitingForOcclusionResults > 0) { - this->_activeLoading = true; - } else if (this->_activeLoading && this->LoadProgress == 100) { - - // There might be a few frames where nothing needs to be loaded as we - // are waiting for occlusion results to come back, which means we are not - // done with loading all the tiles in the tileset yet. - if (this->_lastTilesWaitingForOcclusionResults == 0) { - TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::BroadcastOnTilesetLoaded) + // We can now report 100 percent loaded + float lastLoadProgress = this->LoadProgress; + this->LoadProgress = 100; - // Tileset just finished loading, we broadcast the update - UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnTileLoaded")); - OnTilesetLoaded.Broadcast(); + // Only broadcast the update when we first hit 100%, not everytime + if (lastLoadProgress != LoadProgress) { + TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::BroadcastOnTilesetLoaded) - // Tileset remains 100% loaded if we don't have to reload it - // so we don't want to keep on sending finished loading updates - this->_activeLoading = false; - } + // Tileset just finished loading, we broadcast the update + UE_LOG(LogCesium, Verbose, TEXT("Broadcasting OnTileLoaded")); + OnTilesetLoaded.Broadcast(); } } @@ -1019,6 +1027,8 @@ void ACesium3DTileset::LoadTileset() { this->_startTime = std::chrono::high_resolution_clock::now(); + this->LoadProgress = 0; + Cesium3DTilesSelection::TilesetOptions options; options.enableOcclusionCulling = diff --git a/Source/CesiumRuntime/Public/Cesium3DTileset.h b/Source/CesiumRuntime/Public/Cesium3DTileset.h index e4bbe3ac0..8fbf50bc7 100644 --- a/Source/CesiumRuntime/Public/Cesium3DTileset.h +++ b/Source/CesiumRuntime/Public/Cesium3DTileset.h @@ -1204,7 +1204,6 @@ class CESIUMRUNTIME_API ACesium3DTileset : public AActor { uint32_t _lastTilesRendered; uint32_t _lastWorkerThreadTileLoadQueueLength; uint32_t _lastMainThreadTileLoadQueueLength; - bool _activeLoading; uint32_t _lastTilesVisited; uint32_t _lastCulledTilesVisited; From 868c71ad80e0a9754c5033880c4c875e55f63159 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 27 Sep 2023 13:32:10 -0600 Subject: [PATCH 64/95] Move final cleanup of setSuspendUpdate to completion of test --- .../Private/Tests/CesiumLoadTest.cpp | 15 ++++++++++++--- 1 file changed, 12 insertions(+), 3 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index af8b064a1..74240e77d 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -110,9 +110,6 @@ bool TimeLoadingCommand::Update() { if (verifyStep) verifyStep(context.playContext); - // Turn on the editor tileset updates so we can see what we loaded - gLoadTestContext.creationContext.setSuspendUpdate(false); - context.testInProgress = false; // Command is done @@ -123,6 +120,16 @@ bool TimeLoadingCommand::Update() { return false; } +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( + TestCleanupCommand, + LoadTestContext&, + context); +bool TestCleanupCommand::Update() { + // Turn on the editor tileset updates so we can see what we loaded + gLoadTestContext.creationContext.setSuspendUpdate(false); + return true; +} + struct TestPass { FString name; std::function setupStep; @@ -187,6 +194,8 @@ bool RunLoadTest( // End play in editor ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); + ADD_LATENT_AUTOMATION_COMMAND(TestCleanupCommand(gLoadTestContext)); + return true; } From cb1431f5d4d200fa312bc1258900d4f9a67f03bc Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 3 Oct 2023 11:32:57 -0600 Subject: [PATCH 65/95] Fix start mark encompassing PIE startup time --- .../Private/Tests/CesiumLoadTest.cpp | 16 ++++++++++++++-- 1 file changed, 14 insertions(+), 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 74240e77d..25e81da7e 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -130,6 +130,14 @@ bool TestCleanupCommand::Update() { return true; } +DEFINE_LATENT_AUTOMATION_COMMAND(WaitForPIECommand); +bool WaitForPIECommand::Update() { + if (!GEditor || !GEditor->IsPlayingSessionInEditor()) + return false; + UE_LOG(LogCesium, Display, TEXT("Play in Editor ready...")); + return true; +} + struct TestPass { FString name; std::function setupStep; @@ -168,8 +176,12 @@ bool RunLoadTest( // Start async commands // - // Start play in editor (don't sim in editor) + // Wait for shaders. Shader compiles could affect performance + ADD_LATENT_AUTOMATION_COMMAND(FWaitForShadersToFinishCompiling); + + // Queue play in editor, then wait for it (don't sim in editor) ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(false)); + ADD_LATENT_AUTOMATION_COMMAND(WaitForPIECommand()); std::vector::const_iterator it; for (it = testPasses.begin(); it != testPasses.end(); ++it) { @@ -188,7 +200,7 @@ bool RunLoadTest( pass.verifyStep)); } - // Wait a bit + // Wait a bit to show a distinct gap if using a profiler ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); // End play in editor From c921427f2b61e32c29331e0d8da6e108308b3d5c Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Tue, 3 Oct 2023 16:56:24 -0600 Subject: [PATCH 66/95] Let tests run with predetermined viewport sizes --- .../Private/Tests/CesiumLoadTest.cpp | 34 +++++---- .../Private/Tests/CesiumSceneGeneration.cpp | 69 +++++++++---------- .../Private/Tests/CesiumSceneGeneration.h | 6 +- 3 files changed, 60 insertions(+), 49 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp index 25e81da7e..6261b52e3 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp @@ -35,6 +35,10 @@ struct LoadTestContext { SceneGenerationContext creationContext; SceneGenerationContext playContext; + float cameraFieldOfView = 90.0f; + int viewportWidth = 1024; + int viewportHeight = 768; + bool testInProgress; double startMark; double endMark; @@ -64,6 +68,7 @@ bool TimeLoadingCommand::Update() { // Bind all play in editor pointers context.playContext.initForPlay(context.creationContext); + context.playContext.syncWorldPlayerCamera(); if (setupStep) setupStep(context.playContext); @@ -179,15 +184,23 @@ bool RunLoadTest( // Wait for shaders. Shader compiles could affect performance ADD_LATENT_AUTOMATION_COMMAND(FWaitForShadersToFinishCompiling); - // Queue play in editor, then wait for it (don't sim in editor) - ADD_LATENT_AUTOMATION_COMMAND(FStartPIECommand(false)); + // Queue play in editor and set desired viewport size + FRequestPlaySessionParams Params; + Params.WorldType = EPlaySessionWorldType::PlayInEditor; + Params.EditorPlaySettings = NewObject(); + Params.EditorPlaySettings->NewWindowWidth = gLoadTestContext.viewportWidth; + Params.EditorPlaySettings->NewWindowHeight = gLoadTestContext.viewportHeight; + Params.EditorPlaySettings->EnableGameSound = false; + GEditor->RequestPlaySession(Params); + + // Wait until PIE is ready ADD_LATENT_AUTOMATION_COMMAND(WaitForPIECommand()); std::vector::const_iterator it; for (it = testPasses.begin(); it != testPasses.end(); ++it) { const TestPass& pass = *it; - // Wait a bit + // Wait to show distinct gap in profiler ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); // Do our timing capture @@ -200,7 +213,7 @@ bool RunLoadTest( pass.verifyStep)); } - // Wait a bit to show a distinct gap if using a profiler + // Wait to show distinct gap in profiler ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); // End play in editor @@ -237,14 +250,11 @@ bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { auto adjustCamera = [this](SceneGenerationContext& context) { // Zoom way out - FCesiumCamera zoomedOut; - zoomedOut.ViewportSize = FVector2D(1024, 768); - zoomedOut.Location = FVector(0, 0, 7240000.0); - zoomedOut.Rotation = FRotator(-90.0, 0.0, 0.0); - zoomedOut.FieldOfViewDegrees = 90; - context.setCamera(zoomedOut); - - context.pawn->SetActorLocation(zoomedOut.Location); + context.startPosition = FVector(0, 0, 7240000.0); + context.startRotation = FRotator(-90.0, 0.0, 0.0); + context.syncWorldPlayerCamera(); + + context.pawn->SetActorLocation(context.startPosition); }; auto verifyVisibleTiles = [this](SceneGenerationContext& context) { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index e18bf30b8..181afe5f5 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -22,16 +22,6 @@ namespace Cesium { FString SceneGenerationContext::testIonToken( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); -void SceneGenerationContext::setCamera(const FCesiumCamera& camera) { - // Take over first camera, or add if it doesn't exist - const TMap cameras = cameraManager->GetCameras(); - if (cameras.IsEmpty()) { - cameraManager->AddCamera(camera); - } else { - cameraManager->UpdateCamera(0, camera); - } -} - void SceneGenerationContext::refreshTilesets() { std::vector::iterator it; for (it = tilesets.begin(); it != tilesets.end(); ++it) @@ -80,6 +70,10 @@ void SceneGenerationContext::initForPlay( cameraManager = CesiumTestHelpers::findInPlay(creationContext.cameraManager); pawn = CesiumTestHelpers::findInPlay(creationContext.pawn); + startPosition = creationContext.startPosition; + startRotation = creationContext.startRotation; + startFieldOfView = creationContext.startFieldOfView; + tilesets.clear(); std::vector& creationTilesets = creationContext.tilesets; @@ -91,6 +85,20 @@ void SceneGenerationContext::initForPlay( } } +void SceneGenerationContext::syncWorldPlayerCamera() { + assert(world->GetNumPlayerControllers() == 1); + + APlayerController* controller = world->GetFirstPlayerController(); + assert(controller); + + controller->ClientSetLocation(startPosition, startRotation); + + APlayerCameraManager* cameraManager = controller->PlayerCameraManager; + assert(cameraManager); + + cameraManager->SetFOV(startFieldOfView); +} + void createCommonWorldObjects(SceneGenerationContext& context) { context.world = FAutomationEditorCommonUtils::CreateNewMap(); @@ -118,22 +126,18 @@ void createCommonWorldObjects(SceneGenerationContext& context) { } void setupForGoogleTiles(SceneGenerationContext& context) { - FVector targetOrigin(-122.083969, 37.424492, 142.859116); FString targetUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-25, 95, 0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); + context.startPosition = FVector(0, 0, 0); + context.startRotation = FRotator(-25, 95, 0); + context.startFieldOfView = 90.0f; context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-25, 95, 0)); + context.pawn->SetActorLocation(context.startPosition); + context.pawn->SetActorRotation(context.startRotation); ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(targetUrl); @@ -144,20 +148,16 @@ void setupForGoogleTiles(SceneGenerationContext& context) { } void setupForDenver(SceneGenerationContext& context) { - FVector targetOrigin(-104.988892, 39.743462, 1798.679443); - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-5.2, -149.4, 0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); + context.startPosition = FVector(0, 0, 0); + context.startRotation = FRotator(-5.2, -149.4, 0); + context.startFieldOfView = 90.0f; context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-5.2, -149.4, 0)); + context.pawn->SetActorLocation(context.startPosition); + context.pawn->SetActorRotation(context.startRotation); // Add Cesium World Terrain ACesium3DTileset* worldTerrainTileset = @@ -194,17 +194,14 @@ void setupForDenver(SceneGenerationContext& context) { void setupForMontrealPointCloud(SceneGenerationContext& context) { FVector targetOrigin(-73.616526, 45.57335, 95.048859); - FCesiumCamera camera; - camera.ViewportSize = FVector2D(1024, 768); - camera.Location = FVector(0, 0, 0); - camera.Rotation = FRotator(-90.0, 0.0, 0.0); - camera.FieldOfViewDegrees = 90; - context.setCamera(camera); + context.startPosition = FVector(0, 0, 0); + context.startRotation = FRotator(-90.0, 0.0, 0.0); + context.startFieldOfView = 90.0f; context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - context.pawn->SetActorLocation(FVector(0, 0, 0)); - context.pawn->SetActorRotation(FRotator(-90.0, 0.0, 0.0)); + context.pawn->SetActorLocation(context.startPosition); + context.pawn->SetActorRotation(context.startRotation); // Montreal Point Cloud ACesium3DTileset* montrealTileset = diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 85ff0cd1b..35a19f8d8 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -21,13 +21,17 @@ struct SceneGenerationContext { AGlobeAwareDefaultPawn* pawn; std::vector tilesets; - void setCamera(const FCesiumCamera& camera); + FVector startPosition; + FRotator startRotation; + float startFieldOfView; + void refreshTilesets(); void setSuspendUpdate(bool suspend); bool areTilesetsDoneLoading(); void trackForPlay(); void initForPlay(SceneGenerationContext& creationContext); + void syncWorldPlayerCamera(); static FString testIonToken; }; From a692f4223d6bdd33026bd531d4a26766bdda125d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 13:50:12 -0600 Subject: [PATCH 67/95] Break up code, tests separate from core logic --- ...iumLoadTest.cpp => CesiumLoadTestCore.cpp} | 100 ++---------------- .../Private/Tests/CesiumLoadTestCore.h | 26 +++++ .../Private/Tests/CesiumLoadTestSamples.cpp | 95 +++++++++++++++++ .../Private/Tests/CesiumSceneGeneration.cpp | 10 +- .../Private/Tests/CesiumSceneGeneration.h | 5 +- 5 files changed, 131 insertions(+), 105 deletions(-) rename Source/CesiumRuntime/Private/Tests/{CesiumLoadTest.cpp => CesiumLoadTestCore.cpp} (62%) create mode 100644 Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h create mode 100644 Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp similarity index 62% rename from Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp rename to Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 6261b52e3..93c70c175 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -2,34 +2,16 @@ #if WITH_EDITOR -#include "Framework/Application/SlateApplication.h" -#include "Misc/AutomationTest.h" -#include "Tests/AutomationCommon.h" -#include "Tests/AutomationEditorCommon.h" +#include "CesiumLoadTestCore.h" #include "CesiumAsync/ICacheDatabase.h" -#include "CesiumGltfComponent.h" #include "CesiumRuntime.h" -#include "CesiumSceneGeneration.h" -#include "CesiumTestHelpers.h" -#include "GlobeAwareDefaultPawn.h" - -using namespace Cesium; -IMPLEMENT_SIMPLE_AUTOMATION_TEST( - FCesiumLoadTestDenver, - "Cesium.Performance.LoadTestDenver", - EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) - -IMPLEMENT_SIMPLE_AUTOMATION_TEST( - FCesiumLoadTestGoogleplex, - "Cesium.Performance.LoadTestGoogleplex", - EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +#include "Editor.h" +#include "Tests/AutomationCommon.h" +#include "Tests/AutomationEditorCommon.h" -IMPLEMENT_SIMPLE_AUTOMATION_TEST( - FCesiumLoadTestMontrealPointCloud, - "Cesium.Performance.LoadTestMontrealPointCloud", - EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +namespace Cesium { struct LoadTestContext { SceneGenerationContext creationContext; @@ -143,12 +125,6 @@ bool WaitForPIECommand::Update() { return true; } -struct TestPass { - FString name; - std::function setupStep; - std::function verifyStep; -}; - void clearCacheDb() { std::shared_ptr pCacheDatabase = getCacheDatabase(); @@ -224,70 +200,6 @@ bool RunLoadTest( return true; } -void refreshTilesets(SceneGenerationContext& context) { - gLoadTestContext.playContext.refreshTilesets(); -} - -bool FCesiumLoadTestDenver::RunTest(const FString& Parameters) { - - std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - - return RunLoadTest(GetTestName(), setupForDenver, testPasses); -} - -bool FCesiumLoadTestGoogleplex::RunTest(const FString& Parameters) { - - std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - - return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); -} - -bool FCesiumLoadTestMontrealPointCloud::RunTest(const FString& Parameters) { - - auto adjustCamera = [this](SceneGenerationContext& context) { - // Zoom way out - context.startPosition = FVector(0, 0, 7240000.0); - context.startRotation = FRotator(-90.0, 0.0, 0.0); - context.syncWorldPlayerCamera(); - - context.pawn->SetActorLocation(context.startPosition); - }; - - auto verifyVisibleTiles = [this](SceneGenerationContext& context) { - Cesium3DTilesSelection::Tileset* pTileset = - context.tilesets[0]->GetTileset(); - if (TestNotNull("Tileset", pTileset)) { - int visibleTiles = 0; - pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { - if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) - return; - const Cesium3DTilesSelection::TileContent& content = tile.getContent(); - const Cesium3DTilesSelection::TileRenderContent* pRenderContent = - content.getRenderContent(); - if (!pRenderContent) { - return; - } - - UCesiumGltfComponent* Gltf = static_cast( - pRenderContent->getRenderResources()); - if (Gltf && Gltf->IsVisible()) { - ++visibleTiles; - } - }); - - TestEqual("visibleTiles", visibleTiles, 1); - } - }; - - std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); - - return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); -} +}; // namespace Cesium #endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h new file mode 100644 index 000000000..9908b8baf --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h @@ -0,0 +1,26 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#pragma once + +#if WITH_EDITOR + +#include + +#include "CesiumSceneGeneration.h" + +namespace Cesium { + +struct TestPass { + FString name; + std::function setupStep; + std::function verifyStep; +}; + +bool RunLoadTest( + const FString& testName, + std::function locationSetup, + const std::vector& testPasses); + +}; // namespace Cesium + +#endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp new file mode 100644 index 000000000..940c538ce --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -0,0 +1,95 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "Misc/AutomationTest.h" + +#include "CesiumGltfComponent.h" +#include "GlobeAwareDefaultPawn.h" + +using namespace Cesium; + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumSampleLoadDenver, + "Cesium.Performance.SampleLoadDenver", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumSampleLoadGoogleplex, + "Cesium.Performance.SampleLoadGoogleplex", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FCesiumSampleLoadMontrealPointCloud, + "Cesium.Performance.SampleLoadMontrealPointCloud", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +void refreshTilesets(SceneGenerationContext& context) { + context.refreshTilesets(); +} + +bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { + + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForDenver, testPasses); +} + +bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { + + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); +} + +bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { + + auto adjustCamera = [this](SceneGenerationContext& context) { + // Zoom way out + context.startPosition = FVector(0, 0, 7240000.0); + context.startRotation = FRotator(-90.0, 0.0, 0.0); + context.syncWorldPlayerCamera(); + + context.pawn->SetActorLocation(context.startPosition); + }; + + auto verifyVisibleTiles = [this](SceneGenerationContext& context) { + Cesium3DTilesSelection::Tileset* pTileset = + context.tilesets[0]->GetTileset(); + if (TestNotNull("Tileset", pTileset)) { + int visibleTiles = 0; + pTileset->forEachLoadedTile([&](Cesium3DTilesSelection::Tile& tile) { + if (tile.getState() != Cesium3DTilesSelection::TileLoadState::Done) + return; + const Cesium3DTilesSelection::TileContent& content = tile.getContent(); + const Cesium3DTilesSelection::TileRenderContent* pRenderContent = + content.getRenderContent(); + if (!pRenderContent) { + return; + } + + UCesiumGltfComponent* Gltf = static_cast( + pRenderContent->getRenderResources()); + if (Gltf && Gltf->IsVisible()) { + ++visibleTiles; + } + }); + + TestEqual("visibleTiles", visibleTiles, 1); + } + }; + + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); + + return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); +} + +#endif diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 181afe5f5..6928bf5db 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -1,15 +1,14 @@ // Copyright 2020-2023 CesiumGS, Inc. and Contributors -#include "CesiumSceneGeneration.h" - #if WITH_EDITOR +#include "CesiumSceneGeneration.h" + #include "Tests/AutomationEditorCommon.h" #include "GameFramework/PlayerStart.h" #include "Cesium3DTileset.h" -#include "CesiumCameraManager.h" #include "CesiumGeoreference.h" #include "CesiumIonRasterOverlay.h" #include "CesiumSunSky.h" @@ -53,7 +52,6 @@ bool SceneGenerationContext::areTilesetsDoneLoading() { void SceneGenerationContext::trackForPlay() { CesiumTestHelpers::trackForPlay(georeference); - CesiumTestHelpers::trackForPlay(cameraManager); CesiumTestHelpers::trackForPlay(pawn); std::vector::iterator it; @@ -67,7 +65,6 @@ void SceneGenerationContext::initForPlay( SceneGenerationContext& creationContext) { world = GEditor->PlayWorld; georeference = CesiumTestHelpers::findInPlay(creationContext.georeference); - cameraManager = CesiumTestHelpers::findInPlay(creationContext.cameraManager); pawn = CesiumTestHelpers::findInPlay(creationContext.pawn); startPosition = creationContext.startPosition; @@ -106,9 +103,6 @@ void createCommonWorldObjects(SceneGenerationContext& context) { ACesiumSunSky* sunSky = context.world->SpawnActor(); APlayerStart* playerStart = context.world->SpawnActor(); - context.cameraManager = - ACesiumCameraManager::GetDefaultCameraManager(context.world); - FSoftObjectPath objectPath( TEXT("Class'/CesiumForUnreal/DynamicPawn.DynamicPawn_C'")); TSoftObjectPtr DynamicPawn = TSoftObjectPtr(objectPath); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 35a19f8d8..394743199 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -4,20 +4,19 @@ #if WITH_EDITOR -#include "CesiumCameraManager.h" -#include "Editor.h" +#include class UWorld; class ACesiumGeoreference; class AGlobeAwareDefaultPawn; class ACesium3DTileset; +class ACesiumCameraManager; namespace Cesium { struct SceneGenerationContext { UWorld* world; ACesiumGeoreference* georeference; - ACesiumCameraManager* cameraManager; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; From df50be9f2b7c8ca543eb5ecb2a0c414541654306 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 14:38:10 -0600 Subject: [PATCH 68/95] Move google tiles key next to ion key --- .../CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp | 8 ++++---- .../CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 8 ++++---- .../CesiumRuntime/Private/Tests/CesiumSceneGeneration.h | 3 ++- 3 files changed, 10 insertions(+), 9 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index 940c538ce..5442882e8 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -26,7 +26,7 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.SampleLoadMontrealPointCloud", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -void refreshTilesets(SceneGenerationContext& context) { +void refreshSampleTilesets(SceneGenerationContext& context) { context.refreshTilesets(); } @@ -34,7 +34,7 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); return RunLoadTest(GetTestName(), setupForDenver, testPasses); } @@ -43,9 +43,9 @@ bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForGoogleTiles, testPasses); + return RunLoadTest(GetTestName(), setupForGoogleplex, testPasses); } bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 6928bf5db..49d5d14e6 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -20,6 +20,8 @@ namespace Cesium { FString SceneGenerationContext::testIonToken( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); +FString SceneGenerationContext::testGoogleUrl( + "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); void SceneGenerationContext::refreshTilesets() { std::vector::iterator it; @@ -119,10 +121,8 @@ void createCommonWorldObjects(SceneGenerationContext& context) { pWorldSettings->bEnableWorldBoundsChecks = false; } -void setupForGoogleTiles(SceneGenerationContext& context) { +void setupForGoogleplex(SceneGenerationContext& context) { FVector targetOrigin(-122.083969, 37.424492, 142.859116); - FString targetUrl( - "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); context.startPosition = FVector(0, 0, 0); context.startRotation = FRotator(-25, 95, 0); @@ -134,7 +134,7 @@ void setupForGoogleTiles(SceneGenerationContext& context) { context.pawn->SetActorRotation(context.startRotation); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(targetUrl); + tileset->SetUrl(SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 394743199..72c0e772a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -33,12 +33,13 @@ struct SceneGenerationContext { void syncWorldPlayerCamera(); static FString testIonToken; + static FString testGoogleUrl; }; void createCommonWorldObjects(SceneGenerationContext& context); void setupForDenver(SceneGenerationContext& context); -void setupForGoogleTiles(SceneGenerationContext& context); +void setupForGoogleplex(SceneGenerationContext& context); void setupForMontrealPointCloud(SceneGenerationContext& context); }; // namespace Cesium From 2b378351f8b7d7130ebab96ff0282f36f81091e3 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 14:44:47 -0600 Subject: [PATCH 69/95] Fix unity build (header include) --- Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 93c70c175..400da9870 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -8,6 +8,7 @@ #include "CesiumRuntime.h" #include "Editor.h" +#include "Settings/LevelEditorPlaySettings.h" #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" From 2bf0b3b060f2075a0f500d69fa39bae2000af9b4 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:09:51 -0600 Subject: [PATCH 70/95] Let tests specify viewport sizes --- .../Private/Tests/CesiumLoadTestCore.cpp | 13 +++++++------ .../Private/Tests/CesiumLoadTestCore.h | 4 +++- .../Private/Tests/CesiumLoadTestSamples.cpp | 11 ++++++++--- 3 files changed, 18 insertions(+), 10 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 400da9870..ccb210f06 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -19,8 +19,6 @@ struct LoadTestContext { SceneGenerationContext playContext; float cameraFieldOfView = 90.0f; - int viewportWidth = 1024; - int viewportHeight = 768; bool testInProgress; double startMark; @@ -135,17 +133,20 @@ void clearCacheDb() { bool RunLoadTest( const FString& testName, std::function locationSetup, - const std::vector& testPasses) { + const std::vector& testPasses, + int viewportWidth, + int viewportHeight) { gLoadTestContext.reset(); // // Programmatically set up the world // - UE_LOG(LogCesium, Display, TEXT("Creating world objects...")); + UE_LOG(LogCesium, Display, TEXT("Creating common world objects...")); createCommonWorldObjects(gLoadTestContext.creationContext); // Configure location specific objects + UE_LOG(LogCesium, Display, TEXT("Setting up location...")); locationSetup(gLoadTestContext.creationContext); gLoadTestContext.creationContext.trackForPlay(); @@ -165,8 +166,8 @@ bool RunLoadTest( FRequestPlaySessionParams Params; Params.WorldType = EPlaySessionWorldType::PlayInEditor; Params.EditorPlaySettings = NewObject(); - Params.EditorPlaySettings->NewWindowWidth = gLoadTestContext.viewportWidth; - Params.EditorPlaySettings->NewWindowHeight = gLoadTestContext.viewportHeight; + Params.EditorPlaySettings->NewWindowWidth = viewportWidth; + Params.EditorPlaySettings->NewWindowHeight = viewportHeight; Params.EditorPlaySettings->EnableGameSound = false; GEditor->RequestPlaySession(Params); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h index 9908b8baf..75e5fcb74 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.h @@ -19,7 +19,9 @@ struct TestPass { bool RunLoadTest( const FString& testName, std::function locationSetup, - const std::vector& testPasses); + const std::vector& testPasses, + int viewportWidth, + int viewportHeight); }; // namespace Cesium diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index 5442882e8..a0337d7c9 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -36,7 +36,7 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForDenver, testPasses); + return RunLoadTest(GetTestName(), setupForDenver, testPasses, 1024, 768); } bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { @@ -45,7 +45,7 @@ bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForGoogleplex, testPasses); + return RunLoadTest(GetTestName(), setupForGoogleplex, testPasses, 1280, 720); } bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { @@ -89,7 +89,12 @@ bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); - return RunLoadTest(GetTestName(), setupForMontrealPointCloud, testPasses); + return RunLoadTest( + GetTestName(), + setupForMontrealPointCloud, + testPasses, + 512, + 512); } #endif From b6df20ed7480b7d6bd56314a64e62b75601eacc9 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 15:25:53 -0600 Subject: [PATCH 71/95] Refactor away some duplicate code when creating locations --- .../Private/Tests/CesiumSceneGeneration.cpp | 58 ++++++++++--------- .../Private/Tests/CesiumSceneGeneration.h | 6 ++ 2 files changed, 36 insertions(+), 28 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 49d5d14e6..3b5bb0528 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -23,6 +23,21 @@ FString SceneGenerationContext::testIonToken( FString SceneGenerationContext::testGoogleUrl( "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); +void SceneGenerationContext::setCommonProperties( + const FVector& origin, + const FVector& position, + const FRotator& rotation, + float fieldOfView) { + startPosition = position; + startRotation = rotation; + startFieldOfView = fieldOfView; + + georeference->SetOriginLongitudeLatitudeHeight(origin); + + pawn->SetActorLocation(startPosition); + pawn->SetActorRotation(startRotation); +} + void SceneGenerationContext::refreshTilesets() { std::vector::iterator it; for (it = tilesets.begin(); it != tilesets.end(); ++it) @@ -122,16 +137,12 @@ void createCommonWorldObjects(SceneGenerationContext& context) { } void setupForGoogleplex(SceneGenerationContext& context) { - FVector targetOrigin(-122.083969, 37.424492, 142.859116); - - context.startPosition = FVector(0, 0, 0); - context.startRotation = FRotator(-25, 95, 0); - context.startFieldOfView = 90.0f; - - context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - context.pawn->SetActorLocation(context.startPosition); - context.pawn->SetActorRotation(context.startRotation); + context.setCommonProperties( + FVector(-122.083969, 37.424492, 142.859116), + FVector(0, 0, 0), + FRotator(-25, 95, 0), + 90.0f); ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(SceneGenerationContext::testGoogleUrl); @@ -142,16 +153,12 @@ void setupForGoogleplex(SceneGenerationContext& context) { } void setupForDenver(SceneGenerationContext& context) { - FVector targetOrigin(-104.988892, 39.743462, 1798.679443); - context.startPosition = FVector(0, 0, 0); - context.startRotation = FRotator(-5.2, -149.4, 0); - context.startFieldOfView = 90.0f; - - context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - - context.pawn->SetActorLocation(context.startPosition); - context.pawn->SetActorRotation(context.startRotation); + context.setCommonProperties( + FVector(-104.988892, 39.743462, 1798.679443), + FVector(0, 0, 0), + FRotator(-5.2, -149.4, 0), + 90.0f); // Add Cesium World Terrain ACesium3DTileset* worldTerrainTileset = @@ -186,18 +193,13 @@ void setupForDenver(SceneGenerationContext& context) { } void setupForMontrealPointCloud(SceneGenerationContext& context) { - FVector targetOrigin(-73.616526, 45.57335, 95.048859); - - context.startPosition = FVector(0, 0, 0); - context.startRotation = FRotator(-90.0, 0.0, 0.0); - context.startFieldOfView = 90.0f; - - context.georeference->SetOriginLongitudeLatitudeHeight(targetOrigin); - context.pawn->SetActorLocation(context.startPosition); - context.pawn->SetActorRotation(context.startRotation); + context.setCommonProperties( + FVector(-73.616526, 45.57335, 95.048859), + FVector(0, 0, 0), + FRotator(-90.0, 0.0, 0.0), + 90.0f); - // Montreal Point Cloud ACesium3DTileset* montrealTileset = context.world->SpawnActor(); montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 72c0e772a..9a63ec1eb 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -24,6 +24,12 @@ struct SceneGenerationContext { FRotator startRotation; float startFieldOfView; + void setCommonProperties( + const FVector& origin, + const FVector& position, + const FRotator& rotation, + float fieldOfView); + void refreshTilesets(); void setSuspendUpdate(bool suspend); bool areTilesetsDoneLoading(); From c603ce0aebd1908bb99eab09e6262a7d8318376d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Wed, 4 Oct 2023 16:06:45 -0600 Subject: [PATCH 72/95] Initial drop --- .../Private/Tests/Google3dTilesLoadTest.cpp | 154 ++++++++++++++++++ 1 file changed, 154 insertions(+) create mode 100644 Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp new file mode 100644 index 000000000..216ccc08b --- /dev/null +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -0,0 +1,154 @@ +// Copyright 2020-2023 CesiumGS, Inc. and Contributors + +#if WITH_EDITOR + +#include "CesiumLoadTestCore.h" + +#include "Engine/World.h" +#include "Misc/AutomationTest.h" + +#include "Cesium3DTileset.h" + +using namespace Cesium; + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesPompidou, + "Cesium.Performance.GoogleTilesPompidou", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesChrysler, + "Cesium.Performance.GoogleTilesChrysler", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesGuggenheim, + "Cesium.Performance.GoogleTilesGuggenheim", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesDeathValley, + "Cesium.Performance.GoogleTilesDeathValley", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesTokyo, + "Cesium.Performance.GoogleTilesTokyo", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + +void setupForPompidou(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(2.352200, 48.860600, 200), + FVector(0, 0, 0), + FRotator(-20.0, 0.0, 0.0), + 60.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Center Pompidou, Paris, France")); + context.tilesets.push_back(tileset); +} + +void setupForChrysler(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-73.9752624659, 40.74697185903, 307.38), + FVector(0, 0, 0), + FRotator(-15.0, 0.0, 0.0), + 60.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Chrysler Building, NYC")); + context.tilesets.push_back(tileset); +} + +void setupForGuggenheim(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-2.937, 43.2685, 150), + FVector(0, 0, 0), + FRotator(-15.0, 90.0, 0.0), + 60.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Guggenheim Museum, Bilbao, Spain")); + context.tilesets.push_back(tileset); +} + +void setupForDeathValley(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-116.812278, 36.42, 300), + FVector(0, 0, 0), + FRotator(0, 90.0, 0.0), + 60.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel( + TEXT("Zabriskie Point, Death Valley National Park, California")); + context.tilesets.push_back(tileset); +} + +void setupForTokyo(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(139.7563178458, 35.652798383944, 525.62), + FVector(0, 0, 0), + FRotator(-15, 300, 0.0), + 60.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Tokyo Tower, Tokyo, Japan")); + context.tilesets.push_back(tileset); +} + +void refreshTilesets(SceneGenerationContext& context) { + context.refreshTilesets(); +} + +bool FGoogleTilesPompidou::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForPompidou, testPasses, 1280, 720); +} + +bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForChrysler, testPasses, 1280, 720); +} + +bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForGuggenheim, testPasses, 1280, 720); +} + +bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForDeathValley, testPasses, 1280, 720); +} + +bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); + + return RunLoadTest(GetTestName(), setupForTokyo, testPasses, 1280, 720); +} + +#endif From 75a7a9bf7f9ec43cec0b35edabe2b6675c048ff8 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 5 Oct 2023 14:55:14 -0600 Subject: [PATCH 73/95] Let editor viewport show the same camera orientation as the tests --- .../Private/Tests/CesiumLoadTestCore.cpp | 5 ++- .../Private/Tests/CesiumLoadTestSamples.cpp | 2 +- .../Private/Tests/CesiumSceneGeneration.cpp | 42 +++++++++++++------ .../Private/Tests/CesiumSceneGeneration.h | 2 +- 4 files changed, 36 insertions(+), 15 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index ccb210f06..75219dd05 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -49,7 +49,7 @@ bool TimeLoadingCommand::Update() { // Bind all play in editor pointers context.playContext.initForPlay(context.creationContext); - context.playContext.syncWorldPlayerCamera(); + context.playContext.syncWorldCamera(); if (setupStep) setupStep(context.playContext); @@ -155,6 +155,9 @@ bool RunLoadTest( gLoadTestContext.creationContext.refreshTilesets(); clearCacheDb(); + // Let the editor viewports see the same thing the test will + gLoadTestContext.creationContext.syncWorldCamera(); + // // Start async commands // diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index a0337d7c9..2f92defe9 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -54,7 +54,7 @@ bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { // Zoom way out context.startPosition = FVector(0, 0, 7240000.0); context.startRotation = FRotator(-90.0, 0.0, 0.0); - context.syncWorldPlayerCamera(); + context.syncWorldCamera(); context.pawn->SetActorLocation(context.startPosition); }; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 3b5bb0528..586563c55 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -7,6 +7,7 @@ #include "Tests/AutomationEditorCommon.h" #include "GameFramework/PlayerStart.h" +#include "LevelEditorViewport.h" #include "Cesium3DTileset.h" #include "CesiumGeoreference.h" @@ -99,18 +100,35 @@ void SceneGenerationContext::initForPlay( } } -void SceneGenerationContext::syncWorldPlayerCamera() { - assert(world->GetNumPlayerControllers() == 1); - - APlayerController* controller = world->GetFirstPlayerController(); - assert(controller); - - controller->ClientSetLocation(startPosition, startRotation); - - APlayerCameraManager* cameraManager = controller->PlayerCameraManager; - assert(cameraManager); - - cameraManager->SetFOV(startFieldOfView); +void SceneGenerationContext::syncWorldCamera() { + assert(GEditor); + + if (GEditor->IsPlayingSessionInEditor()) { + // If in PIE, set the player + assert(world->GetNumPlayerControllers() == 1); + + APlayerController* controller = world->GetFirstPlayerController(); + assert(controller); + + controller->ClientSetLocation(startPosition, startRotation); + + APlayerCameraManager* cameraManager = controller->PlayerCameraManager; + assert(cameraManager); + + cameraManager->SetFOV(startFieldOfView); + } else { + // If editing, set any viewports + for (FLevelEditorViewportClient* ViewportClient : + GEditor->GetLevelViewportClients()) { + if (ViewportClient == NULL) + continue; + ViewportClient->SetViewLocation(startPosition); + ViewportClient->SetViewRotation(startRotation); + if (ViewportClient->ViewportType == LVT_Perspective) + ViewportClient->ViewFOV = startFieldOfView; + ViewportClient->Invalidate(); + } + } } void createCommonWorldObjects(SceneGenerationContext& context) { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 9a63ec1eb..d85ec1635 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -36,7 +36,7 @@ struct SceneGenerationContext { void trackForPlay(); void initForPlay(SceneGenerationContext& creationContext); - void syncWorldPlayerCamera(); + void syncWorldCamera(); static FString testIonToken; static FString testGoogleUrl; From a8091d9f9bdf9f09d8a492cb12a9efbd3309108b Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:15:47 -0600 Subject: [PATCH 74/95] Add sunSky to the scene generation context (so we can adjust time zone) --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 5 ++++- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h | 2 ++ 2 files changed, 6 insertions(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 586563c55..87c21c7dc 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -69,6 +69,7 @@ bool SceneGenerationContext::areTilesetsDoneLoading() { } void SceneGenerationContext::trackForPlay() { + CesiumTestHelpers::trackForPlay(sunSky); CesiumTestHelpers::trackForPlay(georeference); CesiumTestHelpers::trackForPlay(pawn); @@ -82,6 +83,7 @@ void SceneGenerationContext::trackForPlay() { void SceneGenerationContext::initForPlay( SceneGenerationContext& creationContext) { world = GEditor->PlayWorld; + sunSky = CesiumTestHelpers::findInPlay(creationContext.sunSky); georeference = CesiumTestHelpers::findInPlay(creationContext.georeference); pawn = CesiumTestHelpers::findInPlay(creationContext.pawn); @@ -135,7 +137,8 @@ void createCommonWorldObjects(SceneGenerationContext& context) { context.world = FAutomationEditorCommonUtils::CreateNewMap(); - ACesiumSunSky* sunSky = context.world->SpawnActor(); + context.sunSky = context.world->SpawnActor(); + APlayerStart* playerStart = context.world->SpawnActor(); FSoftObjectPath objectPath( diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index d85ec1635..77993eb57 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -7,6 +7,7 @@ #include class UWorld; +class ACesiumSunSky; class ACesiumGeoreference; class AGlobeAwareDefaultPawn; class ACesium3DTileset; @@ -16,6 +17,7 @@ namespace Cesium { struct SceneGenerationContext { UWorld* world; + ACesiumSunSky* sunSky; ACesiumGeoreference* georeference; AGlobeAwareDefaultPawn* pawn; std::vector tilesets; From 58f04d5a2056da7eed0ac3ddcb2766a288c92c4b Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Thu, 5 Oct 2023 15:20:11 -0600 Subject: [PATCH 75/95] Set location time zones. Batch tests under GoogleTiles.X namespace --- .../Private/Tests/Google3dTilesLoadTest.cpp | 26 +++++++++++++++---- 1 file changed, 21 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 216ccc08b..62fa95c53 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -8,32 +8,33 @@ #include "Misc/AutomationTest.h" #include "Cesium3DTileset.h" +#include "CesiumSunSky.h" using namespace Cesium; IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesPompidou, - "Cesium.Performance.GoogleTilesPompidou", + "Cesium.Performance.GoogleTiles.Pompidou", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesChrysler, - "Cesium.Performance.GoogleTilesChrysler", + "Cesium.Performance.GoogleTiles.Chrysler", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesGuggenheim, - "Cesium.Performance.GoogleTilesGuggenheim", + "Cesium.Performance.GoogleTiles.Guggenheim", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesDeathValley, - "Cesium.Performance.GoogleTilesDeathValley", + "Cesium.Performance.GoogleTiles.DeathValley", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesTokyo, - "Cesium.Performance.GoogleTilesTokyo", + "Cesium.Performance.GoogleTiles.Tokyo", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) void setupForPompidou(SceneGenerationContext& context) { @@ -43,6 +44,9 @@ void setupForPompidou(SceneGenerationContext& context) { FRotator(-20.0, 0.0, 0.0), 60.0f); + context.sunSky->TimeZone = 2.0f; + context.sunSky->UpdateSun(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); @@ -57,6 +61,9 @@ void setupForChrysler(SceneGenerationContext& context) { FRotator(-15.0, 0.0, 0.0), 60.0f); + context.sunSky->TimeZone = -4.0f; + context.sunSky->UpdateSun(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); @@ -71,6 +78,9 @@ void setupForGuggenheim(SceneGenerationContext& context) { FRotator(-15.0, 90.0, 0.0), 60.0f); + context.sunSky->TimeZone = 2.0f; + context.sunSky->UpdateSun(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); @@ -85,6 +95,9 @@ void setupForDeathValley(SceneGenerationContext& context) { FRotator(0, 90.0, 0.0), 60.0f); + context.sunSky->TimeZone = -7.0f; + context.sunSky->UpdateSun(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); @@ -100,6 +113,9 @@ void setupForTokyo(SceneGenerationContext& context) { FRotator(-15, 300, 0.0), 60.0f); + context.sunSky->TimeZone = 9.0f; + context.sunSky->UpdateSun(); + ACesium3DTileset* tileset = context.world->SpawnActor(); tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); From 934e8033c1a852c62dde83dd1b7d6f2f24620fa0 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:07:20 -0600 Subject: [PATCH 76/95] Fix camera FOV not being set for generated scene --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 87c21c7dc..ad33ba988 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -37,6 +37,11 @@ void SceneGenerationContext::setCommonProperties( pawn->SetActorLocation(startPosition); pawn->SetActorRotation(startRotation); + + TInlineComponentArray cameras; + pawn->GetComponents(cameras); + for (UCameraComponent* cameraComponent : cameras) + cameraComponent->SetFieldOfView(startFieldOfView); } void SceneGenerationContext::refreshTilesets() { From eaa28eea42491590c41e2a44a48c9f6ffee70e04 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 10:16:56 -0600 Subject: [PATCH 77/95] Fixup heading --- Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 62fa95c53..2576bbc2d 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -110,7 +110,7 @@ void setupForTokyo(SceneGenerationContext& context) { context.setCommonProperties( FVector(139.7563178458, 35.652798383944, 525.62), FVector(0, 0, 0), - FRotator(-15, 300, 0.0), + FRotator(-15, -150, 0.0), 60.0f); context.sunSky->TimeZone = 9.0f; From 2cf8dc8439a7de64af8d1de8082eab2c8f4c304c Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:46:25 -0600 Subject: [PATCH 78/95] Add automatic screenshots for every test pass --- .../Private/Tests/CesiumLoadTestCore.cpp | 32 +++++++++++++++---- .../Private/Tests/CesiumLoadTestSamples.cpp | 6 ++-- 2 files changed, 28 insertions(+), 10 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 75219dd05..0dc7289b7 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -106,6 +106,20 @@ bool TimeLoadingCommand::Update() { return false; } +DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( + LoadTestScreenshotCommand, + FString, + screenshotName); +bool LoadTestScreenshotCommand::Update() { + UE_LOG(LogCesium, Display, TEXT("Requesting screenshot to /Saved/Screenshots/WindowsEditor...")); + + // Add a dash to separate name from unique index of screen shot + // Also add a dot to keep the base path logic from stripping away too much + FString requestFilename = screenshotName + "-" + "."; + FScreenshotRequest::RequestScreenshot(requestFilename, false, true); + return true; +} + DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( TestCleanupCommand, LoadTestContext&, @@ -177,25 +191,29 @@ bool RunLoadTest( // Wait until PIE is ready ADD_LATENT_AUTOMATION_COMMAND(WaitForPIECommand()); + // Wait to show distinct gap in profiler + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + std::vector::const_iterator it; for (it = testPasses.begin(); it != testPasses.end(); ++it) { const TestPass& pass = *it; - // Wait to show distinct gap in profiler - ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); - // Do our timing capture - FString loggingName = testName + ":" + pass.name; + FString loggingName = testName + "-" + pass.name; ADD_LATENT_AUTOMATION_COMMAND(TimeLoadingCommand( loggingName, gLoadTestContext, pass.setupStep, pass.verifyStep)); - } - // Wait to show distinct gap in profiler - ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(2.0f)); + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + + FString screenshotName = testName + "-" + pass.name; + ADD_LATENT_AUTOMATION_COMMAND(LoadTestScreenshotCommand(screenshotName)) + + ADD_LATENT_AUTOMATION_COMMAND(FWaitLatentCommand(1.0f)); + } // End play in editor ADD_LATENT_AUTOMATION_COMMAND(FEndPlayMapCommand()); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index 2f92defe9..a728a6ae1 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -36,7 +36,7 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForDenver, testPasses, 1024, 768); + return RunLoadTest(GetBeautifiedTestName(), setupForDenver, testPasses, 1024, 768); } bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { @@ -45,7 +45,7 @@ bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForGoogleplex, testPasses, 1280, 720); + return RunLoadTest(GetBeautifiedTestName(), setupForGoogleplex, testPasses, 1280, 720); } bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { @@ -90,7 +90,7 @@ bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Adjust", adjustCamera, verifyVisibleTiles}); return RunLoadTest( - GetTestName(), + GetBeautifiedTestName(), setupForMontrealPointCloud, testPasses, 512, From fbe56510f63638569e6290d223b0e9c23b76dc1d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:50:57 -0600 Subject: [PATCH 79/95] Fix formatting --- .../Private/Tests/CesiumLoadTestCore.cpp | 5 ++++- .../Private/Tests/CesiumLoadTestSamples.cpp | 14 ++++++++++++-- 2 files changed, 16 insertions(+), 3 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 0dc7289b7..23f720a30 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -111,7 +111,10 @@ DEFINE_LATENT_AUTOMATION_COMMAND_ONE_PARAMETER( FString, screenshotName); bool LoadTestScreenshotCommand::Update() { - UE_LOG(LogCesium, Display, TEXT("Requesting screenshot to /Saved/Screenshots/WindowsEditor...")); + UE_LOG( + LogCesium, + Display, + TEXT("Requesting screenshot to /Saved/Screenshots/WindowsEditor...")); // Add a dash to separate name from unique index of screen shot // Also add a dot to keep the base path logic from stripping away too much diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index a728a6ae1..c11fcd1e4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -36,7 +36,12 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetBeautifiedTestName(), setupForDenver, testPasses, 1024, 768); + return RunLoadTest( + GetBeautifiedTestName(), + setupForDenver, + testPasses, + 1024, + 768); } bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { @@ -45,7 +50,12 @@ bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - return RunLoadTest(GetBeautifiedTestName(), setupForGoogleplex, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForGoogleplex, + testPasses, + 1280, + 720); } bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { From e3a43621cd13285f1c768d7602e8680fddfcd1aa Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 11:52:23 -0600 Subject: [PATCH 80/95] Use pretty names for logging. Get rid of warm cache tests --- .../Private/Tests/Google3dTilesLoadTest.cpp | 44 +++++++++++++------ 1 file changed, 30 insertions(+), 14 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 2576bbc2d..8c05fd54a 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -123,48 +123,64 @@ void setupForTokyo(SceneGenerationContext& context) { context.tilesets.push_back(tileset); } -void refreshTilesets(SceneGenerationContext& context) { - context.refreshTilesets(); -} - bool FGoogleTilesPompidou::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForPompidou, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForPompidou, + testPasses, + 1280, + 720); } bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForChrysler, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForChrysler, + testPasses, + 1280, + 720); } bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForGuggenheim, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForGuggenheim, + testPasses, + 1280, + 720); } bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForDeathValley, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForDeathValley, + testPasses, + 1280, + 720); } bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshTilesets, nullptr}); - return RunLoadTest(GetTestName(), setupForTokyo, testPasses, 1280, 720); + return RunLoadTest( + GetBeautifiedTestName(), + setupForTokyo, + testPasses, + 1280, + 720); } #endif From aa14d79175aa2d601a5131142ee1868c3ce361dc Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 12:54:50 -0600 Subject: [PATCH 81/95] Add missing header --- Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp | 1 + 1 file changed, 1 insertion(+) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 23f720a30..3004df546 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -11,6 +11,7 @@ #include "Settings/LevelEditorPlaySettings.h" #include "Tests/AutomationCommon.h" #include "Tests/AutomationEditorCommon.h" +#include "UnrealClient.h" namespace Cesium { From aaccba412642b3be4339ed06b81a235a993b0d5e Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:08:32 -0600 Subject: [PATCH 82/95] Bump test timeout to 30 secs Useful when debugging --- Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp index 3004df546..7bc304c1c 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestCore.cpp @@ -71,8 +71,8 @@ bool TimeLoadingCommand::Update() { double testElapsedTime = timeMark - context.startMark; // The command is over if tilesets are loaded, or timed out - // Wait for a maximum of 20 seconds - const size_t testTimeout = 20; + // Wait for a maximum of 30 seconds + const size_t testTimeout = 30; bool tilesetsloaded = context.playContext.areTilesetsDoneLoading(); bool timedOut = testElapsedTime >= testTimeout; From 9a8a53be7472b02a7a94f35aaa97019d3fbeee30 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Fri, 6 Oct 2023 13:10:00 -0600 Subject: [PATCH 83/95] Fix starting orientations --- .../CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp | 8 ++++---- 1 file changed, 4 insertions(+), 4 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 8c05fd54a..40611a668 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -41,7 +41,7 @@ void setupForPompidou(SceneGenerationContext& context) { context.setCommonProperties( FVector(2.352200, 48.860600, 200), FVector(0, 0, 0), - FRotator(-20.0, 0.0, 0.0), + FRotator(-20.0, -90.0, 0.0), 60.0f); context.sunSky->TimeZone = 2.0f; @@ -58,7 +58,7 @@ void setupForChrysler(SceneGenerationContext& context) { context.setCommonProperties( FVector(-73.9752624659, 40.74697185903, 307.38), FVector(0, 0, 0), - FRotator(-15.0, 0.0, 0.0), + FRotator(-15.0, -90.0, 0.0), 60.0f); context.sunSky->TimeZone = -4.0f; @@ -75,7 +75,7 @@ void setupForGuggenheim(SceneGenerationContext& context) { context.setCommonProperties( FVector(-2.937, 43.2685, 150), FVector(0, 0, 0), - FRotator(-15.0, 90.0, 0.0), + FRotator(-15.0, 0.0, 0.0), 60.0f); context.sunSky->TimeZone = 2.0f; @@ -92,7 +92,7 @@ void setupForDeathValley(SceneGenerationContext& context) { context.setCommonProperties( FVector(-116.812278, 36.42, 300), FVector(0, 0, 0), - FRotator(0, 90.0, 0.0), + FRotator(0, 0.0, 0.0), 60.0f); context.sunSky->TimeZone = -7.0f; From 4e22ffd95dea18e0f9b6d9221275ced7aa0d9418 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:12:46 -0600 Subject: [PATCH 84/95] Move new unit tests to Cesium.Unit.X namespace --- .../Private/Tests/CesiumFeatureIdAttribute.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp | 2 +- .../CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp | 2 +- .../Private/Tests/CesiumMetadataConversions.spec.cpp | 2 +- .../Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp | 2 +- .../Private/Tests/CesiumOriginShiftComponent.spec.cpp | 2 +- .../Private/Tests/CesiumPrimitiveFeatures.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp | 2 +- Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp | 2 +- .../Private/Tests/CesiumPropertyTableProperty.spec.cpp | 2 +- 12 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp index b14391ac4..ace818666 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdAttribute.spec.cpp @@ -7,7 +7,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumFeatureIdAttributeSpec, - "Cesium.FeatureIdAttribute", + "Cesium.Unit.FeatureIdAttribute", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp index a70bea7b0..e28971251 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdSet.spec.cpp @@ -8,7 +8,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumFeatureIdSetSpec, - "Cesium.FeatureIdSet", + "Cesium.Unit.FeatureIdSet", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp index 9bb1f047f..b3ebd1971 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumFeatureIdTexture.spec.cpp @@ -7,7 +7,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumFeatureIdTextureSpec, - "Cesium.FeatureIdTexture", + "Cesium.Unit.FeatureIdTexture", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp index a21ee5be5..5d7b3b202 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumGlobeAnchor.spec.cpp @@ -8,7 +8,7 @@ BEGIN_DEFINE_SPEC( FCesiumGlobeAnchorSpec, - "Cesium.GlobeAnchor", + "Cesium.Unit.GlobeAnchor", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataConversions.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataConversions.spec.cpp index 90c0f4b39..89b21ff41 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataConversions.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataConversions.spec.cpp @@ -8,7 +8,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumMetadataConversionsSpec, - "Cesium.MetadataConversions", + "Cesium.Unit.MetadataConversions", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FCesiumMetadataConversionsSpec) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp index cf239f920..a9c43bfd5 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataPickingBlueprintLibrary.spec.cpp @@ -11,7 +11,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumMetadataPickingSpec, - "Cesium.MetadataPicking", + "Cesium.Unit.MetadataPicking", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp index b10c65557..94700accb 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumMetadataValue.spec.cpp @@ -8,7 +8,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumMetadataValueSpec, - "Cesium.MetadataValue", + "Cesium.Unit.MetadataValue", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FCesiumMetadataValueSpec) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp index 51e41e371..f7e0a678f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumOriginShiftComponent.spec.cpp @@ -15,7 +15,7 @@ BEGIN_DEFINE_SPEC( FCesiumOriginShiftComponentSpec, - "Cesium.OriginShiftComponent", + "Cesium.Unit.OriginShiftComponent", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp index cc28df267..ee885ecc4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPrimitiveFeatures.spec.cpp @@ -7,7 +7,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumPrimitiveFeaturesSpec, - "Cesium.PrimitiveFeatures", + "Cesium.Unit.PrimitiveFeatures", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp index ce538820f..d76a0812b 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyArray.spec.cpp @@ -6,7 +6,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumPropertyArraySpec, - "Cesium.PropertyArray", + "Cesium.Unit.PropertyArray", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FCesiumPropertyArraySpec) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp index 487a9da38..a589f438b 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTable.spec.cpp @@ -9,7 +9,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumPropertyTableSpec, - "Cesium.PropertyTable", + "Cesium.Unit.PropertyTable", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) Model model; diff --git a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp index a2bb04aa8..a9f136196 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumPropertyTableProperty.spec.cpp @@ -8,7 +8,7 @@ using namespace CesiumGltf; BEGIN_DEFINE_SPEC( FCesiumPropertyTablePropertySpec, - "Cesium.PropertyTableProperty", + "Cesium.Unit.PropertyTableProperty", EAutomationTestFlags::ApplicationContextMask | EAutomationTestFlags::ProductFilter) END_DEFINE_SPEC(FCesiumPropertyTablePropertySpec) From d3d61f0c60435e2ed330afa30077e7d19a14cc65 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:16:14 -0600 Subject: [PATCH 85/95] Remove google tests (moving to different branch) --- .../Private/Tests/CesiumLoadTestSamples.cpp | 19 ------------------- .../Private/Tests/CesiumSceneGeneration.cpp | 18 ------------------ .../Private/Tests/CesiumSceneGeneration.h | 2 -- 3 files changed, 39 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index c11fcd1e4..e44c82ed6 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -16,11 +16,6 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.SampleLoadDenver", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) -IMPLEMENT_SIMPLE_AUTOMATION_TEST( - FCesiumSampleLoadGoogleplex, - "Cesium.Performance.SampleLoadGoogleplex", - EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) - IMPLEMENT_SIMPLE_AUTOMATION_TEST( FCesiumSampleLoadMontrealPointCloud, "Cesium.Performance.SampleLoadMontrealPointCloud", @@ -44,20 +39,6 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { 768); } -bool FCesiumSampleLoadGoogleplex::RunTest(const FString& Parameters) { - - std::vector testPasses; - testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); - testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); - - return RunLoadTest( - GetBeautifiedTestName(), - setupForGoogleplex, - testPasses, - 1280, - 720); -} - bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { auto adjustCamera = [this](SceneGenerationContext& context) { diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index ad33ba988..051f63803 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -21,8 +21,6 @@ namespace Cesium { FString SceneGenerationContext::testIonToken( "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); -FString SceneGenerationContext::testGoogleUrl( - "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); void SceneGenerationContext::setCommonProperties( const FVector& origin, @@ -162,22 +160,6 @@ void createCommonWorldObjects(SceneGenerationContext& context) { pWorldSettings->bEnableWorldBoundsChecks = false; } -void setupForGoogleplex(SceneGenerationContext& context) { - - context.setCommonProperties( - FVector(-122.083969, 37.424492, 142.859116), - FVector(0, 0, 0), - FRotator(-25, 95, 0), - 90.0f); - - ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(SceneGenerationContext::testGoogleUrl); - tileset->SetTilesetSource(ETilesetSource::FromUrl); - tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); - - context.tilesets.push_back(tileset); -} - void setupForDenver(SceneGenerationContext& context) { context.setCommonProperties( diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index 77993eb57..f076d667f 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -41,13 +41,11 @@ struct SceneGenerationContext { void syncWorldCamera(); static FString testIonToken; - static FString testGoogleUrl; }; void createCommonWorldObjects(SceneGenerationContext& context); void setupForDenver(SceneGenerationContext& context); -void setupForGoogleplex(SceneGenerationContext& context); void setupForMontrealPointCloud(SceneGenerationContext& context); }; // namespace Cesium From 349aca5b30ac6c4987ea0cd451bfc0c29e9a54b2 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 10:37:58 -0600 Subject: [PATCH 86/95] Add googleplex test back in --- .../Private/Tests/Google3dTilesLoadTest.cpp | 47 +++++++++++++++++-- 1 file changed, 42 insertions(+), 5 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 40611a668..398177e36 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -12,6 +12,11 @@ using namespace Cesium; +namespace Cesium { +FString testGoogleUrl( + "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); +} + IMPLEMENT_SIMPLE_AUTOMATION_TEST( FGoogleTilesPompidou, "Cesium.Performance.GoogleTiles.Pompidou", @@ -37,6 +42,11 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.GoogleTiles.Tokyo", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +IMPLEMENT_SIMPLE_AUTOMATION_TEST( + FGoogleTilesGoogleplex, + "Cesium.Performance.GoogleTiles.Googleplex", + EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) + void setupForPompidou(SceneGenerationContext& context) { context.setCommonProperties( FVector(2.352200, 48.860600, 200), @@ -48,7 +58,7 @@ void setupForPompidou(SceneGenerationContext& context) { context.sunSky->UpdateSun(); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetUrl(Cesium::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Center Pompidou, Paris, France")); context.tilesets.push_back(tileset); @@ -65,7 +75,7 @@ void setupForChrysler(SceneGenerationContext& context) { context.sunSky->UpdateSun(); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetUrl(Cesium::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Chrysler Building, NYC")); context.tilesets.push_back(tileset); @@ -82,7 +92,7 @@ void setupForGuggenheim(SceneGenerationContext& context) { context.sunSky->UpdateSun(); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetUrl(Cesium::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Guggenheim Museum, Bilbao, Spain")); context.tilesets.push_back(tileset); @@ -99,7 +109,7 @@ void setupForDeathValley(SceneGenerationContext& context) { context.sunSky->UpdateSun(); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetUrl(Cesium::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel( TEXT("Zabriskie Point, Death Valley National Park, California")); @@ -117,12 +127,27 @@ void setupForTokyo(SceneGenerationContext& context) { context.sunSky->UpdateSun(); ACesium3DTileset* tileset = context.world->SpawnActor(); - tileset->SetUrl(Cesium::SceneGenerationContext::testGoogleUrl); + tileset->SetUrl(Cesium::testGoogleUrl); tileset->SetTilesetSource(ETilesetSource::FromUrl); tileset->SetActorLabel(TEXT("Tokyo Tower, Tokyo, Japan")); context.tilesets.push_back(tileset); } +void setupForGoogleplex(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-122.083969, 37.424492, 142.859116), + FVector(0, 0, 0), + FRotator(-25, 95, 0), + 90.0f); + + ACesium3DTileset* tileset = context.world->SpawnActor(); + tileset->SetUrl(Cesium::testGoogleUrl); + tileset->SetTilesetSource(ETilesetSource::FromUrl); + tileset->SetActorLabel(TEXT("Google Photorealistic 3D Tiles")); + + context.tilesets.push_back(tileset); +} + bool FGoogleTilesPompidou::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); @@ -183,4 +208,16 @@ bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { 720); } +bool FGoogleTilesGoogleplex::RunTest(const FString& Parameters) { + std::vector testPasses; + testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + + return RunLoadTest( + GetBeautifiedTestName(), + setupForGoogleplex, + testPasses, + 1280, + 720); +} + #endif From f52722dd832d7fa24badce81b372dfdfa52e508d Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:17:56 -0600 Subject: [PATCH 87/95] Update google key to latest from samples project --- Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index 398177e36..f94d28528 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -14,7 +14,7 @@ using namespace Cesium; namespace Cesium { FString testGoogleUrl( - "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCnRPXWDIj1LuX6OWIweIqZFHHoXVgdYss"); + "https://tile.googleapis.com/v1/3dtiles/root.json?key=AIzaSyCaIL-JEK2Tw9MMBVKSTIu8dPkwfzfqAbU"); } IMPLEMENT_SIMPLE_AUTOMATION_TEST( From 0b3e828345b5d25e60b8e2ff427e836c65353564 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 12:22:44 -0600 Subject: [PATCH 88/95] Update release-process.md for API keys --- Documentation/release-process.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/release-process.md b/Documentation/release-process.md index c1eea9dcc..3d8145e43 100644 --- a/Documentation/release-process.md +++ b/Documentation/release-process.md @@ -2,11 +2,14 @@ This is the process we follow when releasing a new version of Cesium for Unreal on GitHub and on the Unreal Engine Marketplace. -## Test the release candidate - +## Verify the code +* Update any hard coded API keys in the code + * Google3dTilesLoadTest.cpp, testGoogleUrl - Make sure matches samples project * Verify that the cesium-native submodule in the `extern` directory references the expected commit of cesium-native. Update it if necessary. Verify that CI has completed successfully for that commit of cesium-native. * Merge `ue4-main` into `ue5-main`. * Wait for CI to complete for the `ue4-main` and `ue5-main` branches. Verify that it does so successfully. + +## Test the release candidate * Remove all existing copies of the Cesium for Unreal plugin from the engine plugin directories on your system. On Windows this is usually `C:\Program Files\Epic Games\UE_4.26\Engine\Plugins\Marketplace`, `C:\Program Files\Epic Games\UE_4.27\Engine\Plugins\Marketplace`, and `C:\Program Files\Epic Games\UE_5.0\Engine\Plugins\Marketplace`. * Download the `UE4.27-AllPlatforms` or `UE4.26-AllPlatforms` for the `ue4-main` branch of cesium-unreal. Extract it to the appropriate Unreal Engine installation's engine plugins directory. * In the `ue5-main` branch, go to https://github.com/CesiumGS/cesium-unreal/actions and click the most recent build of the branch (it should be near the top). Scroll down to "Artifcats" and download the artifact that doesn't have an operating system in its name. It will also be the largest artifact. Extract it to `C:\Program Files\Epic Games\UE_5.0\Engine\Plugins\Marketplace` or equivalent. From a76fb1c506ece05235794618c0e805bcc473eada Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:06:40 -0600 Subject: [PATCH 89/95] Avoid unnecessary copy of ViewUpdateResult --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 20 +++++++++---------- 1 file changed, 10 insertions(+), 10 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index c502cdd4a..8eae33fd8 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2077,25 +2077,25 @@ void ACesium3DTileset::Tick(float DeltaTime) { CreateViewStateFromViewParameters(camera, unrealWorldToCesiumTileset)); } - Cesium3DTilesSelection::ViewUpdateResult result; + const Cesium3DTilesSelection::ViewUpdateResult* result; if (this->_captureMovieMode) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) - result = this->_pTileset->updateViewOffline(frustums); + result = &this->_pTileset->updateViewOffline(frustums); } else { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) - result = this->_pTileset->updateView(frustums, DeltaTime); + result = &this->_pTileset->updateView(frustums, DeltaTime); } - updateLastViewUpdateResultState(result); + updateLastViewUpdateResultState(*result); - removeCollisionForTiles(result.tilesFadingOut); + removeCollisionForTiles(result->tilesFadingOut); removeVisibleTilesFromList( _tilesToHideNextFrame, - result.tilesToRenderThisFrame); + result->tilesToRenderThisFrame); hideTiles(_tilesToHideNextFrame); _tilesToHideNextFrame.clear(); - for (Cesium3DTilesSelection::Tile* pTile : result.tilesFadingOut) { + for (Cesium3DTilesSelection::Tile* pTile : result->tilesFadingOut) { Cesium3DTilesSelection::TileRenderContent* pRenderContent = pTile->getContent().getRenderContent(); if (!this->UseLodTransitions || @@ -2105,16 +2105,16 @@ void ACesium3DTileset::Tick(float DeltaTime) { } } - showTilesToRender(result.tilesToRenderThisFrame); + showTilesToRender(result->tilesToRenderThisFrame); if (this->UseLodTransitions) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) - for (Cesium3DTilesSelection::Tile* pTile : result.tilesToRenderThisFrame) { + for (Cesium3DTilesSelection::Tile* pTile : result->tilesToRenderThisFrame) { updateTileFade(pTile, true); } - for (Cesium3DTilesSelection::Tile* pTile : result.tilesFadingOut) { + for (Cesium3DTilesSelection::Tile* pTile : result->tilesFadingOut) { updateTileFade(pTile, false); } } From 079819ce60f70859499d7693c356cdf119755119 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:11:51 -0600 Subject: [PATCH 90/95] Move location setup to samples .cpp --- .../Private/Tests/CesiumLoadTestSamples.cpp | 60 ++++++++++++++++++- .../Private/Tests/CesiumSceneGeneration.cpp | 60 ------------------- .../Private/Tests/CesiumSceneGeneration.h | 3 - 3 files changed, 58 insertions(+), 65 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp index e44c82ed6..a4ad7ebf2 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumLoadTestSamples.cpp @@ -7,6 +7,7 @@ #include "Misc/AutomationTest.h" #include "CesiumGltfComponent.h" +#include "CesiumIonRasterOverlay.h" #include "GlobeAwareDefaultPawn.h" using namespace Cesium; @@ -25,8 +26,64 @@ void refreshSampleTilesets(SceneGenerationContext& context) { context.refreshTilesets(); } -bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { +void setupForDenver(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-104.988892, 39.743462, 1798.679443), + FVector(0, 0, 0), + FRotator(-5.2, -149.4, 0), + 90.0f); + + // Add Cesium World Terrain + ACesium3DTileset* worldTerrainTileset = + context.world->SpawnActor(); + worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + worldTerrainTileset->SetIonAssetID(1); + worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); + + // Bing Maps Aerial overlay + UCesiumIonRasterOverlay* pOverlay = NewObject( + worldTerrainTileset, + FName("Bing Maps Aerial"), + RF_Transactional); + pOverlay->MaterialLayerKey = TEXT("Overlay0"); + pOverlay->IonAssetID = 2; + pOverlay->SetActive(true); + pOverlay->OnComponentCreated(); + worldTerrainTileset->AddInstanceComponent(pOverlay); + + // Aerometrex Denver + ACesium3DTileset* aerometrexTileset = + context.world->SpawnActor(); + aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + aerometrexTileset->SetIonAssetID(354307); + aerometrexTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + aerometrexTileset->SetMaximumScreenSpaceError(2.0); + aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); + + context.tilesets.push_back(worldTerrainTileset); + context.tilesets.push_back(aerometrexTileset); +} + +void setupForMontrealPointCloud(SceneGenerationContext& context) { + context.setCommonProperties( + FVector(-73.616526, 45.57335, 95.048859), + FVector(0, 0, 0), + FRotator(-90.0, 0.0, 0.0), + 90.0f); + + ACesium3DTileset* montrealTileset = + context.world->SpawnActor(); + montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); + montrealTileset->SetIonAssetID(28945); + montrealTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); + montrealTileset->SetMaximumScreenSpaceError(16.0); + montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); + + context.tilesets.push_back(montrealTileset); +} +bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); testPasses.push_back(TestPass{"Warm Cache", refreshSampleTilesets, nullptr}); @@ -40,7 +97,6 @@ bool FCesiumSampleLoadDenver::RunTest(const FString& Parameters) { } bool FCesiumSampleLoadMontrealPointCloud::RunTest(const FString& Parameters) { - auto adjustCamera = [this](SceneGenerationContext& context) { // Zoom way out context.startPosition = FVector(0, 0, 7240000.0); diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index 051f63803..f95640a6a 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -11,7 +11,6 @@ #include "Cesium3DTileset.h" #include "CesiumGeoreference.h" -#include "CesiumIonRasterOverlay.h" #include "CesiumSunSky.h" #include "GlobeAwareDefaultPawn.h" @@ -160,65 +159,6 @@ void createCommonWorldObjects(SceneGenerationContext& context) { pWorldSettings->bEnableWorldBoundsChecks = false; } -void setupForDenver(SceneGenerationContext& context) { - - context.setCommonProperties( - FVector(-104.988892, 39.743462, 1798.679443), - FVector(0, 0, 0), - FRotator(-5.2, -149.4, 0), - 90.0f); - - // Add Cesium World Terrain - ACesium3DTileset* worldTerrainTileset = - context.world->SpawnActor(); - worldTerrainTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - worldTerrainTileset->SetIonAssetID(1); - worldTerrainTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); - worldTerrainTileset->SetActorLabel(TEXT("Cesium World Terrain")); - - // Bing Maps Aerial overlay - UCesiumIonRasterOverlay* pOverlay = NewObject( - worldTerrainTileset, - FName("Bing Maps Aerial"), - RF_Transactional); - pOverlay->MaterialLayerKey = TEXT("Overlay0"); - pOverlay->IonAssetID = 2; - pOverlay->SetActive(true); - pOverlay->OnComponentCreated(); - worldTerrainTileset->AddInstanceComponent(pOverlay); - - // Aerometrex Denver - ACesium3DTileset* aerometrexTileset = - context.world->SpawnActor(); - aerometrexTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - aerometrexTileset->SetIonAssetID(354307); - aerometrexTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); - aerometrexTileset->SetMaximumScreenSpaceError(2.0); - aerometrexTileset->SetActorLabel(TEXT("Aerometrex Denver")); - - context.tilesets.push_back(worldTerrainTileset); - context.tilesets.push_back(aerometrexTileset); -} - -void setupForMontrealPointCloud(SceneGenerationContext& context) { - - context.setCommonProperties( - FVector(-73.616526, 45.57335, 95.048859), - FVector(0, 0, 0), - FRotator(-90.0, 0.0, 0.0), - 90.0f); - - ACesium3DTileset* montrealTileset = - context.world->SpawnActor(); - montrealTileset->SetTilesetSource(ETilesetSource::FromCesiumIon); - montrealTileset->SetIonAssetID(28945); - montrealTileset->SetIonAccessToken(SceneGenerationContext::testIonToken); - montrealTileset->SetMaximumScreenSpaceError(16.0); - montrealTileset->SetActorLabel(TEXT("Montreal Point Cloud")); - - context.tilesets.push_back(montrealTileset); -} - } // namespace Cesium #endif // #if WITH_EDITOR diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h index f076d667f..a6f0ca8b4 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.h @@ -45,9 +45,6 @@ struct SceneGenerationContext { void createCommonWorldObjects(SceneGenerationContext& context); -void setupForDenver(SceneGenerationContext& context); -void setupForMontrealPointCloud(SceneGenerationContext& context); - }; // namespace Cesium #endif // #if WITH_EDITOR From 502105d1195f36cbc531576b3ec1bb83b0eb1a92 Mon Sep 17 00:00:00 2001 From: Brian Langevin <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:13:45 -0600 Subject: [PATCH 91/95] Update release-process.md --- Documentation/release-process.md | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/Documentation/release-process.md b/Documentation/release-process.md index c1eea9dcc..864b591aa 100644 --- a/Documentation/release-process.md +++ b/Documentation/release-process.md @@ -2,11 +2,14 @@ This is the process we follow when releasing a new version of Cesium for Unreal on GitHub and on the Unreal Engine Marketplace. -## Test the release candidate - +## Verify the code +* Update any hard coded API keys in the code + * CesiumSceneGeneration.cpp, testIonToken - Make sure matches samples project * Verify that the cesium-native submodule in the `extern` directory references the expected commit of cesium-native. Update it if necessary. Verify that CI has completed successfully for that commit of cesium-native. * Merge `ue4-main` into `ue5-main`. * Wait for CI to complete for the `ue4-main` and `ue5-main` branches. Verify that it does so successfully. + +## Test the release candidate * Remove all existing copies of the Cesium for Unreal plugin from the engine plugin directories on your system. On Windows this is usually `C:\Program Files\Epic Games\UE_4.26\Engine\Plugins\Marketplace`, `C:\Program Files\Epic Games\UE_4.27\Engine\Plugins\Marketplace`, and `C:\Program Files\Epic Games\UE_5.0\Engine\Plugins\Marketplace`. * Download the `UE4.27-AllPlatforms` or `UE4.26-AllPlatforms` for the `ue4-main` branch of cesium-unreal. Extract it to the appropriate Unreal Engine installation's engine plugins directory. * In the `ue5-main` branch, go to https://github.com/CesiumGS/cesium-unreal/actions and click the most recent build of the branch (it should be near the top). Scroll down to "Artifcats" and download the artifact that doesn't have an operating system in its name. It will also be the largest artifact. Extract it to `C:\Program Files\Epic Games\UE_5.0\Engine\Plugins\Marketplace` or equivalent. From 018cd0012d84f7438ec9fd7160ab4bfb23ae7062 Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 13:55:02 -0600 Subject: [PATCH 92/95] Update ion token --- Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp index f95640a6a..6c8c98b57 100644 --- a/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp +++ b/Source/CesiumRuntime/Private/Tests/CesiumSceneGeneration.cpp @@ -19,7 +19,7 @@ namespace Cesium { FString SceneGenerationContext::testIonToken( - "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiI3NjU3OGE4Zi0xOGM4LTQ4NjYtODc4ZS02YWNkMDZmY2Y1M2YiLCJpZCI6MjU5LCJpYXQiOjE2OTA4Nzg3MjB9.uxePYJL59S4pG5aqJHb9goikVSO-Px6xA7kZH8oM1eM"); + "eyJhbGciOiJIUzI1NiIsInR5cCI6IkpXVCJ9.eyJqdGkiOiIyOGUxNjFmMy1mY2ZhLTQwMmEtYTNkYy1kZmExMGJjNjdlNTkiLCJpZCI6MjU5LCJpYXQiOjE2OTYxOTg1MTl9.QN5_xydinXOHF0xqy2zwQ5Hh4I5pVcLeMaqiJ9ZEsD4"); void SceneGenerationContext::setCommonProperties( const FVector& origin, From 962d4b2bdbfe84d7f93e7255c9bdc44995b7e60b Mon Sep 17 00:00:00 2001 From: Kevin Ring Date: Tue, 17 Oct 2023 09:24:30 +1100 Subject: [PATCH 93/95] result -> pResult --- .../CesiumRuntime/Private/Cesium3DTileset.cpp | 21 ++++++++++--------- 1 file changed, 11 insertions(+), 10 deletions(-) diff --git a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp index 8eae33fd8..cd64188f4 100644 --- a/Source/CesiumRuntime/Private/Cesium3DTileset.cpp +++ b/Source/CesiumRuntime/Private/Cesium3DTileset.cpp @@ -2077,25 +2077,25 @@ void ACesium3DTileset::Tick(float DeltaTime) { CreateViewStateFromViewParameters(camera, unrealWorldToCesiumTileset)); } - const Cesium3DTilesSelection::ViewUpdateResult* result; + const Cesium3DTilesSelection::ViewUpdateResult* pResult; if (this->_captureMovieMode) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateViewOffline) - result = &this->_pTileset->updateViewOffline(frustums); + pResult = &this->_pTileset->updateViewOffline(frustums); } else { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::updateView) - result = &this->_pTileset->updateView(frustums, DeltaTime); + pResult = &this->_pTileset->updateView(frustums, DeltaTime); } - updateLastViewUpdateResultState(*result); + updateLastViewUpdateResultState(*pResult); - removeCollisionForTiles(result->tilesFadingOut); + removeCollisionForTiles(pResult->tilesFadingOut); removeVisibleTilesFromList( _tilesToHideNextFrame, - result->tilesToRenderThisFrame); + pResult->tilesToRenderThisFrame); hideTiles(_tilesToHideNextFrame); _tilesToHideNextFrame.clear(); - for (Cesium3DTilesSelection::Tile* pTile : result->tilesFadingOut) { + for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { Cesium3DTilesSelection::TileRenderContent* pRenderContent = pTile->getContent().getRenderContent(); if (!this->UseLodTransitions || @@ -2105,16 +2105,17 @@ void ACesium3DTileset::Tick(float DeltaTime) { } } - showTilesToRender(result->tilesToRenderThisFrame); + showTilesToRender(pResult->tilesToRenderThisFrame); if (this->UseLodTransitions) { TRACE_CPUPROFILER_EVENT_SCOPE(Cesium::UpdateTileFades) - for (Cesium3DTilesSelection::Tile* pTile : result->tilesToRenderThisFrame) { + for (Cesium3DTilesSelection::Tile* pTile : + pResult->tilesToRenderThisFrame) { updateTileFade(pTile, true); } - for (Cesium3DTilesSelection::Tile* pTile : result->tilesFadingOut) { + for (Cesium3DTilesSelection::Tile* pTile : pResult->tilesFadingOut) { updateTileFade(pTile, false); } } From e288dc3085281e03d584eb708fc29d49904dbbce Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:27:41 -0600 Subject: [PATCH 94/95] Add warm cache tests --- .../Private/Tests/Google3dTilesLoadTest.cpp | 9 +++++++++ 1 file changed, 9 insertions(+) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index f94d28528..d0edc2481 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -47,6 +47,10 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.GoogleTiles.Googleplex", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +void googleWarmCacheSetup(SceneGenerationContext& context) { + context.refreshTilesets(); +} + void setupForPompidou(SceneGenerationContext& context) { context.setCommonProperties( FVector(2.352200, 48.860600, 200), @@ -163,6 +167,7 @@ bool FGoogleTilesPompidou::RunTest(const FString& Parameters) { bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", googleWarmCacheSetup, nullptr}); return RunLoadTest( GetBeautifiedTestName(), @@ -175,6 +180,7 @@ bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", googleWarmCacheSetup, nullptr}); return RunLoadTest( GetBeautifiedTestName(), @@ -187,6 +193,7 @@ bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", googleWarmCacheSetup, nullptr}); return RunLoadTest( GetBeautifiedTestName(), @@ -199,6 +206,7 @@ bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", googleWarmCacheSetup, nullptr}); return RunLoadTest( GetBeautifiedTestName(), @@ -211,6 +219,7 @@ bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { bool FGoogleTilesGoogleplex::RunTest(const FString& Parameters) { std::vector testPasses; testPasses.push_back(TestPass{"Cold Cache", nullptr, nullptr}); + testPasses.push_back(TestPass{"Warm Cache", googleWarmCacheSetup, nullptr}); return RunLoadTest( GetBeautifiedTestName(), From 60e28d259ac268912c6acd560ad39c2286a8c5ad Mon Sep 17 00:00:00 2001 From: Brian L <130494071+csciguy8@users.noreply.github.com> Date: Mon, 16 Oct 2023 16:30:30 -0600 Subject: [PATCH 95/95] Add #define for test window size (remove duplication) --- .../Private/Tests/Google3dTilesLoadTest.cpp | 27 ++++++++++--------- 1 file changed, 15 insertions(+), 12 deletions(-) diff --git a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp index d0edc2481..c8be8b6e8 100644 --- a/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp +++ b/Source/CesiumRuntime/Private/Tests/Google3dTilesLoadTest.cpp @@ -47,6 +47,9 @@ IMPLEMENT_SIMPLE_AUTOMATION_TEST( "Cesium.Performance.GoogleTiles.Googleplex", EAutomationTestFlags::EditorContext | EAutomationTestFlags::PerfFilter) +#define TEST_SCREEN_WIDTH 1280 +#define TEST_SCREEN_HEIGHT 720 + void googleWarmCacheSetup(SceneGenerationContext& context) { context.refreshTilesets(); } @@ -160,8 +163,8 @@ bool FGoogleTilesPompidou::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForPompidou, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { @@ -173,8 +176,8 @@ bool FGoogleTilesChrysler::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForChrysler, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { @@ -186,8 +189,8 @@ bool FGoogleTilesGuggenheim::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForGuggenheim, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { @@ -199,8 +202,8 @@ bool FGoogleTilesDeathValley::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForDeathValley, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { @@ -212,8 +215,8 @@ bool FGoogleTilesTokyo::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForTokyo, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } bool FGoogleTilesGoogleplex::RunTest(const FString& Parameters) { @@ -225,8 +228,8 @@ bool FGoogleTilesGoogleplex::RunTest(const FString& Parameters) { GetBeautifiedTestName(), setupForGoogleplex, testPasses, - 1280, - 720); + TEST_SCREEN_WIDTH, + TEST_SCREEN_HEIGHT); } #endif