SHA256
Document Render Core And API
This commit is contained in:
1 parent
354c42fdd9
commit
8deb64fd4d
22 files changed
+1241
-27
No files matched your search
@@ -6,16 +6,58 @@ using UnityEngine;
|
||||
|
||||
namespace ADOFAIRenderer.Core;
|
||||
|
||||
/// <summary>
|
||||
/// Runs the frame hooks (session and global, see RenderSession) on a captured frame before it is read back.
|
||||
/// Owns two RenderTextures (ping and pong) with the size and format of the source frame; each hook pass reads the
|
||||
/// current frame and writes the other buffer (see FrameHookContext). One instance per render, created in
|
||||
/// RenderManager.SetupPlay and disposed when the render ends. Main thread only.
|
||||
/// </summary>
|
||||
internal class FrameHookPipeline : IDisposable
|
||||
{
|
||||
/// <summary>First ping-pong buffer. Created by EnsureBuffers, released by ReleaseBuffers.</summary>
|
||||
private RenderTexture? _pingRT;
|
||||
|
||||
/// <summary>Second ping-pong buffer. Created by EnsureBuffers, released by ReleaseBuffers.</summary>
|
||||
private RenderTexture? _pongRT;
|
||||
|
||||
/// <summary>
|
||||
/// Buffer returned as the output of the previous Process call (ping or pong), or null when the previous frame was
|
||||
/// not modified by any hook. Its readback may still be in flight, so the next frame starts writing the other buffer.
|
||||
/// </summary>
|
||||
private RenderTexture? _lastOutputRT;
|
||||
|
||||
/// <summary>Context object passed to the hooks; reset and reused for every frame (no allocation per frame).</summary>
|
||||
private FrameHookContext? _reusableContext;
|
||||
|
||||
/// <summary>Width of the current buffers in pixels (0 when no buffers exist).</summary>
|
||||
private int _width;
|
||||
|
||||
/// <summary>Height of the current buffers in pixels (0 when no buffers exist).</summary>
|
||||
private int _height;
|
||||
|
||||
/// <summary>Format of the source texture the current buffers were created for.</summary>
|
||||
private RenderTextureFormat _format;
|
||||
|
||||
/// <summary>
|
||||
/// Runs <paramref name="hooks"/> in order on <paramref name="sourceTexture"/> and returns the resulting texture.
|
||||
/// An exception thrown by a hook is logged and the remaining hooks still run.
|
||||
/// RenderTexture.active is restored after the hooks.
|
||||
/// </summary>
|
||||
/// <param name="sourceTexture">Captured game frame. Hooks do not write into it (they write the ping-pong buffers).</param>
|
||||
/// <param name="frameIndex">Video frame index (0-based) of this frame.</param>
|
||||
/// <param name="renderFrameIndex">
|
||||
/// Render frame index (0-based, RenderManager.frameCountForVideo): counts every game frame since capture started,
|
||||
/// including game frames that were not captured because they fall in an already captured video frame.
|
||||
/// </param>
|
||||
/// <param name="videoTime">Time of this video frame in seconds from the start of the video.</param>
|
||||
/// <param name="renderFps">Render frame rate (game frames per second).</param>
|
||||
/// <param name="videoFps">Effective video frame rate (min(VideoFPS, RenderFPS)).</param>
|
||||
/// <param name="hooks">Hooks to run, in order. Session hooks come before global hooks.</param>
|
||||
/// <returns>
|
||||
/// <paramref name="sourceTexture"/> when there are no hooks, the source is not created, the buffers could not be
|
||||
/// created, or no hook modified the frame; otherwise the texture holding the final frame (a ping-pong buffer, or a
|
||||
/// texture a hook passed to FrameHookContext.ReplaceCurrent).
|
||||
/// </returns>
|
||||
public RenderTexture? Process(
|
||||
RenderTexture sourceTexture,
|
||||
long frameIndex,
|
||||
@@ -81,6 +123,8 @@ internal class FrameHookPipeline : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
// Current is the source when nothing was modified. A texture set by ReplaceCurrent is stored in
|
||||
// _lastOutputRT too; it then matches neither buffer and the next frame starts with ping.
|
||||
var result = _reusableContext.Current;
|
||||
_lastOutputRT = _reusableContext.HasModified ? result : null;
|
||||
return result;
|
||||
@@ -91,6 +135,12 @@ internal class FrameHookPipeline : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Creates the ping and pong buffers when they do not exist, were released, or the source size or format changed.
|
||||
/// The buffers copy the source descriptor without depth, MSAA and mipmaps, and enable random write (UAV) when the
|
||||
/// GPU supports compute shaders and random write for that format, so compute shaders can write them.
|
||||
/// When creating them from the descriptor throws, ARGB32 buffers of the same size are created.
|
||||
/// </summary>
|
||||
private void EnsureBuffers(RenderTexture sourceTexture)
|
||||
{
|
||||
var width = sourceTexture.width;
|
||||
@@ -160,6 +210,9 @@ internal class FrameHookPipeline : IDisposable
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Releases and destroys both buffers and drops the reusable context. The next Process call creates them again.
|
||||
/// </summary>
|
||||
public void ReleaseBuffers()
|
||||
{
|
||||
if (_pingRT)
|
||||
@@ -182,6 +235,7 @@ internal class FrameHookPipeline : IDisposable
|
||||
_reusableContext = null;
|
||||
}
|
||||
|
||||
/// <summary>Same as <see cref="ReleaseBuffers"/>. Main thread (Object.Destroy is used).</summary>
|
||||
public void Dispose()
|
||||
{
|
||||
ReleaseBuffers();
|
||||
|
||||
Reference in new issue
Block a user