/** Restores systems that need references to classes in the renderer module. */ void RestoreReferencesToRendererModuleClasses( const TMap<UWorld*, bool>& WorldsToUpdate, const TMap<FMaterialShaderMap*, TScopedPointer<TArray<uint8> > >& ShaderMapToSerializedShaderData, const TScopedPointer<TArray<uint8> >& GlobalShaderData, const TMap<FShaderType*, FString>& ShaderTypeNames, const TMap<FVertexFactoryType*, FString>& VertexFactoryTypeNames) { FlushShaderFileCache(); // Initialize cached shader type data InitializeShaderTypes(); IRendererModule& RendererModule = GetRendererModule(); FSceneViewStateReference::AllocateAll(); // Recreate all renderer scenes for (TMap<UWorld*, bool>::TConstIterator It(WorldsToUpdate); It; ++It) { UWorld* World = It.Key(); RendererModule.AllocateScene(World, World->RequiresHitProxies(), It.Value(), World->FeatureLevel); for (int32 LevelIndex = 0; LevelIndex < World->GetNumLevels(); LevelIndex++) { ULevel* Level = World->GetLevel(LevelIndex); Level->InitializeRenderingResources(); } } // Restore FShaders from the serialized memory blobs // Shader maps may still not be complete after this due to code changes picked up in the recompile RestoreGlobalShaderMap(GRHIShaderPlatform_DEPRECATED, *GlobalShaderData); UMaterial::RestoreMaterialShadersFromMemory(GRHIShaderPlatform_DEPRECATED, ShaderMapToSerializedShaderData); FMaterialShaderMap::FixupShaderTypes(GRHIShaderPlatform_DEPRECATED, ShaderTypeNames, VertexFactoryTypeNames); TArray<FShaderType*> OutdatedShaderTypes; TArray<const FVertexFactoryType*> OutdatedFactoryTypes; FShaderType::GetOutdatedTypes(OutdatedShaderTypes, OutdatedFactoryTypes); // Recompile any missing shaders UMaterialInterface::IterateOverActiveFeatureLevels([&](ERHIFeatureLevel::Type FeatureLevel) { auto ShaderPlatform = GShaderPlatformForFeatureLevel[FeatureLevel]; BeginRecompileGlobalShaders(OutdatedShaderTypes, ShaderPlatform); UMaterial::UpdateMaterialShaders(OutdatedShaderTypes, OutdatedFactoryTypes, ShaderPlatform); }); // Block on global shader jobs FinishRecompileGlobalShaders(); }
void RecompileShadersForRemote( const FString& PlatformName, EShaderPlatform ShaderPlatformToCompile, const FString& OutputDirectory, const TArray<FString>& MaterialsToLoad, const TArray<uint8>& SerializedShaderResources, TArray<uint8>* MeshMaterialMaps, TArray<FString>* ModifiedFiles, bool bCompileChangedShaders ) { // figure out what shader platforms to recompile ITargetPlatformManagerModule* TPM = GetTargetPlatformManager(); ITargetPlatform* TargetPlatform = TPM->FindTargetPlatform(PlatformName); if (TargetPlatform == NULL) { UE_LOG(LogShaders, Display, TEXT("Failed to find target platform module for %s"), *PlatformName); return; } TArray<FName> DesiredShaderFormats; TargetPlatform->GetAllTargetedShaderFormats(DesiredShaderFormats); UE_LOG(LogShaders, Display, TEXT("Loading %d materials..."), MaterialsToLoad.Num()); // make sure all materials the client has loaded will be processed TArray<UMaterialInterface*> MaterialsToCompile; for (int32 Index = 0; Index < MaterialsToLoad.Num(); Index++) { UE_LOG(LogShaders, Display, TEXT(" --> %s"), *MaterialsToLoad[Index]); MaterialsToCompile.Add(LoadObject<UMaterialInterface>(NULL, *MaterialsToLoad[Index])); } UE_LOG(LogShaders, Display, TEXT(" Done!")) // figure out which shaders are out of date TArray<FShaderType*> OutdatedShaderTypes; TArray<const FVertexFactoryType*> OutdatedFactoryTypes; // Pick up new changes to shader files FlushShaderFileCache(); if( bCompileChangedShaders ) { FShaderType::GetOutdatedTypes( OutdatedShaderTypes, OutdatedFactoryTypes ); UE_LOG( LogShaders, Display, TEXT( "We found %d out of date shader types, and %d out of date VF types!" ), OutdatedShaderTypes.Num(), OutdatedFactoryTypes.Num() ); } { for (int32 FormatIndex = 0; FormatIndex < DesiredShaderFormats.Num(); FormatIndex++) { // get the shader platform enum const EShaderPlatform ShaderPlatform = ShaderFormatToLegacyShaderPlatform(DesiredShaderFormats[FormatIndex]); // Only compile for the desired platform if requested if (ShaderPlatform == ShaderPlatformToCompile || ShaderPlatformToCompile == SP_NumPlatforms) { if( bCompileChangedShaders ) { // Kick off global shader recompiles BeginRecompileGlobalShaders( OutdatedShaderTypes, ShaderPlatform ); // Block on global shaders FinishRecompileGlobalShaders(); } // we only want to actually compile mesh shaders if a client directly requested it, and there's actually some work to do if (MeshMaterialMaps != NULL && (OutdatedShaderTypes.Num() || OutdatedFactoryTypes.Num() || bCompileChangedShaders == false)) { TMap<FString, TArray<TRefCountPtr<FMaterialShaderMap> > > CompiledShaderMaps; UMaterial::CompileMaterialsForRemoteRecompile(MaterialsToCompile, ShaderPlatform, CompiledShaderMaps); // write the shader compilation info to memory, converting fnames to strings FMemoryWriter MemWriter(*MeshMaterialMaps, true); FNameAsStringProxyArchive Ar(MemWriter); // pull the serialized resource ids into an array of resources TArray<FShaderResourceId> ClientResourceIds; FMemoryReader MemReader(SerializedShaderResources, true); MemReader << ClientResourceIds; // save out the shader map to the byte array FMaterialShaderMap::SaveForRemoteRecompile(Ar, CompiledShaderMaps, ClientResourceIds); } // save it out so the client can get it (and it's up to date next time) FString GlobalShaderFilename = SaveGlobalShaderFile(ShaderPlatform, OutputDirectory); // add this to the list of files to tell the other end about if (ModifiedFiles) { // need to put it in non-sandbox terms FString SandboxPath(GlobalShaderFilename); check(SandboxPath.StartsWith(OutputDirectory)); SandboxPath.ReplaceInline(*OutputDirectory, TEXT("../../../")); FPaths::NormalizeFilename(SandboxPath); ModifiedFiles->Add(SandboxPath); } } } } }