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

352 lines
10 KiB
C#

using System.Collections.Generic;
using XCEngine;
using XCEngine.Rendering;
namespace XCEngine.Rendering.Universal
{
public abstract class ScriptableRenderer
{
private readonly List<ScriptableRendererFeature> m_features =
new List<ScriptableRendererFeature>();
private readonly List<ScriptableRenderPass> m_activePassQueue =
new List<ScriptableRenderPass>();
private bool m_disposed;
protected ScriptableRenderer()
{
}
internal void ReleaseRuntimeResourcesInstance()
{
if (m_disposed)
{
return;
}
ReleaseRuntimeResources();
for (int i = 0; i < m_features.Count; ++i)
{
ScriptableRendererFeature feature = m_features[i];
if (feature != null)
{
feature.ReleaseRuntimeResourcesInstance();
}
}
m_features.Clear();
m_activePassQueue.Clear();
m_disposed = true;
}
public void EnqueuePass(
ScriptableRenderPass renderPass)
{
if (renderPass == null)
{
return;
}
int insertIndex = m_activePassQueue.Count;
while (insertIndex > 0 &&
m_activePassQueue[insertIndex - 1].renderPassEvent >
renderPass.renderPassEvent)
{
insertIndex--;
}
m_activePassQueue.Insert(
insertIndex,
renderPass);
}
protected void AddFeature(
ScriptableRendererFeature feature)
{
if (feature == null)
{
return;
}
m_features.Add(feature);
feature.CreateInstance();
}
protected virtual void AddRenderPasses(
RenderingData renderingData)
{
}
internal void AddFeatureInstance(
ScriptableRendererFeature feature)
{
AddFeature(feature);
}
internal bool SupportsRendererRecordingInstance(
RendererRecordingContext context)
{
return SupportsRendererRecording(context);
}
internal void ConfigureCameraFramePlanInstance(
ScriptableRenderPipelinePlanningContext context)
{
ConfigureCameraFramePlan(context);
}
internal void FinalizeCameraFramePlanInstance(
ScriptableRenderPipelinePlanningContext context)
{
FinalizeCameraFramePlan(context);
}
internal bool RecordRendererInstance(
RendererRecordingContext context)
{
return RecordRenderer(context);
}
protected virtual bool SupportsRendererRecording(
RendererRecordingContext context)
{
if (context == null)
{
return false;
}
RenderingData renderingData =
context.renderingData;
BuildPassQueue(renderingData);
for (int i = 0; i < m_activePassQueue.Count; ++i)
{
ScriptableRenderPass renderPass = m_activePassQueue[i];
if (renderPass != null &&
renderPass.SupportsStage(context.stage))
{
return true;
}
}
return false;
}
protected virtual bool RecordRenderer(
RendererRecordingContext context)
{
if (context == null ||
context.renderContext == null)
{
return false;
}
RenderingData renderingData =
context.renderingData;
BuildPassQueue(renderingData);
bool recordedAnyPass = false;
for (int i = 0; i < m_activePassQueue.Count; ++i)
{
ScriptableRenderPass renderPass = m_activePassQueue[i];
if (renderPass == null ||
!renderPass.SupportsStage(renderingData.stage))
{
continue;
}
if (!renderPass.Record(
context.renderContext,
renderingData))
{
return false;
}
recordedAnyPass = true;
}
return recordedAnyPass;
}
protected internal virtual bool SupportsStageRenderGraph(
CameraFrameStage stage)
{
return SupportsRendererRecording(
new RendererRecordingContext(stage));
}
protected internal virtual bool RecordStageRenderGraph(
ScriptableRenderContext context)
{
return context != null &&
RecordRenderer(
new RendererRecordingContext(context));
}
protected virtual void ConfigureCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
}
protected virtual void FinalizeCameraFramePlan(
ScriptableRenderPipelinePlanningContext context)
{
if (context == null)
{
return;
}
ApplyInferredFullscreenStageRequests(
context);
}
private void BuildPassQueue(
RenderingData renderingData)
{
m_activePassQueue.Clear();
for (int i = 0; i < m_features.Count; ++i)
{
ScriptableRendererFeature feature = m_features[i];
if (feature == null || !feature.isActive)
{
continue;
}
feature.AddRenderPasses(
this,
renderingData);
}
AddRenderPasses(renderingData);
}
protected virtual void ReleaseRuntimeResources()
{
}
protected virtual RenderingData CreatePlanningRenderingData(
ScriptableRenderPipelinePlanningContext context)
{
return context != null
? new RenderingData(
CameraFrameStage.MainScene,
context.rendererIndex)
: null;
}
private void ApplyInferredFullscreenStageRequests(
ScriptableRenderPipelinePlanningContext context)
{
RenderingData planningData =
CreatePlanningRenderingData(context);
if (planningData == null)
{
return;
}
BuildPassQueue(planningData);
ApplyInferredStandaloneStageRequests(
context);
bool hasPostProcessPass =
HasQueuedPassForStage(
CameraFrameStage.PostProcess);
bool hasFinalOutputPass =
HasQueuedPassForStage(
CameraFrameStage.FinalOutput);
bool needsFinalOutputDependency =
context.HasFinalColorProcessing() ||
context.IsStageRequested(
CameraFrameStage.FinalOutput) ||
hasFinalOutputPass;
if (hasPostProcessPass)
{
EnsureInferredPostProcessStage(
context,
needsFinalOutputDependency);
}
if (hasFinalOutputPass &&
!context.IsStageRequested(
CameraFrameStage.FinalOutput))
{
context.RequestFullscreenStage(
CameraFrameStage.FinalOutput,
context.IsStageRequested(
CameraFrameStage.PostProcess)
? CameraFrameColorSource.PostProcessColor
: CameraFrameColorSource.MainSceneColor);
}
}
private void ApplyInferredStandaloneStageRequests(
ScriptableRenderPipelinePlanningContext context)
{
if (HasQueuedPassForStage(
CameraFrameStage.ShadowCaster))
{
context.RequestShadowCasterStage();
}
if (HasQueuedPassForStage(
CameraFrameStage.DepthOnly))
{
context.RequestDepthOnlyStage();
}
}
private bool HasQueuedPassForStage(
CameraFrameStage stage)
{
for (int i = 0; i < m_activePassQueue.Count; ++i)
{
ScriptableRenderPass renderPass =
m_activePassQueue[i];
if (renderPass != null &&
renderPass.SupportsStage(stage))
{
return true;
}
}
return false;
}
private static void EnsureInferredPostProcessStage(
ScriptableRenderPipelinePlanningContext context,
bool needsGraphManagedOutputColor)
{
if (!context.IsStageRequested(
CameraFrameStage.PostProcess))
{
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
CameraFrameColorSource.MainSceneColor,
needsGraphManagedOutputColor);
return;
}
CameraFrameColorSource source =
context.GetStageColorSource(
CameraFrameStage.PostProcess);
if (!needsGraphManagedOutputColor ||
source ==
CameraFrameColorSource.ExplicitSurface ||
context.UsesGraphManagedOutputColor(
CameraFrameStage.PostProcess))
{
return;
}
context.ClearFullscreenStage(
CameraFrameStage.PostProcess);
context.RequestFullscreenStage(
CameraFrameStage.PostProcess,
source,
true);
}
}
}