Align URP render graph frame data scope
This commit is contained in:
@@ -6,63 +6,123 @@ already made. It is intentionally not a full map of the current implementation.
|
||||
If this file conflicts with the current code, trust the code and update this
|
||||
file in the same change.
|
||||
|
||||
## Long-Term Goal
|
||||
## Next-Stage Goal
|
||||
|
||||
The rendering module is moving toward a Unity SRP / URP style model:
|
||||
The rendering module's next stage is to close the SRP / URP architecture around
|
||||
Unity's public rendering model. The goal is not merely to have similar class
|
||||
names; pipeline authors should be able to reason about XCEngine rendering with
|
||||
the same mental model they use for Unity SRP and URP.
|
||||
|
||||
Unity alignment is the primary design constraint:
|
||||
|
||||
- Treat `GraphicsSettings.renderPipelineAsset`, `RenderPipelineAsset`,
|
||||
`ScriptableRenderPipelineAsset`, `ScriptableRenderPipeline`,
|
||||
`ScriptableRenderContext`, `ScriptableRendererData`,
|
||||
`ScriptableRenderer`, `ScriptableRendererFeature`,
|
||||
`ScriptableRenderPass`, `RenderPassEvent`, `RenderingData`, and
|
||||
`UniversalAdditionalCameraData` as the product-facing spine.
|
||||
- Keep the managed API close to Unity semantics wherever the engine can support
|
||||
it. If XCEngine must diverge, the divergence should be explicit, documented,
|
||||
and caused by a real engine constraint rather than native convenience.
|
||||
- Prefer Unity-style authoring concepts over native implementation concepts.
|
||||
Public C# code should feel like URP pipeline authoring, not like remote
|
||||
control over a native built-in renderer.
|
||||
|
||||
The pipeline selection contract must stay explicit and Unity-like:
|
||||
|
||||
- `GraphicsSettings.renderPipelineAsset == null` selects the built-in pipeline.
|
||||
- `GraphicsSettings.renderPipelineAsset != null` selects the programmable SRP
|
||||
path.
|
||||
- The managed product shape should stay close to:
|
||||
`ScriptableRenderPipelineAsset -> ScriptableRendererData ->
|
||||
ScriptableRenderer -> ScriptableRendererFeature/ScriptableRenderPass`.
|
||||
- `ScriptableRenderPipelineHost` is the native host for managed SRP execution;
|
||||
it must not become a hidden fallback renderer when managed SRP planning or
|
||||
recording fails.
|
||||
- Managed SRP / URP owns renderer selection, stage planning, feature/pass
|
||||
organization, camera policy, and optional stage requests such as shadow,
|
||||
depth, post-process, and final output.
|
||||
- Native rendering owns scene extraction, renderer-list drawing, render graph
|
||||
execution, fullscreen primitive execution, and built-in private draw kernels.
|
||||
- Public managed scene drawing should expose drawing capability, not native
|
||||
built-in injection order. Keep the public surface centered on
|
||||
`DrawRenderers(...)`, `DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
- `GraphicsSettings.renderPipelineAsset != null` selects the managed SRP path.
|
||||
- Runtime startup must not silently assign a project default SRP asset. A
|
||||
project default can be loaded by project/editor policy, but rendering mode
|
||||
changes must remain visible through `GraphicsSettings.renderPipelineAsset`.
|
||||
- If a managed SRP asset cannot create a valid pipeline, recorder, or backend
|
||||
bridge, creation should fail visibly and let the top-level factory choose the
|
||||
built-in pipeline. `ScriptableRenderPipelineHost` must not impersonate a
|
||||
successful managed SRP by drawing through a hidden fallback renderer.
|
||||
|
||||
The URP object model should be the center of future work:
|
||||
|
||||
- `ScriptableRenderPipelineAsset` owns pipeline defaults, renderer-data lists,
|
||||
default renderer selection, camera policy, final-color policy, shadow policy,
|
||||
and managed pipeline lifetime.
|
||||
- `ScriptableRendererData` is the serialized renderer configuration. It owns
|
||||
renderer feature lists, default feature creation, runtime invalidation, and
|
||||
renderer instance rebuilds.
|
||||
- `ScriptableRenderer` owns per-camera pass queue construction. It should
|
||||
enqueue passes from renderer features, sort by `RenderPassEvent`, partition
|
||||
work into URP-like renderer blocks, and record only the stage requested by
|
||||
the native frame plan.
|
||||
- `ScriptableRendererFeature` owns reusable renderer extensions. Features
|
||||
should configure camera/frame policy and enqueue `ScriptableRenderPass`
|
||||
instances without reaching into native private pass order.
|
||||
- `ScriptableRenderPass` owns pass lifecycle and recording. The long-term pass
|
||||
surface should be `RecordRenderGraph(...)`, renderer-list drawing, public
|
||||
texture/resource declarations, and explicit pass data.
|
||||
|
||||
The native/managed boundary should remain strict:
|
||||
|
||||
- Managed SRP / URP owns renderer selection, feature/pass organization,
|
||||
optional stage planning, camera clear policy, shadow/depth requests,
|
||||
post-process and final-output policy, and public frame data exposed to user
|
||||
passes.
|
||||
- Native rendering owns scene extraction, culling and renderer-list
|
||||
realization, render graph compilation/execution, RHI resource lifetime,
|
||||
fullscreen primitive execution, and private built-in draw kernels.
|
||||
- Managed scene drawing should expose draw capabilities, not native injection
|
||||
points. Keep the public scene surface centered on `DrawRenderers(...)`,
|
||||
`DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
`DrawTransparentRenderers()`.
|
||||
- Do not reintroduce implicit project-default SRP activation, hidden
|
||||
`ScriptableRenderPipelineHost` fallback, or public managed wrappers for
|
||||
built-in private scene injection points.
|
||||
- Future URP alignment should add managed-side renderer/pass/render-graph
|
||||
capability. It should not reopen native private fallback paths just to make a
|
||||
feature appear to work.
|
||||
- Main-scene, shadow, and depth work should be renderer-driven. Managed passes
|
||||
may request those stages and call public draw APIs, while native continues to
|
||||
execute renderer lists and low-level draw kernels.
|
||||
|
||||
Managed RenderGraph is the key capability gap for the next stage:
|
||||
|
||||
- Grow the current fullscreen-pass bridge into a URP-style render-graph
|
||||
authoring surface with explicit texture creation/imports, read/write
|
||||
declarations, pass data, frame-data/context-container access, and scheduled
|
||||
renderer-list drawing.
|
||||
- Post-process and final-output should become ordinary URP feature/pass work
|
||||
where possible. Native fullscreen kernels may remain execution primitives,
|
||||
but they should not appear as feature-specific public shortcuts.
|
||||
- Prefer data-driven frame state (`CameraData`, `LightingData`, `ShadowData`,
|
||||
`EnvironmentData`, `FinalColorData`, `StageColorData`) over direct scene
|
||||
object inspection during pass recording.
|
||||
|
||||
Tests should protect Unity-facing semantics while the architecture closes:
|
||||
|
||||
- Prioritize contract tests for null-vs-SRP selection, managed SRP creation
|
||||
failure, no hidden fallback rendering, renderer-data/default-renderer
|
||||
selection, camera renderer override, feature/pass enqueue order, stage
|
||||
planning, render-graph recording, and forbidden public API surface.
|
||||
- Add URP integration scenes after the API and responsibility boundaries are
|
||||
stable: default Universal renderer, `RenderObjectsRendererFeature`,
|
||||
post-process/final-output, shadow/depth, camera override, and camera stack.
|
||||
- Avoid overfitting tests to temporary native bridge details. Tests should lock
|
||||
Unity SRP / URP semantics first, implementation mechanics second.
|
||||
|
||||
Guardrails:
|
||||
|
||||
- Do not reintroduce public managed wrappers for native private scene injection
|
||||
points.
|
||||
- Do not make `RenderPassEvent` or renderer blocks a thin alias for native
|
||||
built-in pass order. They should describe URP scheduling semantics.
|
||||
- Do not add managed APIs that only work by reaching into one built-in native
|
||||
renderer path. Add a public renderer-list, render-graph, or pass abstraction
|
||||
instead.
|
||||
- A managed SRP stage that declares support and then fails to record should
|
||||
fail visibly. It should not silently continue by drawing the default native
|
||||
scene.
|
||||
|
||||
## Past Execution
|
||||
|
||||
- Established the top-level selection rule: explicit null means built-in,
|
||||
explicit managed asset means SRP, and runtime startup must not silently assign
|
||||
`ProjectDefaultRenderPipelineAsset`.
|
||||
- Removed public managed native scene injection APIs such as
|
||||
`ScriptableRenderContext.RecordSceneInjectionPoint(...)`,
|
||||
`RecordBefore/After*Injection(...)`, and
|
||||
`RecordOpaque/Skybox/TransparentScenePhase(...)`.
|
||||
- Kept `RecordScene()` / `RecordScenePhase(...)` internal and made the public
|
||||
managed scene surface express draw operations through `DrawRenderers(...)`,
|
||||
`DrawSkybox()`, `DrawOpaqueRenderers()`, and
|
||||
`DrawTransparentRenderers()`.
|
||||
- Moved renderer-backed SRP stage ownership into `ScriptableRenderer`,
|
||||
`ScriptableRendererFeature`, and `ScriptableRenderPass`; renderer-backed
|
||||
assets clear native optional stage defaults before managed renderer/features
|
||||
explicitly request the stages they need.
|
||||
- Removed `CameraRenderRequestContext.hasDirectionalShadow` and
|
||||
`ClearDirectionalShadow()` from the ScriptCore public surface. Core keeps only
|
||||
internal bridge access, while URP policy belongs in renderer asset, renderer
|
||||
data, and feature code.
|
||||
- Reordered managed camera request policy so managed / URP first observes the
|
||||
native directional-shadow baseline, then the final managed policy recomputes
|
||||
or clears the request without native planning adding it back afterward.
|
||||
- Prevented URP default renderer feature factories from auto-injecting built-in
|
||||
private feature wrappers.
|
||||
- Tightened SRP creation failure semantics:
|
||||
`ManagedScriptableRenderPipelineAsset::CreatePipeline()` fails when managed
|
||||
runtime, backend asset, or stage recorder is unavailable; factory fallback
|
||||
then returns the built-in pipeline instead of letting
|
||||
`ScriptableRenderPipelineHost` impersonate a successful managed SRP.
|
||||
- Made the public managed
|
||||
`ScriptableRenderPass.RecordRenderGraph(RenderGraph, ContextContainer)` path
|
||||
receive real URP frame data. `RenderingData`, `CameraData`, `LightingData`,
|
||||
`ShadowData`, `EnvironmentData`, `FinalColorData`, and `StageColorData` are
|
||||
now `ContextItem`s populated before public render-graph recording.
|
||||
- Moved managed public render-graph frame data ownership from individual
|
||||
`ScriptableRenderPass` calls to the `ScriptableRenderer` stage recording
|
||||
scope. Public `ContextContainer` state is now shared across renderer passes
|
||||
for the same stage, matching URP's frame-data mental model instead of
|
||||
pass-local scratch data.
|
||||
|
||||
Reference in New Issue
Block a user