SHA256
Optimize FrameReader by Caching Color Conversion Kernel
This commit is contained in:
1 file changed
+32
-30
+32
-30
@@ -27,11 +27,33 @@ namespace ADOFAIRenderer.Util
|
|||||||
private bool _isInitialized;
|
private bool _isInitialized;
|
||||||
private volatile bool _isDisposed;
|
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)
|
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();
|
InitializePool();
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -71,42 +93,22 @@ namespace ADOFAIRenderer.Util
|
|||||||
state.IsInFlight = true;
|
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
|
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);
|
_computeShader.SetTexture(_kernelIndex, SourceTexture, texture);
|
||||||
ModAssets.ColorConversionShader.SetBuffer(kernelIndex, DestinationBuffer, state.GPUBuffer);
|
_computeShader.SetBuffer(_kernelIndex, DestinationBuffer, state.GPUBuffer);
|
||||||
ModAssets.ColorConversionShader.SetInt(Width, texture.width);
|
_computeShader.SetInt(Width, texture.width);
|
||||||
ModAssets.ColorConversionShader.SetInt(Height, texture.height);
|
_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 + 31) / 32
|
||||||
: (texture.width + 63) / 64;
|
: (texture.width + 63) / 64;
|
||||||
var threadGroupsY = (texture.height + 15) / 16;
|
var threadGroupsY = (texture.height + 15) / 16;
|
||||||
|
|
||||||
ModAssets.ColorConversionShader.Dispatch(kernelIndex, threadGroupsX, threadGroupsY, 1);
|
_computeShader.Dispatch(_kernelIndex, threadGroupsX, threadGroupsY, 1);
|
||||||
|
|
||||||
AsyncGPUReadback.RequestIntoNativeArray(
|
AsyncGPUReadback.RequestIntoNativeArray(
|
||||||
ref state.NativeBuffer, state.GPUBuffer, state.CachedCallback
|
ref state.NativeBuffer, state.GPUBuffer, state.CachedCallback
|
||||||
|
|||||||
Reference in new issue
Block a user