refactor(rendering/srp): unify managed fullscreen raster recording
This commit is contained in:
@@ -0,0 +1,338 @@
|
||||
using System;
|
||||
using XCEngine;
|
||||
using XCEngine.Rendering;
|
||||
|
||||
namespace XCEngine.Rendering.Universal
|
||||
{
|
||||
public abstract class ScriptableRenderPass
|
||||
{
|
||||
private const string kColorScaleFullscreenPassName =
|
||||
"Universal.ColorScaleFullscreen";
|
||||
private const string kShaderVectorFullscreenPassName =
|
||||
"Universal.ShaderVectorFullscreen";
|
||||
|
||||
private enum RecordedScenePhase
|
||||
{
|
||||
Opaque = 0,
|
||||
Skybox = 1,
|
||||
Transparent = 3
|
||||
}
|
||||
|
||||
private enum RecordedSceneInjectionPoint
|
||||
{
|
||||
BeforeOpaque = 0,
|
||||
AfterOpaque = 1,
|
||||
BeforeSkybox = 2,
|
||||
AfterSkybox = 3,
|
||||
BeforeTransparent = 4,
|
||||
AfterTransparent = 5
|
||||
}
|
||||
|
||||
protected ScriptableRenderPass()
|
||||
{
|
||||
}
|
||||
|
||||
public RenderPassEvent renderPassEvent { get; protected set; } =
|
||||
RenderPassEvent.BeforeRenderingOpaques;
|
||||
|
||||
public virtual bool SupportsStage(
|
||||
CameraFrameStage stage)
|
||||
{
|
||||
CameraFrameStage resolvedStage;
|
||||
return TryResolveStage(
|
||||
renderPassEvent,
|
||||
out resolvedStage) &&
|
||||
resolvedStage == stage;
|
||||
}
|
||||
|
||||
internal bool Record(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData)
|
||||
{
|
||||
return RecordRenderGraph(
|
||||
context,
|
||||
renderingData);
|
||||
}
|
||||
|
||||
protected abstract bool RecordRenderGraph(
|
||||
ScriptableRenderContext context,
|
||||
RenderingData renderingData);
|
||||
|
||||
protected bool RecordScene(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return context != null &&
|
||||
InternalCalls
|
||||
.Rendering_ScriptableRenderContext_RecordScene(
|
||||
context.nativeHandle);
|
||||
}
|
||||
|
||||
protected bool RecordOpaqueScenePhase(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordScenePhaseInternal(
|
||||
context,
|
||||
RecordedScenePhase.Opaque);
|
||||
}
|
||||
|
||||
protected bool RecordSkyboxScenePhase(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordScenePhaseInternal(
|
||||
context,
|
||||
RecordedScenePhase.Skybox);
|
||||
}
|
||||
|
||||
protected bool RecordTransparentScenePhase(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordScenePhaseInternal(
|
||||
context,
|
||||
RecordedScenePhase.Transparent);
|
||||
}
|
||||
|
||||
protected bool RecordBeforeOpaqueInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.BeforeOpaque);
|
||||
}
|
||||
|
||||
protected bool RecordAfterOpaqueInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.AfterOpaque);
|
||||
}
|
||||
|
||||
protected bool RecordBeforeSkyboxInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.BeforeSkybox);
|
||||
}
|
||||
|
||||
protected bool RecordAfterSkyboxInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.AfterSkybox);
|
||||
}
|
||||
|
||||
protected bool RecordBeforeTransparentInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.BeforeTransparent);
|
||||
}
|
||||
|
||||
protected bool RecordAfterTransparentInjection(
|
||||
ScriptableRenderContext context)
|
||||
{
|
||||
return RecordSceneInjectionPointInternal(
|
||||
context,
|
||||
RecordedSceneInjectionPoint.AfterTransparent);
|
||||
}
|
||||
|
||||
protected bool RecordColorScaleFullscreenPass(
|
||||
ScriptableRenderContext context,
|
||||
Vector4 colorScale)
|
||||
{
|
||||
RenderGraphTextureHandle sourceColor;
|
||||
RenderGraphTextureHandle outputColor;
|
||||
return TryResolveDefaultFullscreenTargets(
|
||||
context,
|
||||
out sourceColor,
|
||||
out outputColor) &&
|
||||
RecordColorScaleFullscreenPass(
|
||||
context,
|
||||
sourceColor,
|
||||
outputColor,
|
||||
colorScale);
|
||||
}
|
||||
|
||||
protected bool RecordColorScaleFullscreenPass(
|
||||
ScriptableRenderContext context,
|
||||
RenderGraphTextureHandle sourceColor,
|
||||
RenderGraphTextureHandle outputColor,
|
||||
Vector4 colorScale,
|
||||
string passName = null)
|
||||
{
|
||||
if (context == null ||
|
||||
!outputColor.isValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderGraphRasterPassBuilder passBuilder =
|
||||
context.AddRasterPass(
|
||||
ResolveFullscreenPassName(
|
||||
passName,
|
||||
kColorScaleFullscreenPassName));
|
||||
if (sourceColor.isValid)
|
||||
{
|
||||
passBuilder.UseColorSource(sourceColor);
|
||||
}
|
||||
|
||||
return passBuilder
|
||||
.SetColorAttachment(outputColor)
|
||||
.SetColorScaleFullscreenExecution(colorScale)
|
||||
.Commit();
|
||||
}
|
||||
|
||||
protected bool RecordShaderVectorFullscreenPass(
|
||||
ScriptableRenderContext context,
|
||||
string shaderPath,
|
||||
Vector4 vectorPayload,
|
||||
string passName = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shaderPath))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Fullscreen shader path cannot be null or empty.",
|
||||
nameof(shaderPath));
|
||||
}
|
||||
|
||||
RenderGraphTextureHandle sourceColor;
|
||||
RenderGraphTextureHandle outputColor;
|
||||
return TryResolveDefaultFullscreenTargets(
|
||||
context,
|
||||
out sourceColor,
|
||||
out outputColor) &&
|
||||
RecordShaderVectorFullscreenPass(
|
||||
context,
|
||||
sourceColor,
|
||||
outputColor,
|
||||
shaderPath,
|
||||
vectorPayload,
|
||||
passName: passName);
|
||||
}
|
||||
|
||||
protected bool RecordShaderVectorFullscreenPass(
|
||||
ScriptableRenderContext context,
|
||||
RenderGraphTextureHandle sourceColor,
|
||||
RenderGraphTextureHandle outputColor,
|
||||
string shaderPath,
|
||||
Vector4 vectorPayload,
|
||||
string shaderPassName = null,
|
||||
string passName = null)
|
||||
{
|
||||
if (string.IsNullOrEmpty(shaderPath))
|
||||
{
|
||||
throw new ArgumentException(
|
||||
"Fullscreen shader path cannot be null or empty.",
|
||||
nameof(shaderPath));
|
||||
}
|
||||
|
||||
if (context == null ||
|
||||
!outputColor.isValid)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
RenderGraphRasterPassBuilder passBuilder =
|
||||
context.AddRasterPass(
|
||||
ResolveFullscreenPassName(
|
||||
passName,
|
||||
kShaderVectorFullscreenPassName));
|
||||
if (sourceColor.isValid)
|
||||
{
|
||||
passBuilder.UseColorSource(sourceColor);
|
||||
}
|
||||
|
||||
return passBuilder
|
||||
.SetColorAttachment(outputColor)
|
||||
.SetShaderVectorFullscreenExecution(
|
||||
shaderPath,
|
||||
vectorPayload,
|
||||
shaderPassName)
|
||||
.Commit();
|
||||
}
|
||||
|
||||
internal static bool TryResolveStage(
|
||||
RenderPassEvent passEvent,
|
||||
out CameraFrameStage stage)
|
||||
{
|
||||
switch (passEvent)
|
||||
{
|
||||
case RenderPassEvent.BeforeRenderingOpaques:
|
||||
case RenderPassEvent.RenderOpaques:
|
||||
case RenderPassEvent.AfterRenderingOpaques:
|
||||
case RenderPassEvent.BeforeRenderingSkybox:
|
||||
case RenderPassEvent.RenderSkybox:
|
||||
case RenderPassEvent.AfterRenderingSkybox:
|
||||
case RenderPassEvent.BeforeRenderingTransparents:
|
||||
case RenderPassEvent.RenderTransparents:
|
||||
case RenderPassEvent.AfterRenderingTransparents:
|
||||
stage = CameraFrameStage.MainScene;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingPostProcessing:
|
||||
case RenderPassEvent.AfterRenderingPostProcessing:
|
||||
stage = CameraFrameStage.PostProcess;
|
||||
return true;
|
||||
case RenderPassEvent.BeforeRenderingFinalOutput:
|
||||
case RenderPassEvent.AfterRenderingFinalOutput:
|
||||
stage = CameraFrameStage.FinalOutput;
|
||||
return true;
|
||||
default:
|
||||
stage = CameraFrameStage.MainScene;
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
private bool RecordScenePhaseInternal(
|
||||
ScriptableRenderContext context,
|
||||
RecordedScenePhase scenePhase)
|
||||
{
|
||||
return context != null &&
|
||||
InternalCalls
|
||||
.Rendering_ScriptableRenderContext_RecordScenePhase(
|
||||
context.nativeHandle,
|
||||
(int)scenePhase);
|
||||
}
|
||||
|
||||
private bool RecordSceneInjectionPointInternal(
|
||||
ScriptableRenderContext context,
|
||||
RecordedSceneInjectionPoint injectionPoint)
|
||||
{
|
||||
return context != null &&
|
||||
InternalCalls
|
||||
.Rendering_ScriptableRenderContext_RecordSceneInjectionPoint(
|
||||
context.nativeHandle,
|
||||
(int)injectionPoint);
|
||||
}
|
||||
|
||||
private static bool TryResolveDefaultFullscreenTargets(
|
||||
ScriptableRenderContext context,
|
||||
out RenderGraphTextureHandle sourceColor,
|
||||
out RenderGraphTextureHandle outputColor)
|
||||
{
|
||||
sourceColor = new RenderGraphTextureHandle();
|
||||
outputColor = new RenderGraphTextureHandle();
|
||||
if (context == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
sourceColor = context.sourceColorTexture;
|
||||
outputColor = context.primaryColorTarget;
|
||||
return sourceColor.isValid &&
|
||||
outputColor.isValid;
|
||||
}
|
||||
|
||||
private static string ResolveFullscreenPassName(
|
||||
string passName,
|
||||
string defaultPassName)
|
||||
{
|
||||
return string.IsNullOrEmpty(passName)
|
||||
? defaultPassName
|
||||
: passName;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user