Files
UnrealEngineUWP/Engine/Source/Developer/Virtualization/Private/VirtualizationManager.h

360 lines
17 KiB
C
Raw Normal View History

// Copyright Epic Games, Inc. All Rights Reserved.
#pragma once
#include "Compression/CompressedBuffer.h"
#include "HAL/CriticalSection.h"
#include "Logging/LogMacros.h"
#include "Templates/UniquePtr.h"
#include "Virtualization/VirtualizationSystem.h"
class IConsoleObject;
class FOutputDevice;
struct FAnalyticsEventAttribute;
/**
* Configuring the backend hierarchy
*
* The [Core.ContentVirtualization] section can contain a string 'BackendGraph' which will set with the name of
* the backend graph, if not set then the default 'ContentVirtualizationBackendGraph_None' will be used instead.
* This value can also be overridden from the command line by using 'BackendGraph=FooBar' where FooBar is the
* name of the graph.
*
* The first entry in the graph to be parsed will be the 'Hierarchy' which describes which backends should be
* mounted and in which order. For example 'Hierarchy=(Entry=Foo, Entry=Bar)' which should mount two backends
* 'Foo' and 'Bar' in that order.
*
* Each referenced backend in the hierarchy will then require it's own entry in the graph where the key will be
* it's name in the hierarchy and the value a string describing how to set it up.
* The value must contain 'Type=X' where X is the name used to find the correct IVirtualizationBackendFactory
* to create the backend with.
* Once the backend is created then reset of the string will be passed to it, so that additional customization
* can be extracted. Depending on the backend implementation these values may or may not be required.
*
* Example graph:
* [ContentVirtualizationBackendGraph_Example]
* Hierarchy=(Entry=MemoryCache, Entry=NetworkShare)
* MemoryCache=(Type=InMemory)
* NetworkShare=(Type=FileSystem, Path="\\path\to\somewhere")
*
* The graph is named 'ContentVirtualizationBackendGraph_Example'.
* The hierarchy contains two entries 'InMemory' and 'NetworkShare' to be mounted in that order
* MemoryCache creates a backend of type 'InMemory' and has no additional customization
* NetworkShare creates a backend of type 'FileSystem' and provides an additional path, the filesystem backend would
* fatal error without this value.
*/
/**
* Filtering
*
* By default all packages in a project can be virtualized once the system has been enabled. The can be
* overridden by the filtering system, either by excluding specific packages/directories, or by changing
* the default so that no package will be virtualized except packages/directories that have been
* specifically marked as to be virtualized.
*
* Note that the filtering is applied when a package is saved and stored as meta data in the FPackageTrailer.
* This means that you can scan your package files and reason about the behavior of the payloads but also
* means that if you change your project filtering rules that packages have to be re-saved in order for the
* filtering to be applied.
*
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
* @see ShouldVirtualizePackage or ShouldVirtualize for implementation details.
*
* Basic Setup:
*
* [Core.VirtualizationModule]
* FilterMode=OptIn/OptOut The general mode to be applied to all packages. With 'OptIn' packages will
* not be virtualized unless their path is included via VirtualizationFilterSettings.
* With 'OptOut' all packages will be virtualized unless excluded via
* VirtualizationFilterSettings [Default=OptOut]
* FilterMapContent=True/False When true any payload stored in a .umap or _BuildData.uasset file will be
* excluded from virtualization [Default=true]
*
* PackagePath Setup:
*
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
* In addition to the default filtering mode set above, payloads stored in packages can be filtered based on the
* package path. This allows a package to be including in the virtualization process or excluded from it.
*
* Note that these paths will be stored in the ini files under the Saved directory. To remove a path make sure to
* use the - syntax to remove the entry from the array, rather than removing the line itself. Otherwise it will
* persist until the saved config file has been reset.
*
* [/Script/Virtualization.VirtualizationFilterSettings]
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
* +ExcludePackagePaths="/MountPoint/PathToExclude/" Excludes any package found under '/MountPoint/PathToExclude/' from the virtualization process
* +ExcludePackagePaths="/MountPoint/PathTo/ThePackageToExclude" Excludes the specific package '/MountPoint/PathTo/ThePackageToExclude' from the virtualization process
* +IncludePackagePaths="/MountPoint/PathToInclude/" Includes any package found under '/MountPoint/PathToInclude/' in the virtualization process
* +IncludePackagePaths="/MountPoint/PathTo/ThePackageToInclude" Includes the specific package '/MountPoint/PathTo/ThePackageToInclude' in the virtualization process
*/
/*
* FVirtualizationManager
*
* Ini file setup:
*
* EnablePayloadVirtualization [bool]: When true the virtualization process will be enabled (usually when a package is submitted
to revision control. [Default=true]
* EnableCacheOnPull [bool]: When true payloads will be pushed to cached storage after being pulled from persistent
* storage. [Default=true]
* EnableCacheOnPush [bool]: When true payloads will be pushed to cached storage right before being pushed to persistent
* storage. [Default=true]
* MinPayloadLength [int64]: The minimum length (in bytes) that a payload must reach before it can be considered for
* virtualization. Use this to strike a balance between disk space and the number of smaller
payloads in your project being virtualized. [Default=0]
* BackendGraph [string]: The name of the backend graph to use. The default graph has no backends and effectively
disables the system. It is expected that a project will define the graph that it wants
and then set this option [Default=ContentVirtualizationBackendGraph_None]
* VirtualizationProcessTag [string]: The tag to be applied to any set of packages that have had the virtualization process run
* on them. Typically this means appending the tag to the description of a changelist of
* packages. This value can be set to an empty string. [Default="#virtualized"]
* AllowSubmitIfVirtualizationFailed [bool]: Revision control submits that trigger the virtualization system can either allow or block
* the submit if the virtualization process fails based on this value. True will allow a
* submit with an error to continue and false will block the submit. Note that by error we mean
* that the packages were not virtualized, not that bad data was produced. [Default=false]
* LazyInitConnections [bool]: When true, backends will not attempt to connect to their services until actually required.
* This can remove lengthy connection steps from the process init phase and then only connect
* if we actually need that service. Note that if this is true then the connection can come from
* any thread, so custom backend code will need to take that into account. [Default=false]
*/
namespace UE::Virtualization
{
class IVirtualizationBackend;
class IVirtualizationBackendFactory;
class FPullRequestCollection;
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
/** The default mode of filtering to use with package paths that do not match entries in UVirtualizationFilterSettings */
enum class EPackageFilterMode : uint8
{
/** Packages will be virtualized by default and must be opted out by the use of UVirtualizationFilterSettings::ExcludePackagePaths */
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
OptOut = 0,
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
/** Packages will not be virtualized by default and must be opted in by the user of UVirtualizationFilterSettings::IncludePackagePaths */
OptIn
};
/** Attempt to convert a string buffer to EPackageFilterMode */
bool LexTryParseString(EPackageFilterMode& OutValue, FStringView Buffer);
/** This is used as a wrapper around the various potential back end implementations.
The calling code shouldn't need to care about which back ends are actually in use. */
class FVirtualizationManager final : public IVirtualizationSystem
{
public:
using FRegistedFactories = TMap<FName, IVirtualizationBackendFactory*>;
using FBackendArray = TArray<IVirtualizationBackend*>;
FVirtualizationManager();
virtual ~FVirtualizationManager();
private:
/* IVirtualizationSystem implementation */
virtual bool Initialize(const FInitParams& InitParams) override;
virtual bool IsEnabled() const override;
virtual bool IsPushingEnabled(EStorageType StorageType) const override;
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
virtual EPayloadFilterReason FilterPayload(const UObject* Owner) const override;
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
virtual bool AllowSubmitIfVirtualizationFailed() const override;
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
virtual bool PushData(TArrayView<FPushRequest> Requests, EStorageType StorageType) override;
virtual bool PullData(TArrayView<FPullRequest> Requests) override;
virtual EQueryResult QueryPayloadStatuses(TArrayView<const FIoHash> Ids, EStorageType StorageType, TArray<EPayloadStatus>& OutStatuses) override;
Submitting packages on projects with virtualization enabled is much faster when none of the payloads actually needs to be virtualized. #rb PJ.Kack #rnx #preflight 61a795773c29b3cf13cd8250 ### PackageSubmissionChecks - Under the old model submitting a large number of packages could be very slow as each package would check each payload that it owns and is currently stored locally one at a time. For the source control backend this created quite a large overhead even when all of the payloads were already virtualized. - Now we do a pass over the submitted files to find all valid packages that have package trailers with locally stored payloads, gather the payloads into a single list and then query that in one large batch. - Once we find which payloads are not in permanent storage (note that in the case where a project is using multiple permanent storage solutions, if a payload is missing in one backend it counts as not being in permanent storage) we then attempt to virtualized them. - Only after all of this is done will we create the truncated copy of each package and then append the updated trailer to each one. In theory doing it in this order this might slightly increase the change of submit failures that occur after virtualization that result in a package never being submitted and orphaned payloads being added to permanent storage, but this will always be a risk. - Added an assert to fire if we detect a trailer with some virtualized and some local payloads. This should be a supported feature but needs proper testing first before we can allow it. With out current project settings no project should actually encounter this scenario. - To make the code easier to follow we now early out of the entire check when errors are encountered. - Added logging at various stages in the process to help show the user that something is happening and make problems easier to identify in the future. - Notes -- There is a lot of handling of invalid FPayloads. This is because it is currently possible to add empty payloads to the trailer which is inefficient and wastes space. The trailer will be modified to reject empty payloads in a future update at which point a lot of this handling can be removed. -- This could've also been solved by not fully rehydrating a package on save by the end user, which will be added as a project setting in a future piece of work, but this approach will solve the edge case when the user does have a large amount of hydrated packages which contain payloads that are already virtualized so it was better to fix that now while we have good test cases for it. -- We still have scaling problems with large number of package being submitted that do have payloads that need to be virtualized, this will be fixed by extending IVirtualizationSystem::Push to also accept batches of payloads in future work. -- OnPrePackageSubmission could be broken up into smaller chunks to make the code easier to follow. This will be done after the batch payload submission work is done. ### VirtualizationSystem - EStorageType has been promoted to enum class. - Added a new enum FPayloadStatus to be used when querying if a payload exists in a backend storage system or not. - Add a new method ::DoPayloadsExist which allows the caller to query if one or more payloads exists in the given backend storage system. ### VirtualizationManager - Implemented ::DoPayloadsExist. First we get the results from each backend in the storage system (which return as true or false from each backend) then total how many backends found the payload in order to set the correct status. ### IVirtualizationBackend - ::DoesPayloadExist which queries the existence of a single payload has been added to the interface. Most backends already implemented this for private use and if so have had their implementation renamed to match this. - Also added ::DoPayloadsExist which takes a batch of FpayloadIdsto query. Some backends can deal with a batch of payload ids much more efficiently than one at a time, although the default implementation does call ::DoesPayloadExist for each requested payload. -- The default implementation prevents every backend from needing to implement the same for loop but does allow backends that can gain from batching to override it. ### VirtualizationSourceControlBackend - This backend does override ::DoPayloadsExist and implements it's own version as it tends to perform very poorly when not operating on larger batches. - In this case ::DoesPayloadExist calls back to ::DoPayloadsExist to check each payload rather than implement as specific version. ### PackageTrailer - The trailer can now be queries to request how many payloads of a given type it contains #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18339847 in //UE5/Release-5.0/... via CL 18339852 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v895-18170469) [CL 18339859 by paul chipchase in ue5-release-engine-test branch]
2021-12-01 11:13:31 -05:00
virtual FVirtualizationResult TryVirtualizePackages(TConstArrayView<FString> PackagePaths, EVirtualizationOptions Options) override;
virtual FRehydrationResult TryRehydratePackages(TConstArrayView<FString> PackagePaths, ERehydrationOptions Options) override;
virtual ERehydrationResult TryRehydratePackages(TConstArrayView<FString> PackagePaths, uint64 PaddingAlignment, TArray<FText>& OutErrors, TArray<FSharedBuffer>& OutPackages, TArray<FRehydrationInfo>* OutInfo) override;
virtual void DumpStats() const override;
virtual FPayloadActivityInfo GetAccumualtedPayloadActivityInfo() const override;
Add some basic profile data to Mirage to make it easier for people to see when payloads are being pushed to or pulled from the various backends. #rb Per.Larsson #rnx * VirtualizationManager - Add method ::IsEnabled which allows the caller to poll if content virtualization is enabled or not. - Add method ::GetPayloadActivityInfo to return profiling data - Added a new Profiling namespace containing all of the profiling code. -- The idea is to try and keep all profiling data contained in the virtualization manager and not require the backends to be aware of it. - The actual pull/push operations have been moved to new private methods ::TryPushDataToBackend and ::PullDataFromBackend, by limiting the scolpe of where the actual operation occur makes it easier to add the profiling code. - We use the cooking stats system for recording our profiling data. Currently this adds no real value and we could've implemented our own but longer term this code might get hooked into FCookStatsManager:: CookStatsCallbacks to add it to our telemetry systems and this will be easier to do if it is already in the cooking stats formats. * SVirtualizationStaticIndicator - The widget is based on SDDCStatusIndicator for the DDC and is placed just before it in the UI. - The widget will only be shown if the content virtualization system is enabled, so functions as an easy way to check that (maybe in the future it can be on all the time in which case we'd need the widget to reflect when the systems are disabled) - Currently shows a green down arrow when a payload has been pulled and a green up arrow when a payload has been pushed. - The tool tip shown on mouse over will show the total data sizes pulled and pushed from the backends. #preflight 60b87c34ae46a100017d5334 [CL 16544645 by paul chipchase in ue5-main branch]
2021-06-03 04:35:17 -04:00
virtual void GetPayloadActivityInfo( GetPayloadActivityInfoFuncRef ) const override;
virtual void GatherAnalytics(TArray<FAnalyticsEventAttribute>& Attributes) const override;
virtual FOnNotification& GetNotificationEvent() override
{
return NotificationEvent;
}
private:
void ApplySettingsFromConfigFiles(const FConfigFile& ConfigFile);
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
void ApplySettingsFromFromCmdline();
void ApplySettingsFromCVar();
void ApplyDebugSettingsFromFromCmdline();
void RegisterConsoleCommands();
void OnUpdateDebugMissBackendsFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice);
void OnUpdateDebugMissChanceFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice);
void OnUpdateDebugMissCountFromConsole(const TArray<FString>& Args, FOutputDevice& OutputDevice);
void UpdateBackendDebugState();
bool ShouldDebugDisablePulling(FStringView BackendConfigName) const;
bool ShouldDebugFailPulling();
void MountBackends(const FConfigFile& ConfigFile);
void ParseHierarchy(const FConfigFile& ConfigFile, const TCHAR* GraphName, const TCHAR* HierarchyKey, const TCHAR* LegacyHierarchyKey, const FRegistedFactories& FactoryLookupTable, FBackendArray& PushArray);
bool CreateBackend(const FConfigFile& ConfigFile, const TCHAR* GraphName, const FString& ConfigEntryName, const FRegistedFactories& FactoryLookupTable, FBackendArray& PushArray);
void AddBackend(TUniquePtr<IVirtualizationBackend> Backend, FBackendArray& PushArray);
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
void EnsureBackendConnections();
void CachePayloads(TArrayView<FPushRequest> Requests, const IVirtualizationBackend* BackendSource);
bool TryCacheDataToBackend(IVirtualizationBackend& Backend, TArrayView<FPushRequest> Requests);
Packages submitted from the editor together will now virtualize their payloads in a single batch rather than one at a time. #rb PJ.Kack #jira UE-136126 #rnx #preflight ### VirtualizationSystem - Added a new overload for Push to VirtualizationSystem that takes an array of FPushRequest, which is a new structure representing a single payload request. - Filtering by package name is currently disabled, this is because the API has been forced into changing and passing the package name in via a FString rather than FPackagePath which means we would need to be more careful. This will be done in a future submit. - The backend interface has been extended to also have a batch version of PushData, by default this will attempt to submit each request one at a time so payloads don't have to try and implement a batched version if there is no need. - The context being passed with a payload when being pushed has been changed from FPackagePath to FString due to include order issues, as the FPackagePath lives in CoreUObject and the API for virtualization lives in Core. Additionally in the future the payloads might not be owned by a package (there is nothing specifically enforcing this) so the context being a string makes more sense. - NOTE: Due to the context change we currently no longer support the filtering feature, which allows for payloads belonging to packages under specific directories to be excluded from virtualization. This is something that will be solved in a future submit. ### SourceControlBackend - Now that we can submit multiple payloads in the same submit, the CL description has been changed slightly. We will now print a list of payload identifiers -> the package trying to submit that payload. This will only tell the users which package originally caused the payload to submit. If a user submits a new package at a later date that contains the same payload we will not be updating the description. ### PackageSubmissionChecks - Converted the submission process to use the new batch push operation in VirtualizationSystem. -- This means that we do a single push and then have to update the package trailers to convert the now pushed payloads from local to virtualized. - Added new define UE_PRECHECK_PAYLOAD_STATUS that makes it easy to toggle off the checks to see which payloads need to be submitted to the persistent backend. This is useful to test if it actually helps speed up the overall operations or if it is faster to just perform the batch push operations on all payloads and check the return values. -- The hope is that over time the submission processes will become fast enough that we can remove the precheck. - Fixed up logging to not always assume more than one package or payload. ### General Notes - Errors and logging is now a bit more vague as we often not just report that X payloads failed etc rather than specific payload identifiers. This probably doesn't affect the user too much since those identifiers as fairly meaningless to them anyway. - The source control submission could be further optimized by first checking the status of the files in thge depot and only then creating/switching workspace etc. - As currently written, we need to load all of the payloads into memory, then the backends will do what they need (in the case of source control this results in the payloads being written to disk then submitted) which could create quite a large memory spike when submitting a large number of packages. -- One solution would be to change the batch push API to take a "payload provider" interface and have the payloads requested as needed rather than passing in the FCompressedBuffer directly. This would let us immediately write the payload to disk for submission then discard it from memory, preventing larger spikes. Although it could cause overhead if there are multiple backends being submitted to. Internally we are unlikely to have more than one backend per storage solution so maybe we should just make it a config option? #ROBOMERGE-AUTHOR: paul.chipchase #ROBOMERGE-SOURCE: CL 18403735 in //UE5/Release-5.0/... via CL 18403737 #ROBOMERGE-BOT: STARSHIP (Release-Engine-Staging -> Release-Engine-Test) (v896-18170469) [CL 18403738 by paul chipchase in ue5-release-engine-test branch]
2021-12-08 02:19:42 -05:00
bool TryPushDataToBackend(IVirtualizationBackend& Backend, TArrayView<FPushRequest> Requests);
void PullDataFromAllBackends(TArrayView<FPullRequest> Requests);
void PullDataFromBackend(IVirtualizationBackend& Backend, TArrayView<FPullRequest> Requests);
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
bool ShouldVirtualizeAsset(const UObject* Owner) const;
/**
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
* Determines if a package path should be virtualized or not based on any exclusion/inclusion patterns
* that might have been set in UVirtualizationFilterSettings.
* If the path does not match any pattern set in UVirtualizationFilterSettings then use the default
* FilterMode to determine if the payload should be virtualized or not.
*
* @param PackagePath The path of the package to check. This can be empty which would indicate that
* a payload is not owned by a specific package.
* @return True if the package should be virtualized and false if the package path is
* excluded by the projects current filter set up.
*/
bool ShouldVirtualizePackage(const FPackagePath& PackagePath) const;
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
/**
* Determines if a package should be virtualized or not based on the given content.
* If the context can be turned into a package path then ::ShouldVirtualizePackage
* will be used instead.
* If the context is not a package path then we use the default FilterMode to determine
* if the payload should be virtualized or not.
*
* @return True if the context should be virtualized and false if not.
*/
bool ShouldVirtualize(const FString& Context) const;
/** Determines if the default filtering behavior is to virtualize a payload or not */
bool ShouldVirtualizeAsDefault() const;
void BroadcastEvent(TConstArrayView<FPullRequest> Ids, ENotification Event);
private:
// The following members are set from the config file
/** Are packages allowed to be virtualized when submitted to source control. Defaults to true. */
bool bAllowPackageVirtualization;
enum ECachingPolicy
{
/** Never push payloads to cached storage */
None = 0,
/** Cache payloads after they have been pulled from persistent storage */
CacheOnPull = 1 << 0,
/** Cache payloads right before they are pushed to persistent storage */
CacheOnPush = 1 << 1,
AlwaysCache = CacheOnPull | CacheOnPush
};
FRIEND_ENUM_CLASS_FLAGS(ECachingPolicy);
/** A bitfield describing when we push payloads to cached storage. */
ECachingPolicy CachingPolicy;
/** The minimum length for a payload to be considered for virtualization. Defaults to 0 bytes. */
int64 MinPayloadLength;
/** The name of the backend graph to load from the config ini file that will describe the backend hierarchy */
FString BackendGraphName;
/** The tag that will be returned when the virtualization process has run, commonly used to post fix changelist descriptions */
FString VirtualizationProcessTag;
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
/** The default filtering mode to apply if a payload is not matched with an option in UVirtualizationFilterSettings */
EPackageFilterMode FilteringMode;
Allow the virtualization of assets to be opt in, as well as opt out. This would allow a project to selectively turn on virtualization for specific locations or plugins rather than for the whole project by default. #rb PJ.Kack #jira UE-133473 #preflight 620bf6ae483ff0ae5ec22257 ### VirtualizationManager - Added EPackageFilterMode that can be set via [Core.ContentVirtualization] in the config file to control the default virtualization behavior. -- When set to EPackageFilterMode::OptOut(the default) all package paths will virtualize unless excluded by a pattern in UVirtualizationFilterSettings::ExcludePackagePaths. -- When set to EPackageFilterMode::OptIn then no package path will virtualize unless included by a pattern in UVirtualizationFilterSettings::IncludePackagePaths. - Added a TRACE_CPUPROFILER_EVENT_SCOPE to the constructor and ::MountBackends to better track the set up time costs. - Change use of FConfigCacheIni::LoadLocalIniFile to use GConfig, there is no need to load our own. - Improved verbose logging to show when a payload is rejected via filtering. - We now early out if all payloads being requested in a push are rejected during validation. - Renamed the FString overload for ::ShouldVirtualizePackage to ::ShouldVirtualize to make the difference clearer. - Added support for UVirtualizationFilterSettings::ExcludePackagePaths when filtering ### UVirtualizationFilterSettings - Now has a new FString array ExcludePackagePaths, which contains the paths/patterns used to force packages to be virtualized when filtering. [CL 19010992 by paul chipchase in ue5-main branch]
2022-02-16 01:27:09 -05:00
Add a config file option to allow payloads stored in .umap and associated "_builddata.uasset" files to be filtered from the virtualization process. This option defaults to true. #rb Per.Larsson #jira UE-156750 #rnx #preflight 62f212e13b773d04161ee7dd ### Problem - The payloads stored in map files tend to change more than other assets and would cause a lot more churn in the VA system. - Some other systems like the landscape component are not able to sensibly continue if their payloads cannot be accessed (heightmaps for exmaple) and would prefer not to allow virtualization. - As a short term fix we need an option to disable the virtualization on all payloads in map files. Future improvements to the filtering system will allow systems to more easily opt their payloads out of virtualization. When this is functional we might want to change the default from true to false. ### Feature - The config optionf for this filtering is "[Core.VirtualizationModule]FilterMapContent=True" - Testing if the owning UObject for a payload is in a umap can get tricky, because we not only need to check the umap but we also need to check if it is in a "_builddata.uasset" file, which is an additional file we store next to a umap containing things like lightmaps etc. - At the moment we check for this by finding the outermost object for the given owner and check to see if it is a ULevel, UWorld or UMapBuildDataRegistry. This is a bit of a kludge but the types we need to check against are not accessible by this module and making them accessible will pull in a lot of dependencies that we'd prefer not to add. -- One improvement might be to tag the FLinkerSave with the info we need and passing that into the serialization process rather than trying to work it out ourselves but I am wary of making that change until we are 100% sure that we want to keep this feature. ### Refactor - Removed IVirtualizationSystem::IsDisabledForObject and replaced it with ::FilterPayload which can return multiple reasons for preventing a payload from virtualizing. (the method was added during 5.1 development so it should be fine to just replace it without deprecation) -- The original behaviour for FVirtualizationManager::IsDisabledForObject has been moved to FVirtualizationManager::ShouldVirtualizeAsset - Added a new header to declare enums/types used by the various parts of the virtualization system and started by moving EPayloadFilterReason there from the package trailer header. This allows both the core API and PackageTrailer to use EPayloadFilterReason without creating overburdened header dependencies. -- EPayloadFilterReason has moved from the UE namespace to UE::Virtualization so the package trailer code needed updating accordingly. - EditorBulkData will ask the virtualization system for the base filter reason, then add it's own reasons if UE_ENABLE_VIRTUALIZATION_TOGGLE is enabled. This bit of code will be removed for 5.1 [CL 21283179 by paul chipchase in ue5-main branch]
2022-08-09 07:51:55 -04:00
/** Should payloads in .umap files (or associated _BuildData files) be filtered out and never virtualized */
bool bFilterMapContent;
Add an ini file option which when set to true allows package submissions to source control to go ahead even if the virtualization process failed. #rb none #jira UE-159596 #rnx #preflight 62d94160110da0f944afdd32 ### Problem - When rolling our virtualization to projects we have run into a number of set up problems which has caused users to fail to submit packages from the editor as when the virtualization failed we prevented the overall submit from going through. - Although we will eventually work through all of these problems and add better fault tolerance for now it is annoying for the content team so we need an easy way for a project to allow package submits to be completed even if the virtualization process part of the submit failed. - Worth noting that the virtualization process failing should never affect the state of the package files, the only downside is that the packages may not be virtualized. ### Fix - The virtualization/rehydration of packages now return an enum instead of a bool although at the moment we are only returning Success and Failed, but it will allow us to expand in the future - Combined the code calling the virtualization process from both the source control window and the source control changelist window into a single utility function. -- Now the two windows only diverge on how they report failure to the user. - This new utility function now checks to see if the virtualization manager suggests if failing the virtualization process should block any package submission to source control or not. - I am not happy with this solution, but I haven't come up with anything that feels right, this solution will at least work. [CL 21199597 by paul chipchase in ue5-main branch]
2022-07-21 08:31:47 -04:00
/** Should file submits be allowed to continue if a call to TryVirtualizePackages fails */
bool bAllowSubmitIfVirtualizationFailed;
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
/** Should backends defer connecting to their services until first use */
bool bLazyInitConnections;
private:
/** The name of the current project */
FString ProjectName;
It is now possible to disable virtualization for all payloads owned by a specific asset type by adding the name of the asset to [Core.ContentVirtualization]DisabledAsset string array in the engine ini file. #rb Per.Larsson #rnx #jira UE-151377 #preflight 628364050039ea57a52d6989 ### Virtualization - [Core.ContentVirtualization] in the engine ini file now supports an array called 'DisabledAsset' which can be used to name asset types that should not virtualize their payloads. -- By default (in BaseEngine.ini) we have disabled the StaticMesh asset as we know it will crash if a payload is missing and the SoundWave asset as it still is pending testing. - This new way to disable virtualization is data driven. The older hard coded method has not been removed but will likely be reworked in a future submit. - Now when an editor bulkdata is adding it's payload to the package trailer builder during package save it will poll the virtualization system with a call to the new method ::IsDisabledForObject by passing in it's owner. -- If the owner is valid and was present in the 'DisabledAsset' array then the method will return true and the EPayloadFlags::DisableVirtualization flag will be applied. ### Package Trailer - The pre-existing functionality of enum EPayloadFilter has been moved to a new enum EPayloadStorageType as will only filter payloads based on their storage type. - EPayloadFilter has been modified to filter payloads based on functionality although at the moment the only thing it can filter for is to return payloads that can be virtualized, it is left for future expansion. - EPayloadFlags has been reduced to a uint16 with the remaining 2bytes being turned into a new member EPayloadFilterReason. - This new member allows us to record the exact reason why a payload is excluded from virtualization. If it is zero then the payload can virtualize, otherwise it will contain one or more reasons as to why it is being excluded. For this reason the enum is a bitfield. - Added overloads of ::GetPayloads and ::GetNumPayloads that take EPayloadFilter rather than a EPayloadStorageType - Added wrappers around all AccessMode types for FLookupTableEntry. - FPackageTrailerBuilder has been extended to take a EPayloadFilterReason so that the caller can already provide a reason why the payload cannot be virtualized. -- As a future peace of work this will probably be changed and we will ask the caller to pass in the owner UObject pointer instead and then we will process the filtering when building the package trailer to a) keep all of the filtering code in one place b) keep the filtering consistent ### PackageSubmissionChecks - The virtualization process in will now request the payloads that can be virtualized from the package trailer, which respects the new payload flag, rather than requesting all locally stored payloads. ### UObjects - There is no need for the SoundWave or MeshDescription classes to opt out of virtualization on construction. This will be done when the package is saved and is now data driven rather than being hardcoded. ### DumpPackagePayloadInfo - The command has been updated to also display the filter reasons applied to each payload [CL 20240971 by paul chipchase in ue5-main branch]
2022-05-17 07:54:28 -04:00
/** The names of all asset types that should not virtualize. See @IsDisabledForObject */
TSet<FName> DisabledAssetTypes;
/** All of the backends that were mounted during graph creation */
TArray<TUniquePtr<IVirtualizationBackend>> AllBackends;
/** Backends used for caching operations (must support push operations). */
FBackendArray CacheStorageBackends;
/** Backends used for persistent storage operations (must support push operations). */
FBackendArray PersistentStorageBackends;
/**
* The hierarchy of backends to pull from, this is assumed to be ordered from fastest to slowest
* and can contain a mixture of local cacheable and persistent backends
*/
FBackendArray PullEnabledBackends;
Add a number of ways for the VA backend connections to be changed to lazy initialize on first use. #rb Devin.Doucette #jira UE-161599 #rnx #preflight 6303c8d65a5d4e4624e7bf52 - There are some use cases that require the VA system to be initialized and configured correctly but would prefer that the backend connections only run if absolutely needed (usually when a payload is pulled or pushed for the first time), this change provides four different ways of doing this: -- Setting [Core.VirtualizationModule]LazyInitConnections=true in the Engine ini file -- Setting the define 'UE_VIRTUALIZATION_CONNECTION_LAZY_INIT' to 1 in a programs .target.cs -- Running with the commandline option -VA-LazyInitConnections -- Setting the cvar 'VA.LazyInitConnections' to 1 (only works if it is set before the VA system is initialized, changing it mid editor via the console does nothing) --- Note that after the config file, each setting there only opts into lazy initializing the connections, setting the cvar to 0 for example will not prevent the cmdline from opting in etc. - In the future we will allow the connection code to run async, so the latency can be hidden behind the editor loading, but for the current use case we are taking the minimal approach. -- This means we only support the backend being in 3 states. No connection has been made yet, the connection is broken and the connection is working. -- To keep things simple we only record if we have attempted to connect the backends or not. We don't check individual backends nor do we try to reconnect failed ones etc. This is all scheduled for a future work item. - If the connections are not initialized when the VA system is, we wait until the first time someone calls one of the virtualization methods that will actually use a connection: Push/Pull/Query -- We try connecting all of the backends at once, even if they won't be used in the call to keep things simple. - Only the source control backend makes use of the connection system. The horde storage (http) backend could take advantage too, but it is currently unused and most likely going to just be deleted so there seemed little point updating it. - If we try to run an operation on an unconnected backend we only log to verbose. This is to maintain existing behaviour where a failed backend would not be mounted at all. This logging will likely be revisited in a future work item. [CL 21511855 by paul chipchase in ue5-main branch]
2022-08-23 13:01:15 -04:00
/** Do we have backends that have not yet tried connecting to their services */
bool bPendingBackendConnections;
/** Our notification Event */
FOnNotification NotificationEvent;
// Members after this point at used for debugging operations only!
struct FDebugValues
{
/** All of the console commands/variables that we register, so they can be unregistered when the manager is destroyed */
TArray<IConsoleObject*> ConsoleObjects;
/**
* Contains all of the delegate handles that we have bound to IConsoleVariable::OnChangedDelegate and need to be removed
* before it is safe to destroy the manager. Most likely due to having bound a lambda to the delegate that captured the
* FVirtualizationManager this pointer.
*/
TArray<TPair<IConsoleVariable*, FDelegateHandle>> ConsoleDelegateHandles;
/** The critical section used to force single threaded access if bForceSingleThreaded is true */
FCriticalSection ForceSingleThreadedCS;
/** When enabled all public operations will be performed as single threaded */
bool bSingleThreaded = false;
/**
* When enabled we will immediately 'pull' each payload after it has been pushed to either local or persistent
* storage and compare it to the original payload source to make sure that it was uploaded correctly
*/
bool bValidateAfterPush = false;
/** Array of backend names that should have their pull operation disabled */
TArray<FString> MissBackends;
/** The chance that a payload pull can just 'fail' to allow for testing */
float MissChance;
/** The number of upcoming payload pulls that should be failed */
std::atomic<int32> MissCount = 0;
} DebugValues;
};
} // namespace UE::Virtualization