using System; using System.Runtime.CompilerServices; using XCEngine; using XCEngine.Rendering; namespace XCEngine.Rendering.Universal { internal sealed class ScriptableRendererFeatureCollection { private readonly ScriptableRendererData m_owner; private ScriptableRendererFeature[] m_features; public ScriptableRendererFeatureCollection( ScriptableRendererData owner) { m_owner = owner; m_features = Array.Empty(); } public ScriptableRendererFeature[] GetFeatures( ref ScriptableRendererFeature[] configuredFeatures) { if (m_features == null) { ScriptableRendererFeature[] resolvedFeatures = configuredFeatures ?? Array.Empty(); configuredFeatures = resolvedFeatures; m_features = resolvedFeatures; } BindOwners(m_features); return m_features; } public void Reset( ref ScriptableRendererFeature[] configuredFeatures, ScriptableRendererFeature[] features) { configuredFeatures = features ?? Array.Empty(); m_features = configuredFeatures; BindOwners(m_features); } public void Invalidate( ref ScriptableRendererFeature[] configuredFeatures, ref int collectionHash, ref bool collectionHashResolved) { ScriptableRendererFeature[] features = ResolveConfiguredFeatures( ref configuredFeatures); collectionHash = ComputeCollectionHash(features); collectionHashResolved = true; } public void Synchronize( ref ScriptableRendererFeature[] configuredFeatures, ref int collectionHash, ref bool collectionHashResolved, Action onChanged) { ScriptableRendererFeature[] features = ResolveConfiguredFeatures( ref configuredFeatures); int resolvedHash = ComputeCollectionHash(features); if (!collectionHashResolved) { collectionHash = resolvedHash; collectionHashResolved = true; return; } if (resolvedHash == collectionHash) { return; } collectionHash = resolvedHash; onChanged?.Invoke(); } public void ConfigureCameraRenderRequest( ref ScriptableRendererFeature[] configuredFeatures, CameraRenderRequestContext context) { ScriptableRendererFeature[] features = GetFeatures(ref configuredFeatures); for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature == null || !feature.isActive) { continue; } feature.ConfigureCameraRenderRequest( context); } } public void ConfigureCameraFramePlan( ref ScriptableRendererFeature[] configuredFeatures, ScriptableRenderPipelinePlanningContext context) { ScriptableRendererFeature[] features = GetFeatures(ref configuredFeatures); for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature == null || !feature.isActive) { continue; } feature.ConfigureCameraFramePlan( context); } } public void ConfigureRenderSceneSetup( ref ScriptableRendererFeature[] configuredFeatures, RenderSceneSetupContext context) { ScriptableRendererFeature[] features = GetFeatures(ref configuredFeatures); for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature == null || !feature.isActive) { continue; } feature.ConfigureRenderSceneSetup( context); } } public void ConfigureDirectionalShadowExecutionState( ref ScriptableRendererFeature[] configuredFeatures, DirectionalShadowExecutionContext context) { ScriptableRendererFeature[] features = GetFeatures(ref configuredFeatures); for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature == null || !feature.isActive) { continue; } feature .ConfigureDirectionalShadowExecutionState( context); } } public void ReleaseRuntimeResources() { if (m_features == null) { return; } for (int i = 0; i < m_features.Length; ++i) { ScriptableRendererFeature feature = m_features[i]; if (feature != null) { feature.ReleaseRuntimeResourcesInstance(); } } m_features = null; } public void ResetResolvedCache() { m_features = null; } private ScriptableRendererFeature[] ResolveConfiguredFeatures( ref ScriptableRendererFeature[] configuredFeatures) { ScriptableRendererFeature[] features = configuredFeatures ?? Array.Empty(); configuredFeatures = features; m_features = features; BindOwners(features); return features; } private void BindOwners( ScriptableRendererFeature[] features) { if (features == null) { return; } for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature != null) { feature.BindOwnerInstance(m_owner); } } } private static int ComputeCollectionHash( ScriptableRendererFeature[] features) { unchecked { int hash = 17; if (features == null) { return hash; } hash = (hash * 31) + features.Length; for (int i = 0; i < features.Length; ++i) { ScriptableRendererFeature feature = features[i]; if (feature == null) { hash = (hash * 31) + 1; continue; } hash = (hash * 31) + RuntimeHelpers.GetHashCode(feature); hash = (hash * 31) + feature.GetRuntimeStateVersionInstance(); } return hash; } } } }