您的位置:首页 > 其它

虚幻4 材质的编译。

2016-04-28 00:57 776 查看

\Engine\Source\Runtime\Engine\Private\Materials\MaterialShader.cpp

这个文件中的

/**
* Compiles the shaders for a material and caches them in this shader map.
* @param Material - The material to compile shaders for.
* @param InShaderMapId - the set of static parameters to compile for
* @param Platform - The platform to compile to
*/
void FMaterialShaderMap::Compile(
FMaterial* Material,
const FMaterialShaderMapId& InShaderMapId,
TRefCountPtr<FShaderCompilerEnvironment> MaterialEnvironment,
const FMaterialCompilationOutput& InMaterialCompilationOutput,
EShaderPlatform InPlatform,
bool bSynchronousCompile,
bool bApplyCompletedShaderMapForRendering)
{
if (FPlatformProperties::RequiresCookedData())
{
UE_LOG(LogMaterial, Fatal, TEXT("Trying to compile %s at run-time, which is not supported on consoles!"), *Material->GetFriendlyName() );
}
else
{


然后调用到这里:

Engine\Source\Runtime\Engine\Private\ShaderCompiler\ShaderCompiler.cpp

/** Enqueues a shader compile job with GShaderCompilingManager. */
void GlobalBeginCompileShader(
const FString& DebugGroupName,
FVertexFactoryType* VFType,
FShaderType* ShaderType,
const FShaderPipelineType* ShaderPipelineType,
const TCHAR* SourceFilename,
const TCHAR* FunctionName,
FShaderTarget Target,
FShaderCompileJob* NewJob,
TArray<FShaderCommonCompileJob*>& NewJobs,
bool bAllowDevelopmentShaderCompile
)
{

吧编译一个shader的任务加入队列。

下面的函数没有被调用,不知道为什么,总觉得最后应该调用到他了。但是可以看到这个函数最后调用了 编译函数。

void FShaderCompileThreadRunnable::CompileDirectlyThroughDll()
{
for (int32 WorkerIndex = 0; WorkerIndex < WorkerInfos.Num(); WorkerIndex++)
{
FShaderCompileWorkerInfo& CurrentWorkerInfo = *WorkerInfos[WorkerIndex];

if (CurrentWorkerInfo.QueuedJobs.Num() > 0)
{
for (int32 JobIndex = 0; JobIndex < CurrentWorkerInfo.QueuedJobs.Num(); JobIndex++)
{
FShaderCommonCompileJob& CurrentJob = *CurrentWorkerInfo.QueuedJobs[JobIndex];

check(!CurrentJob.bFinalized);
CurrentJob.bFinalized = true;

static ITargetPlatformManagerModule& TPM = GetTargetPlatformManagerRef();
auto* SingleJob = CurrentJob.GetSingleShaderJob();
if (SingleJob)
{
const FName Format = LegacyShaderPlatformToShaderFormat(EShaderPlatform(SingleJob->Input.Target.Platform));
const IShaderFormat* Compiler = TPM.FindShaderFormat(Format);

if (!Compiler)
{
UE_LOG(LogShaderCompilers, Fatal, TEXT("Can't compile shaders for format %s, couldn't load compiler dll"), *Format.ToString());
}
CA_ASSUME(Compiler != NULL);

if (IsValidRef(SingleJob->Input.SharedEnvironment))
{
// Merge the shared environment into the per-shader environment before calling into the compile function
// Normally this happens in the worker
SingleJob->Input.Environment.Merge(*SingleJob->Input.SharedEnvironment);
}

// Compile the shader directly through the platform dll (directly from the shader dir as the working directory)
Compiler->CompileShader(Format, SingleJob->Input, SingleJob->Output, FString(FPlatformProcess::ShaderDir()));

SingleJob->bSucceeded = SingleJob->Output.bSucceeded;

if (SingleJob->Output.bSucceeded)
{
// Generate a hash of the output and cache it
// The shader processing this output will use it to search for existing FShaderResources
SingleJob->Output.GenerateOutputHash();
}
}
else
{
auto* PipelineJob = CurrentJob.GetShaderPipelineJob();
check(PipelineJob);

EShaderPlatform Platform = (EShaderPlatform)PipelineJob->StageJobs[0]->GetSingleShaderJob()->Input.Target.Platform;
const FName Format = LegacyShaderPlatformToShaderFormat(Platform);
const IShaderFormat* Compiler = TPM.FindShaderFormat(Format);

if (!Compiler)
{
UE_LOG(LogShaderCompilers, Fatal, TEXT("Can't compile shaders for format %s, couldn't load compiler dll"), *Format.ToString());
}
CA_ASSUME(Compiler != NULL);

// Verify same platform on all stages
for (int32 Index = 1; Index < PipelineJob->StageJobs.Num(); ++Index)
{
auto* SingleStage = PipelineJob->StageJobs[Index]->GetSingleShaderJob();
if (!SingleStage)
{
UE_LOG(LogShaderCompilers, Fatal, TEXT("Can't nest Shader Pipelines inside Shader Pipeline '%s'!"), PipelineJob->ShaderPipeline->GetName());
}
if (Platform != SingleStage->Input.Target.Platform)
{
UE_LOG(LogShaderCompilers, Fatal, TEXT("Mismatched Target Platform %s while compiling Shader Pipeline '%s'."), *Format.GetPlainNameString(), PipelineJob->ShaderPipeline->GetName());
}
}

CompileShaderPipeline(Compiler, Format, PipelineJob, FString(FPlatformProcess::ShaderDir()));
}
}

CurrentWorkerInfo.bComplete = true;
}
}
}


我找到了这个

\Engine\Source\Programs\ShaderCompileWorker\Private\ShaderCompileWorker.cpp

目前猜测材质的渲染都是通过这个CPP里面的workerloop完成的。

class FWorkLoop
{
public:
FWorkLoop(const TCHAR* ParentProcessIdText,const TCHAR* InWorkingDirectory,const TCHAR* InInputFilename,const TCHAR* InOutputFilename, TMap<FString, uint16>& InFormatVersionMap)
:	ParentProcessId(FCString::Atoi(ParentProcessIdText))
,	WorkingDirectory(InWorkingDirectory)
,	InputFilename(InInputFilename)
,	OutputFilename(InOutputFilename)
,	InputFilePath(FString(InWorkingDirectory) + InInputFilename)
,	OutputFilePath(FString(InWorkingDirectory) + InOutputFilename)
,	FormatVersionMap(InFormatVersionMap)
{
}

void Loop()
{
UE_LOG(LogShaders, Log, TEXT("Entering job loop"));

while(true)
{
TArray<FJobResult> SingleJobResults;
TArray<FPipelineJobResult> PipelineJobResults;

// Read & Process Input
{
FArchive* InputFilePtr = OpenInputFile();
if(!InputFilePtr)
{
break;
}

UE_LOG(LogShaders, Log, TEXT("Processing shader"));

ProcessInputFromArchive(InputFilePtr, SingleJobResults, PipelineJobResults);

LastCompileTime = FPlatformTime::Seconds();

// Close the input file.
delete InputFilePtr;
}

// Prepare for output
FArchive* OutputFilePtr = CreateOutputArchive();
check(OutputFilePtr);
WriteToOutputArchive(OutputFilePtr, SingleJobResults, PipelineJobResults);

// Close the output file.
delete OutputFilePtr;

// Change the output file name to requested one
IFileManager::Get().Move(*OutputFilePath, *TempFilePath);

if (GShaderCompileUseXGE)
{
// To signal compilation completion, create a zero length file in the working directory.
WriteXGESuccessFile(*WorkingDirectory);

// We only do one pass per process when using XGE.
break;
}
}

UE_LOG(LogShaders, Log, TEXT("Exiting job loop"));
}
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: