using System; using XCEngine; using XCEngine.Rendering; namespace XCEngine.Rendering.Universal { public abstract class RendererBackedRenderPipelineAsset : ScriptableRenderPipelineAsset { public ScriptableRendererData[] rendererDataList = Array.Empty(); public int defaultRendererIndex = 0; private int m_rendererDataRuntimeStateHash; private bool m_rendererDataRuntimeStateHashResolved; protected RendererBackedRenderPipelineAsset() { } protected override ScriptableRenderPipeline CreatePipeline() { return CreateRendererBackedPipeline(); } protected override void ConfigureCameraRenderRequest( CameraRenderRequestContext context) { ConfigureRendererCameraRequest( new RendererCameraRequestContext(context)); ScriptableRendererData resolvedRendererData = ResolveSelectedRendererData(); if (resolvedRendererData != null) { resolvedRendererData .ConfigureCameraRenderRequestInstance( context); } } protected override void ConfigureCameraFramePlan( ScriptableRenderPipelinePlanningContext context) { ScriptableRendererData resolvedRendererData = ResolveSelectedRendererData(); if (resolvedRendererData != null) { resolvedRendererData .ConfigureCameraFramePlanInstance( context); } } protected override string GetPipelineRendererAssetKey() { ScriptableRendererData resolvedRendererData = ResolveSelectedRendererData(); return resolvedRendererData != null ? resolvedRendererData .GetPipelineRendererAssetKeyInstance() : string.Empty; } protected override void ReleaseRuntimeResources() { ReleaseRendererDataRuntimeResources(); } protected override void SynchronizeRuntimeResourceVersion() { int runtimeStateHash = ComputeRendererDataRuntimeStateHash(); if (!m_rendererDataRuntimeStateHashResolved) { m_rendererDataRuntimeStateHash = runtimeStateHash; m_rendererDataRuntimeStateHashResolved = true; return; } if (runtimeStateHash == m_rendererDataRuntimeStateHash) { return; } m_rendererDataRuntimeStateHash = runtimeStateHash; SetDirty(); } protected virtual ScriptableRenderPipeline CreateRendererBackedPipeline() { return new RendererBackedRenderPipeline(this); } protected virtual void ConfigureRendererCameraRequest( RendererCameraRequestContext context) { } protected virtual ScriptableRendererData CreateDefaultRendererData() { return null; } internal ScriptableRendererData GetDefaultRendererData() { return ResolveSelectedRendererData(); } internal ScriptableRenderer GetDefaultRenderer() { return ResolveSelectedRenderer(); } internal ScriptableRendererData ResolveSelectedRendererData() { return ResolveRendererDataByResolvedIndex( ResolveSelectedRendererIndex()); } internal ScriptableRenderer ResolveSelectedRenderer() { ScriptableRendererData rendererData = ResolveSelectedRendererData(); return rendererData != null ? rendererData.GetRendererInstance() : null; } internal ScriptableRendererData GetRendererData( int rendererIndex) { return ResolveRendererDataByResolvedIndex( ResolveRendererIndex(rendererIndex)); } internal ScriptableRenderer GetRenderer( int rendererIndex) { ScriptableRendererData rendererData = GetRendererData(rendererIndex); return rendererData != null ? rendererData.GetRendererInstance() : null; } protected internal void ReleaseRendererDataRuntimeResources() { EnsureRendererDataList(); for (int i = 0; i < rendererDataList.Length; ++i) { ScriptableRendererData rendererData = rendererDataList[i]; if (rendererData == null || WasRendererDataReleasedEarlier(i)) { continue; } rendererData.ReleaseRuntimeResourcesInstance(); } } private void EnsureRendererDataList() { if (rendererDataList != null && rendererDataList.Length > 0) { return; } ScriptableRendererData defaultRendererData = CreateDefaultRendererData(); rendererDataList = defaultRendererData != null ? new ScriptableRendererData[] { defaultRendererData } : Array.Empty(); defaultRendererIndex = 0; } private bool WasRendererDataReleasedEarlier( int rendererDataIndex) { ScriptableRendererData rendererData = rendererDataList[rendererDataIndex]; for (int i = 0; i < rendererDataIndex; ++i) { if (object.ReferenceEquals( rendererDataList[i], rendererData)) { return true; } } return false; } private int ComputeRendererDataRuntimeStateHash() { unchecked { int hash = 17; hash = (hash * 31) + ResolveSelectedRendererIndex(); if (rendererDataList == null) { return hash; } hash = (hash * 31) + rendererDataList.Length; for (int i = 0; i < rendererDataList.Length; ++i) { ScriptableRendererData rendererData = rendererDataList[i]; if (rendererData != null) { hash = (hash * 31) + rendererData .GetRuntimeStateVersionInstance(); } } return hash; } } private ScriptableRendererData ResolveRendererDataByResolvedIndex( int resolvedRendererIndex) { EnsureRendererDataList(); if (resolvedRendererIndex < 0) { return null; } if (rendererDataList[resolvedRendererIndex] == null) { rendererDataList[resolvedRendererIndex] = CreateDefaultRendererData(); } return rendererDataList[resolvedRendererIndex]; } private int ResolveSelectedRendererIndex() { return ResolveRendererIndex(defaultRendererIndex); } private int ResolveRendererIndex( int rendererIndex) { EnsureRendererDataList(); if (rendererDataList.Length == 0) { return -1; } if (rendererIndex < 0 || rendererIndex >= rendererDataList.Length) { return ResolveDefaultRendererIndex(); } return rendererIndex; } private int ResolveDefaultRendererIndex() { EnsureRendererDataList(); if (rendererDataList.Length == 0) { return -1; } if (defaultRendererIndex < 0 || defaultRendererIndex >= rendererDataList.Length) { defaultRendererIndex = 0; } return defaultRendererIndex; } } }