Files
XCEngine/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs

434 lines
14 KiB
C#

using System;
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public abstract class ScriptableRenderPass
{
private const string kColorScaleFullscreenPassName =
"Universal.ColorScaleFullscreen";
private const string kFinalColorFullscreenPassName =
"Universal.FinalColorFullscreen";
private const string kShaderVectorFullscreenPassName =
"Universal.ShaderVectorFullscreen";
private readonly CommandBuffer m_lifecycleCommandBuffer =
new CommandBuffer("ScriptableRenderPass");
private ScriptableRenderPassInput m_input =
ScriptableRenderPassInput.None;
protected ScriptableRenderPass()
{
}
public RenderPassEvent renderPassEvent { get; set; } =
RenderPassEvent.BeforeRenderingOpaques;
public ScriptableRenderPassInput input
{
get
{
return m_input;
}
}
public bool requiresIntermediateTexture
{
get
{
return m_input != ScriptableRenderPassInput.None;
}
}
protected ProfilingSampler profilingSampler { get; set; } =
new ProfilingSampler("Unnamed_ScriptableRenderPass");
public void ConfigureInput(
ScriptableRenderPassInput passInput)
{
m_input = passInput;
}
public virtual bool SupportsStage(
CameraFrameStage stage)
{
RendererBlock block;
return TryResolveRendererBlock(
renderPassEvent,
out block) &&
RendererBlockUtility.GetStage(block) == stage;
}
internal bool SupportsRendererBlock(
RendererBlock block)
{
RendererBlock resolvedBlock;
return TryResolveRendererBlock(
renderPassEvent,
out resolvedBlock) &&
resolvedBlock == block;
}
internal bool Record(
ScriptableRenderContext context,
RenderingData renderingData)
{
RenderingData passRenderingData =
renderingData;
OnCameraSetup(
m_lifecycleCommandBuffer,
ref passRenderingData);
try
{
return RecordRenderGraph(
context,
passRenderingData);
}
finally
{
OnCameraCleanup(
m_lifecycleCommandBuffer);
}
}
public virtual void Execute(
ScriptableRenderContext context,
ref RenderingData renderingData)
{
}
public virtual void OnCameraSetup(
CommandBuffer cmd,
ref RenderingData renderingData)
{
}
public virtual void OnCameraCleanup(
CommandBuffer cmd)
{
}
public virtual void OnFinishCameraStackRendering(
CommandBuffer cmd)
{
}
protected virtual bool RecordRenderGraph(
ScriptableRenderContext context,
RenderingData renderingData)
{
if (context == null ||
renderingData == null)
{
return false;
}
Execute(
context,
ref renderingData);
return true;
}
public static bool operator >(
ScriptableRenderPass lhs,
ScriptableRenderPass rhs)
{
return CompareRenderPassEvents(
lhs,
rhs) > 0;
}
public static bool operator <(
ScriptableRenderPass lhs,
ScriptableRenderPass rhs)
{
return CompareRenderPassEvents(
lhs,
rhs) < 0;
}
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();
}
protected bool RecordFinalColorFullscreenPass(
ScriptableRenderContext context,
FinalColorSettings settings,
string passName = null)
{
RenderGraphTextureHandle sourceColor;
RenderGraphTextureHandle outputColor;
return TryResolveDefaultFullscreenTargets(
context,
out sourceColor,
out outputColor) &&
RecordFinalColorFullscreenPass(
context,
sourceColor,
outputColor,
settings,
passName);
}
protected bool RecordFinalColorFullscreenPass(
ScriptableRenderContext context,
RenderGraphTextureHandle sourceColor,
RenderGraphTextureHandle outputColor,
FinalColorSettings settings,
string passName = null)
{
if (context == null ||
!outputColor.isValid)
{
return false;
}
RenderGraphRasterPassBuilder passBuilder =
context.AddRasterPass(
ResolveFullscreenPassName(
passName,
kFinalColorFullscreenPassName));
if (sourceColor.isValid)
{
passBuilder.UseColorSource(sourceColor);
}
return passBuilder
.SetColorAttachment(outputColor)
.SetFinalColorFullscreenExecution(settings)
.Commit();
}
internal static bool TryResolveStage(
RenderPassEvent passEvent,
out CameraFrameStage stage)
{
RendererBlock block;
if (TryResolveRendererBlock(
passEvent,
out block))
{
stage =
RendererBlockUtility.GetStage(block);
return true;
}
stage = CameraFrameStage.MainScene;
return false;
}
internal static bool TryResolveRendererBlock(
RenderPassEvent passEvent,
out RendererBlock block)
{
switch (passEvent)
{
case RenderPassEvent.BeforeRenderingShadows:
case RenderPassEvent.AfterRenderingShadows:
block = RendererBlock.ShadowCaster;
return true;
case RenderPassEvent.BeforeRenderingPrePasses:
case RenderPassEvent.AfterRenderingPrePasses:
block = RendererBlock.DepthPrepass;
return true;
case RenderPassEvent.BeforeRenderingGbuffer:
case RenderPassEvent.AfterRenderingGbuffer:
case RenderPassEvent.BeforeRenderingDeferredLights:
case RenderPassEvent.AfterRenderingDeferredLights:
case RenderPassEvent.BeforeRenderingOpaques:
case RenderPassEvent.RenderOpaques:
case RenderPassEvent.AfterRenderingOpaques:
block = RendererBlock.MainOpaque;
return true;
case RenderPassEvent.BeforeRenderingSkybox:
case RenderPassEvent.RenderSkybox:
case RenderPassEvent.AfterRenderingSkybox:
block = RendererBlock.MainSkybox;
return true;
case RenderPassEvent.BeforeRenderingTransparents:
case RenderPassEvent.RenderTransparents:
case RenderPassEvent.AfterRenderingTransparents:
block = RendererBlock.MainTransparent;
return true;
case RenderPassEvent.BeforeRenderingPostProcessing:
case RenderPassEvent.AfterRenderingPostProcessing:
block = RendererBlock.PostProcess;
return true;
case RenderPassEvent.BeforeRenderingFinalOutput:
case RenderPassEvent.AfterRendering:
case RenderPassEvent.AfterRenderingFinalOutput:
block = RendererBlock.FinalOutput;
return true;
default:
block = RendererBlock.MainOpaque;
return false;
}
}
private static int CompareRenderPassEvents(
ScriptableRenderPass lhs,
ScriptableRenderPass rhs)
{
if (ReferenceEquals(
lhs,
rhs))
{
return 0;
}
if (lhs == null)
{
return -1;
}
if (rhs == null)
{
return 1;
}
return lhs.renderPassEvent.CompareTo(
rhs.renderPassEvent);
}
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;
}
}
}