using System; using System.Runtime.CompilerServices; using XCEngine; using XCEngine.Rendering; namespace XCEngine.Rendering.Universal { public abstract class ScriptableRendererData : ScriptableObject { public ScriptableRendererFeature[] rendererFeatures; private readonly ScriptableRendererFeatureCollection m_featureCollection; private ScriptableRenderer m_rendererInstance; private bool m_rendererInvalidated; private int m_runtimeStateVersion = 1; private int m_rendererFeatureCollectionHash; private bool m_rendererFeatureCollectionHashResolved; protected ScriptableRendererData() { rendererFeatures = Array.Empty(); m_featureCollection = new ScriptableRendererFeatureCollection(this); } internal ScriptableRenderer CreateRendererInstance() { return GetRendererInstance(); } internal ScriptableRenderer GetRendererInstance() { if (m_rendererInstance == null) { m_rendererInstance = CreateRenderer(); if (m_rendererInstance != null) { SetupRendererInstance(m_rendererInstance); m_rendererInvalidated = false; } } return m_rendererInstance; } internal void SetupRendererInstance( ScriptableRenderer renderer) { if (renderer == null) { return; } SetupRenderer(renderer); } internal void SetDirtyInstance() { SetDirty(); } internal void InvalidateRendererFeaturesInstance() { m_featureCollection.Invalidate( ref rendererFeatures, ref m_rendererFeatureCollectionHash, ref m_rendererFeatureCollectionHashResolved); SetDirty(); } internal int GetRuntimeStateVersionInstance() { SynchronizeRendererFeatureCollectionState(); return m_runtimeStateVersion; } internal void ReleaseRuntimeResourcesInstance() { ReleaseRendererSetupCache(); ReleaseRuntimeResources(); m_rendererInvalidated = false; } internal void ConfigureCameraRenderRequestInstance( CameraRenderRequestContext context) { ConfigureCameraRenderRequest(context); m_featureCollection.ConfigureCameraRenderRequest( ref rendererFeatures, context); } internal void ConfigureCameraFramePlanInstance( ScriptableRenderPipelinePlanningContext context) { ConfigureCameraFramePlan(context); ScriptableRenderer renderer = GetRendererInstance(); if (renderer != null) { renderer.ConfigureCameraFramePlanInstance( context); } m_featureCollection.ConfigureCameraFramePlan( ref rendererFeatures, context); if (renderer != null) { renderer.FinalizeCameraFramePlanInstance( context); } } internal bool ConfigureRenderSceneSetupInstance( RenderSceneSetupContext context) { ConfigureRenderSceneSetup(context); ScriptableRenderer renderer = GetRendererInstance(); if (renderer != null) { renderer.ConfigureRenderSceneSetupInstance( context); } m_featureCollection.ConfigureRenderSceneSetup( ref rendererFeatures, context); return context != null && context.isConfigured; } internal bool ConfigureDirectionalShadowExecutionStateInstance( DirectionalShadowExecutionContext context) { ConfigureDirectionalShadowExecutionState( context); ScriptableRenderer renderer = GetRendererInstance(); if (renderer != null) { renderer .ConfigureDirectionalShadowExecutionStateInstance( context); } m_featureCollection .ConfigureDirectionalShadowExecutionState( ref rendererFeatures, context); return context != null && context.isConfigured; } protected virtual ScriptableRenderer CreateRenderer() { return null; } protected virtual void SetupRenderer( ScriptableRenderer renderer) { AddRendererFeatures( renderer, GetRendererFeatures()); } protected virtual void ConfigureCameraRenderRequest( CameraRenderRequestContext context) { } protected virtual void ConfigureCameraFramePlan( ScriptableRenderPipelinePlanningContext context) { } protected virtual void ConfigureRenderSceneSetup( RenderSceneSetupContext context) { } protected virtual void ConfigureDirectionalShadowExecutionState( DirectionalShadowExecutionContext context) { } protected virtual void ReleaseRuntimeResources() { } protected virtual ScriptableRendererFeature[] CreateDefaultRendererFeatures() { return Array.Empty(); } protected bool isInvalidated { get { return m_rendererInvalidated; } } protected bool HasDirectionalShadow( CameraRenderRequestContext context) { return context != null && InternalCalls .Rendering_CameraRenderRequestContext_GetHasDirectionalShadow( context.nativeHandle); } protected void ClearDirectionalShadow( CameraRenderRequestContext context) { if (context == null) { return; } InternalCalls .Rendering_CameraRenderRequestContext_ClearDirectionalShadow( context.nativeHandle); } protected void SetDirty() { ReleaseRendererSetupCache(); m_rendererInvalidated = true; unchecked { ++m_runtimeStateVersion; } if (m_runtimeStateVersion <= 0) { m_runtimeStateVersion = 1; } } protected void AddRendererFeature( ScriptableRenderer renderer, ScriptableRendererFeature rendererFeature) { if (renderer == null || rendererFeature == null) { return; } renderer.AddFeatureInstance(rendererFeature); } protected void AddRendererFeatures( ScriptableRenderer renderer, ScriptableRendererFeature[] rendererFeatures) { if (renderer == null || rendererFeatures == null) { return; } for (int i = 0; i < rendererFeatures.Length; ++i) { AddRendererFeature( renderer, rendererFeatures[i]); } } protected void ResetRendererFeaturesToDefault() { m_featureCollection.Reset( ref rendererFeatures, CreateDefaultRendererFeatures() ?? Array.Empty()); } private ScriptableRendererFeature[] GetRendererFeatures() { return m_featureCollection.GetFeatures( ref rendererFeatures); } private void SynchronizeRendererFeatureCollectionState() { m_featureCollection.Synchronize( ref rendererFeatures, ref m_rendererFeatureCollectionHash, ref m_rendererFeatureCollectionHashResolved, SetDirty); } private void ReleaseRendererSetupCache() { if (m_rendererInstance != null) { m_rendererInstance.ReleaseRuntimeResourcesInstance(); m_rendererInstance = null; m_featureCollection.ResetResolvedCache(); return; } m_featureCollection.ReleaseRuntimeResources(); } } }