You've already forked UnrealEngineUWP
mirror of
https://github.com/izzy2lost/UnrealEngineUWP.git
synced 2026-03-26 18:15:20 -07:00
* Restaging a build no longer just constantly increases size * Inclusive size actually looks at valid data * Horde URL environment variable corrected. * Add a new root pseudo plugin json event that holds the size of all plugins that don't belong to a root plugin. #rb charles.bloom [CL 26335038 by dan thompson in ue5-main branch]
261 lines
9.8 KiB
C++
261 lines
9.8 KiB
C++
// Copyright Epic Games, Inc. All Rights Reserved.
|
|
|
|
#pragma once
|
|
|
|
#include "Containers/Array.h"
|
|
#include "Containers/UnrealString.h"
|
|
#include "CoreTypes.h"
|
|
#include "Memory/MemoryFwd.h"
|
|
|
|
|
|
namespace UE::Cook
|
|
{
|
|
|
|
enum class ECookMetadataStateVersion : uint8
|
|
{
|
|
InvalidVersion = 0,
|
|
PluginHierarchy = 1,
|
|
PostWritebackHash = 2,
|
|
FixSerialization = 3,
|
|
|
|
// Add new versions above this.
|
|
VersionCount,
|
|
LatestVersion = VersionCount - 1
|
|
};
|
|
|
|
/**
|
|
* We classify various bits of the plugin data based on how it will be delivered to the end user in order to
|
|
* more appropriately track the user's experience.
|
|
*
|
|
* Each iostore chunk (note: NOT pak chunk!) gets compressed during staging and unreal pak will update the size
|
|
* for the plugin based on how the chunk gets deployed.
|
|
*/
|
|
enum class EPluginSizeTypes : uint8
|
|
{
|
|
// The iostore chunks will be deployed to servers for downloading on-demand by the game using the Individual Asset Streaming
|
|
// system.
|
|
Streaming,
|
|
// The iostore chunks are written to normal iostore containers that are expected to be distributed with the game. This
|
|
// includes the required global iostore container.
|
|
Installed,
|
|
// The iostore chunks are written to a separate container that isn't required to be distributed with the game. This is where e.g.
|
|
// OptionalMips go for textures. They appear as .uptnl files in the Cooked directory (if cooking to Loose Files),
|
|
// The CopyBuildToStagingDirectory script manually assigns the iostore chunk to a corresponding pak chunk with the name
|
|
// ending in "optional", e.g. pakChunk0optional.pak/ucas/utoc/sig. The only way to catch this in UnrealPak
|
|
// is to parse the filename.
|
|
Optional,
|
|
// These are sidecar files for distributing EditorOnly data for Cooked Editor builds. When cooking to loose files
|
|
// they will contain ".o" inside their filename, e.g. "myasset.o.ubulk". They are never intended to be shipped with
|
|
// a game.
|
|
OptionalSegment,
|
|
COUNT
|
|
};
|
|
constexpr uint8 EPluginSizeTypesCount = (uint8)EPluginSizeTypes::COUNT;
|
|
|
|
struct FPluginSizeInfo
|
|
{
|
|
uint64 Sizes[EPluginSizeTypesCount] = {};
|
|
|
|
void Zero() { FMemory::Memzero(this, sizeof(*this)); }
|
|
void AddSizes(uint64 SizesPerType[EPluginSizeTypesCount])
|
|
{
|
|
for (uint8 Type = 0; Type < EPluginSizeTypesCount; Type++)
|
|
{
|
|
Sizes[Type] += SizesPerType[Type];
|
|
}
|
|
}
|
|
void Add(const FPluginSizeInfo& Other)
|
|
{
|
|
for (uint8 Type = 0; Type < EPluginSizeTypesCount; Type++)
|
|
{
|
|
Sizes[Type] += Other.Sizes[Type];
|
|
}
|
|
}
|
|
uint64 TotalSize() const
|
|
{
|
|
uint64 Total = 0;
|
|
for (uint8 Type = 0; Type < EPluginSizeTypesCount; Type++)
|
|
{
|
|
Total += Sizes[Type];
|
|
}
|
|
return Total;
|
|
}
|
|
|
|
friend FArchive& operator<<(FArchive& Ar, FPluginSizeInfo& SizeInfo)
|
|
{
|
|
for (uint8 i = 0; i < EPluginSizeTypesCount; i++)
|
|
{
|
|
Ar << SizeInfo.Sizes[i];
|
|
}
|
|
return Ar;
|
|
}
|
|
|
|
uint64& operator[](EPluginSizeTypes InType) { return Sizes[(uint8)InType]; }
|
|
const uint64& operator[](EPluginSizeTypes InType) const { return Sizes[(uint8)InType]; }
|
|
};
|
|
|
|
/*
|
|
* Unrealpak doesn't compress the data for all platforms. In those cases, the data written back
|
|
* during staging isn't compressed and is not representative of the final sizes that occurs after
|
|
* the corresponding SDK tools process them for deployment.
|
|
*/
|
|
enum class ECookMetadataSizesPresent
|
|
{
|
|
// staging has not occured, or writeback wasn't enabled in project packaing settings.
|
|
NotPresent,
|
|
|
|
// unrealpak compressed the iostore chunks and the data we have is compressed sizes
|
|
Compressed,
|
|
|
|
// the selected platform isn't compressed by unrealpak, or package compression was disabled.
|
|
Uncompressed,
|
|
|
|
Count
|
|
};
|
|
|
|
/** The name and dependency information for a plugin that was enabled during cooking. */
|
|
struct COOKMETADATA_API FCookMetadataPluginEntry
|
|
{
|
|
FString Name;
|
|
|
|
// The dependencies are stored in the FCookMetadataPluginHierarchy::PluginDependencies array,
|
|
// and this is an index into it. From there you can get a further index into PluginsEnabledAtCook
|
|
// to get the plugin information.
|
|
// Example:
|
|
// for (uint16 DependencyIndex = Plugin->DependencyIndexStart; DependencyIndex < Plugin->DependencyIndexEnd; DependencyIndex++)
|
|
// {
|
|
// const UE::Cook::FCookMetadataPluginEntry& DependentPlugin = PluginHierarchy.PluginsEnabledAtCook[PluginHierarchy.PluginDependencies[DependencyIndex]];
|
|
// }
|
|
//
|
|
uint16 DependencyIndexStart = 0;
|
|
uint16 DependencyIndexEnd = 0;
|
|
|
|
//
|
|
// Theses sizes are set during staging by unrealpak if the option in project packaging is set.
|
|
// To determine if they are set, check FCookMetadataState::GetSizesPresent(). Inclusive contains
|
|
// the size of the plugin and all of its dependencies listed in its uplugin file.
|
|
//
|
|
FPluginSizeInfo InclusiveSizes;
|
|
FPluginSizeInfo ExclusiveSizes;
|
|
|
|
uint16 DependencyCount() const { return DependencyIndexEnd - DependencyIndexStart; }
|
|
|
|
friend FArchive& operator<<(FArchive& Ar, FCookMetadataPluginEntry& Entry)
|
|
{
|
|
Ar << Entry.Name << Entry.DependencyIndexStart << Entry.DependencyIndexEnd;
|
|
Ar << Entry.InclusiveSizes << Entry.ExclusiveSizes;
|
|
return Ar;
|
|
}
|
|
};
|
|
|
|
struct COOKMETADATA_API FCookMetadataPluginHierarchy
|
|
{
|
|
// The list of plugins that were enabled during the cook that generated the FCookMetadataState,
|
|
// pruned to remove plugins that aren't enabled on the cook platform. If the cook was DLC, this
|
|
// is further pruned to only the DLC plugin and its dependencies.
|
|
TArray<FCookMetadataPluginEntry> PluginsEnabledAtCook;
|
|
|
|
// The list of plugin dependencies. FCookMetadataPluginEntry::DependencyIndexStart indexes into this
|
|
// array.
|
|
TArray<uint16> PluginDependencies;
|
|
|
|
// The list of root plugins for the project as defined by the Editor.ini file.
|
|
TArray<uint16> RootPlugins;
|
|
|
|
friend FArchive& operator<<(FArchive& Ar, FCookMetadataPluginHierarchy& Hierarchy)
|
|
{
|
|
return Ar << Hierarchy.PluginsEnabledAtCook << Hierarchy.PluginDependencies << Hierarchy.RootPlugins;
|
|
}
|
|
};
|
|
|
|
/**
|
|
* Structure serialized to disk to contain non-asset related metadata about a cook. This should always
|
|
* exist alongside a Development Asset Registry, and to ensure that the pair is not out of sync, users
|
|
* should validate the development asset registry they are using with GetAssociatedDevelopmentAssetRegistryHash().
|
|
*/
|
|
class COOKMETADATA_API FCookMetadataState
|
|
{
|
|
public:
|
|
FCookMetadataState() = default;
|
|
FCookMetadataState(const FCookMetadataState&) = default;
|
|
FCookMetadataState(FCookMetadataState&& Rhs) = default;
|
|
~FCookMetadataState() = default;
|
|
|
|
FCookMetadataState& operator=(const FCookMetadataState&) = default;
|
|
FCookMetadataState& operator=(FCookMetadataState&& O) = default;
|
|
|
|
bool IsValid() const { return Version == ECookMetadataStateVersion::LatestVersion; }
|
|
void Reset() { *this = FCookMetadataState(); }
|
|
|
|
bool Serialize(FArchive& Ar);
|
|
|
|
// Plugin hierarchy information
|
|
void SetPluginHierarchyInfo(FCookMetadataPluginHierarchy&& InPluginHierarchy) { PluginHierarchy = MoveTemp(InPluginHierarchy); }
|
|
const FCookMetadataPluginHierarchy& GetPluginHierarchy() const { return PluginHierarchy; }
|
|
|
|
// So that unrealpak can update the sizes.
|
|
FCookMetadataPluginHierarchy& GetMutablePluginHierarchy() { return PluginHierarchy; }
|
|
|
|
/**
|
|
* Associated DevAR Hash.
|
|
*
|
|
* This is computed by reading the development asset registry file into a memory buffer and calling
|
|
* ComputeHashOfDevelopmentAssetRegistry on the data.
|
|
*
|
|
* Use this to ensure that the files you are working with were produced by the same cook and didn't
|
|
* get out of sync somehow.
|
|
*
|
|
* *IMPORTANT* If asset registry writeback is enabled during staging, then the hash of the development
|
|
* asset registry changes, and you'll need to check against GetAssociatedDevelopmentAssetRegistryHashPostWriteback.
|
|
* If you don't know which one you have, check both - they are both valid.
|
|
*
|
|
* e.g.
|
|
* uint64 CheckHash = GetAssociatedDevelopmentAssetRegistryHash();
|
|
* bValidDevAr = ComputeHashOfDevelopmentAssetRegistry(MakeMemoryView(SerializedAssetRegistry)) == CheckHash;
|
|
*/
|
|
void SetAssociatedDevelopmentAssetRegistryHash(uint64 InHash) { AssociatedDevelopmentAssetRegistryHash = InHash; }
|
|
void SetAssociatedDevelopmentAssetRegistryHashPostWriteback(uint64 InHash) { AssociatedDevelopmentAssetRegistryHashPostWriteback = InHash; }
|
|
|
|
uint64 GetAssociatedDevelopmentAssetRegistryHash() const { return AssociatedDevelopmentAssetRegistryHash; }
|
|
uint64 GetAssociatedDevelopmentAssetRegistryHashPostWriteback() const { return AssociatedDevelopmentAssetRegistryHashPostWriteback; }
|
|
|
|
void SetPlatformAndBuildVersion(const FString& InPlatform, const TCHAR* InBuildVersion) { Platform = InPlatform; BuildVersion = FString(InBuildVersion); }
|
|
const FString& GetPlatform() const { return Platform; }
|
|
const FString GetBuildVersion() const { return BuildVersion; }
|
|
|
|
void SetHordeJobId(FString&& InHordeJobId) { HordeJobId = MoveTemp(InHordeJobId); }
|
|
const FString& GetHordeJobId() const { return HordeJobId; }
|
|
|
|
static uint64 ComputeHashOfDevelopmentAssetRegistry(FMemoryView InSerializedDevelopmentAssetRegistry);
|
|
|
|
// Returns what size information is present in FCookMetadataPluginEntry. This varies based on the platform
|
|
// and settings.
|
|
FText GetSizesPresentAsText() const;
|
|
ECookMetadataSizesPresent GetSizesPresent() const { return SizesPresent; }
|
|
void SetSizesPresent(ECookMetadataSizesPresent InSizesPresent) { SizesPresent = InSizesPresent; }
|
|
private:
|
|
|
|
ECookMetadataStateVersion Version = ECookMetadataStateVersion::InvalidVersion;
|
|
FCookMetadataPluginHierarchy PluginHierarchy;
|
|
|
|
uint64 AssociatedDevelopmentAssetRegistryHash = 0;
|
|
|
|
// Asset registry size writeback changes the AR, so we have a separate hash for that DevAR that this
|
|
// also matches.
|
|
uint64 AssociatedDevelopmentAssetRegistryHashPostWriteback = 0;
|
|
|
|
FString Platform;
|
|
|
|
// BUILD_VERSION definition from definitions.h for the cook.
|
|
FString BuildVersion;
|
|
|
|
// If cooked on Horde, this is the job id that cooked it.
|
|
FString HordeJobId;
|
|
|
|
// Updated by unrealpak when plugin size information is added.
|
|
ECookMetadataSizesPresent SizesPresent = ECookMetadataSizesPresent::NotPresent;
|
|
};
|
|
|
|
COOKMETADATA_API const FString& GetCookMetadataFilename();
|
|
|
|
}; // namespace
|