You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
#rb Per.Larsson #jira UE-163103 #rnx #preflight 6318989c2b7fe03eb664e9f0 ### VirtualizationSystem/VirtualizationManager - Added an overload of ::Push taking just one FPUshRequest so that people don't have to keep adding MakeArrayView boiler plate when pushing a single request - Change the order of the last two parameters for the raw ::Push call as this will group all of the payload specific parameters together and leave the target storage type at the end. It is unlikely that anyone is calling the older version but it has been deprecated for safety. ### IVirtualizationBackend - The none FPushRequest overload of ::PushData is no longer virtual, it just converts the parameters to FPushRequest and calls that overload instead. In this way we now only have one pushing code path in our backends. We could probably look into removing this overload at this point (since the higher level IVirtualizationSystem will now convert all push requests into a FPushRequest form) but it is not considered worth it at the moment when the simple overload covers our needs. - Removed EPushResult in favour of just returning true/false for the overall operation.If the caller needs a more detailed breakdown then they will have to use an overload that takes an FPushRequest over raw parameters. -- At the moment FPushRequest does not contain a full breakdown of what happened, so with this submit we are effectively losing the ability to find out if the payload was already in the backends or not, however the batch version of push was already not returning this info so it is not a big loss. Fixing FPushRequest to return a better break down of what happened will be done in UE-160942 - Removed the none batch Push paths from the source control and ddc backends as they already supported batch pushing. - File backend needed to be converted to supporting batch pushing, which is pretty much the same code as before except we need to iterate over the container of FPushRequests. -- The backend does not early out on error as it tends to be quite fast. We might want to consider an official policy for the VA system, if we should early out of errors or not. [CL 21907558 by paul chipchase in ue5-main branch]
193 lines
5.7 KiB
C++
193 lines
5.7 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#include "VirtualizationDDCBackend.h"
|
|
|
|
#include "Misc/Parse.h"
|
|
#include "DerivedDataCache.h"
|
|
#include "DerivedDataCacheRecord.h"
|
|
#include "DerivedDataRequestOwner.h"
|
|
#include "DerivedDataValue.h"
|
|
|
|
namespace UE::Virtualization
|
|
{
|
|
|
|
/** Utility function to help convert from UE::Virtualization::FIoHash to UE::DerivedData::FValueId */
|
|
static UE::DerivedData::FValueId ToDerivedDataValueId(const FIoHash& Id)
|
|
{
|
|
return UE::DerivedData::FValueId::FromHash(Id);
|
|
}
|
|
|
|
FDDCBackend::FDDCBackend(FStringView ProjectName, FStringView ConfigName, FStringView InDebugName)
|
|
: IVirtualizationBackend(ConfigName, InDebugName, EOperations::Push | EOperations::Pull)
|
|
, BucketName(TEXT("BulkData"))
|
|
, TransferPolicy(UE::DerivedData::ECachePolicy::None)
|
|
, QueryPolicy(UE::DerivedData::ECachePolicy::None)
|
|
{
|
|
|
|
}
|
|
|
|
bool FDDCBackend::Initialize(const FString& ConfigEntry)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(Initialize::Initialize);
|
|
|
|
FString BucketNameIniFile;
|
|
if(FParse::Value(*ConfigEntry, TEXT("Bucket="), BucketNameIniFile))
|
|
{
|
|
BucketName = BucketNameIniFile;
|
|
}
|
|
|
|
bool bAllowLocal = true;
|
|
FParse::Bool(*ConfigEntry, TEXT("LocalStorage="), bAllowLocal);
|
|
|
|
bool bAllowRemote = true;
|
|
FParse::Bool(*ConfigEntry, TEXT("RemoteStorage="), bAllowRemote);
|
|
|
|
UE_LOG(LogVirtualization, Log, TEXT("[%s] Bucket set to '%s"), *GetDebugName(), *BucketName);
|
|
UE_LOG(LogVirtualization, Log, TEXT("[%s] Use of local storage set to '%s"), *GetDebugName(), bAllowLocal ? TEXT("true") : TEXT("false"));
|
|
UE_LOG(LogVirtualization, Log, TEXT("[%s] Use of remote storage set to '%s"), *GetDebugName(), bAllowRemote ? TEXT("true") : TEXT("false"));
|
|
|
|
if (!bAllowLocal && !bAllowRemote)
|
|
{
|
|
UE_LOG(LogVirtualization, Error, TEXT("[%s] LocalStorage and RemoteStorage cannot both be disabled"), *GetDebugName());
|
|
return false;
|
|
}
|
|
|
|
if (bAllowLocal)
|
|
{
|
|
TransferPolicy |= UE::DerivedData::ECachePolicy::Local;
|
|
QueryPolicy |= UE::DerivedData::ECachePolicy::QueryLocal;
|
|
}
|
|
|
|
if (bAllowRemote)
|
|
{
|
|
TransferPolicy |= UE::DerivedData::ECachePolicy::Remote;
|
|
QueryPolicy |= UE::DerivedData::ECachePolicy::QueryRemote;
|
|
}
|
|
|
|
Bucket = UE::DerivedData::FCacheBucket(BucketName);
|
|
|
|
return true;
|
|
}
|
|
|
|
IVirtualizationBackend::EConnectionStatus FDDCBackend::OnConnect()
|
|
{
|
|
return IVirtualizationBackend::EConnectionStatus::Connected;
|
|
}
|
|
|
|
bool FDDCBackend::PushData(TArrayView<FPushRequest> Requests)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::PushData);
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Normal);
|
|
|
|
bool bWasSuccess = true;
|
|
|
|
// TODO: We tend not to memory bloat too much on large batches as the requests complete quite quickly
|
|
// however we might want to consider adding better control on how much total memory we can dedicate to
|
|
// loading payloads before we wait for requests to complete?
|
|
for (FPushRequest& Request : Requests)
|
|
{
|
|
if (DoesPayloadExist(Request.GetIdentifier()))
|
|
{
|
|
Request.SetStatus(FPushRequest::EStatus::Success);
|
|
}
|
|
else
|
|
{
|
|
UE::DerivedData::FRequestBarrier Barrier(Owner);
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Request.GetIdentifier();
|
|
|
|
UE::DerivedData::FValue DerivedDataValue(Request.GetPayload());
|
|
check(DerivedDataValue.GetRawHash() == Request.GetIdentifier());
|
|
|
|
UE::DerivedData::FCacheRecordBuilder RecordBuilder(Key);
|
|
RecordBuilder.AddValue(ToDerivedDataValueId(Request.GetIdentifier()), DerivedDataValue);
|
|
|
|
UE::DerivedData::FCachePutResponse Result;
|
|
auto Callback = [&Request, &bWasSuccess](UE::DerivedData::FCachePutResponse&& Response)
|
|
{
|
|
if (Response.Status == UE::DerivedData::EStatus::Ok)
|
|
{
|
|
Request.SetStatus(FPushRequest::EStatus::Success);
|
|
}
|
|
else
|
|
{
|
|
Request.SetStatus(FPushRequest::EStatus::Failed);
|
|
bWasSuccess = false;
|
|
}
|
|
};
|
|
|
|
// TODO: Improve the name when we start passing more context to this function
|
|
Cache.Put({ {{TEXT("Mirage")}, RecordBuilder.Build(), TransferPolicy} }, Owner, MoveTemp(Callback));
|
|
}
|
|
}
|
|
|
|
Owner.Wait();
|
|
|
|
return bWasSuccess;
|
|
}
|
|
|
|
FCompressedBuffer FDDCBackend::PullData(const FIoHash& Id)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::PullData);
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Id;
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Blocking);
|
|
|
|
FCompressedBuffer ResultData;
|
|
UE::DerivedData::EStatus ResultStatus;
|
|
|
|
auto Callback = [&Id, &ResultData, &ResultStatus](UE::DerivedData::FCacheGetResponse&& Response)
|
|
{
|
|
ResultStatus = Response.Status;
|
|
if (ResultStatus == UE::DerivedData::EStatus::Ok)
|
|
{
|
|
ResultData = Response.Record.GetValue(ToDerivedDataValueId(Id)).GetData();
|
|
}
|
|
};
|
|
|
|
// TODO: Improve the name when we start passing more context to this function
|
|
Cache.Get({{{TEXT("Mirage")}, Key, TransferPolicy}}, Owner, MoveTemp(Callback));
|
|
|
|
Owner.Wait();
|
|
|
|
return ResultData;
|
|
}
|
|
|
|
bool FDDCBackend::DoesPayloadExist(const FIoHash& Id)
|
|
{
|
|
TRACE_CPUPROFILER_EVENT_SCOPE(FDDCBackend::DoesPayloadExist);
|
|
|
|
UE::DerivedData::ICache& Cache = UE::DerivedData::GetCache();
|
|
|
|
UE::DerivedData::FCacheKey Key;
|
|
Key.Bucket = Bucket;
|
|
Key.Hash = Id;
|
|
|
|
UE::DerivedData::FRequestOwner Owner(UE::DerivedData::EPriority::Blocking);
|
|
|
|
UE::DerivedData::EStatus ResultStatus;
|
|
auto Callback = [&ResultStatus](UE::DerivedData::FCacheGetResponse&& Response)
|
|
{
|
|
ResultStatus = Response.Status;
|
|
};
|
|
|
|
// TODO: Improve the name when we start passing more context to this function
|
|
Cache.Get({{{TEXT("Mirage")}, Key, QueryPolicy | UE::DerivedData::ECachePolicy::SkipData}}, Owner, MoveTemp(Callback));
|
|
|
|
Owner.Wait();
|
|
|
|
return ResultStatus == UE::DerivedData::EStatus::Ok;
|
|
}
|
|
|
|
UE_REGISTER_VIRTUALIZATION_BACKEND_FACTORY(FDDCBackend, DDCBackend);
|
|
} // namespace UE::Virtualization
|