Files
Rolando Caloca 5154fdf98c Merging //UE4/Dev-Main@4871865 to Dev-Rendering (//UE4/Dev-Rendering)
#rb none
#rnx

[CL 4872315 by Rolando Caloca in Dev-Rendering branch]
2019-02-01 18:09:46 -05:00

222 lines
7.7 KiB
C++

// Copyright 1998-2019 Epic Games, Inc. All Rights Reserved.
/*=============================================================================
GlobalShader.cpp: Global shader implementation.
=============================================================================*/
#include "GlobalShader.h"
#include "Misc/MessageDialog.h"
#include "HAL/FileManager.h"
#include "Serialization/NameAsStringProxyArchive.h"
#include "Misc/Paths.h"
#include "Serialization/MemoryWriter.h"
#include "Serialization/MemoryReader.h"
#include "Misc/ScopedSlowTask.h"
#include "Misc/App.h"
#include "StaticBoundShaderState.h"
/** The global shader map. */
TShaderMap<FGlobalShaderType>* GGlobalShaderMap[SP_NumPlatforms] = {};
IMPLEMENT_SHADER_TYPE(,FNULLPS,TEXT("/Engine/Private/NullPixelShader.usf"),TEXT("Main"),SF_Pixel);
/** Used to identify the global shader map in compile queues. */
const int32 GlobalShaderMapId = 0;
FGlobalShaderMapId::FGlobalShaderMapId(EShaderPlatform Platform)
{
TArray<FShaderType*> ShaderTypes;
TArray<const FShaderPipelineType*> ShaderPipelineTypes;
for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList()); ShaderTypeIt; ShaderTypeIt.Next())
{
FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType();
if (!GlobalShaderType)
{
continue;
}
bool bList = false;
for (int32 PermutationId = 0; PermutationId < GlobalShaderType->GetPermutationCount(); PermutationId++)
{
if (GlobalShaderType->ShouldCompilePermutation(Platform, PermutationId))
{
bList = true;
break;
}
}
if (bList)
{
ShaderTypes.Add(GlobalShaderType);
}
}
for (TLinkedList<FShaderPipelineType*>::TIterator ShaderPipelineIt(FShaderPipelineType::GetTypeList()); ShaderPipelineIt; ShaderPipelineIt.Next())
{
const FShaderPipelineType* Pipeline = *ShaderPipelineIt;
if (Pipeline->IsGlobalTypePipeline())
{
int32 NumStagesNeeded = 0;
auto& StageTypes = Pipeline->GetStages();
for (const FShaderType* Shader : StageTypes)
{
const FGlobalShaderType* GlobalShaderType = Shader->GetGlobalShaderType();
if (GlobalShaderType->ShouldCompilePermutation(Platform, /* PermutationId = */ 0))
{
++NumStagesNeeded;
}
else
{
break;
}
}
if (NumStagesNeeded == StageTypes.Num())
{
ShaderPipelineTypes.Add(Pipeline);
}
}
}
// Individual shader dependencies
ShaderTypes.Sort(FCompareShaderTypes());
for (int32 TypeIndex = 0; TypeIndex < ShaderTypes.Num(); TypeIndex++)
{
FShaderType* ShaderType = ShaderTypes[TypeIndex];
FShaderTypeDependency Dependency(ShaderType, Platform);
const TCHAR* ShaderFilename = Dependency.ShaderType->GetShaderFilename();
TArray<FShaderTypeDependency>& Dependencies = ShaderFilenameToDependenciesMap.FindOrAdd(ShaderFilename);
Dependencies.Add(Dependency);
}
// Shader pipeline dependencies
ShaderPipelineTypes.Sort(FCompareShaderPipelineNameTypes());
for (int32 TypeIndex = 0; TypeIndex < ShaderPipelineTypes.Num(); TypeIndex++)
{
const FShaderPipelineType* Pipeline = ShaderPipelineTypes[TypeIndex];
FShaderPipelineTypeDependency Dependency(Pipeline, Platform);
ShaderPipelineTypeDependencies.Add(Dependency);
}
}
void FGlobalShaderMapId::AppendKeyString(FString& KeyString, const TArray<FShaderTypeDependency>& Dependencies) const
{
#if WITH_EDITOR
TMap<const TCHAR*,FCachedUniformBufferDeclaration> ReferencedUniformBuffers;
for (int32 ShaderIndex = 0; ShaderIndex < Dependencies.Num(); ShaderIndex++)
{
const FShaderTypeDependency& ShaderTypeDependency = Dependencies[ShaderIndex];
KeyString += TEXT("_");
KeyString += ShaderTypeDependency.ShaderType->GetName();
KeyString += FString::Printf(TEXT("%i"), ShaderTypeDependency.PermutationId);
// Add the type's source hash so that we can invalidate cached shaders when .usf changes are made
KeyString += ShaderTypeDependency.SourceHash.ToString();
// Add the serialization history to the key string so that we can detect changes to global shader serialization without a corresponding .usf change
ShaderTypeDependency.ShaderType->GetSerializationHistory().AppendKeyString(KeyString);
const TMap<const TCHAR*, FCachedUniformBufferDeclaration>& ReferencedUniformBufferStructsCache = ShaderTypeDependency.ShaderType->GetReferencedUniformBufferStructsCache();
// Gather referenced uniform buffers
for (TMap<const TCHAR*, FCachedUniformBufferDeclaration>::TConstIterator It(ReferencedUniformBufferStructsCache); It; ++It)
{
ReferencedUniformBuffers.Add(It.Key(), It.Value());
}
}
for (int32 Index = 0; Index < ShaderPipelineTypeDependencies.Num(); ++Index)
{
const FShaderPipelineTypeDependency& Dependency = ShaderPipelineTypeDependencies[Index];
KeyString += TEXT("_");
KeyString += Dependency.ShaderPipelineType->GetName();
// Add the type's source hash so that we can invalidate cached shaders when .usf changes are made
KeyString += Dependency.StagesSourceHash.ToString();
for (const FShaderType* ShaderType : Dependency.ShaderPipelineType->GetStages())
{
const TMap<const TCHAR*, FCachedUniformBufferDeclaration>& ReferencedUniformBufferStructsCache = ShaderType->GetReferencedUniformBufferStructsCache();
// Gather referenced uniform buffers
for (TMap<const TCHAR*, FCachedUniformBufferDeclaration>::TConstIterator It(ReferencedUniformBufferStructsCache); It; ++It)
{
ReferencedUniformBuffers.Add(It.Key(), It.Value());
}
}
}
{
TArray<uint8> TempData;
FSerializationHistory SerializationHistory;
FMemoryWriter Ar(TempData, true);
FShaderSaveArchive SaveArchive(Ar, SerializationHistory);
// Save uniform buffer member info so we can detect when layout has changed
SerializeUniformBufferInfo(SaveArchive, ReferencedUniformBuffers);
SerializationHistory.AppendKeyString(KeyString);
}
#endif // WITH_EDITOR
}
FGlobalShader::FGlobalShader(const ShaderMetaType::CompiledShaderInitializerType& Initializer)
: FShader(Initializer)
{}
void BackupGlobalShaderMap(FGlobalShaderBackupData& OutGlobalShaderBackup)
{
for (int32 i = (int32)ERHIFeatureLevel::ES2; i < (int32)ERHIFeatureLevel::Num; ++i)
{
EShaderPlatform ShaderPlatform = GetFeatureLevelShaderPlatform((ERHIFeatureLevel::Type)i);
if (ShaderPlatform < EShaderPlatform::SP_NumPlatforms && GGlobalShaderMap[ShaderPlatform] != nullptr)
{
TUniquePtr<TArray<uint8>> ShaderData = MakeUnique<TArray<uint8>>();
FMemoryWriter Ar(*ShaderData);
GGlobalShaderMap[ShaderPlatform]->SerializeInline(Ar, true, true, false, nullptr);
GGlobalShaderMap[ShaderPlatform]->RegisterSerializedShaders(false);
GGlobalShaderMap[ShaderPlatform]->Empty();
OutGlobalShaderBackup.FeatureLevelShaderData[i] = MoveTemp(ShaderData);
}
}
// Remove cached references to global shaders
for (TLinkedList<FGlobalBoundShaderStateResource*>::TIterator It(FGlobalBoundShaderStateResource::GetGlobalBoundShaderStateList()); It; It.Next())
{
BeginUpdateResourceRHI(*It);
}
}
void RestoreGlobalShaderMap(const FGlobalShaderBackupData& GlobalShaderBackup)
{
for (int32 i = (int32)ERHIFeatureLevel::ES2; i < (int32)ERHIFeatureLevel::Num; ++i)
{
EShaderPlatform ShaderPlatform = GetFeatureLevelShaderPlatform((ERHIFeatureLevel::Type)i);
if (GlobalShaderBackup.FeatureLevelShaderData[i] != nullptr
&& ShaderPlatform < EShaderPlatform::SP_NumPlatforms
&& GGlobalShaderMap[ShaderPlatform] != nullptr)
{
FMemoryReader Ar(*GlobalShaderBackup.FeatureLevelShaderData[i]);
GGlobalShaderMap[ShaderPlatform]->SerializeInline(Ar, true, true, false, nullptr);
GGlobalShaderMap[ShaderPlatform]->RegisterSerializedShaders(false);
}
}
}
TShaderMap<FGlobalShaderType>* GetGlobalShaderMap(EShaderPlatform Platform)
{
// If the global shader map hasn't been created yet
check(GGlobalShaderMap[Platform]);
return GGlobalShaderMap[Platform];
}