Пример #1
0
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;
}
Пример #2
0
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;
}
Пример #3
0
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;
}
bool FMeshMaterialShaderMap::IsComplete(
	const FMeshMaterialShaderMap* MeshShaderMap,
	EShaderPlatform Platform,
	const FMaterial* Material,
	FVertexFactoryType* InVertexFactoryType,
	bool bSilent
	)
{
	// Iterate over all mesh material shader types.
	for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next())
	{
		FMeshMaterialShaderType* ShaderType = ShaderTypeIt->GetMeshMaterialShaderType();
		if (ShaderType && !IsMeshShaderComplete(MeshShaderMap, Platform, Material, ShaderType, nullptr, InVertexFactoryType, bSilent))
		{
			return false;
		}
	}

	// Iterate over all pipeline types
	for (TLinkedList<FShaderPipelineType*>::TIterator ShaderPipelineIt(FShaderPipelineType::GetTypeList());ShaderPipelineIt;ShaderPipelineIt.Next())
	{
		const FShaderPipelineType* ShaderPipelineType = *ShaderPipelineIt;
		if (ShaderPipelineType->IsMeshMaterialTypePipeline())
		{
			auto& Stages = ShaderPipelineType->GetStages();

			// Verify all the ShouldCache are in sync
			int32 NumShouldCache = 0;
			for (int32 Index = 0; Index < Stages.Num(); ++Index)
			{
				auto* ShaderType = Stages[Index]->GetMeshMaterialShaderType();
				if (ShouldCacheMeshShader(ShaderType, Platform, Material, InVertexFactoryType))
				{
					++NumShouldCache;
				}
				else
				{
					break;
				}
			}

			if (NumShouldCache == Stages.Num())
			{
				// Now check the completeness of the shader map
				for (int32 Index = 0; Index < Stages.Num(); ++Index)
				{
					auto* ShaderType = Stages[Index]->GetMeshMaterialShaderType();
					if (ShaderType && !IsMeshShaderComplete(MeshShaderMap, Platform, Material, ShaderType, ShaderPipelineType, InVertexFactoryType, bSilent))
					{
						return false;
					}
				}
			}
		}
	}

	return true;
}
Пример #5
0
FShaderType* FindShaderTypeByName(const TCHAR* ShaderTypeName)
{
	for(TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next())
	{
		if(!FCString::Stricmp(ShaderTypeIt->GetName(),ShaderTypeName))
		{
			return *ShaderTypeIt;
		}
	}
	return NULL;
}
Пример #6
0
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);
	}
}
Пример #7
0
/**
 * 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);
		}
	}
}
void FMeshMaterialShaderMap::LoadMissingShadersFromMemory(
	const FSHAHash& MaterialShaderMapHash, 
	const FMaterial* Material, 
	EShaderPlatform Platform)
{
	for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next())
	{
		FMeshMaterialShaderType* ShaderType = ShaderTypeIt->GetMeshMaterialShaderType();
		if (ShaderType && ShouldCacheMeshShader(ShaderType, Platform, Material, VertexFactoryType) && !HasShader((FShaderType*)ShaderType))
		{
			const FShaderId ShaderId(MaterialShaderMapHash, nullptr, VertexFactoryType, (FShaderType*)ShaderType, FShaderTarget(ShaderType->GetFrequency(), Platform));
			FShader* FoundShader = ((FShaderType*)ShaderType)->FindShaderById(ShaderId);

			if (FoundShader)
			{
				AddShader((FShaderType*)ShaderType, FoundShader);
			}
		}
	}

	// Try to find necessary FShaderPipelineTypes in memory
	for (TLinkedList<FShaderPipelineType*>::TIterator ShaderPipelineIt(FShaderPipelineType::GetTypeList());ShaderPipelineIt;ShaderPipelineIt.Next())
	{
		const FShaderPipelineType* PipelineType = *ShaderPipelineIt;
		if (PipelineType && PipelineType->IsMeshMaterialTypePipeline() && !HasShaderPipeline(PipelineType))
		{
			auto& Stages = PipelineType->GetStages();
			int32 NumShaders = 0;
			for (const FShaderType* Shader : Stages)
			{
				FMeshMaterialShaderType* ShaderType = (FMeshMaterialShaderType*)Shader->GetMeshMaterialShaderType();
				if (ShaderType && ShouldCacheMeshShader(ShaderType, Platform, Material, VertexFactoryType))
				{
					++NumShaders;
				}
				else
				{
					break;
				}
			}

			if (NumShaders == Stages.Num())
			{
				TArray<FShader*> ShadersForPipeline;
				for (auto* Shader : Stages)
				{
					FMeshMaterialShaderType* ShaderType = (FMeshMaterialShaderType*)Shader->GetMeshMaterialShaderType();
					if (!HasShader(ShaderType))
					{
						const FShaderId ShaderId(MaterialShaderMapHash, PipelineType->ShouldOptimizeUnusedOutputs() ? PipelineType : nullptr, VertexFactoryType, ShaderType, FShaderTarget(ShaderType->GetFrequency(), Platform));
						FShader* FoundShader = ShaderType->FindShaderById(ShaderId);
						if (FoundShader)
						{
							AddShader(ShaderType, FoundShader);
							ShadersForPipeline.Add(FoundShader);
						}
					}
				}

				if (ShadersForPipeline.Num() == NumShaders && !HasShaderPipeline(PipelineType))
				{
					auto* Pipeline = new FShaderPipeline(PipelineType, ShadersForPipeline);
					AddShaderPipeline(PipelineType, Pipeline);
				}
			}
		}
	}
}
/**
 * Enqueues compilation for all shaders for a material and vertex factory type.
 * @param Material - The material to compile shaders for.
 * @param VertexFactoryType - The vertex factory type to compile shaders for.
 * @param Platform - The platform to compile for.
 */
uint32 FMeshMaterialShaderMap::BeginCompile(
	uint32 ShaderMapId,
	const FMaterialShaderMapId& InShaderMapId, 
	const FMaterial* Material,
	FShaderCompilerEnvironment* MaterialEnvironment,
	EShaderPlatform Platform,
	TArray<FShaderCommonCompileJob*>& NewJobs
	)
{
	if (!VertexFactoryType)
	{
		return 0;
	}

	uint32 NumShadersPerVF = 0;
	TSet<FString> ShaderTypeNames;

	// Iterate over all mesh material shader types.
	TMap<FShaderType*, FShaderCompileJob*> SharedShaderJobs;
	for (TLinkedList<FShaderType*>::TIterator ShaderTypeIt(FShaderType::GetTypeList());ShaderTypeIt;ShaderTypeIt.Next())
	{
		FMeshMaterialShaderType* ShaderType = ShaderTypeIt->GetMeshMaterialShaderType();
		if (ShaderType && ShouldCacheMeshShader(ShaderType, Platform, Material, VertexFactoryType))
		{
			// Verify that the shader map Id contains inputs for any shaders that will be put into this shader map
			check(InShaderMapId.ContainsVertexFactoryType(VertexFactoryType));
			check(InShaderMapId.ContainsShaderType(ShaderType));

			NumShadersPerVF++;
			// only compile the shader if we don't already have it
			if (!HasShader(ShaderType))
			{
				// Compile this mesh material shader for this material and vertex factory type.
				auto* Job = ShaderType->BeginCompileShader(
					ShaderMapId,
					Platform,
					Material,
					MaterialEnvironment,
					VertexFactoryType,
					nullptr,
					NewJobs
					);
				check(!SharedShaderJobs.Find(ShaderType));
				SharedShaderJobs.Add(ShaderType, Job);
			}
		}
	}

	// Now the pipeline jobs; if it's a shareable pipeline, do not add duplicate jobs
	for (TLinkedList<FShaderPipelineType*>::TIterator ShaderPipelineIt(FShaderPipelineType::GetTypeList());ShaderPipelineIt;ShaderPipelineIt.Next())
	{
		const FShaderPipelineType* Pipeline = *ShaderPipelineIt;
		if (Pipeline->IsMeshMaterialTypePipeline())
		{
			auto& StageTypes = Pipeline->GetStages();
			int32 NumShaderStagesToCompile = 0;
			for (auto* Shader : StageTypes)
			{
				const FMeshMaterialShaderType* ShaderType = Shader->GetMeshMaterialShaderType();
				if (ShouldCacheMeshShader(ShaderType, Platform, Material, VertexFactoryType))
				{
					++NumShaderStagesToCompile;
				}
				else
				{
					break;
				}
			}

			if (NumShaderStagesToCompile == StageTypes.Num())
			{
				// Verify that the shader map Id contains inputs for any shaders that will be put into this shader map
				check(InShaderMapId.ContainsShaderPipelineType(Pipeline));

				if (Pipeline->ShouldOptimizeUnusedOutputs())
				{
					NumShadersPerVF += NumShaderStagesToCompile;
					TArray<FMeshMaterialShaderType*> ShaderStagesToCompile;
					for (auto* Shader : StageTypes)
					{
						const FMeshMaterialShaderType* ShaderType = Shader->GetMeshMaterialShaderType();

						// Verify that the shader map Id contains inputs for any shaders that will be put into this shader map
						check(InShaderMapId.ContainsVertexFactoryType(VertexFactoryType));
						check(InShaderMapId.ContainsShaderType(ShaderType));
						ShaderStagesToCompile.Add((FMeshMaterialShaderType*)ShaderType);
					}

					// Make a pipeline job with all the stages
					FMeshMaterialShaderType::BeginCompileShaderPipeline(ShaderMapId, Platform, Material, MaterialEnvironment, VertexFactoryType, Pipeline, ShaderStagesToCompile, NewJobs);
				}
				else
				{
					// If sharing shaders amongst pipelines, add this pipeline as a dependency of an existing job
					for (const FShaderType* ShaderType : StageTypes)
					{
						FShaderCompileJob** Job = SharedShaderJobs.Find(ShaderType);
						checkf(Job, TEXT("Couldn't find existing shared job for mesh shader %s on pipeline %s!"), ShaderType->GetName(), Pipeline->GetName());
						auto* SingleJob = (*Job)->GetSingleShaderJob();
						auto& PipelinesToShare = SingleJob->SharingPipelines.FindOrAdd(VertexFactoryType);
						check(!PipelinesToShare.Contains(Pipeline));
						PipelinesToShare.Add(Pipeline);
					}
				}
			}
		}
	}

	if (NumShadersPerVF > 0)
	{
		UE_LOG(LogShaders, Verbose, TEXT("			%s - %u shaders"), VertexFactoryType->GetName(), NumShadersPerVF);
	}

	return NumShadersPerVF;
}