Development repository for FSR2 integration into Unity Post-Processing Stack V2.
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

186 lines
5.9 KiB

#if UNITY_EDITOR_WIN
using System;
using System.Diagnostics;
using System.IO;
using UnityEditor;
using UnityEditor.Build;
using UnityEditor.Build.Reporting;
using UnityEditor.UnityLinker;
using UnityEngine;
using PlayerSettings = UnityEditor.PlayerSettings;
using WW1.PlayStation;
internal class BuildPackageLibs : IPreprocessBuildWithReport, IMovePRXCallback
{
public int callbackOrder => 0;
static string PackageName => "com.ww1gameseries.pssr";
static string SourcePath => $"Packages/{PackageName}/Source~";
const int k_PRXBuildTimeOutS = 600; //10 minutes is the max time allowed to build the PRX
#region CompileLibs
readonly string[] m_CompileAgainstLibs = new string[]
{
"SceSysmodule_stub_weak",
"ScePsml",
"ScePsml_stub_weak",
"SceAgcGnmp",
"SceAgc",
"SceAgcCore",
"SceAgcGpuAddress",
"SceVideoOut_stub_weak",
"SceAgcDriver_stub_weak",
"SceAgc_stub_weak",
};
#endregion
public void OnPreprocessBuild(BuildReport report)
{
var buildTarget = report.summary.platform;
if (!IsBuildTargetValid(buildTarget))
{
return;
}
string prxPath = GetPRXBuildLocation(buildTarget);
string prxDir = Path.GetDirectoryName(prxPath);
if (IsPRXRebuildRequired(prxPath))
{
if (!Directory.Exists(prxDir))
{
if (string.IsNullOrWhiteSpace(prxDir))
{
throw new BuildFailedException("No PRX Directory");
}
Directory.CreateDirectory(prxDir);
}
BuildPackagePRX(buildTarget, prxPath, m_CompileAgainstLibs);
}
}
public void MovePRXToBuildLocation(BuildTarget target, string buildOutputLocation, bool developmentBuild)
{
if (!IsBuildTargetValid(target))
{
return;
}
string projectDir = Application.dataPath.Replace("/Assets", "");
string stagingArea = BuildUtils.GetStagingAreaLocationFor(target, projectDir, buildOutputLocation);
CopyLibraryPRXToStagingArea(GetPRXBuildLocation(target), stagingArea);
}
static bool IsPRXRebuildRequired(string prxPath)
{
if (!File.Exists(prxPath))
{
return true;
}
DateTime prxLastWrite = File.GetLastWriteTimeUtc(prxPath);
if (BuildUtils.HaveSourceFilesBeenModifiedSince(SourcePath, prxLastWrite))
{
return true;
}
return false;
}
static void BuildPackagePRX(BuildTarget target, string outputPath, string[] compileAgainstLibs)
{
string sdkLoc = Environment.GetEnvironmentVariable(SDKUtils.GetSdkEnvVarFor(target));
string clangLoc = $"{sdkLoc}/host_tools/bin/{SDKUtils.GetClangFor(target)}";
string allSourcePaths = string.Empty;
string[] allDirs = Directory.GetDirectories(SourcePath, "*", SearchOption.AllDirectories);
//Include the base folder also, if it has cpp files in it
if (Directory.GetFiles(SourcePath, "*.cpp").Length > 0)
{
allSourcePaths += $"\"{Path.GetFullPath(Path.Combine(SourcePath, "*.cpp"))}\" ";
}
foreach (var dir in allDirs)
{
if (Directory.GetFiles(dir, "*.cpp").Length == 0)
{
continue;
}
allSourcePaths += $"\"{Path.GetFullPath(Path.Combine(dir, "*.cpp"))}\" ";
}
string allLinkLibs = string.Empty;
foreach (var lib in compileAgainstLibs)
{
allLinkLibs += $"-l {lib} ";
}
//Additionally include the common includes
string command = $"-D\"NDEBUG\" -O2 -Wall -o\"{outputPath}\" {allSourcePaths} --for-linker=--oformat=prx {allLinkLibs}";
ProcessStartInfo startInfo = new ProcessStartInfo(clangLoc, command)
{
CreateNoWindow = true,
UseShellExecute = false,
RedirectStandardError = true,
};
Console.WriteLine($"Building PRX with {clangLoc} {command}");
Process proc = Process.Start(startInfo);
string errorOutput = proc.StandardError.ReadToEnd();
proc.WaitForExit(k_PRXBuildTimeOutS);
if (!proc.HasExited)
{
proc.Kill();
throw new BuildFailedException($"PRX Build Timed Out\n{errorOutput}");
}
if (proc.ExitCode != 0)
{
throw new BuildFailedException(errorOutput);
}
}
static void CopyLibraryPRXToStagingArea(string prxLocation, string stagingArea)
{
string copyPath = Path.Combine(stagingArea, LibraryInfo.LibraryNameWithExtension);
if (!Directory.Exists(stagingArea))
{
Directory.CreateDirectory(stagingArea);
}
File.Copy(prxLocation, copyPath, true);
}
static string GetPRXBuildLocation(BuildTarget target)
{
//Example Path: Library/SourceGeneratedPlugins/PS5/7000045/CommonDialog.prx
string relativePath = Path.Combine("Library", "SourceGeneratedPlugins", target.ToString(),
SDKUtils.GetSDKVersionString(target), $"{LibraryInfo.LibraryNameWithExtension}");
return Path.GetFullPath(relativePath);
}
static bool IsBuildTargetValid(BuildTarget target)
{
return target is BuildTarget.PS5;
}
}
internal interface IMovePRXCallback : IUnityLinkerProcessor
{
string IUnityLinkerProcessor.GenerateAdditionalLinkXmlFile(BuildReport report, UnityLinkerBuildPipelineData data)
{
//In 2021.3 report can return null for non-playstation platforms
if (report == null)
{
return string.Empty;
}
MovePRXToBuildLocation(report.summary.platform, report.summary.outputPath, report.summary.options.HasFlag(BuildOptions.Development));
return string.Empty;
}
public void MovePRXToBuildLocation(BuildTarget target, string buildOutputLocation, bool developmentBuild);
}
#endif