/** 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();
}
Exemplo n.º 2
0
	void ProcessInputFromArchive(FArchive* InputFilePtr, TArray<FJobResult>& OutJobResults)
	{
		int32 NumBatches = 0;

		FArchive& InputFile = *InputFilePtr;
		int32 InputVersion;
		InputFile << InputVersion;
		checkf(ShaderCompileWorkerInputVersion == InputVersion, TEXT("Exiting due to ShaderCompilerWorker expecting input version %d, got %d instead! Did you forget to build ShaderCompilerWorker?"), ShaderCompileWorkerInputVersion, InputVersion);

		TMap<FString, uint16> ReceivedFormatVersionMap;
		InputFile << ReceivedFormatVersionMap;

		VerifyFormatVersions(ReceivedFormatVersionMap);

		InputFile << NumBatches;

		// Flush cache, to make sure we load the latest version of the input file.
		// (Otherwise quick changes to a shader file can result in the wrong output.)
		FlushShaderFileCache();

		for (int32 BatchIndex = 0; BatchIndex < NumBatches; BatchIndex++)
		{
			// Deserialize the job's inputs.
			FShaderCompilerInput CompilerInput;
			InputFile << CompilerInput;

			if (IsValidRef(CompilerInput.SharedEnvironment))
			{
				// Merge the shared environment into the per-shader environment before calling into the compile function
				CompilerInput.Environment.Merge(*CompilerInput.SharedEnvironment);
			}

			// Process the job.
			FShaderCompilerOutput CompilerOutput;
			ProcessCompilationJob(CompilerInput,CompilerOutput,WorkingDirectory);

			// Serialize the job's output.
			FJobResult& JobResult = *new(OutJobResults) FJobResult;
			JobResult.CompilerOutput = CompilerOutput;
		}
	}
Exemplo n.º 3
0
	void ProcessInputFromArchive(FArchive* InputFilePtr, TArray<FJobResult>& OutJobResults)
	{
		int32 NumBatches = 0;

		FArchive& InputFile = *InputFilePtr;
		int32 InputVersion;
		InputFile << InputVersion;
		check(ShaderCompileWorkerInputVersion == InputVersion);

		InputFile << NumBatches;

		// Flush cache, to make sure we load the latest version of the input file.
		// (Otherwise quick changes to a shader file can result in the wrong output.)
		FlushShaderFileCache();

		for (int32 BatchIndex = 0; BatchIndex < NumBatches; BatchIndex++)
		{
			// Deserialize the job's inputs.
			FShaderCompilerInput CompilerInput;
			InputFile << CompilerInput;

			if (IsValidRef(CompilerInput.SharedEnvironment))
			{
				// Merge the shared environment into the per-shader environment before calling into the compile function
				CompilerInput.Environment.Merge(*CompilerInput.SharedEnvironment);
			}

			// Process the job.
			FShaderCompilerOutput CompilerOutput;
			ProcessCompilationJob(CompilerInput,CompilerOutput,WorkingDirectory);

			// Serialize the job's output.
			FJobResult& JobResult = *new(OutJobResults) FJobResult;
			JobResult.CompilerOutput = CompilerOutput;
		}
	}
Exemplo n.º 4
0
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);
				}
			}
		}
	}
}
Exemplo n.º 5
0
TShaderMap<FGlobalShaderType>* GetGlobalShaderMap(EShaderPlatform Platform, bool bRefreshShaderMap)
{
	// No global shaders needed on dedicated server
	if (FPlatformProperties::IsServerOnly())
	{
		if (!GGlobalShaderMap[Platform])
		{
			GGlobalShaderMap[Platform] = new TShaderMap<FGlobalShaderType>();
			return GGlobalShaderMap[Platform];
		}
		return NULL;
	}

	if (bRefreshShaderMap)
	{
		// delete the current global shader map
		delete GGlobalShaderMap[Platform];
		GGlobalShaderMap[Platform] = NULL;

		// make sure we look for updated shader source files
		FlushShaderFileCache();
	}

	// If the global shader map hasn't been created yet, create it.
	if(!GGlobalShaderMap[Platform])
	{
		// GetGlobalShaderMap is called the first time during startup in the main thread.
		check(IsInGameThread());

		FScopedSlowTask SlowTask(70);

		// verify that all shader source files are intact
		SlowTask.EnterProgressFrame(20);
		VerifyShaderSourceFiles();

		GGlobalShaderMap[Platform] = new TShaderMap<FGlobalShaderType>();

		bool bLoadedFromCacheFile = false;

		// Try to load the global shaders from a local cache file if it exists
		// This method is used exclusively with cooked content, since the DDC is not present
		if (FPlatformProperties::RequiresCookedData())
		{
			SlowTask.EnterProgressFrame(50);

			TArray<uint8> GlobalShaderData;
			FString GlobalShaderCacheFilename = FPaths::GetRelativePathToRoot() / GetGlobalShaderCacheFilename(Platform);
			FPaths::MakeStandardFilename(GlobalShaderCacheFilename);
			bLoadedFromCacheFile = FFileHelper::LoadFileToArray(GlobalShaderData, *GlobalShaderCacheFilename, FILEREAD_Silent);

			if (!bLoadedFromCacheFile)
			{
				// Handle this gracefully and exit.
				FString SandboxPath = IFileManager::Get().ConvertToAbsolutePathForExternalAppForWrite(*GlobalShaderCacheFilename);				
				// This can be too early to localize in some situations.
				const FText Message = FText::Format( NSLOCTEXT("Engine", "GlobalShaderCacheFileMissing", "The global shader cache file '{0}' is missing.\n\nYou're running a version of the application built to load COOKED content only, however no COOKED content was found. Consider cooking content for this build, or build and run the UNCOOKED version of the application instead."), FText::FromString( SandboxPath ) );
				if (FPlatformProperties::SupportsWindowedMode())
				{
					UE_LOG(LogMaterial, Error, TEXT("%s"), *Message.ToString());
					FMessageDialog::Open(EAppMsgType::Ok, Message);
					FPlatformMisc::RequestExit(false);
					return NULL;
				}
				else
				{
					UE_LOG(LogMaterial, Fatal, TEXT("%s"), *Message.ToString());
				}
			}

			FMemoryReader MemoryReader(GlobalShaderData);
			SerializeGlobalShaders(MemoryReader, GGlobalShaderMap[Platform]);
		}
		// Uncooked platform
		else
		{
			FGlobalShaderMapId ShaderMapId(Platform);

			TArray<uint8> CachedData;
			SlowTask.EnterProgressFrame(40);
			const FString DataKey = GetGlobalShaderMapKeyString(ShaderMapId, Platform);

			// Find the shader map in the derived data cache
			SlowTask.EnterProgressFrame(10);
			if (GetDerivedDataCacheRef().GetSynchronous(*DataKey, CachedData))
			{
				FMemoryReader Ar(CachedData, true);

				// Deserialize from the cached data
				SerializeGlobalShaders(Ar, GGlobalShaderMap[Platform]);
			}
		}

		// If any shaders weren't loaded, compile them now.
		VerifyGlobalShaders(Platform, bLoadedFromCacheFile);

		extern int32 GCreateShadersOnLoad;
		if (GCreateShadersOnLoad && Platform == GMaxRHIShaderPlatform)
		{
			for (TMap<FShaderType*, TRefCountPtr<FShader> >::TConstIterator ShaderIt(GGlobalShaderMap[Platform]->GetShaders()); ShaderIt; ++ShaderIt)
			{
				FShader* Shader = ShaderIt.Value();

				if (Shader)
				{
					Shader->InitializeResource();
				}
			}
		}
	}
	return GGlobalShaderMap[Platform];
}