SHA256
Compare commits
5
Commits
| Author | SHA256 | Date | |
|---|---|---|---|
|
|
ba83935190
|
||
|
|
d2390665af
|
||
|
|
ceb3190274
|
||
|
|
08b13460ae
|
||
|
|
ed7dd5dba4 |
No files matched your search
@@ -13,6 +13,8 @@
|
||||
|
||||
By decoupling the game's simulation timestep from wall-clock time, ADOFAI Renderer enables creators to produce smooth, ultra-high-definition game videos with perfect audio sync, regardless of hardware limitations or level complexity.
|
||||
|
||||
> Generative AI technology was partially utilized in the development of this mod.
|
||||
|
||||
---
|
||||
|
||||
## ✨ Key Features
|
||||
|
||||
+1
-1
@@ -9,7 +9,7 @@ using MelonLoader.Utils;
|
||||
using UnityEngine;
|
||||
using Object = UnityEngine.Object;
|
||||
|
||||
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.2.3-INDEV", "ADOFAI Editor Forum")]
|
||||
[assembly: MelonInfo(typeof(RenderMod), "ADOFAI Renderer", "0.2.4-INDEV", "ADOFAI Editor Forum")]
|
||||
[assembly: MelonGame("7th Beat Games", "A Dance of Fire and Ice")]
|
||||
|
||||
namespace ADOFAIRenderer;
|
||||
|
||||
+935
-296
File diff suppressed because it is too large.
Load diff
+33
-31
@@ -26,12 +26,34 @@ namespace ADOFAIRenderer.Util
|
||||
private readonly object _poolLock = new();
|
||||
private bool _isInitialized;
|
||||
private volatile bool _isDisposed;
|
||||
|
||||
private readonly AVPixelFormat _targetFormat;
|
||||
|
||||
private readonly ComputeShader? _computeShader;
|
||||
private readonly int _kernelIndex = -1;
|
||||
private readonly bool _useGPUConversion;
|
||||
private readonly AVPixelFormat _expectedFormat;
|
||||
|
||||
public FrameReader(AVPixelFormat targetFormat)
|
||||
{
|
||||
_targetFormat = targetFormat;
|
||||
_computeShader = ModAssets.ColorConversionShader;
|
||||
if (_computeShader)
|
||||
{
|
||||
var kernelName = targetFormat switch
|
||||
{
|
||||
AVPixelFormat.AV_PIX_FMT_NV12 => "CSMain_NV12",
|
||||
AVPixelFormat.AV_PIX_FMT_YUV420P => "CSMain_YUV420P",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (kernelName != null)
|
||||
{
|
||||
try { _kernelIndex = _computeShader.FindKernel(kernelName); }
|
||||
catch { _kernelIndex = -1; }
|
||||
}
|
||||
}
|
||||
|
||||
_useGPUConversion = _kernelIndex >= 0;
|
||||
_expectedFormat = _useGPUConversion ? targetFormat : AVPixelFormat.AV_PIX_FMT_RGBA;
|
||||
|
||||
InitializePool();
|
||||
}
|
||||
|
||||
@@ -71,42 +93,22 @@ namespace ADOFAIRenderer.Util
|
||||
state.IsInFlight = true;
|
||||
}
|
||||
|
||||
// Check if GPU color conversion is available
|
||||
var expectedFmt = AVPixelFormat.AV_PIX_FMT_RGBA;
|
||||
|
||||
var kernelIndex = -1;
|
||||
if (ModAssets.ColorConversionShader)
|
||||
{
|
||||
var kernalName = _targetFormat switch
|
||||
{
|
||||
AVPixelFormat.AV_PIX_FMT_NV12 => "CSMain_NV12",
|
||||
AVPixelFormat.AV_PIX_FMT_YUV420P => "CSMain_YUV420P",
|
||||
_ => null
|
||||
};
|
||||
|
||||
if (kernalName != null)
|
||||
kernelIndex = ModAssets.ColorConversionShader.FindKernel(kernalName);
|
||||
}
|
||||
|
||||
var useGPUConversion = kernelIndex >= 0;
|
||||
if (useGPUConversion) expectedFmt = _targetFormat;
|
||||
|
||||
var bufferSize = texture.width * texture.height * 4; // RGBA = 4 channel
|
||||
state.Setup(currentFrame, bufferSize, useGPUConversion, expectedFmt, texture.width, texture.height);
|
||||
state.Setup(currentFrame, bufferSize, _useGPUConversion, _expectedFormat, texture.width, texture.height);
|
||||
|
||||
if (useGPUConversion && state.GPUBuffer != null && ModAssets.ColorConversionShader)
|
||||
if (_useGPUConversion && state.GPUBuffer != null && _computeShader)
|
||||
{
|
||||
ModAssets.ColorConversionShader.SetTexture(kernelIndex, SourceTexture, texture);
|
||||
ModAssets.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer);
|
||||
ModAssets.ColorConversionShader.SetInt(Width, texture.width);
|
||||
ModAssets.ColorConversionShader.SetInt(Height, texture.height);
|
||||
_computeShader.SetTexture(_kernelIndex, SourceTexture, texture);
|
||||
_computeShader.SetBuffer(_kernelIndex, DestinationBuffer, state.GPUBuffer);
|
||||
_computeShader.SetInt(Width, texture.width);
|
||||
_computeShader.SetInt(Height, texture.height);
|
||||
|
||||
var threadGroupsX = expectedFmt == AVPixelFormat.AV_PIX_FMT_NV12
|
||||
var threadGroupsX = _expectedFormat == AVPixelFormat.AV_PIX_FMT_NV12
|
||||
? (texture.width + 31) / 32
|
||||
: (texture.width + 63) / 64;
|
||||
var threadGroupsY = (texture.height + 15) / 16;
|
||||
|
||||
ModAssets.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1);
|
||||
_computeShader.Dispatch(_kernelIndex, threadGroupsX, threadGroupsY, 1);
|
||||
|
||||
AsyncGPUReadback.RequestIntoNativeArray(
|
||||
ref state.NativeBuffer, state.GPUBuffer, state.CachedCallback
|
||||
|
||||
Reference in new issue
Block a user