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);
		}
	}
}
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)
		{
			TArray<uint8>* ShaderData = new TArray<uint8>();
			FMemoryWriter Ar(*ShaderData);
			GGlobalShaderMap[ShaderPlatform]->SerializeInline(Ar, true, true);
			GGlobalShaderMap[ShaderPlatform]->Empty();
			OutGlobalShaderBackup.FeatureLevelShaderData[i] = ShaderData;
		}
	}

	// Remove cached references to global shaders
	for (TLinkedList<FGlobalBoundShaderStateResource*>::TIterator It(FGlobalBoundShaderStateResource::GetGlobalBoundShaderStateList()); It; It.Next())
	{
		BeginUpdateResourceRHI(*It);
	}
}
/**
 * Build Shaders to compute tex coord scale per texture.
 *
 * @param InWorld			The world to build streaming for.
 * @param QualityLevel		The quality level for the shaders.
 * @param FeatureLevel		The feature level for the shaders.
 * @param TexCoordScales	The map to store material interfaces used by the current primitive world.
 * @param MaterialToLevels	The map to bind a material to all levels where primitives are refering it.
 * @param bIncremental		true if the build should only update components that have no data.
 * @return true if the operation is a success, false if it was canceled.
 */
ENGINE_API bool BuildTextureStreamingShaders(UWorld* InWorld, EMaterialQualityLevel::Type QualityLevel, ERHIFeatureLevel::Type FeatureLevel, OUT FTexCoordScaleMap& TexCoordScales, OUT FMaterialToLevelsMap& MaterialToLevels, bool bIncremental, FSlowTask& BuildTextureStreamingTask)
{
#if WITH_EDITORONLY_DATA

    if (!InWorld || !GShaderCompilingManager) return false;

    const bool bUseNewMetrics = CVarStreamingUseNewMetrics.GetValueOnGameThread() != 0;
    const double StartTime = FPlatformTime::Seconds();

    FlushRenderingCommands();

    if (!WaitForShaderCompilation(LOCTEXT("TextureStreamingBuild_FinishPendingShadersCompilation", "Waiting For Pending Shaders Compilation"), BuildTextureStreamingTask))
    {
        return false;
    }

    if (!bIncremental)
    {
        FDebugViewModeMaterialProxy::ClearAllShaders();
    }
    else // Otherwise, if there are no shaders, then we need to rebuild them all.
    {
        bIncremental = FDebugViewModeMaterialProxy::HasAnyShaders();
    }

    // Without the new metrics, the shaders will are not compiled, making the texcoord scale viewmode non functional.
    if (bUseNewMetrics && AllowDebugViewPS(DVSM_MaterialTexCoordScalesAnalysis, GetFeatureLevelShaderPlatform(FeatureLevel)))
    {
        const float NumPrimitiveComponents = (float)GetNumTextureStreamingPrimitives(InWorld);

        {
            FScopedSlowTask SlowTask(NumPrimitiveComponents, (LOCTEXT("TextureStreamingBuild_ParsingPrimitiveMaterials ", "Parsing Primitive Materials")));
            for (int32 LevelIndex = 0; LevelIndex < InWorld->GetNumLevels(); LevelIndex++)
            {
                ULevel* Level = InWorld->GetLevel(LevelIndex);

                TArray<UPrimitiveComponent*> Components;
                GetTextureStreamingPrimitives(Level, Components);
                for (UPrimitiveComponent* Primitive : Components)
                {
                    SlowTask.EnterProgressFrame();
                    BuildTextureStreamingTask.EnterProgressFrame(1.f / NumPrimitiveComponents);
                    if (GWarn->ReceivedUserCancel())
                    {
                        FDebugViewModeMaterialProxy::ClearAllShaders();
                        return false;
                    }

                    // When only updating (viewmode path), skip primitives that already have data.
                    if (bIncremental && Primitive->HasStreamingSectionData(true))
                        continue;

                    TArray<UMaterialInterface*> Materials;
                    Primitive->GetUsedMaterials(Materials);

                    for (UMaterialInterface* MaterialInterface : Materials)
                    {
                        if (!MaterialInterface) continue;

                        // Landscape material resources can not be used. See logic in FLandscapeMaterialResource::ShouldCache().
                        const FMaterial* Material = MaterialInterface->GetMaterialResource(FeatureLevel);
                        if (!Material || Material->IsUsedWithLandscape())
                        {
                            UE_LOG(TextureStreamingBuild, Verbose, TEXT("Landscape material %s not supported, skipping shader"), *MaterialInterface->GetName());
                            continue;
                        }

                        if (!TexCoordScales.Contains(MaterialInterface))
                        {
                            TexCoordScales.Add(MaterialInterface);
                            FDebugViewModeMaterialProxy::AddShader(MaterialInterface, QualityLevel, FeatureLevel, EMaterialShaderMapUsage::DebugViewModeTexCoordScale);
                        }
                        MaterialToLevels.FindOrAdd(MaterialInterface).AddUnique(Level);
                    }
                }
            }
        }

        if (WaitForShaderCompilation(LOCTEXT("TextureStreamingBuild_CompTexCoordScaleShaders", "Compiling Shaders For TexCoord Scale Analysis "), BuildTextureStreamingTask))
        {
            // Check The validity of all shaders, removing invalid entries
            FDebugViewModeMaterialProxy::ValidateAllShaders(TexCoordScales);
            return true;
        }
        else
        {
            FDebugViewModeMaterialProxy::ClearAllShaders();
            return false;
        }
    }
    else
    {
        return true; // Nothing to build but this is not an error.
    }

#else
    UE_LOG(TextureStreamingBuild, Fatal,TEXT("Build Texture Streaming Shaders should not be called on a console"));
    return false;
#endif
}