295 lines
11 KiB
C++
295 lines
11 KiB
C++
// Fill out your copyright notice in the Description page of Project Settings.
|
|
|
|
#include "ShaderLibUtils//FlibShaderCodeLibraryHelper.h"
|
|
#include "HotPatcherLog.h"
|
|
#include "FlibHotPatcherCoreHelper.h"
|
|
#include "HotPatcherCore.h"
|
|
|
|
#include "ShaderCompiler.h"
|
|
#include "IPlatformFileSandboxWrapper.h"
|
|
#include "Interfaces/IPluginManager.h"
|
|
#include "Interfaces/ITargetPlatform.h"
|
|
#include "Misc/EngineVersionComparison.h"
|
|
|
|
#define REMAPPED_PLUGINS TEXT("RemappedPlugins")
|
|
|
|
FString UFlibShaderCodeLibraryHelper::ShaderExtension = TEXT(".ushaderbytecode");
|
|
FString UFlibShaderCodeLibraryHelper::ShaderAssetInfoExtension = TEXT(".assetinfo.json");
|
|
FString UFlibShaderCodeLibraryHelper::StableExtension = TEXT(".scl.csv");
|
|
|
|
// FMergeShaderCollectionProxy::FMergeShaderCollectionProxy(const TArray<FShaderCodeFormatMap>& InShaderCodeFiles):ShaderCodeFiles(InShaderCodeFiles)
|
|
// {
|
|
// Init();
|
|
// }
|
|
// FMergeShaderCollectionProxy::~FMergeShaderCollectionProxy()
|
|
// {
|
|
// Shutdown();
|
|
// }
|
|
//
|
|
// void FMergeShaderCollectionProxy::Init()
|
|
// {
|
|
// for(const auto& ShaderCodeFoemat:ShaderCodeFiles)
|
|
// {
|
|
// TArray<FName> ShaderFormatNames = UFlibShaderCodeLibraryHelper::GetShaderFormatsByTargetPlatform(ShaderCodeFoemat.Platform);
|
|
//
|
|
// for(const auto& ShaderFormatName:ShaderFormatNames)
|
|
// {
|
|
// EShaderPlatform ShaderPlatform= ::ShaderFormatToLegacyShaderPlatform(ShaderFormatName);
|
|
//
|
|
// if(ShaderCodeFoemat.ShaderCodeTypeFilesMap.Contains(ShaderFormatName.ToString()))
|
|
// {
|
|
// SHADER_COOKER_CLASS::InitForCooking(ShaderCodeFoemat.bIsNative);
|
|
// SHADER_COOKER_CLASS::InitForRuntime(ShaderPlatform);
|
|
// TArray<FName> CurrentPlatforomShaderTypeNames;
|
|
// {
|
|
// TArray<FString> PlatforomShaderTypeNames;
|
|
// ShaderCodeFoemat.ShaderCodeTypeFilesMap.GetKeys(PlatforomShaderTypeNames);
|
|
// for(const auto& Name:PlatforomShaderTypeNames)
|
|
// {
|
|
// CurrentPlatforomShaderTypeNames.AddUnique(*Name);
|
|
// }
|
|
// }
|
|
//
|
|
// #if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 25
|
|
// TArray<SHADER_COOKER_CLASS::FShaderFormatDescriptor> ShaderFormatsWithStableKeys = UFlibShaderCodeLibraryHelper::GetShaderFormatsWithStableKeys(CurrentPlatforomShaderTypeNames);
|
|
// #else
|
|
// TArray<TPair<FName, bool>> ShaderFormatsWithStableKeys;
|
|
// for (FName& Format : ShaderFormatNames)
|
|
// {
|
|
// ShaderFormatsWithStableKeys.Push(MakeTuple(Format, true));
|
|
// }
|
|
// #endif
|
|
//
|
|
// SHADER_COOKER_CLASS::CookShaderFormats(ShaderFormatsWithStableKeys);
|
|
// FShaderCodeFormatMap::FShaderFormatNameFiles ShaderFormatNameFiles = *ShaderCodeFoemat.ShaderCodeTypeFilesMap.Find(ShaderFormatName.ToString());
|
|
// for(const auto& File:ShaderFormatNameFiles.Files)
|
|
// {
|
|
// FString Path = FPaths::GetPath(File);
|
|
// FShaderCodeLibrary::OpenLibrary(ShaderFormatNameFiles.ShaderName,Path);
|
|
// }
|
|
// if(!UFlibShaderCodeLibraryHelper::SaveShaderLibrary(ShaderCodeFoemat.Platform, NULL, FApp::GetProjectName(),ShaderCodeFoemat.SaveBaseDir,true))
|
|
// {
|
|
// UE_LOG(LogHotPatcherCoreHelper,Display,TEXT("SaveShaderLibrary %s for %s Failed!"),*FApp::GetProjectName(),*ShaderCodeFoemat.Platform->PlatformName() );
|
|
// }
|
|
// SHADER_COOKER_CLASS::Shutdown();
|
|
// }
|
|
// }
|
|
// }
|
|
// }
|
|
//
|
|
// void FMergeShaderCollectionProxy::Shutdown()
|
|
// {
|
|
// FShaderCodeLibrary::Shutdown();
|
|
// }
|
|
|
|
#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 25
|
|
TArray<SHADER_COOKER_CLASS::FShaderFormatDescriptor> UFlibShaderCodeLibraryHelper::GetShaderFormatsWithStableKeys(
|
|
const TArray<FName>& ShaderFormats,bool bNeedShaderStableKeys/* = true*/,bool bNeedsDeterministicOrder/* = true*/)
|
|
{
|
|
TArray<SHADER_COOKER_CLASS::FShaderFormatDescriptor> ShaderFormatsWithStableKeys;
|
|
for (const FName& Format : ShaderFormats)
|
|
{
|
|
SHADER_COOKER_CLASS::FShaderFormatDescriptor NewDesc;
|
|
NewDesc.ShaderFormat = Format;
|
|
NewDesc.bNeedsStableKeys = bNeedShaderStableKeys;
|
|
NewDesc.bNeedsDeterministicOrder = bNeedsDeterministicOrder;
|
|
ShaderFormatsWithStableKeys.Push(NewDesc);
|
|
}
|
|
return ShaderFormatsWithStableKeys;
|
|
}
|
|
#endif
|
|
|
|
TArray<FName> UFlibShaderCodeLibraryHelper::GetShaderFormatsByTargetPlatform(ITargetPlatform* TargetPlatform)
|
|
{
|
|
TArray<FName> ShaderFormats;
|
|
TargetPlatform->GetAllTargetedShaderFormats(ShaderFormats);
|
|
return ShaderFormats;
|
|
}
|
|
|
|
FString UFlibShaderCodeLibraryHelper::GenerateShaderCodeLibraryName(FString const& Name, bool bIsIterateSharedBuild)
|
|
{
|
|
FString ActualName = (!bIsIterateSharedBuild) ? Name : Name + TEXT("_SC");
|
|
return ActualName;
|
|
}
|
|
|
|
bool UFlibShaderCodeLibraryHelper::SaveShaderLibrary(const ITargetPlatform* TargetPlatform,TArray<FName> ShaderFormats, const FString& ShaderCodeDir,const FString& RootMetaDataPath, bool bMaster)
|
|
{
|
|
bool bSaved = false;
|
|
// TargetPlatform->GetAllTargetedShaderFormats(ShaderFormats);
|
|
if (ShaderFormats.Num() > 0)
|
|
{
|
|
FString TargetPlatformName = TargetPlatform->PlatformName();
|
|
TArray<FString> PlatformSCLCSVPaths;// = OutSCLCSVPaths.FindOrAdd(FName(TargetPlatformName));
|
|
|
|
#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 25
|
|
#if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26
|
|
FString ErrorString;
|
|
#if !UE_VERSION_OLDER_THAN(5,1,0)
|
|
bool bOutHasData = false;
|
|
#endif
|
|
bSaved = SHADER_COOKER_CLASS::SaveShaderLibraryWithoutChunking(TargetPlatform, FApp::GetProjectName(), ShaderCodeDir, RootMetaDataPath, PlatformSCLCSVPaths, ErrorString
|
|
#if !UE_VERSION_OLDER_THAN(5,1,0)
|
|
,bOutHasData
|
|
#endif
|
|
);
|
|
#else
|
|
TArray<TSet<FName>> ChunkAssignments;
|
|
bSaved = FShaderCodeLibrary::SaveShaderCode(ShaderCodeDir, RootMetaDataPath, ShaderFormats, PlatformSCLCSVPaths, &ChunkAssignments);
|
|
#endif
|
|
#else
|
|
if(bMaster)
|
|
{
|
|
bSaved = FShaderCodeLibrary::SaveShaderCodeMaster(ShaderCodeDir, RootMetaDataPath, ShaderFormats, PlatformSCLCSVPaths);
|
|
}
|
|
else
|
|
{
|
|
bSaved = FShaderCodeLibrary::SaveShaderCodeChild(ShaderCodeDir, RootMetaDataPath, ShaderFormats);
|
|
}
|
|
#endif
|
|
}
|
|
return bSaved;
|
|
}
|
|
|
|
bool UFlibShaderCodeLibraryHelper::SaveShaderLibrary(const ITargetPlatform* TargetPlatform, const TArray<TSet<FName>>* ChunkAssignments, FString const& Name, const FString&
|
|
SaveBaseDir, bool bMaster)
|
|
{
|
|
bool bSaved = false;
|
|
FString ActualName = GenerateShaderCodeLibraryName(Name, false);
|
|
FString BasePath = FPaths::ProjectContentDir();
|
|
|
|
FString ShaderCodeDir = FPaths::Combine(SaveBaseDir,TargetPlatform->PlatformName());
|
|
|
|
const FString RootMetaDataPath = ShaderCodeDir / TEXT("Metadata") / TEXT("PipelineCaches");
|
|
|
|
// note that shader formats can be shared across the target platforms
|
|
TArray<FName> ShaderFormats;
|
|
TargetPlatform->GetAllTargetedShaderFormats(ShaderFormats);
|
|
if (ShaderFormats.Num() > 0)
|
|
{
|
|
bSaved = UFlibShaderCodeLibraryHelper::SaveShaderLibrary(TargetPlatform,ShaderFormats,ShaderCodeDir,RootMetaDataPath,bMaster);
|
|
// FString TargetPlatformName = TargetPlatform->PlatformName();
|
|
// TArray<FString> PlatformSCLCSVPaths;// = OutSCLCSVPaths.FindOrAdd(FName(TargetPlatformName));
|
|
//
|
|
// #if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 25
|
|
// #if ENGINE_MAJOR_VERSION > 4 || ENGINE_MINOR_VERSION > 26
|
|
// FString ErrorString;
|
|
// bSaved = SHADER_COOKER_CLASS::SaveShaderLibraryWithoutChunking(TargetPlatform, FApp::GetProjectName(), ShaderCodeDir, RootMetaDataPath, PlatformSCLCSVPaths, ErrorString);
|
|
// #else
|
|
// bSaved = FShaderCodeLibrary::SaveShaderCode(ShaderCodeDir, RootMetaDataPath, ShaderFormats, PlatformSCLCSVPaths, ChunkAssignments);
|
|
// #endif
|
|
// #else
|
|
// if(bMaster)
|
|
// {
|
|
// bSaved = FShaderCodeLibrary::SaveShaderCodeMaster(ShaderCodeDir, RootMetaDataPath, ShaderFormats, PlatformSCLCSVPaths);
|
|
// }
|
|
// else
|
|
// {
|
|
// bSaved = FShaderCodeLibrary::SaveShaderCodeChild(ShaderCodeDir, RootMetaDataPath, ShaderFormats);
|
|
// }
|
|
// #endif
|
|
}
|
|
return bSaved;
|
|
}
|
|
|
|
|
|
TArray<FString> UFlibShaderCodeLibraryHelper::FindCookedShaderLibByShaderFrmat(const FString& ShaderFormatName,const FString& Directory)
|
|
{
|
|
TArray<FString> result;
|
|
TArray<FString > FoundShaderFiles;
|
|
IFileManager::Get().FindFiles(FoundShaderFiles,*Directory,TEXT("ushaderbytecode"));
|
|
|
|
FString FormatExtersion = FString::Printf(TEXT("*%s*.ushaderbytecode"),*ShaderFormatName);
|
|
for(const auto& ShaderFile:FoundShaderFiles)
|
|
{
|
|
if(ShaderFile.MatchesWildcard(FormatExtersion))
|
|
{
|
|
result.Add(ShaderFile);
|
|
}
|
|
}
|
|
return result;
|
|
}
|
|
|
|
TArray<FString> UFlibShaderCodeLibraryHelper::FindCookedShaderLibByPlatform(const FString& PlatfomName,const FString& Directory, bool bRecursive)
|
|
{
|
|
SCOPED_NAMED_EVENT_TEXT("UFlibShaderCodeLibraryHelper::FindCookedShaderLibByPlatform",FColor::Red);
|
|
TArray<FString> FoundFiles;
|
|
auto GetMetalShaderFormatLambda = [](const FString& Directory,const FString& Extersion, bool bRecursive)
|
|
{
|
|
TArray<FString> FoundMetallibFiles;
|
|
if(bRecursive)
|
|
{
|
|
IFileManager::Get().FindFilesRecursive(FoundMetallibFiles,*Directory,*Extersion,true,false, false);
|
|
}
|
|
else
|
|
{
|
|
IFileManager::Get().FindFiles(FoundMetallibFiles,*Directory,*Extersion);
|
|
}
|
|
return FoundMetallibFiles;
|
|
};
|
|
|
|
if(PlatfomName.StartsWith(TEXT("IOS"),ESearchCase::IgnoreCase) || PlatfomName.StartsWith(TEXT("Mac"),ESearchCase::IgnoreCase))
|
|
{
|
|
FoundFiles.Append(GetMetalShaderFormatLambda(Directory,TEXT("metallib"),bRecursive));
|
|
FoundFiles.Append(GetMetalShaderFormatLambda(Directory,TEXT("metalmap"),bRecursive));
|
|
}
|
|
|
|
if(!FoundFiles.Num())
|
|
{
|
|
FoundFiles.Append(GetMetalShaderFormatLambda(Directory,TEXT("ushaderbytecode"),bRecursive));
|
|
}
|
|
for(auto& File:FoundFiles)
|
|
{
|
|
File = FPaths::Combine(Directory,File);
|
|
}
|
|
return FoundFiles;
|
|
}
|
|
|
|
void UFlibShaderCodeLibraryHelper::WaitShaderCompilingComplete()
|
|
{
|
|
// Wait for all shaders to finish compiling
|
|
if (GShaderCompilingManager)
|
|
{
|
|
SCOPED_NAMED_EVENT_TEXT("WaitShaderCompileComplete",FColor::Red);
|
|
while(GShaderCompilingManager->IsCompiling())
|
|
{
|
|
GShaderCompilingManager->ProcessAsyncResults(false, false);
|
|
// int32 CurrentNumRemaingingJobs = GShaderCompilingManager->GetNumRemainingJobs();
|
|
// if(GCookLog && LastRemainingJob != CurrentNumRemaingingJobs)
|
|
// {
|
|
// UE_LOG(LogHotPatcher,Display,TEXT("Remaining Shader %d"),CurrentNumRemaingingJobs);
|
|
// LastRemainingJob = CurrentNumRemaingingJobs;
|
|
// }
|
|
// GShaderCompilingManager->FinishAllCompilation();
|
|
FPlatformProcess::Sleep(0.5f);
|
|
GLog->Flush();
|
|
}
|
|
|
|
// One last process to get the shaders that were compiled at the very end
|
|
GShaderCompilingManager->ProcessAsyncResults(false, false);
|
|
GShaderCompilingManager->FinishAllCompilation();
|
|
}
|
|
}
|
|
|
|
void UFlibShaderCodeLibraryHelper::CleanShaderWorkerDir()
|
|
{
|
|
if (FPaths::DirectoryExists(FPaths::ShaderWorkingDir()) && !IFileManager::Get().DeleteDirectory(*FPaths::ShaderWorkingDir(), false, true))
|
|
{
|
|
UE_LOG(LogHotPatcher, Warning, TEXT("Could not delete the shader compiler working directory '%s'."), *FPaths::ShaderWorkingDir());
|
|
}
|
|
}
|
|
|
|
void UFlibShaderCodeLibraryHelper::CancelMaterialShaderCompile(UMaterialInterface* MaterialInterface)
|
|
{
|
|
if(MaterialInterface)
|
|
{
|
|
UMaterial* Material = MaterialInterface->GetMaterial();
|
|
for (int32 FeatureLevel = 0; FeatureLevel < ERHIFeatureLevel::Num; ++FeatureLevel)
|
|
{
|
|
if (FMaterialResource* Res = Material->GetMaterialResource((ERHIFeatureLevel::Type)FeatureLevel))
|
|
{
|
|
Res->CancelCompilation();
|
|
}
|
|
}
|
|
}
|
|
}
|