From f1d9e7ae28bf0667487c939aa32b1ef833da80f4 Mon Sep 17 00:00:00 2001 From: Tommy Walton Date: Thu, 11 Nov 2021 12:55:06 -0800 Subject: [PATCH] Skybox hot reloading - fix black screen when running the editor for the first time with a clean cache (#5529) * Add a default fallback image when a StreamingImageAsset fails to load Signed-off-by: Tommy Walton * Don't release a missing/invalid texture reference in the skybox component. Hold on to the reference so that it can hot-reload Signed-off-by: Tommy Walton * Don't release a missing/invalid texture reference in the ibl component. Hold on to the reference so that it can hot-reload Signed-off-by: Tommy Walton * Use a different fallback image depending on the status of the asset. Including a setting to use a friendly image that is less obnoxious for anything that might have been missed in a release build Signed-off-by: Tommy Walton * Adding the stubbed in fallback textures Signed-off-by: Tommy Walton * Updated the seedlist for the RPI to include the fallback images. It only needs the default and the missing asset images, since the AP doesn't run in release builds, the asset status will always be unknown, not processing or failed to process, so if an asset is not bundled, it is just missing. Signed-off-by: Tommy Walton * Switched to GetAssetIdByPath and removed some tabs Signed-off-by: Tommy Walton --- .../Textures/Defaults/DefaultFallback.png | 3 + .../RPI/Assets/Textures/Defaults/Missing.png | 3 + .../Assets/Textures/Defaults/Processing.png | 3 + .../Textures/Defaults/ProcessingFailed.png | 3 + Gems/Atom/RPI/Assets/seedList.seed | 16 ++++++ .../Image/StreamingImageAssetHandler.h | 3 + .../Image/StreamingImageAssetHandler.cpp | 57 ++++++++++++++++++- .../Atom/RPI/Registry/atom_rpi.release.setreg | 9 +++ Gems/Atom/RPI/Registry/atom_rpi.setreg | 3 +- .../ImageBasedLightComponentController.cpp | 2 - .../SkyBox/HDRiSkyboxComponentController.cpp | 2 - 11 files changed, 97 insertions(+), 7 deletions(-) create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png create mode 100644 Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png create mode 100644 Gems/Atom/RPI/Registry/atom_rpi.release.setreg diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png b/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png new file mode 100644 index 0000000000..1352d14edf --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/DefaultFallback.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:fb91c050a829ff03b972202cf8c90034e4f252d972332224791d135c07d9d528 +size 796 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png new file mode 100644 index 0000000000..3e9bc68ea5 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Missing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:28c3cfd8958813b4b539738bfff589731da0aeec5b3376558f377da2ebe973ff +size 5455 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png new file mode 100644 index 0000000000..914499d6e7 --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/Processing.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:8a0935be7347d695ed1716d030b5bae68153a88239b0ff15f67f900ac90be442 +size 5038 diff --git a/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png new file mode 100644 index 0000000000..558b16b96e --- /dev/null +++ b/Gems/Atom/RPI/Assets/Textures/Defaults/ProcessingFailed.png @@ -0,0 +1,3 @@ +version https://git-lfs.github.com/spec/v1 +oid sha256:bb243cd6d6414b4e95eab919fa94193b57825902b8d09f40ce3f334d829e74e2 +size 6286 diff --git a/Gems/Atom/RPI/Assets/seedList.seed b/Gems/Atom/RPI/Assets/seedList.seed index 300092e6c3..622638d698 100644 --- a/Gems/Atom/RPI/Assets/seedList.seed +++ b/Gems/Atom/RPI/Assets/seedList.seed @@ -24,6 +24,22 @@ + + + + + + + + + + + + + + + + diff --git a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h index 3f4e15744a..b3b62cbc31 100644 --- a/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h +++ b/Gems/Atom/RPI/Code/Include/Atom/RPI.Reflect/Image/StreamingImageAssetHandler.h @@ -25,6 +25,9 @@ namespace AZ const Data::Asset& asset, AZStd::shared_ptr stream, const Data::AssetFilterCB& assetLoadFilterCB) override; + + // Return a default fallback image if an asset is missing + Data::AssetId AssetMissingInCatalog(const Data::Asset& /*asset*/) override; }; } } diff --git a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp index fa39820329..fd04635da3 100644 --- a/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp +++ b/Gems/Atom/RPI/Code/Source/RPI.Reflect/Image/StreamingImageAssetHandler.cpp @@ -7,6 +7,8 @@ */ #include +#include +#include namespace AZ { @@ -40,5 +42,56 @@ namespace AZ return loadResult; } - } -} + + Data::AssetId StreamingImageAssetHandler::AssetMissingInCatalog(const Data::Asset& asset) + { + // Find out if the asset is missing completely, or just still processing + // and escalate the asset to the top of the list + AzFramework::AssetSystem::AssetStatus missingAssetStatus; + AzFramework::AssetSystemRequestBus::BroadcastResult( + missingAssetStatus, &AzFramework::AssetSystem::AssetSystemRequests::GetAssetStatusById, asset.GetId().m_guid); + + // Determine which fallback image to use + const char* relativePath = "textures/defaults/defaultfallback.png.streamingimage"; + + bool useDebugFallbackImages = true; + if (auto settingsRegistry = AZ::SettingsRegistry::Get(); settingsRegistry != nullptr) + { + settingsRegistry->GetObject(useDebugFallbackImages, "/O3DE/Atom/RPI/UseDebugFallbackImages"); + } + + if (useDebugFallbackImages) + { + switch (missingAssetStatus) + { + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Queued: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiling: + relativePath = "textures/defaults/processing.png.streamingimage"; + break; + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Failed: + relativePath = "textures/defaults/processingfailed.png.streamingimage"; + break; + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Missing: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Unknown: + case AzFramework::AssetSystem::AssetStatus::AssetStatus_Compiled: + relativePath = "textures/defaults/missing.png.streamingimage"; + break; + } + } + + // Make sure the fallback image has been processed + AzFramework::AssetSystem::AssetStatus status = AzFramework::AssetSystem::AssetStatus_Unknown; + AzFramework::AssetSystemRequestBus::BroadcastResult( + status, &AzFramework::AssetSystemRequestBus::Events::CompileAssetSync, relativePath); + + // Return the asset id of the fallback image + Data::AssetId assetId{}; + bool autoRegisterIfNotFound = false; + Data::AssetCatalogRequestBus::BroadcastResult( + assetId, &Data::AssetCatalogRequestBus::Events::GetAssetIdByPath, relativePath, + azrtti_typeid(), autoRegisterIfNotFound); + + return assetId; + } + } // namespace RPI +} // namespace AZ diff --git a/Gems/Atom/RPI/Registry/atom_rpi.release.setreg b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg new file mode 100644 index 0000000000..72fb4f01e8 --- /dev/null +++ b/Gems/Atom/RPI/Registry/atom_rpi.release.setreg @@ -0,0 +1,9 @@ +{ + "O3DE": { + "Atom": { + "RPI": { + "UseDebugFallbackImages": false + } + } + } +} diff --git a/Gems/Atom/RPI/Registry/atom_rpi.setreg b/Gems/Atom/RPI/Registry/atom_rpi.setreg index bcbade5d38..9f3cacd1a9 100644 --- a/Gems/Atom/RPI/Registry/atom_rpi.setreg +++ b/Gems/Atom/RPI/Registry/atom_rpi.setreg @@ -17,7 +17,8 @@ "DynamicDrawSystemDescriptor": { "DynamicBufferPoolSize": 50331648 // 3 * 16 * 1024 * 1024 (for 3 frames) } - } + }, + "UseDebugFallbackImages": true } } } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp index 6ea7580fc6..73cfd53c21 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/ImageBasedLights/ImageBasedLightComponentController.cpp @@ -163,8 +163,6 @@ namespace AZ return true; } } - // If this asset didn't load or isn't a cubemap, release it. - configAsset.Release(); return false; } diff --git a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp index 171c5e417f..7bf6237c1a 100644 --- a/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp +++ b/Gems/AtomLyIntegration/CommonFeatures/Code/Source/SkyBox/HDRiSkyboxComponentController.cpp @@ -196,8 +196,6 @@ namespace AZ } else { - // If this asset didn't load or isn't a cubemap, release it. - m_configuration.m_cubemapAsset.Release(); m_featureProcessorInterface->SetCubemap(nullptr); } }