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

389 lines
12 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 readonly RendererBlocks m_rendererBlocks =
new RendererBlocks();
private bool m_isBuildingPassQueue;
private CameraFrameStage m_passQueueStage =
CameraFrameStage.MainScene;
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_rendererBlocks.Clear();
m_disposed = true;
}
public void EnqueuePass(
ScriptableRenderPass renderPass)
{
if (renderPass == null)
{
return;
}
if (m_isBuildingPassQueue &&
!renderPass.SupportsStage(m_passQueueStage))
{
return;
}
InsertActivePass(
renderPass);
}
private void InsertActivePass(
ScriptableRenderPass renderPass)
{
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 void ConfigureRenderSceneSetupInstance(
RenderSceneSetupContext context)
{
ConfigureRenderSceneSetup(context);
}
internal void ConfigureDirectionalShadowExecutionStateInstance(
DirectionalShadowExecutionContext context)
{
ConfigureDirectionalShadowExecutionState(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);
return SupportsRendererStage(context);
}
protected virtual bool RecordRenderer(
RendererRecordingContext context)
{
if (context == null ||
context.renderContext == null)
{
return false;
}
RenderingData renderingData =
context.renderingData;
BuildPassQueue(renderingData);
return RecordRendererStage(context);
}
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)
{
}
protected virtual void ConfigureRenderSceneSetup(
RenderSceneSetupContext context)
{
}
protected virtual void ConfigureDirectionalShadowExecutionState(
DirectionalShadowExecutionContext context)
{
}
private bool HasRendererBlock(
RendererBlock block)
{
return m_rendererBlocks.HasPasses(block);
}
protected virtual bool SupportsRendererStage(
RendererRecordingContext context)
{
if (context == null)
{
return false;
}
switch (context.stage)
{
case CameraFrameStage.ShadowCaster:
return HasRendererBlock(
RendererBlock.ShadowCaster);
case CameraFrameStage.DepthOnly:
return HasRendererBlock(
RendererBlock.DepthPrepass);
case CameraFrameStage.MainScene:
return HasRendererBlock(
RendererBlock.MainOpaque) ||
HasRendererBlock(
RendererBlock.MainSkybox) ||
HasRendererBlock(
RendererBlock.MainTransparent);
case CameraFrameStage.PostProcess:
return HasRendererBlock(
RendererBlock.PostProcess);
case CameraFrameStage.FinalOutput:
return HasRendererBlock(
RendererBlock.FinalOutput);
default:
return false;
}
}
protected virtual bool RecordRendererStage(
RendererRecordingContext context)
{
if (context == null ||
context.renderContext == null)
{
return false;
}
bool recordedAnyPass = false;
switch (context.stage)
{
case CameraFrameStage.ShadowCaster:
return RecordRendererBlock(
RendererBlock.ShadowCaster,
context,
ref recordedAnyPass) &&
recordedAnyPass;
case CameraFrameStage.DepthOnly:
return RecordRendererBlock(
RendererBlock.DepthPrepass,
context,
ref recordedAnyPass) &&
recordedAnyPass;
case CameraFrameStage.MainScene:
return RecordRendererBlock(
RendererBlock.MainOpaque,
context,
ref recordedAnyPass) &&
RecordRendererBlock(
RendererBlock.MainSkybox,
context,
ref recordedAnyPass) &&
RecordRendererBlock(
RendererBlock.MainTransparent,
context,
ref recordedAnyPass) &&
recordedAnyPass;
case CameraFrameStage.PostProcess:
return RecordRendererBlock(
RendererBlock.PostProcess,
context,
ref recordedAnyPass) &&
recordedAnyPass;
case CameraFrameStage.FinalOutput:
return RecordRendererBlock(
RendererBlock.FinalOutput,
context,
ref recordedAnyPass) &&
recordedAnyPass;
default:
return false;
}
}
private bool RecordRendererBlock(
RendererBlock block,
RendererRecordingContext context,
ref bool recordedAnyPass)
{
if (context == null ||
context.renderContext == null)
{
return false;
}
int firstPassIndex;
int lastPassIndex;
if (!m_rendererBlocks.TryGetPassRange(
block,
out firstPassIndex,
out lastPassIndex))
{
return true;
}
for (int i = firstPassIndex;
i <= lastPassIndex;
++i)
{
ScriptableRenderPass renderPass =
m_activePassQueue[i];
if (renderPass == null ||
!renderPass.SupportsRendererBlock(block))
{
continue;
}
if (!renderPass.Record(
context.renderContext,
context.renderingData))
{
return false;
}
recordedAnyPass = true;
}
return true;
}
private void BuildPassQueue(
RenderingData renderingData)
{
m_activePassQueue.Clear();
m_rendererBlocks.Clear();
m_isBuildingPassQueue = true;
m_passQueueStage =
renderingData != null
? renderingData.stage
: CameraFrameStage.MainScene;
try
{
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);
m_rendererBlocks.Build(m_activePassQueue);
}
finally
{
m_isBuildingPassQueue = false;
m_passQueueStage =
CameraFrameStage.MainScene;
}
}
protected virtual void ReleaseRuntimeResources()
{
}
}
}