Files
UnrealEngineUWP/Engine/Source/Programs/CrossCompilerTool/Private/CrossCompilerTool.cpp
Matthew Griffin bb70b349ce Merging CL 2804086 from //UE4/Release-4.11 to Dev-Main (//UE4/Dev-Main) to isolate copyright update
#lockdown Nick.Penwarden

[CL 2819020 by Matthew Griffin in Main branch]
2016-01-07 08:17:16 -05:00

260 lines
6.8 KiB
C++

// Copyright 1998-2016 Epic Games, Inc. All Rights Reserved.
// CrossCompilerTool.cpp: Driver for testing compilation of an individual shader
#include "CrossCompilerTool.h"
#include "hlslcc.h"
#include "MetalBackend.h"
#include "GlslBackend.h"
#include "HlslAST.h"
#include "HlslLexer.h"
#include "HlslParser.h"
#include "ShaderPreprocessor.h"
#include "ShaderCompilerCommon.h"
#include "RequiredProgramMainCPPInclude.h"
DEFINE_LOG_CATEGORY(LogCrossCompilerTool);
IMPLEMENT_APPLICATION(CrossCompilerTool, "CrossCompilerTool");
namespace CCT
{
static bool Preprocess(const FString& InputFile, FString& Output)
{
FShaderCompilerInput CompilerInput;
CompilerInput.SourceFilename = InputFile;
FShaderCompilerOutput CompilerOutput;
TArray<FShaderCompilerError> Errors;
return PreprocessShaderFile(Output, Errors, InputFile);
}
static void DumpMessages(CrossCompiler::FCompilerMessages& Messages)
{
for (auto& Message : Messages.MessageList)
{
if (Message.bIsError)
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("%s"), *Message.Message);
}
else
{
UE_LOG(LogCrossCompilerTool, Warning, TEXT("%s"), *Message.Message);
}
}
}
static int32 Run(const FRunInfo& RunInfo)
{
ILanguageSpec* Language = nullptr;
FCodeBackend* Backend = nullptr;
EHlslCompileTarget CompileTarget = RunInfo.Target;
uint32 Flags = HLSLCC_PackUniforms;
Flags |= RunInfo.bValidate ? 0 : HLSLCC_NoValidation;
Flags |= RunInfo.bRunCPP ? 0 : HLSLCC_NoPreprocess;
Flags |= RunInfo.bPackIntoUBs ? HLSLCC_PackUniformsIntoUniformBuffers : 0;
Flags |= RunInfo.bUseDX11Clip ? HLSLCC_DX11ClipSpace : 0;
Flags |= RunInfo.bFlattenUBs ? HLSLCC_FlattenUniformBuffers : 0;
Flags |= RunInfo.bFlattenUBStructs ? HLSLCC_FlattenUniformBufferStructures : 0;
Flags |= RunInfo.bGroupFlattenUBs ? HLSLCC_GroupFlattenedUniformBuffers : 0;
Flags |= RunInfo.bCSE ? HLSLCC_ApplyCommonSubexpressionElimination : 0;
Flags |= RunInfo.bExpandExpressions ? HLSLCC_ExpandSubexpressions : 0;
Flags |= RunInfo.bFixAtomics ? HLSLCC_FixAtomicReferences : 0;
Flags |= RunInfo.bSeparateShaders ? HLSLCC_SeparateShaderObjects : 0;
FGlslLanguageSpec GlslLanguage(RunInfo.Target == HCT_FeatureLevelES2);
FGlslCodeBackend GlslBackend(Flags, RunInfo.Target);
FMetalLanguageSpec MetalLanguage;
FMetalCodeBackend MetalBackend(Flags, CompileTarget);
switch (RunInfo.BackEnd)
{
case CCT::FRunInfo::BE_Metal:
Language = &MetalLanguage;
Backend = &MetalBackend;
CompileTarget = HCT_FeatureLevelES3_1;
break;
case CCT::FRunInfo::BE_OpenGL:
Language = &GlslLanguage;
Backend = &GlslBackend;
Flags |= HLSLCC_DX11ClipSpace;
break;
default:
return 1;
}
FString HLSLShaderSource;
if (RunInfo.bUseNew)
{
if (RunInfo.bList)
{
if (!FFileHelper::LoadFileToString(HLSLShaderSource, *RunInfo.InputFile))
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Couldn't load Input file '%s'!"), *RunInfo.InputFile);
return 1;
}
TArray<FString> List;
if (!FFileHelper::LoadANSITextFileToStrings(*RunInfo.InputFile, &IFileManager::Get(), List))
{
return 1;
}
int32 Count = 0;
for (auto& File : List)
{
FString HLSLShader;
if (!FFileHelper::LoadFileToString(HLSLShader, *File))
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Couldn't load Input file '%s'!"), *File);
continue;
}
UE_LOG(LogCrossCompilerTool, Log, TEXT("%d: %s"), Count++, *File);
CrossCompiler::FCompilerMessages Messages;
if (!CrossCompiler::Parser::Parse(HLSLShader, File, Messages))
{
DumpMessages(Messages);
UE_LOG(LogCrossCompilerTool, Log, TEXT("Error compiling '%s'!"), *File);
return 1;
}
DumpMessages(Messages);
}
}
else
{
if (RunInfo.bRunCPP)
{
//GMalloc->DumpAllocatorStats(*FGenericPlatformOutputDevices::GetLog());
if (!Preprocess(RunInfo.InputFile, HLSLShaderSource))
{
UE_LOG(LogCrossCompilerTool, Log, TEXT("Error during preprocessor on '%s'!"), *RunInfo.InputFile);
return 1;
}
//GMalloc->DumpAllocatorStats(*FGenericPlatformOutputDevices::GetLog());
}
else
{
if (!FFileHelper::LoadFileToString(HLSLShaderSource, *RunInfo.InputFile))
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Couldn't load Input file '%s'!"), *RunInfo.InputFile);
return 1;
}
}
if (RunInfo.bPreprocessOnly)
{
return 0;
}
CrossCompiler::FCompilerMessages Messages;
if (!CrossCompiler::Parser::Parse(HLSLShaderSource, *RunInfo.InputFile, Messages))
{
UE_LOG(LogCrossCompilerTool, Log, TEXT("Error compiling '%s'!"), *RunInfo.InputFile);
DumpMessages(Messages);
return 1;
}
DumpMessages(Messages);
}
//Scanner.Dump();
return 0;
}
else
{
if (!FFileHelper::LoadFileToString(HLSLShaderSource, *RunInfo.InputFile))
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Couldn't load Input file '%s'!"), *RunInfo.InputFile);
return 1;
}
}
ANSICHAR* ShaderSource = 0;
ANSICHAR* ErrorLog = 0;
FHlslCrossCompilerContext Context(Flags, RunInfo.Frequency, CompileTarget);
if (Context.Init(TCHAR_TO_ANSI(*RunInfo.InputFile), Language))
{
Context.Run(
TCHAR_TO_ANSI(*HLSLShaderSource),
TCHAR_TO_ANSI(*RunInfo.Entry),
Backend,
&ShaderSource,
&ErrorLog);
}
if (ErrorLog)
{
FString OutError(ANSI_TO_TCHAR(ErrorLog));
UE_LOG(LogCrossCompilerTool, Warning, TEXT("%s"), *OutError);
}
if (ShaderSource)
{
FString OutSource(ANSI_TO_TCHAR(ShaderSource));
UE_LOG(LogCrossCompilerTool, Display, TEXT("%s"), *OutSource);
if (RunInfo.OutputFile.Len() > 0)
{
FFileHelper::SaveStringToFile(OutSource, *RunInfo.OutputFile);
}
}
if (ShaderSource)
{
const ANSICHAR* USFSource = ShaderSource;
CrossCompiler::FHlslccHeader CCHeader;
int32 Len = FCStringAnsi::Strlen(USFSource);
if (!CCHeader.Read(USFSource, Len))
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Bad hlslcc header found"));
}
if (Language == &GlslLanguage && *USFSource != '#')
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Bad hlslcc header found! Missing '#'!"));
}
}
free(ShaderSource);
free(ErrorLog);
return 0;
}
}
INT32_MAIN_INT32_ARGC_TCHAR_ARGV()
{
GEngineLoop.PreInit(ArgC, ArgV, TEXT("-NOPACKAGECACHE -Multiprocess"));
TArray<FString> Tokens, Switches;
FCommandLine::Parse(FCommandLine::Get(), Tokens, Switches);
if (Tokens.Num() < 1)
{
UE_LOG(LogCrossCompilerTool, Error, TEXT("Missing input file!"));
CCT::PrintUsage();
return 1;
}
if (Tokens.Num() > 1)
{
UE_LOG(LogCrossCompilerTool, Warning,TEXT("Ignoring extra command line arguments!"));
}
CCT::FRunInfo RunInfo;
if (!RunInfo.Setup(Tokens[0], Switches))
{
return 1;
}
int32 Value = CCT::Run(RunInfo);
//FGenericPlatformOutputDevices::GetLog()->Flush();
return Value;
}