Files
UnrealEngine/Engine/Plugins/Experimental/NNERuntimeIREE/Source/IREEUtils/Private/IREEUtils.cpp
Brandyn / Techy fcc1b09210 init
2026-04-04 15:40:51 -05:00

150 lines
4.6 KiB
C++

// Copyright Epic Games, Inc. All Rights Reserved.
#include "IREEUtils.h"
#include "HAL/PlatformFileManager.h"
#include "IREEUtilsLog.h"
#include "Misc/FileHelper.h"
#include "Misc/MonitoredProcess.h"
#include "Misc/Paths.h"
namespace UE::IREEUtils
{
bool ResolveEnvironmentVariables(FString& String)
{
const FString StartString = "$ENV{";
const FString EndString = "}";
FString ResultString = String;
int32 StartIndex = ResultString.Find(StartString, ESearchCase::CaseSensitive);
while (StartIndex != INDEX_NONE)
{
StartIndex += StartString.Len();
int32 EndIndex = ResultString.Find(EndString, ESearchCase::CaseSensitive, ESearchDir::FromStart, StartIndex);
if (EndIndex > StartIndex)
{
FString EnvironmentVariableName = ResultString.Mid(StartIndex, EndIndex - StartIndex);
FString EnvironmentVariableValue = FPlatformMisc::GetEnvironmentVariable(*EnvironmentVariableName);
if (EnvironmentVariableValue.IsEmpty())
{
return false;
}
else
{
ResultString.ReplaceInline(*(StartString + EnvironmentVariableName + EndString), *EnvironmentVariableValue, ESearchCase::CaseSensitive);
}
}
else
{
return false;
}
StartIndex = ResultString.Find(StartString, ESearchCase::CaseSensitive);
}
String = ResultString;
return true;
}
void RunCommand(const FString& Command, const FString& Arguments, const FString& WorkingDir, const FString& LogFilePath)
{
int32 ReturnCode = 0;
bool IsCanceled = false;
FMonitoredProcess Process(Command, Arguments, WorkingDir, true);
Process.OnCompleted().BindLambda([&ReturnCode] (int32 _ReturnCode) { ReturnCode = _ReturnCode; });
Process.OnCanceled().BindLambda([&IsCanceled] (){ IsCanceled = true; });
if (!Process.Launch())
{
UE_LOG(LogIREEUtils, Warning, TEXT("Failed to launch subprocess!"));
return;
}
while (Process.Update())
{
// Poll until process has finished
}
if (IsCanceled)
{
UE_LOG(LogIREEUtils, Warning, TEXT("Execution of subprocess was canceled!"));
}
else if (ReturnCode)
{
UE_LOG(LogIREEUtils, Warning, TEXT("Subprocess exited with non-zero code %d"), ReturnCode);
}
if (!LogFilePath.IsEmpty())
{
const FString Output = Process.GetFullOutputWithoutDelegate();
FStringBuilderBase Builder;
Builder.Append(Command)
.Append(TEXT(" "))
.Append(Arguments)
.Append(LINE_TERMINATOR LINE_TERMINATOR)
.Append(Output);
FFileHelper::SaveStringToFile(Builder.ToString(), *LogFilePath);
UE_LOG(LogIREEUtils, Log, TEXT("Saved subprocess output to: %s"), *LogFilePath);
}
}
bool ImportOnnx(const FString& ImporterCommand, const FString& ImporterArguments, TConstArrayView<uint8> InFileData, const FString& InModelName, const FString& InOutputDir, TArray64<uint8>& OutMlirData)
{
SCOPED_NAMED_EVENT_TEXT("IREEUtils::ImportOnnx", FColor::Magenta);
using namespace Private;
IPlatformFile& PlatformFile = FPlatformFileManager::Get().GetPlatformFile();
FString InputFilePath = FPaths::Combine(InOutputDir, InModelName) + ".onnx";
if (!PlatformFile.FileExists(*InputFilePath))
{
SCOPED_NAMED_EVENT_TEXT("InputFile", FColor::Magenta);
if(!FFileHelper::SaveArrayToFile(InFileData, *InputFilePath))
{
UE_LOG(LogIREEUtils, Warning, TEXT("IREECompilerRDG failed to save ONNX model \"%s\""), *InputFilePath);
return false;
}
}
FString OutputFilePath = FPaths::Combine(InOutputDir, InModelName) + ".mlir";
FString IntermediateFilePathNoExt = FPaths::Combine(InOutputDir, InModelName);
FString ImporterArgumentsCopy = ImporterArguments;
if (!IREEUtils::ResolveEnvironmentVariables(ImporterArgumentsCopy))
{
UE_LOG(LogIREEUtils, Warning, TEXT("IREECompilerRDG could not replace environment variables in %s"), *ImporterArgumentsCopy);
return false;
}
ImporterArgumentsCopy.ReplaceInline(*FString("${INPUT_PATH}"), *(FString("\"") + InputFilePath + "\""));
ImporterArgumentsCopy.ReplaceInline(*FString("${OUTPUT_PATH}"), *(FString("\"") + OutputFilePath + "\""));
{
SCOPED_NAMED_EVENT_TEXT("Import", FColor::Magenta);
IREEUtils::RunCommand(ImporterCommand, ImporterArgumentsCopy, FPaths::RootDir(), IntermediateFilePathNoExt + "_import-log.txt");
}
if (!PlatformFile.FileExists(*OutputFilePath))
{
UE_LOG(LogIREEUtils, Warning, TEXT("IREECompilerRDG failed to import the model \"%s\" using the command:"), *InputFilePath);
UE_LOG(LogIREEUtils, Warning, TEXT("\"%s\" %s"), *ImporterCommand, *ImporterArgumentsCopy);
return false;
}
{
SCOPED_NAMED_EVENT_TEXT("Load", FColor::Magenta);
if(!FFileHelper::LoadFileToArray(OutMlirData, *OutputFilePath))
{
UE_LOG(LogIREEUtils, Warning, TEXT("IREECompilerRDG failed to load imported model \"%s\""), *OutputFilePath);
return false;
}
}
return true;
}
} // namespace UE::IREEUtils