using System; using System.Reflection; using XCEngine; using XCEngine.Rendering; using XCEngine.Rendering.Universal; namespace ProjectScripts { internal static class ProjectProbeRuntimeVersionUtility { private static readonly MethodInfo s_getRuntimeResourceVersionMethod = typeof(ScriptableRenderPipelineAsset) .GetMethod( "GetRuntimeResourceVersionInstance", BindingFlags.Instance | BindingFlags.NonPublic); public static int GetRuntimeResourceVersion( ScriptableRenderPipelineAsset asset) { if (asset == null || s_getRuntimeResourceVersionMethod == null) { return 0; } object version = s_getRuntimeResourceVersionMethod.Invoke( asset, null); return version is int resolvedVersion ? resolvedVersion : 0; } } public sealed class ProjectPostProcessColorScalePass : ScriptableRenderPass { public ProjectPostProcessColorScalePass() { renderPassEvent = RenderPassEvent.BeforeRenderingPostProcessing; } protected override bool RecordRenderGraph( ScriptableRenderContext context, RenderingData renderingData) { return context != null && renderingData != null && renderingData.isPostProcessStage && RecordColorScaleFullscreenPass( context, new Vector4(1.15f, 0.95f, 1.05f, 1.0f)); } } public sealed class ProjectPostProcessColorScaleFeature : ScriptableRendererFeature { private ProjectPostProcessColorScalePass m_pass; public override void Create() { m_pass = new ProjectPostProcessColorScalePass(); } public override void ConfigureCameraFramePlan( ScriptableRenderPipelinePlanningContext context) { if (context == null || context.IsStageRequested( CameraFrameStage.PostProcess)) { return; } context.RequestFullscreenStage( CameraFrameStage.PostProcess, CameraFrameColorSource.MainSceneColor); } public override void AddRenderPasses( ScriptableRenderer renderer, RenderingData renderingData) { if (renderer == null || renderingData == null || !renderingData.isPostProcessStage) { return; } if (m_pass == null) { Create(); } renderer.EnqueuePass(m_pass); } } public sealed class ProjectUniversalFeaturePipelineAsset : UniversalRenderPipelineAsset { public ProjectUniversalFeaturePipelineAsset() { rendererDataList = new ScriptableRendererData[] { new UniversalRendererData { rendererFeatures = new ScriptableRendererFeature[] { new ProjectPostProcessColorScaleFeature() } } }; } } public sealed class ProjectRenderObjectsFeaturePipelineAsset : UniversalRenderPipelineAsset { public ProjectRenderObjectsFeaturePipelineAsset() { rendererDataList = new ScriptableRendererData[] { new UniversalRendererData { defaultScenePasses = Array.Empty(), rendererFeatures = new ScriptableRendererFeature[] { new RenderObjectsRendererFeature { passEvent = RenderPassEvent.RenderOpaques, scenePhase = SceneRenderPhase.Opaque, shaderPassName = "Unlit", overrideMaterialPath = "Assets/New Material.mat", overrideRenderStateBlock = true, renderStateBlock = new RenderStateBlock { mask = RenderStateMask.Depth, depthState = new DepthState { writeEnabled = true, compareFunction = CompareFunction.LessEqual }, stencilState = StencilState.CreateDefault(), stencilReference = 0 }, overrideRenderQueueRange = true, renderQueueRange = RenderQueueRange.Opaque, overrideRenderLayerMask = true, renderLayerMask = 1u << 0, rendererListType = RendererListType.Opaque } } } }; } } public sealed class ProjectCustomRenderer : ScriptableRenderer { private readonly DrawObjectsPass m_opaquePass = new DrawObjectsPass( RenderPassEvent.RenderOpaques, SceneRenderPhase.Opaque, RendererListDesc.CreateDefault( RendererListType.Opaque)); protected override void AddRenderPasses( RenderingData renderingData) { if (renderingData == null || !renderingData.isMainSceneStage) { return; } EnqueuePass(m_opaquePass); } } public sealed class ProjectCustomRendererData : ScriptableRendererData { protected override ScriptableRenderer CreateRenderer() { return new ProjectCustomRenderer(); } protected override string GetPipelineRendererAssetKey() { return "BuiltinForward"; } } public sealed class ProjectCustomRendererPipelineAsset : RendererBackedRenderPipelineAsset { public ProjectCustomRendererPipelineAsset() { rendererDataList = new ScriptableRendererData[] { new ProjectCustomRendererData() }; } } internal static class ProjectRendererInvalidationProbeState { public static int CreatePipelineCallCount; public static int DisposePipelineCallCount; public static int CreateRendererCallCount; public static int SetupRendererCallCount; public static int CreateFeatureCallCount; public static int DisposeRendererCallCount; public static int DisposeFeatureCallCount; public static int InvalidateRendererCallCount; public static void Reset() { CreatePipelineCallCount = 0; DisposePipelineCallCount = 0; CreateRendererCallCount = 0; SetupRendererCallCount = 0; CreateFeatureCallCount = 0; DisposeRendererCallCount = 0; DisposeFeatureCallCount = 0; InvalidateRendererCallCount = 0; } } public sealed class ProjectRendererInvalidationProbePipeline : RendererBackedRenderPipeline { public ProjectRendererInvalidationProbePipeline( RendererBackedRenderPipelineAsset asset) : base(asset) { ProjectRendererInvalidationProbeState .CreatePipelineCallCount++; } protected override void Dispose( bool disposing) { if (disposing) { ProjectRendererInvalidationProbeState .DisposePipelineCallCount++; } base.Dispose(disposing); } } public sealed class ProjectRendererInvalidationProbeFeature : ScriptableRendererFeature { protected override void ReleaseRuntimeResources() { ProjectRendererInvalidationProbeState .DisposeFeatureCallCount++; } } public sealed class ProjectRendererInvalidationProbeRenderer : ScriptableRenderer { protected override bool SupportsRendererRecording( RendererRecordingContext context) { return context != null && context.stage == CameraFrameStage.MainScene; } protected override bool RecordRenderer( RendererRecordingContext context) { return context != null; } protected override void ReleaseRuntimeResources() { ProjectRendererInvalidationProbeState .DisposeRendererCallCount++; } } public sealed class ProjectRendererInvalidationProbeRendererData : ScriptableRendererData { protected override ScriptableRenderer CreateRenderer() { ProjectRendererInvalidationProbeState .CreateRendererCallCount++; return new ProjectRendererInvalidationProbeRenderer(); } protected override void SetupRenderer( ScriptableRenderer renderer) { ProjectRendererInvalidationProbeState .SetupRendererCallCount++; base.SetupRenderer(renderer); } protected override ScriptableRendererFeature[] CreateRendererFeatures() { ProjectRendererInvalidationProbeState .CreateFeatureCallCount++; return new ScriptableRendererFeature[] { new ProjectRendererInvalidationProbeFeature() }; } protected override string GetPipelineRendererAssetKey() { return "BuiltinForward"; } public void InvalidateForTest() { ProjectRendererInvalidationProbeState .InvalidateRendererCallCount++; SetDirty(); } } public sealed class ProjectRendererInvalidationProbeAsset : RendererBackedRenderPipelineAsset { private readonly ProjectRendererInvalidationProbeRendererData m_rendererData; public ProjectRendererInvalidationProbeAsset() { ProjectRendererInvalidationProbeState.Reset(); m_rendererData = new ProjectRendererInvalidationProbeRendererData(); rendererDataList = new ScriptableRendererData[] { m_rendererData }; } protected override ScriptableRenderPipeline CreateRendererBackedPipeline() { return new ProjectRendererInvalidationProbePipeline( this); } public void InvalidateDefaultRendererForTest() { if (m_rendererData == null) { return; } m_rendererData.InvalidateForTest(); } } internal static class ProjectPersistentFeatureProbeState { public static int CreateRendererCallCount; public static int CreateFeatureRuntimeCallCount; public static int DisposeRendererCallCount; public static int DisposeFeatureCallCount; public static int InvalidateRendererCallCount; public static void Reset() { CreateRendererCallCount = 0; CreateFeatureRuntimeCallCount = 0; DisposeRendererCallCount = 0; DisposeFeatureCallCount = 0; InvalidateRendererCallCount = 0; } } public sealed class ProjectPersistentFeatureProbeRendererFeature : ScriptableRendererFeature { public override void Create() { ProjectPersistentFeatureProbeState .CreateFeatureRuntimeCallCount++; } protected override void ReleaseRuntimeResources() { ProjectPersistentFeatureProbeState .DisposeFeatureCallCount++; } } public sealed class ProjectPersistentFeatureProbeRenderer : ScriptableRenderer { protected override bool SupportsRendererRecording( RendererRecordingContext context) { return context != null && context.stage == CameraFrameStage.MainScene; } protected override bool RecordRenderer( RendererRecordingContext context) { return context != null; } protected override void ReleaseRuntimeResources() { ProjectPersistentFeatureProbeState .DisposeRendererCallCount++; } } public sealed class ProjectPersistentFeatureProbeRendererData : ScriptableRendererData { private readonly ProjectPersistentFeatureProbeRendererFeature m_feature = new ProjectPersistentFeatureProbeRendererFeature(); protected override ScriptableRenderer CreateRenderer() { ProjectPersistentFeatureProbeState .CreateRendererCallCount++; return new ProjectPersistentFeatureProbeRenderer(); } protected override ScriptableRendererFeature[] CreateRendererFeatures() { return new ScriptableRendererFeature[] { m_feature }; } protected override string GetPipelineRendererAssetKey() { return "BuiltinForward"; } public void InvalidateForTest() { ProjectPersistentFeatureProbeState .InvalidateRendererCallCount++; SetDirty(); } } public sealed class ProjectPersistentFeatureProbeAsset : RendererBackedRenderPipelineAsset { private readonly ProjectPersistentFeatureProbeRendererData m_rendererData; public ProjectPersistentFeatureProbeAsset() { ProjectPersistentFeatureProbeState.Reset(); m_rendererData = new ProjectPersistentFeatureProbeRendererData(); rendererDataList = new ScriptableRendererData[] { m_rendererData }; } public void InvalidateDefaultRendererForTest() { if (m_rendererData == null) { return; } m_rendererData.InvalidateForTest(); } } internal static class ProjectAssetInvalidationProbeState { public static int CreatePipelineCallCount; public static int DisposePipelineCallCount; public static int InvalidateAssetCallCount; public static int LastCreatedSupportedStage; public static void Reset() { CreatePipelineCallCount = 0; DisposePipelineCallCount = 0; InvalidateAssetCallCount = 0; LastCreatedSupportedStage = (int)CameraFrameStage.MainScene; } } public sealed class ProjectAssetInvalidationProbePipeline : ScriptableRenderPipeline { private readonly CameraFrameStage m_supportedStage; public ProjectAssetInvalidationProbePipeline( CameraFrameStage supportedStage) { m_supportedStage = supportedStage; ProjectAssetInvalidationProbeState .LastCreatedSupportedStage = (int)supportedStage; } protected override bool SupportsStageRenderGraph( CameraFrameStage stage) { return stage == m_supportedStage; } protected override bool RecordStageRenderGraph( ScriptableRenderContext context) { return context != null; } protected override void Dispose( bool disposing) { if (disposing) { ProjectAssetInvalidationProbeState .DisposePipelineCallCount++; } } } public sealed class ProjectAssetInvalidationProbeAsset : ScriptableRenderPipelineAsset { private CameraFrameStage m_supportedStage = CameraFrameStage.MainScene; public ProjectAssetInvalidationProbeAsset() { ProjectAssetInvalidationProbeState.Reset(); } protected override ScriptableRenderPipeline CreatePipeline() { ProjectAssetInvalidationProbeState .CreatePipelineCallCount++; return new ProjectAssetInvalidationProbePipeline( m_supportedStage); } public void InvalidatePipelineForTest( CameraFrameStage supportedStage) { if (m_supportedStage == supportedStage) { return; } m_supportedStage = supportedStage; ProjectAssetInvalidationProbeState .InvalidateAssetCallCount++; SetDirty(); } } public sealed class ProjectRendererInvalidationRuntimeSelectionProbe : MonoBehaviour { public void Start() { GraphicsSettings.renderPipelineAsset = new ProjectRendererInvalidationProbeAsset(); } } public sealed class ProjectRendererInvalidationObservationProbe : MonoBehaviour { public int ObservedCreatePipelineCallCount; public int ObservedDisposePipelineCallCount; public int ObservedCreateRendererCallCount; public int ObservedSetupRendererCallCount; public int ObservedCreateFeatureCallCount; public int ObservedDisposeRendererCallCount; public int ObservedDisposeFeatureCallCount; public int ObservedInvalidateRendererCallCount; public int ObservedRuntimeResourceVersionBeforeInvalidation; public int ObservedRuntimeResourceVersionAfterInvalidation; private bool m_requestedInvalidation; public void Update() { ProjectRendererInvalidationProbeAsset selectedAsset = GraphicsSettings.renderPipelineAsset as ProjectRendererInvalidationProbeAsset; if (!m_requestedInvalidation && selectedAsset != null && ProjectRendererInvalidationProbeState .CreateRendererCallCount > 0) { ObservedRuntimeResourceVersionBeforeInvalidation = ProjectProbeRuntimeVersionUtility .GetRuntimeResourceVersion( selectedAsset); selectedAsset.InvalidateDefaultRendererForTest(); ObservedRuntimeResourceVersionAfterInvalidation = ProjectProbeRuntimeVersionUtility .GetRuntimeResourceVersion( selectedAsset); m_requestedInvalidation = true; } ObservedCreatePipelineCallCount = ProjectRendererInvalidationProbeState .CreatePipelineCallCount; ObservedDisposePipelineCallCount = ProjectRendererInvalidationProbeState .DisposePipelineCallCount; ObservedCreateRendererCallCount = ProjectRendererInvalidationProbeState .CreateRendererCallCount; ObservedSetupRendererCallCount = ProjectRendererInvalidationProbeState .SetupRendererCallCount; ObservedCreateFeatureCallCount = ProjectRendererInvalidationProbeState .CreateFeatureCallCount; ObservedDisposeRendererCallCount = ProjectRendererInvalidationProbeState .DisposeRendererCallCount; ObservedDisposeFeatureCallCount = ProjectRendererInvalidationProbeState .DisposeFeatureCallCount; ObservedInvalidateRendererCallCount = ProjectRendererInvalidationProbeState .InvalidateRendererCallCount; } } public sealed class ProjectPersistentFeatureRuntimeSelectionProbe : MonoBehaviour { public void Start() { GraphicsSettings.renderPipelineAsset = new ProjectPersistentFeatureProbeAsset(); } } public sealed class ProjectPersistentFeatureObservationProbe : MonoBehaviour { public int ObservedCreateRendererCallCount; public int ObservedCreateFeatureRuntimeCallCount; public int ObservedDisposeRendererCallCount; public int ObservedDisposeFeatureCallCount; public int ObservedInvalidateRendererCallCount; private bool m_requestedInvalidation; public void Update() { ProjectPersistentFeatureProbeAsset selectedAsset = GraphicsSettings.renderPipelineAsset as ProjectPersistentFeatureProbeAsset; if (!m_requestedInvalidation && selectedAsset != null && ProjectPersistentFeatureProbeState .CreateFeatureRuntimeCallCount > 0) { selectedAsset.InvalidateDefaultRendererForTest(); m_requestedInvalidation = true; } ObservedCreateRendererCallCount = ProjectPersistentFeatureProbeState .CreateRendererCallCount; ObservedCreateFeatureRuntimeCallCount = ProjectPersistentFeatureProbeState .CreateFeatureRuntimeCallCount; ObservedDisposeRendererCallCount = ProjectPersistentFeatureProbeState .DisposeRendererCallCount; ObservedDisposeFeatureCallCount = ProjectPersistentFeatureProbeState .DisposeFeatureCallCount; ObservedInvalidateRendererCallCount = ProjectPersistentFeatureProbeState .InvalidateRendererCallCount; } } public sealed class ProjectAssetInvalidationRuntimeSelectionProbe : MonoBehaviour { public void Start() { GraphicsSettings.renderPipelineAsset = new ProjectAssetInvalidationProbeAsset(); } } public sealed class ProjectAssetInvalidationObservationProbe : MonoBehaviour { public int ObservedCreatePipelineCallCount; public int ObservedDisposePipelineCallCount; public int ObservedInvalidateAssetCallCount; public int ObservedLastCreatedSupportedStage; private bool m_requestedInvalidation; public void Update() { ProjectAssetInvalidationProbeAsset selectedAsset = GraphicsSettings.renderPipelineAsset as ProjectAssetInvalidationProbeAsset; if (!m_requestedInvalidation && selectedAsset != null && ProjectAssetInvalidationProbeState .CreatePipelineCallCount > 0) { selectedAsset.InvalidatePipelineForTest( CameraFrameStage.PostProcess); m_requestedInvalidation = true; } ObservedCreatePipelineCallCount = ProjectAssetInvalidationProbeState .CreatePipelineCallCount; ObservedDisposePipelineCallCount = ProjectAssetInvalidationProbeState .DisposePipelineCallCount; ObservedInvalidateAssetCallCount = ProjectAssetInvalidationProbeState .InvalidateAssetCallCount; ObservedLastCreatedSupportedStage = ProjectAssetInvalidationProbeState .LastCreatedSupportedStage; } } }