void BeginRecompileGlobalShaders(const TArray<FShaderType*>& OutdatedShaderTypes, EShaderPlatform ShaderPlatform) { if( !FPlatformProperties::RequiresCookedData() ) { // Flush pending accesses to the existing global shaders. FlushRenderingCommands(); TShaderMap<FGlobalShaderType>* GlobalShaderMap = GetGlobalShaderMap(ShaderPlatform); for (int32 TypeIndex = 0; TypeIndex < OutdatedShaderTypes.Num(); TypeIndex++) { FGlobalShaderType* CurrentGlobalShaderType = OutdatedShaderTypes[TypeIndex]->GetGlobalShaderType(); if (CurrentGlobalShaderType) { UE_LOG(LogShaders, Log, TEXT("Flushing Global Shader %s"), CurrentGlobalShaderType->GetName()); GlobalShaderMap->RemoveShaderType(CurrentGlobalShaderType); //invalidate global bound shader states so they will be created with the new shaders the next time they are set (in SetGlobalBoundShaderState) for(TLinkedList<FGlobalBoundShaderStateResource*>::TIterator It(FGlobalBoundShaderStateResource::GetGlobalBoundShaderStateList());It;It.Next()) { BeginUpdateResourceRHI(*It); } } } VerifyGlobalShaders(ShaderPlatform, false); } }
void ProcessCompiledGlobalShaders(const TArray<FShaderCompileJob*>& CompilationResults) { UE_LOG(LogShaders, Warning, TEXT("Compiled %u global shaders"), CompilationResults.Num()); TArray<EShaderPlatform> ShaderPlatformsProcessed; for (int32 ResultIndex = 0; ResultIndex < CompilationResults.Num(); ResultIndex++) { const FShaderCompileJob& CurrentJob = *CompilationResults[ResultIndex]; FGlobalShaderType* GlobalShaderType = CurrentJob.ShaderType->GetGlobalShaderType(); check(GlobalShaderType); FShader* Shader = GlobalShaderType->FinishCompileShader(CurrentJob); if (Shader) { // Add the new global shader instance to the global shader map. EShaderPlatform Platform = (EShaderPlatform)CurrentJob.Input.Target.Platform; GGlobalShaderMap[Platform]->AddShader(GlobalShaderType,Shader); ShaderPlatformsProcessed.AddUnique(Platform); } else { UE_LOG(LogShaders, Fatal,TEXT("Failed to compile global shader %s. Enable 'r.ShaderDevelopmentMode' in ConsoleVariables.ini for retries."), GlobalShaderType->GetName()); } } for (int32 PlatformIndex = 0; PlatformIndex < ShaderPlatformsProcessed.Num(); PlatformIndex++) { // Save the global shader map for any platforms that were recompiled SaveGlobalShaderMapToDerivedDataCache(ShaderPlatformsProcessed[PlatformIndex]); } }
bool IsGlobalShaderMapComplete(const TCHAR* TypeNameSubstring) { for (int32 i = 0; i < SP_NumPlatforms; ++i) { EShaderPlatform Platform = (EShaderPlatform)i; TShaderMap<FGlobalShaderType>* GlobalShaderMap = GGlobalShaderMap[Platform]; if (GlobalShaderMap) { for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList()); ShaderTypeIt; ShaderTypeIt.Next()) { FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType(); if (GlobalShaderType && (TypeNameSubstring == nullptr || (FPlatformString::Strstr(GlobalShaderType->GetName(), TypeNameSubstring) != nullptr)) && GlobalShaderType->ShouldCache(Platform)) { if (!GlobalShaderMap->HasShader(GlobalShaderType)) { return false; } } } } } return true; }
bool AreGlobalShadersComplete(const TCHAR* TypeNameSubstring) { EShaderPlatform Platform = GRHIShaderPlatform; TShaderMap<FGlobalShaderType>* GlobalShaderMap = GGlobalShaderMap[Platform]; if (GlobalShaderMap) { for(TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next()) { FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType(); if (GlobalShaderType && FPlatformString::Strstr(GlobalShaderType->GetName(), TypeNameSubstring) != NULL && GlobalShaderType->ShouldCache(Platform)) { if (!GlobalShaderMap->HasShader(GlobalShaderType)) { return false; } } } return true; } return false; }
bool IsGlobalShaderMapComplete() { EShaderPlatform Platform = GRHIShaderPlatform; TShaderMap<FGlobalShaderType>* GlobalShaderMap = GGlobalShaderMap[Platform]; if (GlobalShaderMap) { for(TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next()) { FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType(); if (GlobalShaderType && GlobalShaderType->ShouldCache(Platform)) { if (!GlobalShaderMap->HasShader(GlobalShaderType)) { return false; } } } return true; } return false; }
FGlobalShaderMapId::FGlobalShaderMapId(EShaderPlatform Platform) { TArray<FShaderType*> ShaderTypes; for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList()); ShaderTypeIt; ShaderTypeIt.Next()) { FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType(); if (GlobalShaderType && GlobalShaderType->ShouldCache(Platform)) { ShaderTypes.Add(GlobalShaderType); } } ShaderTypes.Sort(FCompareShaderTypes()); for (int32 TypeIndex = 0; TypeIndex < ShaderTypes.Num(); TypeIndex++) { FShaderTypeDependency Dependency; Dependency.ShaderType = ShaderTypes[TypeIndex]; Dependency.SourceHash = ShaderTypes[TypeIndex]->GetSourceHash(); ShaderTypeDependencies.Add(Dependency); } }
/** * Makes sure all global shaders are loaded and/or compiled for the passed in platform. * Note: if compilation is needed, this only kicks off the compile. * * @param Platform Platform to verify global shaders for */ void VerifyGlobalShaders(EShaderPlatform Platform, bool bLoadedFromCacheFile) { check(IsInGameThread()); check(!FPlatformProperties::IsServerOnly()); check(GGlobalShaderMap[Platform]); UE_LOG(LogShaders, Log, TEXT("Verifying Global Shaders for %s"), *LegacyShaderPlatformToShaderFormat(Platform).ToString()); // Ensure that the global shader map contains all global shader types. TShaderMap<FGlobalShaderType>* GlobalShaderMap = GetGlobalShaderMap(Platform); const bool bEmptyMap = GlobalShaderMap->IsEmpty(); if (bEmptyMap) { UE_LOG(LogShaders, Warning, TEXT(" Empty global shader map, recompiling all global shaders")); } TArray<FShaderCompileJob*> GlobalShaderJobs; for(TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next()) { FGlobalShaderType* GlobalShaderType = ShaderTypeIt->GetGlobalShaderType(); if(GlobalShaderType && GlobalShaderType->ShouldCache(Platform)) { if(!GlobalShaderMap->HasShader(GlobalShaderType)) { bool bErrorOnMissing = bLoadedFromCacheFile; if (FPlatformProperties::RequiresCookedData()) { // We require all shaders to exist on cooked platforms because we can't compile them. bErrorOnMissing = true; } if (bErrorOnMissing) { UE_LOG(LogShaders, Fatal,TEXT("Missing global shader %s, Please make sure cooking was successful."), GlobalShaderType->GetName()); } if (!bEmptyMap) { UE_LOG(LogShaders, Warning, TEXT(" %s"), GlobalShaderType->GetName()); } // Compile this global shader type. GlobalShaderType->BeginCompileShader(Platform, GlobalShaderJobs); } } } if (GlobalShaderJobs.Num() > 0) { GShaderCompilingManager->AddJobs(GlobalShaderJobs, true, true); const bool bAllowAsynchronousGlobalShaderCompiling = // OpenGL requires that global shader maps are compiled before attaching // primitives to the scene as it must be able to find FNULLPS. // TODO_OPENGL: Allow shaders to be compiled asynchronously. !IsOpenGLPlatform(GMaxRHIShaderPlatform) && GShaderCompilingManager->AllowAsynchronousShaderCompiling(); if (!bAllowAsynchronousGlobalShaderCompiling) { TArray<int32> ShaderMapIds; ShaderMapIds.Add(GlobalShaderMapId); GShaderCompilingManager->FinishCompilation(TEXT("Global"), ShaderMapIds); } } }