33 changed files with 1750 additions and 81 deletions
-
2.gitignore
-
3Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/Plugins/PS5.meta
-
BINPackages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/Plugins/PS5/PSSRPlugin.prx
-
77Packages/com.unity.postprocessing@3.2.2/PostProcessing/Runtime/Effects/Upscaling/Plugins/PS5/PSSRPlugin.prx.meta
-
2Packages/com.ww1gameseries.pssr/Editor.meta
-
186Packages/com.ww1gameseries.pssr/Editor/BuildPackageLibs.cs
-
11Packages/com.ww1gameseries.pssr/Editor/BuildPackageLibs.cs.meta
-
77Packages/com.ww1gameseries.pssr/Editor/BuildUtils.cs
-
11Packages/com.ww1gameseries.pssr/Editor/BuildUtils.cs.meta
-
18Packages/com.ww1gameseries.pssr/Editor/PSSRPlugin.Editor.asmdef
-
7Packages/com.ww1gameseries.pssr/Editor/PSSRPlugin.Editor.asmdef.meta
-
68Packages/com.ww1gameseries.pssr/Editor/SDKUtils.cs
-
11Packages/com.ww1gameseries.pssr/Editor/SDKUtils.cs.meta
-
8Packages/com.ww1gameseries.pssr/Runtime.meta
-
3Packages/com.ww1gameseries.pssr/Runtime/AssemblyInfo.cs
-
11Packages/com.ww1gameseries.pssr/Runtime/AssemblyInfo.cs.meta
-
8Packages/com.ww1gameseries.pssr/Runtime/LibraryInfo.cs
-
11Packages/com.ww1gameseries.pssr/Runtime/LibraryInfo.cs.meta
-
16Packages/com.ww1gameseries.pssr/Runtime/PSSRPlugin.Runtime.asmdef
-
7Packages/com.ww1gameseries.pssr/Runtime/PSSRPlugin.Runtime.asmdef.meta
-
164Packages/com.ww1gameseries.pssr/Runtime/PSSRPlugin.cs
-
11Packages/com.ww1gameseries.pssr/Runtime/PSSRPlugin.cs.meta
-
85Packages/com.ww1gameseries.pssr/Source~/PSSRPlugin.vcxproj
-
39Packages/com.ww1gameseries.pssr/Source~/PSSRPlugin.vcxproj.filters
-
64Packages/com.ww1gameseries.pssr/Source~/UnityPluginAPI/IUnityGraphics.h
-
32Packages/com.ww1gameseries.pssr/Source~/UnityPluginAPI/IUnityGraphicsAgcPS5.h
-
21Packages/com.ww1gameseries.pssr/Source~/UnityPluginAPI/IUnityGraphicsPS5.h
-
209Packages/com.ww1gameseries.pssr/Source~/UnityPluginAPI/IUnityInterface.h
-
37Packages/com.ww1gameseries.pssr/Source~/UnityPluginAPI/IUnityLog.h
-
606Packages/com.ww1gameseries.pssr/Source~/pssrplugin.cpp
-
13Packages/com.ww1gameseries.pssr/package.json
-
7Packages/com.ww1gameseries.pssr/package.json.meta
-
6Packages/packages-lock.json
@ -1,3 +0,0 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 32c5585f0ac1473aaa942ede8bc01712 |
|||
timeCreated: 1730718066 |
|||
@ -1,77 +0,0 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 82cb3c505a5252e4db0b661d9ccd67cb |
|||
PluginImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
iconMap: {} |
|||
executionOrder: {} |
|||
defineConstraints: [] |
|||
isPreloaded: 1 |
|||
isOverridable: 1 |
|||
isExplicitlyReferenced: 0 |
|||
validateReferences: 1 |
|||
platformData: |
|||
- first: |
|||
: Any |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
Exclude Editor: 1 |
|||
Exclude GameCoreScarlett: 1 |
|||
Exclude GameCoreXboxOne: 1 |
|||
Exclude Linux64: 1 |
|||
Exclude OSXUniversal: 1 |
|||
Exclude PS4: 1 |
|||
Exclude PS5: 0 |
|||
Exclude Win: 1 |
|||
Exclude Win64: 1 |
|||
- first: |
|||
Any: |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
Editor: Editor |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
DefaultValueInitialized: true |
|||
OS: AnyOS |
|||
- first: |
|||
PS4: PS4 |
|||
second: |
|||
enabled: 0 |
|||
settings: {} |
|||
- first: |
|||
PS5: PS5 |
|||
second: |
|||
enabled: 1 |
|||
settings: {} |
|||
- first: |
|||
Standalone: Linux64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: OSXUniversal |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
- first: |
|||
Standalone: Win64 |
|||
second: |
|||
enabled: 0 |
|||
settings: |
|||
CPU: AnyCPU |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -1,5 +1,5 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 5fe0a1d4497ee1c43bca193c0efc0b4f |
|||
guid: 90b76d351f2ce6c4e92b07204ce4b3a1 |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
@ -0,0 +1,186 @@ |
|||
#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
|
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 9ecb3065343dab3468b39fb88f387d0a |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,77 @@ |
|||
#if UNITY_EDITOR_WIN
|
|||
using System; |
|||
using System.IO; |
|||
using System.Text.RegularExpressions; |
|||
using UnityEditor; |
|||
|
|||
internal static class BuildUtils |
|||
{ |
|||
internal static readonly string kBuildFolderName = "Build"; |
|||
|
|||
internal static bool HaveSourceFilesBeenModifiedSince(string sourcePath, DateTime lastPrxWrite) |
|||
{ |
|||
DateTime latestWriteTime = DateTime.MinValue; |
|||
DirectoryInfo di = new DirectoryInfo(sourcePath); |
|||
foreach (var file in di.GetFiles("*.cpp", SearchOption.AllDirectories)) |
|||
{ |
|||
var fileLW = File.GetLastWriteTimeUtc(file.FullName); |
|||
latestWriteTime = (fileLW > latestWriteTime) ? fileLW: latestWriteTime; |
|||
} |
|||
foreach (var file in di.GetFiles("*.h", SearchOption.AllDirectories)) |
|||
{ |
|||
var fileLW = File.GetLastWriteTimeUtc(file.FullName); |
|||
latestWriteTime = (fileLW > latestWriteTime) ? fileLW: latestWriteTime; |
|||
} |
|||
|
|||
System.Console.WriteLine($"latestWriteTime:{latestWriteTime} lastwritepre:{lastPrxWrite}"); |
|||
if (latestWriteTime < lastPrxWrite) |
|||
{ |
|||
System.Console.WriteLine($"skipping package prebuild step. No changes detected"); |
|||
return false; |
|||
} |
|||
|
|||
return true; |
|||
} |
|||
|
|||
internal static string GetStagingAreaLocationFor(BuildTarget buildPlatform, string projectDir, string outputPath) |
|||
{ |
|||
string stagingArea; |
|||
|
|||
//2021.3 (pre-IBP) has StagingArea as a root to just the StagingArea Folder
|
|||
//2022 (IBP) uses the [BUILD_OUTPUT]/Build path as its StagingArea and ignores the staging area
|
|||
//completely
|
|||
#if UNITY_2022_2_OR_NEWER
|
|||
if (buildPlatform == BuildTarget.PS4) |
|||
{ |
|||
stagingArea = Path.Combine(outputPath, kBuildFolderName, "Media", "Plugins"); |
|||
} |
|||
else if (buildPlatform == BuildTarget.PS5) |
|||
{ |
|||
stagingArea = Path.Combine(projectDir, "Temp", "StagingArea", "User", "Media", "Plugins"); |
|||
}else |
|||
{ |
|||
throw new InvalidOperationException($"Cannot get staging area for {buildPlatform}"); |
|||
} |
|||
#else
|
|||
//PS4 will auto copy the contents of Data to the media folder and if you have already created a media folder
|
|||
//(i.e. StagingArea/Media) it will throw an error, so instead just copy to data and allow the PS4 build process to
|
|||
//do the copying to Media
|
|||
if (buildPlatform == BuildTarget.PS4) |
|||
{ |
|||
stagingArea = Path.Combine(projectDir, "Temp", "StagingArea", "Data", "Plugins"); |
|||
} |
|||
else if (buildPlatform == BuildTarget.PS5) |
|||
{ |
|||
stagingArea = Path.Combine(projectDir, "Temp", "StagingArea", "Media", "Plugins"); |
|||
} |
|||
else |
|||
{ |
|||
throw new InvalidOperationException($"Cannot get staging area for {buildPlatform}"); |
|||
} |
|||
#endif
|
|||
|
|||
return stagingArea; |
|||
} |
|||
|
|||
} |
|||
#endif
|
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: a9c85a4918ae7274782eafae60d67746 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,18 @@ |
|||
{ |
|||
"name": "PSSRPlugin.Editor", |
|||
"rootNamespace": "", |
|||
"references": [ |
|||
"PSSRPlugin.Runtime" |
|||
], |
|||
"includePlatforms": [ |
|||
"Editor" |
|||
], |
|||
"excludePlatforms": [], |
|||
"allowUnsafeCode": false, |
|||
"overrideReferences": false, |
|||
"precompiledReferences": [], |
|||
"autoReferenced": true, |
|||
"defineConstraints": [], |
|||
"versionDefines": [], |
|||
"noEngineReferences": false |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
fileFormatVersion: 2 |
|||
guid: efdaa6148c335c646b2b4e1dd3e6bdb6 |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,68 @@ |
|||
#if UNITY_EDITOR_WIN
|
|||
using System; |
|||
using System.IO; |
|||
using System.Text.RegularExpressions; |
|||
using UnityEditor; |
|||
|
|||
internal static class SDKUtils |
|||
{ |
|||
internal static string GetSDKVersionString(BuildTarget target) |
|||
{ |
|||
string verstring = string.Empty; |
|||
string sdkPath = System.Environment.GetEnvironmentVariable(GetSdkEnvVarFor(target)); |
|||
if (sdkPath != null) |
|||
{ |
|||
string versionFile = Path.Combine(sdkPath, "target/include/sdk_version.h"); |
|||
if (File.Exists(versionFile)) |
|||
{ |
|||
string[] lines = File.ReadAllLines(versionFile); |
|||
foreach (string line in lines) |
|||
{ |
|||
//Extract the value following #define SCE_PROSPERO_SDK_VERSION
|
|||
string regexPattern = $@"#define\s+{GetSdkVersionStringFor(target)}\s+\(\s*0x([0-9a-fA-F]+)u\s*\)"; |
|||
Match match = Regex.Match(line, regexPattern); |
|||
if (match.Success) |
|||
{ |
|||
verstring = match.Groups[1].Value; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
|
|||
return verstring; |
|||
} |
|||
|
|||
internal static string GetSdkEnvVarFor(BuildTarget target) |
|||
{ |
|||
switch (target) |
|||
{ |
|||
case BuildTarget.PS5: |
|||
return "SCE_PROSPERO_SDK_DIR"; |
|||
default: |
|||
throw new InvalidOperationException($"Cannot get env var for {target}"); |
|||
} |
|||
} |
|||
|
|||
internal static string GetClangFor(BuildTarget target) |
|||
{ |
|||
switch (target) |
|||
{ |
|||
case BuildTarget.PS5: |
|||
return "prospero-clang.exe"; |
|||
default: |
|||
throw new InvalidOperationException($"Cannot get clang for {target}"); |
|||
} |
|||
} |
|||
|
|||
static string GetSdkVersionStringFor(BuildTarget target) |
|||
{ |
|||
switch (target) |
|||
{ |
|||
case BuildTarget.PS5: |
|||
return "SCE_PROSPERO_SDK_VERSION"; |
|||
default: |
|||
throw new InvalidOperationException($"Cannot get SDK for {target}"); |
|||
} |
|||
} |
|||
} |
|||
#endif
|
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 053e3eab3ada35648ae6894cb24855c3 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,8 @@ |
|||
fileFormatVersion: 2 |
|||
guid: c73d52c9900b2ae4bba5ec72be77f33b |
|||
folderAsset: yes |
|||
DefaultImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,3 @@ |
|||
using System.Runtime.CompilerServices; |
|||
|
|||
[assembly: InternalsVisibleTo("PSSRPlugin.Editor")] |
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 6978c53bdde0f304daa0bf3a8ab67bc8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,8 @@ |
|||
namespace WW1.PlayStation |
|||
{ |
|||
internal static class LibraryInfo |
|||
{ |
|||
internal const string LibraryName = "PSSRPlugin"; |
|||
internal static string LibraryNameWithExtension => $"{LibraryName}.prx"; |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: fc79f70c3d6f5694fb6670287b08929d |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,16 @@ |
|||
{ |
|||
"name": "PSSRPlugin.Runtime", |
|||
"references": [], |
|||
"includePlatforms": [ |
|||
"Editor", |
|||
"PS5" |
|||
], |
|||
"excludePlatforms": [], |
|||
"allowUnsafeCode": false, |
|||
"overrideReferences": false, |
|||
"precompiledReferences": [], |
|||
"autoReferenced": true, |
|||
"defineConstraints": [], |
|||
"versionDefines": [], |
|||
"noEngineReferences": false |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 75c98c12b3993194db6c4bc91f7afa0c |
|||
AssemblyDefinitionImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,164 @@ |
|||
using System; |
|||
using System.Runtime.InteropServices; |
|||
using UnityEngine; |
|||
using UnityEngine.Rendering; |
|||
|
|||
namespace WW1.PlayStation |
|||
{ |
|||
public static class PSSRPlugin |
|||
{ |
|||
public static readonly uint MaxNumContexts = 4; |
|||
|
|||
public enum Event |
|||
{ |
|||
Create, |
|||
Dispatch, |
|||
Destroy, |
|||
Capture, |
|||
} |
|||
|
|||
public static void IssuePluginEvent<T>(CommandBuffer cmd, Event pluginEvent, NativeData<T> data) where T : struct |
|||
{ |
|||
cmd.IssuePluginEventAndData(GetRenderEventAndDataFunc(), (int)pluginEvent, data.GetPointer()); |
|||
} |
|||
|
|||
[DllImport(LibraryInfo.LibraryName)] |
|||
public static extern IntPtr GetRenderEventAndDataFunc(); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_Init")] |
|||
public static extern int Init(); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_Release")] |
|||
public static extern void Release(); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_CreateContext")] |
|||
public static extern int CreateContext(ref InitParams initParams, out IntPtr outputColorTexturePtr); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_DestroyContext")] |
|||
public static extern void DestroyContext(uint contextIndex); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_Dispatch")] |
|||
public static extern void Dispatch(ref DispatchParams dispatchParams); |
|||
|
|||
[DllImport(LibraryInfo.LibraryName, EntryPoint = "PSSR_RequestCapture")] |
|||
public static extern int RequestCapture(uint contextIndex, byte frameNum = 64); |
|||
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct InitParams |
|||
{ |
|||
public uint contextIndex; |
|||
|
|||
public uint displayWidth; |
|||
public uint displayHeight; |
|||
public uint maxRenderWidth; |
|||
public uint maxRenderHeight; |
|||
|
|||
public uint autoKeepCopies; |
|||
} |
|||
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct DispatchParams |
|||
{ |
|||
public uint contextIndex; |
|||
|
|||
public IntPtr color; |
|||
public IntPtr depth; |
|||
public IntPtr prevDepth; |
|||
public IntPtr motionVectors; |
|||
public IntPtr prevMotionVectors; |
|||
public IntPtr exposure; |
|||
public IntPtr reactiveMask; |
|||
public IntPtr outputColor; |
|||
|
|||
public uint renderWidth; |
|||
public uint renderHeight; |
|||
|
|||
public Vector2 jitter; |
|||
public Vector2 motionVectorScale; |
|||
|
|||
public Matrix4x4 camProjectionNoJitter; |
|||
public Vector3 camForward; |
|||
public Vector3 camUp; |
|||
public Vector3 camRight; |
|||
public double camPositionX; |
|||
public double camPositionY; |
|||
public double camPositionZ; |
|||
public float camNear; |
|||
public float camFar; |
|||
public float preExposure; |
|||
public uint resetHistory; |
|||
public OptionFlags flags; |
|||
|
|||
public void FromCamera(Camera cam) |
|||
{ |
|||
camProjectionNoJitter = cam.nonJitteredProjectionMatrix; |
|||
camForward = cam.transform.forward; |
|||
camUp = cam.transform.up; |
|||
camRight = cam.transform.right; |
|||
camPositionX = cam.transform.position.x; |
|||
camPositionY = cam.transform.position.y; |
|||
camPositionZ = cam.transform.position.z; |
|||
camNear = cam.nearClipPlane; |
|||
camFar = cam.farClipPlane; |
|||
} |
|||
} |
|||
|
|||
[Flags] |
|||
public enum OptionFlags: uint |
|||
{ |
|||
None = 0u, |
|||
ViewSpaceDepth = 1u << 14, |
|||
ReverseDepth = 1u << 15, |
|||
AutoExposure = 1u << 16, |
|||
PassThrough = 1u << 31, |
|||
} |
|||
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct DestroyParams |
|||
{ |
|||
public uint contextIndex; |
|||
} |
|||
|
|||
[StructLayout(LayoutKind.Sequential)] |
|||
public struct CaptureParams |
|||
{ |
|||
public uint contextIndex; |
|||
|
|||
public byte frameNum; |
|||
} |
|||
|
|||
/// <summary>
|
|||
/// Helper class to deal with all the nasty business of converting managed struct data into a pointer to native memory for use with plugin events.
|
|||
/// </summary>
|
|||
public class NativeData<T> where T : struct |
|||
{ |
|||
private T _value; |
|||
private IntPtr _nativeBuffer = IntPtr.Zero; |
|||
|
|||
public ref T Value => ref _value; |
|||
|
|||
public void Initialize() |
|||
{ |
|||
if (_nativeBuffer != IntPtr.Zero) |
|||
return; |
|||
|
|||
_nativeBuffer = Marshal.AllocHGlobal(Marshal.SizeOf<T>()); |
|||
} |
|||
|
|||
public void Destroy() |
|||
{ |
|||
if (_nativeBuffer == IntPtr.Zero) |
|||
return; |
|||
|
|||
Marshal.FreeHGlobal(_nativeBuffer); |
|||
_nativeBuffer = IntPtr.Zero; |
|||
} |
|||
|
|||
public IntPtr GetPointer() |
|||
{ |
|||
Marshal.StructureToPtr(_value, _nativeBuffer, false); |
|||
return _nativeBuffer; |
|||
} |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,11 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 272bc1969de41c147b9279094be5afa8 |
|||
MonoImporter: |
|||
externalObjects: {} |
|||
serializedVersion: 2 |
|||
defaultReferences: [] |
|||
executionOrder: 0 |
|||
icon: {instanceID: 0} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
@ -0,0 +1,85 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project DefaultTargets="Build" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup Label="ProjectConfigurations"> |
|||
<ProjectConfiguration Include="Debug|Prospero"> |
|||
<Configuration>Debug</Configuration> |
|||
<Platform>Prospero</Platform> |
|||
</ProjectConfiguration> |
|||
<ProjectConfiguration Include="Release|Prospero"> |
|||
<Configuration>Release</Configuration> |
|||
<Platform>Prospero</Platform> |
|||
</ProjectConfiguration> |
|||
</ItemGroup> |
|||
<PropertyGroup Label="Globals"> |
|||
<ProjectGuid>{cfc8c665-7287-4dac-9016-2d97e70b63be}</ProjectGuid> |
|||
<ProsperoSdkVersion /> |
|||
</PropertyGroup> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" /> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Prospero'" Label="Configuration"> |
|||
<ConfigurationType>DynamicLibrary</ConfigurationType> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Prospero'" Label="Configuration"> |
|||
<ConfigurationType>DynamicLibrary</ConfigurationType> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration"> |
|||
<PlatformToolset>v143</PlatformToolset> |
|||
</PropertyGroup> |
|||
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration"> |
|||
<PlatformToolset>v143</PlatformToolset> |
|||
</PropertyGroup> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" /> |
|||
<PropertyGroup Condition="'$(DebuggerFlavor)'=='ProsperoDebugger'" Label="OverrideDebuggerDefaults"> |
|||
<!--LocalDebuggerCommand>$(TargetPath)</LocalDebuggerCommand--> |
|||
<!--LocalDebuggerCommandArguments></LocalDebuggerCommandArguments--> |
|||
<!--LocalDebuggerTarget></LocalDebuggerTarget--> |
|||
<!--LocalDebuggerWorkingDirectory>$(ProjectDir)</LocalDebuggerWorkingDirectory--> |
|||
<!--LocalRunCommandLine></LocalRunCommandLine--> |
|||
</PropertyGroup> |
|||
<ImportGroup Label="ExtensionSettings"> |
|||
<Import Condition="Exists('$(VCTargetsPath)\BuildCustomizations\OrbisWavePsslc.props')" Project="$(VCTargetsPath)\BuildCustomizations\OrbisWavePsslc.props" /> |
|||
</ImportGroup> |
|||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Prospero'"> |
|||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
|||
</ImportGroup> |
|||
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Prospero'"> |
|||
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" /> |
|||
</ImportGroup> |
|||
<PropertyGroup Label="UserMacros" /> |
|||
<PropertyGroup /> |
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Prospero'"> |
|||
<ClCompile> |
|||
<PreprocessorDefinitions>_DEBUG;%(PreprocessorDefinitions);</PreprocessorDefinitions> |
|||
<GenerateDebugInformation>true</GenerateDebugInformation> |
|||
</ClCompile> |
|||
<Link> |
|||
<Addressing>NonAslr</Addressing> |
|||
<AdditionalLibraryDirectories> |
|||
</AdditionalLibraryDirectories> |
|||
<AdditionalDependencies>-lSceSysmodule_stub_weak;-lScePsml;-lScePsml_stub_weak;-lSceAgcGnmp;-lSceAgc;-lSceAgcCore;-lSceAgcGpuAddress;-lSceVideoOut_stub_weak;-lSceAgcDriver_stub_weak;-lSceAgc_stub_weak</AdditionalDependencies> |
|||
</Link> |
|||
</ItemDefinitionGroup> |
|||
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Prospero'"> |
|||
<ClCompile> |
|||
<PreprocessorDefinitions>NDEBUG;%(PreprocessorDefinitions);</PreprocessorDefinitions> |
|||
<OptimizationLevel>Level2</OptimizationLevel> |
|||
</ClCompile> |
|||
<Link> |
|||
<AdditionalDependencies>-lSceSysmodule_stub_weak;-lScePsml;-lScePsml_stub_weak;-lSceAgcGnmp;-lSceAgc;-lSceAgcCore;-lSceAgcGpuAddress;-lSceVideoOut_stub_weak;-lSceAgcDriver_stub_weak;-lSceAgc_stub_weak</AdditionalDependencies> |
|||
</Link> |
|||
</ItemDefinitionGroup> |
|||
<ItemGroup> |
|||
<ClCompile Include="pssrplugin.cpp" /> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphics.h" /> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphicsAgcPS5.h" /> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphicsPS5.h" /> |
|||
<ClInclude Include="UnityPluginAPI\IUnityInterface.h" /> |
|||
<ClInclude Include="UnityPluginAPI\IUnityLog.h" /> |
|||
</ItemGroup> |
|||
<Import Condition="'$(ConfigurationType)' == 'Makefile' and Exists('$(VCTargetsPath)\Platforms\$(Platform)\SCE.Makefile.$(Platform).targets')" Project="$(VCTargetsPath)\Platforms\$(Platform)\SCE.Makefile.$(Platform).targets" /> |
|||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" /> |
|||
<ImportGroup Label="ExtensionTargets"> |
|||
<Import Condition="Exists('$(VCTargetsPath)\BuildCustomizations\OrbisWavePsslc.targets')" Project="$(VCTargetsPath)\BuildCustomizations\OrbisWavePsslc.targets" /> |
|||
</ImportGroup> |
|||
</Project> |
|||
@ -0,0 +1,39 @@ |
|||
<?xml version="1.0" encoding="utf-8"?> |
|||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003"> |
|||
<ItemGroup> |
|||
<Filter Include="Source Files"> |
|||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier> |
|||
<Extensions>cpp;c;cxx;cc;s;asm</Extensions> |
|||
</Filter> |
|||
<Filter Include="Header Files"> |
|||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier> |
|||
<Extensions>h;hpp;pssli</Extensions> |
|||
</Filter> |
|||
<Filter Include="Shader Files"> |
|||
<UniqueIdentifier>{5FAE8098-8EE5-44A0-ABB6-C797B807CDE6}</UniqueIdentifier> |
|||
<Extensions>pssl;scu</Extensions> |
|||
</Filter> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ClCompile Include="pssrplugin.cpp"> |
|||
<Filter>Source Files</Filter> |
|||
</ClCompile> |
|||
</ItemGroup> |
|||
<ItemGroup> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphics.h"> |
|||
<Filter>Header Files</Filter> |
|||
</ClInclude> |
|||
<ClInclude Include="UnityPluginAPI\IUnityInterface.h"> |
|||
<Filter>Header Files</Filter> |
|||
</ClInclude> |
|||
<ClInclude Include="UnityPluginAPI\IUnityLog.h"> |
|||
<Filter>Header Files</Filter> |
|||
</ClInclude> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphicsAgcPS5.h"> |
|||
<Filter>Header Files</Filter> |
|||
</ClInclude> |
|||
<ClInclude Include="UnityPluginAPI\IUnityGraphicsPS5.h"> |
|||
<Filter>Header Files</Filter> |
|||
</ClInclude> |
|||
</ItemGroup> |
|||
</Project> |
|||
@ -0,0 +1,64 @@ |
|||
// Unity Native Plugin API copyright © 2015 Unity Technologies ApS |
|||
// |
|||
// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
// |
|||
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. |
|||
|
|||
#pragma once |
|||
#include "IUnityInterface.h" |
|||
|
|||
// Has to match the GfxDeviceRenderer enum |
|||
typedef enum UnityGfxRenderer |
|||
{ |
|||
//kUnityGfxRendererOpenGL = 0, // Legacy OpenGL, removed |
|||
//kUnityGfxRendererD3D9 = 1, // Direct3D 9, removed |
|||
kUnityGfxRendererD3D11 = 2, // Direct3D 11 |
|||
kUnityGfxRendererNull = 4, // "null" device (used in batch mode) |
|||
//kUnityGfxRendererOpenGLES20 = 8, // OpenGL ES 2.0, removed |
|||
kUnityGfxRendererOpenGLES30 = 11, // OpenGL ES 3.0 |
|||
//kUnityGfxRendererGXM = 12, // PlayStation Vita, removed |
|||
kUnityGfxRendererPS4 = 13, // PlayStation 4 |
|||
kUnityGfxRendererXboxOne = 14, // Xbox One |
|||
kUnityGfxRendererMetal = 16, // iOS Metal |
|||
kUnityGfxRendererOpenGLCore = 17, // OpenGL core |
|||
kUnityGfxRendererD3D12 = 18, // Direct3D 12 |
|||
kUnityGfxRendererVulkan = 21, // Vulkan |
|||
kUnityGfxRendererNvn = 22, // Nintendo Switch NVN API |
|||
kUnityGfxRendererXboxOneD3D12 = 23, // MS XboxOne Direct3D 12 |
|||
kUnityGfxRendererGameCoreXboxOne = 24, // GameCore Xbox One |
|||
kUnityGfxRendererGameCoreXboxSeries = 25, // GameCore XboxSeries |
|||
kUnityGfxRendererPS5 = 26, // PS5 |
|||
kUnityGfxRendererPS5NGGC = 27, // PS5 NGGC |
|||
|
|||
kUnityGfxRendererReservedCFE = 29 |
|||
} UnityGfxRenderer; |
|||
|
|||
typedef enum UnityGfxDeviceEventType |
|||
{ |
|||
kUnityGfxDeviceEventInitialize = 0, |
|||
kUnityGfxDeviceEventShutdown = 1, |
|||
kUnityGfxDeviceEventBeforeReset = 2, |
|||
kUnityGfxDeviceEventAfterReset = 3, |
|||
} UnityGfxDeviceEventType; |
|||
|
|||
typedef void (UNITY_INTERFACE_API * IUnityGraphicsDeviceEventCallback)(UnityGfxDeviceEventType eventType); |
|||
|
|||
// Should only be used on the rendering thread unless noted otherwise. |
|||
UNITY_DECLARE_INTERFACE(IUnityGraphics) |
|||
{ |
|||
UnityGfxRenderer(UNITY_INTERFACE_API * GetRenderer)(); // Thread safe |
|||
|
|||
// This callback will be called when graphics device is created, destroyed, reset, etc. |
|||
// It is possible to miss the kUnityGfxDeviceEventInitialize event in case plugin is loaded at a later time, |
|||
// when the graphics device is already created. |
|||
void(UNITY_INTERFACE_API * RegisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback); |
|||
void(UNITY_INTERFACE_API * UnregisterDeviceEventCallback)(IUnityGraphicsDeviceEventCallback callback); |
|||
int(UNITY_INTERFACE_API * ReserveEventIDRange)(int count); // reserves 'count' event IDs. Plugins should use the result as a base index when issuing events back and forth to avoid event id clashes. |
|||
}; |
|||
UNITY_REGISTER_INTERFACE_GUID(0x7CBA0A9CA4DDB544ULL, 0x8C5AD4926EB17B11ULL, IUnityGraphics) |
|||
|
|||
|
|||
// Certain Unity APIs (GL.IssuePluginEvent, CommandBuffer.IssuePluginEvent) can callback into native plugins. |
|||
// Provide them with an address to a function of this signature. |
|||
typedef void (UNITY_INTERFACE_API * UnityRenderingEvent)(int eventId); |
|||
typedef void (UNITY_INTERFACE_API * UnityRenderingEventAndData)(int eventId, void* data); |
|||
@ -0,0 +1,32 @@ |
|||
// Unity Native Plugin API copyright © 2021 Unity Technologies ApS |
|||
// |
|||
// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
// |
|||
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. |
|||
|
|||
#pragma once |
|||
#if UNITY |
|||
#include "Runtime/PluginInterface/Headers/IUnityInterface.h" |
|||
#else |
|||
#include "IUnityInterface.h" |
|||
#endif |
|||
#include <agc/commandbuffer.h> |
|||
#include <agc/registerstructs.h> |
|||
#include <stdint.h> |
|||
|
|||
// Should only be used on the rendering thread unless noted otherwise. |
|||
UNITY_DECLARE_INTERFACE(IUnityGraphicsAgcPS5) |
|||
{ |
|||
void *(UNITY_INTERFACE_API * AllocateGPUMemory)(size_t size, int alignment); |
|||
void(UNITY_INTERFACE_API * ReleaseGPUMemory)(void *data); |
|||
|
|||
void* (UNITY_INTERFACE_API * AllocateContiguousPhysicalGPUMemory)(size_t size, int alignment); |
|||
void(UNITY_INTERFACE_API * ReleaseContiguousPhysicalGPUMemory)(void* data); |
|||
|
|||
void(UNITY_INTERFACE_API * SubmitGraphics)(sce::Agc::PacketAddress dcbGpuAddr, uint32_t dcbSizeInDwords); |
|||
|
|||
int (UNITY_INTERFACE_API * GetCurrentRenderTargetNum)(); |
|||
void (UNITY_INTERFACE_API * GetCurrentRenderTarget)(sce::Agc::CxRenderTarget *renderTarget, int index); |
|||
void (UNITY_INTERFACE_API * GetCurrentDepthRenderTarget)(sce::Agc::CxDepthRenderTarget *depthRenderTarget); |
|||
}; |
|||
UNITY_REGISTER_INTERFACE_GUID(0xE55C42913A8F419DULL, 0x872AB8A995684235ULL, IUnityGraphicsAgcPS5) |
|||
@ -0,0 +1,21 @@ |
|||
// Unity Native Plugin API copyright © 2020 Unity Technologies ApS |
|||
// |
|||
// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
// |
|||
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. |
|||
|
|||
#pragma once |
|||
#include "IUnityInterface.h" |
|||
|
|||
// Should only be used on the rendering thread unless noted otherwise. |
|||
UNITY_DECLARE_INTERFACE(IUnityGraphicsPS5) |
|||
{ |
|||
void* (UNITY_INTERFACE_API * GetGfxContext)(); |
|||
|
|||
void *(UNITY_INTERFACE_API * AllocateGPUMemory)(size_t size, int alignment); |
|||
void(UNITY_INTERFACE_API * ReleaseGPUMemory)(void *data); |
|||
|
|||
void *(UNITY_INTERFACE_API * GetCurrentRenderTarget)(int index); |
|||
void *(UNITY_INTERFACE_API * GetCurrentDepthRenderTarget)(); |
|||
}; |
|||
UNITY_REGISTER_INTERFACE_GUID(0x74a62b5d78f14e8ULL, 0xa60947365e5561ceULL, IUnityGraphicsPS5) |
|||
@ -0,0 +1,209 @@ |
|||
// Unity Native Plugin API copyright © 2015 Unity Technologies ApS |
|||
// |
|||
// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
// |
|||
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. |
|||
|
|||
#pragma once |
|||
|
|||
// Unity native plugin API |
|||
// Compatible with C99 |
|||
|
|||
#if defined(__CYGWIN32__) |
|||
#define UNITY_INTERFACE_API __stdcall |
|||
#define UNITY_INTERFACE_EXPORT __declspec(dllexport) |
|||
#elif defined(WIN32) || defined(_WIN32) || defined(__WIN32__) || defined(_WIN64) || defined(WINAPI_FAMILY) |
|||
#define UNITY_INTERFACE_API __stdcall |
|||
#define UNITY_INTERFACE_EXPORT __declspec(dllexport) |
|||
#elif defined(__ORBIS__) || defined(__PROSPERO__) |
|||
#define UNITY_INTERFACE_API |
|||
#define UNITY_INTERFACE_EXPORT __declspec(dllexport) |
|||
#elif defined(__MACH__) || defined(__ANDROID__) || defined(__linux__) || defined(LUMIN) |
|||
#define UNITY_INTERFACE_API |
|||
#define UNITY_INTERFACE_EXPORT __attribute__ ((visibility ("default"))) |
|||
#else |
|||
#define UNITY_INTERFACE_API |
|||
#define UNITY_INTERFACE_EXPORT |
|||
#endif |
|||
|
|||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
// IUnityInterface is a registry of interfaces we choose to expose to plugins. |
|||
// |
|||
// USAGE: |
|||
// --------- |
|||
// To retrieve an interface a user can do the following from a plugin, assuming they have the header file for the interface: |
|||
// |
|||
// IMyInterface * ptr = registry->Get<IMyInterface>(); |
|||
///////////////////////////////////////////////////////////////////////////////////////////////////////////////////// |
|||
|
|||
// Unity Interface GUID |
|||
// Ensures global uniqueness. |
|||
// |
|||
// Template specialization is used to produce a means of looking up a GUID from its interface type at compile time. |
|||
// The net result should compile down to passing around the GUID. |
|||
// |
|||
// UNITY_REGISTER_INTERFACE_GUID should be placed in the header file of any interface definition outside of all namespaces. |
|||
// The interface structure and the registration GUID are all that is required to expose the interface to other systems. |
|||
struct UnityInterfaceGUID |
|||
{ |
|||
#ifdef __cplusplus |
|||
UnityInterfaceGUID(unsigned long long high, unsigned long long low) |
|||
: m_GUIDHigh(high) |
|||
, m_GUIDLow(low) |
|||
{ |
|||
} |
|||
|
|||
UnityInterfaceGUID(const UnityInterfaceGUID& other) |
|||
{ |
|||
m_GUIDHigh = other.m_GUIDHigh; |
|||
m_GUIDLow = other.m_GUIDLow; |
|||
} |
|||
|
|||
UnityInterfaceGUID& operator=(const UnityInterfaceGUID& other) |
|||
{ |
|||
m_GUIDHigh = other.m_GUIDHigh; |
|||
m_GUIDLow = other.m_GUIDLow; |
|||
return *this; |
|||
} |
|||
|
|||
bool Equals(const UnityInterfaceGUID& other) const { return m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow == other.m_GUIDLow; } |
|||
bool LessThan(const UnityInterfaceGUID& other) const { return m_GUIDHigh < other.m_GUIDHigh || (m_GUIDHigh == other.m_GUIDHigh && m_GUIDLow < other.m_GUIDLow); } |
|||
#endif |
|||
unsigned long long m_GUIDHigh; |
|||
unsigned long long m_GUIDLow; |
|||
}; |
|||
#ifdef __cplusplus |
|||
inline bool operator==(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.Equals(right); } |
|||
inline bool operator!=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !left.Equals(right); } |
|||
inline bool operator<(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return left.LessThan(right); } |
|||
inline bool operator>(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return right.LessThan(left); } |
|||
inline bool operator>=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator<(left, right); } |
|||
inline bool operator<=(const UnityInterfaceGUID& left, const UnityInterfaceGUID& right) { return !operator>(left, right); } |
|||
#else |
|||
typedef struct UnityInterfaceGUID UnityInterfaceGUID; |
|||
#endif |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
#define UNITY_DECLARE_INTERFACE(NAME) \ |
|||
struct NAME : IUnityInterface |
|||
|
|||
// Generic version of GetUnityInterfaceGUID to allow us to specialize it |
|||
// per interface below. The generic version has no actual implementation |
|||
// on purpose. |
|||
// |
|||
// If you get errors about return values related to this method then |
|||
// you have forgotten to include UNITY_REGISTER_INTERFACE_GUID with |
|||
// your interface, or it is not visible at some point when you are |
|||
// trying to retrieve or add an interface. |
|||
template<typename TYPE> |
|||
inline const UnityInterfaceGUID GetUnityInterfaceGUID(); |
|||
|
|||
// This is the macro you provide in your public interface header |
|||
// outside of a namespace to allow us to map between type and GUID |
|||
// without the user having to worry about it when attempting to |
|||
// add or retrieve and interface from the registry. |
|||
#define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE) \ |
|||
template<> \ |
|||
inline const UnityInterfaceGUID GetUnityInterfaceGUID<TYPE>() \ |
|||
{ \ |
|||
return UnityInterfaceGUID(HASHH,HASHL); \ |
|||
} |
|||
|
|||
// Same as UNITY_REGISTER_INTERFACE_GUID but allows the interface to live in |
|||
// a particular namespace. As long as the namespace is visible at the time you call |
|||
// GetUnityInterfaceGUID< INTERFACETYPE >() or you explicitly qualify it in the template |
|||
// calls this will work fine, only the macro here needs to have the additional parameter |
|||
#define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE) \ |
|||
const UnityInterfaceGUID TYPE##_GUID(HASHH, HASHL); \ |
|||
template<> \ |
|||
inline const UnityInterfaceGUID GetUnityInterfaceGUID< NAMESPACE :: TYPE >() \ |
|||
{ \ |
|||
return UnityInterfaceGUID(HASHH,HASHL); \ |
|||
} |
|||
|
|||
// These macros allow for C compatibility in user code. |
|||
#define UNITY_GET_INTERFACE_GUID(TYPE) GetUnityInterfaceGUID< TYPE >() |
|||
|
|||
|
|||
#else |
|||
#define UNITY_DECLARE_INTERFACE(NAME) \ |
|||
typedef struct NAME NAME; \ |
|||
struct NAME |
|||
|
|||
// NOTE: This has the downside that one some compilers it will not get stripped from all compilation units that |
|||
// can see a header containing this constant. However, it's only for C compatibility and thus should have |
|||
// minimal impact. |
|||
#define UNITY_REGISTER_INTERFACE_GUID(HASHH, HASHL, TYPE) \ |
|||
const UnityInterfaceGUID TYPE##_GUID = {HASHH, HASHL}; |
|||
|
|||
// In general namespaces are going to be a problem for C code any interfaces we expose in a namespace are |
|||
// not going to be usable from C. |
|||
#define UNITY_REGISTER_INTERFACE_GUID_IN_NAMESPACE(HASHH, HASHL, TYPE, NAMESPACE) |
|||
|
|||
// These macros allow for C compatibility in user code. |
|||
#define UNITY_GET_INTERFACE_GUID(TYPE) TYPE##_GUID |
|||
#endif |
|||
|
|||
// Using this in user code rather than INTERFACES->Get<TYPE>() will be C compatible for those places in plugins where |
|||
// this may be needed. Unity code itself does not need this. |
|||
#define UNITY_GET_INTERFACE(INTERFACES, TYPE) (TYPE*)INTERFACES->GetInterfaceSplit (UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDHigh, UNITY_GET_INTERFACE_GUID(TYPE).m_GUIDLow); |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
struct IUnityInterface |
|||
{ |
|||
}; |
|||
#else |
|||
typedef void IUnityInterface; |
|||
#endif |
|||
|
|||
|
|||
typedef struct IUnityInterfaces |
|||
{ |
|||
// Returns an interface matching the guid. |
|||
// Returns nullptr if the given interface is unavailable in the active Unity runtime. |
|||
IUnityInterface* (UNITY_INTERFACE_API * GetInterface)(UnityInterfaceGUID guid); |
|||
|
|||
// Registers a new interface. |
|||
void(UNITY_INTERFACE_API * RegisterInterface)(UnityInterfaceGUID guid, IUnityInterface * ptr); |
|||
|
|||
// Split APIs for C |
|||
IUnityInterface* (UNITY_INTERFACE_API * GetInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow); |
|||
void(UNITY_INTERFACE_API * RegisterInterfaceSplit)(unsigned long long guidHigh, unsigned long long guidLow, IUnityInterface * ptr); |
|||
|
|||
#ifdef __cplusplus |
|||
// Helper for GetInterface. |
|||
template<typename INTERFACE> |
|||
INTERFACE* Get() |
|||
{ |
|||
return static_cast<INTERFACE*>(GetInterface(GetUnityInterfaceGUID<INTERFACE>())); |
|||
} |
|||
|
|||
// Helper for RegisterInterface. |
|||
template<typename INTERFACE> |
|||
void Register(IUnityInterface* ptr) |
|||
{ |
|||
RegisterInterface(GetUnityInterfaceGUID<INTERFACE>(), ptr); |
|||
} |
|||
|
|||
#endif |
|||
} IUnityInterfaces; |
|||
|
|||
|
|||
#ifdef __cplusplus |
|||
extern "C" { |
|||
#endif |
|||
|
|||
// If exported by a plugin, this function will be called when the plugin is loaded. |
|||
void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces); |
|||
// If exported by a plugin, this function will be called when the plugin is about to be unloaded. |
|||
void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload(); |
|||
|
|||
#ifdef __cplusplus |
|||
} |
|||
#endif |
|||
|
|||
struct RenderSurfaceBase; |
|||
typedef struct RenderSurfaceBase* UnityRenderBuffer; |
|||
typedef unsigned int UnityTextureID; |
|||
@ -0,0 +1,37 @@ |
|||
// Unity Native Plugin API copyright © 2015 Unity Technologies ApS |
|||
// |
|||
// Licensed under the Unity Companion License for Unity - dependent projects--see[Unity Companion License](http://www.unity3d.com/legal/licenses/Unity_Companion_License). |
|||
// |
|||
// Unless expressly provided otherwise, the Software under this license is made available strictly on an “AS IS” BASIS WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED.Please review the license for details on these and other terms and conditions. |
|||
|
|||
#pragma once |
|||
#include "IUnityInterface.h" |
|||
|
|||
/// The type of the log message |
|||
enum UnityLogType |
|||
{ |
|||
/// UnityLogType used for Errors. |
|||
kUnityLogTypeError = 0, |
|||
/// UnityLogType used for Warnings. |
|||
kUnityLogTypeWarning = 2, |
|||
/// UnityLogType used for regular log messages. |
|||
kUnityLogTypeLog = 3, |
|||
/// UnityLogType used for Exceptions. |
|||
kUnityLogTypeException = 4, |
|||
}; |
|||
|
|||
#define UNITY_WRAP_CODE(CODE_) do { CODE_; } while (0) |
|||
#define UNITY_LOG(PTR_, MSG_) UNITY_WRAP_CODE((PTR_)->Log(kUnityLogTypeLog, MSG_, __FILE__, __LINE__)) |
|||
#define UNITY_LOG_WARNING(PTR_, MSG_) UNITY_WRAP_CODE((PTR_)->Log(kUnityLogTypeWarning, MSG_, __FILE__, __LINE__)) |
|||
#define UNITY_LOG_ERROR(PTR_, MSG_) UNITY_WRAP_CODE((PTR_)->Log(kUnityLogTypeError, MSG_, __FILE__, __LINE__)) |
|||
|
|||
UNITY_DECLARE_INTERFACE(IUnityLog) |
|||
{ |
|||
// Writes information message to Unity log. |
|||
// \param type type log channel type which defines importance of the message. |
|||
// \param message UTF-8 null terminated string. |
|||
// \param fileName UTF-8 null terminated string with file name of the point where message is generated. |
|||
// \param fileLine integer file line number of the point where message is generated. |
|||
void(UNITY_INTERFACE_API * Log)(UnityLogType type, const char* message, const char *fileName, const int fileLine); |
|||
}; |
|||
UNITY_REGISTER_INTERFACE_GUID(0x9E7507fA5B444D5DULL, 0x92FB979515EA83FCULL, IUnityLog) |
|||
@ -0,0 +1,606 @@ |
|||
#include <libsysmodule.h>
|
|||
#include <agc.h>
|
|||
#include <agc/gnmp/gnmp.h>
|
|||
#include <psml_mfsr.h>
|
|||
|
|||
#include "UnityPluginAPI/IUnityInterface.h"
|
|||
#include "UnityPluginAPI/IUnityLog.h"
|
|||
#include "UnityPluginAPI/IUnityGraphics.h"
|
|||
|
|||
#include "UnityPluginAPI/IUnityGraphicsPS5.h"
|
|||
#include "UnityPluginAPI/IUnityGraphicsAgcPS5.h"
|
|||
|
|||
using namespace sce::Agc; |
|||
using namespace sce::Psml; |
|||
|
|||
static IUnityInterfaces* s_UnityInterfaces = nullptr; |
|||
static IUnityLog* s_Log = nullptr; |
|||
static IUnityGraphics* s_Graphics = nullptr; |
|||
static IUnityGraphicsPS5* s_GraphicsPS5 = nullptr; // Old Gnmp-based graphics API
|
|||
static IUnityGraphicsAgcPS5* s_GraphicsAgcPS5 = nullptr; // New Agc-based graphics API (NGGC)
|
|||
static UnityGfxRenderer s_RendererType = kUnityGfxRendererNull; |
|||
|
|||
static bool s_mfsrInitialized = false; |
|||
static size_t s_mfsrSharedResourcesMemorySize = 0; |
|||
static off_t s_mfsrSharedResourcesMemoryAddress = 0; |
|||
static MfsrPhysicalMemoryBlock* s_mfsrSharedResourcesMemoryBlocks = nullptr; |
|||
static MfsrSharedResources s_mfsrSharedResources = nullptr; |
|||
|
|||
struct PssrContext |
|||
{ |
|||
Core::BasicContext agcContext; |
|||
|
|||
size_t mfsrMemorySize = 0; |
|||
off_t mfsrMemoryPhysicalAddress = 0; |
|||
MfsrPhysicalMemoryBlock* mfsrMemoryBlocks = nullptr; |
|||
|
|||
MfsrContext mfsrContext = nullptr; |
|||
Core::Texture outputColorTexture; |
|||
}; |
|||
|
|||
// "Multiple contexts (up to 4) can be generated to perform multiple MFSR processes within an application."
|
|||
static const int MaxNumContexts = 4; |
|||
static PssrContext s_contexts[MaxNumContexts]; |
|||
|
|||
static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType); |
|||
static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data); |
|||
|
|||
// Unity plugin load event
|
|||
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginLoad(IUnityInterfaces* unityInterfaces) |
|||
{ |
|||
s_UnityInterfaces = unityInterfaces; |
|||
s_Log = unityInterfaces->Get<IUnityLog>(); |
|||
s_Graphics = unityInterfaces->Get<IUnityGraphics>(); |
|||
|
|||
s_Graphics->RegisterDeviceEventCallback(OnGraphicsDeviceEvent); |
|||
|
|||
// Run OnGraphicsDeviceEvent(initialize) manually on plugin load
|
|||
// to not miss the event in case the graphics device is already initialized
|
|||
OnGraphicsDeviceEvent(kUnityGfxDeviceEventInitialize); |
|||
} |
|||
|
|||
// Unity plugin unload event
|
|||
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API UnityPluginUnload() |
|||
{ |
|||
s_Graphics->UnregisterDeviceEventCallback(OnGraphicsDeviceEvent); |
|||
} |
|||
|
|||
// Freely defined function to pass a callback to plugin-specific scripts
|
|||
extern "C" UnityRenderingEventAndData UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API GetRenderEventAndDataFunc() |
|||
{ |
|||
return OnRenderEventAndData; |
|||
} |
|||
|
|||
static void UNITY_INTERFACE_API OnGraphicsDeviceEvent(UnityGfxDeviceEventType eventType) |
|||
{ |
|||
switch (eventType) |
|||
{ |
|||
case kUnityGfxDeviceEventInitialize: |
|||
{ |
|||
s_RendererType = s_Graphics->GetRenderer(); |
|||
if (s_RendererType != kUnityGfxRendererPS5 && s_RendererType != kUnityGfxRendererPS5NGGC) |
|||
{ |
|||
return; |
|||
} |
|||
|
|||
s_GraphicsPS5 = s_UnityInterfaces->Get<IUnityGraphicsPS5>(); |
|||
s_GraphicsAgcPS5 = s_UnityInterfaces->Get<IUnityGraphicsAgcPS5>(); |
|||
if (s_GraphicsPS5 == nullptr && s_GraphicsAgcPS5 == nullptr) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "Could not obtain PS5 Graphics interface!"); |
|||
return; |
|||
} |
|||
|
|||
break; |
|||
} |
|||
case kUnityGfxDeviceEventShutdown: |
|||
{ |
|||
s_GraphicsPS5 = nullptr; |
|||
s_GraphicsAgcPS5 = nullptr; |
|||
s_RendererType = kUnityGfxRendererNull; |
|||
break; |
|||
} |
|||
case kUnityGfxDeviceEventBeforeReset: |
|||
{ |
|||
break; |
|||
} |
|||
case kUnityGfxDeviceEventAfterReset: |
|||
{ |
|||
break; |
|||
} |
|||
}; |
|||
} |
|||
|
|||
extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_Init() |
|||
{ |
|||
if (s_Log == nullptr || s_Graphics == nullptr) |
|||
{ |
|||
// Plugin was not loaded correctly, cannot log an error message here
|
|||
return INT32_MIN; |
|||
} |
|||
|
|||
// Check if we're running on PS5 Pro
|
|||
if (!sceKernelIsTrinityMode()) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "Kernel is not running in Trinity mode, PSML is not supported!"); |
|||
return -1; |
|||
} |
|||
|
|||
// Load PSML module
|
|||
if (sceSysmoduleIsLoaded(SCE_SYSMODULE_PSML) != SCE_SYSMODULE_LOADED) |
|||
{ |
|||
int res = sceSysmoduleLoadModule(SCE_SYSMODULE_PSML); |
|||
if (res < SCE_OK) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Failed to load PSML sysmodule, error code = " << res; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return res; |
|||
} |
|||
} |
|||
|
|||
// Initialize MFSR
|
|||
int res = initMfsr(); |
|||
if (res != SCE_OK && res != SCE_PSML_MFSR_ERROR_ALREADY_INITIALIZED) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Failed to initialize MFSR, error code = " << res; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return res; |
|||
} |
|||
|
|||
if (s_mfsrInitialized) |
|||
{ |
|||
return SCE_OK; |
|||
} |
|||
|
|||
// Set up MFSR shared resources
|
|||
{ |
|||
// Get required physical memory blocks sizeAlign for initializing MFSR shared resources
|
|||
MfsrSharedResourcesInitParameters mfsrSharedResourcesInitParameters; |
|||
mfsrSharedResourcesInitParameters.init(); |
|||
mfsrSharedResourcesInitParameters.m_profile = MfsrProfile::kQuality; |
|||
|
|||
MfsrSharedResourcesInitRequirement mfsrSharedResourcesInitRequirement; |
|||
getMfsrSharedResourcesInitRequirement(&mfsrSharedResourcesInitRequirement, &mfsrSharedResourcesInitParameters); |
|||
|
|||
// Allocate physical memory blocks for MFSR shared resource and setup shared resources init param
|
|||
s_mfsrSharedResourcesMemoryBlocks = new MfsrPhysicalMemoryBlock[mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockCount]; |
|||
|
|||
size_t blockSize = mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockSize; |
|||
size_t blockAlign = mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockAlignment; |
|||
|
|||
s_mfsrSharedResourcesMemorySize = mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockCount * blockSize; |
|||
sceKernelAllocateMainDirectMemory(s_mfsrSharedResourcesMemorySize, blockAlign, SCE_KERNEL_MTYPE_C_SHARED, &s_mfsrSharedResourcesMemoryAddress); |
|||
|
|||
for (uint32_t i = 0; i < mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockCount; i++) |
|||
{ |
|||
s_mfsrSharedResourcesMemoryBlocks[i].m_size = blockSize; |
|||
s_mfsrSharedResourcesMemoryBlocks[i].m_offset = s_mfsrSharedResourcesMemoryAddress + blockSize * i; |
|||
} |
|||
|
|||
mfsrSharedResourcesInitParameters.m_physicalMemoryBlocks = s_mfsrSharedResourcesMemoryBlocks; |
|||
mfsrSharedResourcesInitParameters.m_physicalMemoryBlockCount = mfsrSharedResourcesInitRequirement.m_physicalMemoryBlockCount; |
|||
|
|||
// Create MFSR shared resources with the memory
|
|||
createMfsrSharedResources(&s_mfsrSharedResources, &mfsrSharedResourcesInitParameters); |
|||
} |
|||
|
|||
s_mfsrInitialized = true; |
|||
|
|||
UNITY_LOG(s_Log, "PSSR plugin initialized"); |
|||
return SCE_OK; |
|||
} |
|||
|
|||
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_Release() |
|||
{ |
|||
s_mfsrInitialized = false; |
|||
|
|||
// Destroy the MFSR shared resources
|
|||
if (s_mfsrSharedResources != nullptr) |
|||
{ |
|||
releaseMfsrSharedResources(s_mfsrSharedResources); |
|||
s_mfsrSharedResources = nullptr; |
|||
} |
|||
|
|||
// Free the memory used for MFSR shared resource data
|
|||
if (s_mfsrSharedResourcesMemoryAddress != 0) |
|||
{ |
|||
sceKernelReleaseDirectMemory(s_mfsrSharedResourcesMemoryAddress, s_mfsrSharedResourcesMemorySize); |
|||
s_mfsrSharedResourcesMemoryAddress = 0; |
|||
s_mfsrSharedResourcesMemorySize = 0; |
|||
} |
|||
|
|||
if (s_mfsrSharedResourcesMemoryBlocks != nullptr) |
|||
{ |
|||
delete[] s_mfsrSharedResourcesMemoryBlocks; |
|||
s_mfsrSharedResourcesMemoryBlocks = nullptr; |
|||
} |
|||
} |
|||
|
|||
typedef struct pssr_init_params_s |
|||
{ |
|||
uint32_t contextIndex; |
|||
|
|||
uint32_t displayWidth; |
|||
uint32_t displayHeight; |
|||
uint32_t maxRenderWidth; |
|||
uint32_t maxRenderHeight; |
|||
|
|||
uint32_t autoKeepCopies; |
|||
} pssr_init_params_t; |
|||
|
|||
typedef struct pssr_dispatch_params_s |
|||
{ |
|||
uint32_t contextIndex; |
|||
|
|||
sce::Agc::Core::Texture* color; |
|||
sce::Agc::Core::Texture* depth; |
|||
sce::Agc::Core::Texture* prevDepth; |
|||
sce::Agc::Core::Texture* motionVectors; |
|||
sce::Agc::Core::Texture* prevMotionVectors; |
|||
sce::Agc::Core::Texture* exposure; |
|||
sce::Agc::Core::Texture* reactiveMask; |
|||
sce::Agc::Core::Texture* outputColor; |
|||
|
|||
uint32_t renderWidth; |
|||
uint32_t renderHeight; |
|||
|
|||
Vector2f jitter; |
|||
Vector2f motionVectorScale; |
|||
|
|||
Matrix4f camProjectionNoJitter; |
|||
Vector3f camForward; |
|||
Vector3f camUp; |
|||
Vector3f camRight; |
|||
Vector3d camPosition; |
|||
float camNear; |
|||
float camFar; |
|||
float preExposure; |
|||
uint32_t resetHistory; |
|||
MfsrOptionFlags flags; |
|||
|
|||
} pssr_dispatch_params_t; |
|||
|
|||
typedef struct pssr_destroy_params_s |
|||
{ |
|||
uint32_t contextIndex; |
|||
} pssr_destroy_params_t; |
|||
|
|||
typedef struct pssr_capture_params_s |
|||
{ |
|||
uint32_t contextIndex; |
|||
|
|||
uint8_t frameNum; |
|||
} pssr_capture_params_t; |
|||
|
|||
static bool IsInitialized() |
|||
{ |
|||
if (!s_mfsrInitialized) |
|||
return false; |
|||
|
|||
if (s_RendererType == kUnityGfxRendererPS5 && s_GraphicsPS5 == nullptr) |
|||
return false; |
|||
|
|||
if (s_RendererType == kUnityGfxRendererPS5NGGC && s_GraphicsAgcPS5 == nullptr) |
|||
return false; |
|||
|
|||
return true; |
|||
} |
|||
|
|||
extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_CreateContext(const pssr_init_params_t* params, Core::Texture** outputColorTexture) |
|||
{ |
|||
if (!IsInitialized()) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "PSSR plugin is not initialized properly"); |
|||
return -1; |
|||
} |
|||
|
|||
if (params->contextIndex < 0 || params->contextIndex >= MaxNumContexts) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Invalid PSSR context index: " << params->contextIndex; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return -1; |
|||
} |
|||
|
|||
PssrContext& context = s_contexts[params->contextIndex]; |
|||
|
|||
MfsrContextInitParameters initParams = {}; |
|||
initParams.init(); |
|||
initParams.m_outputColorWidth = params->displayWidth; |
|||
initParams.m_outputColorHeight = params->displayHeight; |
|||
initParams.m_sharedResources = s_mfsrSharedResources; |
|||
|
|||
MfsrKeepCopyTextureSpec depthCopySpec = {}, mvCopySpec = {}; |
|||
if (params->autoKeepCopies) |
|||
{ |
|||
// Keep a copy of the previous depth internally
|
|||
depthCopySpec.m_width = params->maxRenderWidth; |
|||
depthCopySpec.m_height = params->maxRenderHeight; |
|||
depthCopySpec.m_bytesPerPixel = 4; // R32_SFloat
|
|||
initParams.m_maxSizeDepthForKeepCopy = &depthCopySpec; |
|||
|
|||
// Keep a copy of the previous motion vectors internally
|
|||
mvCopySpec.m_width = params->maxRenderWidth; |
|||
mvCopySpec.m_height = params->maxRenderHeight; |
|||
mvCopySpec.m_bytesPerPixel = 4; // R16G16_SFloat
|
|||
initParams.m_maxSizeMotionVectorsForKeepCopy = &mvCopySpec; |
|||
} |
|||
|
|||
// Allocate memory used by this MFSR context
|
|||
{ |
|||
MfsrContextInitRequirement mfsrInitRequirement = {}; |
|||
getMfsrContextInitRequirement(&mfsrInitRequirement, &initParams); |
|||
|
|||
context.mfsrMemoryBlocks = new MfsrPhysicalMemoryBlock[mfsrInitRequirement.m_physicalMemoryBlockCount]; |
|||
|
|||
size_t size = mfsrInitRequirement.m_physicalMemoryBlockSize; |
|||
size_t align = mfsrInitRequirement.m_physicalMemoryBlockAlignment; |
|||
|
|||
context.mfsrMemorySize = mfsrInitRequirement.m_physicalMemoryBlockCount * size; |
|||
sceKernelAllocateMainDirectMemory(context.mfsrMemorySize, align, SCE_KERNEL_MTYPE_C_SHARED, &context.mfsrMemoryPhysicalAddress); |
|||
|
|||
for (uint32_t i = 0; i < mfsrInitRequirement.m_physicalMemoryBlockCount; i++) |
|||
{ |
|||
context.mfsrMemoryBlocks[i].m_size = size; |
|||
context.mfsrMemoryBlocks[i].m_offset = context.mfsrMemoryPhysicalAddress + mfsrInitRequirement.m_physicalMemoryBlockSize * i; |
|||
} |
|||
|
|||
initParams.m_sharedResources = s_mfsrSharedResources; |
|||
initParams.m_physicalMemoryBlocks = context.mfsrMemoryBlocks; |
|||
initParams.m_physicalMemoryBlockCount = mfsrInitRequirement.m_physicalMemoryBlockCount; |
|||
} |
|||
|
|||
// Set up output color texture with the correct specifications (k11_11_10Float with tile mode kStandard256B)
|
|||
if (outputColorTexture != nullptr) |
|||
{ |
|||
Core::TextureSpec texSpec; |
|||
texSpec.init(); |
|||
texSpec.setAllowNullptr(true); |
|||
texSpec.m_width = params->displayWidth; |
|||
texSpec.m_height = params->displayHeight; |
|||
texSpec.m_format = { Core::TypedFormat::k11_11_10Float, Core::Swizzle::kRGB1_R3S34 }; |
|||
texSpec.setTileMode(Core::Texture::TileMode::kStandard256B); |
|||
|
|||
SizeAlign sizeAlign = Core::getSize(&texSpec); |
|||
if (s_GraphicsPS5 != nullptr) |
|||
{ |
|||
texSpec.m_dataAddress = s_GraphicsPS5->AllocateGPUMemory(sizeAlign.m_size, MfsrAlignment::kOutputTexture); |
|||
} |
|||
else if (s_GraphicsAgcPS5 != nullptr) |
|||
{ |
|||
texSpec.m_dataAddress = s_GraphicsAgcPS5->AllocateGPUMemory(sizeAlign.m_size, MfsrAlignment::kOutputTexture); |
|||
} |
|||
|
|||
int res = Core::initialize(&context.outputColorTexture, &texSpec); |
|||
if (res != SCE_OK) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Failed to create MFSR output color texture, error code = " << res; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return res; |
|||
} |
|||
|
|||
*outputColorTexture = &context.outputColorTexture; |
|||
} |
|||
|
|||
// Set up command buffer for NGGC
|
|||
if (s_RendererType == kUnityGfxRendererPS5NGGC && s_GraphicsAgcPS5 != nullptr) |
|||
{ |
|||
const size_t agcContextSize = 128 * 1024; |
|||
context.agcContext.m_dcb.init(s_GraphicsAgcPS5->AllocateGPUMemory(agcContextSize, Alignment::kCommandBuffer), agcContextSize); |
|||
context.agcContext.m_bdr.init(&context.agcContext.m_dcb, &context.agcContext.m_dcb); |
|||
context.agcContext.m_sb.init(256, &context.agcContext.m_dcb, &context.agcContext.m_dcb); |
|||
} |
|||
|
|||
// Finally, create the actual MFSR context
|
|||
int res = createMfsrContext(&context.mfsrContext, &initParams); |
|||
if (res != SCE_OK) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Failed to create MFSR context, error code = " << res; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return res; |
|||
} |
|||
|
|||
UNITY_LOG(s_Log, "Created PSSR context"); |
|||
return SCE_OK; |
|||
} |
|||
|
|||
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_DestroyContext(uint32_t contextIndex) |
|||
{ |
|||
if (!IsInitialized()) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "PSSR plugin is not initialized properly"); |
|||
return; |
|||
} |
|||
|
|||
if (contextIndex < 0 || contextIndex >= MaxNumContexts) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Invalid PSSR context index: " << contextIndex; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return; |
|||
} |
|||
|
|||
PssrContext& context = s_contexts[contextIndex]; |
|||
|
|||
// Destroy the MFSR context
|
|||
if (context.mfsrContext != nullptr) |
|||
{ |
|||
releaseMfsrContext(context.mfsrContext); |
|||
context.mfsrContext = nullptr; |
|||
} |
|||
|
|||
// Destroy the NGGC command buffer
|
|||
if (s_GraphicsAgcPS5 != nullptr && context.agcContext.m_dcb.m_bottom != nullptr) |
|||
{ |
|||
s_GraphicsAgcPS5->ReleaseGPUMemory(context.agcContext.m_dcb.m_bottom); |
|||
context.agcContext.m_dcb.clear(); |
|||
} |
|||
|
|||
// Destroy the output color texture
|
|||
if (context.outputColorTexture.getDataAddress()) |
|||
{ |
|||
if (s_GraphicsPS5 != nullptr) |
|||
{ |
|||
s_GraphicsPS5->ReleaseGPUMemory(context.outputColorTexture.getDataAddress()); |
|||
} |
|||
else if (s_GraphicsAgcPS5 != nullptr) |
|||
{ |
|||
s_GraphicsAgcPS5->ReleaseGPUMemory(context.outputColorTexture.getDataAddress()); |
|||
} |
|||
|
|||
context.outputColorTexture.init(); |
|||
} |
|||
|
|||
// Free the memory used for MFSR context data
|
|||
if (context.mfsrMemoryPhysicalAddress != 0) |
|||
{ |
|||
sceKernelReleaseDirectMemory(context.mfsrMemoryPhysicalAddress, context.mfsrMemorySize); |
|||
context.mfsrMemoryPhysicalAddress = 0; |
|||
context.mfsrMemorySize = 0; |
|||
} |
|||
|
|||
if (context.mfsrMemoryBlocks != nullptr) |
|||
{ |
|||
delete[] context.mfsrMemoryBlocks; |
|||
context.mfsrMemoryBlocks = nullptr; |
|||
} |
|||
|
|||
UNITY_LOG(s_Log, "Destroyed PSSR context"); |
|||
} |
|||
|
|||
extern "C" void UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_Dispatch(const pssr_dispatch_params_t* params) |
|||
{ |
|||
if (!IsInitialized()) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "PSSR plugin is not initialized properly"); |
|||
return; |
|||
} |
|||
|
|||
if (params->contextIndex < 0 || params->contextIndex >= MaxNumContexts) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Invalid PSSR context index: " << params->contextIndex; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return; |
|||
} |
|||
|
|||
PssrContext& context = s_contexts[params->contextIndex]; |
|||
if (context.mfsrContext == nullptr) |
|||
return; |
|||
|
|||
// How we obtain a command buffer to dispatch to depends on which graphics API we're using in Unity
|
|||
sce::Agc::DrawCommandBuffer* cmd = nullptr; |
|||
if (s_RendererType == kUnityGfxRendererPS5) |
|||
{ |
|||
auto* gfxc = (sce::Agc::Gnmp::LightweightGfxContext*)s_GraphicsPS5->GetGfxContext(); |
|||
cmd = &gfxc->m_agcCtx.m_dcb; |
|||
} |
|||
else if (s_RendererType == kUnityGfxRendererPS5NGGC) |
|||
{ |
|||
Core::BasicContext& ctx = context.agcContext.reset(); |
|||
cmd = &ctx.m_dcb; |
|||
} |
|||
|
|||
cmd->pushMarker("Dispatch MFSR"); |
|||
|
|||
DispatchMfsrParameters dispatchParams = {}; |
|||
dispatchParams.init(); |
|||
dispatchParams.m_outputColor = params->outputColor; |
|||
dispatchParams.m_color = params->color; |
|||
dispatchParams.m_motionVectors = params->motionVectors; |
|||
dispatchParams.m_prevDepth = params->prevDepth; |
|||
dispatchParams.m_depth = params->depth; |
|||
dispatchParams.m_exposure = params->exposure; |
|||
dispatchParams.m_reactiveMask = params->reactiveMask; |
|||
dispatchParams.m_prevMotionVectors = params->prevMotionVectors; |
|||
dispatchParams.m_preExposure = params->preExposure; |
|||
dispatchParams.m_projectionNoJitter = params->camProjectionNoJitter; |
|||
dispatchParams.m_camForward = params->camForward; |
|||
dispatchParams.m_camUp = params->camUp; |
|||
dispatchParams.m_camRight = params->camRight; |
|||
dispatchParams.m_camPosD = params->camPosition; |
|||
dispatchParams.m_nearZ = params->camNear; |
|||
dispatchParams.m_farZ = params->camFar; |
|||
dispatchParams.m_renderWidth = params->renderWidth; |
|||
dispatchParams.m_renderHeight = params->renderHeight; |
|||
dispatchParams.m_jitter = params->jitter; |
|||
dispatchParams.m_motionVectorScale = params->motionVectorScale; |
|||
dispatchParams.m_motionVectorGamma = 1.0f; |
|||
dispatchParams.m_reset = params->resetHistory != 0; |
|||
dispatchParams.m_flags = params->flags; |
|||
|
|||
dispatchMfsr(context.mfsrContext, cmd, &dispatchParams); |
|||
|
|||
cmd->popMarker(); |
|||
|
|||
if (s_RendererType == kUnityGfxRendererPS5NGGC) |
|||
{ |
|||
s_GraphicsAgcPS5->SubmitGraphics(cmd->getSubmitPointer(), cmd->getSubmitSize()); |
|||
} |
|||
} |
|||
|
|||
extern "C" int32_t UNITY_INTERFACE_EXPORT UNITY_INTERFACE_API PSSR_RequestCapture(uint32_t contextIndex, uint8_t frameNum) |
|||
{ |
|||
if (!IsInitialized()) |
|||
{ |
|||
UNITY_LOG_ERROR(s_Log, "PSSR plugin is not initialized properly"); |
|||
return -1; |
|||
} |
|||
|
|||
if (contextIndex < 0 || contextIndex >= MaxNumContexts) |
|||
{ |
|||
std::stringstream msg; |
|||
msg << "Invalid PSSR context index: " << contextIndex; |
|||
UNITY_LOG_ERROR(s_Log, msg.str().c_str()); |
|||
return -1; |
|||
} |
|||
|
|||
PssrContext& context = s_contexts[contextIndex]; |
|||
if (context.mfsrContext == nullptr) |
|||
return -1; |
|||
|
|||
if (isMfsrCaptureInProgress(context.mfsrContext)) |
|||
{ |
|||
UNITY_LOG_WARNING(s_Log, "PSSR capture already in progress"); |
|||
return -1; |
|||
} |
|||
|
|||
return requestMfsrCapture(context.mfsrContext, frameNum); |
|||
} |
|||
|
|||
// Plugin function to handle a specific rendering event
|
|||
static void UNITY_INTERFACE_API OnRenderEventAndData(int eventID, void* data) |
|||
{ |
|||
// User rendering code
|
|||
switch (eventID) |
|||
{ |
|||
case 0: // Create PSSR context
|
|||
{ |
|||
auto* params = (pssr_init_params_t*)data; |
|||
PSSR_CreateContext(params, nullptr); |
|||
break; |
|||
} |
|||
case 1: // Execute PSSR
|
|||
{ |
|||
auto* params = (pssr_dispatch_params_t*)data; |
|||
PSSR_Dispatch(params); |
|||
break; |
|||
} |
|||
case 2: // Destroy PSSR context
|
|||
{ |
|||
auto* params = (pssr_destroy_params_t*)data; |
|||
PSSR_DestroyContext(params->contextIndex); |
|||
break; |
|||
} |
|||
case 3: // Request PSSR capture
|
|||
{ |
|||
auto* params = (pssr_capture_params_t*)data; |
|||
PSSR_RequestCapture(params->contextIndex, params->frameNum); |
|||
break; |
|||
} |
|||
} |
|||
} |
|||
@ -0,0 +1,13 @@ |
|||
{ |
|||
"name": "com.ww1gameseries.pssr", |
|||
"version": "1.0.0", |
|||
"author": "WW1 Game Series", |
|||
"unity": "2022.3", |
|||
"displayName": "PSSR Upscaler Plugin", |
|||
"description": "Provides a native plugin for the PS5 Pro's PSSR upscaling technology", |
|||
"keywords": [ |
|||
"ps5", |
|||
"playstation" |
|||
], |
|||
"dependencies": {} |
|||
} |
|||
@ -0,0 +1,7 @@ |
|||
fileFormatVersion: 2 |
|||
guid: 1eef1819b5808e94e9a9d4de243456bb |
|||
PackageManifestImporter: |
|||
externalObjects: {} |
|||
userData: |
|||
assetBundleName: |
|||
assetBundleVariant: |
|||
Write
Preview
Loading…
Cancel
Save
Reference in new issue