diff --git a/engine/include/XCEngine/Rendering/AGENTS.md b/engine/include/XCEngine/Rendering/AGENTS.md index 196ceeaa..d109d6de 100644 --- a/engine/include/XCEngine/Rendering/AGENTS.md +++ b/engine/include/XCEngine/Rendering/AGENTS.md @@ -8,8 +8,10 @@ ### 方向 -渲染器有意参考 Unity SRP 和 URP 设计。后续工作在概念适配本引擎时,应优先采用 -Unity 兼容的公开命名、对象所有权和扩展点。 +渲染器的 managed public surface 以 Unity SRP 和 URP 为直接蓝本。后续工作默认先照搬 +Unity 的公开命名、生命周期、对象所有权、扩展点和用户心智;native RenderGraph、RHI 和 +SceneDrawBackend 只是执行后端,不是另一个面向 URP authors 的策略模型。这里不宣称能跑 +Unity 项目、Unity package 或 Unity asset,只要求用户可见的 SRP/URP 设计形状尽量按 Unity 来。 - 保持 managed 公开表面接近 Unity:`GraphicsSettings.renderPipelineAsset`、 `RenderPipelineAsset`、`ScriptableRenderPipelineAsset`、 @@ -17,20 +19,38 @@ Unity 兼容的公开命名、对象所有权和扩展点。 `UniversalRenderPipelineAsset`、`UniversalRendererData`、 `ScriptableRenderer`、`ScriptableRendererFeature`、`ScriptableRenderPass`、 `RenderPassEvent`、`ContextContainer` 和 `RenderGraph`。 -- 在发明新的公开词汇前,优先对齐行为。如果某个 Unity 概念在这里只实现了一部分, - 要诚实暴露已实现的子集,把缺失行为留在内部代码或测试里。 +- 只要 Unity 有对应概念,不新增平行 public 词汇或平行 authoring 模型。如果某个 Unity + 概念暂时只实现了一部分,public shape 仍要跟随 Unity;缺失行为应显式失败、进入 debt, + 或由测试标明未覆盖,而不是改写成 XCEngine 专属语义。 - 保留 Unity 风格的 `RenderPassEvent` 数值顺序。新增或移动事件时,必须一起更新 `ScriptableRenderPass.TryResolveRendererBlock`、`RendererBlocks`、probes 和测试。 - 管线自定义优先使用 managed URP features 和 passes。Native 路径应提供后端执行、 - 场景提取、fallback passes 和工具支持。 + 场景提取、legacy/native fallback passes 和工具支持,不应成为 URP 用户的首选扩展面。 - 渲染器代码保持后端无关。D3D12、OpenGL 和 Vulkan 细节属于 `engine/include/XCEngine/RHI/**`、`engine/src/RHI/**` 或 editor host rendering, 不应进入 SRP/URP 策略层。 +### Unity 复刻目标 + +当前目标不是“受 Unity 启发”,而是尽量复刻 Unity SRP/URP 的 public authoring model。 +native 侧可以用本引擎自己的 RenderGraph、RHI 和资源系统实现,但 C# 用户看到的资产、 +renderer data、renderer feature、render pass、RenderGraph 和 command recording 生命周期应优先按 Unity +来组织。 + +- 复刻优先级依次是:C# public API 命名和类型形状,asset/renderer/feature/pass 所有权, + lifecycle 和调用顺序,`RenderPassEvent` ordering 与 block mapping,serialized asset shape, + 最后才是 native 执行细节。 +- 引入 Unity 已有行为时,以 Unity/URP 行为作为事实源;不要把多个 Unity 世代的行为随意混在同一个 + public surface 里。需要升级 Unity 参照线时,同步更新本节、managed probes 和 contract tests。 +- 新增 public managed rendering API 前,先确认 Unity 是否已有同名或等价入口。存在 Unity 入口时, + 优先补齐它;engine-only 工具入口应保持 internal、native-only 或 editor-only。 +- Native convenience 不能作为偏离 Unity public model 的理由。需要临时 native bridge 时,把它藏在 + managed Unity-style API 后面,并在 tests 中锁住用户可观察行为。 + ### 近期目标 -当前优先级是完成 SRP/URP 架构切分,并在每条边界上补目标明确的测试。近期产品目标 -是让 URP 成为渲染决策层,让 native rendering 成为执行层。 +当前优先级是完成 SRP/URP 架构切分,并让 public SRP/URP surface 继续贴近 Unity。 +近期产品目标是让 URP 成为渲染决策层,让 native rendering 成为执行层。 - 将 `BuiltinForwardPipeline` 从策略中心降级为默认 native scene draw backend。它可以 继续作为 backend/fallback 实现存在,但不应决定 URP pass 顺序、feature 参与方式或 @@ -90,12 +110,14 @@ Unity 兼容的公开命名、对象所有权和扩展点。 - SRP/URP 架构已经阶段性收口到可以继续扩展。公开对象模型、managed asset selection、 URP renderer data/features/passes、native frame planning、stage recording 和 RenderGraph execution 现在组成了一条路径。 -- 这还不是完整 Unity URP 兼容。公开形态有意接近 Unity,但执行 feature set 仍小于 Unity URP。 +- 这还不是完整 Unity URP 复刻,但目标是继续补齐 Unity public model。当前执行 feature set + 仍小于 Unity URP;这些差距是待补能力,不是另起一套 public 设计的理由。 - `UniversalRenderPipelineAsset` 可以被选为 active managed SRP asset,所以用户可以把渲染路由到 URP package。把它视为受支持能力,但仍处于过渡状态。 -- 当前 URP package 还不是强意义上对 built-in renderer 的完整替代。URP 拥有 selection、planning、 - renderer feature organization、pass ordering 和 stage recording;native code 仍提供 scene extraction、 - renderer-list realization、RenderGraph execution、RHI resources 和默认 scene draw backend。 +- 当前 URP package 还不是强意义上对 built-in renderer 的完整替代,但它必须继续朝 Unity URP + 用户入口收口。URP 拥有 selection、planning、renderer feature organization、pass ordering 和 + stage recording;native code 仍提供 scene extraction、renderer-list realization、RenderGraph execution、 + RHI resources 和默认 scene draw backend。 - Native execution 本身不是问题。Unity 也通过 native engine 执行。风险在于 native code 继续保留 built-in forward pipeline policy,而不是作为 URP-declared work 的 backend executor。 - 目标所有权模型是:URP 决定渲染什么、何时渲染、哪些 renderer lists/passes/features 激活,以及 @@ -138,7 +160,7 @@ Native renderer 现在是 camera frame planner 加 RenderGraph executor,manage - `SceneRenderer` 是 scene-level convenience entry point。它的公开管线选择根是 `RenderPipelineAsset`; 它通过 `SceneRenderRequestPlanner` 收集 camera requests,通过 `RenderPipelineHost` 构建 `CameraStackFramePlan`,然后以 camera stack 为根渲染。旧的 `BuildFramePlans`/flat-plan `Render` - API 只是兼容包装。 + API 只是过渡包装。 - `RenderPipelineHost` 拥有一个 `CameraFramePlanBuilder` 和一个 `CameraRenderer`。它是从 `CameraRenderRequest` 到 `CameraStackFramePlan` 的常规 native bridge,并沿用同一个 asset selection root。 Stack 渲染完成后由所选 `RenderPipeline` 接收 `FinishCameraStackRendering`,用于 URP stack 生命周期收尾。 @@ -193,7 +215,7 @@ Native passes 仍用于 backend fallback、工具和 built-in rendering。 - 新 native passes 应尽可能实现 `RecordRenderGraph`。只有 legacy execution 仍需要时,才把 `Execute` 保留为 fallback path。 -- 对 fallback-compatible raster passes,使用 `RenderPassGraphContract` 和 `RecordRenderGraphSurfaceIO` +- 对可走 fallback 的 raster passes,使用 `RenderPassGraphContract` 和 `RecordRenderGraphSurfaceIO` helpers。 - `SceneRenderFeaturePass` 用于在 scene phases 周围注入 native scene feature。保持 `SceneRenderInjectionPoint` 中的 injection points、`ScenePhase` 中的 scene phases 与 @@ -227,9 +249,13 @@ Managed SRP assets 通过 `GraphicsSettings.renderPipelineAsset` 选择,并通 - Mono 创建 `MonoManagedRenderPipelineAssetRuntime` 和 `MonoManagedRenderPipelineStageRecorder`。 Scriptable context、planning context、camera request context、scene setup context 和 shadow execution context handles 都是临时 native registry entries。不要在调用之外保存 managed context objects。 +- `ScriptableRenderContext` 的 public 职责只保留 SRP v1 场景绘制兼容入口,例如 + `DrawRenderers` 和 `DrawSkybox`。`stage`、`rendererIndex`、`framePlanId`、 + `sourceColorTexture`、`primaryColorTarget`、`depthTarget`、transient texture creation 和 + `AddRasterPass` 都是 internal bridge data,不是用户 authoring surface。 - 当前 Mono-backed SRP assets 显式使用 `DefaultNativeBackend` 做 scene drawing。URP 内置对象和 skybox drawing 通过 managed RenderGraph 声明 renderer list、attachments 和 render func,再由 native - `SceneDrawBackend` 执行。`ScriptableRenderContext.DrawRenderers` 和 `DrawSkybox` 仍作为 SRP v1 兼容入口保留, + `SceneDrawBackend` 执行。`ScriptableRenderContext.DrawRenderers` 和 `DrawSkybox` 仍作为 SRP v1 旧入口保留, 并委托给 `NativeSceneRecorder`。 - Managed resource/version invalidation 是正确性的一部分。如果 managed asset、renderer data 或 feature 修改 runtime state,调用 `SetDirty` 或本地 invalidation helper,确保 native runtime caches 被释放。 @@ -241,7 +267,8 @@ Managed SRP assets 通过 `GraphicsSettings.renderPipelineAsset` 选择,并通 ### URP Model URP package 位于 `managed/XCEngine.RenderPipelines.Universal`。它应被视为主要面向用户的 render pipeline -package。 +package,也是照搬 Unity URP public surface 的主战场。新的用户可见渲染策略应先落到 managed URP +概念里,再由 native backend 执行。 - `UniversalRenderPipelineAsset` 拥有 `rendererDataList`、`defaultRendererIndex`、 `UniversalShadowSettings` 和 `UniversalFinalColorSettings`。它从 `UniversalAdditionalCameraData` 解析 @@ -256,7 +283,7 @@ package。 `RendererPassQueueData`,不暴露 `RenderingData.stage`;passes 按 `RenderPassEvent` 顺序插入,并归组到 `RendererBlocks`。 - URP stage planning 以 `ScriptableRenderer` 的 active pass queue 为最终事实源。`ConfigureCameraFramePlan` - 仍是兼容和高级策略 hook,但它不能单独声明 shadow、depth、post 或 final-output stage;没有被 pass queue + 仍是旧式和高级策略 hook,但它不能单独声明 shadow、depth、post 或 final-output stage;没有被 pass queue 覆盖到的 side/fullscreen stage 必须在最终 plan 中清掉。 - Native `CameraFramePlanBuilder` 不得在 renderer/pass-queue-derived manifest 应用之后再补 fullscreen stage 请求;URP path 中 post/final stage 的存在性必须完全来自 `ScriptableRenderer` @@ -293,11 +320,16 @@ package。 ### Managed RenderGraph -Managed RenderGraph 目前有意保持较小,但应维持 Unity 的现代形态。 +Managed RenderGraph 目前实现规模较小,但 public shape 必须继续维持 Unity 的现代 RenderGraph 形态。 +规模小只能表示能力未补齐,不能变成另一个 XCEngine 专属 authoring model。 - Public managed authoring 通过 `XCEngine.Rendering.RenderGraphModule.RenderGraph.AddRasterPass` 和 `RenderGraphRasterPassBuilder` 进行。 +- Public pass authoring 入口是 + `ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)`。不要让用户代码通过 + `ScriptableRenderContext` 读取 graph texture handles、创建 transient textures 或添加 raster pass; + 这些能力应由 `RenderGraph` 暴露,并由 `ContextContainer` 提供当帧 URP data。 - Public passes 应声明 reads、bindings、color attachments、depth attachment 和 render func,然后 `Commit`。 - Renderer-list drawing 是 RenderGraph authoring 的一等声明:先用 `RenderGraph.CreateRendererList(RendererListDesc, DrawingSettings)` 创建 `RendererListHandle`,再通过 @@ -423,7 +455,7 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。 stage manifest。Stage support 和 stage recording 现在消费 planning 阶段保存的同一份冻结 plan, 关闭了 feature planning hook、support probe、recording 和各 stage 分别重建 pass queue 的重复事实源。 - 顶层 native orchestration 已从 flat camera frame list 收口为 `CameraStackFramePlan`。`SceneRenderer` - 和 `RenderPipelineHost` 的真实渲染入口以 camera stack 为根;flat `CameraFramePlan` APIs 保留为兼容包装。 + 和 `RenderPipelineHost` 的真实渲染入口以 camera stack 为根;flat `CameraFramePlan` APIs 保留为过渡包装。 - URP `OnFinishCameraStackRendering` 已改为 stack-end 语义:recording 阶段只登记待收尾 pass,native `CameraStackFramePlan` 渲染完成后再通过 pipeline/stage-recorder bridge 触发。 - `CameraFramePlanBuilder` 已移除对 fullscreen stages 的通用尾部自动补齐;selected @@ -437,8 +469,9 @@ Scene data 每个 camera frame 提取一次,然后由 pipeline 调整。 - URP runtime-state invalidation 已覆盖 asset-level shadow/final-color settings 和 renderer-data-level main-scene/shadow-caster/depth-prepass block settings。配置变更会通过 runtime resource version 释放 renderer caches,并让后续 planning 重新生成 `RendererFramePlan` 和 stage manifest。 -- Public managed RenderGraph raster authoring 已存在;internal fullscreen kernels 仍是 URP implementation - details。 +- Public managed RenderGraph raster authoring 已从 `ScriptableRenderContext` 收口到 `RenderGraph`。 + `ScriptableRenderContext` 不再公开 graph texture handles、transient texture creation、`AddRasterPass` + 或 `framePlanId`;internal fullscreen kernels 仍是 URP implementation details。 - Public managed `SetRenderFunc` 已从 recording-time 调用改为 RenderGraph execution-time 调用; native 通过 retained managed delegate 和 pass-scoped `CommandBuffer` bridge 执行已支持的 command stream, 当前支持 `CommandBuffer.ClearRenderTarget(Color)`、`CommandBuffer.DrawRendererList(RendererListHandle)` 和 diff --git a/managed/GameScripts/RenderPipelineApiProbe.cs b/managed/GameScripts/RenderPipelineApiProbe.cs index 80e55722..5207b7c5 100644 --- a/managed/GameScripts/RenderPipelineApiProbe.cs +++ b/managed/GameScripts/RenderPipelineApiProbe.cs @@ -203,29 +203,31 @@ namespace Gameplay m_passName = passName ?? string.Empty; } - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) { - return context != null && - renderingData != null && - RecordFullscreen(context); - } + RenderingData renderingData = + frameData != null + ? frameData.Get() + : null; + if (renderGraph == null || + renderingData == null) + { + return; + } - private bool RecordFullscreen( - ScriptableRenderContext context) - { RenderGraphTextureHandle sourceColor = - context.sourceColorTexture; + renderGraph.sourceColorTexture; RenderGraphTextureHandle outputColor = - context.primaryColorTarget; + renderGraph.primaryColorTarget; if (!sourceColor.isValid || !outputColor.isValid) { - return false; + return; } - return context + renderGraph .AddRasterPass(ResolvePassName()) .UseColorSource(sourceColor) .SetColorAttachment(outputColor) @@ -256,27 +258,31 @@ namespace Gameplay m_passName = passName ?? string.Empty; } - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) { - if (context == null || + RenderingData renderingData = + frameData != null + ? frameData.Get() + : null; + if (renderGraph == null || renderingData == null) { - return false; + return; } RenderGraphTextureHandle sourceColor = - context.sourceColorTexture; + renderGraph.sourceColorTexture; RenderGraphTextureHandle outputColor = - context.primaryColorTarget; + renderGraph.primaryColorTarget; if (!sourceColor.isValid || !outputColor.isValid) { - return false; + return; } - return context + renderGraph .AddRasterPass(ResolvePassName()) .UseColorSource(sourceColor) .SetColorAttachment(outputColor) @@ -2758,12 +2764,18 @@ namespace Gameplay protected override bool RecordStageRenderGraph( ScriptableRenderContext context) { - return context != null && - context + if (context == null) + { + return false; + } + + RenderGraph renderGraph = + new RenderGraph(context); + return renderGraph .AddRasterPass( "Managed.MainSceneGenericRasterPass") .SetColorAttachment( - context.primaryColorTarget) + renderGraph.primaryColorTarget) .SetRenderFunc( rasterContext => { @@ -2807,17 +2819,23 @@ namespace Gameplay protected override bool RecordStageRenderGraph( ScriptableRenderContext context) { - if (context == null || - !context.primaryColorTarget.isValid) + if (context == null) { return false; } - return context + RenderGraph renderGraph = + new RenderGraph(context); + if (!renderGraph.primaryColorTarget.isValid) + { + return false; + } + + return renderGraph .AddRasterPass( "Managed.CommandBufferRenderFunc") .SetColorAttachment( - context.primaryColorTarget) + renderGraph.primaryColorTarget) .SetRenderFunc( rasterContext => { diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs index 99803b85..2c87575c 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/BuiltinFinalColorPass.cs @@ -1,5 +1,6 @@ using XCEngine; using XCEngine.Rendering; +using XCEngine.Rendering.RenderGraphModule; namespace XCEngine.Rendering.Universal { @@ -12,18 +13,26 @@ namespace XCEngine.Rendering.Universal RenderPassEvent.BeforeRenderingFinalOutput; } - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) { - return context != null && - renderingData != null && - renderingData.isFinalOutputStage && - (!renderingData.finalColorData.requiresProcessing || - RecordInternalFinalColorFullscreenPass( - context, - renderingData.finalColorData.settings, - "Universal.BuiltinFinalColor")); + RenderingData renderingData = + frameData != null + ? frameData.Get() + : null; + if (renderGraph == null || + renderingData == null || + !renderingData.isFinalOutputStage || + !renderingData.finalColorData.requiresProcessing) + { + return; + } + + RecordInternalFinalColorFullscreenPass( + renderGraph, + renderingData.finalColorData.settings, + "Universal.BuiltinFinalColor"); } } } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs index fde2ad8d..9705d573 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ColorScalePostProcessRendererFeature.cs @@ -1,5 +1,6 @@ using XCEngine; using XCEngine.Rendering; +using XCEngine.Rendering.RenderGraphModule; namespace XCEngine.Rendering.Universal { @@ -24,21 +25,25 @@ namespace XCEngine.Rendering.Universal m_colorScale = colorScale; } - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) { - if (context == null || + RenderingData renderingData = + frameData != null + ? frameData.Get() + : null; + if (renderGraph == null || renderingData == null || !renderingData.isPostProcessStage) { - return false; + return; } - return RecordInternalColorScaleFullscreenPass( - context, - context.sourceColorTexture, - context.primaryColorTarget, + RecordInternalColorScaleFullscreenPass( + renderGraph, + renderGraph.sourceColorTexture, + renderGraph.primaryColorTarget, m_colorScale, "Universal.ColorScalePostProcess"); } diff --git a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs index 56f3540d..b503ac54 100644 --- a/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs +++ b/managed/XCEngine.RenderPipelines.Universal/Rendering/Universal/ScriptableRenderPass.cs @@ -181,37 +181,37 @@ namespace XCEngine.Rendering.Universal } internal static bool RecordInternalColorScaleFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, Vector4 colorScale) { RenderGraphTextureHandle sourceColor; RenderGraphTextureHandle outputColor; return TryResolveDefaultFullscreenTargets( - context, + renderGraph, out sourceColor, out outputColor) && RecordInternalColorScaleFullscreenPass( - context, + renderGraph, sourceColor, outputColor, colorScale); } internal static bool RecordInternalColorScaleFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, Vector4 colorScale, string passName = null) { - if (context == null || + if (renderGraph == null || !outputColor.isValid) { return false; } RenderGraphRasterPassBuilder passBuilder = - context.AddRasterPass( + renderGraph.AddRasterPass( ResolveFullscreenPassName( passName, kColorScaleFullscreenPassName)); @@ -227,7 +227,7 @@ namespace XCEngine.Rendering.Universal } internal static bool RecordInternalShaderVectorFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, string shaderPath, Vector4 vectorPayload, string passName = null) @@ -242,11 +242,11 @@ namespace XCEngine.Rendering.Universal RenderGraphTextureHandle sourceColor; RenderGraphTextureHandle outputColor; return TryResolveDefaultFullscreenTargets( - context, + renderGraph, out sourceColor, out outputColor) && RecordInternalShaderVectorFullscreenPass( - context, + renderGraph, sourceColor, outputColor, shaderPath, @@ -255,7 +255,7 @@ namespace XCEngine.Rendering.Universal } internal static bool RecordInternalShaderVectorFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, string shaderPath, @@ -270,14 +270,14 @@ namespace XCEngine.Rendering.Universal nameof(shaderPath)); } - if (context == null || + if (renderGraph == null || !outputColor.isValid) { return false; } RenderGraphRasterPassBuilder passBuilder = - context.AddRasterPass( + renderGraph.AddRasterPass( ResolveFullscreenPassName( passName, kShaderVectorFullscreenPassName)); @@ -296,18 +296,18 @@ namespace XCEngine.Rendering.Universal } internal static bool RecordInternalFinalColorFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, FinalColorSettings settings, string passName = null) { RenderGraphTextureHandle sourceColor; RenderGraphTextureHandle outputColor; return TryResolveDefaultFullscreenTargets( - context, + renderGraph, out sourceColor, out outputColor) && RecordInternalFinalColorFullscreenPass( - context, + renderGraph, sourceColor, outputColor, settings, @@ -315,20 +315,20 @@ namespace XCEngine.Rendering.Universal } internal static bool RecordInternalFinalColorFullscreenPass( - ScriptableRenderContext context, + RenderGraph renderGraph, RenderGraphTextureHandle sourceColor, RenderGraphTextureHandle outputColor, FinalColorSettings settings, string passName = null) { - if (context == null || + if (renderGraph == null || !outputColor.isValid) { return false; } RenderGraphRasterPassBuilder passBuilder = - context.AddRasterPass( + renderGraph.AddRasterPass( ResolveFullscreenPassName( passName, kFinalColorFullscreenPassName)); @@ -487,19 +487,19 @@ namespace XCEngine.Rendering.Universal } private static bool TryResolveDefaultFullscreenTargets( - ScriptableRenderContext context, + RenderGraph renderGraph, out RenderGraphTextureHandle sourceColor, out RenderGraphTextureHandle outputColor) { sourceColor = new RenderGraphTextureHandle(); outputColor = new RenderGraphTextureHandle(); - if (context == null) + if (renderGraph == null) { return false; } - sourceColor = context.sourceColorTexture; - outputColor = context.primaryColorTarget; + sourceColor = renderGraph.sourceColorTexture; + outputColor = renderGraph.primaryColorTarget; return sourceColor.isValid && outputColor.isValid; } diff --git a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs index 616b3f0e..c0d824c8 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Core/ScriptableRenderContext.cs @@ -3,8 +3,8 @@ using XCEngine; namespace XCEngine.Rendering { // SRP v1 managed recording surface. Scene draws still delegate to the - // native SceneDrawBackend, and raster-pass recording is limited to the - // fullscreen PostProcess / FinalOutput stages. + // native SceneDrawBackend; RenderGraph raster authoring can record scene + // and fullscreen stages through the Unity-style managed surface. public sealed class ScriptableRenderContext { private readonly ulong m_nativeHandle; @@ -14,16 +14,16 @@ namespace XCEngine.Rendering m_nativeHandle = nativeHandle; } - public CameraFrameStage stage => + internal CameraFrameStage stage => (CameraFrameStage)InternalCalls.Rendering_ScriptableRenderContext_GetStage( m_nativeHandle); - public int rendererIndex => + internal int rendererIndex => InternalCalls .Rendering_ScriptableRenderContext_GetRendererIndex( m_nativeHandle); - public ulong framePlanId => + internal ulong framePlanId => InternalCalls .Rendering_ScriptableRenderContext_GetFramePlanId( m_nativeHandle); @@ -33,19 +33,19 @@ namespace XCEngine.Rendering .Rendering_ScriptableRenderContext_GetPassName( m_nativeHandle) ?? string.Empty; - public RenderGraphTextureHandle sourceColorTexture => + internal RenderGraphTextureHandle sourceColorTexture => RenderGraphTextureHandle.FromNativeIndex( InternalCalls .Rendering_ScriptableRenderContext_GetSourceColorTextureHandle( m_nativeHandle)); - public RenderGraphTextureHandle primaryColorTarget => + internal RenderGraphTextureHandle primaryColorTarget => RenderGraphTextureHandle.FromNativeIndex( InternalCalls .Rendering_ScriptableRenderContext_GetPrimaryColorTargetHandle( m_nativeHandle)); - public RenderGraphTextureHandle depthTarget => + internal RenderGraphTextureHandle depthTarget => RenderGraphTextureHandle.FromNativeIndex( InternalCalls .Rendering_ScriptableRenderContext_GetDepthTargetHandle( @@ -142,7 +142,7 @@ namespace XCEngine.Rendering RendererListType.Transparent)); } - public RenderGraphTextureHandle CreateTransientTexture( + internal RenderGraphTextureHandle CreateTransientTexture( string name, RenderGraphTextureDesc desc) { @@ -154,7 +154,7 @@ namespace XCEngine.Rendering ref desc)); } - public RenderGraphTextureHandle + internal RenderGraphTextureHandle CreateFullscreenTransientColorTexture( string name) { @@ -165,7 +165,7 @@ namespace XCEngine.Rendering name)); } - public RenderGraphTextureHandle + internal RenderGraphTextureHandle CreateFullscreenTransientDepthTexture( string name) { @@ -193,10 +193,10 @@ namespace XCEngine.Rendering ref renderStateBlock)); } - // Public RenderGraph raster authoring entry point. Built-in fullscreen - // kernels are internal URP implementation details, not public context - // shortcuts. - public RenderGraphRasterPassBuilder AddRasterPass( + // Internal backing entry point for public RenderGraph raster authoring. + // Built-in fullscreen kernels are URP implementation details, not + // public context shortcuts. + internal RenderGraphRasterPassBuilder AddRasterPass( string passName) { return new RenderGraphRasterPassBuilder( diff --git a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs index 208eb059..2cbd488c 100644 --- a/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs +++ b/managed/XCEngine.ScriptCore/Rendering/Graph/RenderGraph.cs @@ -31,6 +31,48 @@ namespace XCEngine.Rendering.RenderGraphModule return m_context.AddRasterPass(passName); } + public XCEngine.Rendering.RenderGraphTextureHandle + CreateTransientTexture( + string name, + XCEngine.Rendering.RenderGraphTextureDesc desc) + { + if (m_context == null) + { + throw new InvalidOperationException( + "RenderGraph is not bound to a recording context."); + } + + return m_context.CreateTransientTexture( + name, + desc); + } + + public XCEngine.Rendering.RenderGraphTextureHandle + CreateFullscreenTransientColorTexture( + string name) + { + if (m_context == null) + { + throw new InvalidOperationException( + "RenderGraph is not bound to a recording context."); + } + + return m_context.CreateFullscreenTransientColorTexture(name); + } + + public XCEngine.Rendering.RenderGraphTextureHandle + CreateFullscreenTransientDepthTexture( + string name) + { + if (m_context == null) + { + throw new InvalidOperationException( + "RenderGraph is not bound to a recording context."); + } + + return m_context.CreateFullscreenTransientDepthTexture(name); + } + public XCEngine.Rendering.RendererListHandle CreateRendererList( XCEngine.Rendering.RendererListDesc rendererListDesc) diff --git a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs index 0d22b829..4849aad9 100644 --- a/project/Assets/Scripts/ProjectRenderPipelineProbe.cs +++ b/project/Assets/Scripts/ProjectRenderPipelineProbe.cs @@ -1,6 +1,7 @@ using System.Reflection; using XCEngine; using XCEngine.Rendering; +using XCEngine.Rendering.RenderGraphModule; using XCEngine.Rendering.Universal; namespace ProjectScripts @@ -42,23 +43,27 @@ namespace ProjectScripts RenderPassEvent.BeforeRenderingPostProcessing; } - protected override bool RecordRenderGraph( - ScriptableRenderContext context, - RenderingData renderingData) + public override void RecordRenderGraph( + RenderGraph renderGraph, + ContextContainer frameData) { - if (context == null || + RenderingData renderingData = + frameData != null + ? frameData.Get() + : null; + if (renderGraph == null || renderingData == null || !renderingData.isPostProcessStage || - !context.sourceColorTexture.isValid || - !context.primaryColorTarget.isValid) + !renderGraph.sourceColorTexture.isValid || + !renderGraph.primaryColorTarget.isValid) { - return false; + return; } - return context + renderGraph .AddRasterPass("Project.PostProcessColorScale") - .UseColorSource(context.sourceColorTexture) - .SetColorAttachment(context.primaryColorTarget) + .UseColorSource(renderGraph.sourceColorTexture) + .SetColorAttachment(renderGraph.primaryColorTarget) .SetRenderFunc( rasterContext => { diff --git a/tests/scripting/test_mono_script_runtime.cpp b/tests/scripting/test_mono_script_runtime.cpp index d0472058..c9c621b8 100644 --- a/tests/scripting/test_mono_script_runtime.cpp +++ b/tests/scripting/test_mono_script_runtime.cpp @@ -1693,7 +1693,7 @@ TEST_F( TEST_F( MonoScriptRuntimeTest, - ScriptableRenderContextPublicApiSurfaceUsesDirectContextModel) { + ScriptableRenderContextPublicApiSurfaceUsesRenderGraphAuthoringModel) { Scene* runtimeScene = CreateScene("ScriptableRenderContextApiSurfaceScene"); GameObject* selectionObject = @@ -1724,6 +1724,13 @@ TEST_F( bool hasPublicContextEnvironmentData = false; bool hasPublicContextFinalColorData = false; bool hasPublicContextStageColorData = false; + bool hasPublicContextSourceColorTexture = false; + bool hasPublicContextPrimaryColorTarget = false; + bool hasPublicContextDepthTarget = false; + bool hasPublicContextCreateTransientTexture = false; + bool hasPublicContextCreateFullscreenTransientColorTexture = false; + bool hasPublicContextCreateFullscreenTransientDepthTexture = false; + bool hasPublicContextAddRasterPass = false; bool hasPublicContextFramePlanId = false; bool hasPublicRequestContextHasDirectionalShadow = false; bool hasPublicRequestContextClearDirectionalShadow = false; @@ -1766,6 +1773,7 @@ TEST_F( bool hasRenderGraphRasterContextCommandBuffer = false; bool hasSceneRenderPhaseType = false; bool hasSceneRenderInjectionPointType = false; + bool hasRenderGraphAddRasterPass = false; bool hasRenderGraphCreateRendererList = false; bool hasRendererListHandleType = false; bool hasCommandBufferDrawRendererList = false; @@ -1835,6 +1843,34 @@ TEST_F( selectionScript, "HasPublicContextStageColorData", hasPublicContextStageColorData)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextSourceColorTexture", + hasPublicContextSourceColorTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextPrimaryColorTarget", + hasPublicContextPrimaryColorTarget)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextDepthTarget", + hasPublicContextDepthTarget)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextCreateTransientTexture", + hasPublicContextCreateTransientTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextCreateFullscreenTransientColorTexture", + hasPublicContextCreateFullscreenTransientColorTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextCreateFullscreenTransientDepthTexture", + hasPublicContextCreateFullscreenTransientDepthTexture)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasPublicContextAddRasterPass", + hasPublicContextAddRasterPass)); EXPECT_TRUE(runtime->TryGetFieldValue( selectionScript, "HasPublicContextFramePlanId", @@ -2003,6 +2039,10 @@ TEST_F( selectionScript, "HasSceneRenderInjectionPointType", hasSceneRenderInjectionPointType)); + EXPECT_TRUE(runtime->TryGetFieldValue( + selectionScript, + "HasRenderGraphAddRasterPass", + hasRenderGraphAddRasterPass)); EXPECT_TRUE(runtime->TryGetFieldValue( selectionScript, "HasRenderGraphCreateRendererList", @@ -2051,7 +2091,14 @@ TEST_F( EXPECT_FALSE(hasPublicContextEnvironmentData); EXPECT_FALSE(hasPublicContextFinalColorData); EXPECT_FALSE(hasPublicContextStageColorData); - EXPECT_TRUE(hasPublicContextFramePlanId); + EXPECT_FALSE(hasPublicContextSourceColorTexture); + EXPECT_FALSE(hasPublicContextPrimaryColorTarget); + EXPECT_FALSE(hasPublicContextDepthTarget); + EXPECT_FALSE(hasPublicContextCreateTransientTexture); + EXPECT_FALSE(hasPublicContextCreateFullscreenTransientColorTexture); + EXPECT_FALSE(hasPublicContextCreateFullscreenTransientDepthTexture); + EXPECT_FALSE(hasPublicContextAddRasterPass); + EXPECT_FALSE(hasPublicContextFramePlanId); EXPECT_FALSE(hasPublicRequestContextHasDirectionalShadow); EXPECT_FALSE(hasPublicRequestContextClearDirectionalShadow); EXPECT_FALSE(hasUniversalContextRecordSceneExtension); @@ -2093,6 +2140,7 @@ TEST_F( EXPECT_TRUE(hasRenderGraphRasterContextCommandBuffer); EXPECT_FALSE(hasSceneRenderPhaseType); EXPECT_FALSE(hasSceneRenderInjectionPointType); + EXPECT_TRUE(hasRenderGraphAddRasterPass); EXPECT_TRUE(hasRenderGraphCreateRendererList); EXPECT_TRUE(hasRendererListHandleType); EXPECT_TRUE(hasCommandBufferDrawRendererList);